hash() could return negative values.
[unix-history] / usr / src / usr.bin / mail / send.c
index 51f71fe..7cfae0e 100644 (file)
@@ -4,6 +4,8 @@
 #ifdef VMUNIX
 #include <wait.h>
 #endif
 #ifdef VMUNIX
 #include <wait.h>
 #endif
+#include <ctype.h>
+#include <sys/stat.h>
 
 /*
  * Mail -- a mail program
 
 /*
  * Mail -- a mail program
  * Mail to others.
  */
 
  * Mail to others.
  */
 
-static char *SccsId = "@(#)send.c      1.1 %G%";
+static char *SccsId = "@(#)send.c      2.11 %G%";
 
 /*
  * Send message described by the passed pointer to the
  * passed output buffer.  Return -1 on error, but normally
 
 /*
  * Send message described by the passed pointer to the
  * passed output buffer.  Return -1 on error, but normally
- * the number of lines written.
+ * the number of lines written.  Adjust the status: field
+ * if need be.  If doign is set, suppress ignored header fields.
  */
  */
-
-send(mailp, obuf)
+send(mailp, obuf, doign)
        struct message *mailp;
        FILE *obuf;
 {
        register struct message *mp;
        register int t;
        struct message *mailp;
        FILE *obuf;
 {
        register struct message *mp;
        register int t;
-       unsigned int c;
+       long c;
        FILE *ibuf;
        FILE *ibuf;
-       int lc;
+       char line[LINESIZE], field[BUFSIZ];
+       int lc, ishead, infld, fline, dostat;
+       char *cp, *cp2;
 
        mp = mailp;
        ibuf = setinput(mp);
 
        mp = mailp;
        ibuf = setinput(mp);
-       c = msize(mp);
+       c = mp->m_size;
+       ishead = 1;
+       dostat = 1;
+       infld = 0;
+       fline = 1;
        lc = 0;
        lc = 0;
-       while (c-- > 0) {
-               putc(t = getc(ibuf), obuf);
-               if (t == '\n')
-                       lc++;
+       while (c > 0L) {
+               fgets(line, LINESIZE, ibuf);
+               c -= (long) strlen(line);
+               lc++;
+               if (ishead) {
+                       /* 
+                        * First line is the From line, so no headers
+                        * there to worry about
+                        */
+                       if (fline) {
+                               fline = 0;
+                               goto writeit;
+                       }
+                       /*
+                        * If line is blank, we've reached end of
+                        * headers, so force out status: field
+                        * and note that we are no longer in header
+                        * fields
+                        */
+                       if (line[0] == '\n') {
+                               if (dostat) {
+                                       statusput(mailp, obuf, doign);
+                                       dostat = 0;
+                               }
+                               ishead = 0;
+                               goto writeit;
+                       }
+                       /*
+                        * If this line is a continuation (via space or tab)
+                        * of a previous header field, just echo it
+                        * (unless the field should be ignored).
+                        */
+                       if (infld && (isspace(line[0]) || line[0] == '\t')) {
+                               if (doign && isign(field)) continue;
+                               goto writeit;
+                       }
+                       infld = 0;
+                       /*
+                        * If we are no longer looking at real
+                        * header lines, force out status:
+                        * This happens in uucp style mail where
+                        * there are no headers at all.
+                        */
+                       if (!headerp(line)) {
+                               if (dostat) {
+                                       statusput(mailp, obuf, doign);
+                                       dostat = 0;
+                               }
+                               putc('\n', obuf);
+                               ishead = 0;
+                               goto writeit;
+                       }
+                       infld++;
+                       /*
+                        * Pick up the header field.
+                        * If it is an ignored field and
+                        * we care about such things, skip it.
+                        */
+                       cp = line;
+                       cp2 = field;
+                       while (*cp && *cp != ':' && !isspace(*cp))
+                               *cp2++ = *cp++;
+                       *cp2 = 0;
+                       if (doign && isign(field))
+                               continue;
+                       /*
+                        * If the field is "status," go compute and print the
+                        * real Status: field
+                        */
+                       if (icequal(field, "status")) {
+                               if (dostat) {
+                                       statusput(mailp, obuf, doign);
+                                       dostat = 0;
+                               }
+                               continue;
+                       }
+               }
+writeit:
+               fputs(line, obuf);
                if (ferror(obuf))
                        return(-1);
        }
                if (ferror(obuf))
                        return(-1);
        }
+       if (ferror(obuf))
+               return(-1);
+       if (ishead && (mailp->m_flag & MSTATUS))
+               printf("failed to fix up status field\n");
        return(lc);
 }
 
        return(lc);
 }
 
