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