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]
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.
35 #include <sys/types.h>
39 #include <sys/tsol/label_macro.h>
40 #include <bsm/devices.h>
43 #if defined PS_FAULTED
49 #define WHO_AM_I I_AM_LPADMIN
54 extern void fromallclasses();
56 #if !defined(PATH_MAX)
66 static void configure_printer();
67 static char *fullpath();
69 static void pack_white(char *ptr
);
72 * do_printer() - CREATE OR CHANGE PRINTER
81 * Set or change the printer configuration.
83 if (strlen(modifications
))
84 configure_printer(modifications
);
91 if (allow_form_printer(
92 getlist(NAME_NONE
, "", ","), p
) == -1) {
93 LP_ERRMSG1(ERROR
, E_ADM_ACCESSINFO
, PERROR
);
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
);
103 if (f_deny
&& deny_form_printer(f_deny
, p
) == -1) {
104 LP_ERRMSG1(ERROR
, E_ADM_ACCESSINFO
, PERROR
);
110 /* Add/remove types of paper */
114 if (add_paper_to_printer(
115 getlist(NAME_NONE
, "", ","), p
) == -1) {
116 LP_ERRMSG1(ERROR
, E_ADM_ACCESSINFO
, PERROR
);
121 if (p_add
&& add_paper_to_printer(p_add
, p
) == -1) {
122 LP_ERRMSG1(ERROR
, E_ADM_ACCESSINFO
, PERROR
);
126 if (p_remove
&& remove_paper_from_printer(p_remove
, p
) == -1) {
127 LP_ERRMSG1(ERROR
, E_ADM_ACCESSINFO
, PERROR
);
137 if (allow_user_printer(
138 getlist(NAME_ALL
, "", ","), p
) == -1) {
139 LP_ERRMSG1(ERROR
, E_ADM_ACCESSINFO
, PERROR
);
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
);
149 if (u_deny
&& deny_user_printer(u_deny
, p
) == -1) {
150 LP_ERRMSG1(ERROR
, E_ADM_ACCESSINFO
, PERROR
);
157 * Tell the Spooler about the printer
159 send_message(S_LOAD_PRINTER
, p
, "", "");
160 rc
= output(R_LOAD_PRINTER
);
168 LP_ERRMSG(ERROR
, E_ADM_ERRDEST
);
173 LP_ERRMSG(WARNING
, E_ADM_NOPSPACE
);
176 case MNOPERM
: /* taken care of up front */
178 LP_ERRMSG1(ERROR
, E_LP_BADSTATUS
, rc
);
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.
192 do_mount(p
, (f
? f
: NULL
), (S
? *S
: NULL
));
197 * Display the alert type.
199 if (A
&& STREQU(A
, NAME_LIST
)) {
201 (void) printf(gettext("Printer %s: "), label
);
202 printalert(stdout
, &(oldp
->fault_alert
), 1);
208 if (A
&& STREQU(A
, NAME_QUIET
)) {
210 send_message(S_QUIET_ALERT
, p
, (char *)QA_PRINTER
, "");
211 rc
= output(R_QUIET_ALERT
);
217 case MNODEST
: /* not quite, but not a lie either */
219 LP_ERRMSG1(WARNING
, E_LP_NOQUIET
, p
);
222 case MNOPERM
: /* taken care of up front */
224 LP_ERRMSG1(ERROR
, E_LP_BADSTATUS
, rc
);
231 * Add printer p to class c
237 if (STREQU(c
, NAME_ANY
))
240 Loop
: if (!(pc
= getclass(c
))) {
241 if (STREQU(c
, NAME_ALL
))
244 if (errno
!= ENOENT
) {
245 LP_ERRMSG2(ERROR
, E_LP_GETCLASS
, c
, PERROR
);
252 clsbuf
.name
= strdup(c
);
254 if (addlist(&clsbuf
.members
, p
) == -1) {
255 LP_ERRMSG(ERROR
, E_LP_MALLOC
);
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
);
269 if (putclass(pc
->name
, pc
) == -1) {
270 LP_ERRMSG2(ERROR
, E_LP_PUTCLASS
, pc
->name
,
276 send_message(S_LOAD_CLASS
, pc
->name
);
277 rc
= output(R_LOAD_CLASS
);
285 LP_ERRMSG(ERROR
, E_ADM_ERRDEST
);
290 LP_ERRMSG(WARNING
, E_ADM_NOCSPACE
);
293 case MNOPERM
: /* taken care of up front */
295 LP_ERRMSG1(ERROR
, E_LP_BADSTATUS
, rc
);
300 if (STREQU(c
, NAME_ALL
))
305 * Remove printer p from class r
308 if (STREQU(r
, NAME_ALL
) || STREQU(r
, NAME_ANY
))
316 * configure_printer() - SET OR CHANGE CONFIGURATION OF PRINTER
320 configure_printer(char *list
)
323 PRINTER printer_struct
;
325 char *infile_opts
= NULL
;
332 T
= prbufp
->printer_types
;
336 * Don't copy the original interface program
337 * again, but do keep the name of the original.
339 ignprinter
= BAD_INTERFACE
;
344 * If we are making this a remote printer,
345 * make sure that local-only attributes are
353 prbufp
->dial_info
= 0;
354 prbufp
->fault_rec
= 0;
355 prbufp
->interface
= 0;
358 prbufp
->plen
.val
= 0;
363 prbufp
->pwid
.val
= 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)
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.
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
;
408 prbufp
->interface
= makepath(Lp_Model
, m
, NULL
);
411 prbufp
->plen
.val
= 0;
413 prbufp
->pwid
.val
= 0;
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') {
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
;
436 prbufp
->banner
= banner
;
441 prbufp
->cpi
= cpi_sdn
;
445 prbufp
->description
= D
;
450 prbufp
->interface
= makepath(Lp_A_Interfaces
,
457 prbufp
->fault_rec
= F
;
460 #if defined(CAN_DO_MODULES)
474 prbufp
->interface
= fullpath(i
);
478 prbufp
->input_types
= I
;
488 prbufp
->plen
= length_sdn
;
493 prbufp
->interface
= makepath(Lp_Model
, m
, NULL
);
498 prbufp
->lpi
= lpi_sdn
;
501 #ifdef LP_USE_PAPI_ATTR
505 prbufp
->ppd
= fullpath(n_opt
);
507 prbufp
->ppd
= makepath(Lp_Model
, "ppd",
517 * The "undefined" key-value -o options
519 * Options requires special handling. It is a
520 * list whose members are to be handled
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
532 getpentry(p
, PR_OPTIONS
)) == NULL
) {
533 prbufp
->options
= o_options
;
535 prbufp
->options
= pick_opts(infile_opts
,
544 prbufp
->dial_info
= 0;
554 * lpadmin always defers to stty
557 prbufp
->stty
= stty_opt
;
563 if (STREQU(*S
, NAME_NONE
))
564 prbufp
->char_sets
= 0;
566 prbufp
->char_sets
= S
;
570 prbufp
->printer_types
= T
;
575 prbufp
->dial_info
= U
;
584 prbufp
->dial_info
= 0;
591 prbufp
->pwid
= width_sdn
;
596 prbufp
->fault_alert
.W
= W
;
604 if (putprinter(p
, prbufp
) == -1) {
605 if (errno
== EINVAL
&& (badprinter
& BAD_INTERFACE
))
606 LP_ERRMSG1(ERROR
, E_ADM_BADINTF
,
609 LP_ERRMSG2(ERROR
, E_LP_PUTPRINTER
, p
, PERROR
);
613 if ((getzoneid() == GLOBAL_ZONEID
) && system_labeled
&&
614 (prbufp
->device
!= NULL
))
615 update_dev_dbs(p
, prbufp
->device
, "ADD");
630 while (*str
&& *str
== ' ')
635 if (!(cur_dir
= malloc(PATH_MAX
+ 1)))
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.
650 * nameit() - ADD USER NAME TO COMMAND
660 copy
= malloc(strlen(cmd
) + 1 + strlen(nm
) + 1);
662 (void) strcpy(copy
, cmd
);
663 (void) strcat(copy
, " ");
664 (void) strcat(copy
, nm
);
669 * update_dev_dbs - ADD/REMOVE ENTRIES FOR THE PRINTER IN DEVICE
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.
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
683 * Always 'quiet' return. Failures are ignored.
686 update_dev_dbs(char *prtname
, char *devname
, char *func
)
694 /* fork failed, just return quietly */
698 /* redirect to /dev/null */
701 fd
= open("/dev/null", O_WRONLY
);
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
);
710 if (strcmp(func
, "REMOVE") == 0) {
711 execl("/usr/sbin/remove_allocatable",
712 "remove_allocatable", "-n", prtname
, NULL
);
718 waitpid(pid
, &status
, 0);
724 * pack_white(ptr) trims off multiple occurances of white space from a NULL
725 * terminated string pointed to by "ptr".
728 pack_white(char *ptr
)
739 mptr
= (char *)calloc((unsigned)cnt
+1, sizeof (char));
742 tptr
= strtok(ptr
, " \t");
743 while (tptr
!= NULL
) {
744 (void) strcat(mptr
, tptr
);
745 (void) strcat(mptr
, " ");
746 tptr
= strtok(NULL
, " \t");
749 (void) strcpy(ptr
, mptr
);