#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <limits.h>
#include <sys/types.h>
#include <sys/zone.h>
#include <stdlib.h>
#include <libintl.h>
#include <sys/tsol/label_macro.h>
#include <bsm/devices.h>
#include "lp.h"
#include "class.h"
#include "printers.h"
#include "msgs.h"
#define WHO_AM_I I_AM_LPADMIN
#include "oam.h"
#include "lpadmin.h"
extern void fromallclasses();
#if !defined(PATH_MAX)
#define PATH_MAX 1024
#endif
#if PATH_MAX < 1024
#undef PATH_MAX
#define PATH_MAX 1024
#endif
extern char *label;
static void configure_printer();
static char *fullpath();
char *nameit();
static void pack_white(char *ptr);
void
do_printer(void)
{
int rc;
if (strlen(modifications))
configure_printer(modifications);
BEGIN_CRITICAL
if (!oldp)
if (allow_form_printer(
getlist(NAME_NONE, "", ","), p) == -1) {
LP_ERRMSG1(ERROR, E_ADM_ACCESSINFO, PERROR);
done(1);
}
if (f_allow || f_deny) {
if (f_allow && allow_form_printer(f_allow, p) == -1) {
LP_ERRMSG1(ERROR, E_ADM_ACCESSINFO, PERROR);
done(1);
}
if (f_deny && deny_form_printer(f_deny, p) == -1) {
LP_ERRMSG1(ERROR, E_ADM_ACCESSINFO, PERROR);
done(1);
}
}
END_CRITICAL
BEGIN_CRITICAL
if (!oldp)
if (add_paper_to_printer(
getlist(NAME_NONE, "", ","), p) == -1) {
LP_ERRMSG1(ERROR, E_ADM_ACCESSINFO, PERROR);
done(1);
}
if (p_add && add_paper_to_printer(p_add, p) == -1) {
LP_ERRMSG1(ERROR, E_ADM_ACCESSINFO, PERROR);
done(1);
}
if (p_remove && remove_paper_from_printer(p_remove, p) == -1) {
LP_ERRMSG1(ERROR, E_ADM_ACCESSINFO, PERROR);
done(1);
}
END_CRITICAL
BEGIN_CRITICAL
if (!oldp)
if (allow_user_printer(
getlist(NAME_ALL, "", ","), p) == -1) {
LP_ERRMSG1(ERROR, E_ADM_ACCESSINFO, PERROR);
done(1);
}
if (u_allow || u_deny) {
if (u_allow && allow_user_printer(u_allow, p) == -1) {
LP_ERRMSG1(ERROR, E_ADM_ACCESSINFO, PERROR);
done(1);
}
if (u_deny && deny_user_printer(u_deny, p) == -1) {
LP_ERRMSG1(ERROR, E_ADM_ACCESSINFO, PERROR);
done(1);
}
}
END_CRITICAL
send_message(S_LOAD_PRINTER, p, "", "");
rc = output(R_LOAD_PRINTER);
switch (rc) {
case MOK:
break;
case MNODEST:
case MERRDEST:
LP_ERRMSG(ERROR, E_ADM_ERRDEST);
done(1);
case MNOSPACE:
LP_ERRMSG(WARNING, E_ADM_NOPSPACE);
break;
case MNOPERM:
default:
LP_ERRMSG1(ERROR, E_LP_BADSTATUS, rc);
done(1);
}
if (M)
do_mount(p, (f? f : NULL), (S? *S : NULL));
else if (t)
do_max_trays(p);
if (A && STREQU(A, NAME_LIST)) {
if (label)
(void) printf(gettext("Printer %s: "), label);
printalert(stdout, &(oldp->fault_alert), 1);
}
if (A && STREQU(A, NAME_QUIET)) {
send_message(S_QUIET_ALERT, p, (char *)QA_PRINTER, "");
rc = output(R_QUIET_ALERT);
switch (rc) {
case MOK:
break;
case MNODEST:
case MERRDEST:
LP_ERRMSG1(WARNING, E_LP_NOQUIET, p);
break;
case MNOPERM:
default:
LP_ERRMSG1(ERROR, E_LP_BADSTATUS, rc);
done(1);
}
}
if (c) {
CLASS *pc;
CLASS clsbuf;
if (STREQU(c, NAME_ANY))
c = NAME_ALL;
Loop: if (!(pc = getclass(c))) {
if (STREQU(c, NAME_ALL))
goto Done;
if (errno != ENOENT) {
LP_ERRMSG2(ERROR, E_LP_GETCLASS, c, PERROR);
done(1);
}
clsbuf.name = strdup(c);
clsbuf.members = 0;
if (addlist(&clsbuf.members, p) == -1) {
LP_ERRMSG(ERROR, E_LP_MALLOC);
done(1);
}
pc = &clsbuf;
} else if (searchlist(p, pc->members))
LP_ERRMSG2(WARNING, E_ADM_INCLASS, p, pc->name);
else if (addlist(&pc->members, p) == -1) {
LP_ERRMSG(ERROR, E_LP_MALLOC);
done(1);
}
BEGIN_CRITICAL
if (putclass(pc->name, pc) == -1) {
LP_ERRMSG2(ERROR, E_LP_PUTCLASS, pc->name,
PERROR);
done(1);
}
END_CRITICAL
send_message(S_LOAD_CLASS, pc->name);
rc = output(R_LOAD_CLASS);
switch (rc) {
case MOK:
break;
case MNODEST:
case MERRDEST:
LP_ERRMSG(ERROR, E_ADM_ERRDEST);
done(1);
case MNOSPACE:
LP_ERRMSG(WARNING, E_ADM_NOCSPACE);
break;
case MNOPERM:
default:
LP_ERRMSG1(ERROR, E_LP_BADSTATUS, rc);
done(1);
}
if (STREQU(c, NAME_ALL))
goto Loop;
}
Done:
if (r) {
if (STREQU(r, NAME_ALL) || STREQU(r, NAME_ANY))
fromallclasses(p);
else
fromclass(p, r);
}
}
static void
configure_printer(char *list)
{
PRINTER *prbufp;
PRINTER printer_struct;
char type;
char *infile_opts = NULL;
if (oldp) {
prbufp = oldp;
if (!T)
T = prbufp->printer_types;
if (!i && !e && !m)
ignprinter = BAD_INTERFACE;
else
ignprinter = 0;
if (s) {
prbufp->banner = 0;
prbufp->cpi.val = 0;
prbufp->cpi.sc = 0;
prbufp->device = 0;
prbufp->dial_info = 0;
prbufp->fault_rec = 0;
prbufp->interface = 0;
prbufp->lpi.val = 0;
prbufp->lpi.sc = 0;
prbufp->plen.val = 0;
prbufp->plen.sc = 0;
prbufp->login = 0;
prbufp->speed = 0;
prbufp->stty = 0;
prbufp->pwid.val = 0;
prbufp->pwid.sc = 0;
prbufp->fault_alert.shcmd = strdup(NAME_NONE);
prbufp->fault_alert.Q = 0;
prbufp->fault_alert.W = 0;
#if defined(CAN_DO_MODULES)
prbufp->modules = 0;
#endif
} else if (oldp->remote) {
prbufp->banner = BAN_ALWAYS;
prbufp->interface = makepath(Lp_Model, STANDARD, NULL);
prbufp->fault_alert.shcmd = nameit(NAME_MAIL);
ignprinter = 0;
}
} else {
(void) memset(&printer_struct, 0, sizeof (printer_struct));
prbufp = &printer_struct;
prbufp->banner = BAN_ALWAYS;
prbufp->cpi.val = 0;
prbufp->cpi.sc = 0;
if (!s)
prbufp->interface = makepath(Lp_Model, m, NULL);
prbufp->lpi.val = 0;
prbufp->lpi.sc = 0;
prbufp->plen.val = 0;
prbufp->plen.sc = 0;
prbufp->pwid.val = 0;
prbufp->pwid.sc = 0;
if (!s && !A)
prbufp->fault_alert.shcmd = nameit(NAME_MAIL);
prbufp->fault_alert.Q = 0;
prbufp->fault_alert.W = 0;
prbufp->options = NULL;
}
while ((type = *list++) != '\0') {
switch (type) {
case 'A':
if (!s) {
if (STREQU(A, NAME_MAIL) ||
STREQU(A, NAME_WRITE))
prbufp->fault_alert.shcmd = nameit(A);
else if (!STREQU(A, NAME_QUIET))
prbufp->fault_alert.shcmd = A;
}
break;
case 'b':
if (!s)
prbufp->banner = banner;
break;
case 'c':
if (!s)
prbufp->cpi = cpi_sdn;
break;
case 'D':
prbufp->description = D;
break;
case 'e':
if (!s) {
prbufp->interface = makepath(Lp_A_Interfaces,
e, NULL);
}
break;
case 'F':
if (!s)
prbufp->fault_rec = F;
break;
#if defined(CAN_DO_MODULES)
case 'H':
if (!s)
prbufp->modules = H;
break;
#endif
case 'h':
if (!s)
prbufp->login = 0;
break;
case 'i':
if (!s)
prbufp->interface = fullpath(i);
break;
case 'I':
prbufp->input_types = I;
break;
case 'l':
if (!s)
prbufp->login = 1;
break;
case 'L':
if (!s)
prbufp->plen = length_sdn;
break;
case 'm':
if (!s)
prbufp->interface = makepath(Lp_Model, m, NULL);
break;
case 'M':
if (!s)
prbufp->lpi = lpi_sdn;
break;
#ifdef LP_USE_PAPI_ATTR
case 'n':
if (n_opt != NULL) {
if (*n_opt == '/') {
prbufp->ppd = fullpath(n_opt);
} else {
prbufp->ppd = makepath(Lp_Model, "ppd",
n_opt, NULL);
}
ppdopt = 1;
}
break;
#endif
case 'o':
if (!s) {
if ((infile_opts =
getpentry(p, PR_OPTIONS)) == NULL) {
prbufp->options = o_options;
} else {
prbufp->options = pick_opts(infile_opts,
o_options);
}
}
break;
case 'R':
if (s) {
prbufp->remote = s;
prbufp->dial_info = 0;
prbufp->device = 0;
} else {
prbufp->remote = 0;
}
break;
case 's':
if (!s) {
prbufp->speed = 0;
prbufp->stty = stty_opt;
}
break;
case 'S':
if (!M)
if (STREQU(*S, NAME_NONE))
prbufp->char_sets = 0;
else
prbufp->char_sets = S;
break;
case 'T':
prbufp->printer_types = T;
break;
case 'U':
if (!s) {
prbufp->dial_info = U;
prbufp->device = 0;
prbufp->remote = 0;
}
break;
case 'v':
if (!s) {
prbufp->device = v;
prbufp->dial_info = 0;
prbufp->remote = 0;
}
break;
case 'w':
if (!s)
prbufp->pwid = width_sdn;
break;
case 'W':
if (!s)
prbufp->fault_alert.W = W;
break;
}
}
BEGIN_CRITICAL
if (putprinter(p, prbufp) == -1) {
if (errno == EINVAL && (badprinter & BAD_INTERFACE))
LP_ERRMSG1(ERROR, E_ADM_BADINTF,
prbufp->interface);
else
LP_ERRMSG2(ERROR, E_LP_PUTPRINTER, p, PERROR);
done(1);
}
if ((getzoneid() == GLOBAL_ZONEID) && system_labeled &&
(prbufp->device != NULL))
update_dev_dbs(p, prbufp->device, "ADD");
END_CRITICAL
}
static char *
fullpath(char *str)
{
char *cur_dir;
char *path;
while (*str && *str == ' ')
str++;
if (*str == '/')
return (str);
if (!(cur_dir = malloc(PATH_MAX + 1)))
return (str);
getcwd(cur_dir, PATH_MAX);
path = makepath(cur_dir, str, (char *)0);
return (path);
}
char *
nameit(char *cmd)
{
char *nm;
char *copy;
nm = getname();
copy = malloc(strlen(cmd) + 1 + strlen(nm) + 1);
(void) strcpy(copy, cmd);
(void) strcat(copy, " ");
(void) strcat(copy, nm);
return (copy);
}
void
update_dev_dbs(char *prtname, char *devname, char *func)
{
int fd, status;
pid_t pid;
pid = fork();
switch (pid) {
case -1:
return;
case 0:
(void) close(1);
(void) close(2);
fd = open("/dev/null", O_WRONLY);
fd = dup(fd);
if (strcmp(func, "ADD") == 0) {
execl("/usr/sbin/add_allocatable", "add_allocatable",
"-n", prtname, "-t", "lp", "-l", devname,
"-o", "minlabel=admin_low:maxlabel=admin_high",
"-a", "*", "-c", "/bin/true", NULL);
} else {
if (strcmp(func, "REMOVE") == 0) {
execl("/usr/sbin/remove_allocatable",
"remove_allocatable", "-n", prtname, NULL);
}
}
_exit(1);
default:
waitpid(pid, &status, 0);
return;
}
}
static void
pack_white(char *ptr)
{
char *tptr;
char *mptr;
int cnt;
if (ptr == NULL)
return;
cnt = strlen(ptr);
if (cnt == 0)
return;
mptr = (char *)calloc((unsigned)cnt+1, sizeof (char));
if (mptr == NULL)
return;
tptr = strtok(ptr, " \t");
while (tptr != NULL) {
(void) strcat(mptr, tptr);
(void) strcat(mptr, " ");
tptr = strtok(NULL, " \t");
}
cnt = strlen(mptr);
(void) strcpy(ptr, mptr);
free(mptr);
}