rationalized handling of child processes, cleaned up mail1 some more
authorEdward Wang <edward@ucbvax.Berkeley.EDU>
Fri, 8 Jul 1988 16:43:33 +0000 (08:43 -0800)
committerEdward Wang <edward@ucbvax.Berkeley.EDU>
Fri, 8 Jul 1988 16:43:33 +0000 (08:43 -0800)
SCCS-vsn: usr.bin/mail/names.c 5.12
SCCS-vsn: usr.bin/mail/cmd2.c 5.9
SCCS-vsn: usr.bin/mail/send.c 5.14
SCCS-vsn: usr.bin/mail/main.c 5.18
SCCS-vsn: usr.bin/mail/fio.c 5.14
SCCS-vsn: usr.bin/mail/popen.c 5.12

usr/src/usr.bin/mail/cmd2.c
usr/src/usr.bin/mail/fio.c
usr/src/usr.bin/mail/main.c
usr/src/usr.bin/mail/names.c
usr/src/usr.bin/mail/popen.c
usr/src/usr.bin/mail/send.c

index 2ac4306..67ba647 100644 (file)
@@ -16,7 +16,7 @@
  */
 
 #ifndef lint
  */
 
 #ifndef lint
-static char sccsid[] = "@(#)cmd2.c     5.8 (Berkeley) %G%";
+static char sccsid[] = "@(#)cmd2.c     5.9 (Berkeley) %G%";
 #endif /* not lint */
 
 #include "rcv.h"
 #endif /* not lint */
 
 #include "rcv.h"
@@ -352,25 +352,24 @@ undelete(msgvec)
 
 core()
 {
 
 core()
 {
-       register int pid;
-       union wait status;
+       int pid;
+       extern union wait wait_status;
 
 
-       if ((pid = vfork()) == -1) {
+       switch (pid = vfork()) {
+       case -1:
                perror("fork");
                return(1);
                perror("fork");
                return(1);
-       }
-       if (pid == 0) {
+       case 0:
                abort();
                _exit(1);
        }
        printf("Okie dokie");
        fflush(stdout);
                abort();
                _exit(1);
        }
        printf("Okie dokie");
        fflush(stdout);
-       while (wait(&status) != pid)
-               ;
-       if (status.w_coredump)
-               printf(" -- Core dumped\n");
+       wait_child(pid);
+       if (wait_status.w_coredump)
+               printf(" -- Core dumped.\n");
        else
        else
-               printf("\n");
+               printf(" -- Can't dump core.\n");
        return 0;
 }
 
        return 0;
 }
 
index 05b31e9..210c86e 100644 (file)
@@ -16,7 +16,7 @@
  */
 
 #ifndef lint
  */
 
 #ifndef lint
-static char sccsid[] = "@(#)fio.c      5.13 (Berkeley) %G%";
+static char sccsid[] = "@(#)fio.c      5.14 (Berkeley) %G%";
 #endif /* not lint */
 
 #include "rcv.h"
 #endif /* not lint */
 
 #include "rcv.h"
@@ -411,7 +411,7 @@ expand(name)
        register char *cp, *shell;
        int pivec[2];
        struct stat sbuf;
        register char *cp, *shell;
        int pivec[2];
        struct stat sbuf;
