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