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