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 2001 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.11.1.10 */ 32 /* EMACS_MODES: !fill, lnumb, !overwrite, !nodelete, !picture */ 33 34 #include "lpsched.h" 35 36 #include "validate.h" 37 38 #define register auto 39 40 int pickfilter ( RSTATUS * , CANDIDATE * , FSTATUS * ); 41 42 unsigned long chkprinter_result = 0; 43 char * o_cpi = 0; 44 char * o_lpi = 0; 45 char * o_width = 0; 46 char * o_length = 0; 47 48 static int wants_nobanner = 0; 49 static int lp_or_root = 0; 50 51 static int _chkopts ( RSTATUS *, CANDIDATE * , FSTATUS * ); 52 static void free_candidate ( CANDIDATE * ); 53 54 /** 55 ** _validate() - FIND A PRINTER TO HANDLE A REQUEST 56 **/ 57 58 short 59 _validate(RSTATUS *prs, PSTATUS *pps, PSTATUS *stop_pps, char **prefixp, 60 int moving) 61 { 62 register CANDIDATE *pc = 0, 63 *pcend, 64 *best_pc = 0; 65 66 register FSTATUS *pfs = 0; 67 68 register CSTATUS *pcs = 0; 69 70 CANDIDATE *arena = 0, 71 single; 72 73 size_t n; 74 75 short ret; 76 77 chkprinter_result = 0; 78 o_cpi = o_lpi = o_width = o_length = 0; 79 wants_nobanner = 0; 80 memset (&single, 0, sizeof(single)); 81 82 lp_or_root = 0; 83 84 if (STREQU(prs->secure->system, Local_System)) 85 if (bangequ(prs->secure->user, "root") || 86 bangequ(prs->secure->user, "lp")) 87 lp_or_root = 1; 88 89 90 if (prefixp) 91 *prefixp = prs->request->destination; 92 93 /* 94 * If a destination other than "any" was given, 95 * see if it exists in our internal tables. 96 */ 97 if (!pps && prs->request->destination && 98 !STREQU(prs->request->destination, NAME_ANY)) 99 if (((pps = search_ptable(prs->request->destination)) != NULL) || 100 ((pcs = search_ctable(prs->request->destination)) != NULL) && 101 pcs->class->members) 102 /*EMPTY*/; 103 else { 104 ret = MNODEST; 105 goto Return; 106 } 107 108 /* 109 * If we are trying to avoid a printer, but the request 110 * was destined for just that printer, we're out. 111 */ 112 if (pps && pps == stop_pps) { 113 ret = MERRDEST; 114 goto Return; 115 } 116 117 /* 118 * If a form was given, see if it exists; if so, 119 * see if the user is allowed to use it. 120 * If a remote printer was specified, then don't use any local 121 * form knowledge. 122 */ 123 if (prs && prs->request && prs->request->form && (pps || pcs)) { 124 if ((pfs = search_ftable(prs->request->form))) { 125 if (lp_or_root || allowed(prs->secure->user, 126 pfs->users_allowed, pfs->users_denied)) 127 /*EMPTY*/; 128 else { 129 ret = MDENYMEDIA; 130 goto Return; 131 } 132 } else { 133 ret = MNOMEDIA; 134 goto Return; 135 } 136 } 137 138 /* 139 * If the request includes -o options there may be pitch and 140 * size and no-banner requests that have to be checked. One 141 * could argue that this shouldn't be in the Spooler, because 142 * the Spooler's job is SPOOLING, not PRINTING. That's right, 143 * except that the Spooler will be making a choice of printers 144 * so it has to evaluate carefully: E.g. user wants ANY printer, 145 * so we should pick one that can handle what he/she wants. 146 * 147 * Parse out the important stuff here so we have it when we 148 * need it. 149 */ 150 { 151 register char **list, 152 **pl; 153 154 if ( 155 prs->request->options 156 && (list = dashos(prs->request->options)) 157 ) { 158 for (pl = list ; *pl; pl++) 159 if (STRNEQU(*pl, "cpi=", 4)) 160 o_cpi = Strdup(*pl + 4); 161 else if (STRNEQU(*pl, "lpi=", 4)) 162 o_lpi = Strdup(*pl + 4); 163 else if (STRNEQU(*pl, "width=", 6)) 164 o_width = Strdup(*pl + 6); 165 else if (STRNEQU(*pl, "length=", 7)) 166 o_length = Strdup(*pl + 7); 167 else if (STREQU(*pl, "nobanner")) 168 wants_nobanner = 1; 169 freelist (list); 170 } 171 } 172 173 /* 174 * This macro checks that a form has a mandatory print wheel 175 * (or character set). 176 */ 177 #define CHKMAND(PFS) \ 178 ( \ 179 (PFS) \ 180 && (PFS)->form->chset \ 181 && !STREQU((PFS)->form->chset, NAME_ANY) \ 182 && (PFS)->form->mandatory \ 183 ) 184 185 /* 186 * This macro checks that the user is allowed to use the 187 * printer. 188 */ 189 #define CHKU(PRS,PPS) \ 190 ( \ 191 lp_or_root \ 192 || allowed( \ 193 (PRS)->secure->user, \ 194 (PPS)->users_allowed, \ 195 (PPS)->users_denied \ 196 ) \ 197 ) 198 199 /* 200 * This macro checks that the form is allowed on the printer, 201 * or is already mounted there. 202 * Note: By doing this check we don't have to check that the 203 * characteristics of the form, such as pitch, size, or 204 * character set, against the printer's capabilities, ASSUMING, 205 * of course, that the allow list is correct. That is, the 206 * allow list lists forms that have already been checked against 207 * the printer! 208 */ 209 #define CHKF(PFS,PPS) \ 210 ( \ 211 isFormMountedOnPrinter(PPS,PFS) \ 212 || allowed( \ 213 (PFS)->form->name, \ 214 (PPS)->forms_allowed, \ 215 (PPS)->forms_denied \ 216 ) \ 217 ) 218 219 /* 220 * This macro checks that the print wheel is acceptable 221 * for the printer or is mounted. Note: If the printer doesn't 222 * take print wheels, the check passes. The check for printers 223 * that don't take print wheels is below. 224 */ 225 #define CHKPW(PW,PPS) \ 226 ( \ 227 !(PPS)->printer->daisy \ 228 || ( \ 229 (PPS)->pwheel_name \ 230 && STREQU((PPS)->pwheel_name, (PW)) \ 231 ) \ 232 || searchlist((PW), (PPS)->printer->char_sets) \ 233 ) 234 235 /* 236 * This macro checks the pitch, page size, and (if need be) 237 * the character set. The character set isn't checked if the 238 * printer takes print wheels, or if the character set is 239 * listed in the printer's alias list. 240 * The form has to be checked as well; while we're sure that 241 * at least one type for each printer can handle the form's 242 * cpi/lpi/etc. characteristics (lpadmin made sure), we aren't 243 * sure that ALL the types work. 244 */ 245 #define CHKOPTS(PRS,PC,PFS) _chkopts((PRS),(PC),(PFS)) /* was a macro */ 246 247 /* 248 * This macro checks the acceptance status of a printer. 249 * If the request is already assigned to that printer, 250 * then it's okay. It's ambiguous what should happen if 251 * originally a "-d any" request was accepted, temporarily 252 * assigned one printer, then the administrator (1) rejected 253 * further requests for the printers and (2) made the 254 * temporarily assigned printer unusable for the request. 255 * What will happen, of course, is that the request will 256 * be canceled, even though the other printers would be okay 257 * if not rejecting....but if we were to say, gee it's okay, 258 * the request has already been accepted, we may be allowing 259 * it on printers that were NEVER accepting. Thus we can 260 * continue to accept it only for the printer already assigned. 261 */ 262 #define CHKACCEPT(PRS,PPS) \ 263 ( \ 264 !((PPS)->status & PS_REJECTED) \ 265 || (PRS)->printer == (PPS) \ 266 || moving \ 267 ) 268 269 /* 270 * If a print wheel or character set is given, see if it 271 * is allowed on the form. 272 */ 273 if (prs->request->charset) 274 if ( 275 !CHKMAND(pfs) 276 || STREQU(prs->request->charset, pfs->form->chset) 277 ) 278 /*EMPTY*/; 279 else { 280 ret = MDENYMEDIA; 281 chkprinter_result |= PCK_CHARSET; 282 goto Return; 283 } 284 285 /* 286 * If a single printer was named, check the request against it. 287 * Do the accept/reject check late so that we give the most 288 * useful information to the user. 289 */ 290 if (pps) { 291 (pc = &single)->pps = pps; 292 293 /* Does the printer allow the user? */ 294 if (!CHKU(prs, pps)) { 295 ret = MDENYDEST; 296 goto Return; 297 } 298 299 /* Does the printer allow the form? */ 300 if (pfs && !CHKF(pfs, pps)) { 301 ret = MNOMOUNT; 302 goto Return; 303 } 304 305 /* Does the printer allow the pwheel? */ 306 if ( 307 prs->request->charset 308 && !CHKPW(prs->request->charset, pps) 309 ) { 310 ret = MNOMOUNT; 311 goto Return; 312 } 313 314 /* Can printer handle the pitch/size/charset/nobanner? */ 315 if (!CHKOPTS(prs, pc, pfs)) { 316 ret = MDENYDEST; 317 goto Return; 318 } 319 320 /* Is the printer allowing requests? */ 321 if (!CHKACCEPT(prs, pps)) { 322 ret = MERRDEST; 323 goto Return; 324 } 325 326 /* Is there a filter which will convert the input? */ 327 if (!pickfilter(prs, pc, pfs)) { 328 ret = MNOFILTER; 329 goto Return; 330 } 331 332 best_pc = pc; 333 ret = MOK; 334 goto Return; 335 } 336 337 /* 338 * Do the acceptance check on the class (if we have one) 339 * now so we can proceed with checks on individual printers 340 * in the class. Don't toss out the request if it is already 341 * assigned a printer just because the class is NOW rejecting. 342 */ 343 if ( 344 pcs 345 && (pcs->status & CS_REJECTED) 346 && !moving 347 && !prs->printer 348 ) { 349 ret = MERRDEST; 350 goto Return; 351 } 352 353 /* 354 * Construct a list of printers based on the destination 355 * given. Cross off those that aren't accepting requests, 356 * that can't take the form, or which the user can't use. 357 * See if the list becomes empty. 358 */ 359 360 if (pcs) 361 n = lenlist(pcs->class->members); 362 else { 363 n = 0; 364 for (pps = walk_ptable(1); pps; pps = walk_ptable(0)) 365 n++; 366 } 367 pcend = arena = (CANDIDATE *)Calloc(n, sizeof(CANDIDATE)); 368 369 /* 370 * Start with a list of printers that are accepting requests. 371 * Don't skip a printer if it's rejecting but the request 372 * has already been accepted for it. 373 */ 374 if (pcs) { 375 register char **pn; 376 377 for (pn = pcs->class->members; *pn; pn++) 378 if ( 379 ((pps = search_ptable(*pn)) != NULL) 380 && pps != stop_pps 381 ) 382 (pcend++)->pps = pps; 383 384 385 } else 386 for (pps = walk_ptable(1); pps; pps = walk_ptable(0)) 387 if (CHKACCEPT(prs, pps) && pps != stop_pps) 388 (pcend++)->pps = pps; 389 390 if (pcend == arena) { 391 ret = MERRDEST; 392 goto Return; 393 } 394 395 /* 396 * Clean out printers that the user can't use. We piggy-back 397 * the pitch/size/banner checks here because the same error return 398 * is given (strange, eh?). 399 */ 400 { 401 register CANDIDATE *pcend2; 402 403 for (pcend2 = pc = arena; pc < pcend; pc++) { 404 if (CHKU(prs, pc->pps) && CHKOPTS(prs, pc, pfs)) 405 *pcend2++ = *pc; 406 else 407 free_candidate (pc); 408 } 409 410 if (pcend2 == arena) { 411 ret = MDENYDEST; 412 goto Return; 413 } 414 pcend = pcend2; 415 416 } 417 418 /* 419 * Clean out printers that can't mount the form, 420 * EXCEPT for printers that already have it mounted: 421 */ 422 if (pfs) { 423 register CANDIDATE *pcend2; 424 425 for (pcend2 = pc = arena; pc < pcend; pc++) 426 if (CHKF(pfs, pc->pps)) 427 *pcend2++ = *pc; 428 else 429 free_candidate (pc); 430 431 if (pcend2 == arena) { 432 ret = MNOMOUNT; 433 goto Return; 434 } 435 pcend = pcend2; 436 437 } 438 439 /* 440 * Clean out printers that can't take the print wheel 441 * EXCEPT for printers that already have it mounted 442 * or printers for which it is a selectable character set: 443 */ 444 if (prs->request->charset) { 445 register CANDIDATE *pcend2; 446 447 for (pcend2 = pc = arena; pc < pcend; pc++) 448 if (CHKPW(prs->request->charset, pc->pps)) 449 *pcend2++ = *pc; 450 else 451 free_candidate (pc); 452 453 if (pcend2 == arena) { 454 ret = MNOMOUNT; 455 goto Return; 456 } 457 pcend = pcend2; 458 459 } 460 461 /* 462 * Clean out printers that can't handle the printing 463 * and for which there's no filter to convert the input. 464 * 465 */ 466 467 /* 468 * Is the form mounted, or is none needed? 469 */ 470 #define CHKFMNT(PFS,PPS) (isFormUsableOnPrinter(PPS,PFS)) 471 472 /* 473 * Is the print-wheel mounted, or is none needed? 474 */ 475 #define CHKPWMNT(PRS,PPS) SAME((PPS)->pwheel_name, (PRS)->request->charset) 476 477 /* 478 * Do we NOT need a special character set, or can we select 479 * it on the printer? Note: Getting this far means that IF 480 * the printer has selectable character sets (!daisy) then 481 * it can select the one we want. 482 */ 483 #define CHKCHSET(PRS,PPS) \ 484 ( \ 485 !(PRS)->request->charset \ 486 || !(PPS)->printer->daisy \ 487 ) 488 489 /* 490 * Is the printer able to print now? 491 */ 492 #define CHKENB(PPS) (!((PPS)->status & (PS_DISABLED|PS_FAULTED))) 493 494 /* 495 * Is the printer not busy printing another request, or 496 * not awaiting an auto-retry after a fault? 497 */ 498 #define CHKFREE(PPS) (!((PPS)->status & (PS_BUSY|PS_LATER))) 499 500 /* 501 * Is the printer local? 502 */ 503 #define CHKLOCAL(PPS) (!((PPS)->status & (PS_REMOTE))) 504 505 { 506 register CANDIDATE *pcend2; 507 508 for (pcend2 = pc = arena; pc < pcend; pc++) 509 if (pickfilter(prs, pc, pfs)) { 510 511 /* 512 * Compute a ``weight'' for this printer, 513 * based on its status. We'll later pick 514 * the printer with the highest weight. 515 */ 516 pc->weight = 0; 517 if (!pc->fast && !pc->slow) 518 pc->weight += WEIGHT_NOFILTER; 519 if (CHKFREE(pc->pps)) 520 pc->weight += WEIGHT_FREE; 521 if (CHKENB(pc->pps)) 522 pc->weight += WEIGHT_ENABLED; 523 if (CHKFMNT(pfs, pc->pps)) 524 pc->weight += WEIGHT_MOUNTED; 525 if (CHKPWMNT(prs, pc->pps)) 526 pc->weight += WEIGHT_MOUNTED; 527 if (CHKCHSET(prs, pc->pps)) 528 pc->weight += WEIGHT_SELECTS; 529 if (CHKLOCAL(pc->pps)) 530 pc->weight += WEIGHT_LOCAL; 531 532 #if defined(FILTER_EARLY_OUT) 533 if (pc->weight == WEIGHT_MAX) { 534 /* 535 * This is the one! 536 */ 537 best_pc = pc; 538 ret = MOK; 539 goto Return; 540 } 541 #endif 542 /* 543 * This is a candidate! 544 */ 545 *pcend2++ = *pc; 546 547 } else 548 /* 549 * No filter for this one! 550 */ 551 free_candidate (pc); 552 553 if (pcend2 == arena) { 554 ret = MNOFILTER; 555 goto Return; 556 } 557 pcend = pcend2; 558 559 } 560 561 if (pcend - arena == 1) { 562 best_pc = arena; 563 ret = MOK; 564 goto Return; 565 } 566 567 #if defined(OTHER_FACTORS) 568 /* 569 * Here you might want to add code that considers 570 * other factors: the size of the file(s) to be 571 * printed ("prs->secure->size") in relation to the 572 * printer (e.g. printer A gets mostly large 573 * files, printer B gets mostly small files); the 574 * number/total-size of requests currently queued 575 * for the printer; etc. 576 * 577 * If your code includes eliminating printers drop them 578 * from the list (as done in several places above). 579 * Otherwise, your code should add weights to the weight 580 * already computed. Change the WEIGHT_MAX, increase the 581 * other WEIGHT_X values to compensate, etc., as appropriate. 582 */ 583 ; 584 #endif 585 586 /* 587 * Pick the best printer from a list of eligible candidates. 588 */ 589 best_pc = arena; 590 for (pc = arena + 1; pc < pcend; pc++) 591 if (pc->weight > best_pc->weight) 592 best_pc = pc; 593 ret = MOK; 594 595 /* 596 * Branch to here if MOK and/or if things have been allocated. 597 */ 598 Return: if (ret == MOK) { 599 register USER *pu = Getuser(prs->secure->user); 600 601 register char *pwheel_name; 602 603 PSTATUS *oldpps = prs->printer; 604 605 606 /* 607 * We are going to accept this print request, having 608 * found a printer for it. This printer will be assigned 609 * to the request, although this assignment may be 610 * temporary if other printers qualify and this printer 611 * is changed to no longer qualify. Qualification in 612 * this context includes being ready to print! 613 */ 614 prs->printer = best_pc->pps; 615 load_str (&(prs->printer_type), best_pc->printer_type); 616 617 /* 618 * Assign the form (if any) to the request. Adjust 619 * the number of requests queued for old and new form 620 * accordingly. 621 */ 622 if (prs->form != pfs) { 623 unqueue_form (prs); 624 queue_form (prs, pfs); 625 } 626 627 /* 628 * Ditto for the print wheel, except include here the 629 * print wheel needed by the form. 630 * CAUTION: When checking this request later, don't 631 * refuse to service it if the print wheel for the 632 * form isn't mounted but the form is; a mounted form 633 * overrides its other needs. Don't be confused by the 634 * name of the bit, RSS_PWMAND; a printer that prints 635 * this request MUST have the print wheel mounted 636 * (if it takes print wheels) if the user asked for 637 * a particular print wheel. 638 */ 639 prs->status &= ~RSS_PWMAND; 640 if (CHKMAND(pfs)) 641 pwheel_name = pfs->form->chset; 642 else 643 if ((pwheel_name = prs->request->charset) != NULL) 644 prs->status |= RSS_PWMAND; 645 646 if (!SAME(pwheel_name, prs->pwheel_name)) { 647 unqueue_pwheel (prs); 648 queue_pwheel (prs, pwheel_name); 649 } 650 651 /* 652 * Adjust the priority to lie within the limits allowed 653 * for the user (this is a silent adjustment as required). 654 * CURRENTLY, ONLY NEW REQUESTS WILL GET QUEUED ACCORDING 655 * TO THIS PRIORITY. EXISTING REQUESTS BEING (RE)EVALUATED 656 * WILL NOT BE REQUEUED. 657 * A wild priority is changed to the default, or the 658 * limit, whichever is the lower priority (higher value). 659 */ 660 if (prs->request->priority < 0 || 39 < prs->request->priority) 661 prs->request->priority = getdfltpri(); 662 if (pu && prs->request->priority < pu->priority_limit) 663 prs->request->priority = pu->priority_limit; 664 665 /* 666 * If a filter is involved, change the number of 667 * copies to 1 (if the filter handles it). 668 */ 669 if ( 670 (best_pc->fast || best_pc->slow) 671 && (best_pc->flags & FPARM_COPIES) 672 && prs->request->copies > 1 673 ) 674 prs->copies = 1; 675 else 676 /* 677 * We use two ".copies" because we don't 678 * want to lose track of the number requested, 679 * but do want to mark the number the interface 680 * program is to handle. Here is the best 681 * place to know this. 682 */ 683 prs->copies = prs->request->copies; 684 685 if (best_pc->slow) { 686 /* 687 * If the filter has changed, the request will 688 * have to be refiltered. This may mean stopping 689 * a currently running filter or interface. 690 */ 691 if (!SAME(best_pc->slow, prs->slow)) { 692 693 if (prs->request->outcome & RS_FILTERED) 694 prs->request->outcome &= ~RS_FILTERED; 695 696 if ( 697 prs->request->outcome & RS_FILTERING 698 && !(prs->request->outcome & RS_STOPPED) 699 ) { 700 prs->request->outcome |= RS_REFILTER; 701 prs->request->outcome |= RS_STOPPED; 702 terminate (prs->exec); 703 704 } else if ( 705 prs->request->outcome & RS_PRINTING 706 && !(prs->request->outcome & RS_STOPPED) 707 ) { 708 prs->request->outcome |= RS_STOPPED; 709 terminate (oldpps->exec); 710 } 711 712 } 713 714 load_str (&(prs->slow), best_pc->slow); 715 /* Assumption: if there is a slow filter, 716 * there is an output_type 717 */ 718 719 load_str (&(prs->output_type), best_pc->output_type); 720 } else 721 unload_str (&(prs->slow)); 722 723 load_str (&(prs->fast), best_pc->fast); 724 725 if (prs->request->actions & ACT_FAST && prs->slow) { 726 if (prs->fast) { 727 prs->fast = makestr( 728 prs->slow, 729 "|", 730 prs->fast, 731 (char *)0 732 ); 733 Free (prs->slow); 734 } else 735 prs->fast = prs->slow; 736 prs->slow = 0; 737 } 738 739 } 740 741 742 /* 743 * Free the space allocated for the candidates, INCLUDING 744 * the one chosen. Any allocated space in the chosen candidate 745 * that has to be saved should have been COPIED already. 746 */ 747 if (arena) { 748 for (pc = arena; pc < pcend; pc++) 749 free_candidate (pc); 750 Free ((char *)arena); 751 } else if (best_pc) 752 free_candidate (best_pc); 753 754 if (o_length) 755 Free (o_length); 756 if (o_width) 757 Free (o_width); 758 if (o_lpi) 759 Free (o_lpi); 760 if (o_cpi) 761 Free (o_cpi); 762 763 764 /* 765 * The following value is valid ONLY IF the request 766 * is canceled or rejected. Not all requests that 767 * we fail in this routine are tossed out! 768 */ 769 prs->reason = ret; 770 771 772 return (ret); 773 } 774 775 /** 776 ** _chkopts() - CHECK -o OPTIONS 777 **/ 778 779 static int 780 _chkopts(RSTATUS *prs, CANDIDATE *pc, FSTATUS *pfs) 781 { 782 unsigned long ret = 0; 783 unsigned long chk = 0; 784 785 char * charset; 786 char * cpi = 0; 787 char * lpi = 0; 788 char * width = 0; 789 char * length = 0; 790 char * paper = NULL; 791 792 char ** pt; 793 794 795 /* 796 * If we have a form, it overrides whatever print characteristics 797 * the user gave. 798 */ 799 if (pfs) { 800 cpi = pfs->cpi; 801 lpi = pfs->lpi; 802 width = pfs->pwid; 803 length = pfs->plen; 804 paper = pfs->form->paper; 805 } else { 806 cpi = o_cpi; 807 lpi = o_lpi; 808 width = o_width; 809 length = o_length; 810 } 811 812 /* 813 * If the printer takes print wheels, or the character set 814 * the user wants is listed in the character set map for this 815 * printer, we needn't check if the printer can handle the 816 * character set. (Note: The check for the print wheel case 817 * is done elsewhere.) 818 */ 819 820 if (pc->pps->printer->daisy || 821 search_cslist(prs->request->charset, pc->pps->printer->char_sets)) 822 charset = 0; 823 else 824 charset = prs->request->charset; 825 826 pc->printer_types = 0; 827 for (pt = pc->pps->printer->printer_types; *pt; pt++) { 828 unsigned long this; 829 830 if (paper) { 831 if (allowed(paper,pc->pps->paper_allowed,NULL)) { 832 addlist (&(pc->printer_types), *pt); 833 } else { 834 ret |= PCK_PAPER; 835 } 836 } else { 837 this = chkprinter(*pt, cpi, lpi, length, width, 838 charset); 839 if (this == 0) 840 addlist(&(pc->printer_types), *pt); 841 chk |= this; 842 } 843 } 844 if (!pc->printer_types) 845 ret |= chk; 846 847 if (pc->pps->printer->banner == BAN_ALWAYS) { 848 if ((wants_nobanner == 1) && (lp_or_root != 1)) { 849 /* delete "nobanner" */ 850 char **list; 851 852 if (prs->request->options && 853 (list = dashos(prs->request->options))) { 854 dellist(&list, "nobanner"); 855 free(prs->request->options); 856 prs->request->options = sprintlist(list); 857 } 858 } 859 } else if (pc->pps->printer->banner == BAN_NEVER) { 860 if (wants_nobanner == 0) { 861 /* add "nobanner" */ 862 char **list = NULL; 863 864 if (prs->request->options) { 865 list = dashos(prs->request->options); 866 free(prs->request->options); 867 } 868 appendlist(&list, "nobanner"); 869 prs->request->options = sprintlist(list); 870 } 871 } else /* if (pc->pps->printer->banner == BAN_OPTIONAL) */ { 872 /* it is optional, leave it alone */ 873 } 874 875 chkprinter_result |= ret; 876 return (ret == 0); 877 } 878 879 /** 880 ** free_candidate() 881 **/ 882 883 static void 884 free_candidate(CANDIDATE *pc) 885 { 886 if (pc->slow) 887 unload_str (&(pc->slow)); 888 if (pc->fast) 889 unload_str (&(pc->fast)); 890 if (pc->printer_types) { 891 freelist (pc->printer_types); 892 pc->printer_types = 0; 893 } 894 if (pc->printer_type) 895 unload_str (&(pc->printer_type)); 896 if (pc->output_type) 897 unload_str (&(pc->output_type)); 898 return; 899 } 900