-       union wait s;
+       extern union wait wait_status;
 
        switch (*name) {
        case '%':
 
        switch (*name) {
        case '%':
@@ -454,9 +454,7 @@ expand(name)
        close(pivec[1]);
        l = read(pivec[0], xname, BUFSIZ);
        close(pivec[0]);
        close(pivec[1]);
        l = read(pivec[0], xname, BUFSIZ);
        close(pivec[0]);
-       while (wait(&s) != pid);
-               ;
-       if (s.w_status != 0 && s.w_termsig != SIGPIPE) {
+       if (wait_child(pid) < 0 && wait_status.w_termsig != SIGPIPE) {
                fprintf(stderr, "\"Echo\" failed\n");
                return NOSTR;
        }
                fprintf(stderr, "\"Echo\" failed\n");
                return NOSTR;
        }
index 6d9171c..238b70b 100644 (file)
@@ -22,7 +22,7 @@ char copyright[] =
 #endif /* not lint */
 
 #ifndef lint
 #endif /* not lint */
 
 #ifndef lint
-static char sccsid[] = "@(#)main.c     5.17 (Berkeley) %G%";
+static char sccsid[] = "@(#)main.c     5.18 (Berkeley) %G%";
 #endif /* not lint */
 
 #include "rcv.h"
 #endif /* not lint */
 
 #include "rcv.h"
@@ -45,14 +45,16 @@ main(argc, argv)
        char *ef;
        char nosrc = 0;
        int hdrstop(), (*prevint)();
        char *ef;
        char nosrc = 0;
        int hdrstop(), (*prevint)();
+       int sigchild();
        extern int getopt(), optind, opterr;
        extern char *optarg;
 
        /*
         * Set up a reasonable environment.
        extern int getopt(), optind, opterr;
        extern char *optarg;
 
        /*
         * Set up a reasonable environment.
-        * Figure out whether we are being run interactively, set up
-        * all the temporary files, buffer standard output, and so forth.
+        * Figure out whether we are being run interactively,
+        * start the SIGCHLD catcher, and so forth.
         */
         */
+       (void) signal(SIGCHLD, sigchild);
        if (isatty(0))
                assign("interactive", "");
        image = -1;
        if (isatty(0))
                assign("interactive", "");
        image = -1;
index e165778..fd1a386 100644 (file)
@@ -16,7 +16,7 @@
  */
 
 #ifndef lint
  */
 
 #ifndef lint
-static char sccsid[] = "@(#)names.c    5.11 (Berkeley) %G%";
+static char sccsid[] = "@(#)names.c    5.12 (Berkeley) %G%";
 #endif /* not lint */
 
 /*
 #endif /* not lint */
 
 /*
@@ -26,7 +26,6 @@ static char sccsid[] = "@(#)names.c   5.11 (Berkeley) %G%";
  */
 
 #include "rcv.h"
  */
 
 #include "rcv.h"
-#include <sys/wait.h>
 
 /*
  * Allocate a single element of a name list,
 
 /*
  * Allocate a single element of a name list,
@@ -199,15 +198,11 @@ outof(names, fo, hp)
 {
        register int c;
        register struct name *np, *top;
 {
        register int c;
        register struct name *np, *top;
-#ifdef CRAZYWOW
-       register struct name *t, *x;
-#endif
        time_t now, time();
        time_t now, time();
-       char *date, *fname, *shell, *ctime();
+       char *date, *fname, *ctime();
        FILE *fout, *fin;
        int ispipe;
        extern char tempEdit[];
        FILE *fout, *fin;
        int ispipe;
        extern char tempEdit[];
-       union wait s;
 
        top = names;
        np = names;
 
        top = names;
        np = names;
@@ -243,7 +238,6 @@ outof(names, fo, hp)
                                goto cant;
                        }
                        else {
                                goto cant;
                        }
                        else {
-                               rewind(fo);
                                fprintf(fout, "From %s %s", myname, date);
                                puthead(hp, fout, GTO|GSUBJECT|GCC|GNL);
                                while ((c = getc(fo)) != EOF)
                                fprintf(fout, "From %s %s", myname, date);
                                puthead(hp, fout, GTO|GSUBJECT|GCC|GNL);
                                while ((c = getc(fo)) != EOF)
@@ -264,16 +258,20 @@ outof(names, fo, hp)
                 */
 
                if (ispipe) {
                 */
 
                if (ispipe) {
-                       (void) wait(&s);
+                       int pid;
+                       char *shell;
+
+                       /* XXX, can't really reuse the same image file */
                        if ((shell = value("SHELL")) == NOSTR)
                                shell = SHELL;
                        if ((shell = value("SHELL")) == NOSTR)
                                shell = SHELL;
-                       if (start_command(shell,
-                                       sigmask(SIGHUP)|sigmask(SIGINT)|
-                                                       sigmask(SIGQUIT),
-                                       image, -1, "-c", fname, NOSTR) < 0) {
+                       pid = start_command(shell, sigmask(SIGHUP)|
+                                       sigmask(SIGINT)|sigmask(SIGQUIT),
+                               image, -1, "-c", fname, NOSTR);
+                       if (pid < 0) {
                                senderr++;
                                goto cant;
                        }
                                senderr++;
                                goto cant;
                        }
+                       free_child(pid);
                } else {
                        if ((fout = fopen(fname, "a")) == NULL) {
                                perror(fname);
                } else {
                        if ((fout = fopen(fname, "a")) == NULL) {
                                perror(fname);
@@ -295,31 +293,12 @@ outof(names, fo, hp)
                        (void) fclose(fout);
                        (void) fclose(fin);
                }
                        (void) fclose(fout);
                        (void) fclose(fin);
                }
-
 cant:
 cant:
-
                /*
                 * In days of old we removed the entry from the
                 * the list; now for sake of header expansion
                 * we leave it in and mark it as deleted.
                 */
                /*
                 * In days of old we removed the entry from the
                 * the list; now for sake of header expansion
                 * we leave it in and mark it as deleted.
                 */
-
-#ifdef CRAZYWOW
-               if (np == top) {
-                       top = np->n_flink;
-                       if (top != NIL)
-                               top->n_blink = NIL;
-                       np = top;
-                       continue;
-               }
-               x = np->n_blink;
-               t = np->n_flink;
-               x->n_flink = t;
-               if (t != NIL)
-                       t->n_blink = x;
-               np = t;
-#endif
-
                np->n_type |= GDEL;
                np = np->n_flink;
        }
                np->n_type |= GDEL;
                np = np->n_flink;
        }
@@ -492,14 +471,9 @@ unpack(np)
                *ap++ = "-m";
        if (verbose)
                *ap++ = "-v";
                *ap++ = "-m";
        if (verbose)
                *ap++ = "-v";
-       while (n != NIL) {
-               if (n->n_type & GDEL) {
-                       n = n->n_flink;
-                       continue;
-               }
-               *ap++ = n->n_name;
-               n = n->n_flink;
-       }
+       for (; n != NIL; n = n->n_flink)
+               if ((n->n_type & GDEL) == 0)
+                       *ap++ = n->n_name;
        *ap = NOSTR;
        return(top);
 }
        *ap = NOSTR;
        return(top);
 }
