rationalized mail sending code: keep h_to, h_cc, h_bcc, h_smopts as lists
authorEdward Wang <edward@ucbvax.Berkeley.EDU>
Sun, 19 Jun 1988 19:21:07 +0000 (11:21 -0800)
committerEdward Wang <edward@ucbvax.Berkeley.EDU>
Sun, 19 Jun 1988 19:21:07 +0000 (11:21 -0800)
not strings; h_seq deleted; now understands <...> addresses; and many more.
should be much cleaner and somewhat faster.

SCCS-vsn: usr.bin/mail/names.c 5.9
SCCS-vsn: usr.bin/mail/collect.c 5.9
SCCS-vsn: usr.bin/mail/send.c 5.11
SCCS-vsn: usr.bin/mail/glob.h 5.10
SCCS-vsn: usr.bin/mail/tty.c 5.6
SCCS-vsn: usr.bin/mail/cmd3.c 5.11
SCCS-vsn: usr.bin/mail/main.c 5.15
SCCS-vsn: usr.bin/mail/def.h 5.11

usr/src/usr.bin/mail/cmd3.c
usr/src/usr.bin/mail/collect.c
usr/src/usr.bin/mail/def.h
usr/src/usr.bin/mail/glob.h
usr/src/usr.bin/mail/main.c
usr/src/usr.bin/mail/names.c
usr/src/usr.bin/mail/send.c
usr/src/usr.bin/mail/tty.c

index c6c3995..ef124fd 100644 (file)
@@ -11,7 +11,7 @@
  */
 
 #ifdef notdef
  */
 
 #ifdef notdef
-static char sccsid[] = "@(#)cmd3.c     5.10 (Berkeley) %G%";
+static char sccsid[] = "@(#)cmd3.c     5.11 (Berkeley) %G%";
 #endif /* notdef */
 
 #include "rcv.h"
 #endif /* notdef */
 
 #include "rcv.h"
@@ -211,13 +211,12 @@ respond(msgvec)
  * Reply to a list of messages.  Extract each name from the
  * message header and send them off to mail1()
  */
  * Reply to a list of messages.  Extract each name from the
  * message header and send them off to mail1()
  */
-
 _respond(msgvec)
        int *msgvec;
 {
        struct message *mp;
        char *cp, *rcv, *replyto;
 _respond(msgvec)
        int *msgvec;
 {
        struct message *mp;
        char *cp, *rcv, *replyto;
-       char buf[2 * LINESIZE], **ap;
+       char **ap;
        struct name *np;
        struct header head;
 
        struct name *np;
        struct header head;
 
@@ -227,23 +226,15 @@ _respond(msgvec)
        }
        mp = &message[msgvec[0] - 1];
        dot = mp;
        }
        mp = &message[msgvec[0] - 1];
        dot = mp;
-       rcv = NOSTR;
-       cp = skin(nameof(mp, 1));
-       if (cp != NOSTR)
-           rcv = cp;
-       cp = skin(hfield("from", mp));
-       if (cp != NOSTR)
-           rcv = cp;
-       replyto = skin(hfield("reply-to", mp));
-       strcpy(buf, "");
-       if (replyto != NOSTR)
-               strcpy(buf, replyto);
-       else {
-               cp = skin(hfield("to", mp));
-               if (cp != NOSTR)
-                       strcpy(buf, cp);
-       }
-       np = elide(extract(buf, GTO));
+       if ((rcv = skin(hfield("from", mp))) == NOSTR)
+               rcv = skin(nameof(mp, 1));
+       if ((replyto = skin(hfield("reply-to", mp))) != NOSTR)
+               np = extract(replyto, GTO);
+       else if ((cp = skin(hfield("to", mp))) != NOSTR)
+               np = extract(cp, GTO);
+       else
+               np = NIL;
+       np = elide(np);
        /*
         * Delete my name from the reply list,
         * and with it, all my alternate names.
        /*
         * Delete my name from the reply list,
         * and with it, all my alternate names.
@@ -252,41 +243,29 @@ _respond(msgvec)
        if (altnames)
                for (ap = altnames; *ap; ap++)
                        np = delname(np, *ap, icequal);
        if (altnames)
                for (ap = altnames; *ap; ap++)
                        np = delname(np, *ap, icequal);
-       head.h_seq = 1;
-       cp = detract(np, 0);
-       if (cp != NOSTR && replyto == NOSTR) {
-               strcpy(buf, cp);
-               strcat(buf, " ");
-               strcat(buf, rcv);
-       }
-       else {
-               if (cp == NOSTR && replyto != NOSTR)
+       if (np != NIL && replyto == NOSTR)
+               np = cat(np, extract(rcv, GTO));
+       else if (np == NIL) {
+               if (replyto != NOSTR)
                        printf("Empty reply-to field -- replying to author\n");
                        printf("Empty reply-to field -- replying to author\n");
-               if (cp == NOSTR)
-                       strcpy(buf, rcv);
-               else
-                       strcpy(buf, cp);
+               np = extract(rcv, GTO);
        }
        }
-       head.h_to = buf;
-       head.h_subject = hfield("subject", mp);
-       if (head.h_subject == NOSTR)
+       head.h_to = np;
+       if ((head.h_subject = hfield("subject", mp)) == NOSTR)
                head.h_subject = hfield("subj", mp);
        head.h_subject = reedit(head.h_subject);
                head.h_subject = hfield("subj", mp);
        head.h_subject = reedit(head.h_subject);
-       head.h_cc = NOSTR;
-       if (replyto == NOSTR) {
-               cp = skin(hfield("cc", mp));
-               if (cp != NOSTR) {
-                       np = elide(extract(cp, GCC));
-                       np = delname(np, myname, icequal);
-                       if (altnames != 0)
-                               for (ap = altnames; *ap; ap++)
-                                       np = delname(np, *ap, icequal);
-                       head.h_cc = detract(np, 0);
-               }
-       }
-       head.h_bcc = NOSTR;
-       head.h_smopts = NOSTR;
-       mail1(&head);
+       if (replyto == NOSTR && (cp = skin(hfield("cc", mp))) != NOSTR) {
+               np = elide(extract(cp, GCC));
+               np = delname(np, myname, icequal);
+               if (altnames != 0)
+                       for (ap = altnames; *ap; ap++)
+                               np = delname(np, *ap, icequal);
+               head.h_cc = np;
+       } else
+               head.h_cc = NIL;
+       head.h_bcc = NIL;
+       head.h_smopts = NIL;
+       mail1(&head, 1);
        return(0);
 }
 
        return(0);
 }
 
@@ -294,23 +273,22 @@ _respond(msgvec)
  * Modify the subject we are replying to to begin with Re: if
  * it does not already.
  */
  * Modify the subject we are replying to to begin with Re: if
  * it does not already.
  */
