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 36 /** 37 ** remount_form() - MOUNT A FORM WHERE ANOTHER WAS MOUNTED 38 **/ 39 40 void 41 remount_form(register PSTATUS *pps, FSTATUS *pfs, short trayNum) 42 { 43 trayNum--; /* make zero based */ 44 if (pps->forms && (pps->forms[trayNum].form == pfs)) { 45 pps->forms[trayNum].isAvailable = (pfs ? 1 : 0); 46 /* force it */ 47 return; /* nothing to do */ 48 } else if ((!pps->forms) && (!pfs)) { 49 return; /* nothing to do */ 50 } 51 52 /* 53 * Unmount the old form. 54 */ 55 if (pps->forms && pps->forms[trayNum].form) { 56 register FSTATUS *Opfs = pps->forms[trayNum].form; 57 58 pps->forms[trayNum].form = 0; 59 pps->forms[trayNum].isAvailable = 0; 60 Opfs->mounted--; 61 62 /* 63 * Unmounting the form may make some print requests 64 * no longer printable, because they were accepted 65 * only because the form was already mounted. 66 * Unmounting the form will also force some requests 67 * to another printer (where the form is mounted) 68 * so they can print. 69 */ 70 form_in_question = Opfs; 71 (void)queue_repel (pps, 0, qchk_form); 72 73 /* 74 * Maybe an alert is due. 75 */ 76 check_form_alert (Opfs, (_FORM *)0); 77 } 78 79 /* 80 * Mount the new form? 81 */ 82 if (pfs) { 83 syslog(LOG_DEBUG, "remount_form add %x(%s) to tray %d\n", 84 pfs, (pfs ? pfs->form->name : "NULL"), trayNum); 85 86 if (pps && !pps->forms) { 87 pps->forms = (PFSTATUS *)calloc((trayNum +1), 88 sizeof(PFSTATUS)); 89 pps->numForms = trayNum + 1; 90 } 91 92 if (pps && pps->forms && (pps->numForms > trayNum)) { 93 pps->forms[trayNum].form = pfs; 94 pps->forms[trayNum].isAvailable = 1; 95 pfs->mounted++; 96 } else { 97 return; /* nothing to do, can't mount form, 98 so no need to pretend we did */ 99 } 100 101 102 /* 103 * Attract all the requests needing this newly mounted 104 * form. This may cause some unnecessary shuffling, but 105 * we have to ensure requests aren't assigned to a printer 106 * without the form mounted, so that the alert check is 107 * correct. 108 */ 109 if (pfs->requests) { 110 form_in_question = pfs; 111 queue_attract (pps, qchk_form, 0); 112 113 /* 114 * Maybe an alert can be shut off. 115 */ 116 check_form_alert (pfs, (_FORM *)0); 117 } 118 119 } else { 120 /* 121 * Attract first request that doesn't need a form mounted. 122 * We only need to get one request printing, because it 123 * completing will cause the next request to be attracted. 124 */ 125 form_in_question = 0; 126 queue_attract (pps, qchk_form, 1); 127 } 128 129 dump_pstatus (); 130 131 return; 132 } 133 134 /** 135 ** remount_pwheel() - MOUNT A PRINT-WHEEL WHERE ANOTHER WAS MOUNTED 136 **/ 137 138 static void 139 remount_pwheel(register PSTATUS *pps, char *pwheel_name) 140 { 141 PWSTATUS *ppws; 142 143 if (SAME(pps->pwheel_name, pwheel_name)) 144 return; /* nothing to do */ 145 146 /* 147 * Unmount the old print wheel 148 */ 149 if (pps->pwheel_name) { 150 register PWSTATUS *Oppws = pps->pwheel; 151 152 pps->pwheel = 0; 153 if (Oppws) 154 Oppws->mounted--; 155 156 /* 157 * Unmounting the print wheel may make some print 158 * requests no longer printable, because they were 159 * accepted only because the print wheel was already 160 * mounted. Unmounting the print wheel will also force 161 * some requests to another printer (where the print wheel 162 * is mounted) so they can print. 163 */ 164 pwheel_in_question = pps->pwheel_name; 165 (void)queue_repel (pps, 0, qchk_pwheel); 166 167 unload_str (&pps->pwheel_name); 168 169 /* 170 * Maybe an alert is due. 171 */ 172 if (Oppws) 173 check_pwheel_alert (Oppws, (PWHEEL *)0); 174 } 175 176 /* 177 * Mount the new print wheel? 178 */ 179 if (pwheel_name) { 180 load_str (&pps->pwheel_name, pwheel_name); 181 if (ppws = search_pwstatus(pwheel_name)) { 182 pps->pwheel = ppws; 183 ppws->mounted++; 184 185 /* 186 * Attract all requests needing this newly 187 * mounted print wheel. This may cause some 188 * unnecessary shuffling, but we have to ensure 189 * requests aren't assigned to a printer without 190 * the print-wheel mounted, so that the alert 191 * check is correct. 192 */ 193 if (ppws->requests) { 194 pwheel_in_question = pwheel_name; 195 queue_attract (pps, qchk_pwheel, 0); 196 197 /* 198 * Maybe an alert can be shut off. 199 */ 200 check_pwheel_alert (ppws, (PWHEEL *)0); 201 } 202 203 } else { 204 /* 205 * Attract the first request that needs this newly 206 * mounted print wheel. If no alert has been 207 * defined for the print wheel, we don't know how 208 * many requests are queued waiting for it, so we 209 * have to do this unconditionally. 210 */ 211 pwheel_in_question = pwheel_name; 212 queue_attract (pps, qchk_pwheel, 1); 213 } 214 215 } else { 216 /* 217 * Attract the first request that doesn't need a 218 * print wheel mounted. 219 * We only need to get one request printing, because it 220 * completing will cause the next request to be attracted. 221 */ 222 pwheel_in_question = 0; 223 queue_attract (pps, qchk_pwheel, 1); 224 } 225 226 dump_pstatus (); 227 228 return; 229 } 230 231 #define MAX_TRAYS 100 232 233 /** 234 ** s_max_trays() 235 **/ 236 237 void 238 s_max_trays(char *m, MESG *md) 239 { 240 char *printer; 241 ushort status; 242 short numTrays; 243 register PSTATUS *pps; 244 register PFSTATUS *ppfs; 245 246 (void) getmessage(m, S_MAX_TRAYS, &printer, &numTrays); 247 syslog(LOG_DEBUG, "s_max_trays(%s, %d)", (printer ? printer : "NULL"), 248 numTrays); 249 250 /* Have we seen this printer before? */ 251 if (!*printer || !(pps = search_pstatus(printer))) 252 status = MNODEST; 253 254 /* How about the tray? */ 255 else if ((numTrays <=0) || (numTrays > MAX_TRAYS)) 256 status = MNOTRAY; 257 258 /* If the printer is currently printing, we can't disturb it. */ 259 else if (pps->request) 260 status = MBUSY; 261 262 else if (pps->forms) { 263 if (!(ppfs = Realloc(pps->forms,numTrays * sizeof(PFSTATUS)))) 264 status = MNOMEM; 265 else { 266 int i; 267 268 for (i = pps->numForms; i < numTrays; i++) { 269 ppfs[i].form = NULL; 270 ppfs[i].isAvailable = 0; 271 } 272 pps->forms = ppfs; 273 pps->numForms = numTrays; 274 status = MOK; 275 } 276 } else if (!(ppfs = Calloc(numTrays,sizeof(PFSTATUS)))) { 277 status = MNOMEM; 278 } else { 279 pps->forms = ppfs; 280 pps->numForms = numTrays; 281 status = MOK; 282 } 283 dump_pstatus(); 284 mputm(md, R_MAX_TRAYS, status); 285 } 286 287 /** 288 ** s_mount() 289 **/ 290 291 void 292 s_mount(char *m, MESG *md) 293 { 294 char *printer, *form, *pwheel_name; 295 ushort status; 296 register PSTATUS *pps; 297 register FSTATUS *pfs; 298 299 (void) getmessage(m, S_MOUNT, &printer, &form, &pwheel_name); 300 syslog(LOG_DEBUG, "s_mount(%s, %s, %s)", (printer ? printer : "NULL"), 301 (form ? form : "NULL"), (pwheel_name ? pwheel_name : "NULL")); 302 303 if (!*form && !*pwheel_name) 304 status = MNOMEDIA; 305 306 /* Have we seen this printer before? */ 307 else if (!*printer || !(pps = search_pstatus(printer))) 308 status = MNODEST; 309 310 /* How about the form? */ 311 else if (*form && !(pfs = search_fstatus(form))) 312 status = MNOMEDIA; 313 314 /* If the printer is currently printing, we can't disturb it. */ 315 else if (pps->request) 316 status = MBUSY; 317 318 else { 319 /* 320 * Mount them. 321 */ 322 if (*form) 323 remount_form (pps, pfs,1); 324 if (*pwheel_name) 325 remount_pwheel(pps, pwheel_name); 326 327 status = MOK; 328 } 329 330 mputm(md, R_MOUNT, status); 331 } 332 333 /* 334 * s_mount_tray() 335 */ 336 337 void 338 s_mount_tray(char *m, MESG *md) 339 { 340 char *printer, *form, *pwheel_name; 341 ushort status; 342 short trayNum; 343 register PSTATUS *pps; 344 register FSTATUS *pfs; 345 346 (void) getmessage(m, S_MOUNT_TRAY, &printer, &form, &pwheel_name, 347 &trayNum); 348 syslog(LOG_DEBUG, "s_mount_tray(%s, %s, %s, %d)", 349 (printer ? printer : "NULL"), (form ? form : "NULL"), 350 (pwheel_name ? pwheel_name : "NULL"), trayNum); 351 352 if (!*form && !*pwheel_name) 353 status = MNOMEDIA; 354 355 /* Have we seen this printer before? */ 356 else if (!*printer || !(pps = search_pstatus(printer))) 357 status = MNODEST; 358 359 /* How about the form? */ 360 else if (*form && !(pfs = search_fstatus(form))) 361 status = MNOMEDIA; 362 363 /* How about the tray? */ 364 else if ((trayNum <=0) || (trayNum > pps->numForms)) 365 status = MNOTRAY; 366 367 /* If the printer is currently printing, we can't disturb it. */ 368 else if (pps->request) 369 status = MBUSY; 370 371 else { 372 /* 373 * Mount them. 374 */ 375 if (*form) 376 remount_form(pps, pfs,trayNum); 377 if (*pwheel_name) 378 remount_pwheel(pps, pwheel_name); 379 380 status = MOK; 381 } 382 383 mputm (md, R_MOUNT_TRAY, status); 384 } 385 386 /** 387 ** s_unmount() 388 **/ 389 390 void 391 s_unmount(char *m, MESG *md) 392 { 393 char *printer, 394 *form, 395 *pwheel_name; 396 ushort status; 397 register PSTATUS *pps; 398 399 (void)getmessage (m, S_UNMOUNT, &printer, &form, &pwheel_name); 400 syslog(LOG_DEBUG, "s_unmount(%s, %s, %s)", 401 (printer ? printer : "NULL"), (form ? form : "NULL"), 402 (pwheel_name ? pwheel_name : "NULL")); 403 404 if (!*form && !*pwheel_name) 405 status = MNOMEDIA; 406 407 /* 408 * Have we seen this printer before? 409 */ 410 else if (!*printer || !(pps = search_pstatus(printer))) 411 status = MNODEST; 412 413 414 /* 415 * If the printer is currently printing a request, 416 * we can't unmount the current form/pwheel. 417 */ 418 else if (pps->request) 419 status = MBUSY; 420 421 else { 422 /* 423 * Unmount them. 424 */ 425 if (*form) 426 remount_form (pps, (FSTATUS *)0,1); 427 if (*pwheel_name) 428 remount_pwheel (pps, (char *)0); 429 430 status = MOK; 431 } 432 433 mputm (md, R_UNMOUNT, status); 434 return; 435 } 436 /** 437 ** s_unmount_tray() 438 **/ 439 440 void 441 s_unmount_tray(char *m, MESG *md) 442 { 443 char *printer, 444 *form, 445 *pwheel_name; 446 447 ushort status; 448 short trayNum; 449 450 register PSTATUS *pps; 451 452 (void)getmessage (m, S_UNMOUNT_TRAY, &printer, &form, &pwheel_name, 453 &trayNum); 454 syslog(LOG_DEBUG, "s_unmount_tray(%s, %s, %s, %d)", 455 (printer ? printer : "NULL"), (form ? form : "NULL"), 456 (pwheel_name ? pwheel_name : "NULL"), trayNum); 457 458 459 if (!*form && !*pwheel_name) 460 status = MNOMEDIA; 461 462 else if (!*printer || !(pps = search_pstatus(printer))) 463 /* haven't seen this printer before */ 464 status = MNODEST; 465 else if ((trayNum <=0) || (trayNum > pps->numForms)) 466 /* haven't seen the tray before */ 467 status = MNOTRAY; 468 else if (pps->request) 469 /* is the printer busy */ 470 status = MBUSY; 471 else { 472 /* Unmount them. */ 473 if (*form) 474 remount_form (pps, (FSTATUS *)0,trayNum); 475 if (*pwheel_name) 476 remount_pwheel (pps, (char *)0); 477 478 status = MOK; 479 } 480 481 mputm (md, R_UNMOUNT_TRAY, status); 482 return; 483 } 484 485 /** 486 ** s_load_form() 487 **/ 488 489 void 490 s_load_form(char *m, MESG *md) 491 { 492 char *form; 493 ushort status; 494 register _FORM *pf; 495 register FSTATUS *pfs; 496 497 (void)getmessage (m, S_LOAD_FORM, &form); 498 syslog(LOG_DEBUG, "s_load_form(%s)", (form ? form : "NULL")); 499 500 if (!*form) 501 /* no form specified */ 502 status = MNODEST; 503 else if (!(pf = Getform(form))) { 504 /* strange or missing form */ 505 switch (errno) { 506 case EBADF: 507 status = MERRDEST; 508 break; 509 case ENOENT: 510 default: 511 status = MNODEST; 512 break; 513 } 514 515 } else if ((pfs = search_fstatus(form))) { 516 /* Have we seen this form before? */ 517 unload_list (&pfs->users_allowed); 518 unload_list (&pfs->users_denied); 519 load_userform_access ( 520 pf->name, 521 &pfs->users_allowed, 522 &pfs->users_denied 523 ); 524 525 load_sdn (&pfs->cpi, pf->cpi); 526 load_sdn (&pfs->lpi, pf->lpi); 527 load_sdn (&pfs->plen, pf->plen); 528 load_sdn (&pfs->pwid, pf->pwid); 529 530 531 /* 532 * These have to be done in the order shown, 533 * and after the assignments above, so that all 534 * the new information is in place for the 535 * checks. An unfortunate side effect is that 536 * it is possible for the alert to shut off 537 * and then come on again, if (1) enough requests 538 * are canceled to drop the level below the old 539 * alert threshold, but (2) the new alert threshold 540 * is even lower. The final alert will be correct, 541 * though. 542 */ 543 544 form_in_question = pfs; 545 queue_check (qchk_form); 546 547 check_form_alert (pfs, pf); 548 549 550 status = MOK; 551 552 /* 553 * Room for a new form? 554 */ 555 } else if ((pfs = new_fstatus(pf))) { 556 /* 557 * No alert is possible for a new form, of course, 558 * but this routine does a bit more than just check 559 * the alert. 560 */ 561 check_form_alert (pfs, pf); 562 status = MOK; 563 } else { 564 free_form (pf); 565 status = MNOSPACE; 566 } 567 568 mputm (md, R_LOAD_FORM, status); 569 return; 570 } 571 572 /** 573 ** s_unload_form() 574 **/ 575 576 static void 577 _unload_form(register FSTATUS *pfs) 578 { 579 int i; 580 short numForms; 581 PFSTATUS *ppfs; 582 583 /* 584 * Unmount this form everywhere and get rid of it. 585 */ 586 for (i = 0; PStatus != NULL && PStatus[i] != NULL; i++) 587 if (((ppfs = PStatus[i]->forms) != NULL) && 588 ((numForms = PStatus[i]->numForms) > 0)) { 589 int j; 590 for ( j = 0 ; j < numForms ; j++ ) 591 if (ppfs[j].form == pfs) ppfs[j].form= NULL; 592 } 593 594 return; 595 } 596 597 void 598 s_unload_form(char *m, MESG *md) 599 { 600 char *form; 601 ushort status; 602 RSTATUS *prs; 603 register FSTATUS *pfs; 604 605 (void)getmessage (m, S_UNLOAD_FORM, &form); 606 syslog(LOG_DEBUG, "s_unload_form(%s)", (form ? form : "NULL")); 607 608 if (!*form || STREQU(form, NAME_ALL)) { 609 int i; 610 /* If we have a request queued for ANY form, we can't do it. */ 611 status = MOK; 612 for (i = 0; FStatus != NULL && FStatus[i] != NULL && 613 status == MOK; i++) { 614 for (prs = Request_List; prs != NULL; prs = prs->next) 615 if (prs->form == FStatus[i]) { 616 status = MBUSY; 617 break; 618 } 619 } 620 621 if (status == MOK) { 622 for (i = 0; FStatus != NULL && FStatus[i] != NULL; i++) 623 _unload_form (FStatus[i]); 624 free(FStatus); 625 FStatus = NULL; 626 } 627 628 } else if (!*form || !(pfs = search_fstatus(form))) 629 /* Have we seen this form before? */ 630 status = MNODEST; 631 else { 632 /* Is there even one request waiting for this form? */ 633 status = MOK; 634 for (prs = Request_List; prs != NULL; prs = prs->next) 635 if (prs->form == pfs) { 636 status = MBUSY; 637 break; 638 } 639 640 if (status == MOK) { 641 _unload_form (pfs); 642 list_remove((void ***)&FStatus, (void *)pfs); 643 } 644 } 645 646 mputm (md, R_UNLOAD_FORM, status); 647 return; 648 } 649 650 /** 651 ** s_load_printwheel() 652 **/ 653 654 void 655 s_load_printwheel(char *m, MESG *md) 656 { 657 char *pwheel_name; 658 ushort status; 659 register PWHEEL *ppw; 660 register PWSTATUS *ppws; 661 662 (void)getmessage (m, S_LOAD_PRINTWHEEL, &pwheel_name); 663 syslog(LOG_DEBUG, "s_load_printwheel(%s)", 664 (pwheel_name ? pwheel_name : "NULL")); 665 666 if (!*pwheel_name) 667 /* no printwheel specified */ 668 status = MNODEST; 669 else if (!(ppw = Getpwheel(pwheel_name))) { 670 /* Strange or missing print wheel? */ 671 switch (errno) { 672 case EBADF: 673 status = MERRDEST; 674 break; 675 case ENOENT: 676 default: 677 status = MNODEST; 678 break; 679 } 680 } else if ((ppws = search_pwstatus(pwheel_name))) { 681 /* Print wheel we already know about? */ 682 check_pwheel_alert (ppws, ppw); 683 status = MOK; 684 } else if ((ppws = new_pwstatus(ppw))) { 685 /* Room for a new print wheel? */ 686 register RSTATUS *prs; 687 688 /* 689 * Because of the quirky nature of the print wheel 690 * structures, i.e. no structure unless an alert has 691 * been defined, we have to run through the requests 692 * and see which ones are waiting for this print wheel, 693 * so we can assign alerts and count pending requests. 694 */ 695 for (prs = Request_List; prs != NULL; prs = prs->next) 696 if ((prs->pwheel_name == pwheel_name) && 697 (!one_printer_with_charsets(prs))) { 698 prs->pwheel = ppws; 699 ppws->requests++; 700 } 701 check_pwheel_alert (ppws, ppw); 702 703 status = MOK; 704 } else { 705 freepwheel (ppw); 706 status = MNOSPACE; 707 } 708 709 mputm (md, R_LOAD_PRINTWHEEL, status); 710 return; 711 } 712 713 /** 714 ** s_unload_printwheel() 715 **/ 716 717 static void 718 _unload_pwheel(register PWSTATUS *ppws) 719 { 720 register PSTATUS *pps; 721 register RSTATUS *prs; 722 int i; 723 724 725 /* 726 * ``Unmount'' the alert part of this print wheel everywhere. 727 * THIS IS NOT A COMPLETE UNMOUNT, JUST THE ALERT STRUCTURE 728 * IS REMOVED. 729 */ 730 for (i = 0; PStatus != NULL && PStatus[i] != NULL; i++) 731 if (PStatus[i]->pwheel == ppws) 732 PStatus[i]->pwheel = 0; 733 734 /* 735 * Remove the alert part from all requests. 736 */ 737 for (prs = Request_List; prs; prs = prs->next) 738 if (prs->pwheel == ppws) 739 prs->pwheel = 0; 740 741 /* 742 * Cancel any alert pending. Here we're different from the 743 * similar code for unloading a form, because, to be able to 744 * unload a form we first require NO requests pending. If no 745 * requests are pending there should be no alert to cancel. 746 * Print wheels, on the other hand, only exist as names and 747 * alerts. We can always unload a ``print wheel'' because 748 * all we're really unloading is an alert. Thus, there can 749 * be requests queued for the print wheel (the name), and 750 * thus there can be an alert running. 751 */ 752 if (ppws->alert->active) 753 cancel_alert (A_PWHEEL, ppws); 754 755 free_pwstatus(ppws); 756 757 return; 758 } 759 760 void 761 s_unload_printwheel(char *m, MESG *md) 762 { 763 char *pwheel_name; 764 765 ushort status; 766 767 register PWSTATUS *ppws; 768 769 770 /* 771 * We don't care if any requests are waiting for the print 772 * wheel(s)--what we're removing here is (are) just the alert(s)! 773 */ 774 775 (void)getmessage (m, S_UNLOAD_PRINTWHEEL, &pwheel_name); 776 syslog(LOG_DEBUG, "s_unload_printwheel(%s)", 777 (pwheel_name ? pwheel_name : "NULL")); 778 779 780 /* 781 * Remove all print wheel alerts? 782 */ 783 if (!*pwheel_name || STREQU(pwheel_name, NAME_ALL)) { 784 int i; 785 786 for (i = 0; PWStatus != NULL && PWStatus[i] != NULL; i++) 787 _unload_pwheel (PWStatus[i]); 788 free(PWStatus); 789 PWStatus = NULL; 790 status = MOK; 791 792 /* 793 * Have we seen this print wheel before? 794 */ 795 } else if (!(ppws = search_pwstatus(pwheel_name))) 796 status = MNODEST; 797 798 else { 799 _unload_pwheel (ppws); 800 list_remove((void ***)&PWStatus, (void *)ppws); 801 status = MOK; 802 803 } 804 805 mputm (md, R_UNLOAD_PRINTWHEEL, status); 806 return; 807 } 808