Many changes resulting from a complete code readthrough. Most of these
authorEric Allman <eric@ucbvax.Berkeley.EDU>
Sun, 28 Nov 1982 16:24:21 +0000 (08:24 -0800)
committerEric Allman <eric@ucbvax.Berkeley.EDU>
Sun, 28 Nov 1982 16:24:21 +0000 (08:24 -0800)
fix minor bugs or change the internal structure for clarity, etc.  There
should be almost no externally visible changes (other than some cleaner
error message printouts and the like).

SCCS-vsn: usr.sbin/sendmail/src/main.c 3.141
SCCS-vsn: usr.sbin/sendmail/src/alias.c 3.42
SCCS-vsn: usr.sbin/sendmail/src/conf.c 3.65
SCCS-vsn: usr.sbin/sendmail/src/deliver.c 3.133
SCCS-vsn: usr.sbin/sendmail/src/collect.c 3.55
SCCS-vsn: usr.sbin/sendmail/src/err.c 3.36
SCCS-vsn: usr.sbin/sendmail/src/convtime.c 3.3
SCCS-vsn: usr.sbin/sendmail/src/clock.c 3.13
SCCS-vsn: usr.sbin/sendmail/src/sendmail.h 3.102
SCCS-vsn: usr.sbin/sendmail/src/parseaddr.c 3.67
SCCS-vsn: usr.sbin/sendmail/src/savemail.c 3.50
SCCS-vsn: usr.sbin/sendmail/src/version.c 3.253
SCCS-vsn: usr.sbin/sendmail/src/util.c 3.35
SCCS-vsn: usr.sbin/sendmail/src/queue.c 3.54
SCCS-vsn: usr.sbin/sendmail/src/srvrsmtp.c 3.39
SCCS-vsn: usr.sbin/sendmail/src/recipient.c 3.48
SCCS-vsn: usr.sbin/sendmail/src/usersmtp.c 3.28
SCCS-vsn: usr.sbin/sendmail/src/readcf.c 3.48
SCCS-vsn: usr.sbin/sendmail/src/macro.c 3.18
SCCS-vsn: usr.sbin/sendmail/src/headers.c 3.40
SCCS-vsn: usr.sbin/sendmail/src/stats.c 3.5

21 files changed:
usr/src/usr.sbin/sendmail/src/alias.c
usr/src/usr.sbin/sendmail/src/clock.c
usr/src/usr.sbin/sendmail/src/collect.c
usr/src/usr.sbin/sendmail/src/conf.c
usr/src/usr.sbin/sendmail/src/convtime.c
usr/src/usr.sbin/sendmail/src/deliver.c
usr/src/usr.sbin/sendmail/src/err.c
usr/src/usr.sbin/sendmail/src/headers.c
usr/src/usr.sbin/sendmail/src/macro.c
usr/src/usr.sbin/sendmail/src/main.c
usr/src/usr.sbin/sendmail/src/parseaddr.c
usr/src/usr.sbin/sendmail/src/queue.c
usr/src/usr.sbin/sendmail/src/readcf.c
usr/src/usr.sbin/sendmail/src/recipient.c
usr/src/usr.sbin/sendmail/src/savemail.c
usr/src/usr.sbin/sendmail/src/sendmail.h
usr/src/usr.sbin/sendmail/src/srvrsmtp.c
usr/src/usr.sbin/sendmail/src/stats.c
usr/src/usr.sbin/sendmail/src/usersmtp.c
usr/src/usr.sbin/sendmail/src/util.c
usr/src/usr.sbin/sendmail/src/version.c

index 75bc406..8bbb91a 100644 (file)
@@ -5,17 +5,17 @@
 # include "sendmail.h"
 
 # ifdef DBM
 # include "sendmail.h"
 
 # ifdef DBM
