-/* printjob.c 4.4 83/05/19 */
+#ifndef lint
+static char sccsid[] = "@(#)printjob.c 4.15 (Berkeley) %G%";
+#endif
+
/*
* printjob -- print jobs in the queue.
*
#include "lp.h"
-#define DORETURN 0 /* absorb fork error */
-#define DOABORT 1 /* abort if dofork fails */
+#define DORETURN 0 /* absorb fork error */
+#define DOABORT 1 /* abort if dofork fails */
-char title[80]; /* ``pr'' title */
-FILE *cfp; /* control file */
-int pfd; /* printer file descriptor */
-int ofd; /* output filter file descriptor */
-int lfd; /* lock file descriptor */
-int pid; /* pid of lpd process */
-int prchild; /* id of pr process */
-int child; /* id of any filters */
-int ofilter; /* id of output filter, if any */
-int tof = 1; /* top of form; init true if open does ff */
-int remote; /* non zero if sending files to remote */
+static char title[80]; /* ``pr'' title */
+static FILE *cfp; /* control file */
+static int pfd; /* printer file descriptor */
+static int ofd; /* output filter file descriptor */
+static int lfd; /* lock file descriptor */
+static int pid; /* pid of lpd process */
+static int prchild; /* id of pr process */
+static int child; /* id of any filters */
+static int ofilter; /* id of output filter, if any */
+static int tof; /* true if at top of form */
+static int count; /* Number of files actually printed */
+static int remote; /* true if sending files to remote */
-extern banner(); /* big character printer */
-char logname[32]; /* user's login name */
-char jobname[32]; /* job or file name */
-char class[32]; /* classification field */
-char width[10] = "-w"; /* page width in characters */
-char length[10] = "-l"; /* page length in lines */
-char pxwidth[10] = "-x"; /* page width in pixels */
-char pxlength[10] = "-y"; /* page length in pixels */
+static char fromhost[32]; /* user's host machine */
+static char logname[32]; /* user's login name */
+static char jobname[100]; /* job or file name */
+static char class[32]; /* classification field */
+static char width[10] = "-w"; /* page width in characters */
+static char length[10] = "-l"; /* page length in lines */
+static char pxwidth[10] = "-x"; /* page width in pixels */
+static char pxlength[10] = "-y"; /* page length in pixels */
+static char indent[10] = "-i0"; /* indentation size in characters */
printjob()
{
extern int onintr();
init(); /* set up capabilities */
- (void) close(2); /* set up log file */
- (void) open(LF, FWRONLY|FAPPEND, 0);
- dup2(2, 1); /* closes original connection */
+ (void) write(1, "", 1); /* ack that daemon is started */
+ (void) close(1); /* set up log file */
+ (void) close(2);
+ if (open(LF, O_WRONLY|O_APPEND) < 0)
+ (void) open("/dev/null", O_WRONLY);
+ dup(1);
pid = getpid(); /* for use with lprm */
setpgrp(0, pid);
- sigset(SIGINT, onintr);
+ signal(SIGHUP, onintr);
+ signal(SIGINT, onintr);
+ signal(SIGQUIT, onintr);
+ signal(SIGTERM, onintr);
/*
* uses short form file names
}
if (stat(LO, &stb) == 0 && (stb.st_mode & 0100))
exit(0); /* printing disabled */
- if ((lfd = open(LO, FWRONLY|FCREATE|FTRUNCATE|FEXLOCK|FNBLOCK, 0664)) < 0) {
+ lfd = open(LO, O_WRONLY|O_CREAT, 0644);
+ if (lfd < 0) {
+ log("cannot create %s", LO);
+ exit(1);
+ }
+ if (flock(lfd, LOCK_EX|LOCK_NB) < 0) {
if (errno == EWOULDBLOCK) /* active deamon present */
exit(0);
- log("cannot create %s", LO);
+ log("cannot lock %s", LO);
exit(1);
}
+ ftruncate(lfd, 0);
/*
* write process id for others to know
*/
}
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)
+ log("cannot chmod %s", LO);
+ }
openpr(); /* open printer or remote */
again:
/*
else
i = sendit(q->q_name);
/*
- * Check to see if we are supposed to stop printing.
- */
- if (stat(LO, &stb) == 0 && (stb.st_mode & 0100))
- goto done;
- /*
- * Check to see if we should try reprinting the job.
+ * Check to see if we are supposed to stop printing or
+ * if we are to rebuild the queue.
*/
- if (i > 0) {
+ if (fstat(lfd, &stb) == 0) {
+ if (stb.st_mode & 0100)
+ goto done;
+ if (stb.st_mode & 01) {
+ for (free((char *) q); nitems--; free((char *) q))
+ q = *qp++;
+ if (fchmod(lfd, stb.st_mode & 0776) < 0)
+ log("cannot chmod %s", LO);
+ break;
+ }
+ }
+ if (i == 0) /* file ok and printed */
+ count++;
+ else if (i > 0) { /* try reprinting the job */
log("restarting");
if (ofilter > 0) {
kill(ofilter, SIGCONT); /* to be sure */
}
if (nitems == 0) { /* no more work to do */
done:
- if (!SF && !tof)
- (void) write(ofd, FF, strlen(FF));
- if (TR != NULL) /* output trailer */
- (void) write(ofd, TR, strlen(TR));
+ 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));
+ }
exit(0);
}
goto again;
* Returns 0 if everthing was OK, 1 if we should try to reprint the job and
* -1 if a non-recoverable error occured.
*/
+static
printit(file)
char *file;
{
* T -- "title" for pr
* H -- "host name" of machine where lpr was done
* P -- "person" user's login name
- * I -- "indent" changes default indents driver
- * must have stty/gtty avaialble
+ * I -- "indent" amount to indent output
* 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)
* t -- "file name" troff(1) file to print
+ * n -- "file name" ditroff(1) file to print
* d -- "file name" dvi file to print
* g -- "file name" plot(1G) file to print
* v -- "file name" plain raster file to print
while (getline(cfp))
switch (line[0]) {
case 'H':
- strcpy(host, line+1);
+ strcpy(fromhost, line+1);
if (class[0] == '\0')
- strcpy(class, line+1);
+ strncpy(class, line+1, sizeof(class)-1);
continue;
case 'P':
- strcpy(logname, line+1);
+ strncpy(logname, line+1, sizeof(logname)-1);
if (RS) { /* restricted */
if (getpwnam(logname) == (struct passwd *)0) {
bombed = 2;
case 'J':
if (line[1] != '\0')
- strcpy(jobname, line+1);
+ strncpy(jobname, line+1, sizeof(jobname)-1);
else
strcpy(jobname, " ");
continue;
case 'C':
if (line[1] != '\0')
- strcpy(class, line+1);
+ strncpy(class, line+1, sizeof(class)-1);
else if (class[0] == '\0')
gethostname(class, sizeof (class));
continue;
case 'T': /* header title for pr */
- strcpy(title, line+1);
+ strncpy(title, line+1, sizeof(title)-1);
continue;
case 'L': /* identification line */
continue;
case 'W': /* page width */
- strcpy(width+2, line+1);
+ strncpy(width+2, line+1, sizeof(width)-3);
+ continue;
+
+ case 'I': /* indent amount */
+ strncpy(indent+2, line+1, sizeof(indent)-3);
continue;
default: /* some file to print */
title[0] = '\0';
continue;
- case 'I':
case 'N':
case 'U':
case 'M':
*/
(void) fclose(cfp);
(void) unlink(file);
- return(0);
+ return(bombed ? -1 : 0);
}
/*
* Print a file.
- * Set up the chain [ PR [ | {IF, OF} ] ] or {IF, TF, CF, VF}.
+ * Set up the chain [ PR [ | {IF, OF} ] ] or {IF, RF, TF, NF, DF, CF, VF}.
* Return -1 if a non-recoverable error occured, 1 if a recoverable error and
* 0 if all is well.
* Note: all filters take stdin as the file, stdout as the printer,
* stderr as the log file, and must not ignore SIGINT.
*/
+static
print(format, file)
int format;
char *file;
int pid, p[2], stopped = 0;
union wait status;
- if ((fi = open(file, FRDONLY, 0)) < 0) {
+ if ((fi = open(file, O_RDONLY)) < 0) {
log("%s: open failure <errno = %d>", file, errno);
return(-1);
}
prog = IF;
av[1] = width;
av[2] = length;
- n = 3;
+ av[3] = indent;
+ n = 4;
break;
case 'l': /* like 'f' but pass control characters */
prog = IF;
- av[1] = "-l";
+ av[1] = "-c";
av[2] = width;
av[3] = length;
- n = 4;
+ av[4] = indent;
+ n = 5;
break;
case 'r': /* print a fortran text file */
prog = RF;
n = 3;
break;
case 't': /* print troff output */
+ case 'n': /* print ditroff output */
case 'd': /* print tex output */
(void) unlink(".railmag");
if ((fo = creat(".railmag", FILMOD)) < 0) {
}
(void) close(fo);
}
- prog = (format == 't') ? TF : DF;
+ prog = (format == 't') ? TF : (format == 'n') ? NF : DF;
av[1] = pxwidth;
av[2] = pxlength;
n = 3;
av[n++] = "-n";
av[n++] = logname;
av[n++] = "-h";
- av[n++] = host;
+ av[n++] = fromhost;
av[n++] = AF;
av[n] = 0;
fo = pfd;
* Return -1 if a non-recoverable error occured, 1 if a recoverable error and
* 0 if all is well.
*/
+static
sendit(file)
char *file;
{
* Send a data file to the remote machine and spool it.
* Return positive if we should try resending.
*/
+static
sendfile(type, file)
char type, *file;
{
char buf[BUFSIZ];
int sizerr;
- if ((f = open(file, FRDONLY, 0)) < 0 || fstat(f, &stb) < 0) {
+ if ((f = open(file, O_RDONLY)) < 0 || fstat(f, &stb) < 0) {
log("file (%s) open failure <errno = %d>", file, errno);
return(-1);
}
(void) sprintf(buf, "%c%d %s\n", type, stb.st_size, file);
amt = strlen(buf);
- if (write(pfd, buf, amt) != amt)
+ if (write(pfd, buf, amt) != amt) {
+ (void) close(f);
return(1);
- if (noresponse())
+ }
+ if (noresponse()) {
+ (void) close(f);
return(1);
+ }
sizerr = 0;
for (i = 0; i < stb.st_size; i += BUFSIZ) {
amt = BUFSIZ;
amt = stb.st_size - i;
if (sizerr == 0 && read(f, buf, amt) != amt)
sizerr = 1;
- if (write(pfd, buf, amt) != amt)
+ if (write(pfd, buf, amt) != amt) {
+ (void) close(f);
return(1);
+ }
}
(void) close(f);
if (sizerr) {
/*
* Banner printing stuff
*/
+static
banner(name1, name2)
char *name1, *name2;
{
tof = 1;
}
-char *
+static char *
scnline(key, p, c)
register char key, *p;
char c;
#define TRC(q) (((q)-' ')&0177)
+static
scan_out(scfd, scsp, dlm)
int scfd;
char *scsp, dlm;
}
}
+static
dropit(c)
char c;
{
* sendmail ---
* tell people about job completion
*/
+static
sendmail(bombed)
int bombed;
{
cp++;
else
cp = MAIL;
- sprintf(buf, "%s@%s", line+1, host);
+ sprintf(buf, "%s@%s", line+1, fromhost);
execl(MAIL, cp, buf, 0);
exit(0);
} else if (stat > 0) { /* parent */
dup2(p[1], 1);
- printf("To: %s\n", line+1);
+ printf("To: %s@%s\n", line+1, fromhost);
printf("Subject: printer job\n\n");
printf("Your printer job ");
if (*jobname)
/*
* dofork - fork with retries on failure
*/
+static
dofork(action)
int action;
{
}
/*
- * Cleanup child processes when a SIGINT is caught.
+ * Cleanup child processes when a signal is caught.
*/
+static
onintr()
{
kill(0, SIGINT);
exit(0);
}
+static
init()
{
int status;
- if ((status = pgetent(line, printer)) < 0) {
- log("can't open printer description file");
- exit(1);
- } else if (status == 0) {
- log("unknown printer");
- exit(1);
- }
+ if ((status = pgetent(line, printer)) < 0)
+ fatal("can't open printer description file");
+ else if (status == 0)
+ fatal("unknown printer");
if ((LP = pgetstr("lp", &bp)) == NULL)
LP = DEFDEVLP;
if ((RP = pgetstr("rp", &bp)) == NULL)
IF = pgetstr("if", &bp);
RF = pgetstr("rf", &bp);
TF = pgetstr("tf", &bp);
+ NF = pgetstr("nf", &bp);
DF = pgetstr("df", &bp);
GF = pgetstr("gf", &bp);
VF = pgetstr("vf", &bp);
XC = 0;
if ((XS = pgetnum("xs")) < 0)
XS = 0;
+ tof = !pgetflag("fo");
}
/*
* Acquire line printer or remote connection.
*/
+static
openpr()
{
register int i, n;
if (*LP) {
for (i = 1; ; i = i < 32 ? i << 1 : i) {
- pfd = open(LP, RW ? FRDWR : FWRONLY, 0);
+ pfd = open(LP, RW ? O_RDWR : O_WRONLY);
if (pfd >= 0)
break;
if (errno == ENOENT) {
/*
* setup tty lines.
*/
+static
setty()
{
struct sgttyb ttybuf;
}
ttybuf.sg_ispeed = ttybuf.sg_ospeed = bp->speed;
}
- if (FC)
- ttybuf.sg_flags &= ~FC;
- if (FS)
- ttybuf.sg_flags |= FS;
+ ttybuf.sg_flags &= ~FC;
+ ttybuf.sg_flags |= FS;
if (ioctl(pfd, TIOCSETP, (char *)&ttybuf) < 0) {
log("cannot set tty parameters");
exit(1);
char buf[BUFSIZ];
umask(0);
- if ((fd = open(ST, FWRONLY|FCREATE|FTRUNCATE|FEXLOCK, 0664)) < 0)
+ fd = open(ST, O_WRONLY|O_CREAT, 0664);
+ if (fd < 0 || flock(fd, LOCK_EX) < 0)
fatal("cannot create status file");
+ ftruncate(fd, 0);
sprintf(buf, msg, a1, a2, a3);
strcat(buf, "\n");
(void) write(fd, buf, strlen(buf));