summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--usr.sbin/lpr/Makefile5
-rw-r--r--usr.sbin/lpr/Makefile.inc3
-rw-r--r--usr.sbin/lpr/SMM.doc/Makefile9
-rw-r--r--usr.sbin/lpr/chkprintcap/Makefile10
-rw-r--r--usr.sbin/lpr/chkprintcap/chkprintcap.896
-rw-r--r--usr.sbin/lpr/chkprintcap/chkprintcap.c277
-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
-rw-r--r--usr.sbin/lpr/lp/Makefile2
-rw-r--r--usr.sbin/lpr/lpc/Makefile8
-rw-r--r--usr.sbin/lpr/lpc/cmds.c760
-rw-r--r--usr.sbin/lpr/lpc/cmdtab.c22
-rw-r--r--usr.sbin/lpr/lpc/extern.h19
-rw-r--r--usr.sbin/lpr/lpc/lpc.c15
-rw-r--r--usr.sbin/lpr/lpc/lpc.h3
-rw-r--r--usr.sbin/lpr/lpd/Makefile10
-rw-r--r--usr.sbin/lpr/lpd/extern.h12
-rw-r--r--usr.sbin/lpr/lpd/lpd.c202
-rw-r--r--usr.sbin/lpr/lpd/lpdchar.c4
-rw-r--r--usr.sbin/lpr/lpd/modes.c6
-rw-r--r--usr.sbin/lpr/lpd/printjob.c664
-rw-r--r--usr.sbin/lpr/lpd/recvjob.c53
-rw-r--r--usr.sbin/lpr/lpq/Makefile9
-rw-r--r--usr.sbin/lpr/lpq/lpq.c87
-rw-r--r--usr.sbin/lpr/lpr/Makefile8
-rw-r--r--usr.sbin/lpr/lpr/lpr.c163
-rw-r--r--usr.sbin/lpr/lprm/Makefile8
-rw-r--r--usr.sbin/lpr/lprm/lprm.c34
-rw-r--r--usr.sbin/lpr/pac/Makefile6
-rw-r--r--usr.sbin/lpr/pac/pac.c32
-rw-r--r--usr.sbin/lpr/runqueue/extern.h12
-rw-r--r--usr.sbin/lpr/runqueue/lpdchar.c4
-rw-r--r--usr.sbin/lpr/runqueue/modes.c6
-rw-r--r--usr.sbin/lpr/runqueue/printjob.c664
43 files changed, 2896 insertions, 1921 deletions
diff --git a/usr.sbin/lpr/Makefile b/usr.sbin/lpr/Makefile
index 4ea49c9..c7fc6c0 100644
--- a/usr.sbin/lpr/Makefile
+++ b/usr.sbin/lpr/Makefile
@@ -1,6 +1,7 @@
-# @(#)Makefile 8.1 (Berkeley) 6/6/93
+# $Id$
-SUBDIR= lp lpc lpd lpq lpr lprm lptest pac filters
+SUBDIR= common_source chkprintcap lp lpc lpd lpq lpr lprm lptest pac \
+ filters SMM.doc
.include <bsd.subdir.mk>
diff --git a/usr.sbin/lpr/Makefile.inc b/usr.sbin/lpr/Makefile.inc
new file mode 100644
index 0000000..a881e88
--- /dev/null
+++ b/usr.sbin/lpr/Makefile.inc
@@ -0,0 +1,3 @@
+# $Id$
+
+CWARNFLAGS= -Werror -Wall -Wnested-externs -Wmissing-prototypes
diff --git a/usr.sbin/lpr/SMM.doc/Makefile b/usr.sbin/lpr/SMM.doc/Makefile
index 1701c86..adf53f8 100644
--- a/usr.sbin/lpr/SMM.doc/Makefile
+++ b/usr.sbin/lpr/SMM.doc/Makefile
@@ -1,10 +1,11 @@
-# @(#)Makefile 8.1 (Berkeley) 6/8/93
+# From: @(#)Makefile 8.1 (Berkeley) 6/8/93
+# $Id: Makefile,v 1.3 1997/02/22 13:05:43 peter Exp $
-DIR= smm/07.lpd
+VOLUME= smm/07.lpd
SRCS= 0.t 1.t 2.t 3.t 4.t 5.t 6.t 7.t
MACROS= -ms
-paper.ps: ${SRCS}
- ${TBL} ${SRCS} | ${ROFF} > ${.TARGET}
+USE_TBL= yes
+SRCDIR= ${.CURDIR}
.include <bsd.doc.mk>
diff --git a/usr.sbin/lpr/chkprintcap/Makefile b/usr.sbin/lpr/chkprintcap/Makefile
new file mode 100644
index 0000000..9d6160c
--- /dev/null
+++ b/usr.sbin/lpr/chkprintcap/Makefile
@@ -0,0 +1,10 @@
+# $Id$
+
+PROG= chkprintcap
+MAN8= chkprintcap.8
+CFLAGS+=-I${.CURDIR}/../common_source -Wall -Werror
+.PATH: ${.CURDIR}/../common_source
+LDADD= -L${.OBJDIR}/../common_source -llpr
+
+.include "../../Makefile.inc"
+.include <bsd.prog.mk>
diff --git a/usr.sbin/lpr/chkprintcap/chkprintcap.8 b/usr.sbin/lpr/chkprintcap/chkprintcap.8
new file mode 100644
index 0000000..fce427e
--- /dev/null
+++ b/usr.sbin/lpr/chkprintcap/chkprintcap.8
@@ -0,0 +1,96 @@
+.\" 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.
+.\"
+.\" $Id$
+.Dd November 30, 1997
+.Dt CHKPRINTCAP 8
+.Os
+.Sh NAME
+.Nm chkprintcap
+.Nd check validity of entries in the print spooler database
+.Sh SYNOPSIS
+.Nm chkprintcap
+.Op Fl d
+.Op Fl f Ar printcap
+.Sh DESCRIPTION
+.Nm Chkprintcap
+scans a
+.Xr printcap 5
+database
+(named by the
+.Ar printcap
+argument, or by default
+.Pa /etc/printcap ) ,
+looking for entries which are invalid in one way or another.
+The following checks are currently implemented:
+.Bl -enum -offset indent
+.It
+.Sq Li tc=
+references were properly expanded
+.It
+.Sq Li tc=
+references did not form a loop
+.It
+No two printers share the same spool directory
+.Po
+.Sq Li sd=
+capability
+.Pc .
+.El
+.Pp
+.Nm Chkprintcap
+exits with a status equal to the number of errors encountered before
+processing stopped. (In some cases, processing can stop before the
+entire file is scanned.)
+.Pp
+If the
+.Fl d
+flag is given,
+.Nm chkprintcap
+will attempt to create any missing spool directories, giving them
+.Sq Li u=rwx,go=rx
+(0755) mode, group
+.Sq Li daemon ,
+and the owner specified by the
+.Sq Li du=
+capability in the database (default 1, which corresponds to user
+.Sq Li daemon ) .
+.Sh SEE ALSO
+.Xr lpr 1 ,
+.Xr printcap 5 ,
+.Xr lpd 8
+.Sh AUTHOR
+The
+.Nm chkprintcap
+command was written by
+.An Garrett A. Wollman Aq wollman@lcs.mit.edu .
+.Sh BUGS
+Not enough sanity-checking is done. At a minimum, the ownership and
+mode of the spool directories should also be checked. Other
+parameters whose value could cause
+.Xr lpd 8
+to fail should be diagnosed.
diff --git a/usr.sbin/lpr/chkprintcap/chkprintcap.c b/usr.sbin/lpr/chkprintcap/chkprintcap.c
new file mode 100644
index 0000000..cd9ab66
--- /dev/null
+++ b/usr.sbin/lpr/chkprintcap/chkprintcap.c
@@ -0,0 +1,277 @@
+/*
+ * 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/queue.h>
+#include <sys/stat.h>
+
+#include <err.h>
+#include <errno.h>
+#include <grp.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include <sys/param.h> /* needed for lp.h but not used here */
+#include <dirent.h> /* ditto */
+#include "lp.h"
+#include "lp.local.h"
+
+static void check_spool_dirs(void);
+static int interpret_error(const struct printer *pp, int error);
+static void make_spool_dir(const struct printer *pp);
+static void note_spool_dir(const struct printer *pp, const struct stat *st);
+static void usage(void) __dead2;
+
+static int problems; /* number of problems encountered */
+
+/*
+ * chkprintcap - check the printcap file for syntactic and semantic errors
+ * Returns the number of problems found.
+ */
+int
+main(int argc, char **argv)
+{
+ int c, error, makedirs, more;
+ struct printer myprinter, *pp;
+
+ makedirs = 0;
+ pp = &myprinter;
+
+ while ((c = getopt(argc, argv, "df:")) != -1) {
+ switch (c) {
+ case 'd':
+ makedirs = 1;
+ break;
+
+ case 'f':
+ setprintcap(optarg);
+ break;
+
+ default:
+ usage();
+ }
+ }
+
+ if (optind != argc)
+ usage();
+
+ more = firstprinter(pp, &error);
+ if (interpret_error(pp, error) && more)
+ goto next;
+
+ while (more) {
+ struct stat stab;
+
+ errno = 0;
+ if (stat(pp->spool_dir, &stab) < 0) {
+ if (errno == ENOENT && makedirs) {
+ make_spool_dir(pp);
+ } else {
+ problems++;
+ warn("%s: %s", pp->printer, pp->spool_dir);
+ }
+ } else {
+ note_spool_dir(pp, &stab);
+ }
+
+ /* Make other validity checks here... */
+
+next:
+ more = nextprinter(pp, &error);
+ if (interpret_error(pp, error) && more)
+ goto next;
+ }
+ check_spool_dirs();
+ return problems;
+}
+
+/*
+ * Interpret the error code. Returns 1 if we should skip to the next
+ * record (as this record is unlikely to make sense). If the problem
+ * is very severe, exit. Otherwise, return zero.
+ */
+static int
+interpret_error(const struct printer *pp, int error)
+{
+ switch(error) {
+ case PCAPERR_OSERR:
+ err(++problems, "reading printer database");
+ case PCAPERR_TCLOOP:
+ ++problems;
+ warnx("%s: loop detected in tc= expansion", pp->printer);
+ return 1;
+ case PCAPERR_TCOPEN:
+ warnx("%s: unresolved tc= expansion", pp->printer);
+ return 1;
+ case PCAPERR_SUCCESS:
+ break;
+ default:
+ errx(++problems, "unknown printcap library error %d", error);
+ }
+ return 0;
+}
+
+/*
+ * Keep the list of spool directories. Note that we don't whine
+ * until all spool directories are noted, so that all of the more serious
+ * problems are noted first. We keep the list sorted by st_dev and
+ * st_ino, so that the problem spool directories can be noted in
+ * a single loop.
+ */
+struct dirlist {
+ LIST_ENTRY(dirlist) link;
+ struct stat stab;
+ char *path;
+ char *printer;
+};
+
+static LIST_HEAD(, dirlist) dirlist;
+
+static int
+lessp(const struct dirlist *a, const struct dirlist *b)
+{
+ if (a->stab.st_dev == b->stab.st_dev)
+ return a->stab.st_ino < b->stab.st_ino;
+ return a->stab.st_dev < b->stab.st_dev;
+}
+
+static int
+equal(const struct dirlist *a, const struct dirlist *b)
+{
+ return ((a->stab.st_dev == b->stab.st_dev)
+ && (a->stab.st_ino == b->stab.st_ino));
+}
+
+static void
+note_spool_dir(const struct printer *pp, const struct stat *st)
+{
+ struct dirlist *dp, *dp2, *last;
+
+ dp = malloc(sizeof *dp);
+ if (dp == 0)
+ err(++problems, "malloc(%lu)", (u_long)sizeof *dp);
+
+ dp->stab = *st;
+ dp->printer = strdup(pp->printer);
+ if (dp->printer == 0)
+ err(++problems, "malloc(%lu)", strlen(pp->printer) + 1UL);
+ dp->path = strdup(pp->spool_dir);
+ if (dp->path == 0)
+ err(++problems, "malloc(%lu)", strlen(pp->spool_dir) + 1UL);
+
+ last = 0;
+ dp2 = dirlist.lh_first;
+ while (dp2 && lessp(dp, dp2)) {
+ last = dp2;
+ dp2 = dp2->link.le_next;
+ }
+
+ if (last) {
+ LIST_INSERT_AFTER(last, dp, link);
+ } else {
+ LIST_INSERT_HEAD(&dirlist, dp, link);
+ }
+}
+
+static void
+check_spool_dirs(void)
+{
+ struct dirlist *dp, *dp2;
+
+ for (dp = dirlist.lh_first; dp; dp = dp2) {
+ dp2 = dp->link.le_next;
+
+ if (dp2 != 0 && equal(dp, dp2)) {
+ ++problems;
+ if (strcmp(dp->path, dp2->path) == 0) {
+ warnx("%s and %s share the same spool, %s",
+ dp->printer, dp2->printer, dp->path);
+ } else {
+ warnx("%s (%s) and %s (%s) are the same "
+ "directory", dp->path, dp->printer,
+ dp2->path, dp2->printer);
+ }
+ continue;
+ }
+ /* Should probably check owners and modes here. */
+ }
+}
+
+#ifndef SPOOL_DIR_MODE
+#define SPOOL_DIR_MODE (S_IRUSR | S_IWUSR | S_IXUSR \
+ | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH)
+#endif
+
+static void
+make_spool_dir(const struct printer *pp)
+{
+ char *sd = pp->spool_dir;
+ struct group *gr;
+ struct stat stab;
+
+ if (mkdir(sd, S_IRUSR | S_IXUSR) < 0) {
+ problems++;
+ warn("%s: mkdir %s", pp->printer, sd);
+ return;
+ }
+ gr = getgrnam("daemon");
+ if (gr == 0)
+ errx(++problems, "cannot locate daemon group");
+
+ if (chown(sd, pp->daemon_user, gr->gr_gid) < 0) {
+ ++problems;
+ warn("%s: cannot change ownership to %ld:%ld", sd,
+ (long)pp->daemon_user, (long)gr->gr_gid);
+ return;
+ }
+
+ if (chmod(sd, SPOOL_DIR_MODE) < 0) {
+ ++problems;
+ warn("%s: cannot change mode to %lo", (long)SPOOL_DIR_MODE);
+ return;
+ }
+ if (stat(sd, &stab) < 0)
+ err(++problems, "stat: %s", sd);
+
+ note_spool_dir(pp, &stab);
+}
+
+static void
+usage(void)
+{
+ fprintf(stderr, "usage:\n\tchkprintcap [-d] [-f printcapfile]\n");
+ exit(1);
+}
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);
}
diff --git a/usr.sbin/lpr/lp/Makefile b/usr.sbin/lpr/lp/Makefile
index b23be95..cf0304e 100644
--- a/usr.sbin/lpr/lp/Makefile
+++ b/usr.sbin/lpr/lp/Makefile
@@ -1,4 +1,4 @@
-# @(#)Makefile 5.6 (Berkeley) 6/23/90
+# $Id$
BINDIR = /usr/bin
MAN1 = lp.1
diff --git a/usr.sbin/lpr/lpc/Makefile b/usr.sbin/lpr/lpc/Makefile
index 4aeeab7..8d1326e 100644
--- a/usr.sbin/lpr/lpc/Makefile
+++ b/usr.sbin/lpr/lpc/Makefile
@@ -1,12 +1,14 @@
-# @(#)Makefile 8.1 (Berkeley) 6/6/93
+# From: @(#)Makefile 8.1 (Berkeley) 6/6/93
+# $Id$
PROG= lpc
-CFLAGS+=-I${.CURDIR}/../common_source
+CFLAGS+=-I${.CURDIR}/../common_source ${CWARNFLAGS}
MAN8= lpc.8
-SRCS= lpc.c cmds.c cmdtab.c startdaemon.c common.c
+SRCS= lpc.c cmds.c cmdtab.c
BINGRP= daemon
BINMODE=2555
.PATH: ${.CURDIR}/../common_source
+LDADD= -L${.OBJDIR}/../common_source -llpr
.include "../../Makefile.inc"
.include <bsd.prog.mk>
diff --git a/usr.sbin/lpr/lpc/cmds.c b/usr.sbin/lpr/lpc/cmds.c
index 07ac45a..650ab00 100644
--- a/usr.sbin/lpr/lpc/cmds.c
+++ b/usr.sbin/lpr/lpc/cmds.c
@@ -33,13 +33,17 @@
*/
#ifndef lint
-static char copyright[] =
+static const char copyright[] =
"@(#) Copyright (c) 1983, 1993\n\
The Regents of the University of California. All rights reserved.\n";
#endif /* not lint */
#ifndef lint
+/*
static char sccsid[] = "@(#)cmds.c 8.2 (Berkeley) 4/28/95";
+*/
+static const char rcsid[] =
+ "$Id$";
#endif /* not lint */
/*
@@ -68,97 +72,121 @@ static char sccsid[] = "@(#)cmds.c 8.2 (Berkeley) 4/28/95";
extern uid_t uid, euid;
-static void abortpr __P((int));
-static void cleanpr __P((void));
-static void disablepr __P((void));
+static void abortpr __P((struct printer *, int));
static int doarg __P((char *));
static int doselect __P((struct dirent *));
-static void enablepr __P((void));
-static void prstat __P((void));
-static void putmsg __P((int, char **));
+static void putmsg __P((struct printer *, int, char **));
static int sortq __P((const void *, const void *));
-static void startpr __P((int));
-static void stoppr __P((void));
+static void startpr __P((struct printer *, int));
static int touch __P((struct queue *));
static void unlinkf __P((char *));
-static void upstat __P((char *));
+static void upstat __P((struct printer *, char *));
/*
- * kill an existing daemon and disable printing.
+ * generic framework for commands which operate on all or a specified
+ * set of printers
*/
void
-doabort(argc, argv)
+generic(doit, argc, argv)
+ void (*doit) __P((struct printer *));
int argc;
char *argv[];
{
- register int c, status;
- register char *cp1, *cp2;
- char prbuf[100];
+ int status, more;
+ struct printer myprinter, *pp = &myprinter;
if (argc == 1) {
- printf("Usage: abort {all | printer ...}\n");
- return;
- }
- if (argc == 2 && !strcmp(argv[1], "all")) {
- printer = prbuf;
- while (cgetnext(&bp, printcapdb) > 0) {
- cp1 = prbuf;
- cp2 = bp;
- while ((c = *cp2++) && c != '|' && c != ':' &&
- (cp1 - prbuf) < sizeof(prbuf))
- *cp1++ = c;
- *cp1 = '\0';
- abortpr(1);
+ printf("Usage: %s {all | printer ...}\n", argv[0]);
+ return;
+ }
+ if (argc == 2 && strcmp(argv[1], "all") == 0) {
+ more = firstprinter(pp, &status);
+ if (status)
+ goto looperr;
+ while (more) {
+ (*doit)(pp);
+ do {
+ more = nextprinter(pp, &status);
+looperr:
+ switch (status) {
+ case PCAPERR_TCOPEN:
+ printf("warning: %s: unresolved "
+ "tc= reference(s) ",
+ pp->printer);
+ case PCAPERR_SUCCESS:
+ break;
+ default:
+ fatal(pp, pcaperr(status));
+ }
+ } while (more && status);
}
return;
}
while (--argc) {
- printer = *++argv;
- if ((status = cgetent(&bp, printcapdb, printer)) == -2) {
- printf("cannot open printer description file\n");
+ ++argv;
+ init_printer(pp);
+ status = getprintcap(*argv, pp);
+ switch(status) {
+ default:
+ fatal(pp, pcaperr(status));
+ case PCAPERR_NOTFOUND:
+ printf("unknown printer %s\n", *argv);
continue;
- } else if (status == -1) {
- printf("unknown printer %s\n", printer);
- continue;
- } else if (status == -3)
- fatal("potential reference loop detected in printcap file");
- abortpr(1);
+ case PCAPERR_TCOPEN:
+ printf("warning: %s: unresolved tc= reference(s)\n",
+ *argv);
+ break;
+ case PCAPERR_SUCCESS:
+ break;
+ }
+ (*doit)(pp);
}
}
+/*
+ * kill an existing daemon and disable printing.
+ */
+void
+doabort(pp)
+ struct printer *pp;
+{
+ abortpr(pp, 1);
+}
+
static void
-abortpr(dis)
+abortpr(pp, dis)
+ struct printer *pp;
int dis;
{
register FILE *fp;
struct stat stbuf;
int pid, fd;
+ char lf[MAXPATHLEN];
- if (cgetstr(bp, "sd", &SD) == -1)
- SD = _PATH_DEFSPOOL;
- if (cgetstr(bp, "lo", &LO) == -1)
- LO = DEFLOCK;
- (void) snprintf(line, sizeof(line), "%s/%s", SD, LO);
- printf("%s:\n", printer);
+ lock_file_name(pp, lf, sizeof lf);
+ printf("%s:\n", pp->printer);
/*
* Turn on the owner execute bit of the lock file to disable printing.
*/
if (dis) {
seteuid(euid);
- if (stat(line, &stbuf) >= 0) {
- if (chmod(line, (stbuf.st_mode & 0777) | 0100) < 0)
- printf("\tcannot disable printing\n");
+ if (stat(lf, &stbuf) >= 0) {
+ if (chmod(lf, stbuf.st_mode | LFM_PRINT_DIS) < 0)
+ printf("\tcannot disable printing: %s\n",
+ strerror(errno));
else {
- upstat("printing disabled\n");
+ upstat(pp, "printing disabled\n");
printf("\tprinting disabled\n");
}
} else if (errno == ENOENT) {
- if ((fd = open(line, O_WRONLY|O_CREAT, 0760)) < 0)
- printf("\tcannot create lock file\n");
+ if ((fd = open(lf, O_WRONLY|O_CREAT,
+ LOCK_FILE_MODE | LFM_PRINT_DIS)) < 0)
+ printf("\tcannot create lock file: %s\n",
+ strerror(errno));
else {
(void) close(fd);
- upstat("printing disabled\n");
+ upstat(pp, "printing disabled\n");
printf("\tprinting disabled\n");
printf("\tno daemon to abort\n");
}
@@ -171,7 +199,7 @@ abortpr(dis)
/*
* Kill the current daemon to stop printing now.
*/
- if ((fp = fopen(line, "r")) == NULL) {
+ if ((fp = fopen(lf, "r")) == NULL) {
printf("\tcannot open lock file\n");
goto out;
}
@@ -196,19 +224,18 @@ out:
* Write a message into the status file.
*/
static void
-upstat(msg)
+upstat(pp, msg)
+ struct printer *pp;
char *msg;
{
register int fd;
char statfile[MAXPATHLEN];
- if (cgetstr(bp, "st", &ST) == -1)
- ST = DEFSTAT;
- (void) snprintf(statfile, sizeof(statfile), "%s/%s", SD, ST);
+ status_file_name(pp, statfile, sizeof statfile);
umask(0);
- fd = open(statfile, O_WRONLY|O_CREAT, 0664);
- if (fd < 0 || flock(fd, LOCK_EX) < 0) {
- printf("\tcannot create status file\n");
+ fd = open(statfile, O_WRONLY|O_CREAT|O_EXLOCK, STAT_FILE_MODE);
+ if (fd < 0) {
+ printf("\tcannot create status file: %s\n", strerror(errno));
return;
}
(void) ftruncate(fd, 0);
@@ -219,50 +246,6 @@ upstat(msg)
(void) close(fd);
}
-/*
- * Remove all spool files and temporaries from the spooling area.
- */
-void
-clean(argc, argv)
- int argc;
- char *argv[];
-{
- register int c, status;
- register char *cp1, *cp2;
- char prbuf[100];
-
- if (argc == 1) {
- printf("Usage: clean {all | printer ...}\n");
- return;
- }
- if (argc == 2 && !strcmp(argv[1], "all")) {
- printer = prbuf;
- while (cgetnext(&bp, printcapdb) > 0) {
- cp1 = prbuf;
- cp2 = bp;
- while ((c = *cp2++) && c != '|' && c != ':' &&
- (cp1 - prbuf) < sizeof(prbuf))
- *cp1++ = c;
- *cp1 = '\0';
- cleanpr();
- }
- return;
- }
- while (--argc) {
- printer = *++argv;
- if ((status = cgetent(&bp, printcapdb, printer)) == -2) {
- printf("cannot open printer description file\n");
- continue;
- } else if (status == -1) {
- printf("unknown printer %s\n", printer);
- continue;
- } else if (status == -3)
- fatal("potential reference loop detected in printcap file");
-
- cleanpr();
- }
-}
-
static int
doselect(d)
struct dirent *d;
@@ -301,26 +284,31 @@ sortq(a, b)
}
/*
+ * Remove all spool files and temporaries from the spooling area.
+ * Or, perhaps:
* Remove incomplete jobs from spooling area.
*/
-static void
-cleanpr()
+void
+clean(pp)
+ struct printer *pp;
{
register int i, n;
register char *cp, *cp1, *lp;
struct dirent **queue;
int nitems;
- if (cgetstr(bp, "sd", &SD) == -1)
- SD = _PATH_DEFSPOOL;
- printf("%s:\n", printer);
+ printf("%s:\n", pp->printer);
- for (lp = line, cp = SD; (lp - line) < sizeof(line) && (*lp++ = *cp++);)
- ;
+ lp = line;
+ cp = pp->spool_dir;
+ while (lp < &line[sizeof(line) - 1]) {
+ if ((*lp++ = *cp++) == 0)
+ break;
+ }
lp[-1] = '/';
seteuid(euid);
- nitems = scandir(SD, &queue, doselect, sortq);
+ nitems = scandir(pp->spool_dir, &queue, doselect, sortq);
seteuid(uid);
if (nitems < 0) {
printf("\tcannot examine spool directory\n");
@@ -374,64 +362,21 @@ unlinkf(name)
* Enable queuing to the printer (allow lpr's).
*/
void
-enable(argc, argv)
- int argc;
- char *argv[];
-{
- register int c, status;
- register char *cp1, *cp2;
- char prbuf[100];
-
- if (argc == 1) {
- printf("Usage: enable {all | printer ...}\n");
- return;
- }
- if (argc == 2 && !strcmp(argv[1], "all")) {
- printer = prbuf;
- while (cgetnext(&bp, printcapdb) > 0) {
- cp1 = prbuf;
- cp2 = bp;
- while ((c = *cp2++) && c != '|' && c != ':' &&
- (cp1 - prbuf) < sizeof(prbuf))
- *cp1++ = c;
- *cp1 = '\0';
- enablepr();
- }
- return;
- }
- while (--argc) {
- printer = *++argv;
- if ((status = cgetent(&bp, printcapdb, printer)) == -2) {
- printf("cannot open printer description file\n");
- continue;
- } else if (status == -1) {
- printf("unknown printer %s\n", printer);
- continue;
- } else if (status == -3)
- fatal("potential reference loop detected in printcap file");
-
- enablepr();
- }
-}
-
-static void
-enablepr()
+enable(pp)
+ struct printer *pp;
{
struct stat stbuf;
+ char lf[MAXPATHLEN];
- if (cgetstr(bp, "sd", &SD) == -1)
- SD = _PATH_DEFSPOOL;
- if (cgetstr(bp, "lo", &LO) == -1)
- LO = DEFLOCK;
- (void) snprintf(line, sizeof(line), "%s/%s", SD, LO);
- printf("%s:\n", printer);
+ lock_file_name(pp, lf, sizeof lf);
+ printf("%s:\n", pp->printer);
/*
* Turn off the group execute bit of the lock file to enable queuing.
*/
seteuid(euid);
- if (stat(line, &stbuf) >= 0) {
- if (chmod(line, stbuf.st_mode & 0767) < 0)
+ if (stat(lf, &stbuf) >= 0) {
+ if (chmod(lf, stbuf.st_mode & ~LFM_QUEUE_DIS) < 0)
printf("\tcannot enable queuing\n");
else
printf("\tqueuing enabled\n");
@@ -443,70 +388,30 @@ enablepr()
* Disable queuing.
*/
void
-disable(argc, argv)
- int argc;
- char *argv[];
-{
- register int c, status;
- register char *cp1, *cp2;
- char prbuf[100];
-
- if (argc == 1) {
- printf("Usage: disable {all | printer ...}\n");
- return;
- }
- if (argc == 2 && !strcmp(argv[1], "all")) {
- printer = prbuf;
- while (cgetnext(&bp, printcapdb) > 0) {
- cp1 = prbuf;
- cp2 = bp;
- while ((c = *cp2++) && c != '|' && c != ':' &&
- (cp1 - prbuf) < sizeof(prbuf))
- *cp1++ = c;
- *cp1 = '\0';
- disablepr();
- }
- return;
- }
- while (--argc) {
- printer = *++argv;
- if ((status = cgetent(&bp, printcapdb, printer)) == -2) {
- printf("cannot open printer description file\n");
- continue;
- } else if (status == -1) {
- printf("unknown printer %s\n", printer);
- continue;
- } else if (status == -3)
- fatal("potential reference loop detected in printcap file");
-
- disablepr();
- }
-}
-
-static void
-disablepr()
+disable(pp)
+ struct printer *pp;
{
register int fd;
struct stat stbuf;
-
- if (cgetstr(bp, "sd", &SD) == -1)
- SD = _PATH_DEFSPOOL;
- if (cgetstr(bp, "lo", &LO) == -1)
- LO = DEFLOCK;
- (void) snprintf(line, sizeof(line), "%s/%s", SD, LO);
- printf("%s:\n", printer);
+ char lf[MAXPATHLEN];
+
+ lock_file_name(pp, lf, sizeof lf);
+ printf("%s:\n", pp->printer);
/*
* Turn on the group execute bit of the lock file to disable queuing.
*/
seteuid(euid);
- if (stat(line, &stbuf) >= 0) {
- if (chmod(line, (stbuf.st_mode & 0777) | 010) < 0)
- printf("\tcannot disable queuing\n");
+ if (stat(lf, &stbuf) >= 0) {
+ if (chmod(lf, stbuf.st_mode | LFM_QUEUE_DIS) < 0)
+ printf("\tcannot disable queuing: %s\n",
+ strerror(errno));
else
printf("\tqueuing disabled\n");
} else if (errno == ENOENT) {
- if ((fd = open(line, O_WRONLY|O_CREAT, 0670)) < 0)
- printf("\tcannot create lock file\n");
+ if ((fd = open(lf, O_WRONLY|O_CREAT,
+ LOCK_FILE_MODE | LFM_QUEUE_DIS)) < 0)
+ printf("\tcannot create lock file: %s\n",
+ strerror(errno));
else {
(void) close(fd);
printf("\tqueuing disabled\n");
@@ -525,71 +430,83 @@ down(argc, argv)
int argc;
char *argv[];
{
- register int c, status;
- register char *cp1, *cp2;
- char prbuf[100];
+ int status, more;
+ struct printer myprinter, *pp = &myprinter;
if (argc == 1) {
printf("Usage: down {all | printer} [message ...]\n");
return;
}
if (!strcmp(argv[1], "all")) {
- printer = prbuf;
- while (cgetnext(&bp, printcapdb) > 0) {
- cp1 = prbuf;
- cp2 = bp;
- while ((c = *cp2++) && c != '|' && c != ':' &&
- (cp1 - prbuf) < sizeof(prbuf))
- *cp1++ = c;
- *cp1 = '\0';
- putmsg(argc - 2, argv + 2);
+ more = firstprinter(pp, &status);
+ if (status)
+ goto looperr;
+ while (more) {
+ putmsg(pp, argc - 2, argv + 2);
+ do {
+ more = nextprinter(pp, &status);
+looperr:
+ switch (status) {
+ case PCAPERR_TCOPEN:
+ printf("warning: %s: unresolved "
+ "tc= reference(s) ",
+ pp->printer);
+ case PCAPERR_SUCCESS:
+ break;
+ default:
+ fatal(pp, pcaperr(status));
+ }
+ } while (more && status);
}
return;
}
- printer = argv[1];
- if ((status = cgetent(&bp, printcapdb, printer)) == -2) {
- printf("cannot open printer description file\n");
- return;
- } else if (status == -1) {
- printf("unknown printer %s\n", printer);
+ init_printer(pp);
+ status = getprintcap(argv[1], pp);
+ switch(status) {
+ default:
+ fatal(pp, pcaperr(status));
+ case PCAPERR_NOTFOUND:
+ printf("unknown printer %s\n", argv[1]);
return;
- } else if (status == -3)
- fatal("potential reference loop detected in printcap file");
-
- putmsg(argc - 2, argv + 2);
+ case PCAPERR_TCOPEN:
+ printf("warning: %s: unresolved tc= reference(s)", argv[1]);
+ break;
+ case PCAPERR_SUCCESS:
+ break;
+ }
+ putmsg(pp, argc - 2, argv + 2);
}
static void
-putmsg(argc, argv)
+putmsg(pp, argc, argv)
+ struct printer *pp;
int argc;
char **argv;
{
register int fd;
register char *cp1, *cp2;
char buf[1024];
+ char file[MAXPATHLEN];
struct stat stbuf;
- if (cgetstr(bp, "sd", &SD) == -1)
- SD = _PATH_DEFSPOOL;
- if (cgetstr(bp, "lo", &LO) == -1)
- LO = DEFLOCK;
- if (cgetstr(bp, "st", &ST) == -1)
- ST = DEFSTAT;
- printf("%s:\n", printer);
+ printf("%s:\n", pp->printer);
/*
- * Turn on the group execute bit of the lock file to disable queuing and
+ * Turn on the group execute bit of the lock file to disable queuing;
* turn on the owner execute bit of the lock file to disable printing.
*/
- (void) snprintf(line, sizeof(line), "%s/%s", SD, LO);
+ lock_file_name(pp, file, sizeof file);
seteuid(euid);
- if (stat(line, &stbuf) >= 0) {
- if (chmod(line, (stbuf.st_mode & 0777) | 0110) < 0)
- printf("\tcannot disable queuing\n");
+ if (stat(file, &stbuf) >= 0) {
+ if (chmod(file, stbuf.st_mode|LFM_PRINT_DIS|LFM_QUEUE_DIS) < 0)
+ printf("\tcannot disable queuing: %s\n",
+ strerror(errno));
else
printf("\tprinter and queuing disabled\n");
} else if (errno == ENOENT) {
- if ((fd = open(line, O_WRONLY|O_CREAT, 0770)) < 0)
- printf("\tcannot create lock file\n");
+ if ((fd = open(file, O_WRONLY|O_CREAT,
+ LOCK_FILE_MODE|LFM_PRINT_DIS|LFM_QUEUE_DIS)) < 0)
+ printf("\tcannot create lock file: %s\n",
+ strerror(errno));
else {
(void) close(fd);
printf("\tprinter and queuing disabled\n");
@@ -601,10 +518,10 @@ putmsg(argc, argv)
/*
* Write the message into the status file.
*/
- (void) snprintf(line, sizeof(line), "%s/%s", SD, ST);
- fd = open(line, O_WRONLY|O_CREAT, 0664);
- if (fd < 0 || flock(fd, LOCK_EX) < 0) {
- printf("\tcannot create status file\n");
+ status_file_name(pp, file, sizeof file);
+ fd = open(file, O_WRONLY|O_CREAT|O_EXLOCK, STAT_FILE_MODE);
+ if (fd < 0) {
+ printf("\tcannot create status file: %s\n", strerror(errno));
seteuid(uid);
return;
}
@@ -643,116 +560,47 @@ quit(argc, argv)
* Kill and restart the daemon.
*/
void
-restart(argc, argv)
- int argc;
- char *argv[];
+restart(pp)
+ struct printer *pp;
{
- register int c, status;
- register char *cp1, *cp2;
- char prbuf[100];
-
- if (argc == 1) {
- printf("Usage: restart {all | printer ...}\n");
- return;
- }
- if (argc == 2 && !strcmp(argv[1], "all")) {
- printer = prbuf;
- while (cgetnext(&bp, printcapdb) > 0) {
- cp1 = prbuf;
- cp2 = bp;
- while ((c = *cp2++) && c != '|' && c != ':' &&
- (cp1 - prbuf) < sizeof(prbuf))
- *cp1++ = c;
- *cp1 = '\0';
- abortpr(0);
- startpr(0);
- }
- return;
- }
- while (--argc) {
- printer = *++argv;
- if ((status = cgetent(&bp, printcapdb, printer)) == -2) {
- printf("cannot open printer description file\n");
- continue;
- } else if (status == -1) {
- printf("unknown printer %s\n", printer);
- continue;
- } else if (status == -3)
- fatal("potential reference loop detected in printcap file");
-
- abortpr(0);
- startpr(0);
- }
+ abortpr(pp, 0);
+ startpr(pp, 0);
}
/*
* Enable printing on the specified printer and startup the daemon.
*/
void
-startcmd(argc, argv)
- int argc;
- char *argv[];
+startcmd(pp)
+ struct printer *pp;
{
- register int c, status;
- register char *cp1, *cp2;
- char prbuf[100];
-
- if (argc == 1) {
- printf("Usage: start {all | printer ...}\n");
- return;
- }
- if (argc == 2 && !strcmp(argv[1], "all")) {
- printer = prbuf;
- while (cgetnext(&bp, printcapdb) > 0) {
- cp1 = prbuf;
- cp2 = bp;
- while ((c = *cp2++) && c != '|' && c != ':' &&
- (cp1 - prbuf) < sizeof(prbuf))
- *cp1++ = c;
- *cp1 = '\0';
- startpr(1);
- }
- return;
- }
- while (--argc) {
- printer = *++argv;
- if ((status = cgetent(&bp, printcapdb, printer)) == -2) {
- printf("cannot open printer description file\n");
- continue;
- } else if (status == -1) {
- printf("unknown printer %s\n", printer);
- continue;
- } else if (status == -3)
- fatal("potential reference loop detected in printcap file");
-
- startpr(1);
- }
+ startpr(pp, 1);
}
static void
-startpr(enable)
+startpr(pp, enable)
+ struct printer *pp;
int enable;
{
struct stat stbuf;
+ char lf[MAXPATHLEN];
- if (cgetstr(bp, "sd", &SD) == -1)
- SD = _PATH_DEFSPOOL;
- if (cgetstr(bp, "lo", &LO) == -1)
- LO = DEFLOCK;
- (void) snprintf(line, sizeof(line), "%s/%s", SD, LO);
- printf("%s:\n", printer);
+ lock_file_name(pp, lf, sizeof lf);
+ printf("%s:\n", pp->printer);
/*
* Turn off the owner execute bit of the lock file to enable printing.
*/
seteuid(euid);
- if (enable && stat(line, &stbuf) >= 0) {
- if (chmod(line, stbuf.st_mode & (enable==2 ? 0666 : 0677)) < 0)
+ if (enable && stat(lf, &stbuf) >= 0) {
+ mode_t bits = (enable == 2 ? 0
+ : (LFM_PRINT_DIS | LFM_QUEUE_DIS));
+ if (chmod(lf, stbuf.st_mode & (LOCK_FILE_MODE | bits)) < 0)
printf("\tcannot enable printing\n");
else
printf("\tprinting enabled\n");
}
- if (!startdaemon(printer))
+ if (!startdaemon(pp))
printf("\tcouldn't start daemon\n");
else
printf("\tdaemon started\n");
@@ -760,74 +608,32 @@ startpr(enable)
}
/*
- * Print the status of each queue listed or all the queues.
- */
-void
-status(argc, argv)
- int argc;
- char *argv[];
-{
- register int c, status;
- register char *cp1, *cp2;
- char prbuf[100];
-
- if (argc == 1 || argc == 2 && !strcmp(argv[1], "all")) {
- printer = prbuf;
- while (cgetnext(&bp, printcapdb) > 0) {
- cp1 = prbuf;
- cp2 = bp;
- while ((c = *cp2++) && c != '|' && c != ':' &&
- (cp1 - prbuf) < sizeof(prbuf))
- *cp1++ = c;
- *cp1 = '\0';
- prstat();
- }
- return;
- }
- while (--argc) {
- printer = *++argv;
- if ((status = cgetent(&bp, printcapdb, printer)) == -2) {
- printf("cannot open printer description file\n");
- continue;
- } else if (status == -1) {
- printf("unknown printer %s\n", printer);
- continue;
- } else if (status == -3)
- fatal("potential reference loop detected in printcap file");
-
- prstat();
- }
-}
-
-/*
* Print the status of the printer queue.
*/
-static void
-prstat()
+void
+status(pp)
+ struct printer *pp;
{
struct stat stbuf;
register int fd, i;
register struct dirent *dp;
DIR *dirp;
+ char file[MAXPATHLEN];
- if (cgetstr(bp, "sd", &SD) == -1)
- SD = _PATH_DEFSPOOL;
- if (cgetstr(bp, "lo", &LO) == -1)
- LO = DEFLOCK;
- if (cgetstr(bp, "st", &ST) == -1)
- ST = DEFSTAT;
- printf("%s:\n", printer);
- (void) snprintf(line, sizeof(line), "%s/%s", SD, LO);
- if (stat(line, &stbuf) >= 0) {
+ printf("%s:\n", pp->printer);
+ lock_file_name(pp, file, sizeof file);
+ if (stat(file, &stbuf) >= 0) {
printf("\tqueuing is %s\n",
- (stbuf.st_mode & 010) ? "disabled" : "enabled");
+ ((stbuf.st_mode & LFM_QUEUE_DIS) ? "disabled"
+ : "enabled"));
printf("\tprinting is %s\n",
- (stbuf.st_mode & 0100) ? "disabled" : "enabled");
+ ((stbuf.st_mode & LFM_PRINT_DIS) ? "disabled"
+ : "enabled"));
} else {
printf("\tqueuing is enabled\n");
printf("\tprinting is enabled\n");
}
- if ((dirp = opendir(SD)) == NULL) {
+ if ((dirp = opendir(pp->spool_dir)) == NULL) {
printf("\tcannot examine spool directory\n");
return;
}
@@ -838,12 +644,12 @@ prstat()
}
closedir(dirp);
if (i == 0)
- printf("\tno entries\n");
+ printf("\tno entries in spool area\n");
else if (i == 1)
printf("\t1 entry in spool area\n");
else
printf("\t%d entries in spool area\n", i);
- fd = open(line, O_RDONLY);
+ fd = open(file, O_RDONLY);
if (fd < 0 || flock(fd, LOCK_SH|LOCK_NB) == 0) {
(void) close(fd); /* unlocks as well */
printf("\tprinter idle\n");
@@ -851,10 +657,9 @@ prstat()
}
(void) close(fd);
/* print out the contents of the status file, if it exists */
- (void) snprintf(line, sizeof(line), "%s/%s", SD, ST);
- fd = open(line, O_RDONLY);
+ status_file_name(pp, file, sizeof file);
+ fd = open(file, O_RDONLY|O_SHLOCK);
if (fd >= 0) {
- (void) flock(fd, LOCK_SH);
(void) fstat(fd, &stbuf);
if (stbuf.st_size > 0) {
putchar('\t');
@@ -870,76 +675,36 @@ prstat()
* printing.
*/
void
-stop(argc, argv)
- int argc;
- char *argv[];
-{
- register int c, status;
- register char *cp1, *cp2;
- char prbuf[100];
-
- if (argc == 1) {
- printf("Usage: stop {all | printer ...}\n");
- return;
- }
- if (argc == 2 && !strcmp(argv[1], "all")) {
- printer = prbuf;
- while (cgetnext(&bp, printcapdb) > 0) {
- cp1 = prbuf;
- cp2 = bp;
- while ((c = *cp2++) && c != '|' && c != ':' &&
- (cp1 - prbuf) < sizeof(prbuf))
- *cp1++ = c;
- *cp1 = '\0';
- stoppr();
- }
- return;
- }
- while (--argc) {
- printer = *++argv;
- if ((status = cgetent(&bp, printcapdb, printer)) == -2) {
- printf("cannot open printer description file\n");
- continue;
- } else if (status == -1) {
- printf("unknown printer %s\n", printer);
- continue;
- } else if (status == -3)
- fatal("potential reference loop detected in printcap file");
-
- stoppr();
- }
-}
-
-static void
-stoppr()
+stop(pp)
+ struct printer *pp;
{
register int fd;
struct stat stbuf;
+ char lf[MAXPATHLEN];
- if (cgetstr(bp, "sd", &SD) == -1)
- SD = _PATH_DEFSPOOL;
- if (cgetstr(bp, "lo", &LO) == -1)
- LO = DEFLOCK;
- (void) snprintf(line, sizeof(line), "%s/%s", SD, LO);
- printf("%s:\n", printer);
+ lock_file_name(pp, lf, sizeof lf);
+ printf("%s:\n", pp->printer);
/*
* Turn on the owner execute bit of the lock file to disable printing.
*/
seteuid(euid);
- if (stat(line, &stbuf) >= 0) {
- if (chmod(line, (stbuf.st_mode & 0777) | 0100) < 0)
- printf("\tcannot disable printing\n");
+ if (stat(lf, &stbuf) >= 0) {
+ if (chmod(lf, stbuf.st_mode | LFM_PRINT_DIS) < 0)
+ printf("\tcannot disable printing: %s\n",
+ strerror(errno));
else {
- upstat("printing disabled\n");
+ upstat(pp, "printing disabled\n");
printf("\tprinting disabled\n");
}
} else if (errno == ENOENT) {
- if ((fd = open(line, O_WRONLY|O_CREAT, 0760)) < 0)
- printf("\tcannot create lock file\n");
+ if ((fd = open(lf, O_WRONLY|O_CREAT,
+ LOCK_FILE_MODE | LFM_PRINT_DIS)) < 0)
+ printf("\tcannot create lock file: %s\n",
+ strerror(errno));
else {
(void) close(fd);
- upstat("printing disabled\n");
+ upstat(pp, "printing disabled\n");
printf("\tprinting disabled\n");
}
} else
@@ -962,6 +727,7 @@ topq(argc, argv)
register int i;
struct stat stbuf;
int status, changed;
+ struct printer myprinter, *pp = &myprinter;
if (argc < 3) {
printf("Usage: topq printer [jobnum ...] [user ...]\n");
@@ -969,30 +735,30 @@ topq(argc, argv)
}
--argc;
- printer = *++argv;
- status = cgetent(&bp, printcapdb, printer);
- if (status == -2) {
- printf("cannot open printer description file\n");
- return;
- } else if (status == -1) {
- printf("%s: unknown printer\n", printer);
- return;
- } else if (status == -3)
- fatal("potential reference loop detected in printcap file");
-
- if (cgetstr(bp, "sd", &SD) == -1)
- SD = _PATH_DEFSPOOL;
- if (cgetstr(bp, "lo", &LO) == -1)
- LO = DEFLOCK;
- printf("%s:\n", printer);
+ ++argv;
+ init_printer(pp);
+ status = getprintcap(*argv, pp);
+ switch(status) {
+ default:
+ fatal(pp, pcaperr(status));
+ case PCAPERR_NOTFOUND:
+ printf("unknown printer %s\n", *argv);
+ return;
+ case PCAPERR_TCOPEN:
+ printf("warning: %s: unresolved tc= reference(s)", *argv);
+ break;
+ case PCAPERR_SUCCESS:
+ break;
+ }
+ printf("%s:\n", pp->printer);
seteuid(euid);
- if (chdir(SD) < 0) {
- printf("\tcannot chdir to %s\n", SD);
+ if (chdir(pp->spool_dir) < 0) {
+ printf("\tcannot chdir to %s\n", pp->spool_dir);
goto out;
}
seteuid(uid);
- nitems = getq(&queue);
+ nitems = getq(pp, &queue);
if (nitems == 0)
return;
changed = 0;
@@ -1016,8 +782,8 @@ topq(argc, argv)
* get lpd to rebuild the queue after the current job.
*/
seteuid(euid);
- if (changed && stat(LO, &stbuf) >= 0)
- (void) chmod(LO, (stbuf.st_mode & 0777) | 01);
+ if (changed && stat(pp->lock_file, &stbuf) >= 0)
+ (void) chmod(pp->lock_file, stbuf.st_mode | LFM_RESET_QUE);
out:
seteuid(uid);
@@ -1119,42 +885,8 @@ doarg(job)
* Enable everything and start printer (undo `down').
*/
void
-up(argc, argv)
- int argc;
- char *argv[];
+up(pp)
+ struct printer *pp;
{
- register int c, status;
- register char *cp1, *cp2;
- char prbuf[100];
-
- if (argc == 1) {
- printf("Usage: up {all | printer ...}\n");
- return;
- }
- if (argc == 2 && !strcmp(argv[1], "all")) {
- printer = prbuf;
- while (cgetnext(&bp, printcapdb) > 0) {
- cp1 = prbuf;
- cp2 = bp;
- while ((c = *cp2++) && c != '|' && c != ':' &&
- (cp1 - prbuf) < sizeof(prbuf))
- *cp1++ = c;
- *cp1 = '\0';
- startpr(2);
- }
- return;
- }
- while (--argc) {
- printer = *++argv;
- if ((status = cgetent(&bp, printcapdb, printer)) == -2) {
- printf("cannot open printer description file\n");
- continue;
- } else if (status == -1) {
- printf("unknown printer %s\n", printer);
- continue;
- } else if (status == -3)
- fatal("potential reference loop detected in printcap file");
-
- startpr(2);
- }
+ startpr(pp, 2);
}
diff --git a/usr.sbin/lpr/lpc/cmdtab.c b/usr.sbin/lpr/lpc/cmdtab.c
index 7619791..b4720a8 100644
--- a/usr.sbin/lpr/lpc/cmdtab.c
+++ b/usr.sbin/lpr/lpc/cmdtab.c
@@ -32,7 +32,11 @@
*/
#ifndef lint
+/*
static char sccsid[] = "@(#)cmdtab.c 8.1 (Berkeley) 6/6/93";
+*/
+static const char rcsid[] =
+ "$Id$";
#endif /* not lint */
#include <sys/cdefs.h>
@@ -58,20 +62,20 @@ char topqhelp[] = "put job at top of printer queue";
char uphelp[] = "enable everything and restart spooling daemon";
struct cmd cmdtab[] = {
- { "abort", aborthelp, doabort, 1 },
- { "clean", cleanhelp, clean, 1 },
- { "enable", enablehelp, enable, 1 },
+ { "abort", aborthelp, 0, 1, doabort },
+ { "clean", cleanhelp, 0, 1, clean },
+ { "enable", enablehelp, 0, 1, enable },
{ "exit", quithelp, quit, 0 },
- { "disable", disablehelp, disable, 1 },
+ { "disable", disablehelp, 0, 1, disable },
{ "down", downhelp, down, 1 },
{ "help", helphelp, help, 0 },
{ "quit", quithelp, quit, 0 },
- { "restart", restarthelp, restart, 0 },
- { "start", starthelp, startcmd, 1 },
- { "status", statushelp, status, 0 },
- { "stop", stophelp, stop, 1 },
+ { "restart", restarthelp, 0, 0, restart },
+ { "start", starthelp, 0, 1, startcmd },
+ { "status", statushelp, 0, 0, status },
+ { "stop", stophelp, 0, 1, stop },
{ "topq", topqhelp, topq, 1 },
- { "up", uphelp, up, 1 },
+ { "up", uphelp, 0, 1, up },
{ "?", helphelp, help, 0 },
{ 0 },
};
diff --git a/usr.sbin/lpr/lpc/extern.h b/usr.sbin/lpr/lpc/extern.h
index 1b807b1..c61c474 100644
--- a/usr.sbin/lpr/lpc/extern.h
+++ b/usr.sbin/lpr/lpc/extern.h
@@ -39,19 +39,20 @@
__BEGIN_DECLS
-void clean __P((int, char **));
-void disable __P((int, char **));
-void doabort __P((int, char **));
+void clean __P((struct printer *));
+void disable __P((struct printer *));
+void doabort __P((struct printer *));
void down __P((int, char **));
-void enable __P((int, char **));
+void enable __P((struct printer *));
+void generic __P((void (*) __P((struct printer *)), int, char **));
void help __P((int, char **));
void quit __P((int, char **));
-void restart __P((int, char **));
-void startcmd __P((int, char **));
-void status __P((int, char **));
-void stop __P((int, char **));
+void restart __P((struct printer *));
+void startcmd __P((struct printer *));
+void status __P((struct printer *));
+void stop __P((struct printer *));
void topq __P((int, char **));
-void up __P((int, char **));
+void up __P((struct printer *));
__END_DECLS
extern int NCMDS;
diff --git a/usr.sbin/lpr/lpc/lpc.c b/usr.sbin/lpr/lpc/lpc.c
index bb07d46..9a9b986 100644
--- a/usr.sbin/lpr/lpc/lpc.c
+++ b/usr.sbin/lpr/lpc/lpc.c
@@ -43,13 +43,14 @@ static const char copyright[] =
static char sccsid[] = "@(#)lpc.c 8.3 (Berkeley) 4/28/95";
#endif
static const char rcsid[] =
- "$Id$";
+ "$Id: lpc.c,v 1.5 1997/09/24 06:47:46 charnier Exp $";
#endif /* not lint */
#include <sys/param.h>
#include <ctype.h>
#include <dirent.h>
+#include <err.h>
#include <grp.h>
#include <setjmp.h>
#include <signal.h>
@@ -58,7 +59,7 @@ static const char rcsid[] =
#include <syslog.h>
#include <string.h>
#include <unistd.h>
-#include <sys/param.h>
+
#include "lp.h"
#include "lpc.h"
#include "extern.h"
@@ -116,7 +117,10 @@ main(argc, argv)
printf("?Privileged command\n");
exit(1);
}
- (*c->c_handler)(argc, argv);
+ if (c->c_generic != 0)
+ generic(c->c_generic, argc, argv);
+ else
+ (*c->c_handler)(argc, argv);
exit(0);
}
fromatty = isatty(fileno(stdin));
@@ -172,7 +176,10 @@ cmdscanner(top)
printf("?Privileged command\n");
continue;
}
- (*c->c_handler)(margc, margv);
+ if (c->c_generic != 0)
+ generic(c->c_generic, margc, margv);
+ else
+ (*c->c_handler)(margc, margv);
}
longjmp(toplevel, 0);
}
diff --git a/usr.sbin/lpr/lpc/lpc.h b/usr.sbin/lpr/lpc/lpc.h
index 5e71203..eca7b91 100644
--- a/usr.sbin/lpr/lpc/lpc.h
+++ b/usr.sbin/lpr/lpc/lpc.h
@@ -36,10 +36,13 @@
/*
* Line printer control program.
*/
+struct printer;
+
struct cmd {
char *c_name; /* command name */
char *c_help; /* help message */
/* routine to do the work */
void (*c_handler) __P((int, char *[]));
int c_priv; /* privileged command */
+ void (*c_generic) __P((struct printer *)); /* generic command */
};
diff --git a/usr.sbin/lpr/lpd/Makefile b/usr.sbin/lpr/lpd/Makefile
index b3c8081..f1eb2da 100644
--- a/usr.sbin/lpr/lpd/Makefile
+++ b/usr.sbin/lpr/lpd/Makefile
@@ -1,11 +1,11 @@
-# @(#)Makefile 8.1 (Berkeley) 6/6/93
+# From: @(#)Makefile 8.1 (Berkeley) 6/6/93
+# $Id$
PROG= lpd
-CFLAGS+=-I${.CURDIR}/../common_source
+CFLAGS+=-I${.CURDIR}/../common_source -Wall -Werror
MAN8= lpd.8
-SRCS= lpd.c printjob.c recvjob.c displayq.c rmjob.c startdaemon.c \
- lpdchar.c common.c modes.c
-.PATH: ${.CURDIR}/../common_source
+SRCS= lpd.c printjob.c recvjob.c lpdchar.c modes.c
+LDADD= -L${.OBJDIR}/../common_source -llpr
.include "../../Makefile.inc"
.include <bsd.prog.mk>
diff --git a/usr.sbin/lpr/lpd/extern.h b/usr.sbin/lpr/lpd/extern.h
index 718bef3..db732f5 100644
--- a/usr.sbin/lpr/lpd/extern.h
+++ b/usr.sbin/lpr/lpd/extern.h
@@ -30,7 +30,8 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * @(#)extern.h 8.1 (Berkeley) 6/6/93
+ * From: @(#)extern.h 8.1 (Berkeley) 6/6/93
+ * $Id$
*/
#include <sys/cdefs.h>
@@ -38,5 +39,10 @@
extern char scnkey[][HEIGHT]; /* in lpdchar.c */
extern char fromb[];
-void printjob __P((void));
-void recvjob __P((void));
+struct printer;
+
+__BEGIN_DECLS
+void printjob __P((struct printer *pp));
+void startprinting __P((const char *printer));
+void recvjob __P((const char *printer));
+__END_DECLS
diff --git a/usr.sbin/lpr/lpd/lpd.c b/usr.sbin/lpr/lpd/lpd.c
index e62e6bf..50ee865 100644
--- a/usr.sbin/lpr/lpd/lpd.c
+++ b/usr.sbin/lpr/lpd/lpd.c
@@ -43,7 +43,7 @@ static const char copyright[] =
static char sccsid[] = "@(#)lpd.c 8.7 (Berkeley) 5/10/95";
#endif
static const char rcsid[] =
- "$Id$";
+ "$Id: lpd.c,v 1.8 1997/09/24 06:47:54 charnier Exp $";
#endif /* not lint */
/*
@@ -111,8 +111,11 @@ static void mcleanup __P((int));
static void doit __P((void));
static void startup __P((void));
static void chkhost __P((struct sockaddr_in *));
-static int ckqueue __P((char *));
+static int ckqueue __P((struct printer *));
static void usage __P((void));
+/* From rcmd.c: */
+int __ivaliduser __P((FILE *, u_long, const char *,
+ const char *));
uid_t uid, euid;
@@ -125,7 +128,8 @@ main(argc, argv)
fd_set defreadfds;
struct sockaddr_un un, fromunix;
struct sockaddr_in sin, frominet;
- int omask, lfd;
+ int lfd;
+ sigset_t omask, nmask;
struct servent *sp, serv;
euid = geteuid(); /* these shouldn't be different */
@@ -173,6 +177,31 @@ main(argc, argv)
if (argc != 0)
usage();
+ /*
+ * We run chkprintcap right away to catch any errors and blat them
+ * to stderr while we still have it open, rather than sending them
+ * to syslog and leaving the user wondering why lpd started and
+ * then stopped. There should probably be a command-line flag to
+ * ignore errors from chkprintcap.
+ */
+ {
+ pid_t pid;
+ int status;
+ pid = fork();
+ if (pid < 0) {
+ err(EX_OSERR, "cannot fork");
+ } else if (pid == 0) { /* child */
+ execl(_PATH_CHKPRINTCAP, _PATH_CHKPRINTCAP, (char *)0);
+ err(EX_OSERR, "cannot execute %s", _PATH_CHKPRINTCAP);
+ }
+ if (waitpid(pid, &status, 0) < 0) {
+ err(EX_OSERR, "cannot wait");
+ }
+ if (WIFEXITED(status) && WEXITSTATUS(status) != 0)
+ errx(EX_OSFILE, "%d errors in printcap file, exiting",
+ WEXITSTATUS(status));
+ }
+
#ifndef DEBUG
/*
* Set up standard environment by detaching from the parent.
@@ -183,17 +212,22 @@ main(argc, argv)
openlog("lpd", LOG_PID, LOG_LPR);
syslog(LOG_INFO, "restarted");
(void) umask(0);
- lfd = open(_PATH_MASTERLOCK, O_WRONLY|O_CREAT, 0644);
+ /*
+ * NB: This depends on O_NONBLOCK semantics doing the right thing;
+ * i.e., applying only to the O_EXLOCK and not to the rest of the
+ * open/creation. As of 1997-12-02, this is the case for commonly-
+ * used filesystems. There are other places in this code which
+ * make the same assumption.
+ */
+ lfd = open(_PATH_MASTERLOCK, O_WRONLY|O_CREAT|O_EXLOCK|O_NONBLOCK,
+ LOCK_FILE_MODE);
if (lfd < 0) {
- syslog(LOG_ERR, "%s: %m", _PATH_MASTERLOCK);
- exit(1);
- }
- if (flock(lfd, LOCK_EX|LOCK_NB) < 0) {
if (errno == EWOULDBLOCK) /* active deamon present */
exit(0);
syslog(LOG_ERR, "%s: %m", _PATH_MASTERLOCK);
exit(1);
}
+ fcntl(lfd, F_SETFL, 0); /* turn off non-blocking mode */
ftruncate(lfd, 0);
/*
* write process id for others to know
@@ -215,8 +249,14 @@ main(argc, argv)
syslog(LOG_ERR, "socket: %m");
exit(1);
}
-#define mask(s) (1 << ((s) - 1))
- omask = sigblock(mask(SIGHUP)|mask(SIGINT)|mask(SIGQUIT)|mask(SIGTERM));
+
+ sigemptyset(&nmask);
+ sigaddset(&nmask, SIGHUP);
+ sigaddset(&nmask, SIGINT);
+ sigaddset(&nmask, SIGQUIT);
+ sigaddset(&nmask, SIGTERM);
+ sigprocmask(SIG_BLOCK, &nmask, &omask);
+
(void) umask(07);
signal(SIGHUP, mcleanup);
signal(SIGINT, mcleanup);
@@ -233,7 +273,7 @@ main(argc, argv)
exit(1);
}
(void) umask(0);
- sigsetmask(omask);
+ sigprocmask(SIG_SETMASK, &omask, (sigset_t *)0);
FD_ZERO(&defreadfds);
FD_SET(funix, &defreadfds);
listen(funix, 5);
@@ -259,6 +299,9 @@ main(argc, argv)
*/
memset(&frominet, 0, sizeof(frominet));
memset(&fromunix, 0, sizeof(fromunix));
+ /*
+ * XXX - should be redone for multi-protocol
+ */
for (;;) {
int domain, nfds, s;
fd_set readfds;
@@ -353,17 +396,21 @@ char *cmdnames[] = {
static void
doit()
{
- register char *cp;
- register int n;
+ char *cp, *printer;
+ int n;
+ int status;
+ struct printer myprinter, *pp = &myprinter;
+
+ init_printer(&myprinter);
for (;;) {
cp = cbuf;
do {
if (cp >= &cbuf[sizeof(cbuf) - 1])
- fatal("Command line too long");
+ fatal(0, "Command line too long");
if ((n = read(1, cp, 1)) != 1) {
if (n < 0)
- fatal("Lost connection");
+ fatal(0, "Lost connection");
return;
}
} while (*cp++ != '\n');
@@ -372,26 +419,25 @@ doit()
if (lflag) {
if (*cp >= '\1' && *cp <= '\5')
syslog(LOG_INFO, "%s requests %s %s",
- from, cmdnames[*cp], cp+1);
+ from, cmdnames[(u_char)*cp], cp+1);
else
syslog(LOG_INFO, "bad request (%d) from %s",
*cp, from);
}
switch (*cp++) {
- case '\1': /* check the queue and print any jobs there */
- printer = cp;
- printjob();
+ case CMD_CHECK_QUE: /* check the queue, print any jobs there */
+ startprinting(cp);
break;
- case '\2': /* receive files to be queued */
+ case CMD_TAKE_THIS: /* receive files to be queued */
if (!from_remote) {
syslog(LOG_INFO, "illegal request (%d)", *cp);
exit(1);
}
- printer = cp;
- recvjob();
+ recvjob(cp);
break;
- case '\3': /* display the queue (short form) */
- case '\4': /* display the queue (long form) */
+ case CMD_SHOWQ_SHORT: /* display the queue (short form) */
+ case CMD_SHOWQ_LONG: /* display the queue (long form) */
+ /* XXX - this all needs to be redone. */
printer = cp;
while (*cp) {
if (*cp != ' ') {
@@ -405,17 +451,20 @@ doit()
break;
if (isdigit(*cp)) {
if (requests >= MAXREQUESTS)
- fatal("Too many requests");
+ fatal(0, "Too many requests");
requ[requests++] = atoi(cp);
} else {
if (users >= MAXUSERS)
- fatal("Too many users");
+ fatal(0, "Too many users");
user[users++] = cp;
}
}
- displayq(cbuf[0] - '\3');
+ status = getprintcap(printer, pp);
+ if (status < 0)
+ fatal(pp, pcaperr(status));
+ displayq(pp, cbuf[0] == CMD_SHOWQ_LONG);
exit(0);
- case '\5': /* remove a job from the queue */
+ case CMD_RMJOB: /* remove a job from the queue */
if (!from_remote) {
syslog(LOG_INFO, "illegal request (%d)", *cp);
exit(1);
@@ -439,18 +488,18 @@ doit()
break;
if (isdigit(*cp)) {
if (requests >= MAXREQUESTS)
- fatal("Too many requests");
+ fatal(0, "Too many requests");
requ[requests++] = atoi(cp);
} else {
if (users >= MAXUSERS)
- fatal("Too many users");
+ fatal(0, "Too many users");
user[users++] = cp;
}
}
- rmjob();
+ rmjob(printer);
break;
}
- fatal("Illegal service request");
+ fatal(0, "Illegal service request");
}
}
@@ -461,66 +510,36 @@ doit()
static void
startup()
{
- char *buf;
- register char *cp;
- int pid;
- char *spooldirs[16]; /* Which spooldirs are active? */
- int i; /* Printer index presently processed */
- int j; /* Printer index of potential conflict */
- char *spooldir; /* Spooldir of present printer */
- int canfreespool; /* Is the spooldir malloc()ed? */
-
- /*
- * Restart the daemons and test for spooldir conflict.
- */
- i = 0;
- while (cgetnext(&buf, printcapdb) > 0) {
-
- /* Check for duplicate spooldirs */
- canfreespool = 1;
- if (cgetstr(buf, "sd", &spooldir) <= 0) {
- spooldir = _PATH_DEFSPOOL;
- canfreespool = 0;
+ int pid, status, more;
+ struct printer myprinter, *pp = &myprinter;
+
+ more = firstprinter(pp, &status);
+ if (status)
+ goto errloop;
+ while (more) {
+ if (ckqueue(pp) <= 0) {
+ goto next;
}
- if (i < sizeof(spooldirs)/sizeof(spooldirs[0]))
- spooldirs[i] = spooldir;
- for (j = 0;
- j < MIN(i,sizeof(spooldirs)/sizeof(spooldirs[0]));
- j++) {
- if (strcmp(spooldir, spooldirs[j]) == 0) {
- syslog(LOG_ERR,
- "startup: duplicate spool directories: %s",
- spooldir);
- mcleanup(0);
- }
- }
- if (canfreespool && i >= sizeof(spooldirs)/sizeof(spooldirs[0]))
- free(spooldir);
- i++;
- /* Spooldir test done */
-
- if (ckqueue(buf) <= 0) {
- free(buf);
- continue; /* no work to do for this printer */
- }
- for (cp = buf; *cp; cp++)
- if (*cp == '|' || *cp == ':') {
- *cp = '\0';
- break;
- }
if (lflag)
- syslog(LOG_INFO, "work for %s", buf);
+ syslog(LOG_INFO, "work for %s", pp->printer);
if ((pid = fork()) < 0) {
syslog(LOG_WARNING, "startup: cannot fork");
mcleanup(0);
}
- if (!pid) {
- printer = buf;
- cgetclose();
- printjob();
+ if (pid == 0) {
+ lastprinter();
+ printjob(pp);
/* NOTREACHED */
}
- else free(buf);
+ do {
+next:
+ more = nextprinter(pp, &status);
+errloop:
+ if (status)
+ syslog(LOG_WARNING,
+ "printcap for %s has errors, skipping",
+ pp->printer ? pp->printer : "<???>");
+ } while (more && status);
}
}
@@ -528,15 +547,14 @@ startup()
* Make sure there's some work to do before forking off a child
*/
static int
-ckqueue(cap)
- char *cap;
+ckqueue(pp)
+ struct printer *pp;
{
register struct dirent *d;
DIR *dirp;
char *spooldir;
- if (cgetstr(cap, "sd", &spooldir) == -1)
- spooldir = _PATH_DEFSPOOL;
+ spooldir = pp->spool_dir;
if ((dirp = opendir(spooldir)) == NULL)
return (-1);
while ((d = readdir(dirp)) != NULL) {
@@ -567,7 +585,7 @@ chkhost(f)
hp = gethostbyaddr((char *)&f->sin_addr,
sizeof(struct in_addr), f->sin_family);
if (hp == NULL)
- fatal("Host name for your address (%s) unknown",
+ fatal(0, "Host name for your address (%s) unknown",
inet_ntoa(f->sin_addr));
(void) strncpy(fromb, hp->h_name, sizeof(fromb) - 1);
@@ -577,7 +595,7 @@ chkhost(f)
/* Check for spoof, ala rlogind */
hp = gethostbyname(fromb);
if (!hp)
- fatal("hostname for your address (%s) unknown",
+ fatal(0, "hostname for your address (%s) unknown",
inet_ntoa(f->sin_addr));
for (; good == 0 && hp->h_addr_list[0] != NULL; hp->h_addr_list++) {
if (!bcmp(hp->h_addr_list[0], (caddr_t)&f->sin_addr,
@@ -585,7 +603,7 @@ chkhost(f)
good = 1;
}
if (good == 0)
- fatal("address for your hostname (%s) not matched",
+ fatal(0, "address for your hostname (%s) not matched",
inet_ntoa(f->sin_addr));
hostf = fopen(_PATH_HOSTSEQUIV, "r");
@@ -603,7 +621,7 @@ again:
hostf = fopen(_PATH_HOSTSLPD, "r");
goto again;
}
- fatal("Your host does not have line printer access");
+ fatal(0, "Your host does not have line printer access");
/*NOTREACHED*/
}
diff --git a/usr.sbin/lpr/lpd/lpdchar.c b/usr.sbin/lpr/lpd/lpdchar.c
index 4d24ffd..f5c542a 100644
--- a/usr.sbin/lpr/lpd/lpdchar.c
+++ b/usr.sbin/lpr/lpd/lpdchar.c
@@ -32,7 +32,11 @@
*/
#ifndef lint
+/*
static char sccsid[] = "@(#)lpdchar.c 8.1 (Berkeley) 6/6/93";
+*/
+static const char rcsid[] =
+ "$Id$";
#endif /* not lint */
/*
diff --git a/usr.sbin/lpr/lpd/modes.c b/usr.sbin/lpr/lpd/modes.c
index 7e3dcd9..c85c669 100644
--- a/usr.sbin/lpr/lpd/modes.c
+++ b/usr.sbin/lpr/lpd/modes.c
@@ -29,12 +29,14 @@
* 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.
- *
- * $Id$
*/
#ifndef lint
+/*
static char sccsid[] = "@(#)modes.c 8.3 (Berkeley) 4/2/94";
+*/
+static const char rcsid[] =
+ "$Id$";
#endif /* not lint */
#include <stddef.h>
diff --git a/usr.sbin/lpr/lpd/printjob.c b/usr.sbin/lpr/lpd/printjob.c
index cff1d9f..929d6a3 100644
--- a/usr.sbin/lpr/lpd/printjob.c
+++ b/usr.sbin/lpr/lpd/printjob.c
@@ -33,13 +33,17 @@
*/
#ifndef lint
-static char copyright[] =
+static const char copyright[] =
"@(#) Copyright (c) 1983, 1993\n\
The Regents of the University of California. All rights reserved.\n";
#endif /* not lint */
#ifndef lint
+/*
static char sccsid[] = "@(#)printjob.c 8.7 (Berkeley) 5/10/95";
+*/
+static const char rcsid[] =
+ "$Id$";
#endif /* not lint */
@@ -99,7 +103,6 @@ static int pfd; /* prstatic inter file descriptor */
static int pid; /* pid of lpd process */
static int prchild; /* id of pr process */
static char title[80]; /* ``pr'' title */
-static int tof; /* true if at top of form */
static char class[32]; /* classification field */
static char fromhost[32]; /* user's host machine */
@@ -117,27 +120,32 @@ static char tfile[] = TFILENAME; /* file name for filter output */
static void abortpr __P((int));
static void alarmhandler __P((int));
-static void banner __P((char *, char *));
-static int dofork __P((int));
+static void banner __P((struct printer *pp, char *name1, char *name2));
+static int dofork __P((const struct printer *pp, int action));
static int dropit __P((int));
-static void init __P((void));
-static void openpr __P((void));
-static void opennet __P((char *));
-static void opentty __P((void));
-static void openrem __P((void));
-static int print __P((int, char *));
-static int printit __P((char *));
-static void pstatus __P((const char *, ...));
-static char response __P((void));
-static void scan_out __P((int, char *, int));
+static void init __P((struct printer *pp));
+static void openpr __P((const struct printer *pp));
+static void opennet __P((const struct printer *pp));
+static void opentty __P((const struct printer *pp));
+static void openrem __P((const struct printer *pp));
+static int print __P((struct printer *pp, int format, char *file));
+static int printit __P((struct printer *pp, char *file));
+static void pstatus __P((const struct printer *, const char *, ...));
+static char response __P((const struct printer *pp));
+static void scan_out __P((struct printer *pp, int scfd, char *scsp,
+ int dlm));
static char *scnline __P((int, char *, int));
-static int sendfile __P((int, char *, char));
-static int sendit __P((char *));
-static void sendmail __P((char *, int));
-static void setty __P((void));
+static int sendfile __P((struct printer *pp, int type, char *file,
+ int format));
+static int sendit __P((struct printer *pp, char *file));
+static void sendmail __P((struct printer *pp, char *user, int bombed));
+static void setty __P((const struct printer *pp));
+
+void msearch __P((char *, struct termios *));
void
-printjob()
+printjob(pp)
+ struct printer *pp;
{
struct stat stb;
register struct queue *q, **qp;
@@ -146,11 +154,11 @@ printjob()
off_t pidoff;
int errcnt, count = 0;
- init(); /* set up capabilities */
- (void) write(1, "", 1); /* ack that daemon is started */
+ init(pp); /* set up capabilities */
+ (void) write(1, "", 1); /* ack that daemon is started */
(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, LOG_FILE_MODE) < 0) {
+ syslog(LOG_ERR, "%s: %m", pp->log_file);
(void) open(_PATH_DEVNULL, O_WRONLY);
}
setgid(getegid());
@@ -166,21 +174,23 @@ printjob()
/*
* uses short form file names
*/
- if (chdir(SD) < 0) {
- syslog(LOG_ERR, "%s: %m", SD);
+ if (chdir(pp->spool_dir) < 0) {
+ syslog(LOG_ERR, "%s: %m", pp->spool_dir);
exit(1);
}
- if (stat(LO, &stb) == 0 && (stb.st_mode & 0100))
+ if (stat(pp->lock_file, &stb) == 0 && (stb.st_mode & LFM_PRINT_DIS))
exit(0); /* printing disabled */
- lfd = open(LO, O_WRONLY|O_CREAT, 0644);
+ lfd = open(pp->lock_file, O_WRONLY|O_CREAT|O_EXLOCK|O_NONBLOCK,
+ LOCK_FILE_MODE);
if (lfd < 0) {
- syslog(LOG_ERR, "%s: %s: %m", printer, LO);
+ if (errno == EWOULDBLOCK) /* active daemon present */
+ exit(0);
+ syslog(LOG_ERR, "%s: %s: %m", pp->printer, pp->lock_file);
exit(1);
}
- if (flock(lfd, LOCK_EX|LOCK_NB) < 0) {
- if (errno == EWOULDBLOCK) /* active deamon present */
- exit(0);
- syslog(LOG_ERR, "%s: %s: %m", printer, LO);
+ /* turn off non-blocking mode (was turned on for lock effects only) */
+ if (fcntl(lfd, F_SETFL, 0) < 0) {
+ syslog(LOG_ERR, "%s: %s: %m", pp->printer, pp->lock_file);
exit(1);
}
ftruncate(lfd, 0);
@@ -190,23 +200,25 @@ printjob()
sprintf(line, "%u\n", pid);
pidoff = i = strlen(line);
if (write(lfd, line, i) != i) {
- syslog(LOG_ERR, "%s: %s: %m", printer, LO);
+ syslog(LOG_ERR, "%s: %s: %m", pp->printer, pp->lock_file);
exit(1);
}
/*
* search the spool directory for work and sort by queue order.
*/
- if ((nitems = getq(&queue)) < 0) {
- syslog(LOG_ERR, "%s: can't scan %s", printer, SD);
+ if ((nitems = getq(pp, &queue)) < 0) {
+ syslog(LOG_ERR, "%s: can't scan %s", pp->printer,
+ pp->spool_dir);
exit(1);
}
if (nitems == 0) /* no work to do */
exit(0);
- if (stb.st_mode & 01) { /* reset queue flag */
- if (fchmod(lfd, stb.st_mode & 0776) < 0)
- syslog(LOG_ERR, "%s: %s: %m", printer, LO);
+ if (stb.st_mode & LFM_RESET_QUE) { /* reset queue flag */
+ if (fchmod(lfd, stb.st_mode & ~LFM_RESET_QUE) < 0)
+ syslog(LOG_ERR, "%s: %s: %m", pp->printer,
+ pp->lock_file);
}
- openpr(); /* open printer or remote */
+ openpr(pp); /* open printer or remote */
again:
/*
* we found something to do now do it --
@@ -223,26 +235,28 @@ again:
(void) snprintf(line, sizeof(line), "%s\n", q->q_name);
i = strlen(line);
if (write(lfd, line, i) != i)
- syslog(LOG_ERR, "%s: %s: %m", printer, LO);
- if (!remote)
- i = printit(q->q_name);
+ syslog(LOG_ERR, "%s: %s: %m", pp->printer,
+ pp->lock_file);
+ if (!pp->remote)
+ i = printit(pp, q->q_name);
else
- i = sendit(q->q_name);
+ i = sendit(pp, q->q_name);
/*
* Check to see if we are supposed to stop printing or
* if we are to rebuild the queue.
*/
if (fstat(lfd, &stb) == 0) {
/* stop printing before starting next job? */
- if (stb.st_mode & 0100)
+ if (stb.st_mode & LFM_PRINT_DIS)
goto done;
/* rebuild queue (after lpc topq) */
- if (stb.st_mode & 01) {
- for (free((char *) q); nitems--; free((char *) q))
+ if (stb.st_mode & LFM_RESET_QUE) {
+ for (free(q); nitems--; free(q))
q = *qp++;
- if (fchmod(lfd, stb.st_mode & 0776) < 0)
+ if (fchmod(lfd, stb.st_mode & ~LFM_RESET_QUE)
+ < 0)
syslog(LOG_WARNING, "%s: %s: %m",
- printer, LO);
+ pp->printer, pp->lock_file);
break;
}
}
@@ -250,7 +264,7 @@ again:
count++;
else if (i == REPRINT && ++errcnt < 5) {
/* try reprinting the job */
- syslog(LOG_INFO, "restarting %s", printer);
+ syslog(LOG_INFO, "restarting %s", pp->printer);
if (ofilter > 0) {
kill(ofilter, SIGCONT); /* to be sure */
(void) close(ofd);
@@ -260,37 +274,43 @@ again:
}
(void) close(pfd); /* close printer */
if (ftruncate(lfd, pidoff) < 0)
- syslog(LOG_WARNING, "%s: %s: %m", printer, LO);
- openpr(); /* try to reopen printer */
+ syslog(LOG_WARNING, "%s: %s: %m",
+ pp->printer, pp->lock_file);
+ openpr(pp); /* try to reopen printer */
goto restart;
} else {
- syslog(LOG_WARNING, "%s: job could not be %s (%s)", printer,
- remote ? "sent to remote host" : "printed", q->q_name);
+ syslog(LOG_WARNING, "%s: job could not be %s (%s)",
+ pp->printer,
+ pp->remote ? "sent to remote host" : "printed",
+ q->q_name);
if (i == REPRINT) {
/* ensure we don't attempt this job again */
(void) unlink(q->q_name);
q->q_name[0] = 'd';
(void) unlink(q->q_name);
if (logname[0])
- sendmail(logname, FATALERR);
+ sendmail(pp, logname, FATALERR);
}
}
}
- free((char *) queue);
+ free(queue);
/*
* search the spool directory for more work.
*/
- if ((nitems = getq(&queue)) < 0) {
- syslog(LOG_ERR, "%s: can't scan %s", printer, SD);
+ if ((nitems = getq(pp, &queue)) < 0) {
+ syslog(LOG_ERR, "%s: can't scan %s", pp->printer,
+ pp->spool_dir);
exit(1);
}
if (nitems == 0) { /* no more work to do */
done:
if (count > 0) { /* Files actually printed */
- if (!SF && !tof)
- (void) write(ofd, FF, strlen(FF));
- if (TR != NULL) /* output trailer */
- (void) write(ofd, TR, strlen(TR));
+ if (!pp->no_formfeed && !pp->tof)
+ (void) write(ofd, pp->form_feed,
+ strlen(pp->form_feed));
+ if (pp->trailer != NULL) /* output trailer */
+ (void) write(ofd, pp->trailer,
+ strlen(pp->trailer));
}
(void) close(ofd);
(void) wait(NULL);
@@ -314,7 +334,8 @@ char ifonts[4][40] = {
* and performing the various actions.
*/
static int
-printit(file)
+printit(pp, file)
+ struct printer *pp;
char *file;
{
register int i;
@@ -325,7 +346,7 @@ printit(file)
* open control file; ignore if no longer there.
*/
if ((cfp = fopen(file, "r")) == NULL) {
- syslog(LOG_INFO, "%s: %s: %m", printer, file);
+ syslog(LOG_INFO, "%s: %s: %m", pp->printer, file);
return(OK);
}
/*
@@ -333,7 +354,7 @@ printit(file)
*/
for (i = 0; i < 4; i++)
strcpy(fonts[i], ifonts[i]);
- sprintf(&width[2], "%ld", PW);
+ sprintf(&width[2], "%ld", pp->page_width);
strcpy(indent+2, "0");
/*
@@ -389,10 +410,10 @@ printit(file)
case 'P':
strncpy(logname, line+1, sizeof(logname) - 1);
logname[sizeof(logname) - 1] = '\0';
- if (RS) { /* restricted */
+ if (pp->restricted) { /* restricted */
if (getpwnam(logname) == NULL) {
bombed = NOACCT;
- sendmail(line+1, bombed);
+ sendmail(pp, line+1, bombed);
goto pass2;
}
}
@@ -433,8 +454,8 @@ printit(file)
continue;
case 'L': /* identification line */
- if (!SH && !HL)
- banner(line+1, jobname);
+ if (!pp->no_header && !pp->header_last)
+ banner(pp, line+1, jobname);
continue;
case '1': /* troff fonts */
@@ -459,7 +480,7 @@ printit(file)
continue;
default: /* some file to print */
- switch (i = print(line[0], line+1)) {
+ switch (i = print(pp, line[0], line+1)) {
case ERROR:
if (bombed == OK)
bombed = FATALERR;
@@ -470,7 +491,7 @@ printit(file)
case FILTERERR:
case ACCESS:
bombed = i;
- sendmail(logname, bombed);
+ sendmail(pp, logname, bombed);
}
title[0] = '\0';
continue;
@@ -489,13 +510,13 @@ pass2:
while (getline(cfp))
switch (line[0]) {
case 'L': /* identification line */
- if (!SH && HL)
- banner(line+1, jobname);
+ if (!pp->no_header && pp->header_last)
+ banner(pp, line+1, jobname);
continue;
case 'M':
if (bombed < NOACCT) /* already sent if >= NOACCT */
- sendmail(line+1, bombed);
+ sendmail(pp, line+1, bombed);
continue;
case 'U':
@@ -522,13 +543,14 @@ pass2:
* stderr as the log file, and must not ignore SIGINT.
*/
static int
-print(format, file)
+print(pp, format, file)
+ struct printer *pp;
int format;
char *file;
{
register int n;
register char *prog;
- int dtablesize, fi, fo;
+ int fi, fo;
FILE *fp;
char *av[15], buf[BUFSIZ];
int pid, p[2], stopped = 0;
@@ -545,12 +567,13 @@ print(format, file)
if ((stb.st_mode & S_IFMT) == S_IFLNK && fstat(fi, &stb) == 0 &&
(stb.st_dev != fdev || stb.st_ino != fino))
return(ACCESS);
- if (!SF && !tof) { /* start on a fresh page */
- (void) write(ofd, FF, strlen(FF));
- tof = 1;
+ if (!pp->no_formfeed && !pp->tof) { /* start on a fresh page */
+ (void) write(ofd, pp->form_feed, strlen(pp->form_feed));
+ pp->tof = 1;
}
- if (IF == NULL && (format == 'f' || format == 'l')) {
- tof = 0;
+ if (pp->filters[LPF_INPUT] == NULL
+ && (format == 'f' || format == 'l')) {
+ pp->tof = 0;
while ((n = read(fi, buf, BUFSIZ)) > 0)
if (write(ofd, buf, n) != n) {
(void) close(fi);
@@ -561,7 +584,7 @@ print(format, file)
}
switch (format) {
case 'p': /* print file using 'pr' */
- if (IF == NULL) { /* use output filter */
+ if (pp->filters[LPF_INPUT] == NULL) { /* use output filter */
prog = _PATH_PR;
av[0] = "pr";
av[1] = width;
@@ -574,13 +597,11 @@ print(format, file)
goto start;
}
pipe(p);
- if ((prchild = dofork(DORETURN)) == 0) { /* child */
+ if ((prchild = dofork(pp, DORETURN)) == 0) { /* child */
dup2(fi, 0); /* file is stdin */
dup2(p[1], 1); /* pipe is stdout */
closelog();
- for (n = 3, dtablesize = getdtablesize();
- n < dtablesize; n++)
- (void) close(n);
+ closeallfds(3);
execl(_PATH_PR, "pr", width, length,
"-h", *title ? title : " ", "-F", 0);
syslog(LOG_ERR, "cannot execl %s", _PATH_PR);
@@ -595,14 +616,14 @@ print(format, file)
}
fi = p[0]; /* use pipe for input */
case 'f': /* print plain text file */
- prog = IF;
+ prog = pp->filters[LPF_INPUT];
av[1] = width;
av[2] = length;
av[3] = indent;
n = 4;
break;
case 'l': /* like 'f' but pass control characters */
- prog = IF;
+ prog = pp->filters[LPF_INPUT];
av[1] = "-c";
av[2] = width;
av[3] = length;
@@ -610,7 +631,7 @@ print(format, file)
n = 5;
break;
case 'r': /* print a fortran text file */
- prog = RF;
+ prog = pp->filters[LPF_FORTRAN];
av[1] = width;
av[2] = length;
n = 3;
@@ -620,7 +641,8 @@ print(format, file)
case 'd': /* print tex output */
(void) unlink(".railmag");
if ((fo = creat(".railmag", FILMOD)) < 0) {
- syslog(LOG_ERR, "%s: cannot create .railmag", printer);
+ syslog(LOG_ERR, "%s: cannot create .railmag",
+ pp->printer);
(void) unlink(".railmag");
} else {
for (n = 0; n < 4; n++) {
@@ -632,25 +654,27 @@ print(format, file)
}
(void) close(fo);
}
- prog = (format == 't') ? TF : (format == 'n') ? NF : DF;
+ prog = (format == 't') ? pp->filters[LPF_TROFF]
+ : ((format == 'n') ? pp->filters[LPF_DITROFF]
+ : pp->filters[LPF_DVI]);
av[1] = pxwidth;
av[2] = pxlength;
n = 3;
break;
case 'c': /* print cifplot output */
- prog = CF;
+ prog = pp->filters[LPF_CIFPLOT];
av[1] = pxwidth;
av[2] = pxlength;
n = 3;
break;
case 'g': /* print plot(1G) output */
- prog = GF;
+ prog = pp->filters[LPF_GRAPH];
av[1] = pxwidth;
av[2] = pxlength;
n = 3;
break;
case 'v': /* print raster output */
- prog = VF;
+ prog = pp->filters[LPF_RASTER];
av[1] = pxwidth;
av[2] = pxlength;
n = 3;
@@ -658,14 +682,14 @@ print(format, file)
default:
(void) close(fi);
syslog(LOG_ERR, "%s: illegal format character '%c'",
- printer, format);
+ pp->printer, format);
return(ERROR);
}
if (prog == NULL) {
(void) close(fi);
syslog(LOG_ERR,
"%s: no filter found in printcap for format character '%c'",
- printer, format);
+ pp->printer, format);
return(ERROR);
}
if ((av[0] = strrchr(prog, '/')) != NULL)
@@ -676,7 +700,7 @@ print(format, file)
av[n++] = logname;
av[n++] = "-h";
av[n++] = fromhost;
- av[n++] = AF;
+ av[n++] = pp->acct_file;
av[n] = 0;
fo = pfd;
if (ofilter > 0) { /* stop output filter */
@@ -687,22 +711,23 @@ print(format, file)
if (status.w_stopval != WSTOPPED) {
(void) close(fi);
syslog(LOG_WARNING,
- "%s: output filter died (retcode=%d termsig=%d)",
- printer, status.w_retcode, status.w_termsig);
+ "%s: output filter died "
+ "(retcode=%d termsig=%d)",
+ pp->printer, status.w_retcode,
+ status.w_termsig);
return(REPRINT);
}
stopped++;
}
start:
- if ((child = dofork(DORETURN)) == 0) { /* child */
+ if ((child = dofork(pp, DORETURN)) == 0) { /* child */
dup2(fi, 0);
dup2(fo, 1);
n = open(tempfile, O_WRONLY|O_CREAT|O_TRUNC, 0664);
if (n >= 0)
dup2(n, 2);
closelog();
- for (n = 3, dtablesize = getdtablesize(); n < dtablesize; n++)
- (void) close(n);
+ closeallfds(3);
execv(prog, av);
syslog(LOG_ERR, "cannot execv %s", prog);
exit(2);
@@ -721,7 +746,7 @@ start:
exit(1);
}
}
- tof = 0;
+ pp->tof = 0;
/* Copy filter output to "lf" logfile */
if ((fp = fopen(tempfile, "r"))) {
@@ -732,12 +757,12 @@ start:
if (!WIFEXITED(status)) {
syslog(LOG_WARNING, "%s: filter '%c' terminated (termsig=%d)",
- printer, format, status.w_termsig);
+ pp->printer, format, status.w_termsig);
return(ERROR);
}
switch (status.w_retcode) {
case 0:
- tof = 1;
+ pp->tof = 1;
return(OK);
case 1:
return(REPRINT);
@@ -745,7 +770,7 @@ start:
return(ERROR);
default:
syslog(LOG_WARNING, "%s: filter '%c' exited (retcode=%d)",
- printer, format, status.w_retcode);
+ pp->printer, format, status.w_retcode);
return(FILTERERR);
}
}
@@ -756,7 +781,8 @@ start:
* 0 if all is well.
*/
static int
-sendit(file)
+sendit(pp, file)
+ struct printer *pp;
char *file;
{
register int i, err = OK;
@@ -801,9 +827,9 @@ sendit(file)
strncpy(class, line+1, sizeof(class) - 1);
} else if (line[0] == 'P') {
strncpy(logname, line+1, sizeof(logname) - 1);
- if (RS) { /* restricted */
+ if (pp->restricted) { /* restricted */
if (getpwnam(logname) == NULL) {
- sendmail(line+1, NOACCT);
+ sendmail(pp, line+1, NOACCT);
err = ERROR;
break;
}
@@ -812,10 +838,10 @@ sendit(file)
strncpy(indent+2, line+1, sizeof(indent) - 3);
} else if (line[0] >= 'a' && line[0] <= 'z') {
strcpy(last, line);
- while (i = getline(cfp))
+ while ((i = getline(cfp)) != 0)
if (strcmp(last, line))
break;
- switch (sendfile('\3', last+1, *last)) {
+ switch (sendfile(pp, '\3', last+1, *last)) {
case OK:
if (i)
goto again;
@@ -824,14 +850,14 @@ sendit(file)
(void) fclose(cfp);
return(REPRINT);
case ACCESS:
- sendmail(logname, ACCESS);
+ sendmail(pp, logname, ACCESS);
case ERROR:
err = ERROR;
}
break;
}
}
- if (err == OK && sendfile('\2', file, '\0') > 0) {
+ if (err == OK && sendfile(pp, '\2', file, '\0') > 0) {
(void) fclose(cfp);
return(REPRINT);
}
@@ -855,7 +881,8 @@ sendit(file)
* Return positive if we should try resending.
*/
static int
-sendfile(type, file, format)
+sendfile(pp, type, file, format)
+ struct printer *pp;
int type;
char *file;
char format;
@@ -879,7 +906,7 @@ sendfile(type, file, format)
sizerr = 0;
closedpr = 0;
if (type == '\3') {
- if (IF) {
+ if (pp->filters[LPF_INPUT]) {
/*
* We're sending something with an ifilter, we have to
* run the ifilter and store the output as a
@@ -888,17 +915,16 @@ sendfile(type, file, format)
*/
char *av[15];
int n;
- int nfd;
int ifilter;
- union wait status;
+ union wait status; /* XXX */
strcpy(tfile,TFILENAME);
if ((tfd = mkstemp(tfile)) == -1) {
syslog(LOG_ERR, "mkstemp: %m");
return(ERROR);
}
- if ((av[0] = strrchr(IF, '/')) == NULL)
- av[0] = IF;
+ if ((av[0] = strrchr(pp->filters[LPF_INPUT], '/')) == NULL)
+ av[0] = pp->filters[LPF_INPUT];
else
av[0]++;
if (format == 'l')
@@ -912,19 +938,20 @@ sendfile(type, file, format)
av[++n] = logname;
av[++n] = "-h";
av[++n] = fromhost;
- av[++n] = AF;
+ av[++n] = pp->acct_file;
av[++n] = 0;
- if ((ifilter = dofork(DORETURN)) == 0) { /* child */
+ if ((ifilter = dofork(pp, DORETURN)) == 0) { /* child */
dup2(f, 0);
dup2(tfd, 1);
- n = open(tempfile, O_WRONLY|O_CREAT|O_TRUNC, 0664);
+ n = open(tempfile, O_WRONLY|O_CREAT|O_TRUNC,
+ TEMP_FILE_MODE);
if (n >= 0)
dup2(n, 2);
closelog();
- for (n = 3, nfd = getdtablesize(); n < nfd; n++)
- (void) close(n);
- execv(IF, av);
- syslog(LOG_ERR, "cannot execv %s", IF);
+ closeallfds(3);
+ execv(pp->filters[LPF_INPUT], av);
+ syslog(LOG_ERR, "cannot execv %s",
+ pp->filters[LPF_INPUT]);
exit(2);
}
(void) close(f);
@@ -946,7 +973,7 @@ sendfile(type, file, format)
default:
syslog(LOG_WARNING, "%s: filter '%c' exited"
" (retcode=%d)",
- printer, format, status.w_retcode);
+ pp->printer, format, status.w_retcode);
unlink(tfile);
return(FILTERERR);
}
@@ -980,7 +1007,7 @@ sendfile(type, file, format)
;
ofilter = 0;
if (fstat(tfd, &stb) < 0) { /* the size of tfile */
- openpr();
+ openpr(pp);
return(ERROR);
}
f = tfd;
@@ -993,26 +1020,27 @@ sendfile(type, file, format)
amt = strlen(buf);
for (i = 0; ; i++) {
if (write(pfd, buf, amt) != amt ||
- (resp = response()) < 0 || resp == '\1') {
+ (resp = response(pp)) < 0 || resp == '\1') {
(void) close(f);
if (tfd != -1 && type == '\3') {
tfd = -1;
unlink(tfile);
if (closedpr)
- openpr();
+ openpr(pp);
}
return(REPRINT);
} else if (resp == '\0')
break;
if (i == 0)
- pstatus("no space on remote; waiting for queue to drain");
+ pstatus(pp,
+ "no space on remote; waiting for queue to drain");
if (i == 10)
syslog(LOG_ALERT, "%s: can't send to %s; queue full",
- printer, RM);
+ pp->printer, pp->remote_host);
sleep(5 * 60);
}
if (i)
- pstatus("sending to %s", RM);
+ pstatus(pp, "sending to %s", pp->remote_host);
for (i = 0; i < stb.st_size; i += BUFSIZ) {
amt = BUFSIZ;
if (i + amt > stb.st_size)
@@ -1025,7 +1053,7 @@ sendfile(type, file, format)
tfd = -1;
unlink(tfile);
if (closedpr)
- openpr();
+ openpr(pp);
}
return(REPRINT);
}
@@ -1037,20 +1065,20 @@ sendfile(type, file, format)
unlink(tfile);
}
if (sizerr) {
- syslog(LOG_INFO, "%s: %s: changed size", printer, file);
+ syslog(LOG_INFO, "%s: %s: changed size", pp->printer, file);
/* tell recvjob to ignore this file */
(void) write(pfd, "\1", 1);
if (closedpr)
- openpr();
+ openpr(pp);
return(ERROR);
}
- if (write(pfd, "", 1) != 1 || response()) {
+ if (write(pfd, "", 1) != 1 || response(pp)) {
if (closedpr)
- openpr();
+ openpr(pp);
return(REPRINT);
}
if (closedpr)
- openpr();
+ openpr(pp);
return(OK);
}
@@ -1060,12 +1088,13 @@ sendfile(type, file, format)
* Return non-zero if the connection was lost.
*/
static char
-response()
+response(pp)
+ const struct printer *pp;
{
char resp;
if (read(pfd, &resp, 1) != 1) {
- syslog(LOG_INFO, "%s: lost connection", printer);
+ syslog(LOG_INFO, "%s: lost connection", pp->printer);
return(-1);
}
return(resp);
@@ -1075,15 +1104,16 @@ response()
* Banner printing stuff
*/
static void
-banner(name1, name2)
+banner(pp, name1, name2)
+ struct printer *pp;
char *name1, *name2;
{
time_t tvec;
time(&tvec);
- if (!SF && !tof)
- (void) write(ofd, FF, strlen(FF));
- if (SB) { /* short banner only */
+ if (!pp->no_formfeed && !pp->tof)
+ (void) write(ofd, pp->form_feed, strlen(pp->form_feed));
+ if (pp->short_banner) { /* short banner only */
if (class[0]) {
(void) write(ofd, class, strlen(class));
(void) write(ofd, ":", 1);
@@ -1096,12 +1126,12 @@ banner(name1, name2)
(void) write(ofd, "\n", 1);
} else { /* normal banner */
(void) write(ofd, "\n\n\n", 3);
- scan_out(ofd, name1, '\0');
+ scan_out(pp, ofd, name1, '\0');
(void) write(ofd, "\n\n", 2);
- scan_out(ofd, name2, '\0');
+ scan_out(pp, ofd, name2, '\0');
if (class[0]) {
(void) write(ofd,"\n\n\n",3);
- scan_out(ofd, class, '\0');
+ scan_out(pp, ofd, class, '\0');
}
(void) write(ofd, "\n\n\n\n\t\t\t\t\tJob: ", 15);
(void) write(ofd, name2, strlen(name2));
@@ -1109,9 +1139,9 @@ banner(name1, name2)
(void) write(ofd, ctime(&tvec), 24);
(void) write(ofd, "\n", 1);
}
- if (!SF)
- (void) write(ofd, FF, strlen(FF));
- tof = 1;
+ if (!pp->no_formfeed)
+ (void) write(ofd, pp->form_feed, strlen(pp->form_feed));
+ pp->tof = 1;
}
static char *
@@ -1132,7 +1162,8 @@ scnline(key, p, c)
#define TRC(q) (((q)-' ')&0177)
static void
-scan_out(scfd, scsp, dlm)
+scan_out(pp, scfd, scsp, dlm)
+ struct printer *pp;
int scfd, dlm;
char *scsp;
{
@@ -1150,8 +1181,9 @@ scan_out(scfd, scsp, dlm)
for (j = WIDTH; --j;)
*strp++ = BACKGND;
else
- strp = scnline(scnkey[c][scnhgt-1-d], strp, cc);
- if (*sp == dlm || *sp == '\0' || nchrs++ >= PW/(WIDTH+1)-1)
+ strp = scnline(scnkey[(int)c][scnhgt-1-d], strp, cc);
+ if (*sp == dlm || *sp == '\0' ||
+ nchrs++ >= pp->page_width/(WIDTH+1)-1)
break;
*strp++ = BACKGND;
*strp++ = BACKGND;
@@ -1190,38 +1222,39 @@ dropit(c)
* tell people about job completion
*/
static void
-sendmail(user, bombed)
+sendmail(pp, user, bombed)
+ struct printer *pp;
char *user;
int bombed;
{
register int i;
- int dtablesize;
int p[2], s;
register char *cp;
struct stat stb;
FILE *fp;
pipe(p);
- if ((s = dofork(DORETURN)) == 0) { /* child */
+ if ((s = dofork(pp, DORETURN)) == 0) { /* child */
dup2(p[0], 0);
closelog();
- for (i = 3, dtablesize = getdtablesize(); i < dtablesize; i++)
- (void) close(i);
+ closeallfds(3);
if ((cp = strrchr(_PATH_SENDMAIL, '/')) != NULL)
cp++;
- else
+ else
cp = _PATH_SENDMAIL;
execl(_PATH_SENDMAIL, cp, "-t", 0);
- exit(0);
+ _exit(0);
} else if (s > 0) { /* parent */
dup2(p[1], 1);
printf("To: %s@%s\n", user, fromhost);
- printf("Subject: %s printer job \"%s\"\n", printer,
+ printf("Subject: %s printer job \"%s\"\n", pp->printer,
*jobname ? jobname : "<unknown>");
printf("Reply-To: root@%s\n\n", host);
printf("Your printer job ");
if (*jobname)
printf("(%s) ", jobname);
+
+ cp = "XXX compiler confusion"; /* XXX shut GCC up */
switch (bombed) {
case OK:
printf("\ncompleted successfully\n");
@@ -1254,19 +1287,23 @@ sendmail(user, bombed)
}
fflush(stdout);
(void) close(1);
+ } else {
+ syslog(LOG_WARNING, "unable to send mail to %s: %m", user);
+ return;
}
(void) close(p[0]);
(void) close(p[1]);
wait(NULL);
syslog(LOG_INFO, "mail sent to user %s about job %s on printer %s (%s)",
- user, *jobname ? jobname : "<unknown>", printer, cp);
+ user, *jobname ? jobname : "<unknown>", pp->printer, cp);
}
/*
* dofork - fork with retries on failure
*/
static int
-dofork(action)
+dofork(pp, action)
+ const struct printer *pp;
int action;
{
register int i, pid;
@@ -1280,7 +1317,7 @@ dofork(action)
* Child should run as daemon instead of root
*/
if (pid == 0)
- setuid(DU);
+ setuid(pp->daemon_user);
return(pid);
}
syslog(LOG_ERR, "can't fork");
@@ -1316,127 +1353,90 @@ abortpr(signo)
}
static void
-init()
+init(pp)
+ struct printer *pp;
{
- int status;
char *s;
- if ((status = cgetent(&bp, printcapdb, printer)) == -2) {
- syslog(LOG_ERR, "can't open printer description file");
+ sprintf(&width[2], "%ld", pp->page_width);
+ sprintf(&length[2], "%ld", pp->page_length);
+ sprintf(&pxwidth[2], "%ld", pp->page_pwidth);
+ sprintf(&pxlength[2], "%ld", pp->page_plength);
+ if ((s = checkremote(pp)) != 0) {
+ syslog(LOG_WARNING, "%s", s);
+ free(s);
+ }
+}
+
+void
+startprinting(printer)
+ const char *printer;
+{
+ struct printer myprinter, *pp = &myprinter;
+ int status;
+
+ init_printer(pp);
+ status = getprintcap(printer, pp);
+ switch(status) {
+ case PCAPERR_OSERR:
+ syslog(LOG_ERR, "can't open printer description file: %m");
exit(1);
- } else if (status == -1) {
+ case PCAPERR_NOTFOUND:
syslog(LOG_ERR, "unknown printer: %s", printer);
exit(1);
- } else if (status == -3)
- fatal("potential reference loop detected in printcap file");
-
- if (cgetstr(bp, "lp", &LP) == -1)
- LP = _PATH_DEFDEVLP;
- if (cgetstr(bp, "rp", &RP) == -1)
- RP = DEFLP;
- if (cgetstr(bp, "lo", &LO) == -1)
- LO = DEFLOCK;
- if (cgetstr(bp, "st", &ST) == -1)
- ST = DEFSTAT;
- if (cgetstr(bp, "lf", &LF) == -1)
- LF = _PATH_CONSOLE;
- if (cgetstr(bp, "sd", &SD) == -1)
- SD = _PATH_DEFSPOOL;
- if (cgetnum(bp, "du", &DU) < 0)
- DU = DEFUID;
- if (cgetstr(bp,"ff", &FF) == -1)
- FF = DEFFF;
- if (cgetnum(bp, "pw", &PW) < 0)
- PW = DEFWIDTH;
- sprintf(&width[2], "%ld", PW);
- if (cgetnum(bp, "pl", &PL) < 0)
- PL = DEFLENGTH;
- if (cgetnum(bp, "ct", &CT) < 0)
- CT = DEFTIMEOUT;
- sprintf(&length[2], "%ld", PL);
- if (cgetnum(bp,"px", &PX) < 0)
- PX = 0;
- sprintf(&pxwidth[2], "%ld", PX);
- if (cgetnum(bp, "py", &PY) < 0)
- PY = 0;
- sprintf(&pxlength[2], "%ld", PY);
- cgetstr(bp, "rm", &RM);
- if ((s = checkremote()))
- syslog(LOG_WARNING, s);
-
- cgetstr(bp, "af", &AF);
- cgetstr(bp, "of", &OF);
- cgetstr(bp, "if", &IF);
- cgetstr(bp, "rf", &RF);
- cgetstr(bp, "tf", &TF);
- cgetstr(bp, "nf", &NF);
- cgetstr(bp, "df", &DF);
- cgetstr(bp, "gf", &GF);
- cgetstr(bp, "vf", &VF);
- cgetstr(bp, "cf", &CF);
- cgetstr(bp, "tr", &TR);
- cgetstr(bp, "ms", &MS);
-
- RS = (cgetcap(bp, "rs", ':') != NULL);
- SF = (cgetcap(bp, "sf", ':') != NULL);
- SH = (cgetcap(bp, "sh", ':') != NULL);
- SB = (cgetcap(bp, "sb", ':') != NULL);
- HL = (cgetcap(bp, "hl", ':') != NULL);
- RW = (cgetcap(bp, "rw", ':') != NULL);
-
- cgetnum(bp, "br", &BR);
-
- tof = (cgetcap(bp, "fo", ':') == NULL);
+ case PCAPERR_TCLOOP:
+ fatal(pp, "potential reference loop detected in printcap file");
+ default:
+ break;
+ }
+ printjob(pp);
}
/*
* Acquire line printer or remote connection.
*/
static void
-openpr()
+openpr(pp)
+ const struct printer *pp;
{
- register int i;
- int dtablesize;
+ int p[2];
char *cp;
- if (!remote && *LP) {
- if (cp = strchr(LP, '@'))
- opennet(cp);
+ if (pp->remote) {
+ openrem(pp);
+ } else if (*pp->lp) {
+ if ((cp = strchr(pp->lp, '@')) != NULL)
+ opennet(pp);
else
- opentty();
- } else if (remote) {
- openrem();
+ opentty(pp);
} else {
syslog(LOG_ERR, "%s: no line printer device or host name",
- printer);
+ pp->printer);
exit(1);
}
/*
* Start up an output filter, if needed.
*/
- if (OF && !IF && !ofilter) {
- int p[2];
-
+ if (pp->filters[LPF_OUTPUT] && !pp->filters[LPF_INPUT] && !ofilter) {
pipe(p);
- if (remote) {
- strcpy(tfile,TFILENAME);
+ if (pp->remote) {
+ strcpy(tfile, TFILENAME);
tfd = mkstemp(tfile);
}
- if ((ofilter = dofork(DOABORT)) == 0) { /* child */
+ if ((ofilter = dofork(pp, DOABORT)) == 0) { /* child */
dup2(p[0], 0); /* pipe is std in */
/* tfile/printer is stdout */
- dup2(remote ? tfd : pfd, 1);
+ dup2(pp->remote ? tfd : pfd, 1);
closelog();
- for (i = 3, dtablesize = getdtablesize();
- i < dtablesize; i++)
- (void) close(i);
- if ((cp = strrchr(OF, '/')) == NULL)
- cp = OF;
+ closeallfds(3);
+ if ((cp = strrchr(pp->filters[LPF_OUTPUT], '/')) == NULL)
+ cp = pp->filters[LPF_OUTPUT];
else
cp++;
- execl(OF, cp, width, length, 0);
- syslog(LOG_ERR, "%s: %s: %m", printer, OF);
+ execl(pp->filters[LPF_OUTPUT], cp, width, length, 0);
+ syslog(LOG_ERR, "%s: %s: %m", pp->printer,
+ pp->filters[LPF_OUTPUT]);
exit(1);
}
(void) close(p[0]); /* close input side */
@@ -1452,28 +1452,28 @@ openpr()
* or to a terminal server on the net
*/
static void
-opennet(cp)
- char *cp;
+opennet(pp)
+ const struct printer *pp;
{
register int i;
- int resp, port;
- char save_ch;
+ int resp;
+ u_long port;
+ char *ep;
void (*savealrm)(int);
- save_ch = *cp;
- *cp = '\0';
- port = atoi(LP);
- if (port <= 0) {
- syslog(LOG_ERR, "%s: bad port number: %s", printer, LP);
+ port = strtoul(pp->lp, &ep, 0);
+ if (*ep != ':' || port > 65536) {
+ syslog(LOG_ERR, "%s: bad port number: %s", pp->printer,
+ pp->lp);
exit(1);
}
- *cp++ = save_ch;
+ ep++;
for (i = 1; ; i = i < 256 ? i << 1 : i) {
resp = -1;
savealrm = signal(SIGALRM, alarmhandler);
- alarm(CT);
- pfd = getport(cp, port);
+ alarm(pp->conn_timeout);
+ pfd = getport(pp, ep, port);
alarm(0);
(void)signal(SIGALRM, savealrm);
if (pfd < 0 && errno == ECONNREFUSED)
@@ -1488,145 +1488,120 @@ opennet(cp)
break;
}
if (i == 1) {
- if (resp < 0)
- pstatus("waiting for %s to come up", LP);
- else
- pstatus("waiting for access to printer on %s", LP);
+ if (resp < 0)
+ pstatus(pp, "waiting for %s to come up",
+ pp->lp);
+ else
+ pstatus(pp,
+ "waiting for access to printer on %s",
+ pp->lp);
}
sleep(i);
}
- pstatus("sending to %s port %d", cp, port);
+ pstatus(pp, "sending to %s port %d", ep, port);
}
/*
* Printer is connected to an RS232 port on this host
*/
static void
-opentty()
+opentty(pp)
+ const struct printer *pp;
{
register int i;
- int resp, port;
for (i = 1; ; i = i < 32 ? i << 1 : i) {
- pfd = open(LP, RW ? O_RDWR : O_WRONLY);
+ pfd = open(pp->lp, pp->rw ? O_RDWR : O_WRONLY);
if (pfd >= 0) {
delay(500);
break;
}
if (errno == ENOENT) {
- syslog(LOG_ERR, "%s: %m", LP);
+ syslog(LOG_ERR, "%s: %m", pp->lp);
exit(1);
}
if (i == 1)
- pstatus("waiting for %s to become ready (offline ?)",
- printer);
+ pstatus(pp,
+ "waiting for %s to become ready (offline?)",
+ pp->printer);
sleep(i);
}
if (isatty(pfd))
- setty();
- pstatus("%s is ready and printing", printer);
+ setty(pp);
+ pstatus(pp, "%s is ready and printing", pp->printer);
}
/*
* Printer is on a remote host
*/
static void
-openrem()
+openrem(pp)
+ const struct printer *pp;
{
- register int i, n;
+ register int i;
int resp;
void (*savealrm)(int);
for (i = 1; ; i = i < 256 ? i << 1 : i) {
resp = -1;
savealrm = signal(SIGALRM, alarmhandler);
- alarm(CT);
- pfd = getport(RM, 0);
+ alarm(pp->conn_timeout);
+ pfd = getport(pp, pp->remote_host, 0);
alarm(0);
(void)signal(SIGALRM, savealrm);
if (pfd >= 0) {
- (void) snprintf(line, sizeof(line), "\2%s\n", RP);
- n = strlen(line);
- if (write(pfd, line, n) == n &&
- (resp = response()) == '\0')
+ if ((writel(pfd, "\2", pp->remote_queue, "\n",
+ (char *)0)
+ == 2 + strlen(pp->remote_queue))
+ && (resp = response(pp)) == 0)
break;
(void) close(pfd);
}
if (i == 1) {
if (resp < 0)
- pstatus("waiting for %s to come up", RM);
+ pstatus(pp, "waiting for %s to come up",
+ pp->remote_host);
else {
- pstatus("waiting for queue to be enabled on %s",
- RM);
+ pstatus(pp,
+ "waiting for queue to be enabled on %s",
+ pp->remote_host);
i = 256;
}
}
sleep(i);
}
- pstatus("sending to %s", RM);
+ pstatus(pp, "sending to %s", pp->remote_host);
}
-struct bauds {
- int baud;
- int speed;
-} bauds[] = {
- 50, B50,
- 75, B75,
- 110, B110,
- 134, B134,
- 150, B150,
- 200, B200,
- 300, B300,
- 600, B600,
- 1200, B1200,
- 1800, B1800,
- 2400, B2400,
- 4800, B4800,
- 9600, B9600,
- 19200, EXTA,
- 38400, EXTB,
- 57600, B57600,
- 115200, B115200,
- 0, 0
-};
-
/*
* setup tty lines.
*/
static void
-setty()
+setty(pp)
+ const struct printer *pp;
{
struct termios ttybuf;
- struct bauds *bp;
if (ioctl(pfd, TIOCEXCL, (char *)0) < 0) {
- syslog(LOG_ERR, "%s: ioctl(TIOCEXCL): %m", printer);
+ syslog(LOG_ERR, "%s: ioctl(TIOCEXCL): %m", pp->printer);
exit(1);
}
if (tcgetattr(pfd, &ttybuf) < 0) {
- syslog(LOG_ERR, "%s: tcgetattr: %m", printer);
+ syslog(LOG_ERR, "%s: tcgetattr: %m", pp->printer);
exit(1);
}
- if (BR > 0) {
- for (bp = bauds; bp->baud; bp++)
- if (BR == bp->baud)
- break;
- if (!bp->baud) {
- syslog(LOG_ERR, "%s: illegal baud rate %d", printer, BR);
- exit(1);
- }
- cfsetspeed(&ttybuf, bp->speed);
- }
- if (MS) {
- char *s = strdup(MS), *tmp;
+ if (pp->baud_rate > 0)
+ cfsetspeed(&ttybuf, pp->baud_rate);
+ if (pp->mode_set) {
+ char *s = strdup(pp->mode_set), *tmp;
- while (tmp = strsep (&s, ",")) {
+ while ((tmp = strsep(&s, ",")) != NULL) {
msearch(tmp, &ttybuf);
}
}
- if (MS || (BR > 0)) {
+ if (pp->mode_set != 0 || pp->baud_rate > 0) {
if (tcsetattr(pfd, TCSAFLUSH, &ttybuf) == -1) {
- syslog(LOG_ERR, "%s: tcsetattr: %m", printer);
+ syslog(LOG_ERR, "%s: tcsetattr: %m", pp->printer);
}
}
}
@@ -1639,15 +1614,16 @@ setty()
static void
#ifdef __STDC__
-pstatus(const char *msg, ...)
+pstatus(const struct printer *pp, const char *msg, ...)
#else
-pstatus(msg, va_alist)
+pstatus(pp, msg, va_alist)
+ const struct printer *pp;
char *msg;
va_dcl
#endif
{
- register int fd;
- char buf[BUFSIZ];
+ int fd;
+ char *buf;
va_list ap;
#ifdef __STDC__
va_start(ap, msg);
@@ -1656,17 +1632,17 @@ pstatus(msg, va_alist)
#endif
umask(0);
- fd = open(ST, O_WRONLY|O_CREAT, 0664);
- if (fd < 0 || flock(fd, LOCK_EX) < 0) {
- syslog(LOG_ERR, "%s: %s: %m", printer, ST);
+ fd = open(pp->status_file, O_WRONLY|O_CREAT|O_EXLOCK, STAT_FILE_MODE);
+ if (fd < 0) {
+ syslog(LOG_ERR, "%s: %s: %m", pp->printer, pp->status_file);
exit(1);
}
ftruncate(fd, 0);
- (void)vsnprintf(buf, sizeof(buf) - 1, msg, ap);
+ vasprintf(&buf, msg, ap);
va_end(ap);
- strcat(buf, "\n");
- (void) write(fd, buf, strlen(buf));
- (void) close(fd);
+ writel(fd, buf, "\n", (char *)0);
+ close(fd);
+ free(buf);
}
void
diff --git a/usr.sbin/lpr/lpd/recvjob.c b/usr.sbin/lpr/lpd/recvjob.c
index 0a10e49..6b1c8b0 100644
--- a/usr.sbin/lpr/lpd/recvjob.c
+++ b/usr.sbin/lpr/lpd/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/lpq/Makefile b/usr.sbin/lpr/lpq/Makefile
index 0240b57..c0938ed 100644
--- a/usr.sbin/lpr/lpq/Makefile
+++ b/usr.sbin/lpr/lpq/Makefile
@@ -1,13 +1,14 @@
-# @(#)Makefile 8.1 (Berkeley) 6/6/93
+# From: @(#)Makefile 8.1 (Berkeley) 6/6/93
+# $Id$
PROG= lpq
-CFLAGS+=-I${.CURDIR}/../common_source
-SRCS= lpq.c displayq.c common.c
+CFLAGS+=-I${.CURDIR}/../common_source ${CWARNFLAGS}
+SRCS= lpq.c
BINOWN= root
BINGRP= daemon
BINMODE=6555
BINDIR= /usr/bin
MAN1= lpq.1
-.PATH: ${.CURDIR}/../common_source
+LDADD= -L${.OBJDIR}/../common_source -llpr
.include <bsd.prog.mk>
diff --git a/usr.sbin/lpr/lpq/lpq.c b/usr.sbin/lpr/lpq/lpq.c
index 9dc9c8a..81151a2 100644
--- a/usr.sbin/lpr/lpq/lpq.c
+++ b/usr.sbin/lpr/lpq/lpq.c
@@ -33,13 +33,17 @@
*/
#ifndef lint
-static char copyright[] =
+static const char copyright[] =
"@(#) Copyright (c) 1983, 1993\n\
The Regents of the University of California. All rights reserved.\n";
#endif /* not lint */
#ifndef lint
+/*
static char sccsid[] = "@(#)lpq.c 8.3 (Berkeley) 5/10/95";
+*/
+static const char rcsid[] =
+ "$Id$";
#endif /* not lint */
/*
@@ -54,12 +58,14 @@ static char sccsid[] = "@(#)lpq.c 8.3 (Berkeley) 5/10/95";
#include <sys/param.h>
-#include <syslog.h>
+#include <ctype.h>
#include <dirent.h>
-#include <unistd.h>
-#include <stdlib.h>
+#include <err.h>
#include <stdio.h>
-#include <ctype.h>
+#include <stdlib.h>
+#include <syslog.h>
+#include <unistd.h>
+
#include "lp.h"
#include "lp.local.h"
#include "pathnames.h"
@@ -71,19 +77,19 @@ int users; /* # of users in user array */
uid_t uid, euid;
-static int ckqueue __P((char *));
+static int ckqueue __P((const struct printer *));
static void usage __P((void));
int
main(argc, argv)
- register int argc;
- register char **argv;
+ int argc;
+ char **argv;
{
- extern char *optarg;
- extern int optind;
- int ch, aflag, lflag;
- char *buf, *cp;
+ int ch, aflag, lflag;
+ char *printer;
+ struct printer myprinter, *pp = &myprinter;
+ printer = NULL;
euid = geteuid();
uid = getuid();
seteuid(uid);
@@ -115,47 +121,64 @@ main(argc, argv)
for (argc -= optind, argv += optind; argc; --argc, ++argv)
if (isdigit(argv[0][0])) {
if (requests >= MAXREQUESTS)
- fatal("too many requests");
+ fatal(0, "too many requests");
requ[requests++] = atoi(*argv);
}
else {
if (users >= MAXUSERS)
- fatal("too many users");
+ fatal(0, "too many users");
user[users++] = *argv;
}
if (aflag) {
- while (cgetnext(&buf, printcapdb) > 0) {
- if (ckqueue(buf) <= 0) {
- free(buf);
- continue; /* no jobs */
+ int more, status;
+
+ more = firstprinter(pp, &status);
+ if (status)
+ goto looperr;
+ while (more) {
+ if (ckqueue(pp) > 0) {
+ printf("%s:\n", pp->printer);
+ displayq(pp, lflag);
+ printf("\n");
}
- for (cp = buf; *cp; cp++)
- if (*cp == '|' || *cp == ':') {
- *cp = '\0';
+ do {
+ more = nextprinter(pp, &status);
+looperr:
+ switch (status) {
+ case PCAPERR_TCOPEN:
+ printf("warning: %s: unresolved "
+ "tc= reference(s) ",
+ pp->printer);
+ case PCAPERR_SUCCESS:
break;
+ default:
+ fatal(pp, pcaperr(status));
}
- printer = buf;
- printf("%s:\n", printer);
- displayq(lflag);
- free(buf);
- printf("\n");
+ } while (more && status);
}
- } else
- displayq(lflag);
+ } else {
+ int status;
+
+ init_printer(pp);
+ status = getprintcap(printer, pp);
+ if (status < 0)
+ fatal(pp, pcaperr(status));
+
+ displayq(pp, lflag);
+ }
exit(0);
}
static int
-ckqueue(cap)
- char *cap;
+ckqueue(pp)
+ const struct printer *pp;
{
register struct dirent *d;
DIR *dirp;
char *spooldir;
- if (cgetstr(cap, "sd", &spooldir) == -1)
- spooldir = _PATH_DEFSPOOL;
+ spooldir = pp->spool_dir;
if ((dirp = opendir(spooldir)) == NULL)
return (-1);
while ((d = readdir(dirp)) != NULL) {
diff --git a/usr.sbin/lpr/lpr/Makefile b/usr.sbin/lpr/lpr/Makefile
index eed68fd..0f02d78 100644
--- a/usr.sbin/lpr/lpr/Makefile
+++ b/usr.sbin/lpr/lpr/Makefile
@@ -1,13 +1,15 @@
-# @(#)Makefile 8.1 (Berkeley) 6/6/93
+# From: @(#)Makefile 8.1 (Berkeley) 6/6/93
+# $Id$
PROG= lpr
-CFLAGS+=-I${.CURDIR}/../common_source
-SRCS= lpr.c startdaemon.c common.c
+CFLAGS+=-I${.CURDIR}/../common_source ${CWARNFLAGS}
+SRCS= lpr.c
BINOWN= root
BINGRP= daemon
BINMODE=6555
BINDIR= /usr/bin
MAN1= lpr.1
.PATH: ${.CURDIR}/../common_source
+LDADD= -L${.OBJDIR}/../common_source -llpr
.include <bsd.prog.mk>
diff --git a/usr.sbin/lpr/lpr/lpr.c b/usr.sbin/lpr/lpr/lpr.c
index a22ccc3..41cfa97 100644
--- a/usr.sbin/lpr/lpr/lpr.c
+++ b/usr.sbin/lpr/lpr/lpr.c
@@ -48,7 +48,7 @@ static const char copyright[] =
static char sccsid[] = "@(#)from: lpr.c 8.4 (Berkeley) 4/28/95";
#endif
static const char rcsid[] =
- "$Id$";
+ "$Id: lpr.c,v 1.21 1997/09/24 06:48:07 charnier Exp $";
#endif /* not lint */
/*
@@ -64,6 +64,7 @@ static const char rcsid[] =
#include <dirent.h>
#include <fcntl.h>
#include <a.out.h>
+#include <err.h>
#include <signal.h>
#include <syslog.h>
#include <pwd.h>
@@ -104,14 +105,14 @@ static struct stat statb;
static void card __P((int, char *));
static int checkwriteperm __P((char*, char *));
-static void chkprinter __P((char *));
+static void chkprinter __P((char *printer, struct printer *pp));
static void cleanup __P((int));
-static void copy __P((int, char []));
-static void fatal2 __P((const char *, ...));
+static void copy __P((const struct printer *, int, char []));
static char *itoa __P((int));
static char *linked __P((char *));
-static char *lmktemp __P((char *, int, int));
-static void mktemps __P((void));
+int main __P((int, char **));
+static char *lmktemp __P((const struct printer *pp, char *, int, int));
+static void mktemps __P((const struct printer *pp));
static int nfile __P((char *));
static int test __P((char *));
static void usage __P((void));
@@ -125,11 +126,13 @@ main(argc, argv)
{
struct passwd *pw;
struct group *gptr;
- register char *arg, *cp;
+ char *arg, *cp, *printer;
char buf[BUFSIZ];
int c, i, f, errs;
struct stat stb;
+ struct printer myprinter, *pp = &myprinter;
+ printer = NULL;
euid = geteuid();
uid = getuid();
seteuid(uid);
@@ -247,27 +250,32 @@ main(argc, argv)
usage();
if (printer == NULL && (printer = getenv("PRINTER")) == NULL)
printer = DEFLP;
- chkprinter(printer);
- if (SC && ncopies > 1)
- fatal2("multiple copies are not allowed");
- if (MC > 0 && ncopies > MC)
- fatal2("only %d copies are allowed", MC);
+ chkprinter(printer, pp);
+ if (pp->no_copies && ncopies > 1)
+ errx(1, "multiple copies are not allowed");
+ if (pp->max_copies > 0 && ncopies > pp->max_copies)
+ errx(1, "only %d copies are allowed", pp->max_copies);
/*
* Get the identity of the person doing the lpr using the same
- * algorithm as lprm.
+ * algorithm as lprm. Actually, not quite -- lprm will override
+ * the login name with "root" if the user is running as root;
+ * the daemon actually checks for the string "root" in its
+ * permission checking. Sigh.
*/
- userid = getuid();
- if (userid != DU || person == 0) {
- if ((pw = getpwuid(userid)) == NULL)
- fatal2("Who are you?");
- person = pw->pw_name;
+ if ((person = getlogin()) == NULL) {
+ userid = getuid();
+ if (userid != pp->daemon_user || person == 0) {
+ if ((pw = getpwuid(userid)) == NULL)
+ errx(1, "Who are you?");
+ person = pw->pw_name;
+ }
}
/*
* Check for restricted group access.
*/
- if (RG != NULL && userid != DU) {
- if ((gptr = getgrnam(RG)) == NULL)
- fatal2("Restricted group specified incorrectly");
+ if (pp->restrict_grp != NULL && userid != pp->daemon_user) {
+ if ((gptr = getgrnam(pp->restrict_grp)) == NULL)
+ errx(1, "Restricted group specified incorrectly");
if (gptr->gr_gid != getgid()) {
while (*gptr->gr_mem != NULL) {
if ((strcmp(person, *gptr->gr_mem)) == 0)
@@ -275,22 +283,23 @@ main(argc, argv)
gptr->gr_mem++;
}
if (*gptr->gr_mem == NULL)
- fatal2("Not a member of the restricted group");
+ errx(1, "Not a member of the restricted group");
}
}
/*
* Check to make sure queuing is enabled if userid is not root.
*/
- (void) snprintf(buf, sizeof(buf), "%s/%s", SD, LO);
- if (userid && stat(buf, &stb) == 0 && (stb.st_mode & 010))
- fatal2("Printer queue is disabled");
+ lock_file_name(pp, buf, sizeof buf);
+ if (userid && stat(buf, &stb) == 0 && (stb.st_mode & LFM_QUEUE_DIS))
+ errx(1, "Printer queue is disabled");
/*
* Initialize the control file.
*/
- mktemps();
+ mktemps(pp);
tfd = nfile(tfname);
seteuid(euid);
- (void) fchown(tfd, DU, -1); /* owned by daemon for protection */
+ (void) fchown(tfd, pp->daemon_user, -1);
+ /* owned by daemon for protection */
seteuid(uid);
card('H', host);
card('P', person);
@@ -299,7 +308,8 @@ main(argc, argv)
if (argc == 0)
jobname = "stdin";
else
- jobname = (arg = strrchr(argv[0], '/')) ? arg+1 : argv[0];
+ jobname = ((arg = strrchr(argv[0], '/'))
+ ? arg + 1 : argv[0]);
}
card('J', jobname);
card('C', class);
@@ -320,11 +330,11 @@ main(argc, argv)
* Read the files and spool them.
*/
if (argc == 0)
- copy(0, " ");
+ copy(pp, 0, " ");
else while (argc--) {
if (argv[0][0] == '-' && argv[0][1] == '\0') {
/* use stdin */
- copy(0, " ");
+ copy(pp, 0, " ");
argv++;
continue;
}
@@ -352,7 +362,7 @@ main(argc, argv)
if ((i = open(arg, O_RDONLY)) < 0) {
printf("%s: cannot open %s\n", name, arg);
} else {
- copy(i, arg);
+ copy(pp, i, arg);
(void) close(i);
if (f && unlink(arg) < 0)
printf("%s: %s: not removed\n", name, arg);
@@ -387,7 +397,7 @@ main(argc, argv)
seteuid(uid);
if (qflag) /* just q things up */
exit(0);
- if (!startdaemon(printer))
+ if (!startdaemon(pp))
printf("jobs queued, but cannot start daemon.\n");
exit(0);
}
@@ -400,7 +410,8 @@ main(argc, argv)
* Create the file n and copy from file descriptor f.
*/
static void
-copy(f, n)
+copy(pp, f, n)
+ const struct printer *pp;
int f;
char n[];
{
@@ -424,8 +435,9 @@ copy(f, n)
if (nc >= BUFSIZ) {
nc -= BUFSIZ;
nr++;
- if (MX > 0 && nr > MX) {
- printf("%s: %s: copy file is too large\n", name, n);
+ if (pp->max_blocks > 0 && nr > pp->max_blocks) {
+ printf("%s: %s: copy file is too large\n",
+ name, n);
break;
}
}
@@ -669,27 +681,23 @@ itoa(i)
* Perform lookup for printer name or abbreviation --
*/
static void
-chkprinter(s)
+chkprinter(s, pp)
char *s;
+ struct printer *pp;
{
int status;
- if ((status = cgetent(&bp, printcapdb, s)) == -2)
- fatal2("cannot open printer description file");
- else if (status == -1)
- fatal2("%s: unknown printer", s);
- if (cgetstr(bp, "sd", &SD) == -1)
- SD = _PATH_DEFSPOOL;
- if (cgetstr(bp, "lo", &LO) == -1)
- LO = DEFLOCK;
- cgetstr(bp, "rg", &RG);
- if (cgetnum(bp, "mx", &MX) < 0)
- MX = DEFMX;
- if (cgetnum(bp,"mc", &MC) < 0)
- MC = DEFMAXCOPIES;
- if (cgetnum(bp, "du", &DU) < 0)
- DU = DEFUID;
- SC = (cgetcap(bp, "sc", ':') != NULL);
+ init_printer(pp);
+ status = getprintcap(s, pp);
+ switch(status) {
+ case PCAPERR_OSERR:
+ case PCAPERR_TCLOOP:
+ errx(1, "%s: %s", s, pcaperr(status));
+ case PCAPERR_NOTFOUND:
+ errx(1, "%s: unknown printer", s);
+ case PCAPERR_TCOPEN:
+ warnx("%s: unresolved tc= reference(s)", s);
+ }
}
/*
@@ -709,14 +717,14 @@ usage()
* Make the temp files.
*/
static void
-mktemps()
+mktemps(pp)
+ const struct printer *pp;
{
register int len, fd, n;
register char *cp;
char buf[BUFSIZ];
- char *lmktemp();
- (void) snprintf(buf, sizeof(buf), "%s/.seq", SD);
+ (void) snprintf(buf, sizeof(buf), "%s/.seq", pp->spool_dir);
seteuid(euid);
if ((fd = open(buf, O_RDWR|O_CREAT, 0661)) < 0) {
printf("%s: cannot create %s\n", name, buf);
@@ -735,11 +743,11 @@ mktemps()
n = n * 10 + (*cp++ - '0');
}
}
- len = strlen(SD) + strlen(host) + 8;
- tfname = lmktemp("tf", n, len);
- cfname = lmktemp("cf", n, len);
- dfname = lmktemp("df", n, len);
- inchar = strlen(SD) + 3;
+ len = strlen(pp->spool_dir) + strlen(host) + 8;
+ tfname = lmktemp(pp, "tf", n, len);
+ cfname = lmktemp(pp, "cf", n, len);
+ dfname = lmktemp(pp, "df", n, len);
+ inchar = strlen(pp->spool_dir) + 3;
n = (n + 1) % 1000;
(void) lseek(fd, (off_t)0, 0);
snprintf(buf, sizeof(buf), "%03d\n", n);
@@ -751,42 +759,15 @@ mktemps()
* Make a temp file name.
*/
static char *
-lmktemp(id, num, len)
+lmktemp(pp, id, num, len)
+ const struct printer *pp;
char *id;
int num, len;
{
register char *s;
if ((s = malloc(len)) == NULL)
- fatal2("out of memory");
- (void) snprintf(s, len, "%s/%sA%03d%s", SD, id, num, host);
+ errx(1, "out of memory");
+ (void) snprintf(s, len, "%s/%sA%03d%s", pp->spool_dir, id, num, host);
return(s);
}
-
-#ifdef __STDC__
-#include <stdarg.h>
-#else
-#include <varargs.h>
-#endif
-
-static void
-#ifdef __STDC__
-fatal2(const char *msg, ...)
-#else
-fatal2(msg, va_alist)
- char *msg;
- va_dcl
-#endif
-{
- va_list ap;
-#ifdef __STDC__
- va_start(ap, msg);
-#else
- va_start(ap);
-#endif
- printf("%s: ", name);
- vprintf(msg, ap);
- putchar('\n');
- va_end(ap);
- exit(1);
-}
diff --git a/usr.sbin/lpr/lprm/Makefile b/usr.sbin/lpr/lprm/Makefile
index 77c57e5..cb597c5 100644
--- a/usr.sbin/lpr/lprm/Makefile
+++ b/usr.sbin/lpr/lprm/Makefile
@@ -1,13 +1,15 @@
-# @(#)Makefile 8.1 (Berkeley) 6/6/93
+# From: @(#)Makefile 8.1 (Berkeley) 6/6/93
+# $Id$
PROG= lprm
-CFLAGS+=-I${.CURDIR}/../common_source
-SRCS= lprm.c rmjob.c startdaemon.c common.c
+CFLAGS+=-I${.CURDIR}/../common_source -Wall -Werror
+SRCS= lprm.c
BINOWN= root
BINGRP= daemon
BINMODE=6555
BINDIR= /usr/bin
MAN1= lprm.1
.PATH: ${.CURDIR}/../common_source
+LDADD= -L${.OBJDIR}/../common_source -llpr
.include <bsd.prog.mk>
diff --git a/usr.sbin/lpr/lprm/lprm.c b/usr.sbin/lpr/lprm/lprm.c
index e124744..676869a 100644
--- a/usr.sbin/lpr/lprm/lprm.c
+++ b/usr.sbin/lpr/lprm/lprm.c
@@ -43,7 +43,7 @@ static const char copyright[] =
static char sccsid[] = "@(#)lprm.c 8.1 (Berkeley) 6/6/93";
#endif
static const char rcsid[] =
- "$Id$";
+ "$Id: lprm.c,v 1.3 1997/09/24 06:48:17 charnier Exp $";
#endif /* not lint */
/*
@@ -89,21 +89,33 @@ main(argc, argv)
int argc;
char *argv[];
{
- register char *arg;
+ char *arg, *printer;
struct passwd *p;
+ static char root[] = "root";
+ printer = NULL;
uid = getuid();
euid = geteuid();
seteuid(uid); /* be safe */
name = argv[0];
gethostname(host, sizeof(host));
openlog("lpd", 0, LOG_LPR);
- if ((p = getpwuid(getuid())) == NULL)
- fatal("Who are you?");
- if (strlen(p->pw_name) >= sizeof(luser))
- fatal("Your name is too long");
- strcpy(luser, p->pw_name);
- person = luser;
+
+ /*
+ * Bogus code later checks for string equality between
+ * `person' and "root", so if we are root, better make sure
+ * that code will succeed.
+ */
+ if (getuid() == 0) {
+ person = root;
+ } else if ((person = getlogin()) == NULL) {
+ if ((p = getpwuid(getuid())) == NULL)
+ fatal(0, "Who are you?");
+ if (strlen(p->pw_name) >= sizeof(luser))
+ fatal(0, "Your name is too long");
+ strcpy(luser, p->pw_name);
+ person = luser;
+ }
while (--argc) {
if ((arg = *++argv)[0] == '-')
switch (arg[1]) {
@@ -128,11 +140,11 @@ main(argc, argv)
usage();
if (isdigit(arg[0])) {
if (requests >= MAXREQUESTS)
- fatal("Too many requests");
+ fatal(0, "Too many requests");
requ[requests++] = atoi(arg);
} else {
if (users >= MAXUSERS)
- fatal("Too many users");
+ fatal(0, "Too many users");
user[users++] = arg;
}
}
@@ -140,7 +152,7 @@ main(argc, argv)
if (printer == NULL && (printer = getenv("PRINTER")) == NULL)
printer = DEFLP;
- rmjob();
+ rmjob(printer);
exit(0);
}
diff --git a/usr.sbin/lpr/pac/Makefile b/usr.sbin/lpr/pac/Makefile
index 1f49dea..758045c 100644
--- a/usr.sbin/lpr/pac/Makefile
+++ b/usr.sbin/lpr/pac/Makefile
@@ -1,10 +1,12 @@
-# @(#)Makefile 8.1 (Berkeley) 6/6/93
+# From: @(#)Makefile 8.1 (Berkeley) 6/6/93
+# $Id$
PROG= pac
CFLAGS+=-I${.CURDIR}/../common_source
MAN8= pac.8
-SRCS= pac.c common.c
+SRCS= pac.c
.PATH: ${.CURDIR}/../common_source
+LDADD= -L${.OBJDIR}/../common_source -llpr
.include "../../Makefile.inc"
.include <bsd.prog.mk>
diff --git a/usr.sbin/lpr/pac/pac.c b/usr.sbin/lpr/pac/pac.c
index c89a526..bfb0f51 100644
--- a/usr.sbin/lpr/pac/pac.c
+++ b/usr.sbin/lpr/pac/pac.c
@@ -43,7 +43,7 @@ static const char copyright[] =
static char sccsid[] = "@(#)pac.c 8.1 (Berkeley) 6/6/93";
#endif
static const char rcsid[] =
- "$Id$";
+ "$Id: pac.c,v 1.7 1997/09/24 06:48:24 charnier Exp $";
#endif /* not lint */
/*
@@ -110,9 +110,10 @@ main(argc, argv)
int argc;
char **argv;
{
- register FILE *acct;
- register char *cp;
+ FILE *acct;
+ char *cp, *printer;
+ printer = NULL;
euid = geteuid(); /* these aren't used in pac(1) */
uid = getuid();
while (--argc) {
@@ -433,21 +434,22 @@ chkprinter(s)
register char *s;
{
int stat;
+ struct printer myprinter, *pp = &myprinter;
- if ((stat = cgetent(&bp, printcapdb, s)) == -2) {
- printf("pac: can't open printer description file\n");
+ init_printer(&myprinter);
+ stat = getprintcap(s, pp);
+ switch(stat) {
+ case PCAPERR_OSERR:
+ printf("pac: getprintcap: %s\n", pcaperr(stat));
exit(3);
- } else if (stat == -1)
- return(0);
- else if (stat == -3)
- fatal("potential reference loop detected in printcap file");
-
- if (cgetstr(bp, "af", &acctfile) == -1) {
- printf("accounting not enabled for printer %s\n", printer);
- exit(2);
+ case PCAPERR_NOTFOUND:
+ return 0;
+ case PCAPERR_TCLOOP:
+ fatal(pp, "%s", pcaperr(stat));
}
- if (!pflag && (cgetnum(bp, "pc", &price100) == 0))
- price = price100/10000.0;
+ acctfile = pp->acct_file;
+ if (!pflag && pp->price100)
+ price = pp->price100/10000.0;
sumfile = (char *) calloc(sizeof(char), strlen(acctfile)+5);
if (sumfile == NULL)
errx(1, "calloc failed");
diff --git a/usr.sbin/lpr/runqueue/extern.h b/usr.sbin/lpr/runqueue/extern.h
index 718bef3..db732f5 100644
--- a/usr.sbin/lpr/runqueue/extern.h
+++ b/usr.sbin/lpr/runqueue/extern.h
@@ -30,7 +30,8 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * @(#)extern.h 8.1 (Berkeley) 6/6/93
+ * From: @(#)extern.h 8.1 (Berkeley) 6/6/93
+ * $Id$
*/
#include <sys/cdefs.h>
@@ -38,5 +39,10 @@
extern char scnkey[][HEIGHT]; /* in lpdchar.c */
extern char fromb[];
-void printjob __P((void));
-void recvjob __P((void));
+struct printer;
+
+__BEGIN_DECLS
+void printjob __P((struct printer *pp));
+void startprinting __P((const char *printer));
+void recvjob __P((const char *printer));
+__END_DECLS
diff --git a/usr.sbin/lpr/runqueue/lpdchar.c b/usr.sbin/lpr/runqueue/lpdchar.c
index 4d24ffd..f5c542a 100644
--- a/usr.sbin/lpr/runqueue/lpdchar.c
+++ b/usr.sbin/lpr/runqueue/lpdchar.c
@@ -32,7 +32,11 @@
*/
#ifndef lint
+/*
static char sccsid[] = "@(#)lpdchar.c 8.1 (Berkeley) 6/6/93";
+*/
+static const char rcsid[] =
+ "$Id$";
#endif /* not lint */
/*
diff --git a/usr.sbin/lpr/runqueue/modes.c b/usr.sbin/lpr/runqueue/modes.c
index 7e3dcd9..c85c669 100644
--- a/usr.sbin/lpr/runqueue/modes.c
+++ b/usr.sbin/lpr/runqueue/modes.c
@@ -29,12 +29,14 @@
* 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.
- *
- * $Id$
*/
#ifndef lint
+/*
static char sccsid[] = "@(#)modes.c 8.3 (Berkeley) 4/2/94";
+*/
+static const char rcsid[] =
+ "$Id$";
#endif /* not lint */
#include <stddef.h>
diff --git a/usr.sbin/lpr/runqueue/printjob.c b/usr.sbin/lpr/runqueue/printjob.c
index cff1d9f..929d6a3 100644
--- a/usr.sbin/lpr/runqueue/printjob.c
+++ b/usr.sbin/lpr/runqueue/printjob.c
@@ -33,13 +33,17 @@
*/
#ifndef lint
-static char copyright[] =
+static const char copyright[] =
"@(#) Copyright (c) 1983, 1993\n\
The Regents of the University of California. All rights reserved.\n";
#endif /* not lint */
#ifndef lint
+/*
static char sccsid[] = "@(#)printjob.c 8.7 (Berkeley) 5/10/95";
+*/
+static const char rcsid[] =
+ "$Id$";
#endif /* not lint */
@@ -99,7 +103,6 @@ static int pfd; /* prstatic inter file descriptor */
static int pid; /* pid of lpd process */
static int prchild; /* id of pr process */
static char title[80]; /* ``pr'' title */
-static int tof; /* true if at top of form */
static char class[32]; /* classification field */
static char fromhost[32]; /* user's host machine */
@@ -117,27 +120,32 @@ static char tfile[] = TFILENAME; /* file name for filter output */
static void abortpr __P((int));
static void alarmhandler __P((int));
-static void banner __P((char *, char *));
-static int dofork __P((int));
+static void banner __P((struct printer *pp, char *name1, char *name2));
+static int dofork __P((const struct printer *pp, int action));
static int dropit __P((int));
-static void init __P((void));
-static void openpr __P((void));
-static void opennet __P((char *));
-static void opentty __P((void));
-static void openrem __P((void));
-static int print __P((int, char *));
-static int printit __P((char *));
-static void pstatus __P((const char *, ...));
-static char response __P((void));
-static void scan_out __P((int, char *, int));
+static void init __P((struct printer *pp));
+static void openpr __P((const struct printer *pp));
+static void opennet __P((const struct printer *pp));
+static void opentty __P((const struct printer *pp));
+static void openrem __P((const struct printer *pp));
+static int print __P((struct printer *pp, int format, char *file));
+static int printit __P((struct printer *pp, char *file));
+static void pstatus __P((const struct printer *, const char *, ...));
+static char response __P((const struct printer *pp));
+static void scan_out __P((struct printer *pp, int scfd, char *scsp,
+ int dlm));
static char *scnline __P((int, char *, int));
-static int sendfile __P((int, char *, char));
-static int sendit __P((char *));
-static void sendmail __P((char *, int));
-static void setty __P((void));
+static int sendfile __P((struct printer *pp, int type, char *file,
+ int format));
+static int sendit __P((struct printer *pp, char *file));
+static void sendmail __P((struct printer *pp, char *user, int bombed));
+static void setty __P((const struct printer *pp));
+
+void msearch __P((char *, struct termios *));
void
-printjob()
+printjob(pp)
+ struct printer *pp;
{
struct stat stb;
register struct queue *q, **qp;
@@ -146,11 +154,11 @@ printjob()
off_t pidoff;
int errcnt, count = 0;
- init(); /* set up capabilities */
- (void) write(1, "", 1); /* ack that daemon is started */
+ init(pp); /* set up capabilities */
+ (void) write(1, "", 1); /* ack that daemon is started */
(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, LOG_FILE_MODE) < 0) {
+ syslog(LOG_ERR, "%s: %m", pp->log_file);
(void) open(_PATH_DEVNULL, O_WRONLY);
}
setgid(getegid());
@@ -166,21 +174,23 @@ printjob()
/*
* uses short form file names
*/
- if (chdir(SD) < 0) {
- syslog(LOG_ERR, "%s: %m", SD);
+ if (chdir(pp->spool_dir) < 0) {
+ syslog(LOG_ERR, "%s: %m", pp->spool_dir);
exit(1);
}
- if (stat(LO, &stb) == 0 && (stb.st_mode & 0100))
+ if (stat(pp->lock_file, &stb) == 0 && (stb.st_mode & LFM_PRINT_DIS))
exit(0); /* printing disabled */
- lfd = open(LO, O_WRONLY|O_CREAT, 0644);
+ lfd = open(pp->lock_file, O_WRONLY|O_CREAT|O_EXLOCK|O_NONBLOCK,
+ LOCK_FILE_MODE);
if (lfd < 0) {
- syslog(LOG_ERR, "%s: %s: %m", printer, LO);
+ if (errno == EWOULDBLOCK) /* active daemon present */
+ exit(0);
+ syslog(LOG_ERR, "%s: %s: %m", pp->printer, pp->lock_file);
exit(1);
}
- if (flock(lfd, LOCK_EX|LOCK_NB) < 0) {
- if (errno == EWOULDBLOCK) /* active deamon present */
- exit(0);
- syslog(LOG_ERR, "%s: %s: %m", printer, LO);
+ /* turn off non-blocking mode (was turned on for lock effects only) */
+ if (fcntl(lfd, F_SETFL, 0) < 0) {
+ syslog(LOG_ERR, "%s: %s: %m", pp->printer, pp->lock_file);
exit(1);
}
ftruncate(lfd, 0);
@@ -190,23 +200,25 @@ printjob()
sprintf(line, "%u\n", pid);
pidoff = i = strlen(line);
if (write(lfd, line, i) != i) {
- syslog(LOG_ERR, "%s: %s: %m", printer, LO);
+ syslog(LOG_ERR, "%s: %s: %m", pp->printer, pp->lock_file);
exit(1);
}
/*
* search the spool directory for work and sort by queue order.
*/
- if ((nitems = getq(&queue)) < 0) {
- syslog(LOG_ERR, "%s: can't scan %s", printer, SD);
+ if ((nitems = getq(pp, &queue)) < 0) {
+ syslog(LOG_ERR, "%s: can't scan %s", pp->printer,
+ pp->spool_dir);
exit(1);
}
if (nitems == 0) /* no work to do */
exit(0);
- if (stb.st_mode & 01) { /* reset queue flag */
- if (fchmod(lfd, stb.st_mode & 0776) < 0)
- syslog(LOG_ERR, "%s: %s: %m", printer, LO);
+ if (stb.st_mode & LFM_RESET_QUE) { /* reset queue flag */
+ if (fchmod(lfd, stb.st_mode & ~LFM_RESET_QUE) < 0)
+ syslog(LOG_ERR, "%s: %s: %m", pp->printer,
+ pp->lock_file);
}
- openpr(); /* open printer or remote */
+ openpr(pp); /* open printer or remote */
again:
/*
* we found something to do now do it --
@@ -223,26 +235,28 @@ again:
(void) snprintf(line, sizeof(line), "%s\n", q->q_name);
i = strlen(line);
if (write(lfd, line, i) != i)
- syslog(LOG_ERR, "%s: %s: %m", printer, LO);
- if (!remote)
- i = printit(q->q_name);
+ syslog(LOG_ERR, "%s: %s: %m", pp->printer,
+ pp->lock_file);
+ if (!pp->remote)
+ i = printit(pp, q->q_name);
else
- i = sendit(q->q_name);
+ i = sendit(pp, q->q_name);
/*
* Check to see if we are supposed to stop printing or
* if we are to rebuild the queue.
*/
if (fstat(lfd, &stb) == 0) {
/* stop printing before starting next job? */
- if (stb.st_mode & 0100)
+ if (stb.st_mode & LFM_PRINT_DIS)
goto done;
/* rebuild queue (after lpc topq) */
- if (stb.st_mode & 01) {
- for (free((char *) q); nitems--; free((char *) q))
+ if (stb.st_mode & LFM_RESET_QUE) {
+ for (free(q); nitems--; free(q))
q = *qp++;
- if (fchmod(lfd, stb.st_mode & 0776) < 0)
+ if (fchmod(lfd, stb.st_mode & ~LFM_RESET_QUE)
+ < 0)
syslog(LOG_WARNING, "%s: %s: %m",
- printer, LO);
+ pp->printer, pp->lock_file);
break;
}
}
@@ -250,7 +264,7 @@ again:
count++;
else if (i == REPRINT && ++errcnt < 5) {
/* try reprinting the job */
- syslog(LOG_INFO, "restarting %s", printer);
+ syslog(LOG_INFO, "restarting %s", pp->printer);
if (ofilter > 0) {
kill(ofilter, SIGCONT); /* to be sure */
(void) close(ofd);
@@ -260,37 +274,43 @@ again:
}
(void) close(pfd); /* close printer */
if (ftruncate(lfd, pidoff) < 0)
- syslog(LOG_WARNING, "%s: %s: %m", printer, LO);
- openpr(); /* try to reopen printer */
+ syslog(LOG_WARNING, "%s: %s: %m",
+ pp->printer, pp->lock_file);
+ openpr(pp); /* try to reopen printer */
goto restart;
} else {
- syslog(LOG_WARNING, "%s: job could not be %s (%s)", printer,
- remote ? "sent to remote host" : "printed", q->q_name);
+ syslog(LOG_WARNING, "%s: job could not be %s (%s)",
+ pp->printer,
+ pp->remote ? "sent to remote host" : "printed",
+ q->q_name);
if (i == REPRINT) {
/* ensure we don't attempt this job again */
(void) unlink(q->q_name);
q->q_name[0] = 'd';
(void) unlink(q->q_name);
if (logname[0])
- sendmail(logname, FATALERR);
+ sendmail(pp, logname, FATALERR);
}
}
}
- free((char *) queue);
+ free(queue);
/*
* search the spool directory for more work.
*/
- if ((nitems = getq(&queue)) < 0) {
- syslog(LOG_ERR, "%s: can't scan %s", printer, SD);
+ if ((nitems = getq(pp, &queue)) < 0) {
+ syslog(LOG_ERR, "%s: can't scan %s", pp->printer,
+ pp->spool_dir);
exit(1);
}
if (nitems == 0) { /* no more work to do */
done:
if (count > 0) { /* Files actually printed */
- if (!SF && !tof)
- (void) write(ofd, FF, strlen(FF));
- if (TR != NULL) /* output trailer */
- (void) write(ofd, TR, strlen(TR));
+ if (!pp->no_formfeed && !pp->tof)
+ (void) write(ofd, pp->form_feed,
+ strlen(pp->form_feed));
+ if (pp->trailer != NULL) /* output trailer */
+ (void) write(ofd, pp->trailer,
+ strlen(pp->trailer));
}
(void) close(ofd);
(void) wait(NULL);
@@ -314,7 +334,8 @@ char ifonts[4][40] = {
* and performing the various actions.
*/
static int
-printit(file)
+printit(pp, file)
+ struct printer *pp;
char *file;
{
register int i;
@@ -325,7 +346,7 @@ printit(file)
* open control file; ignore if no longer there.
*/
if ((cfp = fopen(file, "r")) == NULL) {
- syslog(LOG_INFO, "%s: %s: %m", printer, file);
+ syslog(LOG_INFO, "%s: %s: %m", pp->printer, file);
return(OK);
}
/*
@@ -333,7 +354,7 @@ printit(file)
*/
for (i = 0; i < 4; i++)
strcpy(fonts[i], ifonts[i]);
- sprintf(&width[2], "%ld", PW);
+ sprintf(&width[2], "%ld", pp->page_width);
strcpy(indent+2, "0");
/*
@@ -389,10 +410,10 @@ printit(file)
case 'P':
strncpy(logname, line+1, sizeof(logname) - 1);
logname[sizeof(logname) - 1] = '\0';
- if (RS) { /* restricted */
+ if (pp->restricted) { /* restricted */
if (getpwnam(logname) == NULL) {
bombed = NOACCT;
- sendmail(line+1, bombed);
+ sendmail(pp, line+1, bombed);
goto pass2;
}
}
@@ -433,8 +454,8 @@ printit(file)
continue;
case 'L': /* identification line */
- if (!SH && !HL)
- banner(line+1, jobname);
+ if (!pp->no_header && !pp->header_last)
+ banner(pp, line+1, jobname);
continue;
case '1': /* troff fonts */
@@ -459,7 +480,7 @@ printit(file)
continue;
default: /* some file to print */
- switch (i = print(line[0], line+1)) {
+ switch (i = print(pp, line[0], line+1)) {
case ERROR:
if (bombed == OK)
bombed = FATALERR;
@@ -470,7 +491,7 @@ printit(file)
case FILTERERR:
case ACCESS:
bombed = i;
- sendmail(logname, bombed);
+ sendmail(pp, logname, bombed);
}
title[0] = '\0';
continue;
@@ -489,13 +510,13 @@ pass2:
while (getline(cfp))
switch (line[0]) {
case 'L': /* identification line */
- if (!SH && HL)
- banner(line+1, jobname);
+ if (!pp->no_header && pp->header_last)
+ banner(pp, line+1, jobname);
continue;
case 'M':
if (bombed < NOACCT) /* already sent if >= NOACCT */
- sendmail(line+1, bombed);
+ sendmail(pp, line+1, bombed);
continue;
case 'U':
@@ -522,13 +543,14 @@ pass2:
* stderr as the log file, and must not ignore SIGINT.
*/
static int
-print(format, file)
+print(pp, format, file)
+ struct printer *pp;
int format;
char *file;
{
register int n;
register char *prog;
- int dtablesize, fi, fo;
+ int fi, fo;
FILE *fp;
char *av[15], buf[BUFSIZ];
int pid, p[2], stopped = 0;
@@ -545,12 +567,13 @@ print(format, file)
if ((stb.st_mode & S_IFMT) == S_IFLNK && fstat(fi, &stb) == 0 &&
(stb.st_dev != fdev || stb.st_ino != fino))
return(ACCESS);
- if (!SF && !tof) { /* start on a fresh page */
- (void) write(ofd, FF, strlen(FF));
- tof = 1;
+ if (!pp->no_formfeed && !pp->tof) { /* start on a fresh page */
+ (void) write(ofd, pp->form_feed, strlen(pp->form_feed));
+ pp->tof = 1;
}
- if (IF == NULL && (format == 'f' || format == 'l')) {
- tof = 0;
+ if (pp->filters[LPF_INPUT] == NULL
+ && (format == 'f' || format == 'l')) {
+ pp->tof = 0;
while ((n = read(fi, buf, BUFSIZ)) > 0)
if (write(ofd, buf, n) != n) {
(void) close(fi);
@@ -561,7 +584,7 @@ print(format, file)
}
switch (format) {
case 'p': /* print file using 'pr' */
- if (IF == NULL) { /* use output filter */
+ if (pp->filters[LPF_INPUT] == NULL) { /* use output filter */
prog = _PATH_PR;
av[0] = "pr";
av[1] = width;
@@ -574,13 +597,11 @@ print(format, file)
goto start;
}
pipe(p);
- if ((prchild = dofork(DORETURN)) == 0) { /* child */
+ if ((prchild = dofork(pp, DORETURN)) == 0) { /* child */
dup2(fi, 0); /* file is stdin */
dup2(p[1], 1); /* pipe is stdout */
closelog();
- for (n = 3, dtablesize = getdtablesize();
- n < dtablesize; n++)
- (void) close(n);
+ closeallfds(3);
execl(_PATH_PR, "pr", width, length,
"-h", *title ? title : " ", "-F", 0);
syslog(LOG_ERR, "cannot execl %s", _PATH_PR);
@@ -595,14 +616,14 @@ print(format, file)
}
fi = p[0]; /* use pipe for input */
case 'f': /* print plain text file */
- prog = IF;
+ prog = pp->filters[LPF_INPUT];
av[1] = width;
av[2] = length;
av[3] = indent;
n = 4;
break;
case 'l': /* like 'f' but pass control characters */
- prog = IF;
+ prog = pp->filters[LPF_INPUT];
av[1] = "-c";
av[2] = width;
av[3] = length;
@@ -610,7 +631,7 @@ print(format, file)
n = 5;
break;
case 'r': /* print a fortran text file */
- prog = RF;
+ prog = pp->filters[LPF_FORTRAN];
av[1] = width;
av[2] = length;
n = 3;
@@ -620,7 +641,8 @@ print(format, file)
case 'd': /* print tex output */
(void) unlink(".railmag");
if ((fo = creat(".railmag", FILMOD)) < 0) {
- syslog(LOG_ERR, "%s: cannot create .railmag", printer);
+ syslog(LOG_ERR, "%s: cannot create .railmag",
+ pp->printer);
(void) unlink(".railmag");
} else {
for (n = 0; n < 4; n++) {
@@ -632,25 +654,27 @@ print(format, file)
}
(void) close(fo);
}
- prog = (format == 't') ? TF : (format == 'n') ? NF : DF;
+ prog = (format == 't') ? pp->filters[LPF_TROFF]
+ : ((format == 'n') ? pp->filters[LPF_DITROFF]
+ : pp->filters[LPF_DVI]);
av[1] = pxwidth;
av[2] = pxlength;
n = 3;
break;
case 'c': /* print cifplot output */
- prog = CF;
+ prog = pp->filters[LPF_CIFPLOT];
av[1] = pxwidth;
av[2] = pxlength;
n = 3;
break;
case 'g': /* print plot(1G) output */
- prog = GF;
+ prog = pp->filters[LPF_GRAPH];
av[1] = pxwidth;
av[2] = pxlength;
n = 3;
break;
case 'v': /* print raster output */
- prog = VF;
+ prog = pp->filters[LPF_RASTER];
av[1] = pxwidth;
av[2] = pxlength;
n = 3;
@@ -658,14 +682,14 @@ print(format, file)
default:
(void) close(fi);
syslog(LOG_ERR, "%s: illegal format character '%c'",
- printer, format);
+ pp->printer, format);
return(ERROR);
}
if (prog == NULL) {
(void) close(fi);
syslog(LOG_ERR,
"%s: no filter found in printcap for format character '%c'",
- printer, format);
+ pp->printer, format);
return(ERROR);
}
if ((av[0] = strrchr(prog, '/')) != NULL)
@@ -676,7 +700,7 @@ print(format, file)
av[n++] = logname;
av[n++] = "-h";
av[n++] = fromhost;
- av[n++] = AF;
+ av[n++] = pp->acct_file;
av[n] = 0;
fo = pfd;
if (ofilter > 0) { /* stop output filter */
@@ -687,22 +711,23 @@ print(format, file)
if (status.w_stopval != WSTOPPED) {
(void) close(fi);
syslog(LOG_WARNING,
- "%s: output filter died (retcode=%d termsig=%d)",
- printer, status.w_retcode, status.w_termsig);
+ "%s: output filter died "
+ "(retcode=%d termsig=%d)",
+ pp->printer, status.w_retcode,
+ status.w_termsig);
return(REPRINT);
}
stopped++;
}
start:
- if ((child = dofork(DORETURN)) == 0) { /* child */
+ if ((child = dofork(pp, DORETURN)) == 0) { /* child */
dup2(fi, 0);
dup2(fo, 1);
n = open(tempfile, O_WRONLY|O_CREAT|O_TRUNC, 0664);
if (n >= 0)
dup2(n, 2);
closelog();
- for (n = 3, dtablesize = getdtablesize(); n < dtablesize; n++)
- (void) close(n);
+ closeallfds(3);
execv(prog, av);
syslog(LOG_ERR, "cannot execv %s", prog);
exit(2);
@@ -721,7 +746,7 @@ start:
exit(1);
}
}
- tof = 0;
+ pp->tof = 0;
/* Copy filter output to "lf" logfile */
if ((fp = fopen(tempfile, "r"))) {
@@ -732,12 +757,12 @@ start:
if (!WIFEXITED(status)) {
syslog(LOG_WARNING, "%s: filter '%c' terminated (termsig=%d)",
- printer, format, status.w_termsig);
+ pp->printer, format, status.w_termsig);
return(ERROR);
}
switch (status.w_retcode) {
case 0:
- tof = 1;
+ pp->tof = 1;
return(OK);
case 1:
return(REPRINT);
@@ -745,7 +770,7 @@ start:
return(ERROR);
default:
syslog(LOG_WARNING, "%s: filter '%c' exited (retcode=%d)",
- printer, format, status.w_retcode);
+ pp->printer, format, status.w_retcode);
return(FILTERERR);
}
}
@@ -756,7 +781,8 @@ start:
* 0 if all is well.
*/
static int
-sendit(file)
+sendit(pp, file)
+ struct printer *pp;
char *file;
{
register int i, err = OK;
@@ -801,9 +827,9 @@ sendit(file)
strncpy(class, line+1, sizeof(class) - 1);
} else if (line[0] == 'P') {
strncpy(logname, line+1, sizeof(logname) - 1);
- if (RS) { /* restricted */
+ if (pp->restricted) { /* restricted */
if (getpwnam(logname) == NULL) {
- sendmail(line+1, NOACCT);
+ sendmail(pp, line+1, NOACCT);
err = ERROR;
break;
}
@@ -812,10 +838,10 @@ sendit(file)
strncpy(indent+2, line+1, sizeof(indent) - 3);
} else if (line[0] >= 'a' && line[0] <= 'z') {
strcpy(last, line);
- while (i = getline(cfp))
+ while ((i = getline(cfp)) != 0)
if (strcmp(last, line))
break;
- switch (sendfile('\3', last+1, *last)) {
+ switch (sendfile(pp, '\3', last+1, *last)) {
case OK:
if (i)
goto again;
@@ -824,14 +850,14 @@ sendit(file)
(void) fclose(cfp);
return(REPRINT);
case ACCESS:
- sendmail(logname, ACCESS);
+ sendmail(pp, logname, ACCESS);
case ERROR:
err = ERROR;
}
break;
}
}
- if (err == OK && sendfile('\2', file, '\0') > 0) {
+ if (err == OK && sendfile(pp, '\2', file, '\0') > 0) {
(void) fclose(cfp);
return(REPRINT);
}
@@ -855,7 +881,8 @@ sendit(file)
* Return positive if we should try resending.
*/
static int
-sendfile(type, file, format)
+sendfile(pp, type, file, format)
+ struct printer *pp;
int type;
char *file;
char format;
@@ -879,7 +906,7 @@ sendfile(type, file, format)
sizerr = 0;
closedpr = 0;
if (type == '\3') {
- if (IF) {
+ if (pp->filters[LPF_INPUT]) {
/*
* We're sending something with an ifilter, we have to
* run the ifilter and store the output as a
@@ -888,17 +915,16 @@ sendfile(type, file, format)
*/
char *av[15];
int n;
- int nfd;
int ifilter;
- union wait status;
+ union wait status; /* XXX */
strcpy(tfile,TFILENAME);
if ((tfd = mkstemp(tfile)) == -1) {
syslog(LOG_ERR, "mkstemp: %m");
return(ERROR);
}
- if ((av[0] = strrchr(IF, '/')) == NULL)
- av[0] = IF;
+ if ((av[0] = strrchr(pp->filters[LPF_INPUT], '/')) == NULL)
+ av[0] = pp->filters[LPF_INPUT];
else
av[0]++;
if (format == 'l')
@@ -912,19 +938,20 @@ sendfile(type, file, format)
av[++n] = logname;
av[++n] = "-h";
av[++n] = fromhost;
- av[++n] = AF;
+ av[++n] = pp->acct_file;
av[++n] = 0;
- if ((ifilter = dofork(DORETURN)) == 0) { /* child */
+ if ((ifilter = dofork(pp, DORETURN)) == 0) { /* child */
dup2(f, 0);
dup2(tfd, 1);
- n = open(tempfile, O_WRONLY|O_CREAT|O_TRUNC, 0664);
+ n = open(tempfile, O_WRONLY|O_CREAT|O_TRUNC,
+ TEMP_FILE_MODE);
if (n >= 0)
dup2(n, 2);
closelog();
- for (n = 3, nfd = getdtablesize(); n < nfd; n++)
- (void) close(n);
- execv(IF, av);
- syslog(LOG_ERR, "cannot execv %s", IF);
+ closeallfds(3);
+ execv(pp->filters[LPF_INPUT], av);
+ syslog(LOG_ERR, "cannot execv %s",
+ pp->filters[LPF_INPUT]);
exit(2);
}
(void) close(f);
@@ -946,7 +973,7 @@ sendfile(type, file, format)
default:
syslog(LOG_WARNING, "%s: filter '%c' exited"
" (retcode=%d)",
- printer, format, status.w_retcode);
+ pp->printer, format, status.w_retcode);
unlink(tfile);
return(FILTERERR);
}
@@ -980,7 +1007,7 @@ sendfile(type, file, format)
;
ofilter = 0;
if (fstat(tfd, &stb) < 0) { /* the size of tfile */
- openpr();
+ openpr(pp);
return(ERROR);
}
f = tfd;
@@ -993,26 +1020,27 @@ sendfile(type, file, format)
amt = strlen(buf);
for (i = 0; ; i++) {
if (write(pfd, buf, amt) != amt ||
- (resp = response()) < 0 || resp == '\1') {
+ (resp = response(pp)) < 0 || resp == '\1') {
(void) close(f);
if (tfd != -1 && type == '\3') {
tfd = -1;
unlink(tfile);
if (closedpr)
- openpr();
+ openpr(pp);
}
return(REPRINT);
} else if (resp == '\0')
break;
if (i == 0)
- pstatus("no space on remote; waiting for queue to drain");
+ pstatus(pp,
+ "no space on remote; waiting for queue to drain");
if (i == 10)
syslog(LOG_ALERT, "%s: can't send to %s; queue full",
- printer, RM);
+ pp->printer, pp->remote_host);
sleep(5 * 60);
}
if (i)
- pstatus("sending to %s", RM);
+ pstatus(pp, "sending to %s", pp->remote_host);
for (i = 0; i < stb.st_size; i += BUFSIZ) {
amt = BUFSIZ;
if (i + amt > stb.st_size)
@@ -1025,7 +1053,7 @@ sendfile(type, file, format)
tfd = -1;
unlink(tfile);
if (closedpr)
- openpr();
+ openpr(pp);
}
return(REPRINT);
}
@@ -1037,20 +1065,20 @@ sendfile(type, file, format)
unlink(tfile);
}
if (sizerr) {
- syslog(LOG_INFO, "%s: %s: changed size", printer, file);
+ syslog(LOG_INFO, "%s: %s: changed size", pp->printer, file);
/* tell recvjob to ignore this file */
(void) write(pfd, "\1", 1);
if (closedpr)
- openpr();
+ openpr(pp);
return(ERROR);
}
- if (write(pfd, "", 1) != 1 || response()) {
+ if (write(pfd, "", 1) != 1 || response(pp)) {
if (closedpr)
- openpr();
+ openpr(pp);
return(REPRINT);
}
if (closedpr)
- openpr();
+ openpr(pp);
return(OK);
}
@@ -1060,12 +1088,13 @@ sendfile(type, file, format)
* Return non-zero if the connection was lost.
*/
static char
-response()
+response(pp)
+ const struct printer *pp;
{
char resp;
if (read(pfd, &resp, 1) != 1) {
- syslog(LOG_INFO, "%s: lost connection", printer);
+ syslog(LOG_INFO, "%s: lost connection", pp->printer);
return(-1);
}
return(resp);
@@ -1075,15 +1104,16 @@ response()
* Banner printing stuff
*/
static void
-banner(name1, name2)
+banner(pp, name1, name2)
+ struct printer *pp;
char *name1, *name2;
{
time_t tvec;
time(&tvec);
- if (!SF && !tof)
- (void) write(ofd, FF, strlen(FF));
- if (SB) { /* short banner only */
+ if (!pp->no_formfeed && !pp->tof)
+ (void) write(ofd, pp->form_feed, strlen(pp->form_feed));
+ if (pp->short_banner) { /* short banner only */
if (class[0]) {
(void) write(ofd, class, strlen(class));
(void) write(ofd, ":", 1);
@@ -1096,12 +1126,12 @@ banner(name1, name2)
(void) write(ofd, "\n", 1);
} else { /* normal banner */
(void) write(ofd, "\n\n\n", 3);
- scan_out(ofd, name1, '\0');
+ scan_out(pp, ofd, name1, '\0');
(void) write(ofd, "\n\n", 2);
- scan_out(ofd, name2, '\0');
+ scan_out(pp, ofd, name2, '\0');
if (class[0]) {
(void) write(ofd,"\n\n\n",3);
- scan_out(ofd, class, '\0');
+ scan_out(pp, ofd, class, '\0');
}
(void) write(ofd, "\n\n\n\n\t\t\t\t\tJob: ", 15);
(void) write(ofd, name2, strlen(name2));
@@ -1109,9 +1139,9 @@ banner(name1, name2)
(void) write(ofd, ctime(&tvec), 24);
(void) write(ofd, "\n", 1);
}
- if (!SF)
- (void) write(ofd, FF, strlen(FF));
- tof = 1;
+ if (!pp->no_formfeed)
+ (void) write(ofd, pp->form_feed, strlen(pp->form_feed));
+ pp->tof = 1;
}
static char *
@@ -1132,7 +1162,8 @@ scnline(key, p, c)
#define TRC(q) (((q)-' ')&0177)
static void
-scan_out(scfd, scsp, dlm)
+scan_out(pp, scfd, scsp, dlm)
+ struct printer *pp;
int scfd, dlm;
char *scsp;
{
@@ -1150,8 +1181,9 @@ scan_out(scfd, scsp, dlm)
for (j = WIDTH; --j;)
*strp++ = BACKGND;
else
- strp = scnline(scnkey[c][scnhgt-1-d], strp, cc);
- if (*sp == dlm || *sp == '\0' || nchrs++ >= PW/(WIDTH+1)-1)
+ strp = scnline(scnkey[(int)c][scnhgt-1-d], strp, cc);
+ if (*sp == dlm || *sp == '\0' ||
+ nchrs++ >= pp->page_width/(WIDTH+1)-1)
break;
*strp++ = BACKGND;
*strp++ = BACKGND;
@@ -1190,38 +1222,39 @@ dropit(c)
* tell people about job completion
*/
static void
-sendmail(user, bombed)
+sendmail(pp, user, bombed)
+ struct printer *pp;
char *user;
int bombed;
{
register int i;
- int dtablesize;
int p[2], s;
register char *cp;
struct stat stb;
FILE *fp;
pipe(p);
- if ((s = dofork(DORETURN)) == 0) { /* child */
+ if ((s = dofork(pp, DORETURN)) == 0) { /* child */
dup2(p[0], 0);
closelog();
- for (i = 3, dtablesize = getdtablesize(); i < dtablesize; i++)
- (void) close(i);
+ closeallfds(3);
if ((cp = strrchr(_PATH_SENDMAIL, '/')) != NULL)
cp++;
- else
+ else
cp = _PATH_SENDMAIL;
execl(_PATH_SENDMAIL, cp, "-t", 0);
- exit(0);
+ _exit(0);
} else if (s > 0) { /* parent */
dup2(p[1], 1);
printf("To: %s@%s\n", user, fromhost);
- printf("Subject: %s printer job \"%s\"\n", printer,
+ printf("Subject: %s printer job \"%s\"\n", pp->printer,
*jobname ? jobname : "<unknown>");
printf("Reply-To: root@%s\n\n", host);
printf("Your printer job ");
if (*jobname)
printf("(%s) ", jobname);
+
+ cp = "XXX compiler confusion"; /* XXX shut GCC up */
switch (bombed) {
case OK:
printf("\ncompleted successfully\n");
@@ -1254,19 +1287,23 @@ sendmail(user, bombed)
}
fflush(stdout);
(void) close(1);
+ } else {
+ syslog(LOG_WARNING, "unable to send mail to %s: %m", user);
+ return;
}
(void) close(p[0]);
(void) close(p[1]);
wait(NULL);
syslog(LOG_INFO, "mail sent to user %s about job %s on printer %s (%s)",
- user, *jobname ? jobname : "<unknown>", printer, cp);
+ user, *jobname ? jobname : "<unknown>", pp->printer, cp);
}
/*
* dofork - fork with retries on failure
*/
static int
-dofork(action)
+dofork(pp, action)
+ const struct printer *pp;
int action;
{
register int i, pid;
@@ -1280,7 +1317,7 @@ dofork(action)
* Child should run as daemon instead of root
*/
if (pid == 0)
- setuid(DU);
+ setuid(pp->daemon_user);
return(pid);
}
syslog(LOG_ERR, "can't fork");
@@ -1316,127 +1353,90 @@ abortpr(signo)
}
static void
-init()
+init(pp)
+ struct printer *pp;
{
- int status;
char *s;
- if ((status = cgetent(&bp, printcapdb, printer)) == -2) {
- syslog(LOG_ERR, "can't open printer description file");
+ sprintf(&width[2], "%ld", pp->page_width);
+ sprintf(&length[2], "%ld", pp->page_length);
+ sprintf(&pxwidth[2], "%ld", pp->page_pwidth);
+ sprintf(&pxlength[2], "%ld", pp->page_plength);
+ if ((s = checkremote(pp)) != 0) {
+ syslog(LOG_WARNING, "%s", s);
+ free(s);
+ }
+}
+
+void
+startprinting(printer)
+ const char *printer;
+{
+ struct printer myprinter, *pp = &myprinter;
+ int status;
+
+ init_printer(pp);
+ status = getprintcap(printer, pp);
+ switch(status) {
+ case PCAPERR_OSERR:
+ syslog(LOG_ERR, "can't open printer description file: %m");
exit(1);
- } else if (status == -1) {
+ case PCAPERR_NOTFOUND:
syslog(LOG_ERR, "unknown printer: %s", printer);
exit(1);
- } else if (status == -3)
- fatal("potential reference loop detected in printcap file");
-
- if (cgetstr(bp, "lp", &LP) == -1)
- LP = _PATH_DEFDEVLP;
- if (cgetstr(bp, "rp", &RP) == -1)
- RP = DEFLP;
- if (cgetstr(bp, "lo", &LO) == -1)
- LO = DEFLOCK;
- if (cgetstr(bp, "st", &ST) == -1)
- ST = DEFSTAT;
- if (cgetstr(bp, "lf", &LF) == -1)
- LF = _PATH_CONSOLE;
- if (cgetstr(bp, "sd", &SD) == -1)
- SD = _PATH_DEFSPOOL;
- if (cgetnum(bp, "du", &DU) < 0)
- DU = DEFUID;
- if (cgetstr(bp,"ff", &FF) == -1)
- FF = DEFFF;
- if (cgetnum(bp, "pw", &PW) < 0)
- PW = DEFWIDTH;
- sprintf(&width[2], "%ld", PW);
- if (cgetnum(bp, "pl", &PL) < 0)
- PL = DEFLENGTH;
- if (cgetnum(bp, "ct", &CT) < 0)
- CT = DEFTIMEOUT;
- sprintf(&length[2], "%ld", PL);
- if (cgetnum(bp,"px", &PX) < 0)
- PX = 0;
- sprintf(&pxwidth[2], "%ld", PX);
- if (cgetnum(bp, "py", &PY) < 0)
- PY = 0;
- sprintf(&pxlength[2], "%ld", PY);
- cgetstr(bp, "rm", &RM);
- if ((s = checkremote()))
- syslog(LOG_WARNING, s);
-
- cgetstr(bp, "af", &AF);
- cgetstr(bp, "of", &OF);
- cgetstr(bp, "if", &IF);
- cgetstr(bp, "rf", &RF);
- cgetstr(bp, "tf", &TF);
- cgetstr(bp, "nf", &NF);
- cgetstr(bp, "df", &DF);
- cgetstr(bp, "gf", &GF);
- cgetstr(bp, "vf", &VF);
- cgetstr(bp, "cf", &CF);
- cgetstr(bp, "tr", &TR);
- cgetstr(bp, "ms", &MS);
-
- RS = (cgetcap(bp, "rs", ':') != NULL);
- SF = (cgetcap(bp, "sf", ':') != NULL);
- SH = (cgetcap(bp, "sh", ':') != NULL);
- SB = (cgetcap(bp, "sb", ':') != NULL);
- HL = (cgetcap(bp, "hl", ':') != NULL);
- RW = (cgetcap(bp, "rw", ':') != NULL);
-
- cgetnum(bp, "br", &BR);
-
- tof = (cgetcap(bp, "fo", ':') == NULL);
+ case PCAPERR_TCLOOP:
+ fatal(pp, "potential reference loop detected in printcap file");
+ default:
+ break;
+ }
+ printjob(pp);
}
/*
* Acquire line printer or remote connection.
*/
static void
-openpr()
+openpr(pp)
+ const struct printer *pp;
{
- register int i;
- int dtablesize;
+ int p[2];
char *cp;
- if (!remote && *LP) {
- if (cp = strchr(LP, '@'))
- opennet(cp);
+ if (pp->remote) {
+ openrem(pp);
+ } else if (*pp->lp) {
+ if ((cp = strchr(pp->lp, '@')) != NULL)
+ opennet(pp);
else
- opentty();
- } else if (remote) {
- openrem();
+ opentty(pp);
} else {
syslog(LOG_ERR, "%s: no line printer device or host name",
- printer);
+ pp->printer);
exit(1);
}
/*
* Start up an output filter, if needed.
*/
- if (OF && !IF && !ofilter) {
- int p[2];
-
+ if (pp->filters[LPF_OUTPUT] && !pp->filters[LPF_INPUT] && !ofilter) {
pipe(p);
- if (remote) {
- strcpy(tfile,TFILENAME);
+ if (pp->remote) {
+ strcpy(tfile, TFILENAME);
tfd = mkstemp(tfile);
}
- if ((ofilter = dofork(DOABORT)) == 0) { /* child */
+ if ((ofilter = dofork(pp, DOABORT)) == 0) { /* child */
dup2(p[0], 0); /* pipe is std in */
/* tfile/printer is stdout */
- dup2(remote ? tfd : pfd, 1);
+ dup2(pp->remote ? tfd : pfd, 1);
closelog();
- for (i = 3, dtablesize = getdtablesize();
- i < dtablesize; i++)
- (void) close(i);
- if ((cp = strrchr(OF, '/')) == NULL)
- cp = OF;
+ closeallfds(3);
+ if ((cp = strrchr(pp->filters[LPF_OUTPUT], '/')) == NULL)
+ cp = pp->filters[LPF_OUTPUT];
else
cp++;
- execl(OF, cp, width, length, 0);
- syslog(LOG_ERR, "%s: %s: %m", printer, OF);
+ execl(pp->filters[LPF_OUTPUT], cp, width, length, 0);
+ syslog(LOG_ERR, "%s: %s: %m", pp->printer,
+ pp->filters[LPF_OUTPUT]);
exit(1);
}
(void) close(p[0]); /* close input side */
@@ -1452,28 +1452,28 @@ openpr()
* or to a terminal server on the net
*/
static void
-opennet(cp)
- char *cp;
+opennet(pp)
+ const struct printer *pp;
{
register int i;
- int resp, port;
- char save_ch;
+ int resp;
+ u_long port;
+ char *ep;
void (*savealrm)(int);
- save_ch = *cp;
- *cp = '\0';
- port = atoi(LP);
- if (port <= 0) {
- syslog(LOG_ERR, "%s: bad port number: %s", printer, LP);
+ port = strtoul(pp->lp, &ep, 0);
+ if (*ep != ':' || port > 65536) {
+ syslog(LOG_ERR, "%s: bad port number: %s", pp->printer,
+ pp->lp);
exit(1);
}
- *cp++ = save_ch;
+ ep++;
for (i = 1; ; i = i < 256 ? i << 1 : i) {
resp = -1;
savealrm = signal(SIGALRM, alarmhandler);
- alarm(CT);
- pfd = getport(cp, port);
+ alarm(pp->conn_timeout);
+ pfd = getport(pp, ep, port);
alarm(0);
(void)signal(SIGALRM, savealrm);
if (pfd < 0 && errno == ECONNREFUSED)
@@ -1488,145 +1488,120 @@ opennet(cp)
break;
}
if (i == 1) {
- if (resp < 0)
- pstatus("waiting for %s to come up", LP);
- else
- pstatus("waiting for access to printer on %s", LP);
+ if (resp < 0)
+ pstatus(pp, "waiting for %s to come up",
+ pp->lp);
+ else
+ pstatus(pp,
+ "waiting for access to printer on %s",
+ pp->lp);
}
sleep(i);
}
- pstatus("sending to %s port %d", cp, port);
+ pstatus(pp, "sending to %s port %d", ep, port);
}
/*
* Printer is connected to an RS232 port on this host
*/
static void
-opentty()
+opentty(pp)
+ const struct printer *pp;
{
register int i;
- int resp, port;
for (i = 1; ; i = i < 32 ? i << 1 : i) {
- pfd = open(LP, RW ? O_RDWR : O_WRONLY);
+ pfd = open(pp->lp, pp->rw ? O_RDWR : O_WRONLY);
if (pfd >= 0) {
delay(500);
break;
}
if (errno == ENOENT) {
- syslog(LOG_ERR, "%s: %m", LP);
+ syslog(LOG_ERR, "%s: %m", pp->lp);
exit(1);
}
if (i == 1)
- pstatus("waiting for %s to become ready (offline ?)",
- printer);
+ pstatus(pp,
+ "waiting for %s to become ready (offline?)",
+ pp->printer);
sleep(i);
}
if (isatty(pfd))
- setty();
- pstatus("%s is ready and printing", printer);
+ setty(pp);
+ pstatus(pp, "%s is ready and printing", pp->printer);
}
/*
* Printer is on a remote host
*/
static void
-openrem()
+openrem(pp)
+ const struct printer *pp;
{
- register int i, n;
+ register int i;
int resp;
void (*savealrm)(int);
for (i = 1; ; i = i < 256 ? i << 1 : i) {
resp = -1;
savealrm = signal(SIGALRM, alarmhandler);
- alarm(CT);
- pfd = getport(RM, 0);
+ alarm(pp->conn_timeout);
+ pfd = getport(pp, pp->remote_host, 0);
alarm(0);
(void)signal(SIGALRM, savealrm);
if (pfd >= 0) {
- (void) snprintf(line, sizeof(line), "\2%s\n", RP);
- n = strlen(line);
- if (write(pfd, line, n) == n &&
- (resp = response()) == '\0')
+ if ((writel(pfd, "\2", pp->remote_queue, "\n",
+ (char *)0)
+ == 2 + strlen(pp->remote_queue))
+ && (resp = response(pp)) == 0)
break;
(void) close(pfd);
}
if (i == 1) {
if (resp < 0)
- pstatus("waiting for %s to come up", RM);
+ pstatus(pp, "waiting for %s to come up",
+ pp->remote_host);
else {
- pstatus("waiting for queue to be enabled on %s",
- RM);
+ pstatus(pp,
+ "waiting for queue to be enabled on %s",
+ pp->remote_host);
i = 256;
}
}
sleep(i);
}
- pstatus("sending to %s", RM);
+ pstatus(pp, "sending to %s", pp->remote_host);
}
-struct bauds {
- int baud;
- int speed;
-} bauds[] = {
- 50, B50,
- 75, B75,
- 110, B110,
- 134, B134,
- 150, B150,
- 200, B200,
- 300, B300,
- 600, B600,
- 1200, B1200,
- 1800, B1800,
- 2400, B2400,
- 4800, B4800,
- 9600, B9600,
- 19200, EXTA,
- 38400, EXTB,
- 57600, B57600,
- 115200, B115200,
- 0, 0
-};
-
/*
* setup tty lines.
*/
static void
-setty()
+setty(pp)
+ const struct printer *pp;
{
struct termios ttybuf;
- struct bauds *bp;
if (ioctl(pfd, TIOCEXCL, (char *)0) < 0) {
- syslog(LOG_ERR, "%s: ioctl(TIOCEXCL): %m", printer);
+ syslog(LOG_ERR, "%s: ioctl(TIOCEXCL): %m", pp->printer);
exit(1);
}
if (tcgetattr(pfd, &ttybuf) < 0) {
- syslog(LOG_ERR, "%s: tcgetattr: %m", printer);
+ syslog(LOG_ERR, "%s: tcgetattr: %m", pp->printer);
exit(1);
}
- if (BR > 0) {
- for (bp = bauds; bp->baud; bp++)
- if (BR == bp->baud)
- break;
- if (!bp->baud) {
- syslog(LOG_ERR, "%s: illegal baud rate %d", printer, BR);
- exit(1);
- }
- cfsetspeed(&ttybuf, bp->speed);
- }
- if (MS) {
- char *s = strdup(MS), *tmp;
+ if (pp->baud_rate > 0)
+ cfsetspeed(&ttybuf, pp->baud_rate);
+ if (pp->mode_set) {
+ char *s = strdup(pp->mode_set), *tmp;
- while (tmp = strsep (&s, ",")) {
+ while ((tmp = strsep(&s, ",")) != NULL) {
msearch(tmp, &ttybuf);
}
}
- if (MS || (BR > 0)) {
+ if (pp->mode_set != 0 || pp->baud_rate > 0) {
if (tcsetattr(pfd, TCSAFLUSH, &ttybuf) == -1) {
- syslog(LOG_ERR, "%s: tcsetattr: %m", printer);
+ syslog(LOG_ERR, "%s: tcsetattr: %m", pp->printer);
}
}
}
@@ -1639,15 +1614,16 @@ setty()
static void
#ifdef __STDC__
-pstatus(const char *msg, ...)
+pstatus(const struct printer *pp, const char *msg, ...)
#else
-pstatus(msg, va_alist)
+pstatus(pp, msg, va_alist)
+ const struct printer *pp;
char *msg;
va_dcl
#endif
{
- register int fd;
- char buf[BUFSIZ];
+ int fd;
+ char *buf;
va_list ap;
#ifdef __STDC__
va_start(ap, msg);
@@ -1656,17 +1632,17 @@ pstatus(msg, va_alist)
#endif
umask(0);
- fd = open(ST, O_WRONLY|O_CREAT, 0664);
- if (fd < 0 || flock(fd, LOCK_EX) < 0) {
- syslog(LOG_ERR, "%s: %s: %m", printer, ST);
+ fd = open(pp->status_file, O_WRONLY|O_CREAT|O_EXLOCK, STAT_FILE_MODE);
+ if (fd < 0) {
+ syslog(LOG_ERR, "%s: %s: %m", pp->printer, pp->status_file);
exit(1);
}
ftruncate(fd, 0);
- (void)vsnprintf(buf, sizeof(buf) - 1, msg, ap);
+ vasprintf(&buf, msg, ap);
va_end(ap);
- strcat(buf, "\n");
- (void) write(fd, buf, strlen(buf));
- (void) close(fd);
+ writel(fd, buf, "\n", (char *)0);
+ close(fd);
+ free(buf);
}
void
OpenPOWER on IntegriCloud