fixed -c option to `if' filter
[unix-history] / usr / src / usr.sbin / lpr / lpd / printjob.c
index 7f23a18..e95cb85 100644 (file)
@@ -1,4 +1,7 @@
-/*     printjob.c      4.1     83/04/29        */
+#ifndef lint
+static char sccsid[] = "@(#)printjob.c 4.13 (Berkeley) %G%";
+#endif
+
 /*
  * printjob -- print jobs in the queue.
  *
 /*
  * printjob -- print jobs in the queue.
  *
 
 #include "lp.h"
 
 
 #include "lp.h"
 
-#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 */
-
-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 for `pr' */
-char   length[10] = "-l";      /* page length for `pr' */
+#define DORETURN       0               /* absorb fork error */
+#define DOABORT                1               /* abort if dofork fails */
+
+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 */
+
+static char    fromhost[32];           /* user's host machine */
+static char    logname[32];            /* user's login name */
+static char    jobname[32];            /* 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()
 {
 
 printjob()
 {
@@ -39,14 +46,16 @@ printjob()
        long pidoff;
        extern int onintr();
 
        long pidoff;
        extern int onintr();
 
-       name = "printjob";
        init();                                 /* set up capabilities */
        init();                                 /* set up capabilities */
-       (void) close(2);                        /* set up log file */
-       (void) open(LF, FWRONLY|FAPPEND, 0);
-       dup2(2, 1);
-       pid = getpid();
+       (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);
        setpgrp(0, pid);
-       sigset(SIGINT, onintr);                 /* for use with lprm */
+       signal(SIGINT, onintr);
 
        /*
         * uses short form file names
 
        /*
         * uses short form file names
@@ -55,110 +64,44 @@ printjob()
                log("cannot chdir to %s", SD);
                exit(1);
        }
                log("cannot chdir to %s", SD);
                exit(1);
        }
-       if ((lfd = open(LO, FWRONLY|FCREATE|FTRUNCATE|FEXLOCK|FNBLOCK, 0664)) < 0) {
+       if (stat(LO, &stb) == 0 && (stb.st_mode & 0100))
+               exit(0);                /* printing disabled */
+       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);
                if (errno == EWOULDBLOCK)       /* active deamon present */
                        exit(0);
-               log("cannot create %s", LO);
+               log("cannot lock %s", LO);
                exit(1);
        }
                exit(1);
        }
+       ftruncate(lfd, 0);
        /*
         * write process id for others to know
         */
        sprintf(line, "%u\n", pid);
        pidoff = i = strlen(line);
        /*
         * write process id for others to know
         */
        sprintf(line, "%u\n", pid);
        pidoff = i = strlen(line);
-       if (write(lfd, line, i) != i)
+       if (write(lfd, line, i) != i) {
                log("cannot write daemon pid");
                log("cannot write daemon pid");
-       /*
-        * acquire line printer or remote connection
-        */
-restart:
-       if (*LP) {
-               for (i = 1; ; i = i < 32 ? i << 1 : i) {
-                       pfd = open(LP, RW ? FRDWR : FWRONLY, 0);
-                       if (pfd >= 0)
-                               break;
-                       if (errno == ENOENT) {
-                               log("cannot open %s", LP);
-                               exit(1);
-                       }
-                       if (i == 1)
-                               status("waiting for %s to become ready (offline ?)", printer);
-                       sleep(i);
-               }
-               if (isatty(pfd))
-                       setty();
-               status("%s is ready and printing", printer);
-       } else if (RM != NULL) {
-               for (i = 1; ; i = i < 512 ? i << 1 : i) {
-                       pfd = getport();
-                       if (pfd >= 0) {
-                               (void) sprintf(line, "\2%s\n", RP);
-                               nitems = strlen(line);
-                               if (write(pfd, line, nitems) != nitems)
-                                       break;
-                               if (noresponse())
-                                       (void) close(pfd);
-                               else
-                                       break;
-                       }
-                       if (i == 1)
-                               status("waiting for %s to come up", RM);
-                       sleep(i);
-               }
-               status("sending to %s", RM);
-               remote = 1;
-       } else {
-               log("no line printer device or remote machine name");
                exit(1);
        }
                exit(1);
        }