+/*
+ * Test if the passed line is a header line, RFC 733 style.
+ */
+headerp(line)
+       register char *line;
+{
+       register char *cp = line;
+
+       while (*cp && !isspace(*cp) && *cp != ':')
+               cp++;
+       while (*cp && isspace(*cp))
+               cp++;
+       return(*cp == ':');
+}
+
+/*
+ * Output a reasonable looking status field.
+ * But if "status" is ignored and doign, forget it.
+ */
+statusput(mp, obuf, doign)
+       register struct message *mp;
+       register FILE *obuf;
+{
+       char statout[3];
+
+       if (doign && isign("status"))
+               return;
+       if ((mp->m_flag & (MNEW|MREAD)) == MNEW)
+               return;
+       if (mp->m_flag & MREAD)
+               strcpy(statout, "R");
+       else
+               strcpy(statout, "");
+       if ((mp->m_flag & MNEW) == 0)
+               strcat(statout, "O");
+       fprintf(obuf, "Status: %s\n", statout);
+}
+
+
 /*
  * 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.
@@ -112,8 +238,9 @@ mail1(hp)
 {
        register char *cp;
        int pid, i, s, p, gotcha;
 {
        register char *cp;
        int pid, i, s, p, gotcha;
-       char **namelist;
+       char **namelist, *deliver;
        struct name *to, *np;
        struct name *to, *np;
+       struct stat sbuf;
        FILE *mtf, *postage;
        int remote = rflag != NOSTR || rmail;
        char **t;
        FILE *mtf, *postage;
        int remote = rflag != NOSTR || rmail;
        char **t;
@@ -129,10 +256,6 @@ mail1(hp)
        hp->h_seq = 1;
        if (hp->h_subject == NOSTR)
                hp->h_subject = sflag;
        hp->h_seq = 1;
        if (hp->h_subject == NOSTR)
                hp->h_subject = sflag;
-       if (fsize(mtf) == 0 && hp->h_subject == NOSTR) {
-               printf("No message !?!\n");
-               goto out;
-       }
        if (intty && value("askcc") != NOSTR)
                grabh(hp, GCC);
        else if (intty) {
        if (intty && value("askcc") != NOSTR)
                grabh(hp, GCC);
        else if (intty) {
@@ -185,6 +308,9 @@ topdog:
        if (hp->h_seq > 0 && !remote) {
                fixhead(hp, to);
                if (fsize(mtf) == 0)
        if (hp->h_seq > 0 && !remote) {
                fixhead(hp, 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 ((mtf = infix(hp, mtf)) == NULL) {
                        fprintf(stderr, ". . . message lost, sorry.\n");
                        printf("Null message body; hope that's ok\n");
                if ((mtf = infix(hp, mtf)) == NULL) {
                        fprintf(stderr, ". . . message lost, sorry.\n");
@@ -212,7 +338,12 @@ topdog:
         */
 
 #ifdef VMUNIX
         */
 
 #ifdef VMUNIX
+#ifdef pdp11
+       while (wait2(&s, WNOHANG) > 0)
+#endif
+#if defined(vax) || defined(sun)
        while (wait3(&s, WNOHANG, 0) > 0)
        while (wait3(&s, WNOHANG, 0) > 0)
+#endif
                ;
 #else
        wait(&s);
                ;
 #else
        wait(&s);
@@ -226,20 +357,22 @@ topdog:
                goto out;
        }
        if (pid == 0) {
                goto out;
        }
        if (pid == 0) {
+               sigchild();
 #ifdef SIGTSTP
                if (remote == 0) {
 #ifdef SIGTSTP
                if (remote == 0) {
-                       signal(SIGTSTP, SIG_IGN);
-                       signal(SIGTTIN, SIG_IGN);
-                       signal(SIGTTOU, SIG_IGN);
+                       sigset(SIGTSTP, SIG_IGN);
+                       sigset(SIGTTIN, SIG_IGN);
+                       sigset(SIGTTOU, SIG_IGN);
                }
 #endif
                for (i = SIGHUP; i <= SIGQUIT; i++)
                }
 #endif
                for (i = SIGHUP; i <= SIGQUIT; i++)
-                       signal(i, SIG_IGN);
-               if ((postage = fopen("/crp/kurt/postage", "a")) != NULL) {
-                       fprintf(postage, "%s %d %d\n", myname,
-                           count(to), fsize(mtf));
-                       fclose(postage);
-               }
+                       sigset(i, SIG_IGN);
+               if (!stat(POSTAGE, &sbuf))
+                       if ((postage = fopen(POSTAGE, "a")) != NULL) {
+                               fprintf(postage, "%s %d %d\n", myname,
+                                   count(to), fsize(mtf));
+                               fclose(postage);
+                       }
                s = fileno(mtf);
                for (i = 3; i < 15; i++)
                        if (i != s)
                s = fileno(mtf);
                for (i = 3; i < 15; i++)
                        if (i != s)
@@ -250,16 +383,18 @@ topdog:
 #ifdef CC
                submit(getpid());
 #endif CC
 #ifdef CC
                submit(getpid());
 #endif CC
-#ifdef DELIVERMAIL
-               execv(DELIVERMAIL, namelist);
-#endif DELIVERMAIL
+#ifdef SENDMAIL
+               if ((deliver = value("sendmail")) == NOSTR)
+                       deliver = SENDMAIL;
+               execv(deliver, namelist);
+#endif SENDMAIL
                execv(MAIL, namelist);
                perror(MAIL);
                exit(1);
        }
 
 out:
                execv(MAIL, namelist);
                perror(MAIL);
                exit(1);
        }
 
 out:
