use strncpy for jobname, class, etc. to prevent overflows.
[unix-history] / usr / src / usr.sbin / lpr / lpd / printjob.c
index 8af58b6..314e36d 100644 (file)
@@ -1,4 +1,7 @@
-/*     printjob.c      4.3     83/05/18        */
+#ifndef lint
+static char sccsid[] = "@(#)printjob.c 4.15 (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 */
+#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()
 {
 
 printjob()
 {
@@ -42,12 +47,18 @@ printjob()
        extern int onintr();
 
        init();                                 /* set up capabilities */
        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);
        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
 
        /*
         * uses short form file names
@@ -58,12 +69,18 @@ printjob()
        }
        if (stat(LO, &stb) == 0 && (stb.st_mode & 0100))
                exit(0);                /* printing disabled */
        }
        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);
                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
         */
        /*
         * write process id for others to know
         */
@@ -82,6 +99,10 @@ printjob()
        }
        if (nitems == 0)                /* no work to do */
                exit(0);
        }
        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:
        /*
        openpr();                       /* open printer or remote */
 again:
        /*
@@ -104,14 +125,23 @@ again:
                else
                        i = sendit(q->q_name);
                /*
                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 */
                        log("restarting");
                        if (ofilter > 0) {
                                kill(ofilter, SIGCONT); /* to be sure */
@@ -138,10 +168,12 @@ again:
        }
        if (nitems == 0) {              /* no more work to do */
        done:
        }
        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;
                exit(0);
        }
        goto again;
@@ -162,6 +194,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;
 {
@@ -194,12 +227,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
@@ -221,13 +254,13 @@ 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')
                        if (class[0] == '\0')
-                               strcpy(class, line+1);
+                               strncpy(class, line+1, sizeof(class)-1);
                        continue;
 
                case 'P':
                        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;
                        if (RS) {                       /* restricted */
                                if (getpwnam(logname) == (struct passwd *)0) {
                                        bombed = 2;
@@ -239,20 +272,20 @@ printit(file)
 
                case 'J':
                        if (line[1] != '\0')
 
                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')
                        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 */
                        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 'L':       /* identification line */
@@ -269,7 +302,11 @@ printit(file)
                        continue;
 
                case 'W':       /* page width */
                        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 */
                        continue;
 
                default:        /* some file to print */
@@ -281,7 +318,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':
@@ -307,17 +343,18 @@ pass2:
         */
        (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;
@@ -328,7 +365,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);
        }
@@ -381,14 +418,16 @@ 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;
                break;
        case 'r':       /* print a fortran text file */
                prog = RF;
@@ -397,6 +436,7 @@ print(format, file)
                n = 3;
                break;
        case 't':       /* print troff output */
                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) {
        case 'd':       /* print tex output */
                (void) unlink(".railmag");
                if ((fo = creat(".railmag", FILMOD)) < 0) {
@@ -411,7 +451,7 @@ print(format, file)
                        }
                        (void) close(fo);
                }
                        }
                        (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[1] = pxwidth;
                av[2] = pxlength;
                n = 3;
@@ -446,7 +486,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;
@@ -500,6 +540,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;
 {
@@ -568,6 +609,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;
 {
@@ -576,16 +618,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;
@@ -593,8 +639,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) {
@@ -629,6 +677,7 @@ noresponse()
 /*
  * Banner printing stuff
  */
 /*
  * Banner printing stuff
  */
+static
 banner(name1, name2)
        char *name1, *name2;
 {
 banner(name1, name2)
        char *name1, *name2;
 {
@@ -669,7 +718,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;
@@ -685,6 +734,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;
@@ -718,6 +768,7 @@ scan_out(scfd, scsp, dlm)
        }
 }
 
        }
 }
 
+static
 dropit(c)
        char c;
 {
 dropit(c)
        char c;
 {
@@ -742,6 +793,7 @@ dropit(c)
  * sendmail ---
  *   tell people about job completion
  */
  * sendmail ---
  *   tell people about job completion
  */
+static
 sendmail(bombed)
        int bombed;
 {
 sendmail(bombed)
        int bombed;
 {
@@ -760,12 +812,12 @@ 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("Subject: printer job\n\n");
                printf("Your printer job ");
                if (*jobname)
@@ -793,6 +845,7 @@ sendmail(bombed)
 /*
  * dofork - fork with retries on failure
  */
 /*
  * dofork - fork with retries on failure
  */
+static
 dofork(action)
        int action;
 {
 dofork(action)
        int action;
 {
@@ -825,8 +878,9 @@ dofork(action)
 }
 
 /*
 }
 
 /*
- * Cleanup child processes when a SIGINT is caught.
+ * Cleanup child processes when a signal is caught.
  */
  */
+static
 onintr()
 {
        kill(0, SIGINT);
 onintr()
 {
        kill(0, SIGINT);
@@ -837,17 +891,15 @@ 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)
@@ -882,6 +934,7 @@ init()
        IF = pgetstr("if", &bp);
        RF = pgetstr("rf", &bp);
        TF = pgetstr("tf", &bp);
        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);
        DF = pgetstr("df", &bp);
        GF = pgetstr("gf", &bp);
        VF = pgetstr("vf", &bp);
@@ -901,18 +954,20 @@ 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.
  */
 }
 
 /*
  * Acquire line printer or remote connection.
  */
+static
 openpr()
 {
        register int i, n;
 
        if (*LP) {
                for (i = 1; ; i = i < 32 ? i << 1 : i) {
 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) {
                        if (pfd >= 0)
                                break;
                        if (errno == ENOENT) {
@@ -1003,6 +1058,7 @@ struct bauds {
 /*
  * setup tty lines.
  */
 /*
  * setup tty lines.
  */
+static
 setty()
 {
        struct sgttyb ttybuf;
 setty()
 {
        struct sgttyb ttybuf;
@@ -1026,10 +1082,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);
@@ -1057,8 +1111,10 @@ status(msg, a1, a2, a3)
        char buf[BUFSIZ];
 
        umask(0);
        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");
                fatal("cannot create status file");
+       ftruncate(fd, 0);
        sprintf(buf, msg, a1, a2, a3);
        strcat(buf, "\n");
        (void) write(fd, buf, strlen(buf));
        sprintf(buf, msg, a1, a2, a3);
        strcat(buf, "\n");
        (void) write(fd, buf, strlen(buf));