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