-
 char *
 reedit(subj)
 char *
 reedit(subj)
-       char *subj;
+       register char *subj;
 {
 {
-       char sbuf[10];
-       register char *newsubj;
+       char *newsubj;
 
        if (subj == NOSTR)
 
        if (subj == NOSTR)
-               return(NOSTR);
-       strncpy(sbuf, subj, 3);
-       sbuf[3] = 0;
-       if (icequal(sbuf, "re:"))
-               return(subj);
-       newsubj = salloc(strlen(subj) + 6);
-       sprintf(newsubj, "Re: %s", subj);
-       return(newsubj);
+               return NOSTR;
+       if ((subj[0] == 'r' || subj[0] == 'R') &&
+           (subj[1] == 'e' || subj[1] == 'E') &&
+           subj[2] == ':')
+               return subj;
+       newsubj = salloc(strlen(subj) + 5);
+       strcpy(newsubj, "Re: ");
+       strcpy(subj, newsubj + 4);
+       return newsubj;
 }
 
 /*
 }
 
 /*
@@ -595,7 +573,6 @@ file(argv)
 /*
  * Expand file names like echo
  */
 /*
  * Expand file names like echo
  */
-
 echo(argv)
        char **argv;
 {
 echo(argv)
        char **argv;
 {
@@ -611,8 +588,7 @@ echo(argv)
                }
        }
        putchar('\n');
                }
        }
        putchar('\n');
-
-       return(0);
+       return 0;
 }
 
 Respond(msgvec)
 }
 
 Respond(msgvec)
@@ -629,48 +605,33 @@ Respond(msgvec)
  * and not messing around with the To: and Cc: lists as in normal
  * reply.
  */
  * and not messing around with the To: and Cc: lists as in normal
  * reply.
  */
