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