@@ -635,7 +609,7 @@ put(list, node)
 }
 
 /*
 }
 
 /*
- * Determine the number of elements in
+ * Determine the number of undeleted elements in
  * a name list and return it.
  */
 count(np)
  * a name list and return it.
  */
 count(np)
@@ -643,8 +617,9 @@ count(np)
 {
        register int c;
 
 {
        register int c;
 
-       for (c = 0; np != NIL; c++, np = np->n_flink)
-               ;
+       for (c = 0; np != NIL; np = np->n_flink)
+               if ((np->n_type & GDEL) == 0)
+                       c++;
        return c;
 }
 
        return c;
 }
 
index a61f556..e96c801 100644 (file)
@@ -16,7 +16,7 @@
  */
 
 #ifndef lint
  */
 
 #ifndef lint
-static char sccsid[] = "@(#)popen.c    5.11 (Berkeley) %G%";
+static char sccsid[] = "@(#)popen.c    5.12 (Berkeley) %G%";
 #endif /* not lint */
 
 #include "rcv.h"
 #endif /* not lint */
 
 #include "rcv.h"
@@ -66,7 +66,7 @@ Pclose(ptr)
        i = fileno(ptr);
        fclose(ptr);
        omask = sigblock(sigmask(SIGINT)|sigmask(SIGHUP));
        i = fileno(ptr);
        fclose(ptr);
        omask = sigblock(sigmask(SIGINT)|sigmask(SIGHUP));
-       i = wait_command(pid[i]);
+       i = wait_child(pid[i]);
        sigsetmask(omask);
        return i;
 }
        sigsetmask(omask);
        return i;
 }
@@ -81,7 +81,7 @@ Pclose(ptr)
 /*VARARGS4*/
 run_command(cmd, mask, infd, outfd, a0, a1, a2)
        char *cmd;
 /*VARARGS4*/
 run_command(cmd, mask, infd, outfd, a0, a1, a2)
        char *cmd;