-       if (remote) {
+       if (remote || (value("verbose") != NOSTR)) {
                while ((p = wait(&s)) != pid && p != -1)
                        ;
                if (s != 0)
                while ((p = wait(&s)) != pid && p != -1)
                        ;
                if (s != 0)
@@ -311,6 +446,7 @@ 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);
@@ -322,7 +458,6 @@ infix(hp, fi)
        }
        remove(tempMail);
        puthead(hp, nfo, GTO|GSUBJECT|GCC|GNL);
        }
        remove(tempMail);
        puthead(hp, nfo, GTO|GSUBJECT|GCC|GNL);
-       rewind(fi);
        c = getc(fi);
        while (c != EOF) {
                putc(c, nfo);
        c = getc(fi);
        while (c != EOF) {
                putc(c, nfo);
@@ -330,7 +465,6 @@ infix(hp, fi)
        }
        if (ferror(fi)) {
                perror("read");
        }
        if (ferror(fi)) {
                perror("read");
-               fprintf(stderr, "Please notify Kurt Shoens\n");
                return(fi);
        }
        fflush(nfo);
                return(fi);
        }
        fflush(nfo);
@@ -359,13 +493,13 @@ puthead(hp, fo, w)
 
        gotcha = 0;
        if (hp->h_to != NOSTR && w & GTO)
 
        gotcha = 0;
        if (hp->h_to != NOSTR && w & GTO)
-               fprintf(fo, "To: "), fmt(hp->h_to, fo), gotcha++;
+               fmt("To: ", hp->h_to, fo), gotcha++;
        if (hp->h_subject != NOSTR && w & GSUBJECT)
                fprintf(fo, "Subject: %s\n", hp->h_subject), gotcha++;
        if (hp->h_cc != NOSTR && w & GCC)
        if (hp->h_subject != NOSTR && w & GSUBJECT)
                fprintf(fo, "Subject: %s\n", hp->h_subject), gotcha++;
        if (hp->h_cc != NOSTR && w & GCC)
-               fprintf(fo, "Cc: "), fmt(hp->h_cc, fo), gotcha++;
+               fmt("Cc: ", hp->h_cc, fo), gotcha++;
        if (hp->h_bcc != NOSTR && w & GBCC)
        if (hp->h_bcc != NOSTR && w & GBCC)
-               fprintf(fo, "Bcc: "), fmt(hp->h_bcc, fo), gotcha++;
+               fmt("Bcc: ", hp->h_bcc, fo), gotcha++;
        if (gotcha && w & GNL)
                putc('\n', fo);
        return(0);
        if (gotcha && w & GNL)
                putc('\n', fo);
        return(0);
@@ -375,26 +509,44 @@ puthead(hp, fo, w)
  * Format the given text to not exceed 72 characters.
  */
 
  * Format the given text to not exceed 72 characters.
  */
 
-fmt(str, fo)
-       register char *str;
+fmt(str, txt, fo)
+       register char *str, *txt;
        register FILE *fo;
 {
        register int col;
        register FILE *fo;
 {
        register int col;
-       register char *cp;
-
-       cp = str;
-       col = 0;
-       while (*cp) {
-               if (*cp == ' ' && col > 65) {
-                       fprintf(fo, "\n    ");
+       register char *bg, *bl, *pt, ch;
+
+       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;
                        col = 4;
-                       cp++;
-                       continue;
+                       *bl = ch;
+                       pt = bg = ++bl;
+                       bl = 0;
+               }
+               if (!*pt) {
+finish:
+                       fprintf(fo, "%s\n", bg);
+                       return;
                }
                }
-               putc(*cp++, fo);
-               col++;
+               if (isspace(*pt))
+                       bl = pt;
        }
        }
-       putc('\n', fo);
 }
 
 /*
 }
 
 /*