Mercurial > illumos > onarm
annotate usr/src/cmd/lp/cmd/lpadmin/chkopts.c @ 4:1a15d5aaf794
synchronized with onnv_86 (6202) in onnv-gate
author | Koji Uno <koji.uno@sun.com> |
---|---|
date | Mon, 31 Aug 2009 14:38:03 +0900 |
parents | c9caec207d52 |
children |
rev | line source |
---|---|
0 | 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 | |
4
1a15d5aaf794
synchronized with onnv_86 (6202) in onnv-gate
Koji Uno <koji.uno@sun.com>
parents:
0
diff
changeset
|
31 #pragma ident "%Z%%M% %I% %E% SMI" |
0 | 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() */ |