-       /*
-        * Start running as daemon instead of root
-        */
-       setuid(DU);
-       /*
-        * Start up an output filter, if needed.
-        */
-       if (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 */
-                       for (i = 3; i < NOFILE; i++)
-                               (void) close(i);
-                       if ((cp = rindex(OF, '/')) == NULL)
-                               cp = OF;
-                       else
-                               cp++;
-                       execl(OF, cp, 0);
-                       log("can't execl output filter %s", OF);
-                       exit(1);
-               }
-               (void) close(p[0]);             /* close input side */
-               ofd = p[1];                     /* use pipe for output */
-       } else {
-               ofd = pfd;
-               ofilter = 0;
-       }
-
        /*
         * search the spool directory for work and sort by queue order.
         */
        /*
         * search the spool directory for work and sort by queue order.
         */
-again:
        if ((nitems = getq(&queue)) < 0) {
                log("can't scan spool directory %s", SD);
                exit(1);
        }
        if ((nitems = getq(&queue)) < 0) {
                log("can't scan spool directory %s", SD);
                exit(1);
        }
-       if (nitems == 0) {              /* EOF => no work to do */
-               if (!SF && !tof)
-                       (void) write(ofd, FF, strlen(FF));
-               if (TR != NULL)         /* output trailer */
-                       (void) write(ofd, TR, strlen(TR));
+       if (nitems == 0)                /* no work to do */
                exit(0);
                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:
        /*
         * we found something to do now do it --
         *    write the name of the current control file into the lock file
        /*
         * we found something to do now do it --
         *    write the name of the current control file into the lock file
@@ -168,6 +111,7 @@ again:
                q = *qp++;
                if (stat(q->q_name, &stb) < 0)
                        continue;
                q = *qp++;
                if (stat(q->q_name, &stb) < 0)
                        continue;
+       restart:
                (void) lseek(lfd, pidoff, 0);
                (void) sprintf(line, "%s\n", q->q_name);
                i = strlen(line);
                (void) lseek(lfd, pidoff, 0);
                (void) sprintf(line, "%s\n", q->q_name);
                i = strlen(line);
@@ -177,7 +121,24 @@ again:
                        i = printit(q->q_name);
                else
                        i = sendit(q->q_name);
                        i = printit(q->q_name);
                else
                        i = sendit(q->q_name);
-               if (i > 0) {    /* restart daemon to reprint job */
+               /*
+                * Check to see if we are supposed to stop printing or
+                * if we are to rebuild the queue.
+                */
+               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 */
                        log("restarting");
                        if (ofilter > 0) {
                                kill(ofilter, SIGCONT); /* to be sure */
@@ -186,15 +147,32 @@ again:
                                        ;
                                ofilter = 0;
                        }
                                        ;
                                ofilter = 0;
                        }
-                       (void) close(pfd);
-                       free((char *) q);
-                       while (nitems--)
-                               free((char *) *qp++);
-                       free((char *) queue);
+                       (void) close(pfd);      /* close printer */
+                       (void) lseek(lfd, pidoff, 0);
+                       if (write(lfd, "\n", 1) != 1)
+                               log("can't write (%d) control file name", errno);
+                       openpr();               /* try to reopen printer */
                        goto restart;
                }
        }
        free((char *) queue);
                        goto restart;
                }
        }
        free((char *) queue);
+       /*
+        * search the spool directory for more work.
+        */
+       if ((nitems = getq(&queue)) < 0) {
+               log("can't scan spool directory %s", SD);
+               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));
+               }
+               exit(0);
+       }
        goto again;
 }
 
        goto again;
 }
 
