#include "sys/types.h"
#include "sys/stat.h"
#include "stdio.h"
#include "string.h"
#include "errno.h"
#include "stdlib.h"
#include "lp.h"
#include "printers.h"
#include <unistd.h>
#include <sys/wait.h>
#define SHELL "/bin/sh"
#define PPDZIP ".gz"
extern struct {
char *v;
short len,
okremote;
} prtrheadings[];
#if defined(__STDC__)
static void print_sdn (int, char *, SCALED);
static void print_l (int, char *, char **);
static void print_str (int, char *, char *);
#ifdef LP_USE_PAPI_ATTR
static int addPrintersPPD(char *name, PRINTER *prbufp);
static int copyPPDFile(char *ppd, char *printersPPD);
static int unzipPPDFile(char *ppd, char *printersPPD);
#endif
#else
static void print_sdn(),
print_l(),
print_str();
#ifdef LP_USE_PAPI_ATTR
static int addPrintersPPD();
static int copyPPDFile();
static int unzipPPDFile();
#endif
#endif
unsigned long ignprinter = 0;
int ppdopt = 0;
int
putprinter(char *name, PRINTER *prbufp)
{
register char * path;
register char * stty;
register char * speed;
int fdin, fdout;
int fld;
char buf[BUFSIZ];
struct stat statbuf1,
statbuf2;
badprinter = 0;
if (!name || !*name) {
errno = EINVAL;
return (-1);
}
if (STREQU(NAME_ALL, name)) {
errno = EINVAL;
return (-1);
}
if (!okprinter(name, prbufp, 1)) {
errno = EINVAL;
return (-1);
}
if (!Lp_A_Printers || !Lp_A_Interfaces) {
getadminpaths (LPUSER);
if (!Lp_A_Printers || !Lp_A_Interfaces)
return (0);
}
if (!(path = getprinterfile(name, (char *)0)))
return (-1);
if (Stat(path, &statbuf1) == 0) {
if (!S_ISDIR(statbuf1.st_mode)) {
Free (path);
errno = ENOTDIR;
return (-1);
}
} else if (errno != ENOENT || mkdir_lpdir(path, MODE_DIR) == -1) {
Free (path);
return (-1);
}
Free (path);
if (prbufp->remote) {
if (!(path = makepath(Lp_A_Interfaces, name, (char *)0)))
return (-1);
(void)rmfile (path);
Free (path);
}
if (prbufp->interface && (ignprinter & BAD_INTERFACE) == 0) {
if (Stat(prbufp->interface, &statbuf1) == -1)
return (-1);
if (!(path = makepath(Lp_A_Interfaces, name, (char *)0)))
return (-1);
if (
Stat(path, &statbuf2) == -1
|| statbuf1.st_dev != statbuf2.st_dev
|| statbuf1.st_ino != statbuf2.st_ino
) {
register int n;
if ((fdin = open_locked(prbufp->interface, "r", 0)) < 0) {
Free (path);
return (-1);
}
if ((fdout = open_locked(path, "w", MODE_EXEC)) < 0) {
Free (path);
close(fdin);
return (-1);
}
while ((n = read(fdin, buf, BUFSIZ)) > 0)
write (fdout, buf, n);
close(fdout);
close(fdin);
}
Free (path);
}
#ifdef LP_USE_PAPI_ATTR
if ((prbufp->ppd != NULL) && (ppdopt))
{
if (addPrintersPPD(name, prbufp) != 0)
{
return (-1);
}
}
#endif
stty = (prbufp->stty? Strdup(prbufp->stty) : 0);
if (prbufp->speed)
speed = Strdup(prbufp->speed);
else
speed = 0;
if (prbufp->dial_info && stty) {
register char *newstty,
*p,
*q;
register int len;
if (!(q = newstty = Malloc(strlen(stty) + 1))) {
Free (stty);
errno = ENOMEM;
return (-1);
}
newstty[0] = 0;
for (
p = strtok(stty, " ");
p;
p = strtok((char *)0, " ")
) {
len = strlen(p);
if (strspn(p, "0123456789") == len) {
if (!prbufp->speed) {
if (speed)
Free (speed);
speed = Strdup(p);
}
} else {
if (q != newstty)
*q++ = ' ';
strcpy (q, p);
q += len;
}
}
Free (stty);
stty = newstty;
} else if (!prbufp->dial_info && speed) {
register char *newstty;
newstty = Malloc(strlen(stty) + 1 + strlen(speed) + 1);
if (!newstty) {
if (stty)
Free (stty);
errno = ENOMEM;
return (-1);
}
if (stty) {
strcpy (newstty, stty);
strcat (newstty, " ");
strcat (newstty, speed);
Free (stty);
} else
strcpy (newstty, speed);
Free (speed);
speed = 0;
stty = newstty;
}
if (!(path = getprinterfile(name, CONFIGFILE))) {
if (stty)
Free (stty);
if (speed)
Free (speed);
return (-1);
}
if ((fdout = open_locked(path, "w", MODE_READ)) < 0) {
Free (path);
if (stty)
Free (stty);
if (speed)
Free (speed);
return (-1);
}
Free (path);
errno = 0;
for (fld = 0; fld < PR_MAX; fld++) {
if (prbufp->remote && !prtrheadings[fld].okremote)
continue;
switch (fld) {
#define HEAD prtrheadings[fld].v
case PR_BAN:
{
char *ptr = NAME_ON;
switch (prbufp->banner) {
case BAN_ALWAYS:
ptr = NAME_ON;
break;
case BAN_NEVER:
ptr = NAME_OFF;
break;
case BAN_OPTIONAL:
ptr = NAME_OPTIONAL;
break;
}
(void)fdprintf(fdout, "%s %s\n", HEAD, ptr);
}
break;
case PR_CPI:
print_sdn(fdout, HEAD, prbufp->cpi);
break;
case PR_CS:
if (!emptylist(prbufp->char_sets))
print_l(fdout, HEAD, prbufp->char_sets);
break;
case PR_ITYPES:
print_l(fdout, HEAD, prbufp->input_types);
break;
case PR_DEV:
print_str(fdout, HEAD, prbufp->device);
break;
case PR_DIAL:
print_str(fdout, HEAD, prbufp->dial_info);
break;
case PR_RECOV:
print_str(fdout, HEAD, prbufp->fault_rec);
break;
case PR_INTFC:
print_str(fdout, HEAD, prbufp->interface);
break;
case PR_LPI:
print_sdn(fdout, HEAD, prbufp->lpi);
break;
case PR_LEN:
print_sdn(fdout, HEAD, prbufp->plen);
break;
case PR_LOGIN:
if (prbufp->login & LOG_IN)
(void)fdprintf(fdout, "%s\n", HEAD);
break;
case PR_PTYPE:
{
char **printer_types;
if (prbufp->printer_type && !prbufp->printer_types)
printer_types = getlist(
prbufp->printer_type,
LP_WS,
LP_SEP
);
else
printer_types = prbufp->printer_types;
if (!printer_types || !*printer_types)
print_str(fdout, HEAD, NAME_UNKNOWN);
else
print_l(fdout, HEAD, printer_types);
if (printer_types != prbufp->printer_types)
freelist (printer_types);
break;
}
case PR_REMOTE:
print_str(fdout, HEAD, prbufp->remote);
break;
case PR_SPEED:
print_str(fdout, HEAD, speed);
break;
case PR_STTY:
print_str(fdout, HEAD, stty);
break;
case PR_WIDTH:
print_sdn(fdout, HEAD, prbufp->pwid);
break;
#if defined(CAN_DO_MODULES)
case PR_MODULES:
print_l(fdout, HEAD, prbufp->modules);
break;
#endif
case PR_OPTIONS:
print_l(fdout, HEAD, prbufp->options);
break;
case PR_PPD:
{
print_str(fdout, HEAD, prbufp->ppd);
break;
}
}
}
if (stty)
Free (stty);
if (speed)
Free (speed);
if (errno != 0) {
close(fdout);
return (-1);
}
close(fdout);
if (prbufp->description) {
if (!(path = getprinterfile(name, COMMENTFILE)))
return (-1);
if (dumpstring(path, prbufp->description) == -1) {
Free (path);
return (-1);
}
Free (path);
}
if (
prbufp->fault_alert.shcmd
&& putalert(Lp_A_Printers, name, &(prbufp->fault_alert)) == -1
)
return (-1);
return (0);
}
static void
print_sdn(int fd, char *head, SCALED sdn)
{
if (sdn.val <= 0)
return;
(void)fdprintf (fd, "%s ", head);
fdprintsdn (fd, sdn);
return;
}
static void
print_l(int fd, char *head, char **list)
{
(void)fdprintf (fd, "%s ", head);
printlist_setup (0, 0, LP_SEP, 0);
fdprintlist (fd, list);
printlist_unsetup ();
return;
}
static void
print_str(int fd, char *head, char *str)
{
if (!str || !*str)
return;
(void)fdprintf (fd, "%s %s\n", head, str);
return;
}
#ifdef LP_USE_PAPI_ATTR
static int
addPrintersPPD(char *name, PRINTER *prbufp)
{
int result = 0;
char *path = NULL;
char *ppd = NULL;
char buf[BUFSIZ];
struct stat statbuf;
(void) snprintf(buf, sizeof (buf), "%s.ppd", name);
if (prbufp->remote)
{
if (!(path = makepath(ETCDIR, "ppd", buf, (char *)0)))
{
result = -1;
}
else
{
(void) rmfile(path);
}
}
if ((result == 0) && (prbufp->ppd != NULL))
{
ppd = strdup(prbufp->ppd);
if (ppd == NULL)
{
result = -1;
}
else
{
if (Stat(ppd, &statbuf) == -1)
{
if (strstr(ppd, PPDZIP) != NULL)
{
result = -1;
}
else
{
ppd = Realloc(ppd,
strlen(ppd)+strlen(PPDZIP)+2);
if (ppd != NULL)
{
ppd = strcat(ppd, PPDZIP);
if (Stat(ppd, &statbuf) == -1)
{
result = -1;
}
}
else
{
result = -1;
}
}
}
}
if (result == 0)
{
if (!(path = makepath(ETCDIR, "ppd", buf, (char *)0)))
{
result = -1;
}
}
if (result == 0)
{
if (strstr(ppd, PPDZIP) == NULL)
{
result = copyPPDFile(ppd, path);
}
else
{
result = unzipPPDFile(ppd, path);
}
(void) chown_lppath(path);
(void) chmod(path, 0644);
}
if (ppd != NULL)
{
Free(ppd);
}
if (path != NULL)
{
Free(path);
}
}
return (result);
}
static int
copyPPDFile(char *ppd, char *printersPPD)
{
int result = 0;
register int n = 0;
int fdin = 0;
int fdout = 0;
char buf[BUFSIZ];
if ((ppd != NULL) && (printersPPD != NULL))
{
if ((fdin = open_locked(ppd, "r", 0)) < 0)
{
result = -1;
}
else
{
fdout = open_locked(printersPPD, "w", MODE_EXEC);
if (fdout < 0)
{
close(fdin);
result = -1;
}
}
if (result == 0)
{
while ((n = read(fdin, buf, BUFSIZ)) > 0)
{
write(fdout, buf, n);
}
close(fdout);
close(fdin);
}
}
else
{
result = -1;
}
return (result);
}
static int
unzipPPDFile(char *ppd, char *printersPPD)
{
int result = -1;
char *cmdLine = NULL;
pid_t childPID = 0;
int stat = 0;
int clSize = 0;
if ((ppd != NULL) && (printersPPD != NULL))
{
childPID = fork();
switch (childPID)
{
case -1:
{
break;
}
case 0:
{
clSize = strlen("/usr/bin/rm -f ") +
strlen(printersPPD) +
strlen("/usr/bin/gzip -dc ") +
strlen(ppd) +
strlen(printersPPD) + 20;
cmdLine = malloc(clSize);
if (cmdLine != NULL)
{
(void) snprintf(cmdLine, clSize,
"/usr/bin/rm -f %s; /usr/bin/gzip -dc %s > %s",
printersPPD, ppd,
printersPPD);
result = execl(SHELL, SHELL, "-c",
cmdLine, NULL);
exit(result);
}
break;
}
default:
{
while (wait(&stat) != childPID);
if ((stat & 0xff00) == 0)
{
result = 0;
}
break;
}
}
}
return (result);
}
#endif