-       int infd, outfd;
+       int mask, infd, outfd;
        char *a0, *a1, *a2;
 {
        int pid;
        char *a0, *a1, *a2;
 {
        int pid;
@@ -94,7 +94,7 @@ run_command(cmd, mask, infd, outfd, a0, a1, a2)
 /*VARARGS4*/
 start_command(cmd, mask, infd, outfd, a0, a1, a2)
        char *cmd;
 /*VARARGS4*/
 start_command(cmd, mask, infd, outfd, a0, a1, a2)
        char *cmd;
-       int infd, outfd;
+       int mask, infd, outfd;
        char *a0, *a1, *a2;
 {
        int pid;
        char *a0, *a1, *a2;
 {
        int pid;
@@ -111,18 +111,7 @@ start_command(cmd, mask, infd, outfd, a0, a1, a2)
                    (argv[i++] = a1) != NOSTR &&
                    (argv[i++] = a2) != NOSTR)
                        argv[i] = NOSTR;
                    (argv[i++] = a1) != NOSTR &&
                    (argv[i++] = a2) != NOSTR)
                        argv[i] = NOSTR;
-               if (infd >= 0)
-                       dup2(infd, 0);
-               if (outfd >= 0)
-                       dup2(outfd, 1);
-               for (i = getdtablesize(); --i > 2;)
-                       close(i);
-               for (i = 1; i <= NSIG; i++)
-                       if (mask & sigmask(i))
-                               (void) signal(i, SIG_IGN);
-               if ((mask & sigmask(SIGINT)) == 0)
-                       (void) signal(SIGINT, SIG_DFL);
-               (void) sigsetmask(0);
+               prepare_child(mask, infd, outfd);
                execvp(argv[0], argv);
                perror(argv[0]);
                _exit(1);
                execvp(argv[0], argv);
                perror(argv[0]);
                _exit(1);
@@ -130,19 +119,123 @@ start_command(cmd, mask, infd, outfd, a0, a1, a2)
        return pid;
 }
 
        return pid;
 }
 
+prepare_child(mask, infd, outfd)
+       int mask, infd, outfd;
+{
+       int i;
+
+       if (infd >= 0)
+               dup2(infd, 0);
+       if (outfd >= 0)
+               dup2(outfd, 1);
+       for (i = getdtablesize(); --i > 2;)
+               close(i);
+       for (i = 1; i <= NSIG; i++)
+               if (mask & sigmask(i))
+                       (void) signal(i, SIG_IGN);
+       if ((mask & sigmask(SIGINT)) == 0)
+               (void) signal(SIGINT, SIG_DFL);
+       (void) sigsetmask(0);
+}
+
 wait_command(pid)
        int pid;
 {
 wait_command(pid)
        int pid;
 {
-       union wait status;
        int r;
 
        int r;
 
-       while ((r = wait(&status)) >= 0 && r != pid)
-               ;
-       if (r < 0)
-               return -1;
-       if (status.w_status != 0) {
+       if (wait_child(pid) < 0) {
                printf("Fatal error in process.\n");
                return -1;
        }
        return 0;
 }
                printf("Fatal error in process.\n");
                return -1;
        }
        return 0;
 }
+
+struct child {
+       int pid;
+       char done;
+       char free;
+       union wait status;
+       struct child *link;
+};
+static struct child *child;
+
+struct child *
+findchild(pid)
+       int pid;
+{
+       register struct child **cpp;
+
+       for (cpp = &child; *cpp != NULL && (*cpp)->pid != pid;
+            cpp = &(*cpp)->link)
+                       ;
+       if (*cpp == NULL) {
+               *cpp = (struct child *) malloc(sizeof (struct child));
+               (*cpp)->pid = pid;
+               (*cpp)->done = (*cpp)->free = 0;
+               (*cpp)->link = NULL;
+       }
+       return *cpp;
+}
+
+delchild(cp)
+       register struct child *cp;
+{
+       register struct child **cpp;
+
+       for (cpp = &child; *cpp != cp; cpp = &(*cpp)->link)
+               ;
+       *cpp = cp->link;
+       free((char *) cp);
+}
+
+sigchild()
+{
+       int pid;
+       union wait status;
+       register struct child *cp;
+
+       while ((pid = wait3(&status, WNOHANG, (struct timeval *)0)) > 0) {
+               cp = findchild(pid);
+               if (cp->free)
+                       delchild(cp);
+               else {
+                       cp->done = 1;
+                       cp->status = status;
+               }
+       }
+}
+
+union wait wait_status;
+
+/*
+ * Wait for a specific child to die.
+ */
+wait_child(pid)
+       int pid;
+{
+       int mask = sigblock(sigmask(SIGCHLD));
+       register struct child *cp = findchild(pid);
+
+       while (!cp->done)
+               sigpause(mask);
+       wait_status = cp->status;
+       delchild(cp);
+       sigsetmask(mask);
+       return wait_status.w_status ? -1 : 0;
+}
+
+/*
+ * Mark a child as don't care.
+ */
+free_child(pid)
+       int pid;
+{
+       int mask = sigblock(sigmask(SIGCHLD));
+       register struct child *cp = findchild(pid);
+
+       if (cp->done)
+               delchild(cp);
+       else
+               cp->free = 1;
+       sigsetmask(mask);
+}
index 4eb7501..04cd3a4 100644 (file)
  */
 
 #ifndef lint
  */
 
 #ifndef lint