@@ -213,6 +191,7 @@ static char ifonts[4][18] = {
  * Returns 0 if everthing was OK, 1 if we should try to reprint the job and
  * -1 if a non-recoverable error occured.
  */
  * 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;
 {
 printit(file)
        char *file;
 {
@@ -245,12 +224,12 @@ printit(file)
         *              T -- "title" for pr
         *              H -- "host name" of machine where lpr was done
         *              P -- "person" user's login name
         *              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
         *              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
         *              d -- "file name" dvi file to print
         *              g -- "file name" plot(1G) file to print
         *              v -- "file name" plain raster file to print
@@ -272,13 +251,20 @@ printit(file)
        while (getline(cfp))
                switch (line[0]) {
                case 'H':
        while (getline(cfp))
                switch (line[0]) {
                case 'H':
-                       strcpy(host, line+1);
+                       strcpy(fromhost, line+1);
                        if (class[0] == '\0')
                                strcpy(class, line+1);
                        continue;
 
                case 'P':
                        strcpy(logname, line+1);
                        if (class[0] == '\0')
                                strcpy(class, line+1);
                        continue;
 
                case 'P':
                        strcpy(logname, line+1);
+                       if (RS) {                       /* restricted */
+                               if (getpwnam(logname) == (struct passwd *)0) {
+                                       bombed = 2;
+                                       sendmail(bombed);
+                                       goto pass2;
+                               }
+                       }
                        continue;
 
                case 'J':
                        continue;
 
                case 'J':
@@ -316,6 +302,10 @@ printit(file)
                        strcpy(width+2, line+1);
                        continue;
 
                        strcpy(width+2, line+1);
                        continue;
 
+               case 'I':       /* indent amount */
+                       strcpy(indent+2, line+1);
+                       continue;
+
                default:        /* some file to print */
                        if ((i = print(line[0], line+1)) > 0) {
                                (void) fclose(cfp);
                default:        /* some file to print */
                        if ((i = print(line[0], line+1)) > 0) {
                                (void) fclose(cfp);
@@ -325,7 +315,6 @@ printit(file)
                        title[0] = '\0';
                        continue;
 
                        title[0] = '\0';
                        continue;
 
-               case 'I':
                case 'N':
                case 'U':
                case 'M':
                case 'N':
                case 'U':
                case 'M':
@@ -334,11 +323,13 @@ printit(file)
 
        /* pass 2 */
 
 
        /* pass 2 */
 
+pass2:
        fseek(cfp, 0L, 0);
        while (getline(cfp))
                switch (line[0]) {
                case 'M':
        fseek(cfp, 0L, 0);
        while (getline(cfp))
                switch (line[0]) {
                case 'M':
-                       sendmail(bombed);
+                       if (bombed != 2)                /* already sent if 2 */
+                               sendmail(bombed);
                        continue;
 
                case 'U':
                        continue;
 
                case 'U':
@@ -349,17 +340,18 @@ printit(file)
         */
        (void) fclose(cfp);
        (void) unlink(file);
         */
        (void) fclose(cfp);
        (void) unlink(file);
-       return(0);
+       return(bombed ? -1 : 0);
 }
 
 /*
  * Print a file.
 }
 
 /*
  * 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.
  */
  * 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;
 print(format, file)
        int format;
        char *file;
@@ -370,7 +362,7 @@ print(format, file)
        int pid, p[2], stopped = 0;
        union wait status;
 
        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);
        }
                log("%s: open failure <errno = %d>", file, errno);
                return(-1);
        }
@@ -423,19 +415,28 @@ print(format, file)
                prog = IF;
                av[1] = width;
                av[2] = length;
                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;
                break;
        case 'l':       /* like 'f' but pass control characters */
                prog = IF;
-               av[1] = "-l";
+               av[1] = "-c";
                av[2] = width;
                av[3] = length;
                av[2] = width;
                av[3] = length;
-               n = 4;
+               av[4] = indent;
+               n = 5;
+               break;
+       case 'r':       /* print a fortran text file */
+               prog = RF;
+               av[1] = width;
+               av[2] = length;
+               n = 3;
                break;
        case 't':       /* print troff output */
                break;
        case 't':       /* print troff output */
-       case 'd':       /* print troff output */
+       case 'n':       /* print ditroff output */
+       case 'd':       /* print tex output */
                (void) unlink(".railmag");
                (void) unlink(".railmag");
-               if ((fo = creat(".railmag", 0666)) < 0) {
+               if ((fo = creat(".railmag", FILMOD)) < 0) {
                        log("cannot create .railmag");
                        (void) unlink(".railmag");
                } else {
                        log("cannot create .railmag");
                        (void) unlink(".railmag");
                } else {
@@ -447,20 +448,28 @@ print(format, file)
                        }
                        (void) close(fo);
                }
                        }
                        (void) close(fo);
                }
-               prog = (format == 't') ? TF : DF;
-               n = 1;
+               prog = (format == 't') ? TF : (format == 'n') ? NF : DF;
+               av[1] = pxwidth;
+               av[2] = pxlength;
+               n = 3;
                break;
        case 'c':       /* print cifplot output */
                prog = CF;
                break;
        case 'c':       /* print cifplot output */
                prog = CF;
-               n = 1;
+               av[1] = pxwidth;
+               av[2] = pxlength;
+               n = 3;
                break;
        case 'g':       /* print plot(1G) output */
                prog = GF;
                break;
        case 'g':       /* print plot(1G) output */
                prog = GF;
-               n = 1;
+               av[1] = pxwidth;
+               av[2] = pxlength;
+               n = 3;
                break;
        case 'v':       /* print raster output */
                prog = VF;
                break;
        case 'v':       /* print raster output */
                prog = VF;
-               n = 1;
+               av[1] = pxwidth;
+               av[2] = pxlength;
+               n = 3;
                break;
        default:
                (void) close(fi);
                break;
        default:
                (void) close(fi);
@@ -474,7 +483,7 @@ print(format, file)
        av[n++] = "-n";
        av[n++] = logname;
        av[n++] = "-h";
        av[n++] = "-n";
        av[n++] = logname;
        av[n++] = "-h";
-       av[n++] = host;
+       av[n++] = fromhost;
        av[n++] = AF;
        av[n] = 0;
        fo = pfd;
        av[n++] = AF;
        av[n] = 0;
        fo = pfd;
@@ -528,6 +537,7 @@ start:
  * Return -1 if a non-recoverable error occured, 1 if a recoverable error and
  * 0 if all is well.
  */
  * Return -1 if a non-recoverable error occured, 1 if a recoverable error and
  * 0 if all is well.
  */
+static
 sendit(file)
        char *file;
 {
 sendit(file)
        char *file;
 {
@@ -596,6 +606,7 @@ sendit(file)
  * Send a data file to the remote machine and spool it.
  * Return positive if we should try resending.
  */
  * 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;
 {
 sendfile(type, file)
        char type, *file;
 {
@@ -604,16 +615,20 @@ sendfile(type, file)
        char buf[BUFSIZ];
        int sizerr;
 
        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);
                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);
                return(1);
-       if (noresponse())
+       }
+       if (noresponse()) {
+               (void) close(f);
                return(1);
                return(1);
+       }
        sizerr = 0;
        for (i = 0; i < stb.st_size; i += BUFSIZ) {
                amt = BUFSIZ;
        sizerr = 0;
        for (i = 0; i < stb.st_size; i += BUFSIZ) {
                amt = BUFSIZ;
@@ -621,8 +636,10 @@ sendfile(type, file)
                        amt = stb.st_size - i;
                if (sizerr == 0 && read(f, buf, amt) != amt)
                        sizerr = 1;
                        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);
                        return(1);
+               }
        }
        (void) close(f);
        if (sizerr) {
        }
        (void) close(f);
        if (sizerr) {
@@ -657,6 +674,7 @@ noresponse()
 /*
  * Banner printing stuff
  */
 /*
  * Banner printing stuff
  */
+static
 banner(name1, name2)
        char *name1, *name2;
 {
 banner(name1, name2)
        char *name1, *name2;
 {
@@ -697,7 +715,7 @@ banner(name1, name2)
        tof = 1;
 }
 
        tof = 1;
 }
 
-char *
+static char *
 scnline(key, p, c)
        register char key, *p;
        char c;
 scnline(key, p, c)
        register char key, *p;
        char c;
@@ -713,6 +731,7 @@ scnline(key, p, c)
 
 #define TRC(q) (((q)-' ')&0177)
 
 
 #define TRC(q) (((q)-' ')&0177)
 
+static
 scan_out(scfd, scsp, dlm)
        int scfd;
        char *scsp, dlm;
 scan_out(scfd, scsp, dlm)
        int scfd;
        char *scsp, dlm;
@@ -746,6 +765,7 @@ scan_out(scfd, scsp, dlm)
        }
 }
 
        }
 }
 
