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 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 23 /* All Rights Reserved */ 24 25 26 /* 27 * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 28 * Use is subject to license terms. 29 */ 30 31 #pragma ident "%Z%%M% %I% %E% SMI" 32 33 #include "stdio.h" 34 #include "string.h" 35 #include "pwd.h" 36 #include "sys/types.h" 37 #include "errno.h" 38 39 #include "lp.h" 40 #include "printers.h" 41 #include "form.h" 42 #include "class.h" 43 44 #define WHO_AM_I I_AM_LPADMIN 45 #include "oam.h" 46 47 #include "lpadmin.h" 48 49 #define PPDZIP ".gz" 50 51 52 extern PRINTER *printer_pointer; 53 54 extern PWHEEL *pwheel_pointer; 55 56 extern struct passwd *getpwnam(); 57 58 void chkopts2(), 59 chkopts3(); 60 static void chksys(); 61 62 FORM formbuf; 63 64 char **f_allow, 65 **f_deny, 66 **u_allow, 67 **u_deny, 68 **p_add, 69 **p_remove; 70 71 PRINTER *oldp = 0; 72 73 PWHEEL *oldS = 0; 74 75 short daisy = 0; 76 77 static int root_can_write(); 78 79 static char *unpack_sdn(); 80 81 static char ** bad_list; 82 83 #if defined(__STDC__) 84 static unsigned long sum_chkprinter ( char ** , char * , char * , char * , char * , char * ); 85 static int isPPD(char *ppd_file); 86 #else 87 static unsigned long sum_chkprinter(); 88 static int isPPD(); 89 #endif 90 91 /** 92 ** chkopts() -- CHECK LEGALITY OF COMMAND LINE OPTIONS 93 **/ 94 95 void chkopts () 96 { 97 short isfAuto = 0; 98 99 /* 100 * Check -d. 101 */ 102 if (d) { 103 if ( 104 a || c || f || P || j || m || M || t || p || r || u || x 105 #if defined(DIRECT_ACCESS) 106 || C 107 #endif 108 #ifdef LP_USE_PAPI_ATTR 109 || n_opt 110 #endif 111 || strlen(modifications) 112 ) { 113 LP_ERRMSG (ERROR, E_ADM_DALONE); 114 done (1); 115 } 116 117 if ( 118 *d 119 && !STREQU(d, NAME_NONE) 120 && !isprinter(d) 121 && !isclass(d) 122 ) { 123 LP_ERRMSG1 (ERROR, E_ADM_NODEST, d); 124 done (1); 125 } 126 return; 127 } 128 129 /* 130 * Check -x. 131 */ 132 if (x) { 133 if ( /* MR bl88-02718 */ 134 A || a || c || f || P || j || m || M || t || p || r || u || d 135 #if defined(DIRECT_ACCESS) 136 || C 137 #endif 138 #ifdef LP_USE_PAPI_ATTR 139 || n_opt 140 #endif 141 || strlen(modifications) 142 ) { 143 LP_ERRMSG (ERROR, E_ADM_XALONE); 144 done (1); 145 } 146 147 if ( 148 !STREQU(NAME_ALL, x) 149 && !STREQU(NAME_ANY, x) 150 && !isprinter(x) 151 && !isclass(x) 152 ) { 153 LP_ERRMSG1 (ERROR, E_ADM_NODEST, x); 154 done (1); 155 } 156 return; 157 } 158 159 /* 160 * Problems common to both -p and -S (-S alone). 161 */ 162 if (A && STREQU(A, NAME_LIST) && (W != -1 || Q != -1)) { 163 LP_ERRMSG (ERROR, E_ADM_LISTWQ); 164 done (1); 165 } 166 167 168 /* 169 * Check -S. 170 */ 171 if (!p && S) { 172 if ( 173 M || t || a || f || P || c || r || e || i || m || H || h 174 || l || v || I || T || D || F || u || U || j || o 175 #ifdef LP_USE_PAPI_ATTR 176 || n_opt 177 #endif 178 ) { 179 LP_ERRMSG (ERROR, E_ADM_SALONE); 180 done (1); 181 } 182 if (!A && W == -1 && Q == -1) { 183 LP_ERRMSG (ERROR, E_ADM_NOAWQ); 184 done (1); 185 } 186 if (S[0] && S[1]) 187 LP_ERRMSG (WARNING, E_ADM_ASINGLES); 188 if (!STREQU(NAME_ALL, *S) && !STREQU(NAME_ANY, *S)) 189 chkopts3(1); 190 return; 191 } 192 193 /* 194 * At this point we must have a printer (-p option). 195 */ 196 if (!p) { 197 LP_ERRMSG (ERROR, E_ADM_NOACT); 198 done (1); 199 } 200 if (STREQU(NAME_NONE, p)) { 201 LP_ERRMSG1 (ERROR, E_LP_NULLARG, "p"); 202 done (1); 203 } 204 205 206 /* 207 * Mount but nothing to mount? 208 */ 209 if (M && (!f && !S)) { 210 LP_ERRMSG (ERROR, E_ADM_MNTNONE); 211 done (1); 212 } 213 214 /* 215 * -Q isn't allowed with -p. 216 */ 217 if (Q != -1) { 218 LP_ERRMSG (ERROR, E_ADM_PNOQ); 219 done (1); 220 } 221 222 /* 223 * Fault recovery. 224 */ 225 if ( 226 F 227 && !STREQU(F, NAME_WAIT) 228 && !STREQU(F, NAME_BEGINNING) 229 && ( 230 !STREQU(F, NAME_CONTINUE) 231 || j 232 && STREQU(F, NAME_CONTINUE) 233 ) 234 ) { 235 #if defined(J_OPTION) 236 if (j) 237 LP_ERRMSG (ERROR, E_ADM_FBADJ); 238 else 239 #endif 240 LP_ERRMSG (ERROR, E_ADM_FBAD); 241 done (1); 242 } 243 244 #if defined(J_OPTION) 245 /* 246 * The -j option is used only with the -F option. 247 */ 248 if (j) { 249 if (M || t || a || f || P || c || r || e || i || m || H || h || 250 #ifdef LP_USE_PAPI_ATTR 251 n_opt || 252 #endif 253 l || v || I || T || D || u || U || o) { 254 LP_ERRMSG (ERROR, E_ADM_JALONE); 255 done (1); 256 } 257 if (j && !F) { 258 LP_ERRMSG (ERROR, E_ADM_JNOF); 259 done (1); 260 } 261 return; 262 } 263 #endif 264 265 #if defined(DIRECT_ACCESS) 266 /* 267 * -C is only used to modify -u 268 */ 269 if (C && !u) { 270 LP_ERRMSG (ERROR, E_ADM_CNOU); 271 done (1); 272 } 273 #endif 274 275 /* 276 * The -a option needs the -M and -f options, 277 * Also, -ofilebreak is used only with -a. 278 */ 279 if (a && (!M || !f)) { 280 LP_ERRMSG (ERROR, E_ADM_MALIGN); 281 done (1); 282 } 283 if (filebreak && !a) 284 LP_ERRMSG (WARNING, E_ADM_FILEBREAK); 285 286 /* 287 * The "-p all" case is restricted to certain options. 288 */ 289 if ( 290 (STREQU(NAME_ANY, p) || STREQU(NAME_ALL, p)) 291 && ( 292 a || h || l || M || t || D || e || f || P || H || s 293 #ifdef LP_USE_PAPI_ATTR 294 || n_opt 295 #endif 296 || i || I || m || S || T || u || U || v || banner != -1 297 || cpi || lpi || width || length || stty_opt 298 ) 299 ) { 300 LP_ERRMSG (ERROR, E_ADM_ANYALLNONE); 301 done (1); 302 303 } 304 305 /* 306 * Allow giving -v or -U option as way of making 307 * remote printer into local printer. 308 * Note: "!s" here means the user has not given the -s; 309 * later it means the user gave -s local-system. 310 */ 311 if (!s && (v || U)) 312 s = Local_System; 313 314 /* 315 * Be careful about checking "s" before getting here. 316 * We want "s == 0" to mean this is a local printer; however, 317 * if the user wants to change a remote printer to a local 318 * printer, we have to have "s == Local_System" long enough 319 * to get into "chkopts2()" where a special check is made. 320 * After "chkopts2()", "s == 0" means local. 321 */ 322 if (!STREQU(NAME_ALL, p) && !STREQU(NAME_ANY, p)) 323 /* 324 * If old printer, make sure it exists. If new printer, 325 * check that the name is okay, and that enough is given. 326 * (This stuff has been moved to "chkopts2()".) 327 */ 328 chkopts2(1); 329 330 if (!s) { 331 332 /* 333 * Only one of -i, -m, -e. 334 */ 335 if ((i && e) || (m && e) || (i && m)) { 336 LP_ERRMSG (ERROR, E_ADM_INTCONF); 337 done (1); 338 } 339 340 /* 341 * Check -e arg. 342 */ 343 if (e) { 344 if (!isprinter(e)) { 345 LP_ERRMSG1 (ERROR, E_ADM_NOPR, e); 346 done (1); 347 } 348 if (strcmp(e, p) == 0) { 349 LP_ERRMSG (ERROR, E_ADM_SAMEPE); 350 done (1); 351 } 352 } 353 354 /* 355 * Check -m arg. 356 */ 357 if (m && !ismodel(m)) { 358 LP_ERRMSG1 (ERROR, E_ADM_NOMODEL, m); 359 done (1); 360 } 361 362 #ifdef LP_USE_PAPI_ATTR 363 /* 364 * Check -n arg. The ppd file exists. 365 */ 366 if ((n_opt != NULL) && !isPPD(n_opt)) { 367 LP_ERRMSG1 (ERROR, E_ADM_NOPPD, n_opt); 368 done (1); 369 } 370 #endif 371 372 /* 373 * Need exactly one of -h or -l (but will default -h). 374 */ 375 if (h && l) { 376 LP_ERRMSG2 (ERROR, E_ADM_CONFLICT, 'h', 'l'); 377 done (1); 378 } 379 if (!h && !l) 380 h = 1; 381 382 /* 383 * Check -c and -r. 384 */ 385 if (c && r && strcmp(c, r) == 0) { 386 LP_ERRMSG (ERROR, E_ADM_SAMECR); 387 done (1); 388 } 389 390 391 /* 392 * Are we creating a class with the same name as a printer? 393 */ 394 if (c) { 395 if (STREQU(c, p)) { 396 LP_ERRMSG1 (ERROR, E_ADM_CLNPR, c); 397 done (1); 398 } 399 if (isprinter(c)) { 400 LP_ERRMSG1 (ERROR, E_ADM_CLPR, c); 401 done (1); 402 } 403 } 404 405 if (v && (is_printer_uri(v) < 0)) { 406 /* 407 * The device must be writeable by root. 408 */ 409 if (v && root_can_write(v) == -1) 410 done (1); 411 } 412 413 /* 414 * Can't have both device and dial-out. 415 */ 416 if (v && U) { 417 LP_ERRMSG (ERROR, E_ADM_BOTHUV); 418 done (1); 419 } 420 421 } else 422 if ( 423 A || a || e || H || h || i || l || m || ( t && !M) || ( M && !t) 424 || o || U || v || Q != -1 || W != -1 425 #ifdef LP_USE_PAPI_ATTR 426 || n_opt 427 #endif 428 ) { 429 LP_ERRMSG (ERROR, E_ADM_NOTLOCAL); 430 done(1); 431 } 432 433 434 /* 435 * We need the printer type for some things, and the boolean 436 * "daisy" (from Terminfo) for other things. 437 */ 438 if (!T && oldp) 439 T = oldp->printer_types; 440 if (T) { 441 short a_daisy; 442 443 char ** pt; 444 445 446 if (lenlist(T) > 1 && searchlist(NAME_UNKNOWN, T)) { 447 LP_ERRMSG (ERROR, E_ADM_MUNKNOWN); 448 done (1); 449 } 450 451 for (pt = T; *pt; pt++) 452 if (tidbit(*pt, (char *)0) == -1) { 453 LP_ERRMSG1 (ERROR, E_ADM_BADTYPE, *pt); 454 done (1); 455 } 456 457 /* 458 * All the printer types had better agree on whether the 459 * printer takes print wheels! 460 */ 461 daisy = a_daisy = -1; 462 for (pt = T; *pt; pt++) { 463 tidbit (*pt, "daisy", &daisy); 464 if (daisy == -1) 465 daisy = 0; 466 if (a_daisy == -1) 467 a_daisy = daisy; 468 else if (a_daisy != daisy) { 469 LP_ERRMSG (ERROR, E_ADM_MIXEDTYPES); 470 done (1); 471 } 472 } 473 } 474 if (cpi || lpi || length || width || S || f || filebreak) 475 if (!T) { 476 LP_ERRMSG (ERROR, E_ADM_TOPT); 477 done (1); 478 479 } 480 481 /* 482 * Check -o cpi=, -o lpi=, -o length=, -o width= 483 */ 484 if (cpi || lpi || length || width) { 485 unsigned long rc; 486 487 if ((rc = sum_chkprinter(T, cpi, lpi, length, width, NULL)) == 0) { 488 if (bad_list) 489 LP_ERRMSG1 ( 490 INFO, 491 E_ADM_NBADCAPS, 492 sprintlist(bad_list) 493 ); 494 495 } else { 496 if ((rc & PCK_CPI) && cpi) 497 LP_ERRMSG1 (ERROR, E_ADM_BADCAP, "cpi="); 498 499 if ((rc & PCK_LPI) && lpi) 500 LP_ERRMSG1 (ERROR, E_ADM_BADCAP, "lpi="); 501 502 if ((rc & PCK_WIDTH) && width) 503 LP_ERRMSG1 (ERROR, E_ADM_BADCAP, "width="); 504 505 if ((rc & PCK_LENGTH) && length) 506 LP_ERRMSG1 (ERROR, E_ADM_BADCAP, "length="); 507 508 LP_ERRMSG (ERROR, E_ADM_BADCAPS); 509 done(1); 510 } 511 } 512 513 /* 514 * Check -I (old or new): 515 */ 516 if (T && lenlist(T) > 1) { 517 518 #define BADILIST(X) (lenlist(X) > 1 || X && *X && !STREQU(NAME_SIMPLE, *X)) 519 if ( 520 I && BADILIST(I) 521 || !I && oldp && BADILIST(oldp->input_types) 522 ) { 523 LP_ERRMSG (ERROR, E_ADM_ONLYSIMPLE); 524 done (1); 525 } 526 } 527 528 /* 529 * MOUNT: 530 * Only one print wheel can be mounted at a time. 531 */ 532 if (M && S && S[0] && S[1]) 533 LP_ERRMSG (WARNING, E_ADM_MSINGLES); 534 535 /* 536 * NO MOUNT: 537 * If the printer takes print wheels, the -S argument 538 * should be a simple list; otherwise, it must be a 539 * mapping list. (EXCEPT: In either case, "none" alone 540 * means delete the existing list.) 541 */ 542 if (S && !M) { 543 register char **item, 544 *cp; 545 546 /* 547 * For us to be here, "daisy" must have been set. 548 * (-S requires knowing printer type (T), and knowing 549 * T caused call to "tidbit()" to set "daisy"). 550 */ 551 if (!STREQU(S[0], NAME_NONE) || S[1]) 552 if (daisy) { 553 for (item = S; *item; item++) { 554 if (strchr(*item, '=')) { 555 LP_ERRMSG (ERROR, E_ADM_PWHEELS); 556 done (1); 557 } 558 if (!syn_name(*item)) { 559 LP_ERRMSG1 (ERROR, E_LP_NOTNAME, *item); 560 done (1); 561 } 562 } 563 } else { 564 register int die = 0; 565 566 for (item = S; *item; item++) { 567 if (!(cp = strchr(*item, '='))) { 568 LP_ERRMSG (ERROR, E_ADM_CHARSETS); 569 done (1); 570 } 571 572 *cp = 0; 573 if (!syn_name(*item)) { 574 LP_ERRMSG1 (ERROR, E_LP_NOTNAME, *item); 575 done (1); 576 } 577 if (PCK_CHARSET & sum_chkprinter(T, (char *)0, (char *)0, (char *)0, (char *)0, *item)) { 578 LP_ERRMSG1 (ERROR, E_ADM_BADSET, *item); 579 die = 1; 580 } else { 581 if (bad_list) 582 LP_ERRMSG2 ( 583 INFO, 584 E_ADM_NBADSET, 585 *item, 586 sprintlist(bad_list) 587 ); 588 } 589 *cp++ = '='; 590 if (!syn_name(cp)) { 591 LP_ERRMSG1 (ERROR, E_LP_NOTNAME, cp); 592 done (1); 593 } 594 } 595 if (die) { 596 LP_ERRMSG (ERROR, E_ADM_BADSETS); 597 done (1); 598 } 599 } 600 } 601 602 if (P) { 603 int createForm = 0; 604 char **plist; 605 606 if (getform(P, &formbuf, (FALERT *)0, (FILE **)0) != -1) { 607 if ((!formbuf.paper) || (!STREQU(formbuf.paper,P)) ) { 608 LP_ERRMSG (ERROR, E_ADM_ALSO_SEP_FORM); 609 done (1); 610 } 611 } else 612 createForm = 1; 613 614 if (*P == '~') { /* removing types of papers */ 615 P++; 616 p_remove = getlist(P, LP_WS, LP_SEP); 617 p_add = NULL; 618 } else { /* adding types of papers */ 619 p_add = getlist(P, LP_WS, LP_SEP); 620 p_remove = NULL; 621 if (createForm) { 622 char cmdBuf[200]; 623 624 for (plist = p_add; *plist; plist++) { 625 snprintf(cmdBuf, sizeof (cmdBuf), 626 "lpforms -f %s -d\n", *plist); 627 system(cmdBuf); 628 } 629 } 630 } 631 632 if (!f && !M) { /* make paper allowed on printer too */ 633 f = Malloc(strlen(P) + strlen(NAME_ALLOW) + 634 strlen(": ")); 635 sprintf(f, "%s:%s", NAME_ALLOW, P); 636 isfAuto = 1; 637 } 638 } 639 /* 640 * NO MOUNT: 641 * The -f option restricts the forms that can be used with 642 * the printer. 643 * - construct the allow/deny lists 644 * - check each allowed form to see if it'll work 645 * on the printer 646 */ 647 if (f && !M) { 648 register char *type = strtok(f, ":"), 649 *str = strtok((char *)0, ":"), 650 **pf; 651 652 register int die = 0; 653 654 655 if (STREQU(type, NAME_ALLOW) && str) { 656 if ((pf = f_allow = getlist(str, LP_WS, LP_SEP)) != NULL) { 657 while (*pf) { 658 if ((!isfAuto) && 659 !STREQU(*pf, NAME_NONE) 660 && verify_form(*pf) < 0 661 ) 662 die = 1; 663 pf++; 664 } 665 if (die) { 666 LP_ERRMSG (ERROR, E_ADM_FORMCAPS); 667 done (1); 668 } 669 670 } else 671 LP_ERRMSG1 (WARNING, E_ADM_MISSING, NAME_ALLOW); 672 673 } else if (STREQU(type, NAME_DENY) && str) { 674 if ((pf = f_deny = getlist(str, LP_WS, LP_SEP)) != NULL) { 675 if (!STREQU(*pf, NAME_ALL)) { 676 while (*pf) { 677 if ((!isfAuto) && 678 !STREQU(*pf, NAME_NONE) && 679 getform(*pf, &formbuf, 680 (FALERT *)0, (FILE **)0) < 0 681 ) { 682 LP_ERRMSG2(WARNING, 683 E_ADM_ICKFORM, *pf, p); 684 die = 1; 685 } 686 pf++; 687 } 688 } 689 if (die) { 690 done (1); 691 } 692 693 } else 694 LP_ERRMSG1 (WARNING, E_ADM_MISSING, NAME_DENY); 695 696 } else { 697 LP_ERRMSG (ERROR, E_ADM_FALLOWDENY); 698 done (1); 699 } 700 } 701 702 /* 703 * The -u option is setting use restrictions on printers. 704 * - construct the allow/deny lists 705 */ 706 if (u) { 707 register char *type = strtok(u, ":"), 708 *str = strtok((char *)0, ":"); 709 710 if (STREQU(type, NAME_ALLOW) && str) { 711 if (!(u_allow = getlist(str, LP_WS, LP_SEP))) 712 LP_ERRMSG1 (WARNING, E_ADM_MISSING, NAME_ALLOW); 713 714 } else if (STREQU(type, NAME_DENY) && str) { 715 if (!(u_deny = getlist(str, LP_WS, LP_SEP))) 716 LP_ERRMSG1 (WARNING, E_ADM_MISSING, NAME_DENY); 717 718 } else { 719 LP_ERRMSG (ERROR, E_LP_UALLOWDENY); 720 done (1); 721 } 722 } 723 724 return; 725 } 726 727 /** 728 ** root_can_write() - CHECK THAT "root" CAN SENSIBLY WRITE TO PATH 729 **/ 730 731 static int root_can_write (path) 732 char *path; 733 { 734 static int lp_uid = -1; 735 736 struct passwd *ppw; 737 738 struct stat statbuf; 739 740 741 if (lstat(path, &statbuf) == -1) { 742 LP_ERRMSG1 (ERROR, E_ADM_NOENT, v); 743 return (-1); 744 } 745 /* 746 * If the device is a symlink (and it is not a root owned symlink), 747 * verify that the owner matches the destination owner. 748 */ 749 if (S_ISLNK(statbuf.st_mode) && statbuf.st_uid != 0) { 750 uid_t uid = statbuf.st_uid; 751 752 if (Stat(path, &statbuf) == -1) { 753 LP_ERRMSG1 (ERROR, E_ADM_NOENT, v); 754 return (-1); 755 } 756 757 if (statbuf.st_uid != uid) { 758 LP_ERRMSG1 (ERROR, E_ADM_ISMISMATCH, v); 759 done(1); 760 } 761 762 LP_ERRMSG1(WARNING, E_ADM_ISNOTROOTOWNED, v); 763 } 764 765 if ((statbuf.st_mode & S_IFMT) == S_IFDIR) { 766 LP_ERRMSG1 (WARNING, E_ADM_ISDIR, v); 767 } else if ((statbuf.st_mode & S_IFMT) == S_IFBLK) 768 LP_ERRMSG1 (WARNING, E_ADM_ISBLK, v); 769 770 if (lp_uid == -1) { 771 if (!(ppw = getpwnam(LPUSER))) 772 ppw = getpwnam(ROOTUSER); 773 endpwent (); 774 if (ppw) 775 lp_uid = ppw->pw_uid; 776 else 777 lp_uid = 0; 778 } 779 if (!STREQU(v, "/dev/null")) 780 if ((statbuf.st_uid && statbuf.st_uid != lp_uid) 781 || (statbuf.st_mode & (S_IWGRP|S_IRGRP|S_IWOTH|S_IROTH))) 782 LP_ERRMSG1 (WARNING, E_ADM_DEVACCESS, v); 783 784 return (0); 785 } 786 787 /** 788 ** unpack_sdn() - TURN SCALED TYPE INTO char* TYPE 789 **/ 790 791 static char *unpack_sdn (sdn) 792 SCALED sdn; 793 { 794 register char *cp; 795 extern char *malloc(); 796 797 if (sdn.val <= 0 || 99999 < sdn.val) 798 cp = 0; 799 800 else if (sdn.val == N_COMPRESSED) 801 cp = strdup(NAME_COMPRESSED); 802 803 else if ((cp = malloc(sizeof("99999.999x")))) 804 (void) sprintf(cp, "%.3f%c", sdn.val, sdn.sc); 805 806 return (cp); 807 } 808 809 /** 810 ** verify_form() - SEE IF PRINTER CAN HANDLE FORM 811 **/ 812 813 int verify_form (form) 814 char *form; 815 { 816 register char *cpi_f, 817 *lpi_f, 818 *width_f, 819 *length_f, 820 *chset; 821 822 register int rc = 0; 823 char **paperAllowed = NULL; 824 char **paperDenied = NULL; 825 826 register unsigned long checks; 827 828 829 if (STREQU(form, NAME_ANY)) 830 form = NAME_ALL; 831 832 while (getform(form, &formbuf, (FALERT *)0, (FILE **)0) != -1) { 833 if (formbuf.paper) { 834 if (!paperAllowed) { 835 load_paperprinter_access(p, &paperAllowed, 836 &paperDenied); 837 freelist(paperDenied); 838 } 839 if (!allowed(formbuf.paper,paperAllowed,NULL)) { 840 LP_ERRMSG1 (INFO, E_ADM_BADCAP, 841 gettext("printer doesn't support paper type")); 842 rc = -1; 843 } 844 } 845 else { 846 847 cpi_f = unpack_sdn(formbuf.cpi); 848 lpi_f = unpack_sdn(formbuf.lpi); 849 width_f = unpack_sdn(formbuf.pwid); 850 length_f = unpack_sdn(formbuf.plen); 851 852 if ( 853 formbuf.mandatory 854 && !daisy 855 && !search_cslist( 856 formbuf.chset, 857 (S && !M? S : (oldp? oldp->char_sets : (char **)0)) 858 ) 859 ) 860 chset = formbuf.chset; 861 else 862 chset = 0; 863 864 if ((checks = sum_chkprinter( 865 T, 866 cpi_f, 867 lpi_f, 868 length_f, 869 width_f, 870 chset 871 ))) { 872 rc = -1; 873 if ((checks & PCK_CPI) && cpi_f) 874 LP_ERRMSG1 (INFO, E_ADM_BADCAP, "cpi"); 875 876 if ((checks & PCK_LPI) && lpi_f) 877 LP_ERRMSG1 (INFO, E_ADM_BADCAP, "lpi"); 878 879 if ((checks & PCK_WIDTH) && width_f) 880 LP_ERRMSG1 (INFO, E_ADM_BADCAP, "width"); 881 882 if ((checks & PCK_LENGTH) && length_f) 883 LP_ERRMSG1 (INFO, E_ADM_BADCAP, "length"); 884 885 if ((checks & PCK_CHARSET) && formbuf.chset) { 886 LP_ERRMSG1 (INFO, E_ADM_BADSET, formbuf.chset); 887 rc = -2; 888 } 889 LP_ERRMSG1 (INFO, E_ADM_FORMCAP, formbuf.name); 890 } else { 891 if (bad_list) 892 LP_ERRMSG2 ( 893 INFO, 894 E_ADM_NBADMOUNT, 895 formbuf.name, 896 sprintlist(bad_list) 897 ); 898 } 899 } 900 901 if (!STREQU(form, NAME_ALL)) { 902 if (paperAllowed) 903 freelist(paperAllowed); 904 return (rc); 905 } 906 907 } 908 if (paperAllowed) 909 freelist(paperAllowed); 910 911 if (!STREQU(form, NAME_ALL)) { 912 LP_ERRMSG1 (ERROR, E_LP_NOFORM, form); 913 done (1); 914 } 915 916 return (rc); 917 } 918 919 /* 920 Second phase of parsing for -p option. 921 In a seperate routine so we can call it from other 922 routines. This is used when any or all are used as 923 a printer name. main() loops over each printer, and 924 must call this function for each printer found. 925 */ 926 void 927 chkopts2(called_from_chkopts) 928 int called_from_chkopts; 929 { 930 /* 931 Only do the getprinter() if we are not being called 932 from lpadmin.c. Otherwise we mess up our arena for 933 "all" processing. 934 */ 935 if (!called_from_chkopts) 936 oldp = printer_pointer; 937 else if (!(oldp = getprinter(p)) && errno != ENOENT) { 938 LP_ERRMSG2 (ERROR, E_LP_GETPRINTER, p, PERROR); 939 done(1); 940 } 941 942 if (oldp) { 943 if ( 944 !c && !d && !f && !P && !M && !t && !r && !u && !x && !A 945 && !strlen(modifications) 946 ) { 947 LP_ERRMSG (ERROR, E_ADM_PLONELY); 948 done (1); 949 } 950 951 /* 952 * For the case "-s local-system", we need to keep 953 * "s != 0" long enough to get here, where it keeps 954 * us from taking the old value. After this, we make 955 * "s == 0" to indicate this is a local printer. 956 */ 957 if (s && s != Local_System) 958 chksys(s); 959 if (!s && oldp->remote && *(oldp->remote)) 960 s = strdup(oldp->remote); 961 if (s == Local_System) 962 s = 0; 963 964 /* 965 * A remote printer converted to a local printer 966 * requires device or dial info. 967 */ 968 if (!s && oldp->remote && !v && !U) { 969 LP_ERRMSG (ERROR, E_ADM_NOUV); 970 done (1); 971 } 972 973 974 } else { 975 if (getclass(p)) { 976 LP_ERRMSG1 (ERROR, E_ADM_PRCL, p); 977 done (1); 978 } 979 980 if (!syn_name(p)) { 981 LP_ERRMSG1 (ERROR, E_LP_NOTNAME, p); 982 done (1); 983 } 984 985 if (s == Local_System) 986 s = 0; 987 if (s) 988 chksys(s); 989 990 #ifdef LP_USE_PAPI_ATTR 991 /* 992 * New printer - if no model and a PPD file is defined then 993 * use 'standard_foomatic' otherwise use 994 * the 'standard' model. 995 */ 996 if (!(e || i || m) && !s) { 997 if (n_opt != NULL) { 998 m = STANDARD_FOOMATIC; 999 } else { 1000 m = STANDARD; 1001 } 1002 } 1003 #else 1004 /* 1005 * New printer - if no model, use standard 1006 */ 1007 if (!(e || i || m) && !s) 1008 m = STANDARD; 1009 #endif 1010 1011 /* 1012 * A new printer requires device or dial info. 1013 */ 1014 if (!v && !U && !s) { 1015 LP_ERRMSG (ERROR, E_ADM_NOUV); 1016 done (1); 1017 } 1018 1019 /* 1020 * Can't quiet a new printer, 1021 * can't list the alerting for a new printer. 1022 */ 1023 if ( 1024 A 1025 && (STREQU(A, NAME_QUIET) || STREQU(A, NAME_LIST)) 1026 ) { 1027 LP_ERRMSG1 (ERROR, E_ADM_BADQUIETORLIST, p); 1028 done (1); 1029 } 1030 1031 /* 1032 * New printer - if no input types given, assume "simple". 1033 */ 1034 if (!I) { 1035 I = getlist(NAME_SIMPLE, LP_WS, LP_SEP); 1036 strcat (modifications, "I"); 1037 } 1038 } 1039 } 1040 1041 /* 1042 Second phase of parsing for -S option. 1043 In a seperate routine so we can call it from other 1044 routines. This is used when any or all are used as 1045 a print wheel name. main() loops over each print wheel, 1046 and must call this function for each print wheel found. 1047 */ 1048 void 1049 chkopts3(called_from_chkopts) 1050 int called_from_chkopts; 1051 { 1052 /* 1053 Only do the getpwheel() if we are not being called 1054 from lpadmin.c. Otherwise we mess up our arena for 1055 "all" processing. 1056 */ 1057 if (!called_from_chkopts) 1058 oldS = pwheel_pointer; 1059 else 1060 oldS = getpwheel(*S); 1061 1062 if (!oldS) { 1063 if (!syn_name(*S)) { 1064 LP_ERRMSG1 (ERROR, E_LP_NOTNAME, *S); 1065 done (1); 1066 } 1067 1068 /* 1069 * Can't quiet a new print wheel, 1070 * can't list the alerting for a new print wheel. 1071 */ 1072 if ( 1073 A 1074 && (STREQU(A, NAME_QUIET) || STREQU(A, NAME_LIST)) 1075 ) { 1076 LP_ERRMSG1 (ERROR, E_ADM_BADQUIETORLIST, *S); 1077 done (1); 1078 } 1079 } 1080 } 1081 1082 static void 1083 chksys(s) 1084 char *s; 1085 { 1086 char *cp; 1087 1088 if (STREQU(s, NAME_ALL) || STREQU(s, NAME_ANY)) { 1089 LP_ERRMSG (ERROR, E_ADM_ANYALLSYS); 1090 done(1); 1091 } 1092 1093 if ((cp = strchr(s, '!')) != NULL) 1094 *cp = '\0'; 1095 1096 if (cp) 1097 *cp = '!'; 1098 1099 return; 1100 } 1101 1102 /** 1103 ** sum_chkprinter() - CHECK TERMINFO STUFF FOR A LIST OF PRINTER TYPES 1104 **/ 1105 1106 #include "lp.set.h" 1107 1108 static unsigned long 1109 #if defined(__STDC__) 1110 sum_chkprinter ( 1111 char ** types, 1112 char * cpi, 1113 char * lpi, 1114 char * len, 1115 char * wid, 1116 char * cs 1117 ) 1118 #else 1119 sum_chkprinter (types, cpi, lpi, len, wid, cs) 1120 char ** types; 1121 char * cpi; 1122 char * lpi; 1123 char * len; 1124 char * wid; 1125 char * cs; 1126 #endif 1127 { 1128 char ** pt; 1129 1130 unsigned long worst = 0; 1131 unsigned long this = 0; 1132 1133 1134 /* 1135 * Check each printer type, to see if any won't work with 1136 * the attributes requested. However, return ``success'' 1137 * if at least one type works. Keep a list of the failed 1138 * types for the caller to report. 1139 */ 1140 bad_list = 0; 1141 for (pt = types; *pt; pt++) { 1142 this = chkprinter(*pt, cpi, lpi, len, wid, cs); 1143 if (this != 0) 1144 addlist (&bad_list, *pt); 1145 worst |= this; 1146 } 1147 if (lenlist(types) == lenlist(bad_list)) 1148 return (worst); 1149 else 1150 return (0); 1151 } 1152 1153 /* 1154 * Function: isPPD() 1155 * 1156 * Description: Check that the given PPD file exists. The argument given can 1157 * either be a relative path or a full path to the file. 1158 * 1159 * Returns: 1 = PPD file found 1160 * 0 = PPD file not found 1161 */ 1162 1163 static int 1164 isPPD(char *ppd_file) 1165 { 1166 int result = 0; 1167 char *ppd = NULL; 1168 1169 if (ppd_file != NULL) { 1170 if (*ppd_file == '/') { 1171 ppd = strdup(ppd_file); 1172 } else { 1173 ppd = makepath(Lp_Model, "ppd", ppd_file, (char *)0); 1174 } 1175 1176 /* 1177 * now check the file exists 1178 */ 1179 if ((ppd != NULL) && (Access(ppd, 04) != -1)) { 1180 result = 1; 1181 } else { 1182 /* 1183 * files does not exist so append .gz and check if 1184 * that exist 1185 */ 1186 ppd = Realloc(ppd, strlen(ppd)+ strlen(PPDZIP)+2); 1187 if (ppd != NULL) { 1188 ppd = strcat(ppd, PPDZIP); 1189 if (Access(ppd, 04) != -1) { 1190 result = 1; 1191 } 1192 } 1193 } 1194 1195 if (ppd != NULL) { 1196 free(ppd); 1197 } 1198 } 1199 return (result); 1200 } /* isPPD() */ 1201