-static char sccsid[] = "@(#)send.c     5.13 (Berkeley) %G%";
+static char sccsid[] = "@(#)send.c     5.14 (Berkeley) %G%";
 #endif /* not lint */
 
 #include "rcv.h"
 #endif /* not lint */
 
 #include "rcv.h"
-#include <sys/wait.h>
-#include <sys/stat.h>
 
 /*
  * Mail -- a mail program
 
 /*
  * Mail -- a mail program
@@ -207,7 +205,6 @@ statusput(mp, obuf, prefix)
  * Interface between the argument list and the mail1 routine
  * which does all the dirty work.
  */
  * Interface between the argument list and the mail1 routine
  * which does all the dirty work.
  */
-
 mail(to, cc, bcc, smopts, subject)
        struct name *to, *cc, *bcc, *smopts;
        char *subject;
 mail(to, cc, bcc, smopts, subject)
        struct name *to, *cc, *bcc, *smopts;
        char *subject;
@@ -219,7 +216,7 @@ mail(to, cc, bcc, smopts, subject)
        head.h_cc = cc;
        head.h_bcc = bcc;
        head.h_smopts = smopts;
        head.h_cc = cc;
        head.h_bcc = bcc;
        head.h_smopts = smopts;
-       (void) mail1(&head, 0);
+       mail1(&head, 0);
        return(0);
 }
 
        return(0);
 }
 
@@ -228,7 +225,6 @@ mail(to, cc, bcc, smopts, subject)
  * Send mail to a bunch of user names.  The interface is through
  * the mail routine below.
  */
  * Send mail to a bunch of user names.  The interface is through
  * the mail routine below.
  */
-
 sendmail(str)
        char *str;
 {
 sendmail(str)
        char *str;
 {
@@ -239,7 +235,7 @@ sendmail(str)
        head.h_cc = NIL;
        head.h_bcc = NIL;
        head.h_smopts = NIL;
        head.h_cc = NIL;
        head.h_bcc = NIL;
        head.h_smopts = NIL;
-       (void) mail1(&head, 0);
+       mail1(&head, 0);
        return(0);
 }
 
        return(0);
 }
 
@@ -247,27 +243,21 @@ sendmail(str)
  * Mail a message on standard input to the people indicated
  * in the passed header.  (Internal interface).
  */
  * Mail a message on standard input to the people indicated
  * in the passed header.  (Internal interface).
  */
-
 mail1(hp, printheaders)
        struct header *hp;
 {
 mail1(hp, printheaders)
        struct header *hp;
 {
-       register char *cp;
-       int pid, i, p, gotcha;
-       union wait s;
-       char **namelist, *deliver;
-       struct name *to, *np;
-       struct stat sbuf;
-       FILE *mtf, *postage;
-       char **t;
+       char *cp;
+       int pid;
+       char **namelist;
+       struct name *to;
+       FILE *mtf;
 
        /*
         * Collect user's mail from standard input.
         * Get the result as mtf.
         */
 
        /*
         * Collect user's mail from standard input.
         * Get the result as mtf.
         */
-
-       pid = -1;
        if ((mtf = collect(hp, printheaders)) == NULL)
        if ((mtf = collect(hp, printheaders)) == NULL)
-               return(-1);
+               return;
        if (value("interactive") != NOSTR)
                if (value("askcc") != NOSTR)
                        grabh(hp, GCC);
        if (value("interactive") != NOSTR)
                if (value("askcc") != NOSTR)
                        grabh(hp, GCC);
@@ -275,6 +265,11 @@ mail1(hp, printheaders)
                        printf("EOT\n");
                        (void) fflush(stdout);
                }
                        printf("EOT\n");
                        (void) fflush(stdout);
                }
