summaryrefslogtreecommitdiffstats
path: root/usr.sbin/lpr/common_source
diff options
context:
space:
mode:
authorwollman <wollman@FreeBSD.org>1997-12-02 20:46:22 +0000
committerwollman <wollman@FreeBSD.org>1997-12-02 20:46:22 +0000
commitbf21e6b4e0e85ae08cb5d1f2335da248f52e2d26 (patch)
tree041fd28f30eaadf848820e6ceed6899636d31478 /usr.sbin/lpr/common_source
parentfa82bf4e17d3b6422eb922374e04631e08af93ef (diff)
downloadFreeBSD-src-bf21e6b4e0e85ae08cb5d1f2335da248f52e2d26.zip
FreeBSD-src-bf21e6b4e0e85ae08cb5d1f2335da248f52e2d26.tar.gz
Mega lpd/lpd upgrade, part I:
- Get rid of a lot of the static variables which were shared by many routines and programs in the suite. - Create an abstract interface to the printcap database, so that other retrieval and iteration mechanisms could be developed (e.g., YP, Hesiod, or automatic retrieval from a trusted server). - Give each capability a human-readable name in addition to the historic two-character one. - Otherwise generally clean up a lot of dark corners. Many still remain. - When submitting jobs, use the official login name record (from getlogin()) if there is one, rather than reverse-mapping the uid. More to come...
Diffstat (limited to 'usr.sbin/lpr/common_source')
-rw-r--r--usr.sbin/lpr/common_source/Makefile19
-rw-r--r--usr.sbin/lpr/common_source/common.c254
-rw-r--r--usr.sbin/lpr/common_source/displayq.c119
-rw-r--r--usr.sbin/lpr/common_source/lp.h216
-rw-r--r--usr.sbin/lpr/common_source/net.c260
-rw-r--r--usr.sbin/lpr/common_source/pathnames.h1
-rw-r--r--usr.sbin/lpr/common_source/printcap.c428
-rw-r--r--usr.sbin/lpr/common_source/recvjob.c53
-rw-r--r--usr.sbin/lpr/common_source/request.c80
-rw-r--r--usr.sbin/lpr/common_source/rmjob.c139
-rw-r--r--usr.sbin/lpr/common_source/startdaemon.c35
11 files changed, 1210 insertions, 394 deletions
diff --git a/usr.sbin/lpr/common_source/Makefile b/usr.sbin/lpr/common_source/Makefile
new file mode 100644
index 0000000..96151e7
--- /dev/null
+++ b/usr.sbin/lpr/common_source/Makefile
@@ -0,0 +1,19 @@
+# $Id$
+
+#
+# Library of internal routines for the print spooler suite.
+# Originally these were compiled separately into each program,
+# but the library makes it much easier to modularize them.
+#
+LIB= lpr
+SRCS= common.c displayq.c net.c printcap.c request.c rmjob.c \
+ startdaemon.c
+NOMAN= noman
+NOPROFILE= noprofile
+NOPIC= nopic
+CFLAGS+= -Werror -Wall -Wnested-externs -Wmissing-prototypes \
+ -Wstrict-prototypes -Wredundant-decls
+
+install:
+
+.include <bsd.lib.mk>
diff --git a/usr.sbin/lpr/common_source/common.c b/usr.sbin/lpr/common_source/common.c
index 7301e2b..8cfacab 100644
--- a/usr.sbin/lpr/common_source/common.c
+++ b/usr.sbin/lpr/common_source/common.c
@@ -37,151 +37,38 @@
*/
#ifndef lint
+/*
static char sccsid[] = "@(#)common.c 8.5 (Berkeley) 4/28/95";
+*/
+static const char rcsid[] =
+ "$Id$";
#endif /* not lint */
#include <sys/param.h>
#include <sys/stat.h>
#include <sys/time.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <netdb.h>
-
#include <dirent.h>
-#include <errno.h>
-#include <unistd.h>
-#include <stdlib.h>
#include <stdio.h>
+#include <stdlib.h>
#include <string.h>
+#include <unistd.h>
+
#include "lp.h"
+#include "lp.local.h"
#include "pathnames.h"
/*
* Routines and data common to all the line printer functions.
*/
-
-char *AF; /* accounting file */
-long BR; /* baud rate if lp is a tty */
-char *CF; /* name of cifplot filter (per job) */
-long CT; /* TCP connection timeout */
-char *DF; /* name of tex filter (per job) */
-long DU; /* daeomon user-id */
-char *FF; /* form feed string */
-char *GF; /* name of graph(1G) filter (per job) */
-long HL; /* print header last */
-char *IF; /* name of input filter (created per job) */
-char *LF; /* log file for error messages */
-char *LO; /* lock file name */
-char *LP; /* line printer device name */
-long MC; /* maximum number of copies allowed */
-long MX; /* maximum number of blocks to copy */
-char *NF; /* name of ditroff filter (per job) */
-char *OF; /* name of output filter (created once) */
-char *PF; /* name of vrast filter (per job) */
-long PL; /* page length */
-long PW; /* page width */
-long PX; /* page width in pixels */
-long PY; /* page length in pixels */
-char *RF; /* name of fortran text filter (per job) */
-char *RG; /* resricted group */
-char *RM; /* remote machine name */
-char *RP; /* remote printer name */
-long RS; /* restricted to those with local accounts */
-long RW; /* open LP for reading and writing */
-long SB; /* short banner instead of normal header */
-long SC; /* suppress multiple copies */
-char *SD; /* spool directory */
-long SF; /* suppress FF on each print job */
-long SH; /* suppress header page */
-char *ST; /* status file name */
-char *TF; /* name of troff filter (per job) */
-char *TR; /* trailer string to be output when Q empties */
-char *MS; /* mode set, a la stty */
-char *VF; /* name of vplot filter (per job) */
-
char line[BUFSIZ];
-char *bp; /* pointer into printcap buffer. */
char *name; /* program name */
-char *printer; /* printer name */
- /* host machine name */
-char host[MAXHOSTNAMELEN];
-char *from = host; /* client's machine name */
-int remote; /* true if sending files to a remote host */
-char *printcapdb[2] = { _PATH_PRINTCAP, 0 };
extern uid_t uid, euid;
static int compar __P((const void *, const void *));
/*
- * Create a TCP connection to host "rhost" at port "rport".
- * If rport == 0, then use the printer service port.
- * Most of this code comes from rcmd.c.
- */
-int
-getport(rhost, rport)
- char *rhost;
- int rport;
-{
- struct hostent *hp;
- struct servent *sp;
- struct sockaddr_in sin;
- int s, timo = 1, lport = IPPORT_RESERVED - 1;
- int err;
-
- /*
- * Get the host address and port number to connect to.
- */
- if (rhost == NULL)
- fatal("no remote host to connect to");
- bzero((char *)&sin, sizeof(sin));
- sin.sin_addr.s_addr = inet_addr(rhost);
- if (sin.sin_addr.s_addr != INADDR_NONE)
- sin.sin_family = AF_INET;
- else {
- hp = gethostbyname(rhost);
- if (hp == NULL)
- fatal("unknown host %s", rhost);
- bcopy(hp->h_addr, (caddr_t)&sin.sin_addr, hp->h_length);
- sin.sin_family = hp->h_addrtype;
- }
- if (rport == 0) {
- sp = getservbyname("printer", "tcp");
- if (sp == NULL)
- fatal("printer/tcp: unknown service");
- sin.sin_port = sp->s_port;
- } else
- sin.sin_port = htons(rport);
-
- /*
- * Try connecting to the server.
- */
-retry:
- seteuid(euid);
- s = rresvport(&lport);
- seteuid(uid);
- if (s < 0)
- return(-1);
- if (connect(s, (struct sockaddr *)&sin, sizeof(sin)) < 0) {
- err = errno;
- (void) close(s);
- errno = err;
- if (errno == EADDRINUSE) {
- lport--;
- goto retry;
- }
- if (errno == ECONNREFUSED && timo <= 16) {
- sleep(timo);
- timo *= 2;
- goto retry;
- }
- return(-1);
- }
- return(s);
-}
-
-/*
* Getline reads a line from the control file cfp, removes tabs, converts
* new-line to null and leaves it in line.
* Returns 0 at EOF or the number of characters read.
@@ -217,7 +104,8 @@ getline(cfp)
* Return the number of entries and a pointer to the list.
*/
int
-getq(namelist)
+getq(pp, namelist)
+ const struct printer *pp;
struct queue *(*namelist[]);
{
register struct dirent *d;
@@ -228,7 +116,7 @@ getq(namelist)
int arraysz;
seteuid(euid);
- if ((dirp = opendir(SD)) == NULL)
+ if ((dirp = opendir(pp->spool_dir)) == NULL)
return(-1);
if (fstat(dirp->dd_fd, &stbuf) < 0)
goto errdone;
@@ -294,65 +182,65 @@ compar(p1, p2)
return(0);
}
-/*
- * Figure out whether the local machine is the same
- * as the remote machine (RM) entry (if it exists).
- */
-char *
-checkremote()
-{
- char name[MAXHOSTNAMELEN];
- register struct hostent *hp;
- static char errbuf[128];
-
- remote = 0; /* assume printer is local */
- if (RM != NULL) {
- /* get the official name of the local host */
- gethostname(name, sizeof(name));
- name[sizeof(name) - 1] = '\0';
- hp = gethostbyname(name);
- if (hp == (struct hostent *) NULL) {
- (void) snprintf(errbuf, sizeof(errbuf),
- "unable to get official name for local machine %s",
- name);
- return errbuf;
- } else {
- (void) strncpy(name, hp->h_name, sizeof(name));
- name[sizeof(name) - 1] = '\0';
- }
-
- /* get the official name of RM */
- hp = gethostbyname(RM);
- if (hp == (struct hostent *) NULL) {
- (void) snprintf(errbuf, sizeof(errbuf),
- "unable to get official name for remote machine %s",
- RM);
- return errbuf;
- }
-
- /*
- * if the two hosts are not the same,
- * then the printer must be remote.
- */
- if (strcasecmp(name, hp->h_name) != 0)
- remote = 1;
- }
- return NULL;
-}
-
/* sleep n milliseconds */
void
delay(n)
+ int n;
{
struct timeval tdelay;
if (n <= 0 || n > 10000)
- fatal("unreasonable delay period (%d)", n);
+ fatal((struct printer *)0, /* fatal() knows how to deal */
+ "unreasonable delay period (%d)", n);
tdelay.tv_sec = n / 1000;
tdelay.tv_usec = n * 1000 % 1000000;
(void) select(0, (fd_set *)0, (fd_set *)0, (fd_set *)0, &tdelay);
}
+char *
+lock_file_name(pp, buf, len)
+ const struct printer *pp;
+ char *buf;
+ size_t len;
+{
+ static char staticbuf[MAXPATHLEN];
+
+ if (buf == 0)
+ buf = staticbuf;
+ if (len == 0)
+ len = MAXPATHLEN;
+
+ if (pp->lock_file[0] == '/') {
+ buf[0] = '\0';
+ strncpy(buf, pp->lock_file, len);
+ } else {
+ snprintf(buf, len, "%s/%s", pp->spool_dir, pp->lock_file);
+ }
+ return buf;
+}
+
+char *
+status_file_name(pp, buf, len)
+ const struct printer *pp;
+ char *buf;
+ size_t len;
+{
+ static char staticbuf[MAXPATHLEN];
+
+ if (buf == 0)
+ buf = staticbuf;
+ if (len == 0)
+ len = MAXPATHLEN;
+
+ if (pp->status_file[0] == '/') {
+ buf[0] = '\0';
+ strncpy(buf, pp->status_file, len);
+ } else {
+ snprintf(buf, len, "%s/%s", pp->spool_dir, pp->status_file);
+ }
+ return buf;
+}
+
#ifdef __STDC__
#include <stdarg.h>
#else
@@ -361,9 +249,10 @@ delay(n)
void
#ifdef __STDC__
-fatal(const char *msg, ...)
+fatal(const struct printer *pp, const char *msg, ...)
#else
-fatal(msg, va_alist)
+fatal(pp, msg, va_alist)
+ const struct printer *pp;
char *msg;
va_dcl
#endif
@@ -377,10 +266,27 @@ fatal(msg, va_alist)
if (from != host)
(void)printf("%s: ", host);
(void)printf("%s: ", name);
- if (printer)
- (void)printf("%s: ", printer);
+ if (pp && pp->printer)
+ (void)printf("%s: ", pp->printer);
(void)vprintf(msg, ap);
va_end(ap);
(void)putchar('\n');
exit(1);
}
+
+/*
+ * Close all file descriptors from START on up.
+ * This is a horrific kluge, since getdtablesize() might return
+ * ``infinity'', in which case we will be spending a long time
+ * closing ``files'' which were never open. Perhaps it would
+ * be better to close the first N fds, for some small value of N.
+ */
+void
+closeallfds(start)
+ int start;
+{
+ int stop = getdtablesize();
+ for (; start < stop; start++)
+ close(start);
+}
+
diff --git a/usr.sbin/lpr/common_source/displayq.c b/usr.sbin/lpr/common_source/displayq.c
index 01d91a6..3f0ad42 100644
--- a/usr.sbin/lpr/common_source/displayq.c
+++ b/usr.sbin/lpr/common_source/displayq.c
@@ -32,21 +32,30 @@
*/
#ifndef lint
+/*
static char sccsid[] = "@(#)displayq.c 8.4 (Berkeley) 4/28/95";
+*/
+static const char rcsid[] =
+ "$Id$";
#endif /* not lint */
#include <sys/param.h>
#include <sys/stat.h>
-#include <sys/file.h>
-#include <signal.h>
-#include <fcntl.h>
+#include <ctype.h>
#include <dirent.h>
-#include <unistd.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-#include <ctype.h>
+#define psignal foil_gcc_psignal
+#define sys_siglist foil_gcc_siglist
+#include <unistd.h>
+#undef psignal
+#undef sys_siglist
+
#include "lp.h"
#include "lp.local.h"
#include "pathnames.h"
@@ -76,13 +85,14 @@ static char *head0 = "Rank Owner Job Files";
static char *head1 = "Total Size\n";
static void alarmhandler __P((int));
-static void warn __P((void));
+static void warn __P((const struct printer *pp));
/*
* Display the current state of the queue. Format = 1 if long format.
*/
void
-displayq(format)
+displayq(pp, format)
+ struct printer *pp;
int format;
{
register struct queue *q;
@@ -96,71 +106,55 @@ displayq(format)
lflag = format;
totsize = 0;
rank = -1;
- if ((i = cgetent(&bp, printcapdb, printer)) == -2)
- fatal("can't open printer description file");
- else if (i == -1)
- fatal("unknown printer");
- else if (i == -3)
- fatal("potential reference loop detected in printcap file");
- if (cgetstr(bp, "lp", &LP) < 0)
- LP = _PATH_DEFDEVLP;
- if (cgetstr(bp, "rp", &RP) < 0)
- RP = DEFLP;
- if (cgetstr(bp, "sd", &SD) < 0)
- SD = _PATH_DEFSPOOL;
- if (cgetstr(bp,"lo", &LO) < 0)
- LO = DEFLOCK;
- if (cgetstr(bp, "st", &ST) < 0)
- ST = DEFSTAT;
- if (cgetnum(bp, "ct", &CT) < 0)
- CT = DEFTIMEOUT;
- if (cgetstr(bp, "rm", &RM) < 0)
- RM = NULL;
- if ((cp = checkremote()))
+
+ if ((cp = checkremote(pp))) {
printf("Warning: %s\n", cp);
+ free(cp);
+ }
/*
* Print out local queue
* Find all the control files in the spooling directory
*/
seteuid(euid);
- if (chdir(SD) < 0)
- fatal("cannot chdir to spooling directory");
+ if (chdir(pp->spool_dir) < 0)
+ fatal(pp, "cannot chdir to spooling directory: %s",
+ strerror(errno));
seteuid(uid);
- if ((nitems = getq(&queue)) < 0)
- fatal("cannot examine spooling area\n");
+ if ((nitems = getq(pp, &queue)) < 0)
+ fatal(pp, "cannot examine spooling area\n");
seteuid(euid);
- ret = stat(LO, &statb);
+ ret = stat(pp->lock_file, &statb);
seteuid(uid);
if (ret >= 0) {
- if (statb.st_mode & 0100) {
- if (remote)
+ if (statb.st_mode & LFM_PRINT_DIS) {
+ if (pp->remote)
printf("%s: ", host);
- printf("Warning: %s is down: ", printer);
+ printf("Warning: %s is down: ", pp->printer);
seteuid(euid);
- fd = open(ST, O_RDONLY);
+ fd = open(pp->status_file, O_RDONLY|O_SHLOCK);
seteuid(uid);
if (fd >= 0) {
- (void) flock(fd, LOCK_SH);
while ((i = read(fd, line, sizeof(line))) > 0)
(void) fwrite(line, 1, i, stdout);
(void) close(fd); /* unlocks as well */
} else
putchar('\n');
}
- if (statb.st_mode & 010) {
- if (remote)
+ if (statb.st_mode & LFM_QUEUE_DIS) {
+ if (pp->remote)
printf("%s: ", host);
- printf("Warning: %s queue is turned off\n", printer);
+ printf("Warning: %s queue is turned off\n",
+ pp->printer);
}
}
if (nitems) {
seteuid(euid);
- fp = fopen(LO, "r");
+ fp = fopen(pp->lock_file, "r");
seteuid(uid);
if (fp == NULL)
- warn();
+ warn(pp);
else {
/* get daemon pid */
cp = current;
@@ -176,7 +170,7 @@ displayq(format)
seteuid(uid);
}
if (ret < 0) {
- warn();
+ warn(pp);
} else {
/* read current file name */
cp = current;
@@ -186,16 +180,16 @@ displayq(format)
/*
* Print the status file.
*/
- if (remote)
+ if (pp->remote)
printf("%s: ", host);
seteuid(euid);
- fd = open(ST, O_RDONLY);
+ fd = open(pp->status_file, O_RDONLY|O_SHLOCK);
seteuid(uid);
if (fd >= 0) {
- (void) flock(fd, LOCK_SH);
- while ((i = read(fd, line, sizeof(line))) > 0)
- (void) fwrite(line, 1, i, stdout);
- (void) close(fd); /* unlocks as well */
+ while ((i = read(fd, line,
+ sizeof(line))) > 0)
+ fwrite(line, 1, i, stdout);
+ close(fd); /* unlocks as well */
} else
putchar('\n');
}
@@ -209,12 +203,12 @@ displayq(format)
header();
for (i = 0; i < nitems; i++) {
q = queue[i];
- inform(q->q_name);
+ inform(pp, q->q_name);
free(q);
}
free(queue);
}
- if (!remote) {
+ if (!pp->remote) {
if (nitems == 0)
puts("no entries");
return;
@@ -226,7 +220,8 @@ displayq(format)
*/
if (nitems)
putchar('\n');
- (void) snprintf(line, sizeof(line), "%c%s", format + '\3', RP);
+ (void) snprintf(line, sizeof(line), "%c%s", format ? '\4' : '\3',
+ pp->remote_queue);
cp = line;
for (i = 0; i < requests && cp-line+10 < sizeof(line) - 1; i++) {
cp += strlen(cp);
@@ -240,19 +235,19 @@ displayq(format)
}
strcat(line, "\n");
savealrm = signal(SIGALRM, alarmhandler);
- alarm(CT);
- fd = getport(RM, 0);
+ alarm(pp->conn_timeout);
+ fd = getport(pp, pp->remote_host, 0);
alarm(0);
(void)signal(SIGALRM, savealrm);
if (fd < 0) {
if (from != host)
printf("%s: ", host);
- printf("connection to %s is down\n", RM);
+ printf("connection to %s is down\n", pp->remote_host);
}
else {
i = strlen(line);
if (write(fd, line, i) != i)
- fatal("Lost connection");
+ fatal(pp, "Lost connection");
while ((i = read(fd, line, sizeof(line))) > 0)
(void) fwrite(line, 1, i, stdout);
(void) close(fd);
@@ -263,9 +258,10 @@ displayq(format)
* Print a warning message if there is no daemon present.
*/
static void
-warn()
+warn(pp)
+ const struct printer *pp;
{
- if (remote)
+ if (pp->remote)
printf("%s: ", host);
puts("Warning: no daemon present");
current[0] = '\0';
@@ -284,7 +280,8 @@ header()
}
void
-inform(cf)
+inform(pp, cf)
+ const struct printer *pp;
char *cf;
{
register int j;
@@ -301,7 +298,7 @@ inform(cf)
if (rank < 0)
rank = 0;
- if (remote || garbage || strcmp(cf, current))
+ if (pp->remote || garbage || strcmp(cf, current))
rank++;
j = 0;
while (getline(cfp)) {
diff --git a/usr.sbin/lpr/common_source/lp.h b/usr.sbin/lpr/common_source/lp.h
index 816e652..8b3cd5f 100644
--- a/usr.sbin/lpr/common_source/lp.h
+++ b/usr.sbin/lpr/common_source/lp.h
@@ -30,69 +30,123 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * @(#)lp.h 8.2 (Berkeley) 4/28/95
+ * From: @(#)lp.h 8.2 (Berkeley) 4/28/95
+ * $Id$
*/
+#include <sys/queue.h>
/*
- * Global definitions for the line printer system.
+ * All this information used to be in global static variables shared
+ * mysteriously by various parts of the lpr/lpd suite.
+ * This structure attempts to centralize all these declarations in the
+ * hope that they can later be made more dynamic.
+ */
+enum lpd_filters { LPF_CIFPLOT, LPF_DVI, LPF_GRAPH, LPF_INPUT,
+ LPF_DITROFF, LPF_OUTPUT, LPF_FORTRAN, LPF_TROFF,
+ LPF_RASTER, LPF_COUNT };
+/* NB: there is a table in common.c giving the mapping from capability names */
+
+struct printer {
+ char *printer; /* printer name */
+ int remote; /* true if RM points to a remote host */
+ int tof; /* true if we are at top-of-form */
+ /* ------------------------------------------------------ */
+ char *acct_file; /* AF: accounting file */
+ long baud_rate; /* BR: baud rate if lp is a tty */
+ char *filters[LPF_COUNT]; /* CF, DF, GF, IF, NF, OF, RF, TF, VF */
+ long conn_timeout; /* CT: TCP connection timeout */
+ long daemon_user; /* DU: daemon user id -- XXX belongs ???? */
+ char *form_feed; /* FF: form feed */
+ long header_last; /* HL: print header last */
+ char *log_file; /* LF: log file */
+ char *lock_file; /* LO: lock file */
+ char *lp; /* LP: device name or network address */
+ long max_copies; /* MC: maximum number of copies allowed */
+ long max_blocks; /* MX: maximum number of blocks to copy */
+ long price100; /* PC: price per 100 units of output */
+ long page_length; /* PL: page length */
+ long page_width; /* PW: page width */
+ long page_pwidth; /* PX: page width in pixels */
+ long page_plength; /* PY: page length in pixels */
+ char *restrict_grp; /* RG: restricted group */
+ char *remote_host; /* RM: remote machine name */
+ char *remote_queue; /* RP: remote printer name */
+ long restricted; /* RS: restricted to those with local accts */
+ long rw; /* RW: open LP for reading and writing */
+ long short_banner; /* SB: short banner */
+ long no_copies; /* SC: suppress multiple copies */
+ char *spool_dir; /* SD: spool directory */
+ long no_formfeed; /* SF: suppress FF on each print job */
+ long no_header; /* SH: suppress header page */
+ char *status_file; /* ST: status file name */
+ char *trailer; /* TR: trailer string send when Q empties */
+ char *mode_set; /* MS: mode set, a la stty */
+};
+
+/*
+ * Lists of user names and job numbers, for the benefit of the structs
+ * defined below. We use TAILQs so that requests don't get mysteriously
+ * reversed in process.
+ */
+struct req_user {
+ TAILQ_ENTRY(req_user) ru_link; /* macro glue */
+ char ru_uname[1]; /* name of user */
+};
+TAILQ_HEAD(req_user_head, req_user);
+
+struct req_file {
+ TAILQ_ENTRY(req_file) rf_link; /* macro glue */
+ char rf_type; /* type (lowercase cf file letter) of file */
+ char *rf_prettyname; /* user-visible name of file */
+ char rf_fname[1]; /* name of file */
+};
+TAILQ_HEAD(req_file_head, req_file);
+
+struct req_jobid {
+ TAILQ_ENTRY(req_jobid) rj_link; /* macro glue */
+ int rj_job; /* job number */
+};
+TAILQ_HEAD(req_jobid_head, req_jobid);
+
+/*
+ * Encapsulate all the information relevant to a request in the
+ * lpr/lpd protocol.
*/
+enum req_type { REQ_START, REQ_RECVJOB, REQ_LIST, REQ_DELETE };
-extern char *AF; /* accounting file */
-extern long BR; /* baud rate if lp is a tty */
-extern char *CF; /* name of cifplot filter (per job) */
-extern long CT; /* TCP connection timeout */
-extern char *DF; /* name of tex filter (per job) */
-extern long DU; /* daeomon user-id */
-extern char *FF; /* form feed string */
-extern char *GF; /* name of graph(1G) filter (per job) */
-extern long HL; /* print header last */
-extern char *IF; /* name of input filter (created per job) */
-extern char *LF; /* log file for error messages */
-extern char *LO; /* lock file name */
-extern char *LP; /* line printer device name */
-extern long MC; /* maximum number of copies allowed */
-extern long MX; /* maximum number of blocks to copy */
-extern char *NF; /* name of ditroff(1) filter (per job) */
-extern char *OF; /* name of output filter (created once) */
-extern long PL; /* page length */
-extern long PW; /* page width */
-extern long PX; /* page width in pixels */
-extern long PY; /* page length in pixels */
-extern char *RF; /* name of fortran text filter (per job) */
-extern char *RG; /* restricted group */
-extern char *RM; /* remote machine name */
-extern char *RP; /* remote printer name */
-extern long RS; /* restricted to those with local accounts */
-extern long RW; /* open LP for reading and writing */
-extern long SB; /* short banner instead of normal header */
-extern long SC; /* suppress multiple copies */
-extern char *SD; /* spool directory */
-extern long SF; /* suppress FF on each print job */
-extern long SH; /* suppress header page */
-extern char *ST; /* status file name */
-extern char *TF; /* name of troff(1) filter (per job) */
-extern char *TR; /* trailer string to be output when Q empties */
-extern char *MS; /* mode set, a la stty */
-extern char *VF; /* name of raster filter (per job) */
+struct request {
+ enum req_type type; /* what sort of request is this? */
+ struct printer prtr; /* which printer is it for? */
+ int remote; /* did request arrive over network? */
+ char *logname; /* login name of requesting user */
+ char *authname; /* authenticated identity of requesting user */
+ char *prettyname; /* ``pretty'' name of requesting user */
+ int privileged; /* was the request from a privileged user? */
+ void *authinfo; /* authentication information */
+ int authentic; /* was the request securely authenticated? */
+
+ /* Information for queries and deletes... */
+ int nusers; /* length of following list... */
+ struct req_user_head users; /* list of users to query/delete */
+ int njobids; /* length of following list... */
+ struct req_jobid_head jobids; /* list of jobids to query/delete */
+};
+/*
+ * Global definitions for the line printer system.
+ */
extern char line[BUFSIZ];
-extern char *bp; /* pointer into printcap buffer */
extern char *name; /* program name */
-extern char *printer; /* printer name */
/* host machine name */
extern char host[MAXHOSTNAMELEN];
extern char *from; /* client's machine name */
-extern int remote; /* true if sending files to a remote host */
-extern char *printcapdb[]; /* printcap database array */
extern int requ[]; /* job number of spool entries */
extern int requests; /* # of spool requests */
extern char *user[]; /* users to process */
extern int users; /* # of users in user array */
extern char *person; /* name of person doing lprm */
-extern char *name;
-
/*
* Structure used for building a sorted list of control files.
@@ -102,32 +156,78 @@ struct queue {
char q_name[MAXNAMLEN+1]; /* control file name */
};
+/*
+ * Error codes for our mini printcap library.
+ */
+#define PCAPERR_TCLOOP (-3)
+#define PCAPERR_OSERR (-2)
+#define PCAPERR_NOTFOUND (-1)
+#define PCAPERR_SUCCESS 0
+#define PCAPERR_TCOPEN 1
+
+/*
+ * File modes for the various status files maintained by lpd.
+ */
+#define LOCK_FILE_MODE (S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH)
+#define LFM_PRINT_DIS (S_IXUSR)
+#define LFM_QUEUE_DIS (S_IXGRP)
+#define LFM_RESET_QUE (S_IXOTH)
+
+#define STAT_FILE_MODE (S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH)
+#define LOG_FILE_MODE (S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH)
+#define TEMP_FILE_MODE (S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH)
+
+/*
+ * Command codes used in the protocol.
+ */
+#define CMD_CHECK_QUE '\1'
+#define CMD_TAKE_THIS '\2'
+#define CMD_SHOWQ_SHORT '\3'
+#define CMD_SHOWQ_LONG '\4'
+#define CMD_RMJOB '\5'
+
#include <sys/cdefs.h>
__BEGIN_DECLS
-struct dirent;
+struct dirent;
void blankfill __P((int));
-char *checkremote __P((void));
+char *checkremote __P((struct printer *pp));
int chk __P((char *));
-void displayq __P((int));
+void closeallfds __P((int start));
+void delay __P((int));
+void displayq __P((struct printer *pp, int format));
void dump __P((char *, char *, int));
-void fatal __P((const char *, ...));
+void fatal __P((const struct printer *pp, const char *fmp, ...));
+int firstprinter __P((struct printer *pp, int *status));
+void free_printer __P((struct printer *pp));
+void free_request __P((struct request *rp));
int getline __P((FILE *));
-int getport __P((char *, int));
-int getq __P((struct queue *(*[])));
+int getport __P((const struct printer *pp, const char *, int));
+int getprintcap __P((const char *printer, struct printer *pp));
+int getq __P((const struct printer *, struct queue *(*[])));
void header __P((void));
-void inform __P((char *));
+void inform __P((const struct printer *pp, char *cf));
+void init_printer __P((struct printer *pp));
+void init_request __P((struct request *rp));
int inlist __P((char *, char *));
int iscf __P((struct dirent *));
int isowner __P((char *, char *));
void ldump __P((char *, char *, int));
-int lockchk __P((char *));
+void lastprinter __P((void));
+int lockchk __P((struct printer *pp, char *));
+char *lock_file_name __P((const struct printer *pp, char *buf, size_t len));
+int nextprinter __P((struct printer *pp, int *status));
+const
+char *pcaperr __P((int error));
void prank __P((int));
-void process __P((char *));
-void rmjob __P((void));
-void rmremote __P((void));
+void process __P((const struct printer *pp, char *));
+void rmjob __P((const char *printer));
+void rmremote __P((const struct printer *pp));
+void setprintcap __P((char *newprintcap));
void show __P((char *, char *, int));
-int startdaemon __P((char *));
-void delay __P((int));
+int startdaemon __P((const struct printer *pp));
+char *status_file_name __P((const struct printer *pp, char *buf,
+ size_t len));
+ssize_t writel __P((int s, ...));
__END_DECLS
diff --git a/usr.sbin/lpr/common_source/net.c b/usr.sbin/lpr/common_source/net.c
new file mode 100644
index 0000000..d5886f9
--- /dev/null
+++ b/usr.sbin/lpr/common_source/net.c
@@ -0,0 +1,260 @@
+/*
+ * Copyright (c) 1983, 1993
+ * The Regents of the University of California. All rights reserved.
+ * (c) UNIX System Laboratories, Inc.
+ * All or some portions of this file are derived from material licensed
+ * to the University of California by American Telephone and Telegraph
+ * Co. or Unix System Laboratories, Inc. and are reproduced herein with
+ * the permission of UNIX System Laboratories, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * From: @(#)common.c 8.5 (Berkeley) 4/28/95
+ */
+
+#ifndef lint
+static const char rcsid[] =
+ "$Id$";
+#endif /* not lint */
+
+#include <sys/param.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <sys/uio.h>
+
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+
+#include <dirent.h> /* required for lp.h, not used here */
+#include <errno.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "lp.h"
+#include "lp.local.h"
+#include "pathnames.h"
+
+ /* host machine name */
+char host[MAXHOSTNAMELEN];
+char *from = host; /* client's machine name */
+
+extern uid_t uid, euid;
+
+/*
+ * Create a TCP connection to host "rhost" at port "rport".
+ * If rport == 0, then use the printer service port.
+ * Most of this code comes from rcmd.c.
+ */
+int
+getport(const struct printer *pp, const char *rhost, int rport)
+{
+ struct hostent *hp;
+ struct servent *sp;
+ struct sockaddr_in sin;
+ int s, timo = 1, lport = IPPORT_RESERVED - 1;
+ int err;
+
+ /*
+ * Get the host address and port number to connect to.
+ */
+ if (rhost == NULL)
+ fatal(pp, "no remote host to connect to");
+ bzero((char *)&sin, sizeof(sin));
+ sin.sin_len = sizeof sin;
+ sin.sin_family = AF_INET;
+ if (inet_aton(rhost, &sin.sin_addr) == 0) {
+ hp = gethostbyname2(rhost, AF_INET);
+ if (hp == NULL)
+ fatal(pp, "cannot resolve %s: %s", rhost,
+ hstrerror(h_errno));
+ /* XXX - should deal with more addresses */
+ sin.sin_addr = *(struct in_addr *)hp->h_addr_list[0];
+ }
+ if (rport == 0) {
+ sp = getservbyname("printer", "tcp");
+ if (sp == NULL)
+ fatal(pp, "printer/tcp: unknown service");
+ sin.sin_port = sp->s_port;
+ } else
+ sin.sin_port = htons(rport);
+
+ /*
+ * Try connecting to the server.
+ */
+retry:
+ seteuid(euid);
+ s = rresvport(&lport);
+ seteuid(uid);
+ if (s < 0)
+ return(-1);
+ if (connect(s, (struct sockaddr *)&sin, sizeof(sin)) < 0) {
+ err = errno;
+ (void) close(s);
+ errno = err;
+ /*
+ * This used to decrement lport, but the current semantics
+ * of rresvport do not provide such a function (in fact,
+ * rresvport should guarantee that the chosen port will
+ * never result in an EADDRINUSE).
+ */
+ if (errno == EADDRINUSE)
+ goto retry;
+
+ if (errno == ECONNREFUSED && timo <= 16) {
+ sleep(timo);
+ timo *= 2;
+ goto retry;
+ }
+ return(-1);
+ }
+ return(s);
+}
+
+/*
+ * Figure out whether the local machine is the same
+ * as the remote machine (RM) entry (if it exists).
+ * We do this by counting the intersection of our
+ * address list and theirs. This is better than the
+ * old method (comparing the canonical names), as it
+ * allows load-sharing between multiple print servers.
+ * The return value is an error message which must be
+ * free()d.
+ */
+char *
+checkremote(struct printer *pp)
+{
+ char name[MAXHOSTNAMELEN];
+ register struct hostent *hp;
+ char *err;
+ struct in_addr *localaddrs;
+ int i, j, nlocaladdrs, ncommonaddrs;
+
+ pp->remote = 0; /* assume printer is local */
+ if (pp->remote_host != NULL) {
+ /* get the addresses of the local host */
+ gethostname(name, sizeof(name));
+ name[sizeof(name) - 1] = '\0';
+ hp = gethostbyname2(name, AF_INET);
+ if (hp == (struct hostent *) NULL) {
+ asprintf(&err, "unable to get official name "
+ "for local machine %s: %s",
+ name, hstrerror(h_errno));
+ return err;
+ }
+ for (i = 0; hp->h_addr_list[i]; i++)
+ ;
+ nlocaladdrs = i;
+ localaddrs = malloc(i * sizeof(struct in_addr));
+ if (localaddrs == 0) {
+ asprintf(&err, "malloc %lu bytes failed",
+ (u_long)i * sizeof(struct in_addr));
+ return err;
+ }
+ for (i = 0; hp->h_addr_list[i]; i++)
+ localaddrs[i] = *(struct in_addr *)hp->h_addr_list[i];
+
+ /* get the official name of RM */
+ hp = gethostbyname2(pp->remote_host, AF_INET);
+ if (hp == (struct hostent *) NULL) {
+ asprintf(&err, "unable to get address list for "
+ "remote machine %s: %s",
+ pp->remote_host, hstrerror(h_errno));
+ free(localaddrs);
+ return err;
+ }
+
+ ncommonaddrs = 0;
+ for (i = 0; i < nlocaladdrs; i++) {
+ for (j = 0; hp->h_addr_list[j]; j++) {
+ char *them = hp->h_addr_list[j];
+ if (localaddrs[i].s_addr ==
+ (*(struct in_addr *)them).s_addr)
+ ncommonaddrs++;
+ }
+ }
+
+ /*
+ * if the two hosts do not share at least one IP address
+ * then the printer must be remote.
+ */
+ if (ncommonaddrs == 0)
+ pp->remote = 1;
+ free(localaddrs);
+ }
+ return NULL;
+}
+
+/*
+ * This isn't really network-related, but it's used here to write
+ * multi-part strings onto sockets without using stdio. Return
+ * values are as for writev(2).
+ */
+ssize_t
+writel(int s, ...)
+{
+ va_list ap;
+ int i, n;
+ const char *cp;
+#define NIOV 12
+ struct iovec iov[NIOV], *iovp = iov;
+ ssize_t retval;
+
+ /* first count them */
+ va_start(ap, s);
+ n = 0;
+ do {
+ cp = va_arg(ap, char *);
+ n++;
+ } while (cp);
+ va_end(ap);
+ n--; /* correct for count of trailing null */
+
+ if (n > NIOV) {
+ iovp = malloc(n * sizeof *iovp);
+ if (iovp == 0)
+ return -1;
+ }
+
+ /* now make up iovec and send */
+ va_start(ap, s);
+ for (i = 0; i < n; i++) {
+ iovp[i].iov_base = va_arg(ap, char *);
+ iovp[i].iov_len = strlen(iovp[i].iov_base);
+ }
+ va_end(ap);
+ retval = writev(s, iovp, n);
+ if (iovp != iov)
+ free(iovp);
+ return retval;
+}
diff --git a/usr.sbin/lpr/common_source/pathnames.h b/usr.sbin/lpr/common_source/pathnames.h
index 5c07cdb..78ccc7b 100644
--- a/usr.sbin/lpr/common_source/pathnames.h
+++ b/usr.sbin/lpr/common_source/pathnames.h
@@ -48,3 +48,4 @@
#define _PATH_VFONTI "/usr/libdata/vfont/I"
#define _PATH_VFONTR "/usr/libdata/vfont/R"
#define _PATH_VFONTS "/usr/libdata/vfont/S"
+#define _PATH_CHKPRINTCAP "/usr/sbin/chkprintcap"
diff --git a/usr.sbin/lpr/common_source/printcap.c b/usr.sbin/lpr/common_source/printcap.c
new file mode 100644
index 0000000..8991f0d
--- /dev/null
+++ b/usr.sbin/lpr/common_source/printcap.c
@@ -0,0 +1,428 @@
+/*
+ * Copyright (c) 1983, 1993
+ * The Regents of the University of California. All rights reserved.
+ * (c) UNIX System Laboratories, Inc.
+ * All or some portions of this file are derived from material licensed
+ * to the University of California by American Telephone and Telegraph
+ * Co. or Unix System Laboratories, Inc. and are reproduced herein with
+ * the permission of UNIX System Laboratories, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * From: @(#)common.c 8.5 (Berkeley) 4/28/95
+ */
+
+#ifndef lint
+static const char rcsid[] =
+ "$Id$";
+#endif /* not lint */
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <sys/param.h> /* required for lp.h, but not used here */
+#include <sys/dirent.h> /* ditto */
+#include "lp.h"
+#include "lp.local.h"
+#include "pathnames.h"
+
+/*
+ * Routines and data used in processing the printcap file.
+ */
+static char *printcapdb[2] = { _PATH_PRINTCAP, 0 }; /* list for cget* */
+
+static char *capdb_canonical_name(const char *);
+static int capdb_getaltlog(char *, const char *, const char *);
+static int capdb_getaltnum(char *, const char *, const char *, long, long *);
+static int capdb_getaltstr(char *, const char *, const char *, const char *,
+ char **);
+static int getprintcap_int(char *bp, struct printer *pp);
+
+/*
+ * Change the name of the printcap file. Used by chkprintcap(8),
+ * but could be used by other members of the suite with appropriate
+ * security measures.
+ */
+void
+setprintcap(char *newfile)
+{
+ printcapdb[0] = newfile;
+}
+
+/*
+ * Read the printcap database for printer `printer' into the
+ * struct printer pointed by `pp'. Return values are as for
+ * cgetent(3): -1 means we could not find what we wanted, -2
+ * means a system error occurred (and errno is set), -3 if a
+ * reference (`tc=') loop was detected, and 0 means success.
+ *
+ * Copied from lpr; should add additional capabilities as they
+ * are required by the other programs in the suite so that
+ * printcap-reading is consistent across the entire family.
+ */
+int
+getprintcap(const char *printer, struct printer *pp)
+{
+ int status;
+ char *XXX;
+ char *bp;
+
+ /*
+ * A bug in the declaration of cgetent(3) means that we have
+ * to hide the constness of its third argument.
+ */
+ XXX = (char *)printer;
+ if ((status = cgetent(&bp, printcapdb, XXX)) < 0)
+ return status;
+ status = getprintcap_int(bp, pp);
+ free(bp);
+ return status;
+}
+
+/*
+ * Map the status values returned by cgetfirst/cgetnext into those
+ * used by cgetent, returning truth if there are more records to
+ * examine. This points out what is arguably a bug in the cget*
+ * interface (or at least a nasty wart).
+ */
+static int
+firstnextmap(int *status)
+{
+ switch (*status) {
+ case 0:
+ return 0;
+ case 1:
+ *status = 0;
+ return 1;
+ case 2:
+ *status = 1;
+ return 1;
+ case -1:
+ *status = -2;
+ return 0;
+ case -2:
+ *status = -3;
+ return 1;
+ default:
+ return 0;
+ }
+}
+
+/*
+ * Scan through the database of printers using cgetfirst/cgetnext.
+ * Return false of error or end-of-database; else true.
+ */
+int
+firstprinter(struct printer *pp, int *error)
+{
+ int status;
+ char *bp;
+
+ init_printer(pp);
+ status = cgetfirst(&bp, printcapdb);
+ if (firstnextmap(&status) == 0) {
+ if (error)
+ *error = status;
+ return 0;
+ }
+ if (error)
+ *error = status;
+ status = getprintcap_int(bp, pp);
+ free(bp);
+ if (error && status)
+ *error = status;
+ return 1;
+}
+
+int
+nextprinter(struct printer *pp, int *error)
+{
+ int status;
+ char *bp;
+
+ free_printer(pp);
+ status = cgetnext(&bp, printcapdb);
+ if (firstnextmap(&status) == 0) {
+ if (error)
+ *error = status;
+ return 0;
+ }
+ if (error)
+ *error = status;
+ status = getprintcap_int(bp, pp);
+ free(bp);
+ if (error && status)
+ *error = status;
+ return 1;
+}
+
+void
+lastprinter(void)
+{
+ cgetclose();
+}
+
+/*
+ * This must match the order of declaration of enum filter in lp.h.
+ */
+static const char *filters[] = {
+ "cf", "df", "gf", "if", "nf", "of", "rf", "tf", "vf"
+};
+
+static const char *longfilters[] = {
+ "filt.cifplot", "filt.dvi", "filt.plot", "filt.input", "filt.ditroff",
+ "filt.output", "filt.fortran", "filt.troff", "filt.raster"
+};
+
+/*
+ * Internal routine for both getprintcap() and nextprinter().
+ * Actually parse the printcap entry using cget* functions.
+ * Also attempt to figure out the canonical name of the printer
+ * and store a malloced copy of it in pp->printer.
+ */
+static int
+getprintcap_int(bp, pp)
+ char *bp;
+ struct printer *pp;
+{
+ enum lpd_filters filt;
+
+ if ((pp->printer = capdb_canonical_name(bp)) == 0)
+ return PCAPERR_OSERR;
+
+#define CHK(x) do {if ((x) == PCAPERR_OSERR) return PCAPERR_OSERR;}while(0)
+ CHK(capdb_getaltstr(bp, "af", "acct.file", 0, &pp->acct_file));
+ CHK(capdb_getaltnum(bp, "br", "tty.rate", 0, &pp->baud_rate));
+ CHK(capdb_getaltnum(bp, "ct", "remote.timeout", DEFTIMEOUT,
+ &pp->conn_timeout));
+ CHK(capdb_getaltnum(bp, "du", "daemon.user", DEFUID,
+ &pp->daemon_user));
+ CHK(capdb_getaltstr(bp, "ff", "job.formfeed", DEFFF, &pp->form_feed));
+ CHK(capdb_getaltstr(bp, "lf", "spool.log", _PATH_CONSOLE,
+ &pp->log_file));
+ CHK(capdb_getaltstr(bp, "lo", "spool.lock", DEFLOCK, &pp->lock_file));
+ CHK(capdb_getaltstr(bp, "lp", "tty.device", _PATH_DEFDEVLP, &pp->lp));
+ CHK(capdb_getaltnum(bp, "mc", "max.copies", DEFMAXCOPIES,
+ &pp->max_copies));
+ CHK(capdb_getaltstr(bp, "ms", "tty.mode", 0, &pp->mode_set));
+ CHK(capdb_getaltnum(bp, "mx", "max.blocks", DEFMX, &pp->max_blocks));
+ CHK(capdb_getaltnum(bp, "pc", "acct.price", 0, &pp->price100));
+ CHK(capdb_getaltnum(bp, "pl", "page.length", DEFLENGTH,
+ &pp->page_length));
+ CHK(capdb_getaltnum(bp, "pw", "page.width", DEFWIDTH,
+ &pp->page_width));
+ CHK(capdb_getaltnum(bp, "px", "page.pwidth", 0, &pp->page_pwidth));
+ CHK(capdb_getaltnum(bp, "py", "page.plength", 0, &pp->page_plength));
+ CHK(capdb_getaltstr(bp, "rg", "daemon.restrictgrp", 0,
+ &pp->restrict_grp));
+ CHK(capdb_getaltstr(bp, "rm", "remote.host", 0, &pp->remote_host));
+ CHK(capdb_getaltstr(bp, "rp", "remote.queue", DEFLP,
+ &pp->remote_queue));
+ CHK(capdb_getaltstr(bp, "sd", "spool.dir", _PATH_DEFSPOOL,
+ &pp->spool_dir));
+ CHK(capdb_getaltstr(bp, "st", "spool.status", DEFSTAT,
+ &pp->status_file));
+ CHK(capdb_getaltstr(bp, "tr", "job.trailer", 0, &pp->trailer));
+
+ pp->restricted = capdb_getaltlog(bp, "rs", "daemon.restricted");
+ pp->short_banner = capdb_getaltlog(bp, "sb", "banner.short");
+ pp->no_copies = capdb_getaltlog(bp, "sc", "job.no_copies");
+ pp->no_formfeed = capdb_getaltlog(bp, "sf", "job.no_formfeed");
+ pp->no_header = capdb_getaltlog(bp, "sh", "banner.disable");
+ pp->header_last = capdb_getaltlog(bp, "hl", "banner.last");
+ pp->rw = capdb_getaltlog(bp, "rw", "tty.rw");
+ pp->tof = capdb_getaltlog(bp, "fo", "job.topofform");
+
+ /*
+ * Filters:
+ */
+ for (filt = 0; filt < LPF_COUNT; filt++) {
+ CHK(capdb_getaltstr(bp, filters[filt], longfilters[filt], 0,
+ &pp->filters[filt]));
+ }
+
+ return 0;
+}
+
+/*
+ * Decode the error codes returned by cgetent() using the names we
+ * made up for them from "lp.h".
+ * This would have been much better done with Common Error, >sigh<.
+ * Perhaps this can be fixed in the next incarnation of cget*.
+ */
+const char *
+pcaperr(int error)
+{
+ switch(error) {
+ case PCAPERR_TCOPEN:
+ return "unresolved tc= expansion";
+ case PCAPERR_SUCCESS:
+ return "no error";
+ case PCAPERR_NOTFOUND:
+ return "printer not found";
+ case PCAPERR_OSERR:
+ return strerror(errno);
+ case PCAPERR_TCLOOP:
+ return "loop detected in tc= expansion";
+ default:
+ return "unknown printcap error";
+ }
+}
+
+/*
+ * Initialize a `struct printer' to contain values harmless to
+ * the other routines in liblpr.
+ */
+void
+init_printer(struct printer *pp)
+{
+ static struct printer zero;
+ *pp = zero;
+}
+
+/*
+ * Free the dynamically-allocated strings in a `struct printer'.
+ * Idempotent.
+ */
+void
+free_printer(struct printer *pp)
+{
+ enum lpd_filters filt;
+#define cfree(x) do { if (x) free(x); } while(0)
+ cfree(pp->printer);
+ cfree(pp->acct_file);
+ for (filt = 0; filt < LPF_COUNT; filt++)
+ cfree(pp->filters[filt]);
+ cfree(pp->form_feed);
+ cfree(pp->log_file);
+ cfree(pp->lock_file);
+ cfree(pp->lp);
+ cfree(pp->restrict_grp);
+ cfree(pp->remote_host);
+ cfree(pp->remote_queue);
+ cfree(pp->spool_dir);
+ cfree(pp->status_file);
+ cfree(pp->trailer);
+ cfree(pp->mode_set);
+
+ init_printer(pp);
+}
+
+
+/*
+ * The following routines are part of what would be a sensible library
+ * interface to capability databases. Maybe someday this will become
+ * the default.
+ */
+
+/*
+ * It provides similar functionality to cgetstr(),
+ * except that it provides for both a long and a short
+ * capability name and allows for a default to be specified.
+ */
+static int
+capdb_getaltstr(char *bp, const char *shrt, const char *lng,
+ const char *dflt, char **result)
+{
+ int status;
+
+ status = cgetstr(bp, (char *)/*XXX*/lng, result);
+ if (status >= 0 || status == PCAPERR_OSERR)
+ return status;
+ status = cgetstr(bp, (char *)/*XXX*/shrt, result);
+ if (status >= 0 || status == PCAPERR_OSERR)
+ return status;
+ if (dflt) {
+ *result = strdup(dflt);
+ if (*result == 0)
+ return PCAPERR_OSERR;
+ return strlen(*result);
+ }
+ return PCAPERR_NOTFOUND;
+}
+
+/*
+ * The same, only for integers.
+ */
+static int
+capdb_getaltnum(char *bp, const char *shrt, const char *lng, long dflt,
+ long *result)
+{
+ int status;
+
+ status = cgetnum(bp, (char *)/*XXX*/lng, result);
+ if (status >= 0)
+ return status;
+ status = cgetnum(bp, (char *)/*XXX*/shrt, result);
+ if (status >= 0)
+ return status;
+ *result = dflt;
+ return 0;
+}
+
+/*
+ * Likewise for logical values. There's no need for a default parameter
+ * because the default is always false.
+ */
+static int
+capdb_getaltlog(char *bp, const char *shrt, const char *lng)
+{
+ if (cgetcap(bp, (char *)/*XXX*/lng, ':'))
+ return 1;
+ if (cgetcap(bp, (char *)/*XXX*/shrt, ':'))
+ return 1;
+ return 0;
+}
+
+/*
+ * Also should be a part of a better cget* library.
+ * Given a capdb entry, attempt to figure out what its canonical name
+ * is, and return a malloced copy of it. The canonical name is
+ * considered to be the first one listed.
+ */
+static char *
+capdb_canonical_name(const char *bp)
+{
+ char *retval;
+ const char *nameend;
+
+ nameend = strpbrk(bp, "|:");
+ if (nameend == 0)
+ nameend = bp + 1;
+ if ((retval = malloc(nameend - bp + 1)) != 0) {
+ retval[0] = '\0';
+ strncat(retval, bp, nameend - bp);
+ }
+ return retval;
+}
+
+
diff --git a/usr.sbin/lpr/common_source/recvjob.c b/usr.sbin/lpr/common_source/recvjob.c
index 0a10e49..6b1c8b0 100644
--- a/usr.sbin/lpr/common_source/recvjob.c
+++ b/usr.sbin/lpr/common_source/recvjob.c
@@ -43,7 +43,7 @@ static const char copyright[] =
static char sccsid[] = "@(#)recvjob.c 8.2 (Berkeley) 4/27/95";
#endif
static const char rcsid[] =
- "$Id: recvjob.c,v 1.10 1997/09/24 06:47:55 charnier Exp $";
+ "$Id: recvjob.c,v 1.11 1997/10/06 03:58:48 imp Exp $";
#endif /* not lint */
/*
@@ -80,54 +80,56 @@ static int noresponse __P((void));
static void rcleanup __P((int));
static int read_number __P((char *));
static int readfile __P((char *, int));
-static int readjob __P((void));
+static int readjob __P((struct printer *pp));
void
-recvjob()
+recvjob(printer)
+ const char *printer;
{
struct stat stb;
int status;
+ struct printer myprinter, *pp = &myprinter;
/*
* Perform lookup for printer name or abbreviation
*/
- if ((status = cgetent(&bp, printcapdb, printer)) == -2)
+ status = getprintcap(printer, pp);
+ switch (status) {
+ case PCAPERR_OSERR:
frecverr("cannot open printer description file");
- else if (status == -1)
+ break;
+ case PCAPERR_NOTFOUND:
frecverr("unknown printer %s", printer);
- else if (status == -3)
- fatal("potential reference loop detected in printcap file");
+ break;
+ case PCAPERR_TCLOOP:
+ fatal(pp, "potential reference loop detected in printcap file");
+ default:
+ break;
+ }
- if (cgetstr(bp, "lf", &LF) == -1)
- LF = _PATH_CONSOLE;
- if (cgetstr(bp, "sd", &SD) == -1)
- SD = _PATH_DEFSPOOL;
- if (cgetstr(bp, "lo", &LO) == -1)
- LO = DEFLOCK;
-
(void) close(2); /* set up log file */
- if (open(LF, O_WRONLY|O_APPEND, 0664) < 0) {
- syslog(LOG_ERR, "%s: %m", LF);
+ if (open(pp->log_file, O_WRONLY|O_APPEND, 0664) < 0) {
+ syslog(LOG_ERR, "%s: %m", pp->log_file);
(void) open(_PATH_DEVNULL, O_WRONLY);
}
- if (chdir(SD) < 0)
- frecverr("%s: %s: %m", printer, SD);
- if (stat(LO, &stb) == 0) {
+ if (chdir(pp->spool_dir) < 0)
+ frecverr("%s: %s: %m", pp->printer, pp->spool_dir);
+ if (stat(pp->lock_file, &stb) == 0) {
if (stb.st_mode & 010) {
/* queue is disabled */
putchar('\1'); /* return error code */
exit(1);
}
- } else if (stat(SD, &stb) < 0)
- frecverr("%s: %s: %m", printer, SD);
+ } else if (stat(pp->spool_dir, &stb) < 0)
+ frecverr("%s: %s: %m", pp->printer, pp->spool_dir);
minfree = 2 * read_number("minfree"); /* scale KB to 512 blocks */
signal(SIGTERM, rcleanup);
signal(SIGPIPE, rcleanup);
- if (readjob())
- printjob();
+ if (readjob(pp))
+ printjob(pp);
}
/*
@@ -135,7 +137,8 @@ recvjob()
* Return the number of jobs successfully transfered.
*/
static int
-readjob()
+readjob(pp)
+ struct printer *pp;
{
register int size, nfiles;
register char *cp;
@@ -151,7 +154,7 @@ readjob()
if ((size = read(1, cp, 1)) != 1) {
if (size < 0)
frecverr("%s: lost connection",
- printer);
+ pp->printer);
return(nfiles);
}
} while (*cp++ != '\n' && (cp - line + 1) < sizeof(line));
diff --git a/usr.sbin/lpr/common_source/request.c b/usr.sbin/lpr/common_source/request.c
new file mode 100644
index 0000000..d3e3cdf
--- /dev/null
+++ b/usr.sbin/lpr/common_source/request.c
@@ -0,0 +1,80 @@
+/*
+ * Copyright 1997 Massachusetts Institute of Technology
+ *
+ * Permission to use, copy, modify, and distribute this software and
+ * its documentation for any purpose and without fee is hereby
+ * granted, provided that both the above copyright notice and this
+ * permission notice appear in all copies, that both the above
+ * copyright notice and this permission notice appear in all
+ * supporting documentation, and that the name of M.I.T. not be used
+ * in advertising or publicity pertaining to distribution of the
+ * software without specific, written prior permission. M.I.T. makes
+ * no representations about the suitability of this software for any
+ * purpose. It is provided "as is" without express or implied
+ * warranty.
+ *
+ * THIS SOFTWARE IS PROVIDED BY M.I.T. ``AS IS''. M.I.T. DISCLAIMS
+ * ALL EXPRESS OR IMPLIED WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT
+ * SHALL M.I.T. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+static const char copyright[] =
+ "Copyright (C) 1997, Massachusetts Institute of Technology\r\n";
+static const char rcsid[] =
+ "$Id$";
+
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include <stdlib.h>
+#include <unistd.h>
+
+#include <sys/param.h> /* needed for lp.h but not used here */
+#include <dirent.h> /* ditto */
+#include <stdio.h> /* ditto */
+#include "lp.h"
+#include "lp.local.h"
+
+void
+init_request(struct request *rp)
+{
+ static struct request zero;
+
+ *rp = zero;
+ TAILQ_INIT(&rp->users);
+ TAILQ_INIT(&rp->jobids);
+}
+
+void
+free_request(struct request *rp)
+{
+ struct req_user *ru;
+ struct req_jobid *rj;
+
+ if (rp->logname)
+ free(rp->logname);
+ if (rp->authname)
+ free(rp->authname);
+ if (rp->prettyname)
+ free(rp->prettyname);
+ if (rp->authinfo)
+ free(rp->authinfo);
+ while ((ru = rp->users.tqh_first) != 0) {
+ TAILQ_REMOVE(&rp->users, ru, ru_link);
+ free(ru);
+ }
+ while ((rj = rp->jobids.tqh_first) != 0) {
+ TAILQ_REMOVE(&rp->jobids, rj, rj_link);
+ free(rj);
+ }
+ init_request(rp);
+}
diff --git a/usr.sbin/lpr/common_source/rmjob.c b/usr.sbin/lpr/common_source/rmjob.c
index 256da3f..e2406b9 100644
--- a/usr.sbin/lpr/common_source/rmjob.c
+++ b/usr.sbin/lpr/common_source/rmjob.c
@@ -36,19 +36,25 @@
static char sccsid[] = "@(#)rmjob.c 8.2 (Berkeley) 4/28/95";
#endif
static const char rcsid[] =
- "$Id: rmjob.c,v 1.9 1997/09/24 06:47:31 charnier Exp $";
+ "$Id: rmjob.c,v 1.10 1997/10/14 16:00:37 joerg Exp $";
#endif /* not lint */
#include <sys/param.h>
+#include <sys/uio.h>
-#include <signal.h>
-#include <errno.h>
+#include <ctype.h>
#include <dirent.h>
-#include <unistd.h>
-#include <stdlib.h>
+#include <errno.h>
+#include <signal.h>
#include <stdio.h>
+#include <stdlib.h>
#include <string.h>
-#include <ctype.h>
+#define psignal foil_gcc_psignal
+#define sys_siglist foil_gcc_siglist
+#include <unistd.h>
+#undef psignal
+#undef sys_siglist
+
#include "lp.h"
#include "lp.local.h"
#include "pathnames.h"
@@ -71,32 +77,22 @@ static void alarmhandler __P((int));
static void do_unlink __P((char *));
void
-rmjob()
+rmjob(printer)
+ const char *printer;
{
register int i, nitems;
int assasinated = 0;
struct dirent **files;
char *cp;
+ struct printer myprinter, *pp = &myprinter;
- if ((i = cgetent(&bp, printcapdb, printer)) == -2)
- fatal("can't open printer description file");
- else if (i == -1)
- fatal("unknown printer");
- else if (i == -3)
- fatal("potential reference loop detected in printcap file");
- if (cgetstr(bp, "lp", &LP) < 0)
- LP = _PATH_DEFDEVLP;
- if (cgetstr(bp, "rp", &RP) < 0)
- RP = DEFLP;
- if (cgetstr(bp, "sd", &SD) < 0)
- SD = _PATH_DEFSPOOL;
- if (cgetstr(bp,"lo", &LO) < 0)
- LO = DEFLOCK;
- if (cgetnum(bp, "ct", &CT) < 0)
- CT = DEFTIMEOUT;
- cgetstr(bp, "rm", &RM);
- if ((cp = checkremote()))
+ init_printer(pp);
+ if ((i = getprintcap(printer, pp)) < 0)
+ fatal(pp, "getprintcap: %s", pcaperr(i));
+ if ((cp = checkremote(pp))) {
printf("Warning: %s\n", cp);
+ free(cp);
+ }
/*
* If the format was `lprm -' and the user isn't the super-user,
@@ -112,16 +108,16 @@ rmjob()
}
if (!strcmp(person, "-all")) {
if (from == host)
- fatal("The login name \"-all\" is reserved");
+ fatal(pp, "The login name \"-all\" is reserved");
all = 1; /* all those from 'from' */
person = root;
}
seteuid(euid);
- if (chdir(SD) < 0)
- fatal("cannot chdir to spool directory");
+ if (chdir(pp->spool_dir) < 0)
+ fatal(pp, "cannot chdir to spool directory");
if ((nitems = scandir(".", &files, iscf, NULL)) < 0)
- fatal("cannot access spool directory");
+ fatal(pp, "cannot access spool directory");
seteuid(uid);
if (nitems) {
@@ -130,25 +126,25 @@ rmjob()
* kill it if it is reading our file) then remove stuff
* (after which we have to restart the daemon).
*/
- if (lockchk(LO) && chk(current)) {
+ if (lockchk(pp, pp->lock_file) && chk(current)) {
seteuid(euid);
assasinated = kill(cur_daemon, SIGINT) == 0;
seteuid(uid);
if (!assasinated)
- fatal("cannot kill printer daemon");
+ fatal(pp, "cannot kill printer daemon");
}
/*
* process the files
*/
for (i = 0; i < nitems; i++)
- process(files[i]->d_name);
+ process(pp, files[i]->d_name);
}
- rmremote();
+ rmremote(pp);
/*
* Restart the printer daemon if it was killed
*/
- if (assasinated && !startdaemon(printer))
- fatal("cannot restart printer daemon\n");
+ if (assasinated && !startdaemon(pp))
+ fatal(pp, "cannot restart printer daemon\n");
exit(0);
}
@@ -158,7 +154,8 @@ rmjob()
* Return boolean indicating existence of a lock file.
*/
int
-lockchk(s)
+lockchk(pp, s)
+ struct printer *pp;
char *s;
{
register FILE *fp;
@@ -167,7 +164,7 @@ lockchk(s)
seteuid(euid);
if ((fp = fopen(s, "r")) == NULL) {
if (errno == EACCES)
- fatal("can't access lock file");
+ fatal(pp, "%s: %s", s, strerror(errno));
else
return(0);
}
@@ -197,7 +194,8 @@ lockchk(s)
* Process a control file.
*/
void
-process(file)
+process(pp, file)
+ const struct printer *pp;
char *file;
{
FILE *cfp;
@@ -206,7 +204,7 @@ process(file)
return;
seteuid(euid);
if ((cfp = fopen(file, "r")) == NULL)
- fatal("cannot open %s", file);
+ fatal(pp, "cannot open %s", file);
seteuid(uid);
while (getline(cfp)) {
switch (line[0]) {
@@ -315,14 +313,15 @@ isowner(owner, file)
* then try removing files on the remote machine.
*/
void
-rmremote()
+rmremote(pp)
+ const struct printer *pp;
{
- register char *cp;
- register int i, rem;
+ int i, rem, niov, totlen;
char buf[BUFSIZ];
void (*savealrm)(int);
+ struct iovec *iov;
- if (!remote)
+ if (!pp->remote)
return; /* not sending to a remote machine */
/*
@@ -331,34 +330,55 @@ rmremote()
*/
fflush(stdout);
- (void)snprintf(buf, sizeof(buf), "\5%s %s", RP, all ? "-all" : person);
- cp = buf;
- for (i = 0; i < users && cp-buf+1+strlen(user[i]) < sizeof(buf); i++) {
- cp += strlen(cp);
- *cp++ = ' ';
- strcpy(cp, user[i]);
+ /*
+ * Counting:
+ * 4 == "\5" + remote_queue + " " + person
+ * 2 * users == " " + user[i] for each user
+ * requests == asprintf results for each request
+ * 1 == "\n"
+ * Although laborious, doing it this way makes it possible for
+ * us to process requests of indeterminate length without
+ * applying an arbitrary limit. Arbitrary Limits Are Bad (tm).
+ */
+ niov = 4 + 2 * users + requests + 1;
+ iov = malloc(niov * sizeof *iov);
+ if (iov == 0)
+ fatal(pp, "out of memory");
+ iov[0].iov_base = "\5";
+ iov[1].iov_base = pp->remote_queue;
+ iov[2].iov_base = " ";
+ iov[3].iov_base = all ? "-all" : person;
+ for (i = 0; i < users; i++) {
+ iov[4 + 2 * i].iov_base = " ";
+ iov[4 + 2 * i + 1].iov_base = user[i];
}
- for (i = 0; i < requests && cp-buf+10 < sizeof(buf) - 1; i++) {
- cp += strlen(cp);
- (void) sprintf(cp, " %d", requ[i]);
+ for (i = 0; i < requests; i++) {
+ asprintf(&iov[4 + 2 * users + i].iov_base, " %d", requ[i]);
+ if (iov[4 + 2 * users + i].iov_base == 0)
+ fatal(pp, "out of memory");
}
- strcat(cp, "\n");
+ iov[4 + 2 * users + requests].iov_base = "\n";
+ for (totlen = i = 0; i < niov; i++)
+ totlen += (iov[i].iov_len = strlen(iov[i].iov_base));
+
savealrm = signal(SIGALRM, alarmhandler);
- alarm(CT);
- rem = getport(RM, 0);
+ alarm(pp->conn_timeout);
+ rem = getport(pp, pp->remote_host, 0);
(void)signal(SIGALRM, savealrm);
if (rem < 0) {
if (from != host)
printf("%s: ", host);
- printf("connection to %s is down\n", RM);
+ printf("connection to %s is down\n", pp->remote_host);
} else {
- i = strlen(buf);
- if (write(rem, buf, i) != i)
- fatal("Lost connection");
+ if (writev(rem, iov, niov) != totlen)
+ fatal(pp, "Lost connection");
while ((i = read(rem, buf, sizeof(buf))) > 0)
(void) fwrite(buf, 1, i, stdout);
(void) close(rem);
}
+ for (i = 0; i < requests; i++)
+ free(iov[4 + 2 * users + i].iov_base);
+ free(iov);
}
/*
@@ -373,6 +393,7 @@ iscf(d)
void
alarmhandler(signo)
+ int signo;
{
/* ignored */
}
diff --git a/usr.sbin/lpr/common_source/startdaemon.c b/usr.sbin/lpr/common_source/startdaemon.c
index 7f990b4..931a7ef 100644
--- a/usr.sbin/lpr/common_source/startdaemon.c
+++ b/usr.sbin/lpr/common_source/startdaemon.c
@@ -36,12 +36,13 @@
static char sccsid[] = "@(#)startdaemon.c 8.2 (Berkeley) 4/17/94";
#endif
static const char rcsid[] =
- "$Id$";
+ "$Id: startdaemon.c,v 1.6 1997/09/24 06:47:32 charnier Exp $";
#endif /* not lint */
#include <sys/param.h>
#include <sys/socket.h>
+#include <sys/uio.h>
#include <sys/un.h>
#include <dirent.h>
@@ -59,20 +60,20 @@ extern uid_t uid, euid;
*/
int
-startdaemon(printer)
- char *printer;
+startdaemon(pp)
+ const struct printer *pp;
{
struct sockaddr_un un;
register int s, n;
- char buf[BUFSIZ];
+ char c;
- s = socket(AF_UNIX, SOCK_STREAM, 0);
+ s = socket(PF_LOCAL, SOCK_STREAM, 0);
if (s < 0) {
warn("socket");
return(0);
}
memset(&un, 0, sizeof(un));
- un.sun_family = AF_UNIX;
+ un.sun_family = AF_LOCAL;
strcpy(un.sun_path, _PATH_SOCKETNAME);
#ifndef SUN_LEN
#define SUN_LEN(unp) (strlen((unp)->sun_path) + 2)
@@ -85,25 +86,25 @@ startdaemon(printer)
return(0);
}
seteuid(uid);
- if (snprintf(buf, sizeof(buf), "\1%s\n", printer) > sizeof(buf) - 1) {
- close(s);
- return (0);
- }
- n = strlen(buf);
- if (write(s, buf, n) != n) {
+
+ /*
+ * Avoid overruns without putting artificial limitations on
+ * the length.
+ */
+ if (writel(s, "\1", pp->printer, "\n", (char *)0) <= 0) {
warn("write");
(void) close(s);
return(0);
}
- if (read(s, buf, 1) == 1) {
- if (buf[0] == '\0') { /* everything is OK */
+ if (read(s, &c, 1) == 1) {
+ if (c == '\0') { /* everything is OK */
(void) close(s);
return(1);
}
- putchar(buf[0]);
+ putchar(c);
}
- while ((n = read(s, buf, sizeof(buf))) > 0)
- fwrite(buf, 1, n, stdout);
+ while ((n = read(s, &c, 1)) > 0)
+ putchar(c);
(void) close(s);
return(0);
}
OpenPOWER on IntegriCloud