+static
 dropit(c)
        char c;
 {
 dropit(c)
        char c;
 {
@@ -770,6 +790,7 @@ dropit(c)
  * sendmail ---
  *   tell people about job completion
  */
  * sendmail ---
  *   tell people about job completion
  */
+static
 sendmail(bombed)
        int bombed;
 {
 sendmail(bombed)
        int bombed;
 {
@@ -788,20 +809,28 @@ sendmail(bombed)
                        cp++;
                else
                        cp = MAIL;
                        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);
                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)
                        printf("(%s) ", jobname);
                printf("Subject: printer job\n\n");
                printf("Your printer job ");
                if (*jobname)
                        printf("(%s) ", jobname);
-               if (bombed)
-                       printf("bombed\n");
-               else
-                       printf("is done\n");
+               switch (bombed) {
+               case 0:
+                       printf("\ncompleted successfully\n");
+                       break;
+               default:
+               case 1:
+                       printf("\ncould not be printed\n");
+                       break;
+               case 2:
+                       printf("\ncould not be printed without an account on %s\n", host);
+                       break;
+               }
                fflush(stdout);
                (void) close(1);
        }
                fflush(stdout);
                (void) close(1);
        }
@@ -813,16 +842,23 @@ sendmail(bombed)
 /*
  * dofork - fork with retries on failure
  */
 /*
  * dofork - fork with retries on failure
  */