+       if (fsize(mtf) == 0)
+               if (hp->h_subject == NOSTR)
+                       printf("No message, no subject; hope that's ok\n");
+               else
+                       printf("Null message body; hope that's ok\n");
        /*
         * Now, take the user names from the combined
         * to and cc lists and do all the alias
        /*
         * Now, take the user names from the combined
         * to and cc lists and do all the alias
@@ -284,64 +279,45 @@ mail1(hp, printheaders)
        to = usermap(cat(hp->h_bcc, cat(hp->h_to, hp->h_cc)));
        if (to == NIL) {
                printf("No recipients specified\n");
        to = usermap(cat(hp->h_bcc, cat(hp->h_to, hp->h_cc)));
        if (to == NIL) {
                printf("No recipients specified\n");
-               goto topdog;
+               senderr++;
        }
        /*
         * Look through the recipient list for names with /'s
         * in them which we write to as files directly.
         */
        to = outof(to, mtf, hp);
        }
        /*
         * Look through the recipient list for names with /'s
         * in them which we write to as files directly.
         */
        to = outof(to, mtf, hp);
-       rewind(mtf);
        if (senderr) {
        if (senderr) {
-topdog:
                if (fsize(mtf) != 0) {
                        (void) remove(deadletter);
                        (void) exwrite(deadletter, mtf, 1);
                        rewind(mtf);
                }
        }
                if (fsize(mtf) != 0) {
                        (void) remove(deadletter);
                        (void) exwrite(deadletter, mtf, 1);
                        rewind(mtf);
                }
        }
-       for (gotcha = 0, np = to; np != NIL; np = np->n_flink)
-               if ((np->n_type & GDEL) == 0) {
-                       gotcha++;
-                       break;
-               }
-       if (!gotcha)
-               goto out;
        to = elide(to);
        to = elide(to);
