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
chkopts()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
root_can_write(path)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
unpack_sdn(sdn)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
verify_form(form)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
chkopts2(called_from_chkopts)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
chkopts3(called_from_chkopts)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
chksys(s)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__)
sum_chkprinter(char ** types,char * cpi,char * lpi,char * len,char * wid,char * cs)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
isPPD(char * ppd_file)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