1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22 /* 23 * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 28 /* All Rights Reserved */ 29 30 31 #include "dispatch.h" 32 #include <syslog.h> 33 #include <time.h> 34 35 char *showForms(PSTATUS *); 36 37 /* 38 * untidbit_all() - CALL untidbit() FOR A LIST OF TYPES 39 */ 40 41 static void 42 untidbit_all (char **printer_types) 43 { 44 char ** pl; 45 46 for (pl = printer_types; *pl; pl++) 47 untidbit (*pl); 48 return; 49 } 50 51 /* 52 * s_load_printer() 53 */ 54 55 void 56 s_load_printer(char *m, MESG *md) 57 { 58 char *printer; 59 ushort status; 60 register PRINTER *pp; 61 register PSTATUS *pps; 62 char **paperDenied; 63 64 (void) getmessage(m, S_LOAD_PRINTER, &printer); 65 syslog(LOG_DEBUG, "s_load_printer(%s)", (printer ? printer : "NULL")); 66 67 if (!*printer) 68 /* no printer */ 69 status = MNODEST; 70 else if (!(pp = Getprinter(printer))) { 71 /* Strange or missing printer? */ 72 switch (errno) { 73 case EBADF: 74 status = MERRDEST; 75 break; 76 case ENOENT: 77 default: 78 status = MNODEST; 79 break; 80 } 81 } else if ((pps = search_pstatus(printer))) { 82 /* Printer we know about already? */ 83 PRINTER *op = pps->printer; 84 85 pps->printer = pp; 86 87 /* 88 * Ensure that an old Terminfo type that's no longer 89 * needed gets freed, and that an existing type gets 90 * reloaded (in case it has been changed). 91 */ 92 untidbit_all (op->printer_types); 93 untidbit_all (pp->printer_types); 94 95 /* 96 * Does an alert get affected? 97 * - Different command? 98 * - Different wait interval? 99 */ 100 if (pps->alert->active) 101 if (!SAME(pp->fault_alert.shcmd, 102 op->fault_alert.shcmd) || 103 pp->fault_alert.W != op->fault_alert.W) { 104 /* 105 * We can't use "cancel_alert()" here 106 * because it will remove the message. 107 * We'll do half of the cancel, then 108 * check if we need to run the new alert, 109 * and remove the message if not. 110 */ 111 pps->alert->active = 0; 112 terminate (pps->alert->exec); 113 if (pp->fault_alert.shcmd) 114 alert(A_PRINTER, pps, (RSTATUS *)0, 115 (char *)0); 116 else 117 Unlink (pps->alert->msgfile); 118 } 119 freeprinter (op); 120 121 unload_list (&pps->users_allowed); 122 unload_list (&pps->users_denied); 123 unload_list (&pps->forms_allowed); 124 unload_list (&pps->forms_denied); 125 load_userprinter_access(pp->name, &pps->users_allowed, 126 &pps->users_denied); 127 load_formprinter_access(pp->name, &pps->forms_allowed, 128 &pps->forms_denied); 129 130 unload_list (&pps->paper_allowed); 131 load_paperprinter_access(pp->name, &pps->paper_allowed, 132 &paperDenied); 133 freelist(paperDenied); 134 135 load_sdn (&pps->cpi, pp->cpi); 136 load_sdn (&pps->lpi, pp->lpi); 137 load_sdn (&pps->plen, pp->plen); 138 load_sdn (&pps->pwid, pp->pwid); 139 140 pps->last_dial_rc = 0; 141 pps->nretry = 0; 142 143 /* 144 * Evaluate all requests queued for this printer, 145 * to make sure they are still eligible. They will 146 * get moved to another printer, get (re)filtered, 147 * or get canceled. 148 */ 149 (void) queue_repel(pps, 0, (qchk_fnc_type)0); 150 151 status = MOK; 152 } else if (pp->remote) { 153 /* don't really load a remote printer */ 154 status = MOK; 155 } else if ((pps = new_pstatus(pp))) { 156 pps->status = PS_DISABLED | PS_REJECTED; 157 load_str (&pps->dis_reason, CUZ_NEW_PRINTER); 158 load_str (&pps->rej_reason, CUZ_NEW_DEST); 159 load_str (&pps->fault_reason, CUZ_PRINTING_OK); 160 time (&pps->dis_date); 161 time (&pps->rej_date); 162 163 dump_pstatus (); 164 165 status = MOK; 166 } else { 167 freeprinter (pp); 168 status = MNOSPACE; 169 } 170 171 172 mputm (md, R_LOAD_PRINTER, status); 173 return; 174 } 175 176 /* 177 * s_unload_printer() 178 */ 179 180 static void 181 _unload_printer(PSTATUS *pps) 182 { 183 int i; 184 185 if (pps->alert->active) 186 cancel_alert (A_PRINTER, pps); 187 188 /* 189 * Remove this printer from the classes it may be in. 190 * This is likely to be redundant, i.e. upon deleting 191 * a printer the caller is SUPPOSED TO check all the 192 * classes; any that contain the printer will be changed 193 * and we should receive a S_LOAD_CLASS message for each 194 * to reload the class. 195 * 196 * HOWEVER, this leaves a (small) window where someone 197 * can sneak a request in destined for the CLASS. If 198 * we have deleted the printer but still have it in the 199 * class, we may have trouble! 200 */ 201 for (i = 0; CStatus != NULL && CStatus[i] != NULL; i++) 202 (void) dellist(&(CStatus[i]->class->members), 203 pps->printer->name); 204 205 free_pstatus(pps); 206 /* 207 * this is removed from the PStatus table by the caller 208 * list_remove((void ***)&PStatus, (void *)pps); 209 */ 210 211 return; 212 } 213 214 void 215 s_unload_printer(char *m, MESG *md) 216 { 217 char *printer; 218 ushort status; 219 register PSTATUS *pps; 220 221 (void) getmessage(m, S_UNLOAD_PRINTER, &printer); 222 223 syslog(LOG_DEBUG, "s_unload_printer(%s)", 224 (printer ? printer : "NULL")); 225 226 if (!*printer || STREQU(printer, NAME_ALL)) 227 /* Unload ALL printers */ 228 if (!Request_List) 229 /* If we have ANY requests queued, we can't do it. */ 230 status = MBUSY; 231 232 else { 233 int i; 234 for (i = 0; PStatus != NULL && PStatus[i] != NULL; i++) 235 _unload_printer (PStatus[i]); 236 free(PStatus); 237 PStatus = NULL; 238 status = MOK; 239 } 240 241 else if (!(pps = search_pstatus(printer))) 242 /* Have we seen this printer before */ 243 status = MNODEST; 244 else { 245 /* 246 * Note: This routine WILL MOVE requests to another 247 * printer. It will not stop until it has gone through 248 * the entire list of requests, so all requests that 249 * can be moved will be moved. If any couldn't move, 250 * however, we don't unload the printer. 251 */ 252 if (queue_repel(pps, 1, (qchk_fnc_type)0)) 253 status = MOK; 254 else 255 status = MBUSY; 256 257 if (status == MOK) { 258 _unload_printer (pps); 259 list_remove((void ***)&PStatus, (void *)pps); 260 } 261 } 262 263 if (status == MOK) 264 dump_pstatus (); 265 266 mputm (md, R_UNLOAD_PRINTER, status); 267 return; 268 } 269 270 /* 271 * combineReasons() 272 */ 273 274 static char * 275 combineReasons(PSTATUS *pps, char *freeReason) 276 { 277 char *reason = NULL; 278 279 if (pps->status & PS_FAULTED) { 280 if ((pps->status & (PS_DISABLED | PS_LATER)) && 281 (!STREQU(pps->dis_reason, CUZ_STOPPED)) && 282 (addstring(&reason, "Fault reason: ") == 0) && 283 (addstring(&reason, pps->fault_reason) == 0) && 284 (addstring(&reason, "\n\tDisable reason: ") == 0) && 285 (addstring(&reason, pps->dis_reason) == 0)) 286 *freeReason = 1; 287 288 else { 289 if (reason) 290 /* memory allocation failed part way through */ 291 Free(reason); 292 293 reason = pps->fault_reason; 294 *freeReason = 0; 295 } 296 } else { 297 reason = pps->dis_reason; 298 *freeReason = 0; 299 } 300 return (reason); 301 } 302 303 static void 304 local_printer_status(MESG *md, PSTATUS *pps, short status) 305 { 306 char *reason = NULL; 307 char freeReason = 0; 308 char *formList = NULL; 309 310 reason = combineReasons(pps, &freeReason); 311 formList = showForms(pps); 312 313 send(md, R_INQUIRE_PRINTER_STATUS, status, pps->printer->name, 314 (formList ? formList : ""), 315 (pps->pwheel_name ? pps->pwheel_name : ""), 316 reason, pps->rej_reason, pps->status, 317 (pps->request ? pps->request->secure->req_id : ""), 318 pps->dis_date, pps->rej_date); 319 320 if (formList) 321 Free(formList); 322 323 if (freeReason) 324 Free(reason); 325 } 326 327 /* 328 * s_inquire_printer_status() 329 */ 330 331 void 332 s_inquire_printer_status(char *m, MESG *md) 333 { 334 char *printer; 335 register PSTATUS *pps; 336 337 (void) getmessage(m, S_INQUIRE_PRINTER_STATUS, &printer); 338 syslog(LOG_DEBUG, "s_inquire_printer_status(%s)", printer); 339 340 if (!*printer || STREQU(printer, NAME_ALL)) { 341 /* inquire about all printers */ 342 int i; 343 344 for (i = 0; PStatus != NULL && PStatus[i] != NULL; i++) { 345 pps = PStatus[i]; 346 if (PStatus[i + 1] != NULL) 347 local_printer_status(md, pps, MOKMORE); 348 } 349 } else 350 /* inquire about a specific printer */ 351 pps = search_pstatus(printer); 352 353 if (pps) 354 local_printer_status(md, pps, MOK); 355 else { 356 mputm(md, R_INQUIRE_PRINTER_STATUS, MNODEST, "", "", "", "", 357 "", 0, "", 0L, 0L); 358 } 359 } 360 361 362 /* 363 * s_load_class() 364 */ 365 366 void 367 s_load_class(char *m, MESG *md) 368 { 369 char *class; 370 ushort status; 371 register CLASS *pc; 372 register CLSTATUS *pcs; 373 374 (void) getmessage(m, S_LOAD_CLASS, &class); 375 syslog(LOG_DEBUG, "s_load_class(%s)", (class ? class : "NULL")); 376 377 if (!*class) 378 /* no class defined */ 379 status = MNODEST; 380 else if (!(pc = Getclass(class))) { 381 /* Strange or missing class */ 382 switch (errno) { 383 case EBADF: 384 status = MERRDEST; 385 break; 386 case ENOENT: 387 default: 388 status = MNODEST; 389 break; 390 } 391 392 } else if ((pcs = search_cstatus(class))) { 393 /* Class we already know about */ 394 register RSTATUS *prs; 395 396 freeclass (pcs->class); 397 pcs->class = pc; 398 399 /* 400 * Here we go through the list of requests 401 * to see who gets affected. 402 */ 403 for (prs = Request_List; prs != NULL; prs = prs->next) 404 if (STREQU(prs->request->destination, class)) { 405 /* 406 * If not still eligible for this class... 407 */ 408 switch (validate_request(prs, (char **)0, 1)) { 409 case MOK: 410 case MERRDEST: /* rejecting (shouldn't happen) */ 411 break; 412 case MDENYDEST: 413 case MNOMOUNT: 414 case MNOMEDIA: 415 case MNOFILTER: 416 default: 417 /* 418 * ...then too bad! 419 */ 420 cancel (prs, 1); 421 break; 422 } 423 } 424 425 status = MOK; 426 } else if ((pcs = new_cstatus(pc))) { 427 /* Room for new class? */ 428 pcs->status = CS_REJECTED; 429 load_str (&pcs->rej_reason, CUZ_NEW_DEST); 430 time (&pcs->rej_date); 431 432 dump_cstatus (); 433 434 status = MOK; 435 } else { 436 freeclass (pc); 437 status = MNOSPACE; 438 } 439 440 441 mputm (md, R_LOAD_CLASS, status); 442 return; 443 } 444 445 /* 446 * s_unload_class() 447 */ 448 449 static void 450 _unload_class(CLSTATUS *pcs) 451 { 452 freeclass (pcs->class); 453 if (pcs->rej_reason != NULL) 454 Free (pcs->rej_reason); 455 Free(pcs); 456 457 return; 458 } 459 460 void 461 s_unload_class(char *m, MESG *md) 462 { 463 char *class; 464 ushort status; 465 RSTATUS *prs; 466 register CLSTATUS *pcs; 467 468 (void) getmessage(m, S_UNLOAD_CLASS, &class); 469 syslog(LOG_DEBUG, "s_unload_class(%s)", (class ? class : "NULL")); 470 471 /* 472 * Unload ALL classes? 473 */ 474 if (!*class || STREQU(class, NAME_ALL)) { 475 int i; 476 /* 477 * If we have a request queued for a member of ANY 478 * class, we can't do it. 479 */ 480 status = MOK; 481 for (i = 0; ((CStatus[i] != NULL) && (status == MOK)); i++) { 482 for (prs = Request_List; prs != NULL; prs = prs->next) 483 if (STREQU(prs->request->destination, 484 CStatus[i]->class->name)) { 485 status = MBUSY; 486 break; 487 } 488 } 489 490 if (status == MOK) { 491 for (i = 0; CStatus != NULL && CStatus[i] != NULL; i++) 492 _unload_class (CStatus[i]); 493 free(CStatus); 494 CStatus = NULL; 495 } 496 497 /* 498 * Have we seen this class before? 499 */ 500 } else if (!(pcs = search_cstatus(class))) 501 status = MNODEST; 502 503 /* 504 * Is there even one request queued for this class? 505 * If not, we can safely remove it. 506 */ 507 else { 508 status = MOK; 509 for (prs = Request_List; prs != NULL; prs = prs->next) 510 if (STREQU(prs->request->destination, class)) { 511 status = MBUSY; 512 break; 513 } 514 515 if (status == MOK) { 516 _unload_class (pcs); 517 list_remove((void ***)&CStatus, (void *)pcs); 518 } 519 } 520 521 if (status == MOK) 522 dump_cstatus (); 523 524 mputm (md, R_UNLOAD_CLASS, status); 525 return; 526 } 527 528 /* 529 * s_inquire_class() 530 */ 531 532 void 533 s_inquire_class(char *m, MESG *md) 534 { 535 char *class; 536 register CLSTATUS *pcs; 537 538 (void) getmessage(m, S_INQUIRE_CLASS, &class); 539 syslog(LOG_DEBUG, "s_inquire_class(%s)", (class ? class : "NULL")); 540 541 542 543 if (!*class || STREQU(class, NAME_ALL)) { 544 /* inquire about ALL classes */ 545 int i; 546 547 for (i = 0; CStatus != NULL && CStatus[i] != NULL; i++) { 548 pcs = CStatus[i]; 549 if (CStatus[i + 1] != NULL) 550 send(md, R_INQUIRE_CLASS, MOKMORE, 551 pcs->class->name, pcs->status, 552 pcs->rej_reason, pcs->rej_date); 553 } 554 } else 555 /* inquire about a single class */ 556 pcs = search_cstatus(class); 557 558 if (pcs) 559 send(md, R_INQUIRE_CLASS, MOK, pcs->class->name, pcs->status, 560 pcs->rej_reason, pcs->rej_date); 561 else 562 mputm (md, R_INQUIRE_CLASS, MNODEST, "", 0, "", 0L); 563 564 return; 565 } 566 567 /* 568 * s_paper_allowed() 569 */ 570 571 void 572 s_paper_allowed(char *m, MESG *md) 573 { 574 char *printer; 575 char *paperList = NULL; 576 register PSTATUS *pps, *ppsnext; 577 578 (void) getmessage(m, S_PAPER_ALLOWED, &printer); 579 syslog(LOG_DEBUG, "s_paper_allowed(%s)", (printer ? printer : "NULL")); 580 581 582 if (!*printer || STREQU(printer, NAME_ALL)) { 583 /* inquire about ALL printers */ 584 int i; 585 586 for (i = 0; PStatus != NULL && PStatus[i] != NULL; i++) { 587 pps = PStatus[i]; 588 if (PStatus[i + 1] != NULL) { 589 paperList = sprintlist(pps->paper_allowed); 590 send(md, R_PAPER_ALLOWED, MOKMORE, 591 pps->printer->name, 592 (paperList ? paperList : "")); 593 if (paperList) 594 Free(paperList); 595 } 596 } 597 } else 598 /* inquire about a specific printer */ 599 pps = search_pstatus(printer); 600 601 if (pps) { 602 paperList = sprintlist(pps->paper_allowed); 603 send(md, R_PAPER_ALLOWED, MOK, pps->printer->name, 604 (paperList ? paperList : "")); 605 if (paperList) 606 Free(paperList); 607 608 } else { 609 mputm(md, R_PAPER_ALLOWED, MNODEST, "", ""); 610 } 611 } 612