+static
 dofork(action)
        int action;
 {
        register int i, pid;
 
        for (i = 0; i < 20; i++) {
 dofork(action)
        int action;
 {
        register int i, pid;
 
        for (i = 0; i < 20; i++) {
-               if ((pid = fork()) < 0)
+               if ((pid = fork()) < 0) {
                        sleep((unsigned)(i*i));
                        sleep((unsigned)(i*i));
-               else
-                       return(pid);
+                       continue;
+               }
+               /*
+                * Child should run as daemon instead of root
+                */
+               if (pid == 0)
+                       setuid(DU);
+               return(pid);
        }
        log("can't fork");
 
        }
        log("can't fork");
 
@@ -841,6 +877,7 @@ dofork(action)
 /*
  * Cleanup child processes when a SIGINT is caught.
  */
 /*
  * Cleanup child processes when a SIGINT is caught.
  */
+static
 onintr()
 {
        kill(0, SIGINT);
 onintr()
 {
        kill(0, SIGINT);
@@ -851,21 +888,19 @@ onintr()
        exit(0);
 }
 
        exit(0);
 }
 
+static
 init()
 {
        int status;
 
 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 ((LP = pgetstr("lp", &bp)) == NULL)
                LP = DEFDEVLP;
        if ((RP = pgetstr("rp", &bp)) == NULL)
-               RP = printer;
+               RP = DEFLP;
        if ((LO = pgetstr("lo", &bp)) == NULL)
                LO = DEFLOCK;
        if ((ST = pgetstr("st", &bp)) == NULL)
        if ((LO = pgetstr("lo", &bp)) == NULL)
                LO = DEFLOCK;
        if ((ST = pgetstr("st", &bp)) == NULL)
@@ -884,16 +919,25 @@ init()
        if ((PL = pgetnum("pl")) < 0)
                PL = DEFLENGTH;
        sprintf(&length[2], "%d", PL);
        if ((PL = pgetnum("pl")) < 0)
                PL = DEFLENGTH;
        sprintf(&length[2], "%d", PL);
+       if ((PX = pgetnum("px")) < 0)
+               PX = 0;
+       sprintf(&pxwidth[2], "%d", PX);
+       if ((PY = pgetnum("py")) < 0)
+               PY = 0;
+       sprintf(&pxlength[2], "%d", PY);
        RM = pgetstr("rm", &bp);
        AF = pgetstr("af", &bp);
        OF = pgetstr("of", &bp);
        IF = pgetstr("if", &bp);
        RM = pgetstr("rm", &bp);
        AF = pgetstr("af", &bp);
        OF = pgetstr("of", &bp);
        IF = pgetstr("if", &bp);
+       RF = pgetstr("rf", &bp);
        TF = pgetstr("tf", &bp);
        TF = pgetstr("tf", &bp);
+       NF = pgetstr("nf", &bp);
        DF = pgetstr("df", &bp);
        GF = pgetstr("gf", &bp);
        VF = pgetstr("vf", &bp);
        CF = pgetstr("cf", &bp);
        TR = pgetstr("tr", &bp);
        DF = pgetstr("df", &bp);
        GF = pgetstr("gf", &bp);
        VF = pgetstr("vf", &bp);
        CF = pgetstr("cf", &bp);
        TR = pgetstr("tr", &bp);
+       RS = pgetflag("rs");
        SF = pgetflag("sf");
        SH = pgetflag("sh");
        SB = pgetflag("sb");
        SF = pgetflag("sf");
        SH = pgetflag("sh");
        SB = pgetflag("sb");
@@ -907,6 +951,83 @@ init()
                XC = 0;
        if ((XS = pgetnum("xs")) < 0)
                XS = 0;
                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 ? O_RDWR : O_WRONLY);
+                       if (pfd >= 0)
+                               break;
+                       if (errno == ENOENT) {
+                               log("cannot open %s", LP);
+                               exit(1);
+                       }
+                       if (i == 1)
+                               status("waiting for %s to become ready (offline ?)", printer);
+                       sleep(i);
+               }
+               if (isatty(pfd))
+                       setty();
+               status("%s is ready and printing", printer);
+       } else if (RM != NULL) {
+               for (i = 1; ; i = i < 512 ? i << 1 : i) {
+                       pfd = getport(RM);
+                       if (pfd >= 0) {
+                               (void) sprintf(line, "\2%s\n", RP);
+                               n = strlen(line);
+                               if (write(pfd, line, n) != n)
+                                       break;
+                               if (noresponse())
+                                       (void) close(pfd);
+                               else
+                                       break;
+                       }
+                       if (i == 1)
+                               status("waiting for %s to come up", RM);
+                       sleep(i);
+               }
+               status("sending to %s", RM);
+               remote = 1;
+       } else {
+               log("no line printer device or remote machine name");
+               exit(1);
+       }
+       /*
+        * Start up an output filter, if needed.
+        */
+       if (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 */
+                       for (i = 3; i < NOFILE; i++)
+                               (void) close(i);
+                       if ((cp = rindex(OF, '/')) == NULL)
+                               cp = OF;
+                       else
+                               cp++;
+                       execl(OF, cp, width, length, 0);
+                       log("can't execl output filter %s", OF);
+                       exit(1);
+               }
+               (void) close(p[0]);             /* close input side */
+               ofd = p[1];                     /* use pipe for output */
+       } else {
+               ofd = pfd;
+               ofilter = 0;
+       }
 }
 
 struct bauds {
 }
 
 struct bauds {
@@ -934,6 +1055,7 @@ struct bauds {
 /*
  * setup tty lines.
  */
 /*
  * setup tty lines.
  */
+static
 setty()
 {
        struct sgttyb ttybuf;
 setty()
 {
        struct sgttyb ttybuf;
@@ -957,10 +1079,8 @@ setty()
                }
                ttybuf.sg_ispeed = ttybuf.sg_ospeed = bp->speed;
        }
                }
                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);
        if (ioctl(pfd, TIOCSETP, (char *)&ttybuf) < 0) {
                log("cannot set tty parameters");
                exit(1);
@@ -978,3 +1098,22 @@ setty()
                }
        }
 }
                }
        }
 }
+
+/*VARARGS1*/
+static
+status(msg, a1, a2, a3)
+       char *msg;
+{
+       register int fd;
+       char buf[BUFSIZ];
+
+       umask(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));
+       (void) close(fd);
+}