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