-
 _Respond(msgvec)
        int msgvec[];
 {
        struct header head;
        struct message *mp;
 _Respond(msgvec)
        int msgvec[];
 {
        struct header head;
        struct message *mp;
-       register int s, *ap;
-       register char *cp, *cp2, *subject;
+       register int *ap;
+       register char *cp;
 
 
-       for (s = 0, ap = msgvec; *ap != 0; ap++) {
-               mp = &message[*ap - 1];
-               dot = mp;
-               if ((cp = skin(hfield("from", mp))) != NOSTR)
-                   s+= strlen(cp) + 1;
-               else
-                   s += strlen(skin(nameof(mp, 2))) + 1;
-       }
-       if (s == 0)
-               return(0);
-       cp = salloc(s + 2);
-       head.h_to = cp;
+       head.h_to = NIL;
        for (ap = msgvec; *ap != 0; ap++) {
                mp = &message[*ap - 1];
        for (ap = msgvec; *ap != 0; ap++) {
                mp = &message[*ap - 1];
-               if ((cp2 = skin(hfield("from", mp))) == NOSTR)
-                   cp2 = skin(nameof(mp, 2));
-               cp = copy(cp2, cp);
-               *cp++ = ' ';
+               dot = mp;
+               if ((cp = skin(hfield("from", mp))) == NOSTR)
+                       cp = skin(nameof(mp, 2));
+               head.h_to = cat(head.h_to, extract(cp, GTO));
        }
        }
-       *--cp = 0;
+       if (head.h_to == NIL)
+               return 0;
        mp = &message[msgvec[0] - 1];
        mp = &message[msgvec[0] - 1];
-       subject = hfield("subject", mp);
-       head.h_seq = 0;
-       if (subject == NOSTR)
-               subject = hfield("subj", mp);
-       head.h_subject = reedit(subject);
-       if (subject != NOSTR)
-               head.h_seq++;
-       head.h_cc = NOSTR;
-       head.h_bcc = NOSTR;
-       head.h_smopts = NOSTR;
-       mail1(&head);
-       return(0);
+       if ((head.h_subject = hfield("subject", mp)) == NOSTR)
+               head.h_subject = hfield("subj", mp);
+       head.h_subject = reedit(head.h_subject);
+       head.h_cc = NIL;
+       head.h_bcc = NIL;
+       head.h_smopts = NIL;
+       mail1(&head, 1);
+       return 0;
 }
 
 /*
 }
 
 /*
index 160924d..8eb1c40 100644 (file)
@@ -11,7 +11,7 @@
  */
 
 #ifdef notdef
  */
 
 #ifdef notdef
-static char sccsid[] = "@(#)collect.c  5.8 (Berkeley) %G%";
+static char sccsid[] = "@(#)collect.c  5.9 (Berkeley) %G%";
 #endif /* notdef */
 
 /*
 #endif /* notdef */
 
 /*
@@ -45,7 +45,7 @@ static        int     hadintr;                /* Have seen one SIGINT so far */
 static jmp_buf coljmp;                 /* To get back to work */
 
 FILE *
 static jmp_buf coljmp;                 /* To get back to work */
 
 FILE *
-collect(hp)
+collect(hp, printheaders)
        struct header *hp;
 {
        FILE *fp, *fbuf;
        struct header *hp;
 {
        FILE *fp, *fbuf;
@@ -95,7 +95,7 @@ collect(hp)
        if (hp->h_subject == NOSTR && value("interactive") != NOSTR &&
            value("ask"))
                t &= ~GNL, getsub++;
        if (hp->h_subject == NOSTR && value("interactive") != NOSTR &&
            value("ask"))
                t &= ~GNL, getsub++;
-       if (hp->h_seq != 0) {
+       if (printheaders) {
                puthead(hp, stdout, t);
                fflush(stdout);
        }
                puthead(hp, stdout, t);
                fflush(stdout);
        }
@@ -209,8 +209,7 @@ cont:
                        /*
                         * Add to the To list.
                         */
                        /*
                         * Add to the To list.
                         */
-                       hp->h_to = addto(hp->h_to, &linebuf[2]);
-                       hp->h_seq++;
+                       hp->h_to = cat(hp->h_to, extract(&linebuf[2], GTO));
                        break;
                case 's':
                        /*
                        break;
                case 's':
                        /*
@@ -220,21 +219,18 @@ cont:
                        while (isspace(*cp))
                                cp++;
                        hp->h_subject = savestr(cp);
                        while (isspace(*cp))
                                cp++;
                        hp->h_subject = savestr(cp);
-                       hp->h_seq++;
                        break;
                case 'c':
                        /*
                         * Add to the CC list.
                         */
                        break;
                case 'c':
                        /*
                         * Add to the CC list.
                         */
-                       hp->h_cc = addto(hp->h_cc, &linebuf[2]);
-                       hp->h_seq++;
+                       hp->h_cc = cat(hp->h_cc, extract(&linebuf[2], GCC));
                        break;
                case 'b':
                        /*
                         * Add stuff to blind carbon copies list.
                         */
                        break;
                case 'b':
                        /*
                         * Add stuff to blind carbon copies list.
                         */
-                       hp->h_bcc = addto(hp->h_bcc, &linebuf[2]);
-                       hp->h_seq++;
+                       hp->h_bcc = cat(hp->h_bcc, extract(&linebuf[2], GBCC));
                        break;
                case 'd':
                        strcpy(linebuf + 2, deadletter);
                        break;
                case 'd':
                        strcpy(linebuf + 2, deadletter);
@@ -631,7 +627,6 @@ forward(ms, fp, f)
  * line.  Return a count of the characters sent, or -1
  * on error.
  */
  * line.  Return a count of the characters sent, or -1
  * on error.
  */
-
 long
 transmit(mailp, fp)
        struct message *mailp;
 long
 transmit(mailp, fp)
        struct message *mailp;
@@ -687,7 +682,6 @@ collcont(s)
  * signal routine.  We only come here if signals
  * were previously set anyway.
  */
  * signal routine.  We only come here if signals
  * were previously set anyway.
  */
-
 collrub(s)
 {
        register FILE *dbuf;
 collrub(s)
 {
        register FILE *dbuf;
@@ -706,7 +700,6 @@ collrub(s)
        while ((c = getc(collf)) != EOF)
                putc(c, dbuf);
        fclose(dbuf);
        while ((c = getc(collf)) != EOF)
                putc(c, dbuf);
        fclose(dbuf);
-
 done:
        fclose(collf);
        signal(SIGINT, saveint);
 done:
        fclose(collf);
        signal(SIGINT, saveint);
@@ -724,7 +717,6 @@ done:
 /*
  * Acknowledge an interrupt signal from the tty by typing an @
  */
 /*
  * Acknowledge an interrupt signal from the tty by typing an @
  */
-
 /*ARGSUSED*/
 intack(s)
 {
 /*ARGSUSED*/
 intack(s)
 {
@@ -733,31 +725,3 @@ intack(s)
        fflush(stdout);
        clearerr(stdin);
 }
        fflush(stdout);
        clearerr(stdin);
 }
-
-/*
- * Add a string to the end of a header entry field.
- */
-
-char *
-addto(hf, news)
-       char hf[], news[];
-{
-       register char *cp, *cp2, *linebuf;
-
-       if (hf == NOSTR)
-               hf = "";
-       if (*news == '\0')
-               return(hf);
-       linebuf = salloc(strlen(hf) + strlen(news) + 2);
-       for (cp = hf; any(*cp, " \t"); cp++)
-               ;
-       for (cp2 = linebuf; *cp;)
-               *cp2++ = *cp++;
-       *cp2++ = ' ';
-       for (cp = news; any(*cp, " \t"); cp++)
-               ;
-       while (*cp != '\0')
-               *cp2++ = *cp++;
-       *cp2 = '\0';
-       return(linebuf);
-}
index 0da7e56..f68e99a 100644 (file)
@@ -9,7 +9,7 @@
  * software without specific prior written permission. This software
  * is provided ``as is'' without express or implied warranty.
  *
  * software without specific prior written permission. This software
  * is provided ``as is'' without express or implied warranty.
  *
- *     @(#)def.h       5.10 (Berkeley) %G%
+ *     @(#)def.h       5.11 (Berkeley) %G%
  */
 
 #include <sys/param.h>         /* includes <sys/types.h> */
  */
 
 #include <sys/param.h>         /* includes <sys/types.h> */
@@ -144,12 +144,11 @@ struct headline {
  */
 
 struct header {
  */
 
 struct header {
-       char    *h_to;                  /* Dynamic "To:" string */
-       char    *h_subject;             /* Subject string */
-       char    *h_cc;                  /* Carbon copies string */
-       char    *h_bcc;                 /* Blind carbon copies */
-       char    *h_smopts;              /* Sendmail options */
-       int     h_seq;                  /* Sequence for optimization */
+       struct name *h_to;              /* Dynamic "To:" string */
+       char *h_subject;                /* Subject string */
+       struct name *h_cc;              /* Carbon copies string */
+       struct name *h_bcc;             /* Blind carbon copies */
+       struct name *h_smopts;          /* Sendmail options */
 };
 
 /*
 };
 
 /*
@@ -292,6 +291,7 @@ char        *yankword();
 off_t  fsize();
 struct cmd     *lex();
 struct grouphead       *findgroup();
 off_t  fsize();
 struct cmd     *lex();
 struct grouphead       *findgroup();
+struct name    *nalloc();
 struct name    *cat();
 struct name    *delname();
 struct name    *elide();
 struct name    *cat();
 struct name    *delname();
 struct name    *elide();
index 7162704..ed824cc 100644 (file)
@@ -9,7 +9,7 @@
  * software without specific prior written permission. This software
  * is provided ``as is'' without express or implied warranty.
  *
  * software without specific prior written permission. This software
  * is provided ``as is'' without express or implied warranty.
  *
- *     @(#)glob.h      5.9 (Berkeley) %G%
+ *     @(#)glob.h      5.10 (Berkeley) %G%
  */
 
 /*
  */
 
 /*
@@ -23,7 +23,6 @@ int   rcvmode;                        /* True if receiving mail */
 int    sawcom;                         /* Set after first command */
 char   *Tflag;                         /* -T temp file for netnews */
 char   nosrc;                          /* Don't source /usr/lib/Mail.rc */
 int    sawcom;                         /* Set after first command */
 char   *Tflag;                         /* -T temp file for netnews */
 char   nosrc;                          /* Don't source /usr/lib/Mail.rc */
-int    selfsent;                       /* User sent self something */
 int    senderr;                        /* An error while checking */
 int    edit;                           /* Indicates editing a file */
 int    readonly;                       /* Will be unable to rewrite file */
 int    senderr;                        /* An error while checking */
 int    edit;                           /* Indicates editing a file */
 int    readonly;                       /* Will be unable to rewrite file */
@@ -36,7 +35,6 @@ FILE  *otf;                           /* Output temp file buffer */
 FILE   *pipef;                         /* Pipe file we have opened */
 int    image;                          /* File descriptor for image of msg */
 FILE   *input;                         /* Current command input file */
 FILE   *pipef;                         /* Pipe file we have opened */
 int    image;                          /* File descriptor for image of msg */
 FILE   *input;                         /* Current command input file */
-char   *sflag;                         /* Subject given from non tty */
 char   mailname[PATHSIZE];             /* Name of current file */
 char   prevfile[PATHSIZE];             /* Name of previous file */
 int    uid;                            /* The invoker's user id */
 char   mailname[PATHSIZE];             /* Name of current file */
 char   prevfile[PATHSIZE];             /* Name of previous file */
 int    uid;                            /* The invoker's user id */
index 4cc49df..93a2031 100644 (file)
@@ -17,7 +17,7 @@ char copyright[] =
 #endif /* notdef */
 
 #ifdef notdef
 #endif /* notdef */
 
 #ifdef notdef
-static char sccsid[] = "@(#)main.c     5.14 (Berkeley) %G%";
+static char sccsid[] = "@(#)main.c     5.15 (Berkeley) %G%";
 #endif /* notdef */
 
 #include "rcv.h"
 #endif /* notdef */
 
 #include "rcv.h"
@@ -34,10 +34,11 @@ jmp_buf     hdrjmp;
 main(argc, argv)
        char **argv;
 {
 main(argc, argv)
        char **argv;
 {
-       register char *ef;
        register int i;
        struct name *to, *cc, *bcc, *smopts;
        register int i;
        struct name *to, *cc, *bcc, *smopts;
-       int mustsend, hdrstop(), (*prevint)();
+       char *subject;
+       char *ef;
+       int hdrstop(), (*prevint)();
        extern int getopt(), optind, opterr;
        extern char *optarg;
 
        extern int getopt(), optind, opterr;
        extern char *optarg;
 
@@ -58,11 +59,11 @@ main(argc, argv)
         * first of these users.
         */
        ef = NOSTR;
         * first of these users.
         */
        ef = NOSTR;
-       to = NULL;
-       cc = NULL;
-       bcc = NULL;
-       smopts = NULL;
-       mustsend = 0;
+       to = NIL;
+       cc = NIL;
+       bcc = NIL;
+       smopts = NIL;
+       subject = NOSTR;
        while ((i = getopt(argc, argv, "INT:b:c:dfins:u:v")) != EOF) {
                switch (i) {
                case 'T':
        while ((i = getopt(argc, argv, "INT:b:c:dfins:u:v")) != EOF) {
                switch (i) {
                case 'T':
@@ -98,8 +99,7 @@ main(argc, argv)
                         * Give a subject field for sending from
                         * non terminal
                         */
                         * Give a subject field for sending from
                         * non terminal
                         */
-                       mustsend++;
-                       sflag = optarg;
+                       subject = optarg;
                        break;
                case 'f':
                        /*
                        break;
                case 'f':
                        /*
@@ -144,15 +144,13 @@ main(argc, argv)
                        /*
                         * Get Carbon Copy Recipient list
                         */
                        /*
                         * Get Carbon Copy Recipient list
                         */
-                       cc = cat(cc, nalloc(optarg));
-                       mustsend++;
+                       cc = cat(cc, nalloc(optarg, GCC));
                        break;
                case 'b':
                        /*
                         * Get Blind Carbon Copy Recipient list
                         */
                        break;
                case 'b':
                        /*
                         * Get Blind Carbon Copy Recipient list
                         */
-                       bcc = cat(bcc, nalloc(optarg));
-                       mustsend++;
+                       bcc = cat(bcc, nalloc(optarg, GBCC));
                        break;
                case '?':
                        fputs("\
                        break;
                case '?':
                        fputs("\
@@ -165,24 +163,20 @@ Usage: mail [-iInv] [-s subject] [-c cc-addr] [-b bcc-addr] to-addr ...\n\
                }
        }
        for (i = optind; (argv[i]) && (*argv[i] != '-'); i++)
                }
        }
        for (i = optind; (argv[i]) && (*argv[i] != '-'); i++)
-               to = cat(to, nalloc(argv[i]));
+               to = cat(to, nalloc(argv[i], GTO));
        for (; argv[i]; i++)
        for (; argv[i]; i++)
-               smopts = cat(smopts, nalloc(argv[i]));
+               smopts = cat(smopts, nalloc(argv[i], 0));
        /*
         * Check for inconsistent arguments.
         */
        /*
         * Check for inconsistent arguments.
         */
-       if (!to && (cc || bcc)) {
-               fputs("You must also specify direct recipients of mail.\n", stderr);
+       if (to == NIL && (subject != NOSTR || cc != NIL || bcc != NIL)) {
+               fputs("You must specify direct recipients with -s, -c, or -b.\n", stderr);
                exit(1);
        }
                exit(1);
        }
-       if ((ef != NOSTR) && to) {
+       if (ef != NOSTR && to != NIL) {
                fprintf(stderr, "Cannot give -f and people to send to.\n");
                exit(1);
        }
                fprintf(stderr, "Cannot give -f and people to send to.\n");
                exit(1);
        }
-       if (mustsend && !to) {
-               fprintf(stderr, "The flags you gave make no sense since you're not sending mail.\n");
-               exit(1);
-       }
        tinit();
        setscreensize();
        input = stdin;
        tinit();
        setscreensize();
        input = stdin;
@@ -191,15 +185,12 @@ Usage: mail [-iInv] [-s subject] [-c cc-addr] [-b bcc-addr] to-addr ...\n\
                load(MASTER);
        load(mailrc);
        if (!rcvmode) {
                load(MASTER);
        load(mailrc);
        if (!rcvmode) {
-               mail(to, cc, bcc, smopts);
-
+               mail(to, cc, bcc, smopts, subject);
                /*
                 * why wait?
                 */
                /*
                 * why wait?
                 */
-
                exit(senderr);
        }
                exit(senderr);
        }
-
        /*
         * Ok, we are reading mail.
         * Decide whether we are editing a mailbox or reading
        /*
         * Ok, we are reading mail.
         * Decide whether we are editing a mailbox or reading
index fb3f7b7..bb899ca 100644 (file)
@@ -11,7 +11,7 @@
  */
 
 #ifdef notdef
  */
 
 #ifdef notdef
-static char sccsid[] = "@(#)names.c    5.8 (Berkeley) %G%";
+static char sccsid[] = "@(#)names.c    5.9 (Berkeley) %G%";
 #endif /* notdef */
 
 /*
 #endif /* notdef */
 
 /*
@@ -23,19 +23,13 @@ static char sccsid[] = "@(#)names.c 5.8 (Berkeley) %G%";
 #include "rcv.h"
 #include <sys/wait.h>
 
 #include "rcv.h"
 #include <sys/wait.h>
 
-/*
- * Set of network separator characters.
- */
-char   *metanet = "!%@";
-
 /*
  * Allocate a single element of a name list,
  * initialize its name field to the passed
  * name and return it.
  */
 /*
  * Allocate a single element of a name list,
  * initialize its name field to the passed
  * name and return it.
  */
-
 struct name *
 struct name *
-nalloc(str)
+nalloc(str, ntype)
        char str[];
 {
        register struct name *np;
        char str[];
 {
        register struct name *np;
@@ -43,7 +37,7 @@ nalloc(str)
        np = (struct name *) salloc(sizeof *np);
        np->n_flink = NIL;
        np->n_blink = NIL;
        np = (struct name *) salloc(sizeof *np);
        np->n_flink = NIL;
        np->n_blink = NIL;
-       np->n_type = -1;
+       np->n_type = ntype;
        np->n_name = savestr(str);
        return(np);
 }
        np->n_name = savestr(str);
        return(np);
 }
@@ -51,7 +45,6 @@ nalloc(str)
 /*
  * Find the tail of a list and return it.
  */
 /*
  * Find the tail of a list and return it.
  */
-
 struct name *
 tailof(name)
        struct name *name;
 struct name *
 tailof(name)
        struct name *name;
@@ -71,36 +64,21 @@ tailof(name)
  * and make a list of names from it.
  * Return the list or NIL if none found.
  */
  * and make a list of names from it.
  * Return the list or NIL if none found.
  */
-
 struct name *
 extract(line, ntype)
        char line[];
 {
        register char *cp;
        register struct name *top, *np, *t;
 struct name *
 extract(line, ntype)
        char line[];
 {
        register char *cp;
        register struct name *top, *np, *t;
-       char nbuf[BUFSIZ], abuf[BUFSIZ];
+       char nbuf[BUFSIZ];
 
 
-       if (line == NOSTR || strlen(line) == 0)
-               return(NIL);
+       if (line == NOSTR || *line == '\0')
+               return NIL;
        top = NIL;
        np = NIL;
        cp = line;
        while ((cp = yankword(cp, nbuf)) != NOSTR) {
        top = NIL;
        np = NIL;
        cp = line;
        while ((cp = yankword(cp, nbuf)) != NOSTR) {
-               if (np != NIL && equal(nbuf, "at")) {
-                       (void) strcpy(abuf, nbuf);
-                       if ((cp = yankword(cp, nbuf)) == NOSTR) {
-                               (void) strcpy(nbuf, abuf);
-                               goto normal;
-                       }
-                       (void) strcpy(abuf, np->n_name);
-                       stradd(abuf, '@');
-                       (void) strcat(abuf, nbuf);
-                       np->n_name = savestr(abuf);
-                       continue;
-               }
-normal:
-               t = nalloc(nbuf);
-               t->n_type = ntype;
+               t = nalloc(nbuf, ntype);
                if (top == NIL)
                        top = t;
                else
                if (top == NIL)
                        top = t;
                else
@@ -108,13 +86,12 @@ normal:
                t->n_blink = np;
                np = t;
        }
                t->n_blink = np;
                np = t;
        }
-       return(top);
+       return top;
 }
 
 /*
  * Turn a list of names into a string of the same names.
  */
 }
 
 /*
  * Turn a list of names into a string of the same names.
  */
-
 char *
 detract(np, ntype)
        register struct name *np;
 char *
 detract(np, ntype)
        register struct name *np;
@@ -159,9 +136,8 @@ detract(np, ntype)
 
 /*
  * Grab a single word (liberal word)
 
 /*
  * Grab a single word (liberal word)
- * Throw away things between ()'s.
+ * Throw away things between ()'s, and take anything between <>.
  */
  */
-
 char *
 yankword(ap, wbuf)
        char *ap, wbuf[];
 char *
 yankword(ap, wbuf)
        char *ap, wbuf[];
@@ -169,9 +145,9 @@ yankword(ap, wbuf)
        register char *cp, *cp2;
 
        cp = ap;
        register char *cp, *cp2;
 
        cp = ap;
-       do {
-               while (*cp && any(*cp, " \t,"))
-                       cp++;
+       for (;;) {
+               if (*cp == '\0')
+                       return NOSTR;
                if (*cp == '(') {
                        register int nesting = 0;
 
                if (*cp == '(') {
                        register int nesting = 0;
 
@@ -187,14 +163,19 @@ yankword(ap, wbuf)
                                if (nesting <= 0)
                                        break;
                        }
                                if (nesting <= 0)
                                        break;
                        }
-               }
-               if (*cp == '\0')
-                       return(NOSTR);
-       } while (any(*cp, " \t,("));
-       for (cp2 = wbuf; *cp && !any(*cp, " \t,("); *cp2++ = *cp++)
-               ;
+               } else if (*cp == ' ' || *cp == '\t' || *cp == ',')
+                       cp++;
+               else
+                       break;
+       }
+       if (*cp ==  '<')
+               for (cp2 = wbuf; *cp && (*cp2++ = *cp++) != '>';)
+                       ;
+       else
+               for (cp2 = wbuf; *cp && !any(*cp, " \t,("); *cp2++ = *cp++)
+                       ;
        *cp2 = '\0';
        *cp2 = '\0';
-       return(cp);
+       return cp;
 }
 
 /*
 }
 
 /*
@@ -205,7 +186,6 @@ yankword(ap, wbuf)
  * Recipients whose name begins with | are piped through the given
  * program and removed.
  */
  * Recipients whose name begins with | are piped through the given
  * program and removed.
  */
-
 struct name *
 outof(names, fo, hp)
        struct name *names;
 struct name *
 outof(names, fo, hp)
        struct name *names;
@@ -367,19 +347,15 @@ isfileaddr(name)
 {
        register char *cp;
 
 {
        register char *cp;
 
-       if (any('@', name))
-               return(0);
        if (*name == '+')
        if (*name == '+')
-               return(1);
+               return 1;
        for (cp = name; *cp; cp++) {
        for (cp = name; *cp; cp++) {
-               if (*cp == '.')
-                       continue;
-               if (any(*cp, metanet))
-                       return(0);
+               if (*cp == '!' || *cp == '%' || *cp == '@')
+                       return 0;
                if (*cp == '/')
                if (*cp == '/')
-                       return(1);
+                       return 1;
        }
        }
-       return(0);
+       return 0;
 }
 
 /*
 }
 
 /*
@@ -451,8 +427,7 @@ gexpand(nlist, gh, metoo, ntype)
                        continue;
                }
 quote:
                        continue;
                }
 quote:
-               np = nalloc(cp);
-               np->n_type = ntype;
+               np = nalloc(cp, ntype);
                /*
                 * At this point should allow to expand
                 * to self if only person in group
                /*
                 * At this point should allow to expand
                 * to self if only person in group
@@ -468,28 +443,9 @@ skip:
        return(nlist);
 }
 
        return(nlist);
 }
 
-
-
-/*
- * Compute the length of the passed name list and
- * return it.
- */
-
-lengthof(name)
-       struct name *name;
-{
-       register struct name *np;
-       register int c;
-
-       for (c = 0, np = name; np != NIL; c++, np = np->n_flink)
-               ;
-       return(c);
-}
-
 /*
  * Concatenate the two passed name lists, return the result.
  */
 /*
  * Concatenate the two passed name lists, return the result.
  */
-
 struct name *
 cat(n1, n2)
        struct name *n1, *n2;
 struct name *
 cat(n1, n2)
        struct name *n1, *n2;
@@ -510,7 +466,6 @@ cat(n1, n2)
  * Unpack the name list onto a vector of strings.
  * Return an error if the name list won't fit.
  */
  * Unpack the name list onto a vector of strings.
  * Return an error if the name list won't fit.
  */
-
 char **
 unpack(np)
        struct name *np;
 char **
 unpack(np)
        struct name *np;
@@ -520,16 +475,14 @@ unpack(np)
        int t, extra, metoo, verbose;
 
        n = np;
        int t, extra, metoo, verbose;
 
        n = np;
-       if ((t = lengthof(n)) == 0)
+       if ((t = count(n)) == 0)
                panic("No names to unpack");
                panic("No names to unpack");
-
        /*
         * Compute the number of extra arguments we will need.
         * We need at least two extra -- one for "mail" and one for
         * the terminating 0 pointer.  Additional spots may be needed
         * to pass along -f to the host mailer.
         */
        /*
         * Compute the number of extra arguments we will need.
         * We need at least two extra -- one for "mail" and one for
         * the terminating 0 pointer.  Additional spots may be needed
         * to pass along -f to the host mailer.
         */
-
        extra = 2;
        extra++;
        metoo = value("metoo") != NOSTR;
        extra = 2;
        extra++;
        metoo = value("metoo") != NOSTR;
@@ -563,7 +516,6 @@ unpack(np)
  * insertion sorting them, then checking for dups.
  * Return the head of the new list.
  */
  * insertion sorting them, then checking for dups.
  * Return the head of the new list.
  */
-
 struct name *
 elide(names)
        struct name *names;
 struct name *
 elide(names)
        struct name *names;
@@ -662,7 +614,6 @@ elide(names)
 /*
  * Version of strcmp which ignores case differences.
  */
 /*
  * Version of strcmp which ignores case differences.
  */
-
 nstrcmp(s1, s2)
        register char *s1, *s2;
 {
 nstrcmp(s1, s2)
        register char *s1, *s2;
 {
@@ -679,7 +630,6 @@ nstrcmp(s1, s2)
  * Put another node onto a list of names and return
  * the list.
  */
  * Put another node onto a list of names and return
  * the list.
  */
-
 struct name *
 put(list, node)
        struct name *list, *node;
 struct name *
 put(list, node)
        struct name *list, *node;
@@ -695,17 +645,14 @@ put(list, node)
  * Determine the number of elements in
  * a name list and return it.
  */
  * Determine the number of elements in
  * a name list and return it.
  */
-
 count(np)
        register struct name *np;
 {
 count(np)
        register struct name *np;
 {
-       register int c = 0;
+       register int c;
 
 
-       while (np != NIL) {
-               c++;
-               np = np->n_flink;
-       }
-       return(c);
+       for (c = 0; np != NIL; c++, np = np->n_flink)
+               ;
+       return c;
 }
 
 /*
 }
 
 /*
index a8c8118..10947e6 100644 (file)
@@ -11,7 +11,7 @@
  */
 
 #ifdef notdef
  */
 
 #ifdef notdef
-static char sccsid[] = "@(#)send.c     5.10 (Berkeley) %G%";
+static char sccsid[] = "@(#)send.c     5.11 (Berkeley) %G%";
 #endif /* notdef */
 
 #include "rcv.h"
 #endif /* notdef */
 
 #include "rcv.h"
@@ -183,18 +183,18 @@ statusput(mp, obuf)
  * which does all the dirty work.
  */
 
  * which does all the dirty work.
  */
 
-mail(to, cc, bcc, smopts)
+mail(to, cc, bcc, smopts, subject)
        struct name *to, *cc, *bcc, *smopts;
        struct name *to, *cc, *bcc, *smopts;
+       char *subject;
 {
        struct header head;
 
 {
        struct header head;
 
-       head.h_to = detract(to, 0);
-       head.h_subject = NOSTR;
-       head.h_cc = detract(cc, 0);
-       head.h_bcc = detract(bcc, 0);
-       head.h_smopts = detract(smopts, 0);
-       head.h_seq = 0;
-       (void) mail1(&head);
+       head.h_to = to;
+       head.h_subject = subject;
+       head.h_cc = cc;
+       head.h_bcc = bcc;
+       head.h_smopts = smopts;
+       (void) mail1(&head, 0);
        return(0);
 }
 
        return(0);
 }
 
@@ -209,16 +209,12 @@ sendmail(str)
 {
        struct header head;
 
 {
        struct header head;
 
-       if (blankline(str))
-               head.h_to = NOSTR;
-       else
-               head.h_to = str;
+       head.h_to = extract(str, GTO);
        head.h_subject = NOSTR;
        head.h_subject = NOSTR;
-       head.h_cc = NOSTR;
-       head.h_bcc = NOSTR;
-       head.h_smopts = NOSTR;
-       head.h_seq = 0;
-       (void) mail1(&head);
+       head.h_cc = NIL;
+       head.h_bcc = NIL;
+       head.h_smopts = NIL;
+       (void) mail1(&head, 0);
        return(0);
 }
 
        return(0);
 }
 
@@ -227,7 +223,7 @@ sendmail(str)
  * in the passed header.  (Internal interface).
  */
 
  * in the passed header.  (Internal interface).
  */
 
-mail1(hp)
+mail1(hp, printheaders)
        struct header *hp;
 {
        register char *cp;
        struct header *hp;
 {
        register char *cp;
@@ -245,11 +241,8 @@ mail1(hp)
         */
 
        pid = -1;
         */
 
        pid = -1;
-       if (hp->h_subject == NOSTR)
-               hp->h_subject = sflag;
-       if ((mtf = collect(hp)) == NULL)
+       if ((mtf = collect(hp, printheaders)) == NULL)
                return(-1);
                return(-1);
-       hp->h_seq = 1;
        if (value("interactive") != NOSTR)
                if (value("askcc") != NOSTR)
                        grabh(hp, GCC);
        if (value("interactive") != NOSTR)
                if (value("askcc") != NOSTR)
                        grabh(hp, GCC);
@@ -257,26 +250,21 @@ mail1(hp)
                        printf("EOT\n");
                        (void) fflush(stdout);
                }
                        printf("EOT\n");
                        (void) fflush(stdout);
                }
-
        /*
         * Now, take the user names from the combined
         * to and cc lists and do all the alias
         * processing.
         */
        /*
         * Now, take the user names from the combined
         * to and cc lists and do all the alias
         * processing.
         */
-
        senderr = 0;
        senderr = 0;
-       to = usermap(cat(extract(hp->h_bcc, GBCC),
-               cat(extract(hp->h_to, GTO), extract(hp->h_cc, GCC))));
+       to = usermap(cat(hp->h_bcc, cat(hp->h_to, hp->h_cc)));
        if (to == NIL) {
                printf("No recipients specified\n");
                goto topdog;
        }
        if (to == NIL) {
                printf("No recipients specified\n");
                goto topdog;
        }
-
        /*
         * Look through the recipient list for names with /'s
         * in them which we write to as files directly.
         */
        /*
         * 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) {
        to = outof(to, mtf, hp);
        rewind(mtf);
        if (senderr) {
@@ -295,23 +283,22 @@ topdog:
        if (!gotcha)
                goto out;
        to = elide(to);
        if (!gotcha)
                goto out;
        to = elide(to);
-       if (count(to) > 1)
-               hp->h_seq++;
-       if (hp->h_seq > 0) {
-               fixhead(hp, to);
-               if (fsize(mtf) == 0)
-                   if (hp->h_subject == NOSTR)
+       if (fsize(mtf) == 0)
+               if (hp->h_subject == NOSTR)
                        printf("No message, no subject; hope that's ok\n");
                        printf("No message, no subject; hope that's ok\n");
-                   else
+               else
                        printf("Null message body; hope that's ok\n");
                        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 ((mtf = infix(hp, mtf)) == NULL) {
                        fprintf(stderr, ". . . message lost, sorry.\n");
                        return(-1);
                }
        }
-       namelist = unpack(cat(extract(hp->h_smopts, 0), to));
+       namelist = unpack(cat(hp->h_smopts, to));
        if (debug) {
        if (debug) {
-               printf("Recipients of message:\n");
+               printf("Sendmail arguments:");
                for (t = namelist; *t != NOSTR; t++)
                        printf(" \"%s\"", *t);
                printf("\n");
                for (t = namelist; *t != NOSTR; t++)
                        printf(" \"%s\"", *t);
                printf("\n");
@@ -320,7 +307,6 @@ topdog:
        }
        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
        /*
         * Wait, to absorb a potential zombie, then
         * fork, set up the temporary mail file as standard
@@ -328,7 +314,6 @@ topdog:
         * far above. Return the process id to caller in case he
         * wants to await the completion of mail.
         */
         * far above. Return the process id to caller in case he
         * wants to await the completion of mail.
         */
-
        while (wait3(&s, WNOHANG, (struct timeval *) 0) > 0)
                ;
        rewind(mtf);
        while (wait3(&s, WNOHANG, (struct timeval *) 0) > 0)
                ;
        rewind(mtf);
@@ -364,7 +349,6 @@ topdog:
                perror(deliver);
                exit(1);
        }
                perror(deliver);
                exit(1);
        }
-
 out:
        if (value("verbose") != NOSTR) {
                while ((p = wait(&s)) != pid && p != -1)
 out:
        if (value("verbose") != NOSTR) {
                while ((p = wait(&s)) != pid && p != -1)
@@ -374,34 +358,32 @@ out:
                pid = 0;
        }
        (void) fclose(mtf);
                pid = 0;
        }
        (void) fclose(mtf);
-       return(pid);
+       return pid;
 }
 
 /*
  * Fix the header by glopping all of the expanded names from
  * the distribution list into the appropriate fields.
 }
 
 /*
  * Fix the header by glopping all of the expanded names from
  * the distribution list into the appropriate fields.
- * If there are any ARPA net recipients in the message,
- * we must insert commas, alas.
  */
  */
-
 fixhead(hp, tolist)
        struct header *hp;
        struct name *tolist;
 {
 fixhead(hp, tolist)
        struct header *hp;
        struct name *tolist;
 {
-       register int f;
        register struct name *np;
 
        register struct name *np;
 
-       for (f = 0, np = tolist; np != NIL; np = np->n_flink)
-               if (any('@', np->n_name)) {
-                       f |= GCOMMA;
-                       break;
-               }
-
-       if (debug && f & GCOMMA)
-               fprintf(stderr, "Should be inserting commas in recip lists\n");
-       hp->h_to = detract(tolist, GTO|f);
-       hp->h_cc = detract(tolist, GCC|f);
-       hp->h_bcc = detract(tolist, GBCC|f);
+       hp->h_to = NIL;
+       hp->h_cc = NIL;
+       hp->h_bcc = NIL;
+       for (np = tolist; np != NIL; np = np->n_flink)
+               if ((np->n_type & GMASK) == GTO)
+                       hp->h_to =
+                               cat(hp->h_to, nalloc(np->n_name, np->n_type));
+               else if ((np->n_type & GMASK) == GCC)
+                       hp->h_cc =
+                               cat(hp->h_cc, nalloc(np->n_name, np->n_type));
+               else if ((np->n_type & GMASK) == GBCC)
+                       hp->h_bcc =
+                               cat(hp->h_bcc, nalloc(np->n_name, np->n_type));
 }
 
 /*
 }
 
 /*
@@ -429,7 +411,7 @@ infix(hp, fi)
                return(fi);
        }
        (void) remove(tempMail);
                return(fi);
        }
        (void) remove(tempMail);
-       (void) puthead(hp, nfo, GTO|GSUBJECT|GCC|GBCC|GNL);
+       (void) puthead(hp, nfo, GTO|GSUBJECT|GCC|GBCC|GNL|GCOMMA);
        c = getc(fi);
        while (c != EOF) {
                (void) putc(c, nfo);
        c = getc(fi);
        while (c != EOF) {
                (void) putc(c, nfo);
@@ -456,7 +438,6 @@ infix(hp, fi)
  * Dump the to, subject, cc header on the
  * passed file buffer.
  */
  * Dump the to, subject, cc header on the
  * passed file buffer.
  */
-
 puthead(hp, fo, w)
        struct header *hp;
        FILE *fo;
 puthead(hp, fo, w)
        struct header *hp;
        FILE *fo;
@@ -464,14 +445,14 @@ puthead(hp, fo, w)
        register int gotcha;
 
        gotcha = 0;
        register int gotcha;
 
        gotcha = 0;
-       if (hp->h_to != NOSTR && w & GTO)
-               fmt("To: ", hp->h_to, fo), gotcha++;
+       if (hp->h_to != NIL && w & GTO)
+               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_subject != NOSTR && w & GSUBJECT)
                fprintf(fo, "Subject: %s\n", hp->h_subject), gotcha++;
-       if (hp->h_cc != NOSTR && w & GCC)
-               fmt("Cc: ", hp->h_cc, fo), gotcha++;
-       if (hp->h_bcc != NOSTR && w & GBCC)
-               fmt("Bcc: ", hp->h_bcc, fo), gotcha++;
+       if (hp->h_cc != NIL && w & GCC)
+               fmt("Cc: ", hp->h_cc, fo, w&GCOMMA), gotcha++;
+       if (hp->h_bcc != NIL && w & GBCC)
+               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);
@@ -480,45 +461,40 @@ puthead(hp, fo, w)
 /*
  * Format the given text to not exceed 72 characters.
  */
 /*
  * Format the given text to not exceed 72 characters.
  */
-
-fmt(str, txt, fo)
-       register char *str, *txt;
-       register FILE *fo;
+fmt(str, np, fo, comma)
+       char *str;
+       register struct name *np;
+       FILE *fo;
+       int comma;
 {
 {
-       register int col;
-       register char *bg, *bl, *pt, ch;
+       register col, len;
 
 
+       comma = comma ? 1 : 0;
        col = strlen(str);
        if (col)
        col = strlen(str);
        if (col)
-               fprintf(fo, "%s", str);
-       pt = bg = txt;
-       bl = 0;
-       while (*bg) {
-               pt++;
-               if (++col > 72) {
-                       if (!bl) {
-                               bl = bg;
-                               while (*bl && !isspace(*bl))
-                                       bl++;
-                       }
-                       if (!*bl)
-                               goto finish;
-                       ch = *bl;
-                       *bl = '\0';
-                       fprintf(fo, "%s\n    ", bg);
-                       col = 4;
-                       *bl = ch;
-                       pt = bg = ++bl;
-                       bl = 0;
+               fputs(str, fo);
+       len = strlen(np->n_name);
+       for (;;) {
+               fputs(np->n_name, fo);
+               col += len;
+               if (comma) {
+                       putc(',', fo);
+                       col++;
                }
                }
-               if (!*pt) {
-finish:
-                       fprintf(fo, "%s\n", bg);
-                       return;
+               if ((np = np->n_flink) == NIL)
+                       break;
+               if (np->n_flink == NIL)
+                       comma = 0;
+               len = strlen(np->n_name);
+               if (col + len + comma > 72) {
+                       fputs("\n    ", fo);
+                       col = 4;
+               } else {
+                       putc(' ', fo);
+                       col++;
                }
                }
-               if (isspace(*pt))
-                       bl = pt;
        }
        }
+       putc('\n', fo);
 }
 
 /*
 }
 
 /*
index 6a400c5..95c0529 100644 (file)
@@ -11,7 +11,7 @@
  */
 
 #ifdef notdef
  */
 
 #ifdef notdef
-static char sccsid[] = "@(#)tty.c      5.5 (Berkeley) %G%";
+static char sccsid[] = "@(#)tty.c      5.6 (Berkeley) %G%";
 #endif /* notdef */
 
 /*
 #endif /* notdef */
 
 /*
@@ -65,12 +65,11 @@ grabh(hp, gflags)
 #endif
        if (gflags & GTO) {
 #ifndef TIOCSTI
 #endif
        if (gflags & GTO) {
 #ifndef TIOCSTI
-               if (!ttyset && hp->h_to != NOSTR)
+               if (!ttyset && hp->h_to != NIL)
                        ttyset++, stty(fileno(stdin), &ttybuf);
 #endif
                        ttyset++, stty(fileno(stdin), &ttybuf);
 #endif
-               hp->h_to = readtty("To: ", hp->h_to);
-               if (hp->h_to != NOSTR)
-                       hp->h_seq++;
+               hp->h_to =
+                       extract(readtty("To: ", detract(hp->h_to, 0)), GTO);
        }
        if (gflags & GSUBJECT) {
 #ifndef TIOCSTI
        }
        if (gflags & GSUBJECT) {
 #ifndef TIOCSTI
@@ -78,26 +77,22 @@ grabh(hp, gflags)
                        ttyset++, stty(fileno(stdin), &ttybuf);
 #endif
                hp->h_subject = readtty("Subject: ", hp->h_subject);
                        ttyset++, stty(fileno(stdin), &ttybuf);
 #endif
                hp->h_subject = readtty("Subject: ", hp->h_subject);
-               if (hp->h_subject != NOSTR)
-                       hp->h_seq++;
        }
        if (gflags & GCC) {
 #ifndef TIOCSTI
        }
        if (gflags & GCC) {
 #ifndef TIOCSTI
-               if (!ttyset && hp->h_cc != NOSTR)
+               if (!ttyset && hp->h_cc != NIL)
                        ttyset++, stty(fileno(stdin), &ttybuf);
 #endif
                        ttyset++, stty(fileno(stdin), &ttybuf);
 #endif
-               hp->h_cc = readtty("Cc: ", hp->h_cc);
-               if (hp->h_cc != NOSTR)
-                       hp->h_seq++;
+               hp->h_cc =
+                       extract(readtty("Cc: ", detract(hp->h_cc, 0)), GCC);
        }
        if (gflags & GBCC) {
 #ifndef TIOCSTI
        }
        if (gflags & GBCC) {
 #ifndef TIOCSTI
-               if (!ttyset && hp->h_bcc != NOSTR)
+               if (!ttyset && hp->h_bcc != NIL)
                        ttyset++, stty(fileno(stdin), &ttybuf);
 #endif
                        ttyset++, stty(fileno(stdin), &ttybuf);
 #endif
-               hp->h_bcc = readtty("Bcc: ", hp->h_bcc);
-               if (hp->h_bcc != NOSTR)
-                       hp->h_seq++;
+               hp->h_bcc =
+                       extract(readtty("Bcc: ", detract(hp->h_bcc, 0)), GBCC);
        }
        signal(SIGCONT, savecont);
 #ifndef TIOCSTI
        }
        signal(SIGCONT, savecont);
 #ifndef TIOCSTI