-SCCSID(@(#)alias.c     3.41            %G%     (with DBM));
+SCCSID(@(#)alias.c     3.42            %G%     (with DBM));
 # else DBM
 # else DBM
-SCCSID(@(#)alias.c     3.41            %G%     (without DBM));
+SCCSID(@(#)alias.c     3.42            %G%     (without DBM));
 # endif DBM
 
 /*
 **  ALIAS -- Compute aliases.
 **
 # endif DBM
 
 /*
 **  ALIAS -- Compute aliases.
 **
-**     Scans the file /usr/lib/aliases for a set of aliases.
-**     If found, it arranges to deliver to them.  Uses libdbm
-**     database if -DDBM.
+**     Scans the alias file for an alias for the given address.
+**     If found, it arranges to deliver to the alias list instead.
+**     Uses libdbm database if -DDBM.
 **
 **     Parameters:
 **             a -- address to alias.
 **
 **     Parameters:
 **             a -- address to alias.
@@ -28,17 +28,6 @@ SCCSID(@(#)alias.c   3.41            %G%     (without DBM));
 **     Side Effects:
 **             Aliases found are expanded.
 **
 **     Side Effects:
 **             Aliases found are expanded.
 **
-**     Files:
-**             /usr/lib/aliases -- the mail aliases.  The format is
-**                     a series of lines of the form:
-**                             alias:name1,name2,name3,...
-**                     where 'alias' expands to all of
-**                     'name[i]'.  Continuations begin with
-**                     space or tab.
-**             /usr/lib/aliases.pag, /usr/lib/aliases.dir: libdbm version
-**                     of alias file.  Keys are aliases, datums
-**                     (data?) are name1,name2, ...
-**
 **     Notes:
 **             If NoAlias (the "-n" flag) is set, no aliasing is
 **                     done.
 **     Notes:
 **             If NoAlias (the "-n" flag) is set, no aliasing is
 **                     done.
@@ -46,7 +35,6 @@ SCCSID(@(#)alias.c    3.41            %G%     (without DBM));
 **     Deficiencies:
 **             It should complain about names that are aliased to
 **                     nothing.
 **     Deficiencies:
 **             It should complain about names that are aliased to
 **                     nothing.
-**             It is unsophisticated about line overflows.
 */
 
 
 */
 
 
@@ -165,11 +153,13 @@ initaliases(aliasfile, init)
        char *aliasfile;
        bool init;
 {
        char *aliasfile;
        bool init;
 {
+#ifdef DBM
        int atcnt;
        char buf[MAXNAME];
        int atcnt;
        char buf[MAXNAME];
-       struct stat stb;
        time_t modtime;
        int (*oldsigint)();
        time_t modtime;
        int (*oldsigint)();
+#endif DBM
+       struct stat stb;
 
        if (stat(aliasfile, &stb) < 0)
        {
 
        if (stat(aliasfile, &stb) < 0)
        {
@@ -205,7 +195,7 @@ initaliases(aliasfile, init)
        if (!init && (atcnt < 0 || stat(buf, &stb) < 0 || stb.st_mtime < modtime))
        {
                if (AutoRebuild && stb.st_ino != 0 &&
        if (!init && (atcnt < 0 || stat(buf, &stb) < 0 || stb.st_mtime < modtime))
        {
                if (AutoRebuild && stb.st_ino != 0 &&
-                   ((stb.st_mode & 0666) == 0666 || stb.st_uid == geteuid()))
+                   ((stb.st_mode & 0777) == 0666 || stb.st_uid == geteuid()))
                {
                        init = TRUE;
                        message(Arpa_Info, "rebuilding alias database");
                {
                        init = TRUE;
                        message(Arpa_Info, "rebuilding alias database");
@@ -235,6 +225,7 @@ initaliases(aliasfile, init)
                if (close(creat(buf, DBMMODE)) < 0)
                {
                        syserr("cannot make %s", buf);
                if (close(creat(buf, DBMMODE)) < 0)
                {
                        syserr("cannot make %s", buf);
+                       (void) signal(SIGINT, oldsigint);
                        return;
                }
                (void) strcpy(buf, aliasfile);
                        return;
                }
                (void) strcpy(buf, aliasfile);
@@ -242,6 +233,7 @@ initaliases(aliasfile, init)
                if (close(creat(buf, DBMMODE)) < 0)
                {
                        syserr("cannot make %s", buf);
                if (close(creat(buf, DBMMODE)) < 0)
                {
                        syserr("cannot make %s", buf);
+                       (void) signal(SIGINT, oldsigint);
                        return;
                }
        }
                        return;
                }
        }
@@ -289,16 +281,15 @@ readaliases(aliasfile, init)
        char *aliasfile;
        bool init;
 {
        char *aliasfile;
        bool init;
 {
-       char line[BUFSIZ];
        register char *p;
        char *p2;
        char *rhs;
        bool skipping;
        register char *p;
        char *p2;
        char *rhs;
        bool skipping;
-       ADDRESS al, bl;
+       int naliases, bytes, longest;
        FILE *af;
        FILE *af;
-       int lineno;
+       ADDRESS al, bl;
        register STAB *s;
        register STAB *s;
-       int naliases, bytes, longest;
+       char line[BUFSIZ];
 
        if ((af = fopen(aliasfile, "r")) == NULL)
        {
 
        if ((af = fopen(aliasfile, "r")) == NULL)
        {
@@ -315,14 +306,15 @@ readaliases(aliasfile, init)
        **  Read and interpret lines
        */
 
        **  Read and interpret lines
        */
 
-       lineno = 0;
+       FileName = aliasfile;
+       LineNumber = 0;
        naliases = bytes = longest = 0;
        skipping = FALSE;
        while (fgets(line, sizeof (line), af) != NULL)
        {
                int lhssize, rhssize;
 
        naliases = bytes = longest = 0;
        skipping = FALSE;
        while (fgets(line, sizeof (line), af) != NULL)
        {
                int lhssize, rhssize;
 
-               lineno++;
+               LineNumber++;
                switch (line[0])
                {
                  case '#':
                switch (line[0])
                {
                  case '#':
@@ -334,7 +326,7 @@ readaliases(aliasfile, init)
                  case ' ':
                  case '\t':
                        if (!skipping)
                  case ' ':
                  case '\t':
                        if (!skipping)
-                               syserr("aliases: %d: Non-continuation line starts with space", lineno);
+                               syserr("Non-continuation line starts with space");
                        skipping = TRUE;
                        continue;
                }
                        skipping = TRUE;
                        continue;
                }
@@ -353,7 +345,6 @@ readaliases(aliasfile, init)
                        continue;
                if (*p == '\0' || *p == '\n')
                {
                        continue;
                if (*p == '\0' || *p == '\n')
                {
-                syntaxerr:
                        syserr("%s, line %d: syntax error", aliasfile, lineno);
                        continue;
                }
                        syserr("%s, line %d: syntax error", aliasfile, lineno);
                        continue;
                }
@@ -361,7 +352,8 @@ readaliases(aliasfile, init)
                if (parse(line, &al, 1) == NULL)
                {
                        *--p = ':';
                if (parse(line, &al, 1) == NULL)
                {
                        *--p = ':';
-                       goto syntaxerr;
+                       syserr("illegal alias name");
+                       continue;
                }
 
                /*
                }
 
                /*
@@ -440,11 +432,11 @@ readaliases(aliasfile, init)
                        p--;
                        if (fgets(p, sizeof line - (p - line), af) == NULL)
                                break;
                        p--;
                        if (fgets(p, sizeof line - (p - line), af) == NULL)
                                break;
-                       lineno++;
+                       LineNumber++;
                }
                if (al.q_mailer != LocalMailer)
                {
                }
                if (al.q_mailer != LocalMailer)
                {
-                       syserr("aliases: %d: cannot alias non-local names", lineno);
+                       syserr("cannot alias non-local names");
                        continue;
                }
 
                        continue;
                }
 
@@ -481,6 +473,7 @@ readaliases(aliasfile, init)
        }
        (void) fclose(af);
        CurEnv->e_to = NULL;
        }
        (void) fclose(af);
        CurEnv->e_to = NULL;
+       FileName = NULL;
        message(Arpa_Info, "%d aliases, longest %d bytes, %d bytes total",
                        naliases, longest, bytes);
 }
        message(Arpa_Info, "%d aliases, longest %d bytes, %d bytes total",
                        naliases, longest, bytes);
 }
@@ -524,7 +517,7 @@ forward(user, sendq)
 # endif DEBUG
 
        /* good address -- look for .forward file in home */
 # endif DEBUG
 
        /* good address -- look for .forward file in home */
-       define('z', user->q_home);
+       define('z', user->q_home, CurEnv);
        expand("$z/.forward", buf, &buf[sizeof buf - 1], CurEnv);
        if (!safefile(buf, user->q_uid, S_IREAD))
                return;
        expand("$z/.forward", buf, &buf[sizeof buf - 1], CurEnv);
        if (!safefile(buf, user->q_uid, S_IREAD))
                return;
index a9f4429..58b6a21 100644 (file)
@@ -1,10 +1,13 @@
 # include "sendmail.h"
 
 # include "sendmail.h"
 
-SCCSID(@(#)clock.c     3.12            %G%);
+SCCSID(@(#)clock.c     3.13            %G%);
 
 /*
 **  SETEVENT -- set an event to happen at a specific time.
 **
 
 /*
 **  SETEVENT -- set an event to happen at a specific time.
 **
+**     Events are stored in a sorted list for fast processing.
+**     An event only applies to the process that set it.
+**
 **     Parameters:
 **             intvl -- intvl until next event occurs.
 **             func -- function to call on event.
 **     Parameters:
 **             intvl -- intvl until next event occurs.
 **             func -- function to call on event.
@@ -89,7 +92,7 @@ clrevent(ev)
                return;
 
        /* find the parent event */
                return;
 
        /* find the parent event */
-       signal(SIGALRM, SIG_IGN);
+       (void) signal(SIGALRM, SIG_IGN);
        for (evp = &EventQueue; *evp != NULL; evp = &(*evp)->ev_link)
        {
                if (*evp == ev)
        for (evp = &EventQueue; *evp != NULL; evp = &(*evp)->ev_link)
        {
                if (*evp == ev)
@@ -126,7 +129,8 @@ tick()
        register time_t now;
        register EVENT *ev;
 
        register time_t now;
        register EVENT *ev;
 
-       signal(SIGALRM, tick);
+       (void) signal(SIGALRM, SIG_IGN);
+       (void) alarm(0);
        now = curtime();
 
 # ifdef DEBUG
        now = curtime();
 
 # ifdef DEBUG
@@ -149,6 +153,7 @@ tick()
 # endif DEBUG
 
                /* we must be careful in here because ev_func may not return */
 # endif DEBUG
 
                /* we must be careful in here because ev_func may not return */
+               (void) signal(SIGALRM, tick);
                f = ev->ev_func;
                a = ev->ev_arg;
                free((char *) ev);
                f = ev->ev_func;
                a = ev->ev_arg;
                free((char *) ev);
@@ -165,6 +170,7 @@ tick()
                (void) alarm(0);
                now = curtime();
        }
                (void) alarm(0);
                now = curtime();
        }
+       (void) signal(SIGALRM, tick);
        if (EventQueue != NULL)
                (void) alarm(EventQueue->ev_time - now);
 }
        if (EventQueue != NULL)
                (void) alarm(EventQueue->ev_time - now);
 }
index eaa5ba1..9a3682b 100644 (file)
@@ -1,22 +1,14 @@
 # include <errno.h>
 # include "sendmail.h"
 
 # include <errno.h>
 # include "sendmail.h"
 
-SCCSID(@(#)collect.c   3.54            %G%);
+SCCSID(@(#)collect.c   3.55            %G%);
 
 /*
 **  COLLECT -- read & parse message header & make temp file.
 **
 **     Creates a temporary file name and copies the standard
 
 /*
 **  COLLECT -- read & parse message header & make temp file.
 **
 **     Creates a temporary file name and copies the standard
-**     input to that file.  While it is doing it, it looks for
-**     "From:" and "Sender:" fields to use as the from-person
-**     (but only if the -a flag is specified).  It prefers to
-**     to use the "Sender:" field.
-**
-**     MIT seems to like to produce "Sent-By:" fields instead
-**     of "Sender:" fields.  We used to catch this, but it turns
-**     out that the "Sent-By:" field doesn't always correspond
-**     to someone real ("___057", for instance), as required by
-**     the protocol.  So we limp by.....
+**     input to that file.  Leading UNIX-style "From" lines are
+**     stripped off (after important information is extracted).
 **
 **     Parameters:
 **             from -- the person we think it may be from.  If
 **
 **     Parameters:
 **             from -- the person we think it may be from.  If
@@ -86,7 +78,8 @@ maketemp(from)
        **      and prepended with ">" in the body.
        */
 
        **      and prepended with ">" in the body.
        */
 
-       for (; !feof(InChannel); !feof(InChannel) && fgets(buf, MAXFIELD, InChannel) != NULL)
+       for (; !feof(InChannel); !feof(InChannel) &&
+                                fgets(buf, MAXFIELD, InChannel) != NULL)
        {
                register char c;
                extern bool isheader();
        {
                register char c;
                extern bool isheader();
@@ -144,9 +137,9 @@ maketemp(from)
        **  Collect the body of the message.
        */
 
        **  Collect the body of the message.
        */
 
-       for (; !feof(InChannel); !feof(InChannel) && fgets(buf, sizeof buf, InChannel) != NULL)
+       for (; !feof(InChannel); !feof(InChannel) &&
+                                fgets(buf, sizeof buf, InChannel) != NULL)
        {
        {
-               register int i;
                register char *bp = buf;
 
                fixcrlf(buf, TRUE);
                register char *bp = buf;
 
                fixcrlf(buf, TRUE);
@@ -156,7 +149,7 @@ maketemp(from)
                        break;
 
                /* check for transparent dot */
                        break;
 
                /* check for transparent dot */
-               if (OpMode == MD_SMTP && *bp == '.')
+               if (OpMode == MD_SMTP && !IgnrDot && bp[0] == '.' && bp[1] == '.')
                        bp++;
 
 # ifndef NOTUNIX
                        bp++;
 
 # ifndef NOTUNIX
@@ -173,8 +166,7 @@ maketemp(from)
                **  file, and insert a newline if missing.
                */
 
                **  file, and insert a newline if missing.
                */
 
-               i = strlen(bp);
-               CurEnv->e_msgsize += i + 1;
+               CurEnv->e_msgsize += strlen(bp) + 1;
                fputs(bp, tf);
                fputs("\n", tf);
                if (ferror(tf))
                fputs(bp, tf);
                fputs("\n", tf);
                if (ferror(tf))
@@ -197,7 +189,7 @@ maketemp(from)
        **      Examples are who is the from person & the date.
        */
 
        **      Examples are who is the from person & the date.
        */
 
-       eatheader();
+       eatheader(CurEnv);
 
        /*
        **  Add an Apparently-To: line if we have no recipient lines.
 
        /*
        **  Add an Apparently-To: line if we have no recipient lines.
@@ -222,10 +214,6 @@ maketemp(from)
                }
        }
 
                }
        }
 
-       /* check for hop count overflow */
-       if (HopCount > MAXHOP)
-               syserr("Too many hops (%d max); probably forwarding loop", MAXHOP);
-
        if ((TempFile = fopen(CurEnv->e_df, "r")) == NULL)
                syserr("Cannot reopen %s", CurEnv->e_df);
 
        if ((TempFile = fopen(CurEnv->e_df, "r")) == NULL)
                syserr("Cannot reopen %s", CurEnv->e_df);
 
@@ -318,9 +306,9 @@ eatfrom(fm)
                q = xalloc(25);
                strncpy(q, p, 25);
                q[24] = '\0';
                q = xalloc(25);
                strncpy(q, p, 25);
                q[24] = '\0';
-               define('d', q);
+               define('d', q, CurEnv);
                q = arpadate(q);
                q = arpadate(q);
-               define('a', newstr(q));
+               define('a', newstr(q), CurEnv);
        }
 }
 
        }
 }
 
index 433becb..e69268a 100644 (file)
@@ -32,7 +32,7 @@
 
 
 
 
 
 
-SCCSID(@(#)conf.c      3.64            %G%);
+SCCSID(@(#)conf.c      3.65            %G%);
 \f/*
 **  Header info table
 **     Final (null) entry contains the flags used for any other field.
 \f/*
 **  Header info table
 **     Final (null) entry contains the flags used for any other field.
@@ -283,6 +283,29 @@ getrgid()
 
 # endif V6
 \f/*
 
 # endif V6
 \f/*
+**  USERNAME -- return the user id of the logged in user.
+**
+**     Parameters:
+**             none.
+**
+**     Returns:
+**             The login name of the logged in user.
+**
+**     Side Effects:
+**             none.
+**
+**     Notes:
+**             The return value is statically allocated.
+*/
+
+char *
+username()
+{
+       extern char *getlogin();
+
+       return (getlogin());
+}
+\f/*
 **  TTYPATH -- Get the path of the user's tty
 **
 **     Returns the pathname of the user's tty.  Returns NULL if
 **  TTYPATH -- Get the path of the user's tty
 **
 **     Returns the pathname of the user's tty.  Returns NULL if
@@ -317,7 +340,8 @@ ttypath()
        extern char *getlogin();
 
        /* compute the pathname of the controlling tty */
        extern char *getlogin();
 
        /* compute the pathname of the controlling tty */
-       if ((pathn = ttyname(2)) == NULL && (pathn = ttyname(1)) == NULL && (pathn = ttyname(0)) == NULL)
+       if ((pathn = ttyname(2)) == NULL && (pathn = ttyname(1)) == NULL &&
+           (pathn = ttyname(0)) == NULL)
        {
                errno = 0;
                return (NULL);
        {
                errno = 0;
                return (NULL);
@@ -379,7 +403,8 @@ checkcompat(to)
        }
 # ifdef ING70
        s = stab("arpa", ST_MAILER, ST_FIND);
        }
 # ifdef ING70
        s = stab("arpa", ST_MAILER, ST_FIND);
-       if (s != NULL && CurEnv->e_from.q_mailer != LocalMailer && to->q_mailer == s->s_mailer)
+       if (s != NULL && CurEnv->e_from.q_mailer != LocalMailer &&
+           to->q_mailer == s->s_mailer)
        {
                usrerr("No ARPA mail through this machine: see your system administration");
                return (FALSE);
        {
                usrerr("No ARPA mail through this machine: see your system administration");
                return (FALSE);
@@ -387,3 +412,37 @@ checkcompat(to)
 # endif ING70
        return (TRUE);
 }
 # endif ING70
        return (TRUE);
 }
+\f/*
+**  HOLDSIGS -- arrange to hold all signals
+**
+**     Parameters:
+**             none.
+**
+**     Returns:
+**             none.
+**
+**     Side Effects:
+**             Arranges that signals are held.
+*/
+
+holdsigs()
+{
+}
+\f/*
+**  RLSESIGS -- arrange to release all signals
+**
+**     This undoes the effect of holdsigs.
+**
+**     Parameters:
+**             none.
+**
+**     Returns:
+**             none.
+**
+**     Side Effects:
+**             Arranges that signals are released.
+*/
+
+rlsesigs()
+{
+}
index 0acf530..e7d3688 100644 (file)
@@ -1,7 +1,7 @@
 # include <ctype.h>
 # include "useful.h"
 
 # include <ctype.h>
 # include "useful.h"
 
-SCCSID(@(#)convtime.c  3.2             %G%);
+SCCSID(@(#)convtime.c  3.3             %G%);
 
 /*
 **  CONVTIME -- convert time
 
 /*
 **  CONVTIME -- convert time
@@ -13,6 +13,7 @@ SCCSID(@(#)convtime.c 3.2             %G%);
 **       h -- hours
 **       d -- days (default)
 **       w -- weeks
 **       h -- hours
 **       d -- days (default)
 **       w -- weeks
+**     For example, "3d12h" is three and a half days.
 **
 **     Parameters:
 **             p -- pointer to ascii time.
 **
 **     Parameters:
 **             p -- pointer to ascii time.
@@ -63,3 +64,94 @@ convtime(p)
 
        return (r);
 }
 
        return (r);
 }
+\f/*
+**  PINTVL -- produce printable version of a time interval
+**
+**     Parameters:
+**             intvl -- the interval to be converted
+**             brief -- if TRUE, print this in an extremely compact form
+**                     (basically used for logging).
+**
+**     Returns:
+**             A pointer to a string version of intvl suitable for
+**                     printing or framing.
+**
+**     Side Effects:
+**             none.
+**
+**     Warning:
+**             The string returned is in a static buffer.
+*/
+
+# define PLURAL(n)     ((n) == 1 ? "" : "s")
+
+char *
+pintvl(intvl, brief)
+       time_t intvl;
+       bool brief;
+{
+       static char buf[256];
+       register char *p;
+       int wk, dy, hr, mi, se;
+
+       if (intvl == 0 && !brief)
+               return ("zero seconds");
+
+       /* decode the interval into weeks, days, hours, minutes, seconds */
+       se = intvl % 60;
+       intvl /= 60;
+       mi = intvl % 60;
+       intvl /= 60;
+       hr = intvl % 24;
+       intvl /= 24;
+       if (brief)
+               dy = intvl;
+       else
+       {
+               dy = intvl % 7;
+               intvl /= 7;
+               wk = intvl;
+       }
+
+       /* now turn it into a sexy form */
+       p = buf;
+       if (brief)
+       {
+               if (dy > 0)
+               {
+                       (void) sprintf(p, "%d+", dy);
+                       p += strlen(p);
+               }
+               (void) sprintf(p, "%02d:%02d:%02d", hr, mi, se);
+               return (buf);
+       }
+
+       /* use the verbose form */
+       if (wk > 0)
+       {
+               (void) sprintf(p, ", %d week%s", wk, PLURAL(wk));
+               p += strlen(p);
+       }
+       if (dy > 0)
+       {
+               (void) sprintf(p, ", %d day%s", dy, PLURAL(dy));
+               p += strlen(p);
+       }
+       if (hr > 0)
+       {
+               (void) sprintf(p, ", %d hour%s", hr, PLURAL(hr));
+               p += strlen(p);
+       }
+       if (mi > 0)
+       {
+               (void) sprintf(p, ", %d minute%s", mi, PLURAL(mi));
+               p += strlen(p);
+       }
+       if (se > 0)
+       {
+               (void) sprintf(p, ", %d second%s", se, PLURAL(se));
+               p += strlen(p);
+       }
+
+       return (buf + 2);
+}
index 5d15ed8..7abb432 100644 (file)
@@ -3,7 +3,7 @@
 # include "sendmail.h"
 # include <sys/stat.h>
 
 # include "sendmail.h"
 # include <sys/stat.h>
 
-SCCSID(@(#)deliver.c   3.132           %G%);
+SCCSID(@(#)deliver.c   3.133           %G%);
 
 /*
 **  DELIVER -- Deliver a message to a list of addresses.
 
 /*
 **  DELIVER -- Deliver a message to a list of addresses.
@@ -16,6 +16,7 @@ SCCSID(@(#)deliver.c  3.132           %G%);
 **     list.
 **
 **     Parameters:
 **     list.
 **
 **     Parameters:
+**             e -- the envelope to deliver.
 **             firstto -- head of the address list to deliver to.
 **
 **     Returns:
 **             firstto -- head of the address list to deliver to.
 **
 **     Returns:
@@ -26,7 +27,8 @@ SCCSID(@(#)deliver.c  3.132           %G%);
 **             The standard input is passed off to someone.
 */
 
 **             The standard input is passed off to someone.
 */
 
-deliver(firstto)
+deliver(e, firstto)
+       register ENVELOPE *e;
        ADDRESS *firstto;
 {
        char *host;                     /* host being sent to */
        ADDRESS *firstto;
 {
        char *host;                     /* host being sent to */
@@ -34,7 +36,7 @@ deliver(firstto)
        char **pvp;
        register char **mvp;
        register char *p;
        char **pvp;
        register char **mvp;
        register char *p;
-       register struct mailer *m;      /* mailer for this recipient */
+       register MAILER *m;     /* mailer for this recipient */
        extern bool checkcompat();
        char *pv[MAXPV+1];
        char tobuf[MAXLINE-50];         /* text line of to people */
        extern bool checkcompat();
        char *pv[MAXPV+1];
        char tobuf[MAXLINE-50];         /* text line of to people */
@@ -46,7 +48,6 @@ deliver(firstto)
        register ADDRESS *to = firstto;
        bool clever = FALSE;            /* running user smtp to this mailer */
        ADDRESS *tochain = NULL;        /* chain of users in this mailer call */
        register ADDRESS *to = firstto;
        bool clever = FALSE;            /* running user smtp to this mailer */
        ADDRESS *tochain = NULL;        /* chain of users in this mailer call */
-       bool notopen = TRUE;            /* set if connection not quite open */
        register int rcode;             /* response code */
 
        errno = 0;
        register int rcode;             /* response code */
 
        errno = 0;
@@ -80,12 +81,12 @@ deliver(firstto)
                        if (bitset(QDONTSEND, to->q_flags) || to->q_mailer != m)
                                continue;
                        to->q_flags |= QQUEUEUP|QDONTSEND;
                        if (bitset(QDONTSEND, to->q_flags) || to->q_mailer != m)
                                continue;
                        to->q_flags |= QQUEUEUP|QDONTSEND;
-                       CurEnv->e_to = to->q_paddr;
+                       e->e_to = to->q_paddr;
                        message(Arpa_Info, "queued");
                        if (LogLevel > 4)
                                logdelivery("queued");
                }
                        message(Arpa_Info, "queued");
                        if (LogLevel > 4)
                                logdelivery("queued");
                }
-               CurEnv->e_to = NULL;
+               e->e_to = NULL;
                return (0);
        }
 
                return (0);
        }
 
@@ -101,13 +102,15 @@ deliver(firstto)
        */
 
        /* rewrite from address, using rewriting rules */
        */
 
        /* rewrite from address, using rewriting rules */
-       expand("$f", buf, &buf[sizeof buf - 1], CurEnv);
+       expand("$f", buf, &buf[sizeof buf - 1], e);
        mvp = prescan(buf, '\0');
        mvp = prescan(buf, '\0');
+       rewrite(mvp, 3);
+       rewrite(mvp, 1);
        rewrite(mvp, m->m_s_rwset);
        cataddr(mvp, tfrombuf, sizeof tfrombuf);
 
        rewrite(mvp, m->m_s_rwset);
        cataddr(mvp, tfrombuf, sizeof tfrombuf);
 
-       define('g', tfrombuf);          /* translated sender address */
-       define('h', host);              /* to host */
+       define('g', tfrombuf, e);               /* translated sender address */
+       define('h', host, e);                   /* to host */
        Errors = 0;
        pvp = pv;
        *pvp++ = m->m_argv[0];
        Errors = 0;
        pvp = pv;
        *pvp++ = m->m_argv[0];
@@ -119,7 +122,7 @@ deliver(firstto)
                        *pvp++ = "-f";
                else
                        *pvp++ = "-r";
                        *pvp++ = "-f";
                else
                        *pvp++ = "-r";
-               expand("$g", buf, &buf[sizeof buf - 1], CurEnv);
+               expand("$g", buf, &buf[sizeof buf - 1], e);
                *pvp++ = newstr(buf);
        }
 
                *pvp++ = newstr(buf);
        }
 
@@ -139,7 +142,7 @@ deliver(firstto)
                        break;
 
                /* this entry is safe -- go ahead and process it */
                        break;
 
                /* this entry is safe -- go ahead and process it */
-               expand(*mvp, buf, &buf[sizeof buf - 1], CurEnv);
+               expand(*mvp, buf, &buf[sizeof buf - 1], e);
                *pvp++ = newstr(buf);
                if (pvp >= &pv[MAXPV - 3])
                {
                *pvp++ = newstr(buf);
                if (pvp >= &pv[MAXPV - 3])
                {
@@ -175,7 +178,7 @@ deliver(firstto)
        */
 
        tobuf[0] = '\0';
        */
 
        tobuf[0] = '\0';
-       CurEnv->e_to = tobuf;
+       e->e_to = tobuf;
        ctladdr = NULL;
        for (; to != NULL; to = to->q_next)
        {
        ctladdr = NULL;
        for (; to != NULL; to = to->q_next)
        {
@@ -190,7 +193,7 @@ deliver(firstto)
                        continue;
 
                /* avoid overflowing tobuf */
                        continue;
 
                /* avoid overflowing tobuf */
-               if (sizeof tobuf - (strlen(to->q_paddr) + strlen(tobuf) + 1) < 0)
+               if (sizeof tobuf - (strlen(to->q_paddr) + strlen(tobuf) + 2) < 0)
                        break;
 
 # ifdef DEBUG
                        break;
 
 # ifdef DEBUG
@@ -206,7 +209,7 @@ deliver(firstto)
                        ctladdr = getctladdr(to);
 
                user = to->q_user;
                        ctladdr = getctladdr(to);
 
                user = to->q_user;
-               CurEnv->e_to = to->q_paddr;
+               e->e_to = to->q_paddr;
                to->q_flags |= QDONTSEND;
 
                /*
                to->q_flags |= QDONTSEND;
 
                /*
@@ -216,7 +219,7 @@ deliver(firstto)
 
                if (!checkcompat(to))
                {
 
                if (!checkcompat(to))
                {
-                       giveresponse(EX_UNAVAILABLE, TRUE, m);
+                       giveresponse(EX_UNAVAILABLE, m);
                        continue;
                }
 
                        continue;
                }
 
@@ -240,45 +243,6 @@ deliver(firstto)
                if (m == ProgMailer && *user == '|')
                        user++;
 
                if (m == ProgMailer && *user == '|')
                        user++;
 
-               /*
-               **  Do initial connection setup if needed.
-               */
-
-               if (notopen)
-               {
-                       message(Arpa_Info, "Connecting to %s.%s...", host, m->m_name);
-# ifdef SMTP
-                       if (clever)
-                       {
-                               /* send the initial SMTP protocol */
-                               rcode = smtpinit(m, pv, (ADDRESS *) NULL);
-                       }
-# ifdef SMTP
-                       notopen = FALSE;
-               }
-
-               /*
-               **  Pass it to the other host if we are running SMTP.
-               */
-
-               if (clever)
-               {
-# ifdef SMTP
-                       if (rcode == EX_OK)
-                               rcode = smtprcpt(to);
-                       if (rcode != EX_OK)
-                       {
-                               if (rcode == EX_TEMPFAIL)
-                                       to->q_flags |= QQUEUEUP;
-                               else
-                                       to->q_flags |= QBADADDR;
-                               giveresponse(rcode, TRUE, m);
-                       }
-# else SMTP
-                       syserr("trying to be clever");
-# endif SMTP
-               }
-
                /*
                **  If an error message has already been given, don't
                **      bother to send to this address.
                /*
                **  If an error message has already been given, don't
                **      bother to send to this address.
@@ -292,8 +256,7 @@ deliver(firstto)
                        continue;
 
                /* save statistics.... */
                        continue;
 
                /* save statistics.... */
-               Stat.stat_nt[to->q_mailer->m_mno]++;
-               Stat.stat_bt[to->q_mailer->m_mno] += kbytes(CurEnv->e_msgsize);
+               markstats(e, to);
 
                /*
                **  See if this user name is "special".
 
                /*
                **  See if this user name is "special".
@@ -308,7 +271,7 @@ deliver(firstto)
                        if (user[0] == '/')
                        {
                                rcode = mailfile(user, getctladdr(to));
                        if (user[0] == '/')
                        {
                                rcode = mailfile(user, getctladdr(to));
-                               giveresponse(rcode, TRUE, m);
+                               giveresponse(rcode, m);
                                continue;
                        }
                }
                                continue;
                        }
                }
@@ -326,8 +289,8 @@ deliver(firstto)
                if (tobuf[0] != '\0')
                        (void) strcat(tobuf, ",");
                (void) strcat(tobuf, to->q_paddr);
                if (tobuf[0] != '\0')
                        (void) strcat(tobuf, ",");
                (void) strcat(tobuf, to->q_paddr);
-               define('u', user);              /* to user */
-               define('z', to->q_home);        /* user's home */
+               define('u', user, e);           /* to user */
+               define('z', to->q_home, e);     /* user's home */
 
                /*
                **  Expand out this user into argument list.
 
                /*
                **  Expand out this user into argument list.
@@ -335,7 +298,7 @@ deliver(firstto)
 
                if (!clever)
                {
 
                if (!clever)
                {
-                       expand(*mvp, buf, &buf[sizeof buf - 1], CurEnv);
+                       expand(*mvp, buf, &buf[sizeof buf - 1], e);
                        *pvp++ = newstr(buf);
                        if (pvp >= &pv[MAXPV - 2])
                        {
                        *pvp++ = newstr(buf);
                        if (pvp >= &pv[MAXPV - 2])
                        {
@@ -348,16 +311,12 @@ deliver(firstto)
        /* see if any addresses still exist */
        if (tobuf[0] == '\0')
        {
        /* see if any addresses still exist */
        if (tobuf[0] == '\0')
        {
-# ifdef SMTP
-               if (clever && !notopen)
-                       smtpquit(pv[0], FALSE);
-# endif SMTP
-               define('g', (char *) NULL);
+               define('g', (char *) NULL, e);
                return (0);
        }
 
        /* print out messages as full list */
                return (0);
        }
 
        /* print out messages as full list */
-       CurEnv->e_to = tobuf;
+       e->e_to = tobuf;
 
        /*
        **  Fill out any parameters after the $u parameter.
 
        /*
        **  Fill out any parameters after the $u parameter.
@@ -365,7 +324,7 @@ deliver(firstto)
 
        while (!clever && *++mvp != NULL)
        {
 
        while (!clever && *++mvp != NULL)
        {
-               expand(*mvp, buf, &buf[sizeof buf - 1], CurEnv);
+               expand(*mvp, buf, &buf[sizeof buf - 1], e);
                *pvp++ = newstr(buf);
                if (pvp >= &pv[MAXPV])
                        syserr("deliver: pv overflow after $u for %s", pv[0]);
                *pvp++ = newstr(buf);
                if (pvp >= &pv[MAXPV])
                        syserr("deliver: pv overflow after $u for %s", pv[0]);
@@ -380,19 +339,45 @@ deliver(firstto)
        **      If we are running SMTP, we just need to clean up.
        */
 
        **      If we are running SMTP, we just need to clean up.
        */
 
+       message(Arpa_Info, "Connecting to %s.%s...", host, m->m_name);
+
        if (ctladdr == NULL)
        if (ctladdr == NULL)
-               ctladdr = &CurEnv->e_from;
+               ctladdr = &e->e_from;
 # ifdef SMTP
        if (clever)
        {
 # ifdef SMTP
        if (clever)
        {
-               rcode = smtpfinish(m, CurEnv);
+               /* send the initial SMTP protocol */
+               rcode = smtpinit(m, pv, (ADDRESS *) NULL);
+
+               /* send the recipient list */
+               for (to = tochain; to != NULL; to = to->q_tchain)
+               {
+                       int i;
+
+                       if (rcode == EX_OK)
+                               i = smtprcpt(to);
+                       else
+                               i = rcode;
+                       if (i != EX_OK)
+                       {
+                               if (i == EX_TEMPFAIL)
+                                       to->q_flags |= QQUEUEUP;
+                               else
+                                       to->q_flags |= QBADADDR;
+                               giveresponse(rcode, m);
+                       }
+               }
+
+               /* now send the closing protocol */
+               if (rcode == EX_OK)
+                       rcode = smtpfinish(m, e);
                if (rcode != EX_OK)
                if (rcode != EX_OK)
-                       giveresponse(rcode, TRUE, m);
+                       giveresponse(rcode, m);
                smtpquit(pv[0], rcode == EX_OK);
        }
        else
 # endif SMTP
                smtpquit(pv[0], rcode == EX_OK);
        }
        else
 # endif SMTP
-               rcode = sendoff(m, pv, ctladdr);
+               rcode = sendoff(e, m, pv, ctladdr);
 
        /*
        **  If we got a temporary failure, arrange to queue the
 
        /*
        **  If we got a temporary failure, arrange to queue the
@@ -406,7 +391,7 @@ deliver(firstto)
        }
 
        errno = 0;
        }
 
        errno = 0;
-       define('g', (char *) NULL);
+       define('g', (char *) NULL, e);
        return (rcode);
 }
 \f/*
        return (rcode);
 }
 \f/*
@@ -476,6 +461,7 @@ dofork()
 **  SENDOFF -- send off call to mailer & collect response.
 **
 **     Parameters:
 **  SENDOFF -- send off call to mailer & collect response.
 **
 **     Parameters:
+**             e -- the envelope to mail.
 **             m -- mailer descriptor.
 **             pvp -- parameter vector to send to it.
 **             ctladdr -- an address pointer controlling the
 **             m -- mailer descriptor.
 **             pvp -- parameter vector to send to it.
 **             ctladdr -- an address pointer controlling the
@@ -488,8 +474,9 @@ dofork()
 **             none.
 */
 
 **             none.
 */
 
-sendoff(m, pvp, ctladdr)
-       struct mailer *m;
+sendoff(e, m, pvp, ctladdr)
+       register ENVELOPE *e;
+       MAILER *m;
        char **pvp;
        ADDRESS *ctladdr;
 {
        char **pvp;
        ADDRESS *ctladdr;
 {
@@ -508,25 +495,28 @@ sendoff(m, pvp, ctladdr)
 
        /*
        **  Format and send message.
 
        /*
        **  Format and send message.
+       **      We ignore broken pipes so that the mailer need not read
+       **      its input if it is not convenient to do so (e.g., on
+       **      some error).
        */
 
        (void) signal(SIGPIPE, SIG_IGN);
        putfromline(mfile, m);
        */
 
        (void) signal(SIGPIPE, SIG_IGN);
        putfromline(mfile, m);
-       (*CurEnv->e_puthdr)(mfile, m, CurEnv);
+       (*e->e_puthdr)(mfile, m, e);
        fprintf(mfile, "\n");
        fprintf(mfile, "\n");
-       (*CurEnv->e_putbody)(mfile, m, FALSE);
+       (*e->e_putbody)(mfile, m, FALSE);
        (void) fclose(mfile);
 
        i = endmailer(pid, pvp[0]);
        (void) fclose(mfile);
 
        i = endmailer(pid, pvp[0]);
-       giveresponse(i, TRUE, m);
+       giveresponse(i, m);
 
        /* arrange a return receipt if requested */
 
        /* arrange a return receipt if requested */
-       if (CurEnv->e_receiptto != NULL && bitset(M_LOCAL, m->m_flags))
+       if (e->e_receiptto != NULL && bitset(M_LOCAL, m->m_flags))
        {
        {
-               CurEnv->e_flags |= EF_SENDRECEIPT;
+               e->e_flags |= EF_SENDRECEIPT;
                if (ExitStat == EX_OK && Xscript != NULL)
                        fprintf(Xscript, "%s... successfully delivered\n",
                if (ExitStat == EX_OK && Xscript != NULL)
                        fprintf(Xscript, "%s... successfully delivered\n",
-                               CurEnv->e_to);
+                               e->e_to);
                /* do we want to send back more info? */
        }
 
                /* do we want to send back more info? */
        }
 
@@ -555,36 +545,31 @@ endmailer(pid, name)
        int pid;
        char *name;
 {
        int pid;
        char *name;
 {
-       register int i;
-       auto int st;
+       int st;
 
        /* in the IPC case there is nothing to wait for */
        if (pid == 0)
                return (EX_OK);
 
        /* wait for the mailer process to die and collect status */
 
        /* in the IPC case there is nothing to wait for */
        if (pid == 0)
                return (EX_OK);
 
        /* wait for the mailer process to die and collect status */
-       do
-       {
-               errno = 0;
-               i = wait(&st);
-       } while ((i >= 0 && i != pid) || errno == EINTR);
-       if (i < 0)
+       st = waitfor(pid);
+       if (st == -1)
        {
        {
-               syserr("wait");
-               return (-1);
+               syserr("endmailer %s: wait", name);
+               return (EX_SOFTWARE);
        }
 
        /* see if it died a horrid death */
        if ((st & 0377) != 0)
        {
        }
 
        /* see if it died a horrid death */
        if ((st & 0377) != 0)
        {
-               syserr("%s: stat %o", name, st);
+               syserr("endmailer %s: stat %o", name, st);
                ExitStat = EX_UNAVAILABLE;
                ExitStat = EX_UNAVAILABLE;
-               return (-1);
+               return (EX_UNAVAILABLE);
        }
 
        /* normal death -- return status */
        }
 
        /* normal death -- return status */
-       i = (st >> 8) & 0377;
-       return (i);
+       st = (st >> 8) & 0377;
+       return (st);
 }
 \f/*
 **  OPENMAILER -- open connection to mailer.
 }
 \f/*
 **  OPENMAILER -- open connection to mailer.
@@ -607,7 +592,7 @@ endmailer(pid, name)
 */
 
 openmailer(m, pvp, ctladdr, clever, pmfile, prfile)
 */
 
 openmailer(m, pvp, ctladdr, clever, pmfile, prfile)
-       struct mailer *m;
+       MAILER *m;
        char **pvp;
        ADDRESS *ctladdr;
        bool clever;
        char **pvp;
        ADDRESS *ctladdr;
        bool clever;
@@ -630,7 +615,6 @@ openmailer(m, pvp, ctladdr, clever, pmfile, prfile)
 # endif DEBUG
        errno = 0;
 
 # endif DEBUG
        errno = 0;
 
-# ifdef DAEMON
        /*
        **  Deal with the special case of mail handled through an IPC
        **  connection.
        /*
        **  Deal with the special case of mail handled through an IPC
        **  connection.
@@ -641,6 +625,7 @@ openmailer(m, pvp, ctladdr, clever, pmfile, prfile)
 
        if (strcmp(m->m_mailer, "[IPC]") == 0)
        {
 
        if (strcmp(m->m_mailer, "[IPC]") == 0)
        {
+#ifdef DAEMON
                register int i;
                register u_short port;
 
                register int i;
                register u_short port;
 
@@ -658,26 +643,29 @@ openmailer(m, pvp, ctladdr, clever, pmfile, prfile)
                }
                else
                        return (0);
                }
                else
                        return (0);
+#else DAEMON
+               syserr("openmailer: no IPC");
+               return (-1);
+#endif DAEMON
        }
        }
-# endif DAEMON
 
        /* create a pipe to shove the mail through */
        if (pipe(mpvect) < 0)
        {
 
        /* create a pipe to shove the mail through */
        if (pipe(mpvect) < 0)
        {
-               syserr("pipe (to mailer)");
+               syserr("openmailer: pipe (to mailer)");
                return (-1);
        }
 
                return (-1);
        }
 
-# ifdef SMTP
+#ifdef SMTP
        /* if this mailer speaks smtp, create a return pipe */
        if (clever && pipe(rpvect) < 0)
        {
        /* if this mailer speaks smtp, create a return pipe */
        if (clever && pipe(rpvect) < 0)
        {
-               syserr("pipe (from mailer)");
+               syserr("openmailer: pipe (from mailer)");
                (void) close(mpvect[0]);
                (void) close(mpvect[1]);
                return (-1);
        }
                (void) close(mpvect[0]);
                (void) close(mpvect[1]);
                return (-1);
        }
-# endif SMTP
+#endif SMTP
 
        /*
        **  Actually fork the mailer process.
 
        /*
        **  Actually fork the mailer process.
@@ -686,19 +674,22 @@ openmailer(m, pvp, ctladdr, clever, pmfile, prfile)
 
        if (Xscript != NULL)
                (void) fflush(Xscript);                 /* for debugging */
 
        if (Xscript != NULL)
                (void) fflush(Xscript);                 /* for debugging */
+       (void) fflush(stdout);
        DOFORK(XFORK);
        /* pid is set by DOFORK */
        if (pid < 0)
        {
                /* failure */
        DOFORK(XFORK);
        /* pid is set by DOFORK */
        if (pid < 0)
        {
                /* failure */
-               syserr("Cannot fork");
+               syserr("openmailer: cannot fork");
                (void) close(mpvect[0]);
                (void) close(mpvect[1]);
                (void) close(mpvect[0]);
                (void) close(mpvect[1]);
+#ifdef SMTP
                if (clever)
                {
                        (void) close(rpvect[0]);
                        (void) close(rpvect[1]);
                }
                if (clever)
                {
                        (void) close(rpvect[0]);
                        (void) close(rpvect[1]);
                }
+#endif SMTP
                return (-1);
        }
        else if (pid == 0)
                return (-1);
        }
        else if (pid == 0)
@@ -719,6 +710,7 @@ openmailer(m, pvp, ctladdr, clever, pmfile, prfile)
                }
                else if (OpMode == MD_SMTP || HoldErrs)
                {
                }
                else if (OpMode == MD_SMTP || HoldErrs)
                {
+                       /* put mailer output in transcript */
                        (void) close(1);
                        (void) dup(fileno(Xscript));
                }
                        (void) close(1);
                        (void) dup(fileno(Xscript));
                }
@@ -747,7 +739,7 @@ openmailer(m, pvp, ctladdr, clever, pmfile, prfile)
                                (void) setuid(ctladdr->q_uid);
                        }
                }
                                (void) setuid(ctladdr->q_uid);
                        }
                }
-# ifndef VMUNIX
+
                /*
                **  We have to be careful with vfork - we can't mung up the
                **  memory but we don't want the mailer to inherit any extra
                /*
                **  We have to be careful with vfork - we can't mung up the
                **  memory but we don't want the mailer to inherit any extra
@@ -765,11 +757,7 @@ openmailer(m, pvp, ctladdr, clever, pmfile, prfile)
                **  so it will be closed automatically on the exec.
                */
 
                **  so it will be closed automatically on the exec.
                */
 
-               endpwent();
-# ifdef LOG
-               closelog();
-# endif LOG
-# endif VMUNIX
+               closeall();
 
                /* try to execute the mailer */
                execv(m->m_mailer, pvp);
 
                /* try to execute the mailer */
                execv(m->m_mailer, pvp);
@@ -805,9 +793,6 @@ openmailer(m, pvp, ctladdr, clever, pmfile, prfile)
 **             stat -- the status code from the mailer (high byte
 **                     only; core dumps must have been taken care of
 **                     already).
 **             stat -- the status code from the mailer (high byte
 **                     only; core dumps must have been taken care of
 **                     already).
-**             force -- if set, force an error message output, even
-**                     if the mailer seems to like to print its own
-**                     messages.
 **             m -- the mailer descriptor for this mailer.
 **
 **     Returns:
 **             m -- the mailer descriptor for this mailer.
 **
 **     Returns:
@@ -818,10 +803,10 @@ openmailer(m, pvp, ctladdr, clever, pmfile, prfile)
 **             ExitStat may be set.
 */
 
 **             ExitStat may be set.
 */
 
-giveresponse(stat, force, m)
+/*ARGSUSED*/
+giveresponse(stat, m)
        int stat;
        int stat;
-       bool force;
-       register struct mailer *m;
+       register MAILER *m;
 {
        register char *statmsg;
        extern char *SysExMsg[];
 {
        register char *statmsg;
        extern char *SysExMsg[];
@@ -834,40 +819,30 @@ giveresponse(stat, force, m)
        */
 
        i = stat - EX__BASE;
        */
 
        i = stat - EX__BASE;
-       if (i < 0 || i > N_SysEx)
-               statmsg = NULL;
+       if (stat == 0)
+               statmsg = "250 Sent";
+       else if (i < 0 || i > N_SysEx)
+       {
+               (void) sprintf(buf, "554 unknown mailer error %d", stat);
+               stat = EX_UNAVAILABLE;
+               statmsg = buf;
+       }
        else
                statmsg = SysExMsg[i];
        else
                statmsg = SysExMsg[i];
+
+       /*
+       **  Print the message as appropriate
+       */
+
        if (stat == 0)
        if (stat == 0)
-       {
-               statmsg = "250 sent";
                message(Arpa_Info, &statmsg[4]);
                message(Arpa_Info, &statmsg[4]);
-       }
        else if (stat == EX_TEMPFAIL)
        else if (stat == EX_TEMPFAIL)
-       {
                message(Arpa_Info, "deferred");
                message(Arpa_Info, "deferred");
-       }
        else
        {
                Errors++;
        else
        {
                Errors++;
+               usrerr(statmsg);
                CurEnv->e_flags |= EF_FATALERRS;
                CurEnv->e_flags |= EF_FATALERRS;
-               if (statmsg == NULL && m->m_badstat != 0)
-               {
-                       stat = m->m_badstat;
-                       i = stat - EX__BASE;
-# ifdef DEBUG
-                       if (i < 0 || i >= N_SysEx)
-                               syserr("Bad m_badstat %d", stat);
-                       else
-# endif DEBUG
-                               statmsg = SysExMsg[i];
-               }
-               if (statmsg == NULL)
-                       usrerr("unknown mailer response %d", stat);
-               else if (force || !bitset(M_QUIET, m->m_flags) || Verbose)
-                       usrerr(statmsg);
-               else if (Xscript != NULL)
-                       fprintf(Xscript, "%s\n", &statmsg[4]);
        }
 
        /*
        }
 
        /*
@@ -877,17 +852,9 @@ giveresponse(stat, force, m)
        **      that.
        */
 
        **      that.
        */
 
-       if (statmsg == NULL)
-       {
-               (void) sprintf(buf, "554 error %d", stat);
-               statmsg = buf;
-       }
-
-       /* log it in the system log */
        if (LogLevel > ((stat == 0 || stat == EX_TEMPFAIL) ? 3 : 2))
                logdelivery(&statmsg[4]);
 
        if (LogLevel > ((stat == 0 || stat == EX_TEMPFAIL) ? 3 : 2))
                logdelivery(&statmsg[4]);
 
-       /* set the exit status appropriately */
        if (stat != EX_TEMPFAIL)
                setstat(stat);
 }
        if (stat != EX_TEMPFAIL)
                setstat(stat);
 }
@@ -923,7 +890,7 @@ logdelivery(stat)
 **
 **     One of the ugliest hacks seen by human eyes is
 **     contained herein: UUCP wants those stupid
 **
 **     One of the ugliest hacks seen by human eyes is
 **     contained herein: UUCP wants those stupid
-**     "remote from <host>" lines.  Why oh why does a
+**     "emote from <host>" lines.  Why oh why does a
 **     well-meaning programmer such as myself have to
 **     deal with this kind of antique garbage????
 **
 **     well-meaning programmer such as myself have to
 **     deal with this kind of antique garbage????
 **
@@ -958,10 +925,12 @@ putfromline(fp, m)
                if (bang == NULL)
                        syserr("No ! in UUCP! (%s)", sys);
                else
                if (bang == NULL)
                        syserr("No ! in UUCP! (%s)", sys);
                else
+               {
                        *bang = '\0';
                        *bang = '\0';
-               expand("From $f  $d remote from $g\n", buf,
-                               &buf[sizeof buf - 1], CurEnv);
-               *bang = '!';
+                       expand("From $f  $d remote from $g\n", buf,
+                                       &buf[sizeof buf - 1], CurEnv);
+                       *bang = '!';
+               }
        }
        else
 # endif UGLYUUCP
        }
        else
 # endif UGLYUUCP
@@ -969,215 +938,6 @@ putfromline(fp, m)
        putline(buf, fp, bitset(M_FULLSMTP, m->m_flags));
 }
 \f/*
        putline(buf, fp, bitset(M_FULLSMTP, m->m_flags));
 }
 \f/*
-**  PUTHEADER -- put the header part of a message from the in-core copy
-**
-**     Parameters:
-**             fp -- file to put it on.
-**             m -- mailer to use.
-**             e -- envelope to use.
-**
-**     Returns:
-**             none.
-**
-**     Side Effects:
-**             none.
-*/
-
-putheader(fp, m, e)
-       register FILE *fp;
-       register struct mailer *m;
-       register ENVELOPE *e;
-{
-       char buf[BUFSIZ];
-       register HDR *h;
-       extern char *arpadate();
-       extern char *capitalize();
-       char obuf[MAXLINE];
-       bool fullsmtp = bitset(M_FULLSMTP, m->m_flags);
-
-       if (bitset(M_LOCAL, m->m_flags) && fullsmtp)
-               fprintf(fp, "Return-Path: <%s>\n", e->e_from);
-       for (h = e->e_header; h != NULL; h = h->h_link)
-       {
-               register char *p;
-
-               if (bitset(H_CHECK|H_ACHECK, h->h_flags) && !bitset(h->h_mflags, m->m_flags))
-                       continue;
-
-               p = h->h_value;
-               if (bitset(H_DEFAULT, h->h_flags))
-               {
-                       /* macro expand value if generated internally */
-                       expand(p, buf, &buf[sizeof buf], e);
-                       p = buf;
-               }
-               if (p == NULL || *p == '\0')
-                       continue;
-
-               if (bitset(H_FROM|H_RCPT, h->h_flags))
-               {
-                       /* address field */
-                       bool oldstyle = bitset(EF_OLDSTYLE, e->e_flags);
-
-                       if (bitset(H_FROM, h->h_flags))
-                               oldstyle = FALSE;
-                       commaize(h, p, fp, oldstyle, m);
-               }
-               else
-               {
-                       /* vanilla header line */
-                       (void) sprintf(obuf, "%s: %s\n", capitalize(h->h_field), p);
-                       putline(obuf, fp, fullsmtp);
-               }
-               h->h_flags |= H_USED;
-       }
-}
-\f/*
-**  COMMAIZE -- output a header field, making a comma-translated list.
-**
-**     Parameters:
-**             h -- the header field to output.
-**             p -- the value to put in it.
-**             fp -- file to put it to.
-**             oldstyle -- TRUE if this is an old style header.
-**             m -- a pointer to the mailer descriptor.  If NULL,
-**                     don't transform the name at all.
-**
-**     Returns:
-**             none.
-**
-**     Side Effects:
-**             outputs "p" to file "fp".
-*/
-
-commaize(h, p, fp, oldstyle, m)
-       register HDR *h;
-       register char *p;
-       FILE *fp;
-       bool oldstyle;
-       register MAILER *m;
-{
-       register char *obp;
-       int opos;
-       bool fullsmtp = FALSE;
-       bool firstone = TRUE;
-       char obuf[MAXLINE];
-
-       /*
-       **  Output the address list translated by the
-       **  mailer and with commas.
-       */
-
-# ifdef DEBUG
-       if (tTd(14, 2))
-               printf("commaize(%s: %s)\n", h->h_field, p);
-# endif DEBUG
-
-       if (m != NULL && bitset(M_FULLSMTP, m->m_flags))
-               fullsmtp = TRUE;
-
-       obp = obuf;
-       (void) sprintf(obp, "%s: ", capitalize(h->h_field));
-       opos = strlen(h->h_field) + 2;
-       obp += opos;
-
-       /*
-       **  Run through the list of values.
-       */
-
-       while (*p != '\0')
-       {
-               register char *name;
-               char savechar;
-               extern char *remotename();
-               extern char *DelimChar;         /* defined in prescan */
-
-               /*
-               **  Find the end of the name.  New style names
-               **  end with a comma, old style names end with
-               **  a space character.  However, spaces do not
-               **  necessarily delimit an old-style name -- at
-               **  signs mean keep going.
-               */
-
-               /* find end of name */
-               while (isspace(*p) || *p == ',')
-                       p++;
-               name = p;
-               for (;;)
-               {
-                       char *oldp;
-                       extern bool isatword();
-
-                       (void) prescan(p, oldstyle ? ' ' : ',');
-                       p = DelimChar;
-
-                       /* look to see if we have an at sign */
-                       oldp = p;
-                       while (*p != '\0' && isspace(*p))
-                               p++;
-
-                       if (*p != '@' && !isatword(p))
-                       {
-                               p = oldp;
-                               break;
-                       }
-                       p += *p == '@' ? 1 : 2;
-                       while (*p != '\0' && isspace(*p))
-                               p++;
-               }
-               /* at the end of one complete name */
-
-               /* strip off trailing white space */
-               while (p >= name && (isspace(*p) || *p == ',' || *p == '\0'))
-                       p--;
-               if (++p == name)
-                       continue;
-               savechar = *p;
-               *p = '\0';
-
-               /* translate the name to be relative */
-               if (m != NULL)
-                       name = remotename(name, m, bitset(H_FROM, h->h_flags));
-               if (*name == '\0')
-               {
-                       *p = savechar;
-                       continue;
-               }
-
-               /* output the name with nice formatting */
-               opos += qstrlen(name);
-               if (!firstone)
-                       opos += 2;
-               if (opos > 78 && !firstone)
-               {
-                       (void) sprintf(obp, ",\n");
-                       putline(obuf, fp, fullsmtp);
-                       obp = obuf;
-                       (void) sprintf(obp, "        ");
-                       obp += strlen(obp);
-                       opos = 8 + strlen(name);
-               }
-               else if (!firstone)
-               {
-                       (void) sprintf(obp, ", ");
-                       obp += 2;
-               }
-
-               /* strip off quote bits as we output */
-               while (*name != '\0')
-               {
-                       if (bitset(0200, *name))
-                               *obp++ = '\\';
-                       *obp++ = *name++ & ~0200;
-               }
-               firstone = FALSE;
-               *p = savechar;
-       }
-       (void) strcpy(obp, "\n");
-       putline(obuf, fp, fullsmtp);
-}
-\f/*
 **  PUTBODY -- put the body of a message.
 **
 **     Parameters:
 **  PUTBODY -- put the body of a message.
 **
 **     Parameters:
@@ -1194,7 +954,7 @@ commaize(h, p, fp, oldstyle, m)
 
 putbody(fp, m, xdot)
        FILE *fp;
 
 putbody(fp, m, xdot)
        FILE *fp;
-       struct mailer *m;
+       MAILER *m;
        bool xdot;
 {
        char buf[MAXLINE + 1];
        bool xdot;
 {
        char buf[MAXLINE + 1];
@@ -1204,12 +964,6 @@ putbody(fp, m, xdot)
        **  Output the body of the message
        */
 
        **  Output the body of the message
        */
 
-#ifdef lint
-       /* m will be needed later for complete smtp emulation */
-       if (m == NULL)
-               return;
-#endif lint
-
        if (TempFile != NULL)
        {
                rewind(TempFile);
        if (TempFile != NULL)
        {
                rewind(TempFile);
@@ -1233,31 +987,6 @@ putbody(fp, m, xdot)
        errno = 0;
 }
 \f/*
        errno = 0;
 }
 \f/*
-**  ISATWORD -- tell if the word we are pointing to is "at".
-**
-**     Parameters:
-**             p -- word to check.
-**
-**     Returns:
-**             TRUE -- if p is the word at.
-**             FALSE -- otherwise.
-**
-**     Side Effects:
-**             none.
-*/
-
-bool
-isatword(p)
-       register char *p;
-{
-       extern char lower();
-
-       if (lower(p[0]) == 'a' && lower(p[1]) == 't' &&
-           p[2] != '\0' && isspace(p[2]))
-               return (TRUE);
-       return (FALSE);
-}
-\f/*
 **  MAILFILE -- Send a message to a file.
 **
 **     If the file has the setuid/setgid bits set, but NO execute
 **  MAILFILE -- Send a message to a file.
 **
 **     If the file has the setuid/setgid bits set, but NO execute
@@ -1265,6 +994,12 @@ isatword(p)
 **     rather than the real user.  Obviously, this only works if
 **     sendmail runs as root.
 **
 **     rather than the real user.  Obviously, this only works if
 **     sendmail runs as root.
 **
+**     This could be done as a subordinate mailer, except that it
+**     is used implicitly to save messages in ~/dead.letter.  We
+**     view this as being sufficiently important as to include it
+**     here.  For example, if the system is dying, we shouldn't have
+**     to create another process plus some pipes to save the message.
+**
 **     Parameters:
 **             filename -- the name of the file to send to.
 **             ctladdr -- the controlling address header -- includes
 **     Parameters:
 **             filename -- the name of the file to send to.
 **             ctladdr -- the controlling address header -- includes
@@ -1327,10 +1062,10 @@ mailfile(filename, ctladdr)
                if (f == NULL)
                        exit(EX_CANTCREAT);
 
                if (f == NULL)
                        exit(EX_CANTCREAT);
 
-               putfromline(f, Mailer[1]);
-               (*CurEnv->e_puthdr)(f, Mailer[1], CurEnv);
+               putfromline(f, ProgMailer);
+               (*CurEnv->e_puthdr)(f, ProgMailer, CurEnv);
                fputs("\n", f);
                fputs("\n", f);
-               (*CurEnv->e_putbody)(f, Mailer[1], FALSE);
+               (*CurEnv->e_putbody)(f, ProgMailer, FALSE);
                fputs("\n", f);
                (void) fclose(f);
                (void) fflush(stdout);
                fputs("\n", f);
                (void) fclose(f);
                (void) fflush(stdout);
@@ -1343,20 +1078,13 @@ mailfile(filename, ctladdr)
        else
        {
                /* parent -- wait for exit status */
        else
        {
                /* parent -- wait for exit status */
-               register int i;
-               auto int stat;
+               int st;
 
 
-               while ((i = wait(&stat)) != pid)
-               {
-                       if (i < 0)
-                       {
-                               stat = EX_OSERR << 8;
-                               break;
-                       }
-               }
-               if ((stat & 0377) != 0)
-                       stat = EX_UNAVAILABLE << 8;
-               return ((stat >> 8) & 0377);
+               st = waitfor(pid);
+               if ((st & 0377) != 0)
+                       return (EX_UNAVAILABLE);
+               else
+                       return ((st >> 8) & 0377);
        }
 }
 \f/*
        }
 }
 \f/*
@@ -1384,39 +1112,39 @@ sendall(e, mode)
        bool oldverbose;
        int pid;
 
        bool oldverbose;
        int pid;
 
-# ifdef DEBUG
+#ifdef DEBUG
        if (tTd(13, 1))
        {
                printf("\nSENDALL: mode %c, sendqueue:\n", mode);
                printaddr(e->e_sendqueue, TRUE);
        }
        if (tTd(13, 1))
        {
                printf("\nSENDALL: mode %c, sendqueue:\n", mode);
                printaddr(e->e_sendqueue, TRUE);
        }
-# endif DEBUG
+#endif DEBUG
 
        /*
        **  Do any preprocessing necessary for the mode we are running.
 
        /*
        **  Do any preprocessing necessary for the mode we are running.
+       **      Check to make sure the hop count is reasonable.
+       **      Delete sends to the sender in mailing lists.
        */
 
        */
 
-# ifdef QUEUE
-       if (mode == SM_QUEUE)
+       CurEnv = e;
+
+       if (e->e_hopcount > MAXHOP)
        {
        {
-               register ADDRESS *q;
+               syserr("sendall: too many hops (%d max)", MAXHOP);
+               return;
+       }
 
 
-               for (q = e->e_sendqueue; q != NULL; q = q->q_next)
-               {
-                       if (!bitset(QDONTSEND, q->q_flags))
-                       {
-                               e->e_to = q->q_paddr;
-                               message(Arpa_Info, "queued");
-                               if (LogLevel > 4)
-                                       logdelivery("queued");
-                       }
-                       e->e_to = NULL;
-               }
+       if (!MeToo)
+       {
+               e->e_from.q_flags |= QDONTSEND;
+               recipient(&e->e_from, &e->e_sendqueue);
        }
        }
+
+# ifdef QUEUE
        if ((mode == SM_QUEUE || mode == SM_FORK ||
             (mode != SM_VERIFY && SuperSafe)) &&
            !bitset(EF_INQUEUE, e->e_flags))
        if ((mode == SM_QUEUE || mode == SM_FORK ||
             (mode != SM_VERIFY && SuperSafe)) &&
            !bitset(EF_INQUEUE, e->e_flags))
-               queueup(e, TRUE);
+               queueup(e, TRUE, mode == SM_QUEUE);
 #endif QUEUE
 
        oldverbose = Verbose;
 #endif QUEUE
 
        oldverbose = Verbose;
@@ -1469,7 +1197,7 @@ sendall(e, mode)
                                message(Arpa_Info, "deliverable");
                }
                else
                                message(Arpa_Info, "deliverable");
                }
                else
-                       (void) deliver(q);
+                       (void) deliver(e, q);
        }
        Verbose = oldverbose;
 
        }
        Verbose = oldverbose;
 
@@ -1521,9 +1249,8 @@ sendall(e, mode)
 # endif DEBUG
 
                        /* owner list exists -- add it to the error queue */
 # endif DEBUG
 
                        /* owner list exists -- add it to the error queue */
-                       qq->q_flags &= ~QPRIMARY;
-                       sendto(obuf, qq, &e->e_errorqueue);
-                       MailBack = TRUE;
+                       sendto(obuf, (ADDRESS *) NULL, &e->e_errorqueue);
+                       ErrorMode == EM_MAIL;
                        break;
                }
 
                        break;
                }
 
@@ -1535,32 +1262,3 @@ sendall(e, mode)
        if (mode == SM_FORK)
                finis();
 }
        if (mode == SM_FORK)
                finis();
 }
-\f/*
-**  CHECKERRORS -- check a queue of addresses and process errors.
-**
-**     Parameters:
-**             e -- the envelope to check.
-**
-**     Returns:
-**             none.
-**
-**     Side Effects:
-**             Arranges to queue all tempfailed messages in q
-**                     or deliver error responses.
-*/
-
-checkerrors(e)
-       register ENVELOPE *e;
-{
-# ifdef DEBUG
-       if (tTd(4, 1))
-       {
-               printf("\ncheckerrors: e_flags %o, errorqueue:\n", e->e_flags);
-               printaddr(e->e_errorqueue, TRUE);
-       }
-# endif DEBUG
-
-       /* mail back the transcript on errors */
-       if (bitset(EF_FATALERRS, e->e_flags))
-               savemail(e);
-}
index 2686460..88ca458 100644 (file)
@@ -1,6 +1,6 @@
 # include "sendmail.h"
 
 # include "sendmail.h"
 
-SCCSID(@(#)err.c       3.35            %G%);
+SCCSID(@(#)err.c       3.36            %G%);
 
 /*
 **  SYSERR -- Print error message.
 
 /*
 **  SYSERR -- Print error message.
@@ -52,6 +52,7 @@ syserr(fmt, a, b, c, d, e)
                        ExitStat = EX_OSERR;
        }
 
                        ExitStat = EX_OSERR;
        }
 
+       /* insure that we have a queue id for logging */
        (void) queuename(CurEnv, '\0');
 # ifdef LOG
        if (LogLevel > 0)
        (void) queuename(CurEnv, '\0');
 # ifdef LOG
        if (LogLevel > 0)
@@ -233,6 +234,13 @@ fmtmsg(eb, to, num, fmt, a, b, c, d, e)
        (void) sprintf(eb, "%3.3s%c", num, del);
        eb += 4;
 
        (void) sprintf(eb, "%3.3s%c", num, del);
        eb += 4;
 
+       /* output the file name and line number */
+       if (FileName != NULL)
+       {
+               (void) sprintf(eb, "%s: line %d: ", FileName, LineNumber);
+               eb += strlen(eb);
+       }
+
        /* output the "to" person */
        if (to != NULL && to[0] != '\0')
        {
        /* output the "to" person */
        if (to != NULL && to[0] != '\0')
        {
index 5e82f59..698d974 100644 (file)
@@ -1,7 +1,7 @@
 # include <errno.h>
 # include "sendmail.h"
 
 # include <errno.h>
 # include "sendmail.h"
 
-SCCSID(@(#)headers.c   3.39            %G%);
+SCCSID(@(#)headers.c   3.40            %G%);
 
 /*
 **  CHOMPHEADER -- process and save a header line.
 
 /*
 **  CHOMPHEADER -- process and save a header line.
@@ -74,7 +74,8 @@ chompheader(line, def)
                fvalue++;
 
        /* search header list for this header */
                fvalue++;
 
        /* search header list for this header */
-       for (hp = &CurEnv->e_header, h = CurEnv->e_header; h != NULL; hp = &h->h_link, h = h->h_link)
+       for (hp = &CurEnv->e_header, h = CurEnv->e_header; h != NULL;
+               hp = &h->h_link, h = h->h_link)
        {
                if (strcmp(fname, h->h_field) == 0 && bitset(H_DEFAULT, h->h_flags))
                        break;
        {
                if (strcmp(fname, h->h_field) == 0 && bitset(H_DEFAULT, h->h_flags))
                        break;
@@ -91,10 +92,6 @@ chompheader(line, def)
        if (bitset(H_EOH, hi->hi_flags))
                return (hi->hi_flags);
 
        if (bitset(H_EOH, hi->hi_flags))
                return (hi->hi_flags);
 
-       /* count Received: lines to avoid loops (simulate hop counts) */
-       if (bitset(H_TRACE, hi->hi_flags))
-               HopCount++;
-
        /* create/fill in a new node */
        if (h == NULL || bitset(H_FORCE, h->h_flags))
        {
        /* create/fill in a new node */
        if (h == NULL || bitset(H_FORCE, h->h_flags))
        {
@@ -192,7 +189,7 @@ addheader(field, value, e)
 **             NULL if not found.
 **
 **     Side Effects:
 **             NULL if not found.
 **
 **     Side Effects:
-**             sets the H_USED bit in the header if found.
+**             none.
 */
 
 char *
 */
 
 char *
@@ -204,10 +201,7 @@ hvalue(field)
        for (h = CurEnv->e_header; h != NULL; h = h->h_link)
        {
                if (!bitset(H_DEFAULT, h->h_flags) && strcmp(h->h_field, field) == 0)
        for (h = CurEnv->e_header; h != NULL; h = h->h_link)
        {
                if (!bitset(H_DEFAULT, h->h_flags) && strcmp(h->h_field, field) == 0)
-               {
-                       h->h_flags |= H_USED;
                        return (h->h_value);
                        return (h->h_value);
-               }
        }
        return (NULL);
 }
        }
        return (NULL);
 }
@@ -232,65 +226,77 @@ bool
 isheader(s)
        register char *s;
 {
 isheader(s)
        register char *s;
 {
-       if (!isalnum(*s))
-               return (FALSE);
-       while (!isspace(*s) && *s != ':' && *s != '\0')
+       while (*s > ' ' && *s != ':' && *s != '\0')
                s++;
                s++;
+
+       /* following technically violates RFC822 */
        while (isspace(*s))
                s++;
        while (isspace(*s))
                s++;
+
        return (*s == ':');
 }
 \f/*
 **  EATHEADER -- run through the stored header and extract info.
 **
 **     Parameters:
        return (*s == ':');
 }
 \f/*
 **  EATHEADER -- run through the stored header and extract info.
 **
 **     Parameters:
-**             none.
+**             e -- the envelope to process.
 **
 **     Returns:
 **             none.
 **
 **     Side Effects:
 **             Sets a bunch of global variables from information
 **
 **     Returns:
 **             none.
 **
 **     Side Effects:
 **             Sets a bunch of global variables from information
-**             in the collected header.
+**                     in the collected header.
+**             Aborts the message if the hop count is exceeded.
 */
 
 */
 
-eatheader()
+eatheader(e)
+       register ENVELOPE *e;
 {
        register HDR *h;
        register char *p;
 {
        register HDR *h;
        register char *p;
+       int hopcnt = 0;
 
 
-# ifdef DEBUG
-       if (tTd(32, 2))
+#ifdef DEBUG
+       if (tTd(32, 1))
+               printf("----- collected header -----\n");
+#endif DEBUG
+       for (h = e->e_header; h != NULL; h = h->h_link)
        {
        {
+#ifdef DEBUG
                extern char *capitalize();
 
                extern char *capitalize();
 
-               printf("----- collected header -----\n");
-               for (h = CurEnv->e_header; h != NULL; h = h->h_link)
+               if (tTd(32, 1))
                        printf("%s: %s\n", capitalize(h->h_field), h->h_value);
                        printf("%s: %s\n", capitalize(h->h_field), h->h_value);
-               printf("----------------------------\n");
+#endif DEBUG
+               if (bitset(H_TRACE, h->h_flags))
+                       hopcnt++;
        }
        }
-# endif DEBUG
+#ifdef DEBUG
+       if (tTd(32, 1))
+               printf("----------------------------\n");
+#endif DEBUG
+
+       /* store hop count */
+       if (hopcnt > e->e_hopcount)
+               e->e_hopcount = hopcnt;
 
        /* message priority */
 
        /* message priority */
+       p = hvalue("precedence");
+       if (p != NULL)
+               e->e_class = priencode(p);
        if (!QueueRun)
        if (!QueueRun)
-       {
-               /* adjust total priority by message priority */
-               CurEnv->e_msgpriority = CurEnv->e_msgsize;
-               p = hvalue("precedence");
-               if (p != NULL)
-                       CurEnv->e_class = priencode(p);
-               CurEnv->e_msgpriority -= CurEnv->e_class * WKPRIFACT;
-       }
+               e->e_msgpriority = e->e_msgsize - e->e_class * WKPRIFACT;
 
        /* return receipt to */
        p = hvalue("return-receipt-to");
        if (p != NULL)
 
        /* return receipt to */
        p = hvalue("return-receipt-to");
        if (p != NULL)
-               CurEnv->e_receiptto = p;
+               e->e_receiptto = p;
 
        /* errors to */
        p = hvalue("errors-to");
        if (p != NULL)
 
        /* errors to */
        p = hvalue("errors-to");
        if (p != NULL)
-               sendto(p, (ADDRESS *) NULL, &CurEnv->e_errorqueue);
+               sendto(p, (ADDRESS *) NULL, &e->e_errorqueue);
 
        /* from person */
        if (OpMode == MD_ARPAFTP)
 
        /* from person */
        if (OpMode == MD_ARPAFTP)
@@ -303,13 +309,13 @@ eatheader()
                                p = hvalue(hi->hi_field);
                }
                if (p != NULL)
                                p = hvalue(hi->hi_field);
                }
                if (p != NULL)
-                       setfrom(p, (char *) NULL);
+                       setsender(p);
        }
 
        /* full name of from person */
        p = hvalue("full-name");
        if (p != NULL)
        }
 
        /* full name of from person */
        p = hvalue("full-name");
        if (p != NULL)
-               define('x', p);
+               define('x', p, e);
 
        /* date message originated */
        p = hvalue("posted-date");
 
        /* date message originated */
        p = hvalue("posted-date");
@@ -317,9 +323,9 @@ eatheader()
                p = hvalue("date");
        if (p != NULL)
        {
                p = hvalue("date");
        if (p != NULL)
        {
-               define('a', p);
+               define('a', p, e);
                /* we don't have a good way to do canonical conversion ....
                /* we don't have a good way to do canonical conversion ....
-               define('d', newstr(arpatounix(p)));
+               define('d', newstr(arpatounix(p)), e);
                .... so we will ignore the problem for the time being */
        }
 }
                .... so we will ignore the problem for the time being */
        }
 }
@@ -525,3 +531,236 @@ crackaddr(addr)
 
        return (buf);
 }
 
        return (buf);
 }
+\f/*
+**  PUTHEADER -- put the header part of a message from the in-core copy
+**
+**     Parameters:
+**             fp -- file to put it on.
+**             m -- mailer to use.
+**             e -- envelope to use.
+**
+**     Returns:
+**             none.
+**
+**     Side Effects:
+**             none.
+*/
+
+putheader(fp, m, e)
+       register FILE *fp;
+       register MAILER *m;
+       register ENVELOPE *e;
+{
+       char buf[BUFSIZ];
+       register HDR *h;
+       extern char *arpadate();
+       extern char *capitalize();
+       char obuf[MAXLINE];
+       bool fullsmtp = bitset(M_FULLSMTP, m->m_flags);
+
+       for (h = e->e_header; h != NULL; h = h->h_link)
+       {
+               register char *p;
+
+               if (bitset(H_CHECK|H_ACHECK, h->h_flags) &&
+                   !bitset(h->h_mflags, m->m_flags))
+                       continue;
+
+               p = h->h_value;
+               if (bitset(H_DEFAULT, h->h_flags))
+               {
+                       /* macro expand value if generated internally */
+                       expand(p, buf, &buf[sizeof buf], e);
+                       p = buf;
+                       if (p == NULL || *p == '\0')
+                               continue;
+               }
+
+               if (bitset(H_FROM|H_RCPT, h->h_flags))
+               {
+                       /* address field */
+                       bool oldstyle = bitset(EF_OLDSTYLE, e->e_flags);
+
+                       if (bitset(H_FROM, h->h_flags))
+                               oldstyle = FALSE;
+                       commaize(h, p, fp, oldstyle, m);
+               }
+               else
+               {
+                       /* vanilla header line */
+                       (void) sprintf(obuf, "%s: %s\n", capitalize(h->h_field), p);
+                       putline(obuf, fp, fullsmtp);
+               }
+       }
+}
+\f/*
+**  COMMAIZE -- output a header field, making a comma-translated list.
+**
+**     Parameters:
+**             h -- the header field to output.
+**             p -- the value to put in it.
+**             fp -- file to put it to.
+**             oldstyle -- TRUE if this is an old style header.
+**             m -- a pointer to the mailer descriptor.  If NULL,
+**                     don't transform the name at all.
+**
+**     Returns:
+**             none.
+**
+**     Side Effects:
+**             outputs "p" to file "fp".
+*/
+
+commaize(h, p, fp, oldstyle, m)
+       register HDR *h;
+       register char *p;
+       FILE *fp;
+       bool oldstyle;
+       register MAILER *m;
+{
+       register char *obp;
+       int opos;
+       bool fullsmtp = FALSE;
+       bool firstone = TRUE;
+       char obuf[MAXLINE];
+
+       /*
+       **  Output the address list translated by the
+       **  mailer and with commas.
+       */
+
+# ifdef DEBUG
+       if (tTd(14, 2))
+               printf("commaize(%s: %s)\n", h->h_field, p);
+# endif DEBUG
+
+       if (m != NULL && bitset(M_FULLSMTP, m->m_flags))
+               fullsmtp = TRUE;
+
+       obp = obuf;
+       (void) sprintf(obp, "%s: ", capitalize(h->h_field));
+       opos = strlen(h->h_field) + 2;
+       obp += opos;
+
+       /*
+       **  Run through the list of values.
+       */
+
+       while (*p != '\0')
+       {
+               register char *name;
+               char savechar;
+               extern char *remotename();
+               extern char *DelimChar;         /* defined in prescan */
+
+               /*
+               **  Find the end of the name.  New style names
+               **  end with a comma, old style names end with
+               **  a space character.  However, spaces do not
+               **  necessarily delimit an old-style name -- at
+               **  signs mean keep going.
+               */
+
+               /* find end of name */
+               while (isspace(*p) || *p == ',')
+                       p++;
+               name = p;
+               for (;;)
+               {
+                       char *oldp;
+                       extern bool isatword();
+                       extern char **prescan();
+
+                       (void) prescan(p, oldstyle ? ' ' : ',');
+                       p = DelimChar;
+
+                       /* look to see if we have an at sign */
+                       oldp = p;
+                       while (*p != '\0' && isspace(*p))
+                               p++;
+
+                       if (*p != '@' && !isatword(p))
+                       {
+                               p = oldp;
+                               break;
+                       }
+                       p += *p == '@' ? 1 : 2;
+                       while (*p != '\0' && isspace(*p))
+                               p++;
+               }
+               /* at the end of one complete name */
+
+               /* strip off trailing white space */
+               while (p >= name && (isspace(*p) || *p == ',' || *p == '\0'))
+                       p--;
+               if (++p == name)
+                       continue;
+               savechar = *p;
+               *p = '\0';
+
+               /* translate the name to be relative */
+               if (m != NULL)
+                       name = remotename(name, m, bitset(H_FROM, h->h_flags));
+               if (*name == '\0')
+               {
+                       *p = savechar;
+                       continue;
+               }
+
+               /* output the name with nice formatting */
+               opos += qstrlen(name);
+               if (!firstone)
+                       opos += 2;
+               if (opos > 78 && !firstone)
+               {
+                       (void) sprintf(obp, ",\n");
+                       putline(obuf, fp, fullsmtp);
+                       obp = obuf;
+                       (void) sprintf(obp, "        ");
+                       obp += strlen(obp);
+                       opos = 8 + strlen(name);
+               }
+               else if (!firstone)
+               {
+                       (void) sprintf(obp, ", ");
+                       obp += 2;
+               }
+
+               /* strip off quote bits as we output */
+               while (*name != '\0')
+               {
+                       if (bitset(0200, *name))
+                               *obp++ = '\\';
+                       *obp++ = *name++ & ~0200;
+               }
+               firstone = FALSE;
+               *p = savechar;
+       }
+       (void) strcpy(obp, "\n");
+       putline(obuf, fp, fullsmtp);
+}
+\f/*
+**  ISATWORD -- tell if the word we are pointing to is "at".
+**
+**     Parameters:
+**             p -- word to check.
+**
+**     Returns:
+**             TRUE -- if p is the word at.
+**             FALSE -- otherwise.
+**
+**     Side Effects:
+**             none.
+*/
+
+bool
+isatword(p)
+       register char *p;
+{
+       extern char lower();
+
+       if (lower(p[0]) == 'a' && lower(p[1]) == 't' &&
+           p[2] != '\0' && isspace(p[2]))
+               return (TRUE);
+       return (FALSE);
+}
index 0dcd1f4..88e0f4f 100644 (file)
@@ -1,7 +1,7 @@
 # include "sendmail.h"
 # include "conf.h"
 
 # include "sendmail.h"
 # include "conf.h"
 
-SCCSID(@(#)macro.c     3.17            %G%);
+SCCSID(@(#)macro.c     3.18            %G%);
 
 /*
 **  EXPAND -- macro expand a string using $x escapes.
 
 /*
 **  EXPAND -- macro expand a string using $x escapes.
@@ -14,10 +14,15 @@ SCCSID(@(#)macro.c  3.17            %G%);
 **             e -- envelope in which to work.
 **
 **     Returns:
 **             e -- envelope in which to work.
 **
 **     Returns:
-**             End of interpolated output.
+**             none.
 **
 **     Side Effects:
 **             none.
 **
 **     Side Effects:
 **             none.
+**
+**     Bugs:
+**             The handling of $$ (to get one dollar) is rather bizarre,
+**                     especially if there should be another macro
+**                     expansion in the same string.
 */
 
 expand(s, buf, buflim, e)
 */
 
 expand(s, buf, buflim, e)
@@ -25,25 +30,12 @@ expand(s, buf, buflim, e)
        register char *buf;
        char *buflim;
        register ENVELOPE *e;
        register char *buf;
        char *buflim;
        register ENVELOPE *e;
-{
-       extern char *expand2();
-
-       (void) expand2(s, buf, buflim, e);
-}
-
-
-char *
-expand2(s, buf, buflim, e)
-       register char *s;
-       register char *buf;
-       char *buflim;
-       register ENVELOPE *e;
 {
        register char *q;
 {
        register char *q;
-       char xbuf[BUFSIZ];
-       register char *xp = xbuf;
        bool skipping;          /* set if conditionally skipping output */
        bool gotone = FALSE;    /* set if any expansion done */
        bool skipping;          /* set if conditionally skipping output */
        bool gotone = FALSE;    /* set if any expansion done */
+       char xbuf[BUFSIZ];
+       register char *xp = xbuf;
        extern char *macvalue();
 
 # ifdef DEBUG
        extern char *macvalue();
 
 # ifdef DEBUG
@@ -86,8 +78,10 @@ expand2(s, buf, buflim, e)
 
                  case '$':             /* macro interpolation */
                        c = *++s;
 
                  case '$':             /* macro interpolation */
                        c = *++s;
+                       if (c == '$')
+                               break;
                        q = macvalue(c & 0177, e);
                        q = macvalue(c & 0177, e);
-                       if (q == NULL && c != '$')
+                       if (q == NULL)
                                continue;
                        gotone = TRUE;
                        break;
                                continue;
                        gotone = TRUE;
                        break;
@@ -106,7 +100,7 @@ expand2(s, buf, buflim, e)
                                *xp++ = c;
                                break;
                        }
                                *xp++ = c;
                                break;
                        }
-                       if (*q == NULL)
+                       if (*q == '\0')
                                break;
                        *xp++ = *q++;
                }
                                break;
                        *xp++ = *q++;
                }
@@ -124,14 +118,15 @@ expand2(s, buf, buflim, e)
 
        /* recurse as appropriate */
        if (gotone)
 
        /* recurse as appropriate */
        if (gotone)
-               return (expand2(xbuf, buf, buflim, e));
+       {
+               expand(xbuf, buf, buflim, e);
+               return;
+       }
 
        /* copy results out */
        for (q = buf, xp = xbuf; xp != '\0' && q < buflim-1; )
                *q++ = *xp++;
        *q = '\0';
 
        /* copy results out */
        for (q = buf, xp = xbuf; xp != '\0' && q < buflim-1; )
                *q++ = *xp++;
        *q = '\0';
-
-       return (q);
 }
 \f/*
 **  DEFINE -- define a macro.
 }
 \f/*
 **  DEFINE -- define a macro.
@@ -141,12 +136,13 @@ expand2(s, buf, buflim, e)
 **     Parameters:
 **             n -- the macro name.
 **             v -- the macro value.
 **     Parameters:
 **             n -- the macro name.
 **             v -- the macro value.
+**             e -- the envelope to store the definition in.
 **
 **     Returns:
 **             none.
 **
 **     Side Effects:
 **
 **     Returns:
 **             none.
 **
 **     Side Effects:
-**             CurEnv->e_macro[n] is defined.
+**             e->e_macro[n] is defined.
 **
 **     Notes:
 **             There is one macro for each ASCII character,
 **
 **     Notes:
 **             There is one macro for each ASCII character,
@@ -190,9 +186,10 @@ expand2(s, buf, buflim, e)
 **             are available.
 */
 
 **             are available.
 */
 
-define(n, v)
+define(n, v, e)
        char n;
        char *v;
        char n;
        char *v;
+       register ENVELOPE *e;
 {
 # ifdef DEBUG
        if (tTd(35, 3))
 {
 # ifdef DEBUG
        if (tTd(35, 3))
@@ -202,7 +199,7 @@ define(n, v)
                printf(")\n");
        }
 # endif DEBUG
                printf(")\n");
        }
 # endif DEBUG
-       CurEnv->e_macro[n & 0177] = v;
+       e->e_macro[n & 0177] = v;
 }
 \f/*
 **  MACVALUE -- return uninterpreted value of a macro.
 }
 \f/*
 **  MACVALUE -- return uninterpreted value of a macro.
index 09a2180..9a3685f 100644 (file)
@@ -6,7 +6,7 @@
 # include "sendmail.h"
 # include <sys/stat.h>
 
 # include "sendmail.h"
 # include <sys/stat.h>
 
-SCCSID(@(#)main.c      3.140           %G%);
+SCCSID(@(#)main.c      3.141           %G%);
 
 /*
 **  SENDMAIL -- Post mail to a set of destinations.
 
 /*
 **  SENDMAIL -- Post mail to a set of destinations.
@@ -25,82 +25,18 @@ SCCSID(@(#)main.c   3.140           %G%);
 **     server mechanism).
 **
 **     Usage:
 **     server mechanism).
 **
 **     Usage:
-**             /etc/sendmail [flags] addr ...
+**             /usr/lib/sendmail [flags] addr ...
 **
 **
-**     Positional Parameters:
-**             addr -- the address to deliver the mail to.  There
-**                     can be several.
-**
-**     Flags:
-**             -f name         The mail is from "name" -- used for
-**                             the header in local mail, and to
-**                             deliver reports of failures to.
-**             -r name         Same as -f; however, this flag is
-**                             reserved to indicate special processing
-**                             for remote mail delivery as needed
-**                             in the future.  So, network servers
-**                             should use -r.
-**             -Ffullname      Select what the full-name should be
-**                             listed as.
-**             -a              This mail should be in ARPANET std
-**                             format (obsolete version).
-**             -as             Speak SMTP.
-**             -n              Don't do aliasing.  This might be used
-**                             when delivering responses, for
-**                             instance.
-**             -dN             Run with debugging set to level N.
-**             -em             Mail back a response if there was an
-**                             error in processing.  This should be
-**                             used when the origin of this message
-**                             is another machine.
-**             -ew             Write back a response if the user is
-**                             still logged in, otherwise, act like
-**                             -em.
-**             -eq             Don't print any error message (just
-**                             return exit status).
-**             -ep             (default)  Print error messages
-**                             normally.
-**             -ee             Send BerkNet style errors.  This
-**                             is equivalent to MailBack except
-**                             that it has gives zero return code
-**                             (unless there were errors during
-**                             returning).  This used to be
-**                             "EchoBack", but you know how the old
-**                             software bounces.
-**             -m              In group expansion, send to the
-**                             sender also (stands for the Mail metoo
-**                             option.
-**             -i              Do not terminate mail on a line
-**                             containing just dot.
-**             -s              Save UNIX-like "From" lines on the
-**                             front of messages.
-**             -v              Give blow-by-blow description of
-**                             everything that happens.
-**             -t              Read "to" addresses from message.
-**                             Looks at To:, Cc:, and Bcc: lines.
-**             -I              Initialize the DBM alias files from
-**                             the text format files.
-**             -Cfilename      Use alternate configuration file.
-**             -Afilename      Use alternate alias file.
-**             -DXvalue        Define macro X to have value.
-**             -bv             Verify addresses only.
-**             -bd             Run as a daemon.  Berkeley 4.2 only.
-**             -bf             Fork after address verification.
-**             -bq             Queue up for later delivery.
-**             -ba             Process mail completely.
-**
-**     Return Codes:
-**             As defined in <sysexits.h>.
-**
-**             These codes are actually returned from the auxiliary
-**             mailers; it is their responsibility to make them
-**             correct.
-**
-**     Compilation Flags:
-**             LOG -- if set, everything is logged.
+**             See the associated documentation for details.
 **
 **     Author:
 **
 **     Author:
-**             Eric Allman, UCB/INGRES
+**             Eric Allman, UCB/INGRES (until 10/81)
+**                          Britton-Lee, Inc., purveyors of fine
+**                             database computers (from 11/81)
+**             The support of the INGRES Project and Britton-Lee is
+**                     gratefully acknowledged.  Britton-Lee in
+**                     particular had absolutely nothing to gain from
+**                     my involvement in this project.
 */
 
 
 */
 
 
@@ -177,6 +113,9 @@ main(argc, argv)
        BlankEnvelope.e_putbody = putbody;
        CurEnv = &BlankEnvelope;
 
        BlankEnvelope.e_putbody = putbody;
        CurEnv = &BlankEnvelope;
 
+       /* make sure we have a clean slate */
+       closeall();
+
 # ifdef LOG
        openlog("sendmail", 0);
 # endif LOG
 # ifdef LOG
        openlog("sendmail", 0);
 # endif LOG
@@ -300,7 +239,7 @@ main(argc, argv)
                                        break;
                                }
                        }
                                        break;
                                }
                        }
-                       HopCount = atoi(p);
+                       CurEnv->e_hopcount = atoi(p);
                        break;
                
                  case 'n':     /* don't alias */
                        break;
                
                  case 'n':     /* don't alias */
@@ -412,10 +351,8 @@ main(argc, argv)
        */
 
        initaliases(AliasFile, OpMode == MD_INITALIAS);
        */
 
        initaliases(AliasFile, OpMode == MD_INITALIAS);
-# ifdef DBM
        if (OpMode == MD_INITALIAS)
                exit(EX_OK);
        if (OpMode == MD_INITALIAS)
                exit(EX_OK);
-# endif DBM
 
 # ifdef DEBUG
        if (tTd(0, 15))
 
 # ifdef DEBUG
        if (tTd(0, 15))
@@ -498,7 +435,6 @@ main(argc, argv)
        }
 # endif QUEUE
 
        }
 # endif QUEUE
 
-#ifdef DAEMON
        /*
        **  If a daemon, wait for a request.
        **      getrequests will always return in a child.
        /*
        **  If a daemon, wait for a request.
        **      getrequests will always return in a child.
@@ -525,6 +461,7 @@ main(argc, argv)
                        /* disconnect from our controlling tty */
                        disconnect(FALSE);
                }
                        /* disconnect from our controlling tty */
                        disconnect(FALSE);
                }
+
 # ifdef QUEUE
                if (queuemode)
                {
 # ifdef QUEUE
                if (queuemode)
                {
@@ -534,17 +471,17 @@ main(argc, argv)
                                        pause();
                }
 # endif QUEUE
                                        pause();
                }
 # endif QUEUE
-               checkerrors(CurEnv);
+               dropenvelope(CurEnv);
+
+#ifdef DAEMON
                getrequests();
 
                /* at this point we are in a child: reset state */
                OpMode = MD_SMTP;
                getrequests();
 
                /* at this point we are in a child: reset state */
                OpMode = MD_SMTP;
-               dropenvelope(CurEnv);
-               CurEnv->e_id = CurEnv->e_df = NULL;
-               CurEnv->e_flags &= ~EF_FATALERRS;
+               (void) newenvelope(CurEnv);
                openxscrpt();
                openxscrpt();
-       }
 #endif DAEMON
 #endif DAEMON
+       }
        
 # ifdef SMTP
        /*
        
 # ifdef SMTP
        /*
@@ -563,7 +500,7 @@ main(argc, argv)
        initsys();
        setsender(from);
 
        initsys();
        setsender(from);
 
-       if (OpMode != MD_DAEMON && ac <= 0 && !GrabTo)
+       if (OpMode != MD_ARPAFTP && ac <= 0 && !GrabTo)
        {
                usrerr("Usage: /etc/sendmail [flags] addr...");
                finis();
        {
                usrerr("Usage: /etc/sendmail [flags] addr...");
                finis();
@@ -571,25 +508,10 @@ main(argc, argv)
        if (OpMode == MD_VERIFY)
                SendMode = SM_VERIFY;
 
        if (OpMode == MD_VERIFY)
                SendMode = SM_VERIFY;
 
-       /*
-       **  Process Hop count.
-       **      The Hop count tells us how many times this message has
-       **      been processed by sendmail.  If it exceeds some
-       **      fairly large threshold, then we assume that we have
-       **      an infinite forwarding loop and die.
-       */
-
-       if (++HopCount > MAXHOP)
-               syserr("Infinite forwarding loop (%s->%s)", CurEnv->e_from.q_paddr, *av);
-
        /*
        **  Scan argv and deliver the message to everyone.
        /*
        **  Scan argv and deliver the message to everyone.
-       **      Actually, suppress delivery if we are taking To:
-       **      lines from the message.
        */
 
        */
 
-       if (GrabTo)
-               DontSend = TRUE;
        sendtoargv(av);
 
        /* if we have had errors sofar, arrange a meaningful exit stat */
        sendtoargv(av);
 
        /* if we have had errors sofar, arrange a meaningful exit stat */
@@ -600,51 +522,37 @@ main(argc, argv)
        **  Read the input mail.
        */
 
        **  Read the input mail.
        */
 
-       DontSend = FALSE;
        CurEnv->e_to = NULL;
        if (OpMode != MD_VERIFY || GrabTo)
                collect(FALSE);
        errno = 0;
 
        CurEnv->e_to = NULL;
        if (OpMode != MD_VERIFY || GrabTo)
                collect(FALSE);
        errno = 0;
 
-       initsys();
-
        /* collect statistics */
        /* collect statistics */
-       Stat.stat_nf[CurEnv->e_from.q_mailer->m_mno]++;
-       Stat.stat_bf[CurEnv->e_from.q_mailer->m_mno] += kbytes(CurEnv->e_msgsize);
-
-       /*
-       **  Arrange that the person who is sending the mail
-       **  will not be expanded (unless explicitly requested).
-       */
+       if (OpMode != MD_VERIFY)
+               markstats(CurEnv, (ADDRESS *) NULL);
 
 # ifdef DEBUG
        if (tTd(1, 1))
                printf("From person = \"%s\"\n", CurEnv->e_from.q_paddr);
 # endif DEBUG
 
 
 # ifdef DEBUG
        if (tTd(1, 1))
                printf("From person = \"%s\"\n", CurEnv->e_from.q_paddr);
 # endif DEBUG
 
-       CurEnv->e_from.q_flags |= QDONTSEND;
-       if (!MeToo)
-               recipient(&CurEnv->e_from, &CurEnv->e_sendqueue);
-       CurEnv->e_to = NULL;
-
        /*
        **  Actually send everything.
        **      If verifying, just ack.
        */
 
        /*
        **  Actually send everything.
        **      If verifying, just ack.
        */
 
+       CurEnv->e_from.q_flags |= QDONTSEND;
+       CurEnv->e_to = NULL;
        sendall(CurEnv, SendMode);
 
        /*
        ** All done.
        */
 
        sendall(CurEnv, SendMode);
 
        /*
        ** All done.
        */
 
-       CurEnv->e_to = NULL;
-       if (OpMode != MD_VERIFY)
-               poststats(StatFile);
        finis();
 }
 \f/*
        finis();
 }
 \f/*
-**  SETFROM -- set the person who this message is from
+**  SETSENDER -- set the person who this message is from
 **
 **     Under certain circumstances allow the user to say who
 **     s/he is (using -f or -r).  These are:
 **
 **     Under certain circumstances allow the user to say who
 **     s/he is (using -f or -r).  These are:
@@ -665,10 +573,8 @@ main(argc, argv)
 **     ourselves.
 **
 **     Parameters:
 **     ourselves.
 **
 **     Parameters:
-**             from -- the person it is from.
-**             realname -- the actual person executing sendmail.
-**                     If NULL, then take whoever we previously
-**                     thought was the from person.
+**             from -- the person we would like to believe this message
+**                     is from, as specified on the command line.
 **
 **     Returns:
 **             none.
 **
 **     Returns:
 **             none.
@@ -677,23 +583,53 @@ main(argc, argv)
 **             sets sendmail's notion of who the from person is.
 */
 
 **             sets sendmail's notion of who the from person is.
 */
 
-setfrom(from, realname)
+setsender(from)
        char *from;
        char *from;
-       char *realname;
 {
        register char **pvp;
 {
        register char **pvp;
-       char frombuf[MAXNAME];
+       register struct passwd *pw = NULL;
+       char *realname = NULL;
+       char buf[MAXNAME];
+       extern char *macvalue();
        extern char **prescan();
        extern char **prescan();
-       extern char *index();
-
-       if (realname == NULL)
-               realname = CurEnv->e_from.q_paddr;
 
 # ifdef DEBUG
 
 # ifdef DEBUG
-       if (tTd(1, 1))
-               printf("setfrom(%s, %s)\n", from, realname);
+       if (tTd(45, 1))
+               printf("setsender(%s)\n", from);
 # endif DEBUG
 
 # endif DEBUG
 
+       /*
+       **  Figure out the real user executing us.
+       **      Username can return errno != 0 on non-errors.
+       */
+
+       if (QueueRun || OpMode == MD_SMTP || OpMode == MD_ARPAFTP)
+               realname = from;
+       if (realname == NULL || realname[0] == '\0')
+       {
+               extern char *username();
+
+               realname = username();
+               errno = 0;
+       }
+       if (realname == NULL || realname[0] == '\0')
+       {
+               extern struct passwd *getpwuid();
+
+               pw = getpwuid(getruid());
+               if (pw != NULL)
+                       realname = pw->pw_name;
+       }
+       if (realname == NULL || realname[0] == '\0')
+       {
+               syserr("Who are you?");
+               realname = "root";
+       }
+
+       /*
+       **  Determine if this real person is allowed to alias themselves.
+       */
+
        /*
        **  Do validation to determine whether this user is allowed
        **  to change the sender name.
        /*
        **  Do validation to determine whether this user is allowed
        **  to change the sender name.
@@ -729,13 +665,55 @@ setfrom(from, realname)
        }
        else
                FromFlag = TRUE;
        }
        else
                FromFlag = TRUE;
+       CurEnv->e_from.q_flags |= QDONTSEND;
        CurEnv->e_returnto = &CurEnv->e_from;
        SuprErrs = FALSE;
        CurEnv->e_returnto = &CurEnv->e_from;
        SuprErrs = FALSE;
+
+       if (pw == NULL && CurEnv->e_from.q_mailer == LocalMailer)
+       {
+               extern struct passwd *getpwnam();
+
+               pw = getpwnam(CurEnv->e_from.q_user);
+       }
+
+       /*
+       **  Process passwd file entry.
+       */
+
+       if (pw != NULL)
+       {
+               /* extract home directory */
+               CurEnv->e_from.q_home = newstr(pw->pw_dir);
+
+               /* run user's .mailcf file */
+               define('z', CurEnv->e_from.q_home, CurEnv);
+               expand("$z/.mailcf", buf, &buf[sizeof buf - 1], CurEnv);
+               if (safefile(buf, getruid(), S_IREAD))
+                       readcf(buf, FALSE);
+
+               /* if the user has given fullname already, don't redefine */
+               if (FullName == NULL)
+                       FullName = macvalue('x', CurEnv);
+               if (FullName[0] == '\0')
+                       FullName = NULL;
+
+               /* extract full name from passwd file */
+               if (FullName == NULL && pw->pw_gecos != NULL)
+               {
+                       buildfname(pw->pw_gecos, CurEnv->e_from.q_user, buf);
+                       if (buf[0] != '\0')
+                               FullName = newstr(buf);
+               }
+               if (FullName != NULL)
+                       define('x', FullName, CurEnv);
+       }
+
+#ifndef V6
+       if (CurEnv->e_from.q_home == NULL)
+               CurEnv->e_from.q_home = getenv("HOME");
+#endif V6
        CurEnv->e_from.q_uid = getuid();
        CurEnv->e_from.q_gid = getgid();
        CurEnv->e_from.q_uid = getuid();
        CurEnv->e_from.q_gid = getgid();
-# ifndef V6
-       CurEnv->e_from.q_home = getenv("HOME");
-# endif V6
        if (CurEnv->e_from.q_uid != 0)
        {
                DefUid = CurEnv->e_from.q_uid;
        if (CurEnv->e_from.q_uid != 0)
        {
                DefUid = CurEnv->e_from.q_uid;
@@ -755,8 +733,8 @@ setfrom(from, realname)
        }
        rewrite(pvp, 3);
        rewrite(pvp, 1);
        }
        rewrite(pvp, 3);
        rewrite(pvp, 1);
-       cataddr(pvp, frombuf, sizeof frombuf);
-       define('f', newstr(frombuf));
+       cataddr(pvp, buf, sizeof buf);
+       define('f', newstr(buf), CurEnv);
 
        /* save the domain spec if this mailer wants it */
        if (bitset(M_CANONICAL, CurEnv->e_from.q_mailer->m_flags))
 
        /* save the domain spec if this mailer wants it */
        if (bitset(M_CANONICAL, CurEnv->e_from.q_mailer->m_flags))
@@ -811,22 +789,20 @@ trusteduser(user)
 finis()
 {
        CurEnv = &MainEnvelope;
 finis()
 {
        CurEnv = &MainEnvelope;
+       CurEnv->e_to = NULL;
 
 # ifdef DEBUG
        if (tTd(2, 1))
                printf("\n====finis: stat %d e_flags %o\n", ExitStat, CurEnv->e_flags);
 # endif DEBUG
 
 
 # ifdef DEBUG
        if (tTd(2, 1))
                printf("\n====finis: stat %d e_flags %o\n", ExitStat, CurEnv->e_flags);
 # endif DEBUG
 
-       /*
-       **  Clean up temp files.
-       */
-
+       /* clean up temp files */
        dropenvelope(CurEnv);
 
        dropenvelope(CurEnv);
 
-       /*
-       **  And exit.
-       */
+       /* post statistics */
+       poststats(StatFile);
 
 
+       /* and exit */
 # ifdef LOG
        if (LogLevel > 11)
                syslog(LOG_DEBUG, "finis, pid=%d", getpid());
 # ifdef LOG
        if (LogLevel > 11)
                syslog(LOG_DEBUG, "finis, pid=%d", getpid());
@@ -836,7 +812,8 @@ finis()
 \f/*
 **  INTSIG -- clean up on interrupt
 **
 \f/*
 **  INTSIG -- clean up on interrupt
 **
-**     This just arranges to call finis.
+**     This just arranges to exit.  It pessimises in that it
+**     may resend a message.
 **
 **     Parameters:
 **             none.
 **
 **     Parameters:
 **             none.
@@ -845,13 +822,14 @@ finis()
 **             none.
 **
 **     Side Effects:
 **             none.
 **
 **     Side Effects:
-**             Arranges to not unlink the qf and df files.
+**             Unlocks the current job.
 */
 
 intsig()
 {
 */
 
 intsig()
 {
-       CurEnv->e_df = NULL;
-       finis();
+       FileName = NULL;
+       unlockqueue(CurEnv);
+       exit(EX_OK);
 }
 \f/*
 **  OPENXSCRPT -- Open transcript file
 }
 \f/*
 **  OPENXSCRPT -- Open transcript file
@@ -866,7 +844,7 @@ intsig()
 **             none
 **
 **     Side Effects:
 **             none
 **
 **     Side Effects:
-**             Open the transcript file.
+**             Creates the transcript file.
 */
 
 openxscrpt()
 */
 
 openxscrpt()
@@ -881,107 +859,6 @@ openxscrpt()
                (void) chmod(p, 0644);
 }
 \f/*
                (void) chmod(p, 0644);
 }
 \f/*
-**  SETSENDER -- set sendmail's idea of the sender.
-**
-**     Parameters:
-**             from -- the person we would like to believe this
-**                     is from.
-**
-**     Returns:
-**             none.
-**
-**     Side Effects:
-**             Sets the idea of the sender.
-*/
-
-setsender(from)
-       char *from;
-{
-       register char *p;
-       extern char *getlogin();
-       register struct passwd *pw;
-       char *realname;
-       char cfbuf[40];
-       bool nofullname;
-       extern char *macvalue();
-
-       /*
-       **  Figure out the real user executing us.
-       **      Getlogin can return errno != 0 on non-errors.
-       */
-
-       if (OpMode != MD_SMTP && !QueueRun)
-       {
-               errno = 0;
-               p = getlogin();
-               errno = 0;
-               nofullname = (from != NULL);
-       }
-       else
-       {
-               p = from;
-               nofullname = FALSE;
-       }
-       if (p != NULL && p[0] != '\0')
-       {
-               extern struct passwd *getpwnam();
-
-               pw = getpwnam(p);
-               if (pw == NULL)
-               {
-                       if (OpMode != MD_SMTP && !QueueRun)
-                               syserr("Who are you? (name=%s)", p);
-                       p = NULL;
-               }
-       }
-       if (p == NULL || p[0] == '\0')
-       {
-               extern struct passwd *getpwuid();
-               int uid;
-
-               nofullname = TRUE;
-               uid = getruid();
-               pw = getpwuid(uid);
-               if (pw == NULL)
-                       syserr("Who are you? (uid=%d)", uid);
-               else
-                       p = pw->pw_name;
-       }
-       if (p == NULL || p[0] == '\0' || pw == NULL)
-               finis();
-
-       realname = p;
-
-       /*
-       **  Process passwd file entry.
-       */
-
-       /* run user's .mailcf file */
-       define('z', pw->pw_dir);
-       expand("$z/.mailcf", cfbuf, &cfbuf[sizeof cfbuf - 1], CurEnv);
-       if (!nofullname && safefile(cfbuf, getruid(), S_IREAD))
-               readcf(cfbuf, FALSE);
-
-       /* if the user has given fullname already, don't redefine */
-       if (FullName == NULL)
-               FullName = macvalue('x', CurEnv);
-
-       /* extract full name from passwd file */
-       if (!nofullname && (FullName == NULL || FullName[0] == '\0') &&
-           pw != NULL && pw->pw_gecos != NULL)
-       {
-               char nbuf[MAXNAME];
-
-               fullname(pw, nbuf);
-               if (nbuf[0] != '\0')
-                       FullName = newstr(nbuf);
-       }
-       if (FullName != NULL && FullName[0] != '\0')
-               define('x', FullName);
-
-       setfrom(from, realname);
-}
-\f/*
 **  INITSYS -- initialize instantiation of system
 **
 **     In Daemon mode, this is done in the child.
 **  INITSYS -- initialize instantiation of system
 **
 **     In Daemon mode, this is done in the child.
@@ -1036,29 +913,29 @@ initsys()
 
        /* process id */
        (void) sprintf(pbuf, "%d", getpid());
 
        /* process id */
        (void) sprintf(pbuf, "%d", getpid());
-       define('p', pbuf);
+       define('p', pbuf, CurEnv);
 
        /* hop count */
 
        /* hop count */
-       (void) sprintf(cbuf, "%d", HopCount);
-       define('c', cbuf);
+       (void) sprintf(cbuf, "%d", CurEnv->e_hopcount);
+       define('c', cbuf, CurEnv);
 
        /* time as integer, unix time, arpa time */
        now = curtime();
        tm = gmtime(&now);
        (void) sprintf(tbuf, "%02d%02d%02d%02d%02d", tm->tm_year, tm->tm_mon,
                        tm->tm_mday, tm->tm_hour, tm->tm_min);
 
        /* time as integer, unix time, arpa time */
        now = curtime();
        tm = gmtime(&now);
        (void) sprintf(tbuf, "%02d%02d%02d%02d%02d", tm->tm_year, tm->tm_mon,
                        tm->tm_mday, tm->tm_hour, tm->tm_min);
-       define('t', tbuf);
+       define('t', tbuf, CurEnv);
        (void) strcpy(dbuf, ctime(&now));
        *index(dbuf, '\n') = '\0';
        if (macvalue('d', CurEnv) == NULL)
        (void) strcpy(dbuf, ctime(&now));
        *index(dbuf, '\n') = '\0';
        if (macvalue('d', CurEnv) == NULL)
-               define('d', dbuf);
+               define('d', dbuf, CurEnv);
        p = newstr(arpadate(dbuf));
        if (macvalue('a', CurEnv) == NULL)
        p = newstr(arpadate(dbuf));
        if (macvalue('a', CurEnv) == NULL)
-               define('a', p);
-       define('b', p);
+               define('a', p, CurEnv);
+       define('b', p, CurEnv);
 
        /* version */
 
        /* version */
-       define('v', Version);
+       define('v', Version, CurEnv);
 
        /* tty name */
        if (macvalue('y', CurEnv) == NULL)
 
        /* tty name */
        if (macvalue('y', CurEnv) == NULL)
@@ -1069,7 +946,7 @@ initsys()
                        if (rindex(p, '/') != NULL)
                                p = rindex(p, '/') + 1;
                        (void) strcpy(ybuf, p);
                        if (rindex(p, '/') != NULL)
                                p = rindex(p, '/') + 1;
                        (void) strcpy(ybuf, p);
-                       define('y', ybuf);
+                       define('y', ybuf, CurEnv);
                }
        }
 }
                }
        }
 }
@@ -1119,14 +996,14 @@ initmacros()
        {
                buf[0] = m->metaval;
                buf[1] = '\0';
        {
                buf[0] = m->metaval;
                buf[1] = '\0';
-               define(m->metaname, newstr(buf));
+               define(m->metaname, newstr(buf), CurEnv);
        }
        buf[0] = MATCHREPL;
        buf[2] = '\0';
        for (c = '0'; c <= '9'; c++)
        {
                buf[1] = c;
        }
        buf[0] = MATCHREPL;
        buf[2] = '\0';
        for (c = '0'; c <= '9'; c++)
        {
                buf[1] = c;
-               define(c, newstr(buf));
+               define(c, newstr(buf), CurEnv);
        }
 }
 \f/*
        }
 }
 \f/*
@@ -1150,13 +1027,17 @@ newenvelope(e)
 {
        register HDR *bh;
        register HDR **nhp;
 {
        register HDR *bh;
        register HDR **nhp;
+       register ENVELOPE *parent;
 
 
+       parent = CurEnv;
+       if (e == CurEnv)
+               parent = e->e_parent;
        clear((char *) e, sizeof *e);
        bmove((char *) &CurEnv->e_from, (char *) &e->e_from, sizeof e->e_from);
        clear((char *) e, sizeof *e);
        bmove((char *) &CurEnv->e_from, (char *) &e->e_from, sizeof e->e_from);
-       e->e_parent = CurEnv;
+       e->e_parent = parent;
        e->e_ctime = curtime();
        e->e_ctime = curtime();
-       e->e_puthdr = CurEnv->e_puthdr;
-       e->e_putbody = CurEnv->e_putbody;
+       e->e_puthdr = parent->e_puthdr;
+       e->e_putbody = parent->e_putbody;
        bh = BlankEnvelope.e_header;
        nhp = &e->e_header;
        while (bh != NULL)
        bh = BlankEnvelope.e_header;
        nhp = &e->e_header;
        while (bh != NULL)
@@ -1166,6 +1047,8 @@ newenvelope(e)
                bh = bh->h_link;
                nhp = &(*nhp)->h_link;
        }
                bh = bh->h_link;
                nhp = &(*nhp)->h_link;
        }
+       if (Xscript != NULL)
+               (void) fflush(Xscript);
 
        return (e);
 }
 
        return (e);
 }
@@ -1187,7 +1070,6 @@ dropenvelope(e)
        register ENVELOPE *e;
 {
        bool queueit = FALSE;
        register ENVELOPE *e;
 {
        bool queueit = FALSE;
-       bool sendreceipt = bitset(EF_SENDRECEIPT, e->e_flags);
        register ADDRESS *q;
 
 #ifdef DEBUG
        register ADDRESS *q;
 
 #ifdef DEBUG
@@ -1208,15 +1090,13 @@ dropenvelope(e)
        {
                if (bitset(QQUEUEUP, q->q_flags))
                        queueit = TRUE;
        {
                if (bitset(QQUEUEUP, q->q_flags))
                        queueit = TRUE;
-               if (bitset(QBADADDR, q->q_flags))
-                       sendreceipt = TRUE;
        }
 
        /*
        **  Send back return receipts as requested.
        */
 
        }
 
        /*
        **  Send back return receipts as requested.
        */
 
-       if (e->e_receiptto != NULL && sendreceipt)
+       if (e->e_receiptto != NULL && bitset(EF_SENDRECEIPT, e->e_flags))
        {
                auto ADDRESS *rlist;
 
        {
                auto ADDRESS *rlist;
 
@@ -1250,9 +1130,31 @@ dropenvelope(e)
                xunlink(queuename(e, 'q'));
        }
        else if (queueit || !bitset(EF_INQUEUE, e->e_flags))
                xunlink(queuename(e, 'q'));
        }
        else if (queueit || !bitset(EF_INQUEUE, e->e_flags))
-               queueup(e, FALSE);
+               queueup(e, FALSE, FALSE);
+
+       /* now unlock the job */
+       unlockqueue(e);
+
+       /* make sure that this envelope is marked unused */
+       e->e_id = e->e_df = NULL;
+}
+\f/*
+**  UNLOCKQUEUE -- unlock the queue entry for a specified envelope
+**
+**     Parameters:
+**             e -- the envelope to unlock.
+**
+**     Returns:
+**             none
+**
+**     Side Effects:
+**             unlocks the queue for `e'.
+*/
 
 
-       /* in any case, remove the transcript */
+unlockqueue(e)
+       ENVELOPE *e;
+{
+       /* remove the transcript */
 #ifdef DEBUG
        if (!tTd(51, 4))
 #endif DEBUG
 #ifdef DEBUG
        if (!tTd(51, 4))
 #endif DEBUG
@@ -1291,10 +1193,9 @@ queuename(e, type)
        char type;
 {
        static char buf[MAXNAME];
        char type;
 {
        static char buf[MAXNAME];
-       /* these must go in initialized data space for freeze/thaw in smtp */
        static int pid = -1;
        static int pid = -1;
-       static char c1 = 'A';
-       static char c2 = 'A';
+       char c1 = 'A';
+       char c2 = 'A';
 
        if (e->e_id == NULL)
        {
 
        if (e->e_id == NULL)
        {
@@ -1356,7 +1257,7 @@ queuename(e, type)
                        exit(EX_OSERR);
                }
                e->e_id = newstr(&qf[2]);
                        exit(EX_OSERR);
                }
                e->e_id = newstr(&qf[2]);
-               define('i', e->e_id);
+               define('i', e->e_id, e);
 # ifdef DEBUG
                if (tTd(7, 1))
                        printf("queuename: assigned id %s, env=%x\n", e->e_id, e);
 # ifdef DEBUG
                if (tTd(7, 1))
                        printf("queuename: assigned id %s, env=%x\n", e->e_id, e);
@@ -1387,18 +1288,22 @@ queuename(e, type)
 **             Writes BSS and malloc'ed memory to freezefile
 */
 
 **             Writes BSS and malloc'ed memory to freezefile
 */
 
-struct frz
+union frz
 {
 {
-       time_t  frzstamp;               /* timestamp on this freeze */
-       char    *frzbrk;                /* the current break */
-       char    frzver[252];            /* sendmail version */
+       char            frzpad[BUFSIZ]; /* insure we are on a BUFSIZ boundary */
+       struct
+       {
+               time_t  frzstamp;       /* timestamp on this freeze */
+               char    *frzbrk;        /* the current break */
+               char    frzver[252];    /* sendmail version */
+       } frzinfo;
 };
 
 freeze(freezefile)
        char *freezefile;
 {
        int f;
 };
 
 freeze(freezefile)
        char *freezefile;
 {
        int f;
-       struct frz fhdr;
+       union frz fhdr;
        extern char edata;
        extern char *sbrk();
 
        extern char edata;
        extern char *sbrk();
 
@@ -1415,14 +1320,17 @@ freeze(freezefile)
        }
 
        /* build the freeze header */
        }
 
        /* build the freeze header */
-       fhdr.frzstamp = curtime();
-       fhdr.frzbrk = sbrk(0);
-       strcpy(fhdr.frzver, Version);
+       fhdr.frzinfo.frzstamp = curtime();
+       fhdr.frzinfo.frzbrk = sbrk(0);
+       strcpy(fhdr.frzinfo.frzver, Version);
 
        /* write out the freeze header */
        if (write(f, (char *) &fhdr, sizeof fhdr) != sizeof fhdr ||
 
        /* write out the freeze header */
        if (write(f, (char *) &fhdr, sizeof fhdr) != sizeof fhdr ||
-           write(f, (char *) &edata, fhdr.frzbrk - &edata) != (fhdr.frzbrk - &edata))
+           write(f, (char *) &edata, fhdr.frzinfo.frzbrk - &edata) !=
+                                       (fhdr.frzinfo.frzbrk - &edata))
+       {
                syserr("Cannot freeze");
                syserr("Cannot freeze");
+       }
 
        /* fine, clean up */
        (void) close(f);
 
        /* fine, clean up */
        (void) close(f);
@@ -1445,7 +1353,7 @@ thaw(freezefile)
        char *freezefile;
 {
        int f;
        char *freezefile;
 {
        int f;
-       struct frz fhdr;
+       union frz fhdr;
        extern char edata;
 
        if (freezefile == NULL)
        extern char edata;
 
        if (freezefile == NULL)
@@ -1461,26 +1369,27 @@ thaw(freezefile)
 
        /* read in the header */
        if (read(f, (char *) &fhdr, sizeof fhdr) < sizeof fhdr ||
 
        /* read in the header */
        if (read(f, (char *) &fhdr, sizeof fhdr) < sizeof fhdr ||
-           strcmp(fhdr.frzver, Version) != 0)
+           strcmp(fhdr.frzinfo.frzver, Version) != 0)
        {
                (void) close(f);
                return (FALSE);
        }
 
        /* arrange to have enough space */
        {
                (void) close(f);
                return (FALSE);
        }
 
        /* arrange to have enough space */
-       if (brk(fhdr.frzbrk) < 0)
+       if (brk(fhdr.frzinfo.frzbrk) < 0)
        {
        {
-               syserr("Cannot break to %x", fhdr.frzbrk);
+               syserr("Cannot break to %x", fhdr.frzinfo.frzbrk);
                (void) close(f);
                return (FALSE);
        }
 
        /* now read in the freeze file */
                (void) close(f);
                return (FALSE);
        }
 
        /* now read in the freeze file */
-       if (read(f, (char *) &edata, fhdr.frzbrk - &edata) != (fhdr.frzbrk - &edata))
+       if (read(f, (char *) &edata, fhdr.frzinfo.frzbrk - &edata) !=
+                                       (fhdr.frzinfo.frzbrk - &edata))
        {
                /* oops!  we have trashed memory..... */
        {
                /* oops!  we have trashed memory..... */
-               fprintf(stderr, "Cannot read freeze file\n");
-               exit(EX_SOFTWARE);
+               write(2, "Cannot read freeze file\n", 24);
+               _exit(EX_SOFTWARE);
        }
 
        (void) close(f);
        }
 
        (void) close(f);
@@ -1522,7 +1431,8 @@ disconnect(all)
        signal(SIGQUIT, SIG_IGN);
 
        /* we can't communicate with our caller, so.... */
        signal(SIGQUIT, SIG_IGN);
 
        /* we can't communicate with our caller, so.... */
-       HoldErrs = MailBack = TRUE;
+       HoldErrs = TRUE;
+       ErrorMode = EM_MAIL;
        Verbose = FALSE;
 
        /* all input from /dev/null */
        Verbose = FALSE;
 
        /* all input from /dev/null */
index c4b9d08..668ebed 100644 (file)
@@ -1,6 +1,6 @@
 # include "sendmail.h"
 
 # include "sendmail.h"
 
-SCCSID(@(#)parseaddr.c 3.66            %G%);
+SCCSID(@(#)parseaddr.c 3.67            %G%);
 
 /*
 **  PARSE -- Parse an address
 
 /*
 **  PARSE -- Parse an address
@@ -38,6 +38,7 @@ SCCSID(@(#)parseaddr.c        3.66            %G%);
 **             none
 */
 
 **             none
 */
 
+/* following delimiters are inherent to the internal algorithms */
 # define DELIMCHARS    "$()<>,;\\\"\r\n"       /* word delimiters */
 
 ADDRESS *
 # define DELIMCHARS    "$()<>,;\\\"\r\n"       /* word delimiters */
 
 ADDRESS *
@@ -145,11 +146,8 @@ parse(addr, a, copyf)
 \f/*
 **  PRESCAN -- Prescan name and make it canonical
 **
 \f/*
 **  PRESCAN -- Prescan name and make it canonical
 **
-**     Scans a name and turns it into canonical form.  This involves
-**     deleting blanks, comments (in parentheses), and turning the
-**     word "at" into an at-sign ("@").  The name is copied as this
-**     is done; it is legal to copy a name onto itself, since this
-**     process can only make things smaller.
+**     Scans a name and turns it into a set of tokens.  This process
+**     deletes blanks and comments (in parentheses).
 **
 **     This routine knows about quoted strings and angle brackets.
 **
 **
 **     This routine knows about quoted strings and angle brackets.
 **
@@ -599,108 +597,107 @@ rewrite(pvp, ruleset)
                **  See if we successfully matched
                */
 
                **  See if we successfully matched
                */
 
-               if (rvp >= rwr->r_lhs && *rvp == NULL)
+               if (rvp < rwr->r_lhs || *rvp != NULL)
                {
                {
-                       rvp = rwr->r_rhs;
 # ifdef DEBUG
 # ifdef DEBUG
-                       if (tTd(21, 12))
-                       {
-                               printf("-----rule matches:");
-                               printav(rvp);
-                       }
+                       if (tTd(21, 10))
+                               printf("----- rule fails\n");
 # endif DEBUG
 # endif DEBUG
+                       rwr = rwr->r_next;
+                       continue;
+               }
 
 
-                       rp = *rvp;
-                       if (*rp == CANONUSER)
-                       {
-                               rvp++;
-                               rwr = rwr->r_next;
-                       }
-                       else if (*rp == CANONHOST)
-                       {
-                               rvp++;
-                               rwr = NULL;
-                       }
-                       else if (*rp == CANONNET)
-                               rwr = NULL;
+               rvp = rwr->r_rhs;
+# ifdef DEBUG
+               if (tTd(21, 12))
+               {
+                       printf("-----rule matches:");
+                       printav(rvp);
+               }
+# endif DEBUG
+
+               rp = *rvp;
+               if (*rp == CANONUSER)
+               {
+                       rvp++;
+                       rwr = rwr->r_next;
+               }
+               else if (*rp == CANONHOST)
+               {
+                       rvp++;
+                       rwr = NULL;
+               }
+               else if (*rp == CANONNET)
+                       rwr = NULL;
+
+               /* substitute */
+               for (avp = npvp; *rvp != NULL; rvp++)
+               {
+                       register struct match *m;
+                       register char **pp;
 
 
-                       /* substitute */
-                       for (avp = npvp; *rvp != NULL; rvp++)
+                       rp = *rvp;
+                       if (*rp != MATCHREPL)
                        {
                        {
-                               rp = *rvp;
-                               if (*rp == MATCHREPL)
+                               if (avp >= &npvp[MAXATOM])
                                {
                                {
-                                       register struct match *m;
-                                       register char **pp;
+                                       syserr("rewrite: expansion too long");
+                                       return;
+                               }
+                               *avp++ = rp;
+                               continue;
+                       }
 
 
-                                       m = &mlist[rp[1] - '1'];
+                       /* substitute from LHS */
+                       m = &mlist[rp[1] - '1'];
 # ifdef DEBUG
 # ifdef DEBUG
-                                       if (tTd(21, 15))
-                                       {
-                                               printf("$%c:", rp[1]);
-                                               pp = m->first;
-                                               while (pp <= m->last)
-                                               {
-                                                       printf(" %x=\"", *pp);
-                                                       (void) fflush(stdout);
-                                                       printf("%s\"", *pp++);
-                                               }
-                                               printf("\n");
-                                       }
-# endif DEBUG
-                                       pp = m->first;
-                                       while (pp <= m->last)
-                                       {
-                                               if (avp >= &npvp[MAXATOM])
-                                               {
-                                                       syserr("rewrite: expansion too long");
-                                                       return;
-                                               }
-                                               *avp++ = *pp++;
-                                       }
-                               }
-                               else
+                       if (tTd(21, 15))
+                       {
+                               printf("$%c:", rp[1]);
+                               pp = m->first;
+                               while (pp <= m->last)
                                {
                                {
-                                       if (avp >= &npvp[MAXATOM])
-                                       {
-                                               syserr("rewrite: expansion too long");
-                                               return;
-                                       }
-                                       *avp++ = rp;
+                                       printf(" %x=\"", *pp);
+                                       (void) fflush(stdout);
+                                       printf("%s\"", *pp++);
                                }
                                }
+                               printf("\n");
                        }
                        }
-                       *avp++ = NULL;
-                       if (**npvp == CALLSUBR)
-                       {
-                               bmove((char *) &npvp[2], (char *) pvp,
-                                       (avp - npvp - 2) * sizeof *avp);
-# ifdef DEBUG
-                               if (tTd(21, 3))
-                                       printf("-----callsubr %s\n", npvp[1]);
 # endif DEBUG
 # endif DEBUG
-                               rewrite(pvp, atoi(npvp[1]));
-                       }
-                       else
+                       pp = m->first;
+                       while (pp <= m->last)
                        {
                        {
-                               bmove((char *) npvp, (char *) pvp,
-                                       (avp - npvp) * sizeof *avp);
+                               if (avp >= &npvp[MAXATOM])
+                               {
+                                       syserr("rewrite: expansion too long");
+                                       return;
+                               }
+                               *avp++ = *pp++;
                        }
                        }
+               }
+               *avp++ = NULL;
+               if (**npvp == CALLSUBR)
+               {
+                       bmove((char *) &npvp[2], (char *) pvp,
+                               (avp - npvp - 2) * sizeof *avp);
 # ifdef DEBUG
 # ifdef DEBUG
-                       if (tTd(21, 4))
-                       {
-                               printf("rewritten as:");
-                               printav(pvp);
-                       }
+                       if (tTd(21, 3))
+                               printf("-----callsubr %s\n", npvp[1]);
 # endif DEBUG
 # endif DEBUG
+                       rewrite(pvp, atoi(npvp[1]));
                }
                else
                {
                }
                else
                {
+                       bmove((char *) npvp, (char *) pvp,
+                               (avp - npvp) * sizeof *avp);
+               }
 # ifdef DEBUG
 # ifdef DEBUG
-                       if (tTd(21, 10))
-                               printf("----- rule fails\n");
-# endif DEBUG
-                       rwr = rwr->r_next;
+               if (tTd(21, 4))
+               {
+                       printf("rewritten as:");
+                       printav(pvp);
                }
                }
+# endif DEBUG
        }
 
        if (OpMode == MD_TEST || tTd(21, 2))
        }
 
        if (OpMode == MD_TEST || tTd(21, 2))
@@ -853,8 +850,6 @@ cataddr(pvp, buf, sz)
 **
 **     Parameters:
 **             a, b -- pointers to the internal forms to compare.
 **
 **     Parameters:
 **             a, b -- pointers to the internal forms to compare.
-**             wildflg -- if TRUE, 'a' may have no user specified,
-**                     in which case it is to match anything.
 **
 **     Returns:
 **             TRUE -- they represent the same mailbox.
 **
 **     Returns:
 **             TRUE -- they represent the same mailbox.
@@ -865,17 +860,16 @@ cataddr(pvp, buf, sz)
 */
 
 bool
 */
 
 bool
-sameaddr(a, b, wildflg)
+sameaddr(a, b)
        register ADDRESS *a;
        register ADDRESS *b;
        register ADDRESS *a;
        register ADDRESS *b;
-       bool wildflg;
 {
        /* if they don't have the same mailer, forget it */
        if (a->q_mailer != b->q_mailer)
                return (FALSE);
 
        /* if the user isn't the same, we can drop out */
 {
        /* if they don't have the same mailer, forget it */
        if (a->q_mailer != b->q_mailer)
                return (FALSE);
 
        /* if the user isn't the same, we can drop out */
-       if ((!wildflg || a->q_user[0] != '\0') && strcmp(a->q_user, b->q_user) != 0)
+       if (strcmp(a->q_user, b->q_user) != 0)
                return (FALSE);
 
        /* if the mailer ignores hosts, we have succeeded! */
                return (FALSE);
 
        /* if the mailer ignores hosts, we have succeeded! */
@@ -1054,9 +1048,9 @@ remotename(name, m, senderaddress)
        */
 
        cataddr(pvp, lbuf, sizeof lbuf);
        */
 
        cataddr(pvp, lbuf, sizeof lbuf);
-       define('g', lbuf);
+       define('g', lbuf, CurEnv);
        expand(fancy, buf, &buf[sizeof buf - 1], CurEnv);
        expand(fancy, buf, &buf[sizeof buf - 1], CurEnv);
-       define('g', oldg);
+       define('g', oldg, CurEnv);
 
 # ifdef DEBUG
        if (tTd(12, 1))
 
 # ifdef DEBUG
        if (tTd(12, 1))
index dc3d996..ccf07f9 100644 (file)
@@ -5,33 +5,45 @@
 # include <errno.h>
 
 # ifndef QUEUE
 # include <errno.h>
 
 # ifndef QUEUE
-SCCSID(@(#)queue.c     3.53            %G%     (no queueing));
+SCCSID(@(#)queue.c     3.54            %G%     (no queueing));
 # else QUEUE
 
 # else QUEUE
 
-SCCSID(@(#)queue.c     3.53            %G%);
+SCCSID(@(#)queue.c     3.54            %G%);
 
 /*
 
 /*
+**  Work queue.
+*/
+
+struct work
+{
+       char            *w_name;        /* name of control file */
+       long            w_pri;          /* priority of message, see below */
+       struct work     *w_next;        /* next in queue */
+};
+
+typedef struct work    WORK;
+
+WORK   *WorkQ;                 /* queue of things to be done */
+\f/*
 **  QUEUEUP -- queue a message up for future transmission.
 **
 **  QUEUEUP -- queue a message up for future transmission.
 **
-**     The queued message should already be in the correct place.
-**     This routine just outputs the control file as appropriate.
-**
 **     Parameters:
 **             e -- the envelope to queue up.
 **             queueall -- if TRUE, queue all addresses, rather than
 **                     just those with the QQUEUEUP flag set.
 **     Parameters:
 **             e -- the envelope to queue up.
 **             queueall -- if TRUE, queue all addresses, rather than
 **                     just those with the QQUEUEUP flag set.
+**             announce -- if TRUE, tell when you are queueing up.
 **
 **     Returns:
 **             none.
 **
 **     Side Effects:
 **
 **     Returns:
 **             none.
 **
 **     Side Effects:
-**             The current request (only unsatisfied addresses)
-**                     are saved in a control file.
+**             The current request are saved in a control file.
 */
 
 */
 
-queueup(e, queueall)
+queueup(e, queueall, announce)
        register ENVELOPE *e;
        bool queueall;
        register ENVELOPE *e;
        bool queueall;
+       bool announce;
 {
        char *tf;
        char *qf;
 {
        char *tf;
        char *qf;
@@ -75,14 +87,18 @@ queueup(e, queueall)
                        return;
                }
                (void) chmod(e->e_df, FileMode);
                        return;
                }
                (void) chmod(e->e_df, FileMode);
-               (*e->e_putbody)(dfp, Mailer[1], FALSE);
+               (*e->e_putbody)(dfp, ProgMailer, FALSE);
                (void) fclose(dfp);
        }
 
        /*
        **  Output future work requests.
                (void) fclose(dfp);
        }
 
        /*
        **  Output future work requests.
+       **      Priority should be first, since it is read by orderq.
        */
 
        */
 
+       /* output message priority */
+       fprintf(tfp, "P%ld\n", e->e_msgpriority);
+
        /* output name of data file */
        fprintf(tfp, "D%s\n", e->e_df);
 
        /* output name of data file */
        fprintf(tfp, "D%s\n", e->e_df);
 
@@ -92,9 +108,6 @@ queueup(e, queueall)
        /* output creation time */
        fprintf(tfp, "T%ld\n", e->e_ctime);
 
        /* output creation time */
        fprintf(tfp, "T%ld\n", e->e_ctime);
 
-       /* output message priority */
-       fprintf(tfp, "P%ld\n", e->e_msgpriority);
-
        /* output message class */
        fprintf(tfp, "C%d\n", e->e_class);
 
        /* output message class */
        fprintf(tfp, "C%d\n", e->e_class);
 
@@ -112,11 +125,26 @@ queueup(e, queueall)
                               bitset(QQUEUEUP, q->q_flags))
                {
                        fprintf(tfp, "R%s\n", q->q_paddr);
                               bitset(QQUEUEUP, q->q_flags))
                {
                        fprintf(tfp, "R%s\n", q->q_paddr);
+                       if (announce)
+                       {
+                               e->e_to = q->q_paddr;
+                               message(Arpa_Info, "queued");
+                               if (LogLevel > 4)
+                                       logdelivery("queued");
+                               e->e_to = NULL;
+                       }
                }
        }
 
                }
        }
 
-       /* output headers for this message */
-       define('g', "$f");
+       /*
+       **  Output headers for this message.
+       **      Expand macros completely here.  Queue run will deal with
+       **      everything as absolute headers.
+       **              All headers that must be relative to the recipient
+       **              can be cracked later.
+       */
+
+       define('g', "$f", e);
        for (h = e->e_header; h != NULL; h = h->h_link)
        {
                if (h->h_value == NULL || h->h_value[0] == '\0')
        for (h = e->e_header; h != NULL; h = h->h_link)
        {
                if (h->h_value == NULL || h->h_value[0] == '\0')
@@ -144,11 +172,13 @@ queueup(e, queueall)
 
        (void) fclose(tfp);
        qf = queuename(e, 'q');
 
        (void) fclose(tfp);
        qf = queuename(e, 'q');
+       holdsigs();
        (void) unlink(qf);
        if (link(tf, qf) < 0)
                syserr("cannot link(%s, %s), df=%s", tf, qf, e->e_df);
        else
                (void) unlink(tf);
        (void) unlink(qf);
        if (link(tf, qf) < 0)
                syserr("cannot link(%s, %s), df=%s", tf, qf, e->e_df);
        else
                (void) unlink(tf);
+       rlsesigs();
 
 # ifdef LOG
        /* save log info */
 
 # ifdef LOG
        /* save log info */
@@ -175,8 +205,6 @@ queueup(e, queueall)
 runqueue(forkflag)
        bool forkflag;
 {
 runqueue(forkflag)
        bool forkflag;
 {
-       register int i;
-
        /*
        **  See if we want to go off and do other useful work.
        */
        /*
        **  See if we want to go off and do other useful work.
        */
@@ -189,12 +217,7 @@ runqueue(forkflag)
                if (pid != 0)
                {
                        /* parent -- pick up intermediate zombie */
                if (pid != 0)
                {
                        /* parent -- pick up intermediate zombie */
-                       do
-                       {
-                               auto int stat;
-
-                               i = wait(&stat);
-                       } while (i >= 0 && i != pid);
+                       (void) waitfor(pid);
                        if (QueueIntvl != 0)
                                (void) setevent(QueueIntvl, runqueue, TRUE);
                        return;
                        if (QueueIntvl != 0)
                                (void) setevent(QueueIntvl, runqueue, TRUE);
                        return;
@@ -290,8 +313,8 @@ orderq()
 
        while (wn < WLSIZE && (d = readdir(f)) != NULL)
        {
 
        while (wn < WLSIZE && (d = readdir(f)) != NULL)
        {
-               char lbuf[MAXNAME];
                FILE *cf;
                FILE *cf;
+               char lbuf[MAXNAME];
 
                /* is this an interesting entry? */
                if (d->d_ino == 0)
 
                /* is this an interesting entry? */
                if (d->d_ino == 0)
@@ -317,11 +340,8 @@ orderq()
                /* extract useful information */
                while (fgets(lbuf, sizeof lbuf, cf) != NULL)
                {
                /* extract useful information */
                while (fgets(lbuf, sizeof lbuf, cf) != NULL)
                {
-                       fixcrlf(lbuf, TRUE);
-
-                       switch (lbuf[0])
+                       if (lbuf[0] == 'P')
                        {
                        {
-                         case 'P':             /* message priority */
                                (void) sscanf(&lbuf[1], "%ld", &wlist[wn].w_pri);
                                break;
                        }
                                (void) sscanf(&lbuf[1], "%ld", &wlist[wn].w_pri);
                                break;
                        }
@@ -339,6 +359,7 @@ orderq()
 
        /*
        **  Convert the work list into canonical form.
 
        /*
        **  Convert the work list into canonical form.
+       **      Should be turning it into a list of envelopes here perhaps.
        */
 
        wp = &WorkQ;
        */
 
        wp = &WorkQ;
@@ -406,7 +427,6 @@ dowork(w)
        register WORK *w;
 {
        register int i;
        register WORK *w;
 {
        register int i;
-       auto int xstat;
 
 # ifdef DEBUG
        if (tTd(40, 1))
 
 # ifdef DEBUG
        if (tTd(40, 1))
@@ -438,7 +458,7 @@ dowork(w)
                (void) alarm(0);
                CurEnv->e_flags &= ~EF_FATALERRS;
                QueueRun = TRUE;
                (void) alarm(0);
                CurEnv->e_flags &= ~EF_FATALERRS;
                QueueRun = TRUE;
-               MailBack = TRUE;
+               ErrorMode = EM_MAIL;
                CurEnv->e_id = &w->w_name[2];
 # ifdef LOG
                if (LogLevel > 11)
                CurEnv->e_id = &w->w_name[2];
 # ifdef LOG
                if (LogLevel > 11)
@@ -468,9 +488,9 @@ dowork(w)
                initsys();
 
                /* read the queue control file */
                initsys();
 
                /* read the queue control file */
-               readqf(queuename(CurEnv, 'q'));
+               readqf(CurEnv);
                CurEnv->e_flags |= EF_INQUEUE;
                CurEnv->e_flags |= EF_INQUEUE;
-               eatheader();
+               eatheader(CurEnv);
 
                /* do the delivery */
                if (!bitset(EF_FATALERRS, CurEnv->e_flags))
 
                /* do the delivery */
                if (!bitset(EF_FATALERRS, CurEnv->e_flags))
@@ -494,19 +514,13 @@ dowork(w)
        */
 
        errno = 0;
        */
 
        errno = 0;
-       while ((i = wait(&xstat)) > 0 && errno != EINTR)
-       {
-               if (errno == EINTR)
-               {
-                       errno = 0;
-               }
-       }
+       (void) waitfor(i);
 }
 \f/*
 **  READQF -- read queue file and set up environment.
 **
 **     Parameters:
 }
 \f/*
 **  READQF -- read queue file and set up environment.
 **
 **     Parameters:
-**             cf -- name of queue control file.
+**             e -- the envelope of the job to run.
 **
 **     Returns:
 **             none.
 **
 **     Returns:
 **             none.
@@ -516,31 +530,35 @@ dowork(w)
 **             we had been invoked by argument.
 */
 
 **             we had been invoked by argument.
 */
 
-readqf(cf)
-       char *cf;
+readqf(e)
+       register ENVELOPE *e;
 {
        register FILE *f;
        char buf[MAXFIELD];
        extern char *fgetfolded();
 {
        register FILE *f;
        char buf[MAXFIELD];
        extern char *fgetfolded();
+       register char *p;
        extern ADDRESS *sendto();
 
        /*
        **  Open the file created by queueup.
        */
 
        extern ADDRESS *sendto();
 
        /*
        **  Open the file created by queueup.
        */
 
-       f = fopen(cf, "r");
+       p = queuename(e, 'q');
+       f = fopen(p, "r");
        if (f == NULL)
        {
        if (f == NULL)
        {
-               syserr("readqf: no cf file %s", cf);
+               syserr("readqf: no control file %s", p);
                return;
        }
                return;
        }
+       FileName = p;
+       LineNumber = 0;
 
        /*
        **  Read and process the file.
        */
 
        if (Verbose)
 
        /*
        **  Read and process the file.
        */
 
        if (Verbose)
-               printf("\nRunning %s\n", cf);
+               printf("\nRunning %s\n", e->e_id);
        while (fgetfolded(buf, sizeof buf, f) != NULL)
        {
                switch (buf[0])
        while (fgetfolded(buf, sizeof buf, f) != NULL)
        {
                switch (buf[0])
@@ -558,36 +576,34 @@ readqf(cf)
                        break;
 
                  case 'D':             /* data file name */
                        break;
 
                  case 'D':             /* data file name */
-                       CurEnv->e_df = newstr(&buf[1]);
-                       TempFile = fopen(CurEnv->e_df, "r");
+                       e->e_df = newstr(&buf[1]);
+                       TempFile = fopen(e->e_df, "r");
                        if (TempFile == NULL)
                        if (TempFile == NULL)
-                               syserr("readqf: cannot open %s", CurEnv->e_df);
+                               syserr("readqf: cannot open %s", e->e_df);
                        break;
 
                  case 'T':             /* init time */
                        break;
 
                  case 'T':             /* init time */
-                       (void) sscanf(&buf[1], "%ld", &CurEnv->e_ctime);
+                       (void) sscanf(&buf[1], "%ld", &e->e_ctime);
                        break;
 
                  case 'P':             /* message priority */
                        break;
 
                  case 'P':             /* message priority */
-                       (void) sscanf(&buf[1], "%ld", &CurEnv->e_msgpriority);
+                       (void) sscanf(&buf[1], "%ld", &e->e_msgpriority);
 
                        /* make sure that big things get sent eventually */
 
                        /* make sure that big things get sent eventually */
-                       CurEnv->e_msgpriority -= WKTIMEFACT;
-                       break;
-
-                 case 'C':             /* message class */
-                       (void) sscanf(&buf[1], "%hd", &CurEnv->e_class);
+                       e->e_msgpriority -= WKTIMEFACT;
                        break;
 
                  case 'M':             /* define macro */
                        break;
 
                  case 'M':             /* define macro */
-                       define(buf[1], newstr(&buf[2]));
+                       define(buf[1], newstr(&buf[2]), e);
                        break;
 
                  default:
                        break;
 
                  default:
-                       syserr("readqf(%s): bad line \"%s\"", cf, buf);
+                       syserr("readqf(%s): bad line \"%s\"", e->e_id, buf);
                        break;
                }
        }
                        break;
                }
        }
+
+       FileName = NULL;
 }
 \f/*
 **  TIMEOUT -- process timeout on queue file.
 }
 \f/*
 **  TIMEOUT -- process timeout on queue file.
index 4d43928..0f05e49 100644 (file)
@@ -1,6 +1,6 @@
 # include "sendmail.h"
 
 # include "sendmail.h"
 
-SCCSID(@(#)readcf.c    3.47            %G%);
+SCCSID(@(#)readcf.c    3.48            %G%);
 
 /*
 **  READCF -- read control file.
 
 /*
 **  READCF -- read control file.
@@ -69,6 +69,7 @@ readcf(cfname, safe)
                exit(EX_OSFILE);
        }
 
                exit(EX_OSFILE);
        }
 
+       FileName = cfname;
        LineNumber = 0;
        while (fgetfolded(buf, sizeof buf, cf) != NULL)
        {
        LineNumber = 0;
        while (fgetfolded(buf, sizeof buf, cf) != NULL)
        {
@@ -84,8 +85,7 @@ readcf(cfname, safe)
 
                        if (*p == '\0')
                        {
 
                        if (*p == '\0')
                        {
-                               syserr("line %d: invalid rewrite line \"%s\"",
-                                       LineNumber, buf);
+                               syserr("invalid rewrite line \"%s\"", buf);
                                break;
                        }
 
                                break;
                        }
 
@@ -126,15 +126,14 @@ readcf(cfname, safe)
                        ruleset = atoi(&buf[1]);
                        if (ruleset >= MAXRWSETS || ruleset < 0)
                        {
                        ruleset = atoi(&buf[1]);
                        if (ruleset >= MAXRWSETS || ruleset < 0)
                        {
-                               syserr("readcf: line %d: bad ruleset %d (%d max)",
-                                       LineNumber, ruleset, MAXRWSETS);
+                               syserr("bad ruleset %d (%d max)", ruleset, MAXRWSETS);
                                ruleset = 0;
                        }
                        rwp = NULL;
                        break;
 
                  case 'D':             /* macro definition */
                                ruleset = 0;
                        }
                        rwp = NULL;
                        break;
 
                  case 'D':             /* macro definition */
-                       define(buf[1], newstr(&buf[2]));
+                       define(buf[1], newstr(&buf[2]), CurEnv);
                        break;
 
                  case 'H':             /* required header line */
                        break;
 
                  case 'H':             /* required header line */
@@ -145,7 +144,10 @@ readcf(cfname, safe)
                  case 'F':             /* word class from file */
                        class = buf[1];
                        if (!isalpha(class))
                  case 'F':             /* word class from file */
                        class = buf[1];
                        if (!isalpha(class))
-                               goto badline;
+                       {
+                               syserr("illegal class name %c", class);
+                               break;
+                       }
                        if (isupper(class))
                                class -= 'A';
                        else
                        if (isupper(class))
                                class -= 'A';
                        else
@@ -206,7 +208,7 @@ readcf(cfname, safe)
                                toomany('P', MAXPRIORITIES);
                                break;
                        }
                                toomany('P', MAXPRIORITIES);
                                break;
                        }
-                       for (p = &buf[1]; *p != '\0' && *p != '='; p++)
+                       for (p = &buf[1]; *p != '\0' && *p != '=' && *p != '\t'; p++)
                                continue;
                        if (*p == '\0')
                                goto badline;
                                continue;
                        if (*p == '\0')
                                goto badline;
@@ -242,10 +244,10 @@ readcf(cfname, safe)
 
                  default:
                  badline:
 
                  default:
                  badline:
-                       syserr("readcf: line %d: unknown control line \"%s\"",
-                               LineNumber, buf);
+                       syserr("unknown control line \"%s\"", buf);
                }
        }
                }
        }
+       FileName = NULL;
 }
 \f/*
 **  TOOMANY -- signal too many of some option
 }
 \f/*
 **  TOOMANY -- signal too many of some option
@@ -265,8 +267,7 @@ toomany(id, maxcnt)
        char id;
        int maxcnt;
 {
        char id;
        int maxcnt;
 {
-       syserr("readcf: line %d: too many %c lines, %d max",
-              LineNumber, id, maxcnt);
+       syserr("too many %c lines, %d max", id, maxcnt);
 }
 \f/*
 **  FILECLASS -- read members of a class from a file
 }
 \f/*
 **  FILECLASS -- read members of a class from a file
@@ -367,8 +368,7 @@ makemailer(line, safe)
 
        if (NextMailer >= MAXMAILERS)
        {
 
        if (NextMailer >= MAXMAILERS)
        {
-               syserr("readcf: line %d: too many mailers defined (%d max)",
-                       LineNumber, MAXMAILERS);
+               syserr("too many mailers defined (%d max)", MAXMAILERS);
                return;
        }
 
                return;
        }
 
@@ -389,8 +389,7 @@ makemailer(line, safe)
 
        if (*p == '\0')
        {
 
        if (*p == '\0')
        {
-               syserr("readcf: line %d: invalid M line in configuration file",
-                       LineNumber);
+               syserr("invalid M line in configuration file");
                return;
        }
        if (msset >= MAXRWSETS || mrset >= MAXRWSETS)
                return;
        }
        if (msset >= MAXRWSETS || mrset >= MAXRWSETS)
@@ -407,7 +406,6 @@ makemailer(line, safe)
        m->m_flags = mopts;
        m->m_r_rwset = mrset;
        m->m_s_rwset = msset;
        m->m_flags = mopts;
        m->m_r_rwset = mrset;
        m->m_s_rwset = msset;
-       m->m_badstat = EX_UNAVAILABLE;
        m->m_mno = NextMailer;
        Mailer[NextMailer++] = m;
 
        m->m_mno = NextMailer;
        Mailer[NextMailer++] = m;
 
@@ -487,7 +485,7 @@ struct optlist      OptList[] =
 {
        'f',    M_FOPT,
        'r',    M_ROPT,
 {
        'f',    M_FOPT,
        'r',    M_ROPT,
-       'q',    M_QUIET,
+       'P',    M_RPATH,
        'S',    M_RESTR,
        'n',    M_NHDR,
        'l',    M_LOCAL,
        'S',    M_RESTR,
        'n',    M_NHDR,
        'l',    M_LOCAL,
@@ -583,9 +581,6 @@ setoption(opt, val, safe, sticky)
        bool safe;
        bool sticky;
 {
        bool safe;
        bool sticky;
 {
-       time_t tval;
-       int ival;
-       bool bval;
        int smask;
        int sindex;
        extern bool atobool();
        int smask;
        int sindex;
        extern bool atobool();
@@ -620,43 +615,21 @@ setoption(opt, val, safe, sticky)
        if (getruid() == 0)
                safe = TRUE;
 
        if (getruid() == 0)
                safe = TRUE;
 
-       /*
-       **  Encode this option as appropriate.
-       */
-
-       if (index("rT", opt) != NULL)
-               tval = convtime(val);
-       else if (index("gLu", opt) != NULL)
-               ival = atoi(val);
-       else if (index("F", opt) != NULL)
-               ival = atooct(val);
-       else if (index("acDfimosv", opt) != NULL)
-               bval = atobool(val);
-       else if (index("be", opt) != NULL)
-               /* do nothing */ ;
-       else if (val[0] == '\0')
-               val = "";
-       else
-               val = newstr(val);
-
-       /*
-       **  Now do the actual assignment.
-       */
-
        switch (opt)
        {
          case 'A':             /* set default alias file */
        switch (opt)
        {
          case 'A':             /* set default alias file */
-               AliasFile = val;
-               if (AliasFile[0] == '\0')
+               if (val[0] == '\0')
                        AliasFile = "aliases";
                        AliasFile = "aliases";
+               else
+                       AliasFile = newstr(val);
                break;
 
          case 'a':             /* look for "@:@" in alias file */
                break;
 
          case 'a':             /* look for "@:@" in alias file */
-               SafeAlias = bval;
+               SafeAlias = atobool(val);
                break;
 
          case 'c':             /* don't connect to "expensive" mailers */
                break;
 
          case 'c':             /* don't connect to "expensive" mailers */
-               NoConnect = bval;
+               NoConnect = atobool(val);
                break;
 
          case 'd':             /* delivery mode */
                break;
 
          case 'd':             /* delivery mode */
@@ -679,125 +652,121 @@ setoption(opt, val, safe, sticky)
                break;
 
          case 'D':             /* rebuild alias database as needed */
                break;
 
          case 'D':             /* rebuild alias database as needed */
-               AutoRebuild = bval;
+               AutoRebuild = atobool(val);
                break;
 
          case 'e':             /* set error processing mode */
                switch (*val)
                {
                break;
 
          case 'e':             /* set error processing mode */
                switch (*val)
                {
-                 case 'p':     /* print errors normally */
-                       break;  /* (default) */
-
-                 case 'q':     /* be silent about it */
+                 case EM_QUIET:        /* be silent about it */
                        (void) freopen("/dev/null", "w", stdout);
                        (void) freopen("/dev/null", "w", stdout);
-                       break;
-
-                 case 'm':     /* mail back */
-                       MailBack = TRUE;
-                       HoldErrs = TRUE;
-                       break;
+                       /* fall through... */
 
 
-                 case 'e':     /* do berknet error processing */
-                       BerkNet = TRUE;
+                 case EM_MAIL:         /* mail back */
+                 case EM_BERKNET:      /* do berknet error processing */
+                 case EM_WRITE:        /* write back (or mail) */
                        HoldErrs = TRUE;
                        HoldErrs = TRUE;
-                       break;
+                       /* fall through... */
 
 
-                 case 'w':     /* write back (or mail) */
-                       WriteBack = TRUE;
-                       HoldErrs = TRUE;
+                 case EM_PRINT:        /* print errors normally (default) */
+                       ErrorMode = *val;
                        break;
                }
                break;
 
          case 'F':             /* file mode */
                        break;
                }
                break;
 
          case 'F':             /* file mode */
-               FileMode = ival;
+               FileMode = atooct(val);
                break;
 
          case 'f':             /* save Unix-style From lines on front */
                break;
 
          case 'f':             /* save Unix-style From lines on front */
-               SaveFrom = bval;
+               SaveFrom = atobool(val);
                break;
 
          case 'g':             /* default gid */
                if (safe)
                break;
 
          case 'g':             /* default gid */
                if (safe)
-                       DefGid = ival;
+                       DefGid = atoi(val);
                break;
 
          case 'H':             /* help file */
                break;
 
          case 'H':             /* help file */
-               HelpFile = val;
-               if (HelpFile[0] == '\0')
+               if (val[0] == '\0')
                        HelpFile = "sendmail.hf";
                        HelpFile = "sendmail.hf";
+               else
+                       HelpFile = newstr(val);
                break;
 
          case 'i':             /* ignore dot lines in message */
                break;
 
          case 'i':             /* ignore dot lines in message */
-               IgnrDot = bval;
+               IgnrDot = atobool(val);
                break;
 
          case 'L':             /* log level */
                break;
 
          case 'L':             /* log level */
-               LogLevel = ival;
+               LogLevel = atoi(val);
                break;
 
          case 'M':             /* define macro */
                break;
 
          case 'M':             /* define macro */
-               define(val[0], &val[1]);
+               define(val[0], newstr(&val[1]), CurEnv);
                break;
 
          case 'm':             /* send to me too */
                break;
 
          case 'm':             /* send to me too */
-               MeToo = bval;
+               MeToo = atobool(val);
                break;
 
          case 'o':             /* assume old style headers */
                break;
 
          case 'o':             /* assume old style headers */
-               if (bval)
+               if (atobool(val))
                        CurEnv->e_flags |= EF_OLDSTYLE;
                else
                        CurEnv->e_flags &= ~EF_OLDSTYLE;
                break;
 
          case 'Q':             /* queue directory */
                        CurEnv->e_flags |= EF_OLDSTYLE;
                else
                        CurEnv->e_flags &= ~EF_OLDSTYLE;
                break;
 
          case 'Q':             /* queue directory */
-               QueueDir = val;
-               if (QueueDir[0] == '\0')
+               if (val[0] == '\0')
                        QueueDir = "mqueue";
                        QueueDir = "mqueue";
+               else
+                       QueueDir = newstr(val);
                break;
 
          case 'r':             /* read timeout */
                break;
 
          case 'r':             /* read timeout */
-               ReadTimeout = tval;
+               ReadTimeout = convtime(val);
                break;
 
          case 'S':             /* status file */
                break;
 
          case 'S':             /* status file */
-               StatFile = val;
-               if (StatFile[0] == '\0')
+               if (val[0] == '\0')
                        StatFile = "sendmail.st";
                        StatFile = "sendmail.st";
+               else
+                       StatFile = newstr(val);
                break;
 
          case 's':             /* be super safe, even if expensive */
                break;
 
          case 's':             /* be super safe, even if expensive */
-               SuperSafe = bval;
+               SuperSafe = atobool(val);
                break;
 
          case 'T':             /* queue timeout */
                break;
 
          case 'T':             /* queue timeout */
-               TimeOut = tval;
+               TimeOut = convtime(val);
                break;
 
          case 't':             /* time zone name */
 # ifdef V6
                break;
 
          case 't':             /* time zone name */
 # ifdef V6
-               StdTimezone = val;
-               DstTimezone = index(val, ',');
+               StdTimezone = newstr(val);
+               DstTimezone = index(StdTimeZone, ',');
                if (DstTimezone == NULL)
                if (DstTimezone == NULL)
-                       goto syntax;
-               *DstTimezone++ = '\0';
+                       syserr("bad time zone spec");
+               else
+                       *DstTimezone++ = '\0';
 # endif V6
                break;
 
          case 'u':             /* set default uid */
                if (safe)
 # endif V6
                break;
 
          case 'u':             /* set default uid */
                if (safe)
-                       DefUid = ival;
+                       DefUid = atoi(val);
                break;
 
          case 'v':             /* run in verbose mode */
                break;
 
          case 'v':             /* run in verbose mode */
-               Verbose = bval;
+               Verbose = atobool(val);
                break;
 
 # ifdef DEBUG
          case 'W':             /* set the wizards password */
                if (safe)
                break;
 
 # ifdef DEBUG
          case 'W':             /* set the wizards password */
                if (safe)
-                       WizWord = val;
+                       WizWord = newstr(val);
                break;
 # endif DEBUG
 
                break;
 # endif DEBUG
 
@@ -805,8 +774,4 @@ setoption(opt, val, safe, sticky)
                break;
        }
        return;
                break;
        }
        return;
-
-  syntax:
-       syserr("setoption: line %d: syntax error on \"%c%s\"",
-              LineNumber, opt, val);
 }
 }
index e5df3e9..ce37282 100644 (file)
@@ -2,7 +2,7 @@
 # include "sendmail.h"
 # include <sys/stat.h>
 
 # include "sendmail.h"
 # include <sys/stat.h>
 
-SCCSID(@(#)recipient.c 3.47            %G%);
+SCCSID(@(#)recipient.c 3.48            %G%);
 
 /*
 **  SENDTO -- Designate a send list.
 
 /*
 **  SENDTO -- Designate a send list.
@@ -91,7 +91,7 @@ sendto(list, copyf, ctladdr, qflags)
                        a->q_flags |= QPRIMARY;
 
                /* put on send queue or suppress self-reference */
                        a->q_flags |= QPRIMARY;
 
                /* put on send queue or suppress self-reference */
-               if (ctladdr != NULL && sameaddr(ctladdr, a, FALSE))
+               if (ctladdr != NULL && sameaddr(ctladdr, a))
                        selfref = TRUE;
                else
                        al = a;
                        selfref = TRUE;
                else
                        al = a;
@@ -256,7 +256,7 @@ recipient(a, sendq)
 
        for (pq = sendq; (q = *pq) != NULL; pq = &q->q_next)
        {
 
        for (pq = sendq; (q = *pq) != NULL; pq = &q->q_next)
        {
-               if (!ForceMail && sameaddr(q, a, FALSE))
+               if (!ForceMail && sameaddr(q, a))
                {
 # ifdef DEBUG
                        if (tTd(26, 1))
                {
 # ifdef DEBUG
                        if (tTd(26, 1))
@@ -278,8 +278,6 @@ recipient(a, sendq)
        /* add address on list */
        *pq = a;
        a->q_next = NULL;
        /* add address on list */
        *pq = a;
        a->q_next = NULL;
-       if (DontSend)
-               a->q_flags |= QDONTSEND;
 
        /*
        **  Alias the name and handle :include: specs.
 
        /*
        **  Alias the name and handle :include: specs.
@@ -329,7 +327,7 @@ recipient(a, sendq)
                            (*p = '\0', !safefile(buf, getruid(), S_IWRITE|S_IEXEC)))
                        {
                                a->q_flags |= QBADADDR;
                            (*p = '\0', !safefile(buf, getruid(), S_IWRITE|S_IEXEC)))
                        {
                                a->q_flags |= QBADADDR;
-                               giveresponse(EX_CANTCREAT, TRUE, m);
+                               giveresponse(EX_CANTCREAT, m);
                        }
                }
                else
                        }
                }
                else
@@ -342,7 +340,7 @@ recipient(a, sendq)
                        if (pw == NULL)
                        {
                                a->q_flags |= QBADADDR;
                        if (pw == NULL)
                        {
                                a->q_flags |= QBADADDR;
-                               giveresponse(EX_NOUSER, TRUE, m);
+                               giveresponse(EX_NOUSER, m);
                        }
                        else
                        {
                        }
                        else
                        {
@@ -379,6 +377,9 @@ recipient(a, sendq)
 **     This looks a lot like getpwnam, except that it may want to
 **     do some fancier pattern matching in /etc/passwd.
 **
 **     This looks a lot like getpwnam, except that it may want to
 **     do some fancier pattern matching in /etc/passwd.
 **
+**     This routine contains most of the time of many sendmail runs.
+**     It deserves to be optimized.
+**
 **     Parameters:
 **             name -- the name to match against.
 **
 **     Parameters:
 **             name -- the name to match against.
 **
@@ -507,6 +508,8 @@ include(fname, msg, ctladdr, sendq)
        char buf[MAXLINE];
        register FILE *fp;
        char *oldto = CurEnv->e_to;
        char buf[MAXLINE];
        register FILE *fp;
        char *oldto = CurEnv->e_to;
+       char *oldfilename = FileName;
+       int oldlinenumber = LineNumber;
 
        fp = fopen(fname, "r");
        if (fp == NULL)
 
        fp = fopen(fname, "r");
        if (fp == NULL)
@@ -526,6 +529,8 @@ include(fname, msg, ctladdr, sendq)
        }
 
        /* read the file -- each line is a comma-separated list. */
        }
 
        /* read the file -- each line is a comma-separated list. */
+       FileName = fname;
+       LineNumber = 0;
        while (fgets(buf, sizeof buf, fp) != NULL)
        {
                register char *p = index(buf, '\n');
        while (fgets(buf, sizeof buf, fp) != NULL)
        {
                register char *p = index(buf, '\n');
@@ -542,6 +547,8 @@ include(fname, msg, ctladdr, sendq)
        }
 
        (void) fclose(fp);
        }
 
        (void) fclose(fp);
+       FileName = oldfilename;
+       LineNumber = oldlinenumber;
 }
 \f/*
 **  SENDTOARGV -- send to an argument vector.
 }
 \f/*
 **  SENDTOARGV -- send to an argument vector.
index 4b3fc6b..7054cbf 100644 (file)
@@ -1,12 +1,12 @@
 # include <pwd.h>
 # include "sendmail.h"
 
 # include <pwd.h>
 # include "sendmail.h"
 
-SCCSID(@(#)savemail.c  3.49            %G%);
+SCCSID(@(#)savemail.c  3.50            %G%);
 
 /*
 **  SAVEMAIL -- Save mail on error
 **
 
 /*
 **  SAVEMAIL -- Save mail on error
 **
-**     If the MailBack flag is set, mail it back to the originator
+**     If mailing back errors, mail it back to the originator
 **     together with an error message; otherwise, just put it in
 **     dead.letter in the user's home directory (if he exists on
 **     this machine).
 **     together with an error message; otherwise, just put it in
 **     dead.letter in the user's home directory (if he exists on
 **     this machine).
@@ -32,15 +32,14 @@ savemail(e)
        extern struct passwd *getpwnam();
        register char *p;
        extern char *ttypath();
        extern struct passwd *getpwnam();
        register char *p;
        extern char *ttypath();
-       static int exclusive;
        typedef int (*fnptr)();
 
 # ifdef DEBUG
        if (tTd(6, 1))
        typedef int (*fnptr)();
 
 # ifdef DEBUG
        if (tTd(6, 1))
-               printf("\nsavemail: exclusive %d\n", exclusive);
+               printf("\nsavemail\n");
 # endif DEBUG
 
 # endif DEBUG
 
-       if (exclusive++)
+       if (bitset(EF_RESPONSE, e->e_flags))
                return;
        if (e->e_class < 0)
        {
                return;
        if (e->e_class < 0)
        {
@@ -75,45 +74,56 @@ savemail(e)
        **  Also, if the from address is not local, mail it back.
        */
 
        **  Also, if the from address is not local, mail it back.
        */
 
-       if (BerkNet)
+       if (ErrorMode == EM_BERKNET)
        {
                ExitStat = EX_OK;
        {
                ExitStat = EX_OK;
-               MailBack = TRUE;
+               ErrorMode = EM_MAIL;
        }
        if (!bitset(M_LOCAL, CurEnv->e_returnto->q_mailer->m_flags))
        }
        if (!bitset(M_LOCAL, CurEnv->e_returnto->q_mailer->m_flags))
-               MailBack = TRUE;
+               ErrorMode = EM_MAIL;
 
        /*
        **  If writing back, do it.
        **      If the user is still logged in on the same terminal,
        **      then write the error messages back to hir (sic).
 
        /*
        **  If writing back, do it.
        **      If the user is still logged in on the same terminal,
        **      then write the error messages back to hir (sic).
-       **      If not, set the MailBack flag so that it will get
-       **      mailed back instead.
+       **      If not, mail back instead.
        */
 
        */
 
-       if (WriteBack)
+       if (ErrorMode == EM_WRITE)
        {
                p = ttypath();
                if (p == NULL || freopen(p, "w", stdout) == NULL)
                {
        {
                p = ttypath();
                if (p == NULL || freopen(p, "w", stdout) == NULL)
                {
-                       MailBack = TRUE;
+                       ErrorMode = EM_MAIL;
                        errno = 0;
                }
                else
                {
                        errno = 0;
                }
                else
                {
+                       expand("$n", buf, &buf[sizeof buf - 1], e);
+                       printf("\r\nMessage from %s...\r\n", buf);
+                       printf("Errors occurred while sending mail.\r\n");
                        if (Xscript != NULL)
                        if (Xscript != NULL)
+                       {
                                (void) fflush(Xscript);
                                (void) fflush(Xscript);
-                       xfile = fopen(queuename(e, 'x'), "r");
+                               xfile = fopen(queuename(e, 'x'), "r");
+                       }
+                       else
+                               xfile = NULL;
                        if (xfile == NULL)
                        if (xfile == NULL)
+                       {
                                syserr("Cannot open %s", queuename(e, 'x'));
                                syserr("Cannot open %s", queuename(e, 'x'));
-                       expand("$n", buf, &buf[sizeof buf - 1], e);
-                       printf("\r\nMessage from %s...\r\n", buf);
-                       printf("Errors occurred while sending mail; transcript follows:\r\n");
-                       while (fgets(buf, sizeof buf, xfile) != NULL && !ferror(stdout))
-                               fputs(buf, stdout);
+                               printf("Transcript of session is unavailable.\r\n");
+                       }
+                       else
+                       {
+                               printf("Transcript follows:\r\n");
+                               while (fgets(buf, sizeof buf, xfile) != NULL &&
+                                      !ferror(stdout))
+                                       fputs(buf, stdout);
+                               (void) fclose(xfile);
+                       }
                        if (ferror(stdout))
                                (void) syserr("savemail: stdout: write err");
                        if (ferror(stdout))
                                (void) syserr("savemail: stdout: write err");
-                       (void) fclose(xfile);
                }
        }
 
                }
        }
 
@@ -128,7 +138,7 @@ savemail(e)
        **      sender.
        */
 
        **      sender.
        */
 
-       if (MailBack)
+       if (ErrorMode == EM_MAIL)
        {
                if (returntosender("Unable to deliver mail", CurEnv->e_returnto, TRUE) == 0)
                        return;
        {
                if (returntosender("Unable to deliver mail", CurEnv->e_returnto, TRUE) == 0)
                        return;
@@ -140,13 +150,8 @@ savemail(e)
        **      should save the message in dead.letter so that the
        **      poor person doesn't have to type it over again --
        **      and we all know what poor typists programmers are.
        **      should save the message in dead.letter so that the
        **      poor person doesn't have to type it over again --
        **      and we all know what poor typists programmers are.
-       **      However, if we are running a "smart" protocol, we don't
-       **      bother to return the message, since the other end is
-       **      expected to handle that.
        */
 
        */
 
-       if (OpMode == MD_ARPAFTP || OpMode == MD_SMTP)
-               return;
        p = NULL;
        if (CurEnv->e_returnto->q_mailer == LocalMailer)
        {
        p = NULL;
        if (CurEnv->e_returnto->q_mailer == LocalMailer)
        {
@@ -168,19 +173,19 @@ savemail(e)
                bool oldverb = Verbose;
 
                /* we have a home directory; open dead.letter */
                bool oldverb = Verbose;
 
                /* we have a home directory; open dead.letter */
+               define('z', p, e);
+               expand("$z/dead.letter", buf, &buf[sizeof buf - 1], e);
                Verbose = TRUE;
                Verbose = TRUE;
-               message(Arpa_Info, "Saving message in dead.letter");
+               message(Arpa_Info, "Saving message in %s", buf);
                Verbose = oldverb;
                Verbose = oldverb;
-               define('z', p);
-               expand("$z/dead.letter", buf, &buf[sizeof buf - 1], e);
                e->e_to = buf;
                q = NULL;
                sendto(buf, (ADDRESS *) NULL, &q);
                e->e_to = buf;
                q = NULL;
                sendto(buf, (ADDRESS *) NULL, &q);
-               (void) deliver(q);
+               (void) deliver(e, q);
        }
 
        /* add terminator to writeback message */
        }
 
        /* add terminator to writeback message */
-       if (WriteBack)
+       if (ErrorMode == EM_WRITE)
                printf("-----\r\n");
 }
 \f/*
                printf("-----\r\n");
 }
 \f/*
@@ -216,6 +221,7 @@ returntosender(msg, returnto, sendbody)
        extern ENVELOPE *newenvelope();
        ENVELOPE errenvelope;
        static int returndepth;
        extern ENVELOPE *newenvelope();
        ENVELOPE errenvelope;
        static int returndepth;
+       register ADDRESS *q;
 
 # ifdef DEBUG
        if (tTd(6, 1))
 
 # ifdef DEBUG
        if (tTd(6, 1))
@@ -223,7 +229,7 @@ returntosender(msg, returnto, sendbody)
                printf("Return To Sender: msg=\"%s\", depth=%d, CurEnv=%x,\n",
                       msg, returndepth, CurEnv);
                printf("\treturnto=");
                printf("Return To Sender: msg=\"%s\", depth=%d, CurEnv=%x,\n",
                       msg, returndepth, CurEnv);
                printf("\treturnto=");
-               printaddr(returnto, FALSE);
+               printaddr(returnto, TRUE);
        }
 # endif DEBUG
 
        }
 # endif DEBUG
 
@@ -236,14 +242,19 @@ returntosender(msg, returnto, sendbody)
                return (0);
        }
 
                return (0);
        }
 
-       NoAlias = TRUE;
        SendBody = sendbody;
        SendBody = sendbody;
-       define('g', "$f");
+       define('g', "$f", CurEnv);
        ee = newenvelope(&errenvelope);
        ee->e_puthdr = putheader;
        ee->e_putbody = errbody;
        ee = newenvelope(&errenvelope);
        ee->e_puthdr = putheader;
        ee->e_putbody = errbody;
+       ee->e_flags |= EF_RESPONSE;
+       ee->e_sendqueue = returnto;
        (void) queuename(ee, '\0');
        (void) queuename(ee, '\0');
-       addheader("to", returnto->q_paddr, ee);
+       for (q = returnto; q != NULL; q = q->q_next)
+       {
+               if (q->q_alias == NULL)
+                       addheader("to", q->q_paddr, ee);
+       }
        addheader("subject", msg, ee);
 
        /* fake up an address header for the from person */
        addheader("subject", msg, ee);
 
        /* fake up an address header for the from person */
@@ -255,19 +266,15 @@ returntosender(msg, returnto, sendbody)
                returndepth--;
                return (-1);
        }
                returndepth--;
                return (-1);
        }
-       ee->e_sendqueue = returnto;
 
        /* push state into submessage */
        CurEnv = ee;
 
        /* push state into submessage */
        CurEnv = ee;
-       define('f', "$n");
-       define('x', "Mail Delivery Subsystem");
+       define('f', "$n", ee);
+       define('x', "Mail Delivery Subsystem", ee);
 
        /* actually deliver the error message */
        sendall(ee, SendMode);
 
 
        /* actually deliver the error message */
        sendall(ee, SendMode);
 
-       /* do any closing error processing */
-       checkerrors(ee);
-
        /* restore state */
        dropenvelope(ee);
        CurEnv = CurEnv->e_parent;
        /* restore state */
        dropenvelope(ee);
        CurEnv = CurEnv->e_parent;
@@ -346,7 +353,7 @@ errbody(fp, m, xdot)
                {
                        fprintf(fp, "\n  ----- Message header follows -----\n");
                        (void) fflush(fp);
                {
                        fprintf(fp, "\n  ----- Message header follows -----\n");
                        (void) fflush(fp);
-                       putheader(fp, m, CurEnv);
+                       putheader(fp, m, CurEnv->e_parent);
                }
        }
        else
                }
        }
        else
index c68f399..789d1ad 100644 (file)
@@ -7,7 +7,7 @@
 # ifdef _DEFINE
 # define EXTERN
 # ifndef lint
 # ifdef _DEFINE
 # define EXTERN
 # ifndef lint
-static char SmailSccsId[] =    "@(#)sendmail.h 3.101           %G%";
+static char SmailSccsId[] =    "@(#)sendmail.h 3.102           %G%";
 # endif lint
 # else  _DEFINE
 # define EXTERN extern
 # endif lint
 # else  _DEFINE
 # define EXTERN extern
@@ -83,7 +83,6 @@ struct mailer
        char    *m_name;        /* symbolic name of this mailer */
        char    *m_mailer;      /* pathname of the mailer to use */
        u_long  m_flags;        /* status flags, see below */
        char    *m_name;        /* symbolic name of this mailer */
        char    *m_mailer;      /* pathname of the mailer to use */
        u_long  m_flags;        /* status flags, see below */
-       short   m_badstat;      /* the status code to use on unknown error */
        short   m_mno;          /* mailer number internally */
        char    **m_argv;       /* template argument vector */
        short   m_s_rwset;      /* rewriting set for sender addresses */
        short   m_mno;          /* mailer number internally */
        char    **m_argv;       /* template argument vector */
        short   m_s_rwset;      /* rewriting set for sender addresses */
@@ -95,7 +94,7 @@ typedef struct mailer MAILER;
 /* bits for m_flags */
 # define M_FOPT                000000001L      /* mailer takes picky -f flag */
 # define M_ROPT                000000002L      /* mailer takes picky -r flag */
 /* bits for m_flags */
 # define M_FOPT                000000001L      /* mailer takes picky -f flag */
 # define M_ROPT                000000002L      /* mailer takes picky -r flag */
-# define M_QUIET       000000004L      /* don't print error on bad status */
+# define M_RPATH       000000004L      /* wants a Return-Path: line */
 # define M_RESTR       000000010L      /* must be daemon to execute */
 # define M_NHDR                000000020L      /* don't insert From line */
 # define M_LOCAL       000000040L      /* delivery is to this host */
 # define M_RESTR       000000010L      /* must be daemon to execute */
 # define M_NHDR                000000020L      /* don't insert From line */
 # define M_LOCAL       000000040L      /* delivery is to this host */
@@ -153,7 +152,6 @@ extern struct hdrinfo       HdrInfo[];
 # define H_EOH         00001   /* this field terminates header */
 # define H_RCPT                00002   /* contains recipient addresses */
 # define H_DEFAULT     00004   /* if another value is found, drop this */
 # define H_EOH         00001   /* this field terminates header */
 # define H_RCPT                00002   /* contains recipient addresses */
 # define H_DEFAULT     00004   /* if another value is found, drop this */
-# define H_USED                00010   /* indicates that this has been output */
 # define H_CHECK       00020   /* check h_mflags against m_flags */
 # define H_ACHECK      00040   /* ditto, but always (not just default) */
 # define H_FORCE       00100   /* force this field, even if default */
 # define H_CHECK       00020   /* check h_mflags against m_flags */
 # define H_ACHECK      00040   /* ditto, but always (not just default) */
 # define H_FORCE       00100   /* force this field, even if default */
@@ -183,6 +181,7 @@ struct envelope
        long            e_msgsize;      /* size of the message in bytes */
        short           e_class;        /* msg class (priority, junk, etc.) */
        short           e_flags;        /* flags, see below */
        long            e_msgsize;      /* size of the message in bytes */
        short           e_class;        /* msg class (priority, junk, etc.) */
        short           e_flags;        /* flags, see below */
+       short           e_hopcount;     /* number of times processed */
        int             (*e_puthdr)();  /* function to put header of message */
        int             (*e_putbody)(); /* function to put body of message */
        struct envelope *e_parent;      /* the message this one encloses */
        int             (*e_puthdr)();  /* function to put header of message */
        int             (*e_putbody)(); /* function to put body of message */
        struct envelope *e_parent;      /* the message this one encloses */
@@ -202,25 +201,10 @@ typedef struct envelope   ENVELOPE;
 #define EF_SENDRECEIPT 000020          /* send a return receipt */
 #define EF_FATALERRS   000040          /* fatal errors occured */
 #define EF_KEEPQUEUE   000100          /* keep queue files always */
 #define EF_SENDRECEIPT 000020          /* send a return receipt */
 #define EF_FATALERRS   000040          /* fatal errors occured */
 #define EF_KEEPQUEUE   000100          /* keep queue files always */
+#define EF_RESPONSE    000200          /* this is an error or return receipt */
 
 EXTERN ENVELOPE        *CurEnv;        /* envelope currently being processed */
 \f/*
 
 EXTERN ENVELOPE        *CurEnv;        /* envelope currently being processed */
 \f/*
-**  Work queue.
-*/
-
-struct work
-{
-       char            *w_name;        /* name of control file */
-       long            w_pri;          /* priority of message, see below */
-       struct work     *w_next;        /* next in queue */
-};
-
-typedef struct work    WORK;
-
-EXTERN WORK    *WorkQ;                 /* queue of things to be done */
-
-
-/*
 **  Message priorities.
 **     Priorities > 0 should be preemptive.
 **
 **  Message priorities.
 **     Priorities > 0 should be preemptive.
 **
@@ -343,23 +327,7 @@ typedef struct event       EVENT;
 
 EXTERN EVENT   *EventQueue;            /* head of event queue */
 \f/*
 
 EXTERN EVENT   *EventQueue;            /* head of event queue */
 \f/*
-**  Statistics structure.
-*/
-
-struct statistics
-{
-       time_t  stat_itime;             /* file initialization time */
-       short   stat_size;              /* size of this structure */
-       long    stat_nf[MAXMAILERS];    /* # msgs from each mailer */
-       long    stat_bf[MAXMAILERS];    /* kbytes from each mailer */
-       long    stat_nt[MAXMAILERS];    /* # msgs to each mailer */
-       long    stat_bt[MAXMAILERS];    /* kbytes to each mailer */
-};
-
-EXTERN struct statistics       Stat;
-extern long                    kbytes();       /* for _bf, _bt */
-\f/*
-**  Operation and send modes
+**  Operation, send, and error modes
 **
 **     The operation mode describes the basic operation of sendmail.
 **     This can be set from the command line, and is "send mail" by
 **
 **     The operation mode describes the basic operation of sendmail.
 **     This can be set from the command line, and is "send mail" by
@@ -371,7 +339,7 @@ extern long                 kbytes();       /* for _bf, _bt */
 **     -v (verbose) flag is given, it will be forced to SM_DELIVER
 **     mode.
 **
 **     -v (verbose) flag is given, it will be forced to SM_DELIVER
 **     mode.
 **
-**     The default send mode can be safely changed.
+**     The error mode tells how to return errors.
 */
 
 EXTERN char    OpMode;         /* operation mode, see below */
 */
 
 EXTERN char    OpMode;         /* operation mode, see below */
@@ -394,14 +362,20 @@ EXTERN char       SendMode;       /* send mode, see below */
 #define SM_FORK                'b'             /* deliver in background */
 #define SM_QUEUE       'q'             /* queue, don't deliver */
 #define SM_VERIFY      'v'             /* verify only (used internally) */
 #define SM_FORK                'b'             /* deliver in background */
 #define SM_QUEUE       'q'             /* queue, don't deliver */
 #define SM_VERIFY      'v'             /* verify only (used internally) */
+
+
+EXTERN char    ErrorMode;      /* error mode, see below */
+
+#define EM_PRINT       'p'             /* print errors */
+#define EM_MAIL                'm'             /* mail back errors */
+#define EM_WRITE       'w'             /* write back errors */
+#define EM_BERKNET     'e'             /* special berknet processing */
+#define EM_QUIET       'q'             /* don't print messages (stat only) */
 \f/*
 **  Global variables.
 */
 
 EXTERN bool    FromFlag;       /* if set, "From" person is explicit */
 \f/*
 **  Global variables.
 */
 
 EXTERN bool    FromFlag;       /* if set, "From" person is explicit */
-EXTERN bool    MailBack;       /* mail back response on error */
-EXTERN bool    BerkNet;        /* called from BerkNet */
-EXTERN bool    WriteBack;      /* write back response on error */
 EXTERN bool    NoAlias;        /* if set, don't do any aliasing */
 EXTERN bool    ForceMail;      /* if set, mail even if already got a copy */
 EXTERN bool    MeToo;          /* send to the sender also */
 EXTERN bool    NoAlias;        /* if set, don't do any aliasing */
 EXTERN bool    ForceMail;      /* if set, mail even if already got a copy */
 EXTERN bool    MeToo;          /* send to the sender also */
@@ -409,7 +383,6 @@ EXTERN bool IgnrDot;        /* don't let dot end messages */
 EXTERN bool    SaveFrom;       /* save leading "From" lines */
 EXTERN bool    Verbose;        /* set if blow-by-blow desired */
 EXTERN bool    GrabTo;         /* if set, get recipients from msg */
 EXTERN bool    SaveFrom;       /* save leading "From" lines */
 EXTERN bool    Verbose;        /* set if blow-by-blow desired */
 EXTERN bool    GrabTo;         /* if set, get recipients from msg */
-EXTERN bool    DontSend;       /* mark recipients as QDONTSEND */
 EXTERN bool    NoReturn;       /* don't return letter to sender */
 EXTERN bool    SuprErrs;       /* set if we are suppressing errors */
 EXTERN bool    QueueRun;       /* currently running message from the queue */
 EXTERN bool    NoReturn;       /* don't return letter to sender */
 EXTERN bool    SuprErrs;       /* set if we are suppressing errors */
 EXTERN bool    QueueRun;       /* currently running message from the queue */
@@ -430,7 +403,6 @@ EXTERN int  DefGid;         /* default gid to run as */
 EXTERN int     OldUmask;       /* umask when sendmail starts up */
 EXTERN int     Errors;         /* set if errors (local to single pass) */
 EXTERN int     ExitStat;       /* exit status code */
 EXTERN int     OldUmask;       /* umask when sendmail starts up */
 EXTERN int     Errors;         /* set if errors (local to single pass) */
 EXTERN int     ExitStat;       /* exit status code */
-EXTERN int     HopCount;       /* hop count */
 EXTERN int     AliasLevel;     /* depth of aliasing */
 EXTERN int     MotherPid;      /* proc id of parent process */
 EXTERN int     LineNumber;     /* line number in current input */
 EXTERN int     AliasLevel;     /* depth of aliasing */
 EXTERN int     MotherPid;      /* proc id of parent process */
 EXTERN int     LineNumber;     /* line number in current input */
@@ -443,6 +415,7 @@ EXTERN char *AliasFile;     /* location of alias file */
 EXTERN char    *HelpFile;      /* location of SMTP help file */
 EXTERN char    *StatFile;      /* location of statistics summary */
 EXTERN char    *QueueDir;      /* location of queue directory */
 EXTERN char    *HelpFile;      /* location of SMTP help file */
 EXTERN char    *StatFile;      /* location of statistics summary */
 EXTERN char    *QueueDir;      /* location of queue directory */
+EXTERN char    *FileName;      /* name to print on error messages */
 EXTERN char    *TrustedUsers[MAXTRUST+1];      /* list of trusted users */
 EXTERN jmp_buf TopFrame;       /* branch-to-top-of-loop-on-error frame */
 EXTERN bool    QuickAbort;     /*  .... but only if we want a quick abort */
 EXTERN char    *TrustedUsers[MAXTRUST+1];      /* list of trusted users */
 EXTERN jmp_buf TopFrame;       /* branch-to-top-of-loop-on-error frame */
 EXTERN bool    QuickAbort;     /*  .... but only if we want a quick abort */
index 06b93b2..b5aa034 100644 (file)
@@ -2,10 +2,10 @@
 # include "sendmail.h"
 
 # ifndef SMTP
 # include "sendmail.h"
 
 # ifndef SMTP
-SCCSID(@(#)srvrsmtp.c  3.38            %G%     (no SMTP));
+SCCSID(@(#)srvrsmtp.c  3.39            %G%     (no SMTP));
 # else SMTP
 
 # else SMTP
 
-SCCSID(@(#)srvrsmtp.c  3.38            %G%);
+SCCSID(@(#)srvrsmtp.c  3.39            %G%);
 
 /*
 **  SMTP -- run the SMTP protocol.
 
 /*
 **  SMTP -- run the SMTP protocol.
@@ -78,6 +78,7 @@ bool  IsWiz = FALSE;                  /* set if we are a wizard */
 char   *WizWord = NULL;                /* the wizard word to compare against */
 # endif DEBUG
 bool   InChild = FALSE;                /* true if running in a subprocess */
 char   *WizWord = NULL;                /* the wizard word to compare against */
 # endif DEBUG
 bool   InChild = FALSE;                /* true if running in a subprocess */
+bool   OneXact = FALSE;                /* one xaction only this run */
 #define EX_QUIT                22              /* special code for QUIT command */
 
 smtp()
 #define EX_QUIT                22              /* special code for QUIT command */
 
 smtp()
@@ -149,7 +150,7 @@ smtp()
                switch (c->cmdcode)
                {
                  case CMDHELO:         /* hello -- introduce yourself */
                switch (c->cmdcode)
                {
                  case CMDHELO:         /* hello -- introduce yourself */
-                       define('s', newstr(p));
+                       define('s', newstr(p), CurEnv);
                        message("250", "%s Hello %s, pleased to meet you", HostName, p);
                        break;
 
                        message("250", "%s Hello %s, pleased to meet you", HostName, p);
                        break;
 
@@ -233,7 +234,10 @@ smtp()
                        */
 
                        if (rcps != 1)
                        */
 
                        if (rcps != 1)
-                               HoldErrs = MailBack = TRUE;
+                       {
+                               HoldErrs = TRUE;
+                               ErrorMode == EM_MAIL;
+                       }
                        CurEnv->e_flags &= ~EF_FATALERRS;
 
                        /* send to all recipients */
                        CurEnv->e_flags &= ~EF_FATALERRS;
 
                        /* send to all recipients */
@@ -288,7 +292,7 @@ smtp()
                        break;
 
                  case CMDONEX:         /* doing one transaction only */
                        break;
 
                  case CMDONEX:         /* doing one transaction only */
-                       onexact = TRUE;
+                       OneXact = TRUE;
                        message("200", "Only one transaction");
                        break;
 
                        message("200", "Only one transaction");
                        break;
 
@@ -316,10 +320,24 @@ smtp()
                  case CMDDBGSHELL:     /* give us an interactive shell */
                        if (!iswiz())
                                break;
                  case CMDDBGSHELL:     /* give us an interactive shell */
                        if (!iswiz())
                                break;
+                       if (fileno(InChannel) != 0)
+                       {
+                               (void) close(0);
+                               (void) dup(fileno(InChannel));
+                               (void) fclose(InChannel);
+                               InChannel = stdin;
+                       }
+                       if (fileno(OutChannel) != 1)
+                       {
+                               (void) close(1);
+                               (void) dup(fileno(OutChannel));
+                               (void) fclose(OutChannel);
+                               OutChannel = stdout;
+                       }
                        execl("/bin/csh", "sendmail", 0);
                        execl("/bin/sh", "sendmail", 0);
                        message("500", "Can't");
                        execl("/bin/csh", "sendmail", 0);
                        execl("/bin/sh", "sendmail", 0);
                        message("500", "Can't");
-                       break;
+                       exit(EX_UNAVAILABLE);
 
                  case CMDDBGWIZ:       /* become a wizard */
                        if (WizWord != NULL)
 
                  case CMDDBGWIZ:       /* become a wizard */
                        if (WizWord != NULL)
@@ -496,6 +514,9 @@ runinchild(label)
 {
        int childpid;
 
 {
        int childpid;
 
+       if (OneXact)
+               return (0);
+
        childpid = dofork();
        if (childpid < 0)
        {
        childpid = dofork();
        if (childpid < 0)
        {
@@ -504,16 +525,11 @@ runinchild(label)
        }
        if (childpid > 0)
        {
        }
        if (childpid > 0)
        {
-               /* parent -- wait for child to complete */
                auto int st;
                auto int st;
-               int i;
 
 
-               while ((i = wait(&st)) != childpid)
-               {
-                       if (i < 0 && errno != EINTR)
-                               break;
-               }
-               if (i < 0)
+               /* parent -- wait for child to complete */
+               st = waitfor(childpid);
+               if (st == -1)
                        syserr("%s: lost child", label);
 
                /* if we exited on a QUIT command, complete the process */
                        syserr("%s: lost child", label);
 
                /* if we exited on a QUIT command, complete the process */
index 6d597b0..1b43142 100644 (file)
@@ -1,8 +1,43 @@
 # include "sendmail.h"
 
 # include "sendmail.h"
 
-SCCSID(@(#)stats.c     3.4             %G%);
+SCCSID(@(#)stats.c     3.5             %G%);
 
 /*
 
 /*
+**  Statistics structure.
+*/
+
+struct statistics
+{
+       time_t  stat_itime;             /* file initialization time */
+       short   stat_size;              /* size of this structure */
+       long    stat_nf[MAXMAILERS];    /* # msgs from each mailer */
+       long    stat_bf[MAXMAILERS];    /* kbytes from each mailer */
+       long    stat_nt[MAXMAILERS];    /* # msgs to each mailer */
+       long    stat_bt[MAXMAILERS];    /* kbytes to each mailer */
+};
+
+struct statistics      Stat;
+extern long            kbytes();       /* for _bf, _bt */
+\f/*
+**  MARKSTATS -- mark statistics
+*/
+
+markstats(e, to)
+       register ENVELOPE *e;
+       register ADDRESS *to;
+{
+       if (to == NULL)
+       {
+               Stat.stat_nf[e->e_from.q_mailer->m_mno]++;
+               Stat.stat_bf[e->e_from.q_mailer->m_mno] += kbytes(CurEnv->e_msgsize);
+       }
+       else
+       {
+               Stat.stat_nt[to->q_mailer->m_mno]++;
+               Stat.stat_bt[to->q_mailer->m_mno] += kbytes(CurEnv->e_msgsize);
+       }
+}
+\f/*
 **  POSTSTATS -- post statistics in the statistics file
 **
 **     Parameters:
 **  POSTSTATS -- post statistics in the statistics file
 **
 **     Parameters:
index 021e14a..302be49 100644 (file)
@@ -3,10 +3,10 @@
 # include "sendmail.h"
 
 # ifndef SMTP
 # include "sendmail.h"
 
 # ifndef SMTP
-SCCSID(@(#)usersmtp.c  3.27            %G%     (no SMTP));
+SCCSID(@(#)usersmtp.c  3.28            %G%     (no SMTP));
 # else SMTP
 
 # else SMTP
 
-SCCSID(@(#)usersmtp.c  3.27            %G%);
+SCCSID(@(#)usersmtp.c  3.28            %G%);
 
 /*
 **  SMTPINIT -- initialize SMTP.
 
 /*
 **  SMTPINIT -- initialize SMTP.
@@ -41,7 +41,6 @@ smtpinit(m, pvp, ctladdr)
 {
        register int r;
        char buf[MAXNAME];
 {
        register int r;
        char buf[MAXNAME];
-       extern tick();
        extern char *canonname();
 
        /*
        extern char *canonname();
 
        /*
@@ -249,7 +248,7 @@ smtpquit(name, showresp)
        (void) fclose(SmtpOut);
        i = endmailer(SmtpPid, name);
        if (showresp)
        (void) fclose(SmtpOut);
        i = endmailer(SmtpPid, name);
        if (showresp)
-               giveresponse(i, TRUE, LocalMailer);
+               giveresponse(i, LocalMailer);
 }
 \f/*
 **  REPLY -- read arpanet reply
 }
 \f/*
 **  REPLY -- read arpanet reply
index 317f53b..d551932 100644 (file)
@@ -8,7 +8,7 @@
 # include "sendmail.h"
 # include "conf.h"
 
 # include "sendmail.h"
 # include "conf.h"
 
-SCCSID(@(#)util.c      3.34            %G%);
+SCCSID(@(#)util.c      3.35            %G%);
 
 /*
 **  STRIPQUOTES -- Strip quotes & quote bits from a string.
 
 /*
 **  STRIPQUOTES -- Strip quotes & quote bits from a string.
@@ -516,14 +516,15 @@ dfopen(filename, mode)
 {
        register int tries;
        register FILE *fp;
 {
        register int tries;
        register FILE *fp;
-       extern int errno;
 
        for (tries = 0; tries < 10; tries++)
        {
                sleep(10 * tries);
                errno = 0;
                fp = fopen(filename, mode);
 
        for (tries = 0; tries < 10; tries++)
        {
                sleep(10 * tries);
                errno = 0;
                fp = fopen(filename, mode);
-               if (fp != NULL || errno != ENFILE)
+               if (fp != NULL)
+                       break;
+               if (errno != ENFILE && errno != EINTR)
                        break;
        }
        return (fp);
                        break;
        }
        return (fp);
@@ -707,97 +708,6 @@ fgetfolded(buf, n, f)
        return (NULL);
 }
 \f/*
        return (NULL);
 }
 \f/*
-**  PINTVL -- produce printable version of a time interval
-**
-**     Parameters:
-**             intvl -- the interval to be converted
-**             brief -- if TRUE, print this in an extremely compact form
-**                     (basically used for logging).
-**
-**     Returns:
-**             A pointer to a string version of intvl suitable for
-**                     printing or framing.
-**
-**     Side Effects:
-**             none.
-**
-**     Warning:
-**             The string returned is in a static buffer.
-*/
-
-# define PLURAL(n)     ((n) == 1 ? "" : "s")
-
-char *
-pintvl(intvl, brief)
-       time_t intvl;
-       bool brief;
-{
-       static char buf[MAXNAME];
-       register char *p;
-       int wk, dy, hr, mi, se;
-
-       if (intvl == 0 && !brief)
-               return ("zero seconds");
-
-       /* decode the interval into weeks, days, hours, minutes, seconds */
-       se = intvl % 60;
-       intvl /= 60;
-       mi = intvl % 60;
-       intvl /= 60;
-       hr = intvl % 24;
-       intvl /= 24;
-       if (brief)
-               dy = intvl;
-       else
-       {
-               dy = intvl % 7;
-               intvl /= 7;
-               wk = intvl;
-       }
-
-       /* now turn it into a sexy form */
-       p = buf;
-       if (brief)
-       {
-               if (dy > 0)
-               {
-                       (void) sprintf(p, "%d+", dy);
-                       p += strlen(p);
-               }
-               (void) sprintf(p, "%02d:%02d:%02d", hr, mi, se);
-               return (buf);
-       }
-
-       /* use the verbose form */
-       if (wk > 0)
-       {
-               (void) sprintf(p, ", %d week%s", wk, PLURAL(wk));
-               p += strlen(p);
-       }
-       if (dy > 0)
-       {
-               (void) sprintf(p, ", %d day%s", dy, PLURAL(dy));
-               p += strlen(p);
-       }
-       if (hr > 0)
-       {
-               (void) sprintf(p, ", %d hour%s", hr, PLURAL(hr));
-               p += strlen(p);
-       }
-       if (mi > 0)
-       {
-               (void) sprintf(p, ", %d minute%s", mi, PLURAL(mi));
-               p += strlen(p);
-       }
-       if (se > 0)
-       {
-               (void) sprintf(p, ", %d second%s", se, PLURAL(se));
-               p += strlen(p);
-       }
-
-       return (buf + 2);
-}
-\f/*
 **  CURTIME -- return current time.
 **
 **     Parameters:
 **  CURTIME -- return current time.
 **
 **     Parameters:
@@ -865,3 +775,52 @@ atooct(s)
                i = (i << 3) | (*s++ - '0');
        return (i);
 }
                i = (i << 3) | (*s++ - '0');
        return (i);
 }
+\f/*
+**  WAITFOR -- wait for a particular process id.
+**
+**     Parameters:
+**             pid -- process id to wait for.
+**
+**     Returns:
+**             status of pid.
+**             -1 if pid never shows up.
+**
+**     Side Effects:
+**             none.
+*/
+
+waitfor(pid)
+       int pid;
+{
+       auto int st;
+       int i;
+
+       do
+       {
+               errno = 0;
+               i = wait(&st);
+       } while ((i >= 0 || errno == EINTR) && i != pid);
+       if (i < 0)
+               st = -1;
+       return (st);
+}
+\f/*
+**  CLOSEALL -- close all extraneous file descriptors
+**
+**     Parameters:
+**             none.
+**
+**     Returns:
+**             none.
+**
+**     Side Effects:
+**             Closes all file descriptors except zero, one, and two.
+*/
+
+closeall()
+{
+       int i;
+
+       for (i = 3; i < 50; i++)
+               (void) close(i);
+}
index 0925375..5d50f40 100644 (file)
@@ -1,5 +1,5 @@
 # ifndef lint
 # ifndef lint
-static char    SccsId[] = "@(#)SendMail version 3.252 of %G%";
+static char    SccsId[] = "@(#)SendMail version 3.253 of %G%";
 # endif lint
 
 # endif lint
 
-char   Version[] = "3.252 [%G%]";
+char   Version[] = "3.253 [%G%]";