-       if (fsize(mtf) == 0)
-               if (hp->h_subject == NOSTR)
-                       printf("No message, no subject; hope that's ok\n");
-               else
-                       printf("Null message body; hope that's ok\n");
-       if (count(to) > 0 || hp->h_subject != NOSTR) {
-               /* don't do this unless we have to */
-               fixhead(hp, to);
-               if ((mtf = infix(hp, mtf)) == NULL) {
-                       fprintf(stderr, ". . . message lost, sorry.\n");
-                       return(-1);
-               }
+       if (count(to) == 0)
+               goto out;
+       fixhead(hp, to);
+       if ((mtf = infix(hp, mtf)) == NULL) {
+               fprintf(stderr, ". . . message lost, sorry.\n");
+               return;
        }
        namelist = unpack(cat(hp->h_smopts, to));
        if (debug) {
        }
        namelist = unpack(cat(hp->h_smopts, to));
        if (debug) {
+               char **t;
+
                printf("Sendmail arguments:");
                for (t = namelist; *t != NOSTR; t++)
                        printf(" \"%s\"", *t);
                printf("\n");
                printf("Sendmail arguments:");
                for (t = namelist; *t != NOSTR; t++)
                        printf(" \"%s\"", *t);
                printf("\n");
-               (void) fflush(stdout);
-               return 0;
+               goto out;
        }
        if ((cp = value("record")) != NOSTR)
                (void) savemail(expand(cp), mtf);
        /*
        }
        if ((cp = value("record")) != NOSTR)
                (void) savemail(expand(cp), mtf);
        /*
-        * Wait, to absorb a potential zombie, then
-        * fork, set up the temporary mail file as standard
-        * input for "mail" and exec with the user list we generated
-        * far above. Return the process id to caller in case he
-        * wants to await the completion of mail.
+        * Fork, set up the temporary mail file as standard
+        * input for "mail", and exec with the user list we generated
+        * far above.
         */
         */
-       while (wait3(&s, WNOHANG, (struct timeval *) 0) > 0)
-               ;
-       rewind(mtf);
        pid = fork();
        if (pid == -1) {
                perror("fork");
        pid = fork();
        if (pid == -1) {
                perror("fork");
@@ -350,40 +326,32 @@ topdog:
                goto out;
        }
        if (pid == 0) {
                goto out;
        }
        if (pid == 0) {
-#ifdef SIGTSTP
-               (void) signal(SIGTSTP, SIG_IGN);
-               (void) signal(SIGTTIN, SIG_IGN);
-               (void) signal(SIGTTOU, SIG_IGN);
-#endif
-               (void) signal(SIGHUP, SIG_IGN);
-               (void) signal(SIGINT, SIG_IGN);
-               (void) signal(SIGQUIT, SIG_IGN);
-               if (!stat(POSTAGE, &sbuf))
+               if (access(POSTAGE, 0) == 0) {
+                       FILE *postage;
+
                        if ((postage = fopen(POSTAGE, "a")) != NULL) {
                                fprintf(postage, "%s %d %ld\n", myname,
                                    count(to), fsize(mtf));
                                (void) fclose(postage);
                        }
                        if ((postage = fopen(POSTAGE, "a")) != NULL) {
                                fprintf(postage, "%s %d %ld\n", myname,
                                    count(to), fsize(mtf));
                                (void) fclose(postage);
                        }
-               (void) close(0);
-               (void) dup(fileno(mtf));
-               for (i = getdtablesize(); --i > 2;)
-                       (void) close(i);
-               if ((deliver = value("sendmail")) == NOSTR)
-                       deliver = SENDMAIL;
-               execv(deliver, namelist);
-               perror(deliver);
+               }
+               prepare_child(sigmask(SIGHUP)|sigmask(SIGINT)|sigmask(SIGQUIT)|
+                       sigmask(SIGTSTP)|sigmask(SIGTTIN)|sigmask(SIGTTOU),
+                       fileno(mtf), -1);
+               if ((cp = value("sendmail")) != NOSTR)
+                       cp = expand(cp);
+               else
+                       cp = SENDMAIL;
+               execv(cp, namelist);
+               perror(cp);
                exit(1);
        }
                exit(1);
        }
+       if (value("verbose") != NOSTR)
+               (void) wait_child(pid);
+       else
+               free_child(pid);
 out:
 out:
-       if (value("verbose") != NOSTR) {
-               while ((p = wait(&s)) != pid && p != -1)
-                       ;
-               if (s.w_status != 0)
-                       senderr++;
-               pid = 0;
-       }
        (void) fclose(mtf);
        (void) fclose(mtf);
-       return pid;
 }
 
 /*
 }
 
 /*
@@ -415,7 +383,6 @@ fixhead(hp, tolist)
  * Prepend a header in front of the collected stuff
  * and return the new file.
  */
  * Prepend a header in front of the collected stuff
  * and return the new file.
  */
-
 FILE *
 infix(hp, fi)
        struct header *hp;
 FILE *
 infix(hp, fi)
        struct header *hp;
@@ -425,7 +392,6 @@ infix(hp, fi)
        register FILE *nfo, *nfi;
        register int c;
 
        register FILE *nfo, *nfi;
        register int c;
 
-       rewind(fi);
        if ((nfo = fopen(tempMail, "w")) == NULL) {
                perror(tempMail);
                return(fi);
        if ((nfo = fopen(tempMail, "w")) == NULL) {
                perror(tempMail);
                return(fi);
@@ -444,6 +410,7 @@ infix(hp, fi)
        }
        if (ferror(fi)) {
                perror("read");
        }
        if (ferror(fi)) {
                perror("read");
+               rewind(fi);
                return(fi);
        }
        (void) fflush(nfo);
                return(fi);
        }
        (void) fflush(nfo);
@@ -451,6 +418,7 @@ infix(hp, fi)
                perror(tempMail);
                (void) fclose(nfo);
                (void) fclose(nfi);
                perror(tempMail);
                (void) fclose(nfo);
                (void) fclose(nfi);
