diff options
author | joerg <joerg@FreeBSD.org> | 1996-05-05 22:40:51 +0000 |
---|---|---|
committer | joerg <joerg@FreeBSD.org> | 1996-05-05 22:40:51 +0000 |
commit | 914cbcef2ca2238d808f510c1a2f084eb37952b6 (patch) | |
tree | a2c9a4d920a98c3865b5da51ea401d02253ceae3 /usr.sbin/lpr | |
parent | 8d1089fb9317c3fa275c4470e8a92463cc828758 (diff) | |
download | FreeBSD-src-914cbcef2ca2238d808f510c1a2f084eb37952b6.zip FreeBSD-src-914cbcef2ca2238d808f510c1a2f084eb37952b6.tar.gz |
Pull a bunch of fixes from the 4.4BSD-Lite2 branch. It's really
surprising how many trivial errors there have been... :-)
Some more cleanup is needed, but i'd like to separate the Lite2 changes
from other work, that's why this goes into a different commit.
People with serial printers should see whether i have broken the stty-
style printcap options (i hope not).
Inspired by: Sergey Shkonda <serg@bcs1.bcs.zaporizhzhe.ua>
Diffstat (limited to 'usr.sbin/lpr')
-rw-r--r-- | usr.sbin/lpr/common_source/common.c | 63 | ||||
-rw-r--r-- | usr.sbin/lpr/common_source/displayq.c | 25 | ||||
-rw-r--r-- | usr.sbin/lpr/common_source/lp.h | 7 | ||||
-rw-r--r-- | usr.sbin/lpr/common_source/recvjob.c | 4 | ||||
-rw-r--r-- | usr.sbin/lpr/common_source/rmjob.c | 6 | ||||
-rw-r--r-- | usr.sbin/lpr/lpc/cmds.c | 3 | ||||
-rw-r--r-- | usr.sbin/lpr/lpc/lpc.8 | 7 | ||||
-rw-r--r-- | usr.sbin/lpr/lpd/lpd.8 | 10 | ||||
-rw-r--r-- | usr.sbin/lpr/lpd/printjob.c | 248 | ||||
-rw-r--r-- | usr.sbin/lpr/lpd/recvjob.c | 4 | ||||
-rw-r--r-- | usr.sbin/lpr/lpr/lpr.c | 2 | ||||
-rw-r--r-- | usr.sbin/lpr/runqueue/printjob.c | 248 |
12 files changed, 421 insertions, 206 deletions
diff --git a/usr.sbin/lpr/common_source/common.c b/usr.sbin/lpr/common_source/common.c index a5c6ee5..9b9244e 100644 --- a/usr.sbin/lpr/common_source/common.c +++ b/usr.sbin/lpr/common_source/common.c @@ -37,11 +37,12 @@ */ #ifndef lint -static char sccsid[] = "@(#)common.c 8.2 (Berkeley) 1/21/94"; +static char sccsid[] = "@(#)common.c 8.5 (Berkeley) 4/28/95"; #endif /* not lint */ #include <sys/param.h> #include <sys/stat.h> +#include <sys/time.h> #include <sys/socket.h> #include <netinet/in.h> @@ -105,18 +106,20 @@ char *printer; /* printer name */ /* host machine name */ char host[MAXHOSTNAMELEN]; char *from = host; /* client's machine name */ -int sendtorem; /* are we sending to a remote? */ +int remote; /* true if sending files to a remote host */ char *printcapdb[2] = { _PATH_PRINTCAP, 0 }; static int compar __P((const void *, const void *)); /* - * Create a connection to the remote printer server. + * 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) +getport(rhost, rport) char *rhost; + int rport; { struct hostent *hp; struct servent *sp; @@ -129,16 +132,24 @@ getport(rhost) */ if (rhost == NULL) fatal("no remote host to connect to"); - hp = gethostbyname(rhost); - if (hp == NULL) - fatal("unknown host %s", rhost); - sp = getservbyname("printer", "tcp"); - if (sp == NULL) - fatal("printer/tcp: unknown service"); bzero((char *)&sin, sizeof(sin)); - bcopy(hp->h_addr, (caddr_t)&sin.sin_addr, hp->h_length); - sin.sin_family = hp->h_addrtype; - sin.sin_port = sp->s_port; + 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. @@ -241,8 +252,9 @@ getq(namelist) * realloc the maximum size. */ if (++nitems > arraysz) { + arraysz *= 2; queue = (struct queue **)realloc((char *)queue, - (stbuf.st_size/12) * sizeof(struct queue *)); + arraysz * sizeof(struct queue *)); if (queue == NULL) goto errdone; } @@ -284,8 +296,8 @@ checkremote() register struct hostent *hp; static char errbuf[128]; - sendtorem = 0; /* assume printer is local */ - if (RM != (char *)NULL) { + 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'; @@ -310,10 +322,23 @@ checkremote() * if the two hosts are not the same, * then the printer must be remote. */ - if (strcmp(name, hp->h_name) != 0) - sendtorem = 1; + if (strcasecmp(name, hp->h_name) != 0) + remote = 1; } - return (char *)0; + return NULL; +} + +/* sleep n milliseconds */ +void +delay(n) +{ + struct timeval tdelay; + + if (n <= 0 || n > 10000) + fatal("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); } #if __STDC__ diff --git a/usr.sbin/lpr/common_source/displayq.c b/usr.sbin/lpr/common_source/displayq.c index 59d3cc9..e0b6728 100644 --- a/usr.sbin/lpr/common_source/displayq.c +++ b/usr.sbin/lpr/common_source/displayq.c @@ -32,11 +32,12 @@ */ #ifndef lint -static char sccsid[] = "@(#)displayq.c 8.1 (Berkeley) 6/6/93"; +static char sccsid[] = "@(#)displayq.c 8.4 (Berkeley) 4/28/95"; #endif /* not lint */ #include <sys/param.h> #include <sys/stat.h> +#include <sys/file.h> #include <signal.h> #include <fcntl.h> @@ -124,7 +125,7 @@ displayq(format) fatal("cannot examine spooling area\n"); if (stat(LO, &statb) >= 0) { if (statb.st_mode & 0100) { - if (sendtorem) + if (remote) printf("%s: ", host); printf("Warning: %s is down: ", printer); fd = open(ST, O_RDONLY); @@ -137,7 +138,7 @@ displayq(format) putchar('\n'); } if (statb.st_mode & 010) { - if (sendtorem) + if (remote) printf("%s: ", host); printf("Warning: %s queue is turned off\n", printer); } @@ -150,8 +151,8 @@ displayq(format) else { /* get daemon pid */ cp = current; - while ((*cp = getc(fp)) != EOF && *cp != '\n') - cp++; + while ((i = getc(fp)) != EOF && i != '\n') + *cp++ = i; *cp = '\0'; i = atoi(current); if (i <= 0 || kill(i, 0) < 0) @@ -159,13 +160,13 @@ displayq(format) else { /* read current file name */ cp = current; - while ((*cp = getc(fp)) != EOF && *cp != '\n') - cp++; + while ((i = getc(fp)) != EOF && i != '\n') + *cp++ = i; *cp = '\0'; /* * Print the status file. */ - if (sendtorem) + if (remote) printf("%s: ", host); fd = open(ST, O_RDONLY); if (fd >= 0) { @@ -191,7 +192,7 @@ displayq(format) } free(queue); } - if (!sendtorem) { + if (!remote) { if (nitems == 0) puts("no entries"); return; @@ -215,7 +216,7 @@ displayq(format) (void) strcpy(cp, user[i]); } strcat(line, "\n"); - fd = getport(RM); + fd = getport(RM, 0); if (fd < 0) { if (from != host) printf("%s: ", host); @@ -237,7 +238,7 @@ displayq(format) void warn() { - if (sendtorem) + if (remote) printf("\n%s: ", host); puts("Warning: no daemon present"); current[0] = '\0'; @@ -271,7 +272,7 @@ inform(cf) if (rank < 0) rank = 0; - if (sendtorem || garbage || strcmp(cf, current)) + if (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 4e3827d..b8f956f 100644 --- a/usr.sbin/lpr/common_source/lp.h +++ b/usr.sbin/lpr/common_source/lp.h @@ -30,7 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * @(#)lp.h 8.1 (Berkeley) 6/6/93 + * @(#)lp.h 8.2 (Berkeley) 4/28/95 */ @@ -82,7 +82,7 @@ extern char *printer; /* printer name */ /* host machine name */ extern char host[MAXHOSTNAMELEN]; extern char *from; /* client's machine name */ -extern int sendtorem; /* are we sending to a remote? */ +extern int remote; /* true if sending files to a remote host */ extern char *printcapdb[]; /* printcap database array */ /* * Structure used for building a sorted list of control files. @@ -104,7 +104,7 @@ void displayq __P((int)); void dump __P((char *, char *, int)); void fatal __P((const char *, ...)); int getline __P((FILE *)); -int getport __P((char *)); +int getport __P((char *, int)); int getq __P((struct queue *(*[]))); void header __P((void)); void inform __P((char *)); @@ -120,4 +120,5 @@ void rmremote __P((void)); void show __P((char *, char *, int)); int startdaemon __P((char *)); void warn __P((void)); +void delay __P((int)); __END_DECLS diff --git a/usr.sbin/lpr/common_source/recvjob.c b/usr.sbin/lpr/common_source/recvjob.c index e199af1..35f946f 100644 --- a/usr.sbin/lpr/common_source/recvjob.c +++ b/usr.sbin/lpr/common_source/recvjob.c @@ -39,7 +39,7 @@ static char copyright[] = #endif /* not lint */ #ifndef lint -static char sccsid[] = "@(#)recvjob.c 8.1 (Berkeley) 6/6/93"; +static char sccsid[] = "@(#)recvjob.c 8.2 (Berkeley) 4/27/95"; #endif /* not lint */ /* @@ -342,7 +342,7 @@ frecverr(msg, va_alist) va_dcl #endif { - extern char *fromb; + extern char fromb[]; va_list ap; #if __STDC__ va_start(ap, msg); diff --git a/usr.sbin/lpr/common_source/rmjob.c b/usr.sbin/lpr/common_source/rmjob.c index 74a94d8..bdfe853 100644 --- a/usr.sbin/lpr/common_source/rmjob.c +++ b/usr.sbin/lpr/common_source/rmjob.c @@ -32,7 +32,7 @@ */ #ifndef lint -static char sccsid[] = "@(#)rmjob.c 8.1 (Berkeley) 6/6/93"; +static char sccsid[] = "@(#)rmjob.c 8.2 (Berkeley) 4/28/95"; #endif /* not lint */ #include <sys/param.h> @@ -292,7 +292,7 @@ rmremote() register int i, rem; char buf[BUFSIZ]; - if (!sendtorem) + if (!remote) return; /* not sending to a remote machine */ /* @@ -313,7 +313,7 @@ rmremote() (void) sprintf(cp, " %d", requ[i]); } strcat(cp, "\n"); - rem = getport(RM); + rem = getport(RM, 0); if (rem < 0) { if (from != host) printf("%s: ", host); diff --git a/usr.sbin/lpr/lpc/cmds.c b/usr.sbin/lpr/lpc/cmds.c index 193eac5..84c6a4d 100644 --- a/usr.sbin/lpr/lpc/cmds.c +++ b/usr.sbin/lpr/lpc/cmds.c @@ -39,7 +39,7 @@ static char copyright[] = #endif /* not lint */ #ifndef lint -static char sccsid[] = "@(#)cmds.c 8.1 (Berkeley) 6/6/93"; +static char sccsid[] = "@(#)cmds.c 8.2 (Berkeley) 4/28/95"; #endif /* not lint */ /* @@ -49,6 +49,7 @@ static char sccsid[] = "@(#)cmds.c 8.1 (Berkeley) 6/6/93"; #include <sys/param.h> #include <sys/time.h> #include <sys/stat.h> +#include <sys/file.h> #include <signal.h> #include <fcntl.h> diff --git a/usr.sbin/lpr/lpc/lpc.8 b/usr.sbin/lpr/lpc/lpc.8 index 63c4f0d..07e4aaf 100644 --- a/usr.sbin/lpr/lpc/lpc.8 +++ b/usr.sbin/lpr/lpc/lpc.8 @@ -29,9 +29,9 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.\" @(#)lpc.8 8.3 (Berkeley) 4/19/94 +.\" @(#)lpc.8 8.5 (Berkeley) 4/28/95 .\" -.Dd April 19, 1994 +.Dd April 28, 1995 .Dt LPC 8 .Os BSD 4.2 .Sh NAME @@ -117,6 +117,7 @@ to put new jobs in the spool queue. .It Ic exit .It Ic quit Exit from lpc. +.\" ne 1i .Pp .It Ic restart No {\ all\ |\ printer\ } Attempt to start a new printer daemon. @@ -165,7 +166,7 @@ abbreviation matches more than one command .It Sy "?Invalid command" no match was found .It Sy "?Privileged command" -command can be executed by root only +you must be a member of group "operator" or root to execute this command .El .Sh HISTORY The diff --git a/usr.sbin/lpr/lpd/lpd.8 b/usr.sbin/lpr/lpd/lpd.8 index f0b94b1..3eeee0d 100644 --- a/usr.sbin/lpr/lpd/lpd.8 +++ b/usr.sbin/lpr/lpd/lpd.8 @@ -247,13 +247,3 @@ but not under same administrative control. An .Nm daemon appeared in Version 6 AT&T UNIX. -.Sh BUGS -.Nm Lpd -tends to dump core if a request specifies a file format where no filter -is assigned. This may be particular annoying if somebody is not aware -of the file format specification, such as for a DOS client that always -specifies the -.Em v -format. The workaround is to assign a dummy filter for these file -formats, e. g. a -.Xr cat 1 . diff --git a/usr.sbin/lpr/lpd/printjob.c b/usr.sbin/lpr/lpd/printjob.c index ae0b05a..ea2be9f 100644 --- a/usr.sbin/lpr/lpd/printjob.c +++ b/usr.sbin/lpr/lpd/printjob.c @@ -39,7 +39,7 @@ static char copyright[] = #endif /* not lint */ #ifndef lint -static char sccsid[] = "@(#)printjob.c 8.2 (Berkeley) 4/16/94"; +static char sccsid[] = "@(#)printjob.c 8.7 (Berkeley) 5/10/95"; #endif /* not lint */ @@ -96,7 +96,6 @@ static int ofilter; /* id of output filter, if any */ static int pfd; /* prstatic inter file descriptor */ static int pid; /* pid of lpd process */ static int prchild; /* id of pr process */ -static int remote; /* true if sending files to remote */ static char title[80]; /* ``pr'' title */ static int tof; /* true if at top of form */ @@ -118,6 +117,9 @@ static int dofork __P((int)); 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 *, ...)); @@ -136,8 +138,8 @@ printjob() register struct queue *q, **qp; struct queue **queue; register int i, nitems; - long pidoff; - int count = 0; + off_t pidoff; + int errcnt, count = 0; init(); /* set up capabilities */ (void) write(1, "", 1); /* ack that daemon is started */ @@ -210,8 +212,9 @@ again: q = *qp++; if (stat(q->q_name, &stb) < 0) continue; + errcnt = 0; restart: - (void) lseek(lfd, (off_t)pidoff, 0); + (void) lseek(lfd, pidoff, 0); (void) sprintf(line, "%s\n", q->q_name); i = strlen(line); if (write(lfd, line, i) != i) @@ -240,12 +243,13 @@ again: } if (i == OK) /* file ok and printed */ count++; - else if (i == REPRINT) { /* try reprinting the job */ + else if (i == REPRINT && ++errcnt < 5) { + /* try reprinting the job */ syslog(LOG_INFO, "restarting %s", printer); if (ofilter > 0) { kill(ofilter, SIGCONT); /* to be sure */ (void) close(ofd); - while ((i = wait(0)) > 0 && i != ofilter) + while ((i = wait(NULL)) > 0 && i != ofilter) ; ofilter = 0; } @@ -254,6 +258,17 @@ again: syslog(LOG_WARNING, "%s: %s: %m", printer, LO); openpr(); /* 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); + if (i == REPRINT) { + /* insure 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); + } } } free((char *) queue); @@ -329,6 +344,7 @@ printit(file) * H -- "host name" of machine where lpr was done * P -- "person" user's login name * I -- "indent" amount to indent output + * R -- laser dpi "resolution" * f -- "file name" name of text file to print * l -- "file name" text file with control chars * p -- "file name" text file to print with pr(1) @@ -443,6 +459,7 @@ printit(file) case 'N': case 'U': case 'M': + case 'R': continue; } @@ -544,7 +561,6 @@ print(format, file) (void) close(n); execl(_PATH_PR, "pr", width, length, "-h", *title ? title : " ", "-F", 0); - openlog("lpd", LOG_PID, LOG_LPR); syslog(LOG_ERR, "cannot execl %s", _PATH_PR); exit(2); } @@ -623,6 +639,13 @@ print(format, file) 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); + return(ERROR); + } if ((av[0] = rindex(prog, '/')) != NULL) av[0]++; else @@ -641,8 +664,9 @@ print(format, file) ; if (status.w_stopval != WSTOPPED) { (void) close(fi); - syslog(LOG_WARNING, "%s: output filter died (%d)", - printer, status.w_retcode); + syslog(LOG_WARNING, + "%s: output filter died (retcode=%d termsig=%d)", + printer, status.w_retcode, status.w_termsig); return(REPRINT); } stopped++; @@ -658,7 +682,6 @@ start: for (n = 3; n < NOFILE; n++) (void) close(n); execv(prog, av); - openlog("lpd", LOG_PID, LOG_LPR); syslog(LOG_ERR, "cannot execv %s", prog); exit(2); } @@ -686,7 +709,7 @@ start: } if (!WIFEXITED(status)) { - syslog(LOG_WARNING, "%s: Daemon filter '%c' terminated (%d)", + syslog(LOG_WARNING, "%s: filter '%c' terminated (termsig=%d)", printer, format, status.w_termsig); return(ERROR); } @@ -696,11 +719,12 @@ start: return(OK); case 1: return(REPRINT); - default: - syslog(LOG_WARNING, "%s: Daemon filter '%c' exited (%d)", - printer, format, status.w_retcode); case 2: return(ERROR); + default: + syslog(LOG_WARNING, "%s: filter '%c' exited (retcode=%d)", + printer, format, status.w_retcode); + return(FILTERERR); } } @@ -1022,47 +1046,54 @@ sendmail(user, bombed) cp = _PATH_SENDMAIL; sprintf(buf, "%s@%s", user, fromhost); execl(_PATH_SENDMAIL, cp, buf, 0); - openlog("lpd", LOG_PID, LOG_LPR); - syslog(LOG_ERR, "cannot execl %s", _PATH_SENDMAIL); exit(0); } else if (s > 0) { /* parent */ dup2(p[1], 1); printf("To: %s@%s\n", user, fromhost); - printf("Subject: printer job\n\n"); + printf("Subject: %s printer job \"%s\"\n", printer, + *jobname ? jobname : "<unknown>"); + printf("Reply-To: root@%s\n\n", host); printf("Your printer job "); if (*jobname) printf("(%s) ", jobname); switch (bombed) { case OK: printf("\ncompleted successfully\n"); + cp = "OK"; break; default: case FATALERR: printf("\ncould not be printed\n"); + cp = "FATALERR"; break; case NOACCT: printf("\ncould not be printed without an account on %s\n", host); + cp = "NOACCT"; break; case FILTERERR: if (stat(tempfile, &stb) < 0 || stb.st_size == 0 || (fp = fopen(tempfile, "r")) == NULL) { - printf("\nwas printed but had some errors\n"); + printf("\nhad some errors and may not have printed\n"); break; } - printf("\nwas printed but had the following errors:\n"); + printf("\nhad the following errors and may not have printed:\n"); while ((i = getc(fp)) != EOF) putchar(i); (void) fclose(fp); + cp = "FILTERERR"; break; case ACCESS: printf("\nwas not printed because it was not linked to the original file\n"); + cp = "ACCESS"; } fflush(stdout); (void) close(1); } (void) close(p[0]); (void) close(p[1]); - wait(&s); + wait(NULL); + syslog(LOG_INFO, "mail sent to user %s about job %s on printer %s (%s)", + user, *jobname ? jobname : "<unknown>", printer, cp); } /* @@ -1073,7 +1104,6 @@ dofork(action) int action; { register int i, pid; - struct passwd *pwd; for (i = 0; i < 20; i++) { if ((pid = fork()) < 0) { @@ -1083,15 +1113,8 @@ dofork(action) /* * Child should run as daemon instead of root */ - if (pid == 0) { - if ((pwd = getpwuid(DU)) == NULL) { - syslog(LOG_ERR, "Can't lookup default uid in password file"); - break; - } - initgroups(pwd->pw_name, pwd->pw_gid); - setgid(pwd->pw_gid); + if (pid == 0) setuid(DU); - } return(pid); } syslog(LOG_ERR, "can't fork"); @@ -1202,60 +1225,27 @@ init() static void openpr() { - register int i, n; - int resp; + register int i; + char *cp; - if (!sendtorem && *LP) { - for (i = 1; ; i = i < 32 ? i << 1 : i) { - pfd = open(LP, RW ? O_RDWR : O_WRONLY); - if (pfd >= 0) - break; - if (errno == ENOENT) { - syslog(LOG_ERR, "%s: %m", LP); - exit(1); - } - if (i == 1) - pstatus("waiting for %s to become ready (offline ?)", printer); - sleep(i); - } - if (isatty(pfd)) - setty(); - pstatus("%s is ready and printing", printer); - } else if (RM != NULL) { - for (i = 1; ; i = i < 256 ? i << 1 : i) { - resp = -1; - pfd = getport(RM); - if (pfd >= 0) { - (void) sprintf(line, "\2%s\n", RP); - n = strlen(line); - if (write(pfd, line, n) == n && - (resp = response()) == '\0') - break; - (void) close(pfd); - } - if (i == 1) { - if (resp < 0) - pstatus("waiting for %s to come up", RM); - else { - pstatus("waiting for queue to be enabled on %s", RM); - i = 256; - } - } - sleep(i); - } - pstatus("sending to %s", RM); - remote = 1; + if (!remote && *LP) { + if (cp = index(LP, '@')) + opennet(cp); + else + opentty(); + } else if (remote) { + openrem(); } else { syslog(LOG_ERR, "%s: no line printer device or host name", printer); exit(1); } + /* * Start up an output filter, if needed. */ if (!remote && OF) { int p[2]; - char *cp; pipe(p); if ((ofilter = dofork(DOABORT)) == 0) { /* child */ @@ -1269,7 +1259,6 @@ openpr() else cp++; execl(OF, cp, width, length, 0); - openlog("lpd", LOG_PID, LOG_LPR); syslog(LOG_ERR, "%s: %s: %m", printer, OF); exit(1); } @@ -1281,6 +1270,115 @@ openpr() } } +/* + * Printer connected directly to the network + * or to a terminal server on the net + */ +static void +opennet(cp) + char *cp; +{ + register int i; + int resp, port; + char save_ch; + + save_ch = *cp; + *cp = '\0'; + port = atoi(LP); + if (port <= 0) { + syslog(LOG_ERR, "%s: bad port number: %s", printer, LP); + exit(1); + } + *cp++ = save_ch; + + for (i = 1; ; i = i < 256 ? i << 1 : i) { + resp = -1; + pfd = getport(cp, port); + if (pfd < 0 && errno == ECONNREFUSED) + resp = 1; + else if (pfd >= 0) { + /* + * need to delay a bit for rs232 lines + * to stabilize in case printer is + * connected via a terminal server + */ + delay(500); + 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); + } + sleep(i); + } + pstatus("sending to %s port %d", cp, port); +} + +/* + * Printer is connected to an RS232 port on this host + */ +static void +opentty() +{ + register int i; + int resp, port; + + for (i = 1; ; i = i < 32 ? i << 1 : i) { + pfd = open(LP, RW ? O_RDWR : O_WRONLY); + if (pfd >= 0) { + delay(500); + break; + } + if (errno == ENOENT) { + syslog(LOG_ERR, "%s: %m", LP); + exit(1); + } + if (i == 1) + pstatus("waiting for %s to become ready (offline ?)", + printer); + sleep(i); + } + if (isatty(pfd)) + setty(); + pstatus("%s is ready and printing", printer); +} + +/* + * Printer is on a remote host + */ +static void +openrem() +{ + register int i, n; + int resp, port; + + for (i = 1; ; i = i < 256 ? i << 1 : i) { + resp = -1; + pfd = getport(RM, 0); + if (pfd >= 0) { + (void) sprintf(line, "\2%s\n", RP); + n = strlen(line); + if (write(pfd, line, n) == n && + (resp = response()) == '\0') + break; + (void) close(pfd); + } + if (i == 1) { + if (resp < 0) + pstatus("waiting for %s to come up", RM); + else { + pstatus("waiting for queue to be enabled on %s", + RM); + i = 256; + } + } + sleep(i); + } + pstatus("sending to %s", RM); +} + struct bauds { int baud; int speed; @@ -1352,7 +1450,7 @@ setty() #include <varargs.h> #endif -void +static void #if __STDC__ pstatus(const char *msg, ...) #else diff --git a/usr.sbin/lpr/lpd/recvjob.c b/usr.sbin/lpr/lpd/recvjob.c index e199af1..35f946f 100644 --- a/usr.sbin/lpr/lpd/recvjob.c +++ b/usr.sbin/lpr/lpd/recvjob.c @@ -39,7 +39,7 @@ static char copyright[] = #endif /* not lint */ #ifndef lint -static char sccsid[] = "@(#)recvjob.c 8.1 (Berkeley) 6/6/93"; +static char sccsid[] = "@(#)recvjob.c 8.2 (Berkeley) 4/27/95"; #endif /* not lint */ /* @@ -342,7 +342,7 @@ frecverr(msg, va_alist) va_dcl #endif { - extern char *fromb; + extern char fromb[]; va_list ap; #if __STDC__ va_start(ap, msg); diff --git a/usr.sbin/lpr/lpr/lpr.c b/usr.sbin/lpr/lpr/lpr.c index d1f0d8e..efff82a 100644 --- a/usr.sbin/lpr/lpr/lpr.c +++ b/usr.sbin/lpr/lpr/lpr.c @@ -44,7 +44,7 @@ static char copyright[] = #endif /* not lint */ #ifndef lint -static char sccsid[] = "@(#)lpr.c 8.3 (Berkeley) 3/30/94"; +static char sccsid[] = "@(#)lpr.c 8.4 (Berkeley) 4/28/95"; #endif /* not lint */ /* diff --git a/usr.sbin/lpr/runqueue/printjob.c b/usr.sbin/lpr/runqueue/printjob.c index ae0b05a..ea2be9f 100644 --- a/usr.sbin/lpr/runqueue/printjob.c +++ b/usr.sbin/lpr/runqueue/printjob.c @@ -39,7 +39,7 @@ static char copyright[] = #endif /* not lint */ #ifndef lint -static char sccsid[] = "@(#)printjob.c 8.2 (Berkeley) 4/16/94"; +static char sccsid[] = "@(#)printjob.c 8.7 (Berkeley) 5/10/95"; #endif /* not lint */ @@ -96,7 +96,6 @@ static int ofilter; /* id of output filter, if any */ static int pfd; /* prstatic inter file descriptor */ static int pid; /* pid of lpd process */ static int prchild; /* id of pr process */ -static int remote; /* true if sending files to remote */ static char title[80]; /* ``pr'' title */ static int tof; /* true if at top of form */ @@ -118,6 +117,9 @@ static int dofork __P((int)); 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 *, ...)); @@ -136,8 +138,8 @@ printjob() register struct queue *q, **qp; struct queue **queue; register int i, nitems; - long pidoff; - int count = 0; + off_t pidoff; + int errcnt, count = 0; init(); /* set up capabilities */ (void) write(1, "", 1); /* ack that daemon is started */ @@ -210,8 +212,9 @@ again: q = *qp++; if (stat(q->q_name, &stb) < 0) continue; + errcnt = 0; restart: - (void) lseek(lfd, (off_t)pidoff, 0); + (void) lseek(lfd, pidoff, 0); (void) sprintf(line, "%s\n", q->q_name); i = strlen(line); if (write(lfd, line, i) != i) @@ -240,12 +243,13 @@ again: } if (i == OK) /* file ok and printed */ count++; - else if (i == REPRINT) { /* try reprinting the job */ + else if (i == REPRINT && ++errcnt < 5) { + /* try reprinting the job */ syslog(LOG_INFO, "restarting %s", printer); if (ofilter > 0) { kill(ofilter, SIGCONT); /* to be sure */ (void) close(ofd); - while ((i = wait(0)) > 0 && i != ofilter) + while ((i = wait(NULL)) > 0 && i != ofilter) ; ofilter = 0; } @@ -254,6 +258,17 @@ again: syslog(LOG_WARNING, "%s: %s: %m", printer, LO); openpr(); /* 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); + if (i == REPRINT) { + /* insure 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); + } } } free((char *) queue); @@ -329,6 +344,7 @@ printit(file) * H -- "host name" of machine where lpr was done * P -- "person" user's login name * I -- "indent" amount to indent output + * R -- laser dpi "resolution" * f -- "file name" name of text file to print * l -- "file name" text file with control chars * p -- "file name" text file to print with pr(1) @@ -443,6 +459,7 @@ printit(file) case 'N': case 'U': case 'M': + case 'R': continue; } @@ -544,7 +561,6 @@ print(format, file) (void) close(n); execl(_PATH_PR, "pr", width, length, "-h", *title ? title : " ", "-F", 0); - openlog("lpd", LOG_PID, LOG_LPR); syslog(LOG_ERR, "cannot execl %s", _PATH_PR); exit(2); } @@ -623,6 +639,13 @@ print(format, file) 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); + return(ERROR); + } if ((av[0] = rindex(prog, '/')) != NULL) av[0]++; else @@ -641,8 +664,9 @@ print(format, file) ; if (status.w_stopval != WSTOPPED) { (void) close(fi); - syslog(LOG_WARNING, "%s: output filter died (%d)", - printer, status.w_retcode); + syslog(LOG_WARNING, + "%s: output filter died (retcode=%d termsig=%d)", + printer, status.w_retcode, status.w_termsig); return(REPRINT); } stopped++; @@ -658,7 +682,6 @@ start: for (n = 3; n < NOFILE; n++) (void) close(n); execv(prog, av); - openlog("lpd", LOG_PID, LOG_LPR); syslog(LOG_ERR, "cannot execv %s", prog); exit(2); } @@ -686,7 +709,7 @@ start: } if (!WIFEXITED(status)) { - syslog(LOG_WARNING, "%s: Daemon filter '%c' terminated (%d)", + syslog(LOG_WARNING, "%s: filter '%c' terminated (termsig=%d)", printer, format, status.w_termsig); return(ERROR); } @@ -696,11 +719,12 @@ start: return(OK); case 1: return(REPRINT); - default: - syslog(LOG_WARNING, "%s: Daemon filter '%c' exited (%d)", - printer, format, status.w_retcode); case 2: return(ERROR); + default: + syslog(LOG_WARNING, "%s: filter '%c' exited (retcode=%d)", + printer, format, status.w_retcode); + return(FILTERERR); } } @@ -1022,47 +1046,54 @@ sendmail(user, bombed) cp = _PATH_SENDMAIL; sprintf(buf, "%s@%s", user, fromhost); execl(_PATH_SENDMAIL, cp, buf, 0); - openlog("lpd", LOG_PID, LOG_LPR); - syslog(LOG_ERR, "cannot execl %s", _PATH_SENDMAIL); exit(0); } else if (s > 0) { /* parent */ dup2(p[1], 1); printf("To: %s@%s\n", user, fromhost); - printf("Subject: printer job\n\n"); + printf("Subject: %s printer job \"%s\"\n", printer, + *jobname ? jobname : "<unknown>"); + printf("Reply-To: root@%s\n\n", host); printf("Your printer job "); if (*jobname) printf("(%s) ", jobname); switch (bombed) { case OK: printf("\ncompleted successfully\n"); + cp = "OK"; break; default: case FATALERR: printf("\ncould not be printed\n"); + cp = "FATALERR"; break; case NOACCT: printf("\ncould not be printed without an account on %s\n", host); + cp = "NOACCT"; break; case FILTERERR: if (stat(tempfile, &stb) < 0 || stb.st_size == 0 || (fp = fopen(tempfile, "r")) == NULL) { - printf("\nwas printed but had some errors\n"); + printf("\nhad some errors and may not have printed\n"); break; } - printf("\nwas printed but had the following errors:\n"); + printf("\nhad the following errors and may not have printed:\n"); while ((i = getc(fp)) != EOF) putchar(i); (void) fclose(fp); + cp = "FILTERERR"; break; case ACCESS: printf("\nwas not printed because it was not linked to the original file\n"); + cp = "ACCESS"; } fflush(stdout); (void) close(1); } (void) close(p[0]); (void) close(p[1]); - wait(&s); + wait(NULL); + syslog(LOG_INFO, "mail sent to user %s about job %s on printer %s (%s)", + user, *jobname ? jobname : "<unknown>", printer, cp); } /* @@ -1073,7 +1104,6 @@ dofork(action) int action; { register int i, pid; - struct passwd *pwd; for (i = 0; i < 20; i++) { if ((pid = fork()) < 0) { @@ -1083,15 +1113,8 @@ dofork(action) /* * Child should run as daemon instead of root */ - if (pid == 0) { - if ((pwd = getpwuid(DU)) == NULL) { - syslog(LOG_ERR, "Can't lookup default uid in password file"); - break; - } - initgroups(pwd->pw_name, pwd->pw_gid); - setgid(pwd->pw_gid); + if (pid == 0) setuid(DU); - } return(pid); } syslog(LOG_ERR, "can't fork"); @@ -1202,60 +1225,27 @@ init() static void openpr() { - register int i, n; - int resp; + register int i; + char *cp; - if (!sendtorem && *LP) { - for (i = 1; ; i = i < 32 ? i << 1 : i) { - pfd = open(LP, RW ? O_RDWR : O_WRONLY); - if (pfd >= 0) - break; - if (errno == ENOENT) { - syslog(LOG_ERR, "%s: %m", LP); - exit(1); - } - if (i == 1) - pstatus("waiting for %s to become ready (offline ?)", printer); - sleep(i); - } - if (isatty(pfd)) - setty(); - pstatus("%s is ready and printing", printer); - } else if (RM != NULL) { - for (i = 1; ; i = i < 256 ? i << 1 : i) { - resp = -1; - pfd = getport(RM); - if (pfd >= 0) { - (void) sprintf(line, "\2%s\n", RP); - n = strlen(line); - if (write(pfd, line, n) == n && - (resp = response()) == '\0') - break; - (void) close(pfd); - } - if (i == 1) { - if (resp < 0) - pstatus("waiting for %s to come up", RM); - else { - pstatus("waiting for queue to be enabled on %s", RM); - i = 256; - } - } - sleep(i); - } - pstatus("sending to %s", RM); - remote = 1; + if (!remote && *LP) { + if (cp = index(LP, '@')) + opennet(cp); + else + opentty(); + } else if (remote) { + openrem(); } else { syslog(LOG_ERR, "%s: no line printer device or host name", printer); exit(1); } + /* * Start up an output filter, if needed. */ if (!remote && OF) { int p[2]; - char *cp; pipe(p); if ((ofilter = dofork(DOABORT)) == 0) { /* child */ @@ -1269,7 +1259,6 @@ openpr() else cp++; execl(OF, cp, width, length, 0); - openlog("lpd", LOG_PID, LOG_LPR); syslog(LOG_ERR, "%s: %s: %m", printer, OF); exit(1); } @@ -1281,6 +1270,115 @@ openpr() } } +/* + * Printer connected directly to the network + * or to a terminal server on the net + */ +static void +opennet(cp) + char *cp; +{ + register int i; + int resp, port; + char save_ch; + + save_ch = *cp; + *cp = '\0'; + port = atoi(LP); + if (port <= 0) { + syslog(LOG_ERR, "%s: bad port number: %s", printer, LP); + exit(1); + } + *cp++ = save_ch; + + for (i = 1; ; i = i < 256 ? i << 1 : i) { + resp = -1; + pfd = getport(cp, port); + if (pfd < 0 && errno == ECONNREFUSED) + resp = 1; + else if (pfd >= 0) { + /* + * need to delay a bit for rs232 lines + * to stabilize in case printer is + * connected via a terminal server + */ + delay(500); + 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); + } + sleep(i); + } + pstatus("sending to %s port %d", cp, port); +} + +/* + * Printer is connected to an RS232 port on this host + */ +static void +opentty() +{ + register int i; + int resp, port; + + for (i = 1; ; i = i < 32 ? i << 1 : i) { + pfd = open(LP, RW ? O_RDWR : O_WRONLY); + if (pfd >= 0) { + delay(500); + break; + } + if (errno == ENOENT) { + syslog(LOG_ERR, "%s: %m", LP); + exit(1); + } + if (i == 1) + pstatus("waiting for %s to become ready (offline ?)", + printer); + sleep(i); + } + if (isatty(pfd)) + setty(); + pstatus("%s is ready and printing", printer); +} + +/* + * Printer is on a remote host + */ +static void +openrem() +{ + register int i, n; + int resp, port; + + for (i = 1; ; i = i < 256 ? i << 1 : i) { + resp = -1; + pfd = getport(RM, 0); + if (pfd >= 0) { + (void) sprintf(line, "\2%s\n", RP); + n = strlen(line); + if (write(pfd, line, n) == n && + (resp = response()) == '\0') + break; + (void) close(pfd); + } + if (i == 1) { + if (resp < 0) + pstatus("waiting for %s to come up", RM); + else { + pstatus("waiting for queue to be enabled on %s", + RM); + i = 256; + } + } + sleep(i); + } + pstatus("sending to %s", RM); +} + struct bauds { int baud; int speed; @@ -1352,7 +1450,7 @@ setty() #include <varargs.h> #endif -void +static void #if __STDC__ pstatus(const char *msg, ...) #else |