diff options
Diffstat (limited to 'usr.sbin/lpr')
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 |