8200 cmd/lp: misleading-indentation
[unleashed.git] / usr / src / cmd / lp / cmd / lpadmin / do_printer.c
blobc26c59e39a3da0b19e8634586020d371236f2503
1 /*
2 * CDDL HEADER START
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
19 * CDDL HEADER END
21 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
22 /* All Rights Reserved */
26 * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
27 * Use is subject to license terms.
28 * Copyright (c) 2016 by Delphix. All rights reserved.
31 #include <stdio.h>
32 #include <string.h>
33 #include <errno.h>
34 #include <limits.h>
35 #include <sys/types.h>
36 #include <sys/zone.h>
37 #include <stdlib.h>
38 #include <libintl.h>
39 #include <sys/tsol/label_macro.h>
40 #include <bsm/devices.h>
41 #include "lp.h"
42 #include "class.h"
43 #if defined PS_FAULTED
44 #undef PS_FAULTED
45 #endif
46 #include "printers.h"
47 #include "msgs.h"
49 #define WHO_AM_I I_AM_LPADMIN
50 #include "oam.h"
52 #include "lpadmin.h"
54 extern void fromallclasses();
56 #if !defined(PATH_MAX)
57 #define PATH_MAX 1024
58 #endif
59 #if PATH_MAX < 1024
60 #undef PATH_MAX
61 #define PATH_MAX 1024
62 #endif
64 extern char *label;
66 static void configure_printer();
67 static char *fullpath();
68 char *nameit();
69 static void pack_white(char *ptr);
72 * do_printer() - CREATE OR CHANGE PRINTER
75 void
76 do_printer(void)
78 int rc;
81 * Set or change the printer configuration.
83 if (strlen(modifications))
84 configure_printer(modifications);
87 * Allow/deny forms.
89 BEGIN_CRITICAL
90 if (!oldp)
91 if (allow_form_printer(
92 getlist(NAME_NONE, "", ","), p) == -1) {
93 LP_ERRMSG1(ERROR, E_ADM_ACCESSINFO, PERROR);
94 done(1);
97 if (f_allow || f_deny) {
98 if (f_allow && allow_form_printer(f_allow, p) == -1) {
99 LP_ERRMSG1(ERROR, E_ADM_ACCESSINFO, PERROR);
100 done(1);
103 if (f_deny && deny_form_printer(f_deny, p) == -1) {
104 LP_ERRMSG1(ERROR, E_ADM_ACCESSINFO, PERROR);
105 done(1);
108 END_CRITICAL
110 /* Add/remove types of paper */
112 BEGIN_CRITICAL
113 if (!oldp)
114 if (add_paper_to_printer(
115 getlist(NAME_NONE, "", ","), p) == -1) {
116 LP_ERRMSG1(ERROR, E_ADM_ACCESSINFO, PERROR);
117 done(1);
121 if (p_add && add_paper_to_printer(p_add, p) == -1) {
122 LP_ERRMSG1(ERROR, E_ADM_ACCESSINFO, PERROR);
123 done(1);
126 if (p_remove && remove_paper_from_printer(p_remove, p) == -1) {
127 LP_ERRMSG1(ERROR, E_ADM_ACCESSINFO, PERROR);
128 done(1);
130 END_CRITICAL
133 * Allow/deny users.
135 BEGIN_CRITICAL
136 if (!oldp)
137 if (allow_user_printer(
138 getlist(NAME_ALL, "", ","), p) == -1) {
139 LP_ERRMSG1(ERROR, E_ADM_ACCESSINFO, PERROR);
140 done(1);
143 if (u_allow || u_deny) {
144 if (u_allow && allow_user_printer(u_allow, p) == -1) {
145 LP_ERRMSG1(ERROR, E_ADM_ACCESSINFO, PERROR);
146 done(1);
149 if (u_deny && deny_user_printer(u_deny, p) == -1) {
150 LP_ERRMSG1(ERROR, E_ADM_ACCESSINFO, PERROR);
151 done(1);
154 END_CRITICAL
157 * Tell the Spooler about the printer
159 send_message(S_LOAD_PRINTER, p, "", "");
160 rc = output(R_LOAD_PRINTER);
162 switch (rc) {
163 case MOK:
164 break;
166 case MNODEST:
167 case MERRDEST:
168 LP_ERRMSG(ERROR, E_ADM_ERRDEST);
169 done(1);
170 /*NOTREACHED*/
172 case MNOSPACE:
173 LP_ERRMSG(WARNING, E_ADM_NOPSPACE);
174 break;
176 case MNOPERM: /* taken care of up front */
177 default:
178 LP_ERRMSG1(ERROR, E_LP_BADSTATUS, rc);
179 done(1);
180 /*NOTREACHED*/
184 * Now that the Spooler knows about the printer,
185 * we can do the balance of the changes.
189 * Mount or unmount form, print-wheel.
191 if (M)
192 do_mount(p, (f? f : NULL), (S? *S : NULL));
193 else if (t)
194 do_max_trays(p);
197 * Display the alert type.
199 if (A && STREQU(A, NAME_LIST)) {
200 if (label)
201 (void) printf(gettext("Printer %s: "), label);
202 printalert(stdout, &(oldp->fault_alert), 1);
206 * -A quiet.
208 if (A && STREQU(A, NAME_QUIET)) {
210 send_message(S_QUIET_ALERT, p, (char *)QA_PRINTER, "");
211 rc = output(R_QUIET_ALERT);
213 switch (rc) {
214 case MOK:
215 break;
217 case MNODEST: /* not quite, but not a lie either */
218 case MERRDEST:
219 LP_ERRMSG1(WARNING, E_LP_NOQUIET, p);
220 break;
222 case MNOPERM: /* taken care of up front */
223 default:
224 LP_ERRMSG1(ERROR, E_LP_BADSTATUS, rc);
225 done(1);
226 /*NOTREACHED*/
231 * Add printer p to class c
233 if (c) {
234 CLASS *pc;
235 CLASS clsbuf;
237 if (STREQU(c, NAME_ANY))
238 c = NAME_ALL;
240 Loop: if (!(pc = getclass(c))) {
241 if (STREQU(c, NAME_ALL))
242 goto Done;
244 if (errno != ENOENT) {
245 LP_ERRMSG2(ERROR, E_LP_GETCLASS, c, PERROR);
246 done(1);
250 * Create the class
252 clsbuf.name = strdup(c);
253 clsbuf.members = 0;
254 if (addlist(&clsbuf.members, p) == -1) {
255 LP_ERRMSG(ERROR, E_LP_MALLOC);
256 done(1);
258 pc = &clsbuf;
260 } else if (searchlist(p, pc->members))
261 LP_ERRMSG2(WARNING, E_ADM_INCLASS, p, pc->name);
263 else if (addlist(&pc->members, p) == -1) {
264 LP_ERRMSG(ERROR, E_LP_MALLOC);
265 done(1);
268 BEGIN_CRITICAL
269 if (putclass(pc->name, pc) == -1) {
270 LP_ERRMSG2(ERROR, E_LP_PUTCLASS, pc->name,
271 PERROR);
272 done(1);
274 END_CRITICAL
276 send_message(S_LOAD_CLASS, pc->name);
277 rc = output(R_LOAD_CLASS);
279 switch (rc) {
280 case MOK:
281 break;
283 case MNODEST:
284 case MERRDEST:
285 LP_ERRMSG(ERROR, E_ADM_ERRDEST);
286 done(1);
287 /*NOTREACHED*/
289 case MNOSPACE:
290 LP_ERRMSG(WARNING, E_ADM_NOCSPACE);
291 break;
293 case MNOPERM: /* taken care of up front */
294 default:
295 LP_ERRMSG1(ERROR, E_LP_BADSTATUS, rc);
296 done(1);
297 /*NOTREACHED*/
300 if (STREQU(c, NAME_ALL))
301 goto Loop;
303 Done:
305 * Remove printer p from class r
307 if (r) {
308 if (STREQU(r, NAME_ALL) || STREQU(r, NAME_ANY))
309 fromallclasses(p);
310 else
311 fromclass(p, r);
316 * configure_printer() - SET OR CHANGE CONFIGURATION OF PRINTER
319 static void
320 configure_printer(char *list)
322 PRINTER *prbufp;
323 PRINTER printer_struct;
324 char type;
325 char *infile_opts = NULL;
327 if (oldp) {
329 prbufp = oldp;
331 if (!T)
332 T = prbufp->printer_types;
334 if (!i && !e && !m)
336 * Don't copy the original interface program
337 * again, but do keep the name of the original.
339 ignprinter = BAD_INTERFACE;
340 else
341 ignprinter = 0;
344 * If we are making this a remote printer,
345 * make sure that local-only attributes are
346 * cleared.
348 if (s) {
349 prbufp->banner = 0;
350 prbufp->cpi.val = 0;
351 prbufp->cpi.sc = 0;
352 prbufp->device = 0;
353 prbufp->dial_info = 0;
354 prbufp->fault_rec = 0;
355 prbufp->interface = 0;
356 prbufp->lpi.val = 0;
357 prbufp->lpi.sc = 0;
358 prbufp->plen.val = 0;
359 prbufp->plen.sc = 0;
360 prbufp->login = 0;
361 prbufp->speed = 0;
362 prbufp->stty = 0;
363 prbufp->pwid.val = 0;
364 prbufp->pwid.sc = 0;
365 prbufp->fault_alert.shcmd = strdup(NAME_NONE);
366 prbufp->fault_alert.Q = 0;
367 prbufp->fault_alert.W = 0;
368 #if defined(CAN_DO_MODULES)
369 prbufp->modules = 0;
370 #endif
373 * If we are making this a local printer, make
374 * sure that some local-only attributes are set.
375 * (If the user has specified these as well, their
376 * values will overwrite what we set here.)
378 } else if (oldp->remote) {
379 prbufp->banner = BAN_ALWAYS;
380 prbufp->interface = makepath(Lp_Model, STANDARD, NULL);
381 prbufp->fault_alert.shcmd = nameit(NAME_MAIL);
384 * Being here means "!s && oldp->remote" is true,
385 * i.e. this printer never had an interface pgm
386 * before. Thus we can safely clear the following.
387 * This is needed to let "putprinter()" copy the
388 * (default) interface program.
390 ignprinter = 0;
393 } else {
395 * The following takes care of the lion's share
396 * of the initialization of a new printer structure.
397 * However, special initialization (e.g. non-zero,
398 * or substructure members) needs to be considered
399 * for EACH NEW MEMBER added to the structure.
401 (void) memset(&printer_struct, 0, sizeof (printer_struct));
403 prbufp = &printer_struct;
404 prbufp->banner = BAN_ALWAYS;
405 prbufp->cpi.val = 0;
406 prbufp->cpi.sc = 0;
407 if (!s)
408 prbufp->interface = makepath(Lp_Model, m, NULL);
409 prbufp->lpi.val = 0;
410 prbufp->lpi.sc = 0;
411 prbufp->plen.val = 0;
412 prbufp->plen.sc = 0;
413 prbufp->pwid.val = 0;
414 prbufp->pwid.sc = 0;
415 if (!s && !A)
416 prbufp->fault_alert.shcmd = nameit(NAME_MAIL);
417 prbufp->fault_alert.Q = 0;
418 prbufp->fault_alert.W = 0;
419 prbufp->options = NULL;
422 while ((type = *list++) != '\0') {
423 switch (type) {
424 case 'A':
425 if (!s) {
426 if (STREQU(A, NAME_MAIL) ||
427 STREQU(A, NAME_WRITE))
428 prbufp->fault_alert.shcmd = nameit(A);
429 else if (!STREQU(A, NAME_QUIET))
430 prbufp->fault_alert.shcmd = A;
432 break;
434 case 'b':
435 if (!s)
436 prbufp->banner = banner;
437 break;
439 case 'c':
440 if (!s)
441 prbufp->cpi = cpi_sdn;
442 break;
444 case 'D':
445 prbufp->description = D;
446 break;
448 case 'e':
449 if (!s) {
450 prbufp->interface = makepath(Lp_A_Interfaces,
451 e, NULL);
453 break;
455 case 'F':
456 if (!s)
457 prbufp->fault_rec = F;
458 break;
460 #if defined(CAN_DO_MODULES)
461 case 'H':
462 if (!s)
463 prbufp->modules = H;
464 break;
465 #endif
467 case 'h':
468 if (!s)
469 prbufp->login = 0;
470 break;
472 case 'i':
473 if (!s)
474 prbufp->interface = fullpath(i);
475 break;
477 case 'I':
478 prbufp->input_types = I;
479 break;
481 case 'l':
482 if (!s)
483 prbufp->login = 1;
484 break;
486 case 'L':
487 if (!s)
488 prbufp->plen = length_sdn;
489 break;
491 case 'm':
492 if (!s)
493 prbufp->interface = makepath(Lp_Model, m, NULL);
494 break;
496 case 'M':
497 if (!s)
498 prbufp->lpi = lpi_sdn;
499 break;
501 #ifdef LP_USE_PAPI_ATTR
502 case 'n':
503 if (n_opt != NULL) {
504 if (*n_opt == '/') {
505 prbufp->ppd = fullpath(n_opt);
506 } else {
507 prbufp->ppd = makepath(Lp_Model, "ppd",
508 n_opt, NULL);
510 ppdopt = 1;
512 break;
513 #endif
515 case 'o':
517 * The "undefined" key-value -o options
519 * Options requires special handling. It is a
520 * list whose members are to be handled
521 * individually.
523 * Need to: set new options, keep old options if not
524 * redefined, remove old options if defined as "key=".
527 * "p" is a global containing the printer name
530 if (!s) {
531 if ((infile_opts =
532 getpentry(p, PR_OPTIONS)) == NULL) {
533 prbufp->options = o_options;
534 } else {
535 prbufp->options = pick_opts(infile_opts,
536 o_options);
539 break;
541 case 'R':
542 if (s) {
543 prbufp->remote = s;
544 prbufp->dial_info = 0;
545 prbufp->device = 0;
546 } else {
547 prbufp->remote = 0;
549 break;
551 case 's':
552 if (!s) {
554 * lpadmin always defers to stty
556 prbufp->speed = 0;
557 prbufp->stty = stty_opt;
559 break;
561 case 'S':
562 if (!M)
563 if (STREQU(*S, NAME_NONE))
564 prbufp->char_sets = 0;
565 else
566 prbufp->char_sets = S;
567 break;
569 case 'T':
570 prbufp->printer_types = T;
571 break;
573 case 'U':
574 if (!s) {
575 prbufp->dial_info = U;
576 prbufp->device = 0;
577 prbufp->remote = 0;
579 break;
581 case 'v':
582 if (!s) {
583 prbufp->device = v;
584 prbufp->dial_info = 0;
585 prbufp->remote = 0;
587 break;
589 case 'w':
590 if (!s)
591 prbufp->pwid = width_sdn;
592 break;
594 case 'W':
595 if (!s)
596 prbufp->fault_alert.W = W;
597 break;
603 BEGIN_CRITICAL
604 if (putprinter(p, prbufp) == -1) {
605 if (errno == EINVAL && (badprinter & BAD_INTERFACE))
606 LP_ERRMSG1(ERROR, E_ADM_BADINTF,
607 prbufp->interface);
608 else
609 LP_ERRMSG2(ERROR, E_LP_PUTPRINTER, p, PERROR);
610 done(1);
613 if ((getzoneid() == GLOBAL_ZONEID) && system_labeled &&
614 (prbufp->device != NULL))
615 update_dev_dbs(p, prbufp->device, "ADD");
617 END_CRITICAL
621 * fullpath()
624 static char *
625 fullpath(char *str)
627 char *cur_dir;
628 char *path;
630 while (*str && *str == ' ')
631 str++;
632 if (*str == '/')
633 return (str);
635 if (!(cur_dir = malloc(PATH_MAX + 1)))
636 return (str);
638 getcwd(cur_dir, PATH_MAX);
639 path = makepath(cur_dir, str, (char *)0);
642 * Here we could be nice and strip out /./ and /../
643 * stuff, but it isn't necessary.
646 return (path);
650 * nameit() - ADD USER NAME TO COMMAND
653 char *
654 nameit(char *cmd)
656 char *nm;
657 char *copy;
659 nm = getname();
660 copy = malloc(strlen(cmd) + 1 + strlen(nm) + 1);
662 (void) strcpy(copy, cmd);
663 (void) strcat(copy, " ");
664 (void) strcat(copy, nm);
665 return (copy);
669 * update_dev_dbs - ADD/REMOVE ENTRIES FOR THE PRINTER IN DEVICE
670 * ALLOCATION FILES
672 * We intentionally ignore errors, since we don't want the printer
673 * installation to be viewed as failing just because we didn't add
674 * the device_allocate entry.
676 * Input:
677 * prtname - printer name
678 * devname - device associated w/ this printer
679 * func - [ADD|REMOVE] entries in /etc/security/device_allocate
680 * and /etc/security/device_maps
682 * Return:
683 * Always 'quiet' return. Failures are ignored.
685 void
686 update_dev_dbs(char *prtname, char *devname, char *func)
688 int fd, status;
689 pid_t pid;
691 pid = fork();
692 switch (pid) {
693 case -1:
694 /* fork failed, just return quietly */
695 return;
696 case 0:
697 /* child */
698 /* redirect to /dev/null */
699 (void) close(1);
700 (void) close(2);
701 fd = open("/dev/null", O_WRONLY);
702 fd = dup(fd);
704 if (strcmp(func, "ADD") == 0) {
705 execl("/usr/sbin/add_allocatable", "add_allocatable",
706 "-n", prtname, "-t", "lp", "-l", devname,
707 "-o", "minlabel=admin_low:maxlabel=admin_high",
708 "-a", "*", "-c", "/bin/true", NULL);
709 } else {
710 if (strcmp(func, "REMOVE") == 0) {
711 execl("/usr/sbin/remove_allocatable",
712 "remove_allocatable", "-n", prtname, NULL);
715 _exit(1);
716 /* NOT REACHED */
717 default:
718 waitpid(pid, &status, 0);
719 return;
724 * pack_white(ptr) trims off multiple occurances of white space from a NULL
725 * terminated string pointed to by "ptr".
727 static void
728 pack_white(char *ptr)
730 char *tptr;
731 char *mptr;
732 int cnt;
734 if (ptr == NULL)
735 return;
736 cnt = strlen(ptr);
737 if (cnt == 0)
738 return;
739 mptr = (char *)calloc((unsigned)cnt+1, sizeof (char));
740 if (mptr == NULL)
741 return;
742 tptr = strtok(ptr, " \t");
743 while (tptr != NULL) {
744 (void) strcat(mptr, tptr);
745 (void) strcat(mptr, " ");
746 tptr = strtok(NULL, " \t");
748 cnt = strlen(mptr);
749 (void) strcpy(ptr, mptr);
750 free(mptr);