diff options
author | joerg <joerg@FreeBSD.org> | 1996-05-05 14:04:33 +0000 |
---|---|---|
committer | joerg <joerg@FreeBSD.org> | 1996-05-05 14:04:33 +0000 |
commit | 0291e848bc787305335af649ac14bc8fe5a19a49 (patch) | |
tree | f679484620675241701b875cbab6124b83dc1136 /usr.sbin/lpr/lpd | |
parent | 825cd02612729df0559ca26d13d946c625215900 (diff) | |
download | FreeBSD-src-0291e848bc787305335af649ac14bc8fe5a19a49.zip FreeBSD-src-0291e848bc787305335af649ac14bc8fe5a19a49.tar.gz |
Vendor-branch import of the 4.4BSD-Lite2 code for lpr. There are
several bugfixes in it that are worth considering.
Don't be alarmed about the import conflicts...
Obtained from: 4.4BSD-Lite2
Diffstat (limited to 'usr.sbin/lpr/lpd')
-rw-r--r-- | usr.sbin/lpr/lpd/lpd.c | 37 | ||||
-rw-r--r-- | usr.sbin/lpr/lpd/printjob.c | 240 | ||||
-rw-r--r-- | usr.sbin/lpr/lpd/recvjob.c | 4 |
3 files changed, 216 insertions, 65 deletions
diff --git a/usr.sbin/lpr/lpd/lpd.c b/usr.sbin/lpr/lpd/lpd.c index aaf72b7..3b23359 100644 --- a/usr.sbin/lpr/lpd/lpd.c +++ b/usr.sbin/lpr/lpd/lpd.c @@ -39,7 +39,7 @@ static char copyright[] = #endif /* not lint */ #ifndef lint -static char sccsid[] = "@(#)lpd.c 8.4 (Berkeley) 4/17/94"; +static char sccsid[] = "@(#)lpd.c 8.7 (Berkeley) 5/10/95"; #endif /* not lint */ /* @@ -77,6 +77,7 @@ static char sccsid[] = "@(#)lpd.c 8.4 (Berkeley) 4/17/94"; #include <sys/socket.h> #include <sys/un.h> #include <sys/stat.h> +#include <sys/file.h> #include <netinet/in.h> #include <netdb.h> @@ -103,6 +104,7 @@ 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 *)); int main(argc, argv) @@ -429,11 +431,17 @@ startup() * Restart the daemons. */ while (cgetnext(&buf, printcapdb) > 0) { + 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); if ((pid = fork()) < 0) { syslog(LOG_WARNING, "startup: cannot fork"); mcleanup(0); @@ -442,8 +450,35 @@ startup() printer = buf; cgetclose(); printjob(); + /* NOTREACHED */ } + else free(buf); + } +} + +/* + * Make sure there's some work to do before forking off a child + */ +static int +ckqueue(cap) + char *cap; +{ + register struct dirent *d; + DIR *dirp; + char *spooldir; + + if (cgetstr(cap, "sd", &spooldir) == -1) + spooldir = _PATH_DEFSPOOL; + if ((dirp = opendir(spooldir)) == NULL) + return (-1); + while ((d = readdir(dirp)) != NULL) { + if (d->d_name[0] != 'c' || d->d_name[1] != 'f') + continue; /* daemon control files only */ + closedir(dirp); + return (1); /* found something */ } + closedir(dirp); + return (0); } #define DUMMY ":nobody::" diff --git a/usr.sbin/lpr/lpd/printjob.c b/usr.sbin/lpr/lpd/printjob.c index 87c9352..2d17619 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 */ @@ -54,6 +54,7 @@ static char sccsid[] = "@(#)printjob.c 8.2 (Berkeley) 4/16/94"; #include <sys/wait.h> #include <sys/stat.h> #include <sys/types.h> +#include <sys/file.h> #include <pwd.h> #include <unistd.h> @@ -95,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 */ @@ -117,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 *, ...)); @@ -135,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 */ @@ -209,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) @@ -239,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; } @@ -253,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); @@ -328,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) @@ -442,6 +459,7 @@ printit(file) case 'N': case 'U': case 'M': + case 'R': continue; } @@ -537,6 +555,7 @@ print(format, file) if ((prchild = dofork(DORETURN)) == 0) { /* child */ dup2(fi, 0); /* file is stdin */ dup2(p[1], 1); /* pipe is stdout */ + closelog(); for (n = 3; n < NOFILE; n++) (void) close(n); execl(_PATH_PR, "pr", width, length, @@ -619,6 +638,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 @@ -637,8 +663,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++; @@ -650,6 +677,7 @@ start: n = open(tempfile, O_WRONLY|O_CREAT|O_TRUNC, 0664); if (n >= 0) dup2(n, 2); + closelog(); for (n = 3; n < NOFILE; n++) (void) close(n); execv(prog, av); @@ -680,7 +708,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); } @@ -690,11 +718,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); } } @@ -809,7 +838,7 @@ sendfile(type, file) if ((stb.st_mode & S_IFMT) == S_IFLNK && fstat(f, &stb) == 0 && (stb.st_dev != fdev || stb.st_ino != fino)) return(ACCESS); - (void) sprintf(buf, "%c%qd %s\n", type, stb.st_size, file); + (void) sprintf(buf, "%c%ld %s\n", type, (long)stb.st_size, file); amt = strlen(buf); for (i = 0; ; i++) { if (write(pfd, buf, amt) != amt || @@ -1007,6 +1036,7 @@ sendmail(user, bombed) pipe(p); if ((s = dofork(DORETURN)) == 0) { /* child */ dup2(p[0], 0); + closelog(); for (i = 3; i < NOFILE; i++) (void) close(i); if ((cp = rindex(_PATH_SENDMAIL, '/')) != NULL) @@ -1019,41 +1049,50 @@ sendmail(user, bombed) } 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); } /* @@ -1192,65 +1231,33 @@ 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 */ dup2(p[0], 0); /* pipe is std in */ dup2(pfd, 1); /* printer is std out */ + closelog(); for (i = 3; i < NOFILE; i++) (void) close(i); if ((cp = rindex(OF, '/')) == NULL) @@ -1269,6 +1276,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; @@ -1344,7 +1460,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 67a6183..0b4156c 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); |