+               rewind(fi);
                return(fi);
        }
        (void) fclose(nfo);
                return(fi);
        }
        (void) fclose(nfo);
@@ -471,20 +439,20 @@ puthead(hp, fo, w)
 
        gotcha = 0;
        if (hp->h_to != NIL && w & GTO)
 
        gotcha = 0;
        if (hp->h_to != NIL && w & GTO)
-               fmt("To: ", hp->h_to, fo, w&GCOMMA), gotcha++;
+               fmt("To:", hp->h_to, fo, w&GCOMMA), gotcha++;
        if (hp->h_subject != NOSTR && w & GSUBJECT)
                fprintf(fo, "Subject: %s\n", hp->h_subject), gotcha++;
        if (hp->h_cc != NIL && w & GCC)
        if (hp->h_subject != NOSTR && w & GSUBJECT)
                fprintf(fo, "Subject: %s\n", hp->h_subject), gotcha++;
        if (hp->h_cc != NIL && w & GCC)
-               fmt("Cc: ", hp->h_cc, fo, w&GCOMMA), gotcha++;
+               fmt("Cc:", hp->h_cc, fo, w&GCOMMA), gotcha++;
        if (hp->h_bcc != NIL && w & GBCC)
        if (hp->h_bcc != NIL && w & GBCC)
-               fmt("Bcc: ", hp->h_bcc, fo, w&GCOMMA), gotcha++;
+               fmt("Bcc:", hp->h_bcc, fo, w&GCOMMA), gotcha++;
        if (gotcha && w & GNL)
                (void) putc('\n', fo);
        return(0);
 }
 
 /*
        if (gotcha && w & GNL)
                (void) putc('\n', fo);
        return(0);
 }
 
 /*
- * Format the given text to not exceed 72 characters.
+ * Format the given header line to not exceed 72 characters.
  */
 fmt(str, np, fo, comma)
        char *str;
  */
 fmt(str, np, fo, comma)
        char *str;
@@ -498,26 +466,20 @@ fmt(str, np, fo, comma)
        col = strlen(str);
        if (col)
                fputs(str, fo);
        col = strlen(str);
        if (col)
                fputs(str, fo);
-       len = strlen(np->n_name);
-       for (;;) {
-               fputs(np->n_name, fo);
-               col += len;
-               if (comma) {
-                       putc(',', fo);
-                       col++;
-               }
-               if ((np = np->n_flink) == NIL)
-                       break;
+       for (; np != NIL; np = np->n_flink) {
                if (np->n_flink == NIL)
                        comma = 0;
                len = strlen(np->n_name);
                if (np->n_flink == NIL)
                        comma = 0;
                len = strlen(np->n_name);
-               if (col + len + comma > 72) {
+               col++;          /* for the space */
+               if (col + len + comma > 72 && col > 4) {
                        fputs("\n    ", fo);
                        col = 4;
                        fputs("\n    ", fo);
                        col = 4;
-               } else {
+               } else
                        putc(' ', fo);
                        putc(' ', fo);
-                       col++;
-               }
+               fputs(np->n_name, fo);
+               if (comma)
+                       putc(',', fo);
+               col += len + comma;
        }
        putc('\n', fo);
 }
        }
        putc('\n', fo);
 }
@@ -543,7 +505,6 @@ savemail(name, fi)
        }
        (void) time(&now);
        fprintf(fo, "From %s %s", myname, ctime(&now));
        }
        (void) time(&now);
        fprintf(fo, "From %s %s", myname, ctime(&now));
-       rewind(fi);
        while ((i = fread(buf, 1, sizeof buf, fi)) > 0)
                (void) fwrite(buf, 1, i, fo);
        (void) putc('\n', fo);
        while ((i = fread(buf, 1, sizeof buf, fi)) > 0)
                (void) fwrite(buf, 1, i, fo);
        (void) putc('\n', fo);
@@ -551,5 +512,6 @@ savemail(name, fi)
        if (ferror(fo))
                perror(name);
        (void) fclose(fo);
        if (ferror(fo))
                perror(name);
        (void) fclose(fo);
+       rewind(fi);
        return (0);
 }
        return (0);
 }