SMI changes (somewhat)
authorEric Allman <eric@ucbvax.Berkeley.EDU>
Thu, 19 Sep 1985 15:56:23 +0000 (07:56 -0800)
committerEric Allman <eric@ucbvax.Berkeley.EDU>
Thu, 19 Sep 1985 15:56:23 +0000 (07:56 -0800)
SCCS-vsn: usr.sbin/sendmail/src/macro.c 5.3
SCCS-vsn: usr.sbin/sendmail/src/queue.c 5.5
SCCS-vsn: usr.sbin/sendmail/src/headers.c 5.5
SCCS-vsn: usr.sbin/sendmail/src/deliver.c 5.5
SCCS-vsn: usr.sbin/sendmail/src/util.c 5.6
SCCS-vsn: usr.sbin/sendmail/src/savemail.c 5.3
SCCS-vsn: usr.sbin/sendmail/src/err.c 5.2.1.1
SCCS-vsn: usr.sbin/sendmail/src/conf.h 5.1.1.1
SCCS-vsn: usr.sbin/sendmail/src/conf.c 5.3.1.1
SCCS-vsn: usr.sbin/sendmail/src/main.c 5.4.1.1
SCCS-vsn: usr.sbin/sendmail/src/daemon.c 5.4.1.1
SCCS-vsn: usr.sbin/sendmail/src/sendmail.h 5.1.1.1
SCCS-vsn: usr.sbin/sendmail/src/srvrsmtp.c 5.5.1.1
SCCS-vsn: usr.sbin/sendmail/src/stats.c 5.4.1.1
SCCS-vsn: usr.sbin/sendmail/src/alias.c 5.3.1.1
SCCS-vsn: usr.sbin/sendmail/src/envelope.c 5.3.1.1
SCCS-vsn: usr.sbin/sendmail/src/parseaddr.c 5.1.1.1
SCCS-vsn: usr.sbin/sendmail/src/usersmtp.c 5.3.1.1
SCCS-vsn: usr.sbin/sendmail/src/readcf.c 5.3.1.1

19 files changed:
usr/src/usr.sbin/sendmail/src/alias.c
usr/src/usr.sbin/sendmail/src/conf.c
usr/src/usr.sbin/sendmail/src/conf.h
usr/src/usr.sbin/sendmail/src/daemon.c
usr/src/usr.sbin/sendmail/src/deliver.c
usr/src/usr.sbin/sendmail/src/envelope.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/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

index 6cdd6e5..2c688f9 100644 (file)
@@ -10,9 +10,9 @@
 
 #ifndef lint
 # ifdef DBM
 
 #ifndef lint
 # ifdef DBM
-static char    SccsId[] = "@(#)alias.c 5.3 (Berkeley) %G%      (with DBM)";
+static char    SccsId[] = "@(#)alias.c 5.3.1.1 (Berkeley) %G%  (with DBM)";
 # else DBM
 # else DBM
-static char    SccsId[] = "@(#)alias.c 5.3 (Berkeley) %G%      (without DBM)";
+static char    SccsId[] = "@(#)alias.c 5.3.1.1 (Berkeley) %G%  (without DBM)";
 # endif DBM
 #endif not lint
 
 # endif DBM
 #endif not lint
 
@@ -72,8 +72,6 @@ alias(a, sendq)
        extern ADDRESS *sendto();
        extern char *aliaslookup();
 
        extern ADDRESS *sendto();
        extern char *aliaslookup();
 
-       if (NoAlias)
-               return;
 # ifdef DEBUG
        if (tTd(27, 1))
                printf("alias(%s)\n", a->q_paddr);
 # ifdef DEBUG
        if (tTd(27, 1))
                printf("alias(%s)\n", a->q_paddr);
@@ -89,7 +87,10 @@ alias(a, sendq)
        **  Look up this name
        */
 
        **  Look up this name
        */
 
-       p = aliaslookup(a->q_user);
+       if (NoAlias)
+               p = NULL;
+       else
+               p = aliaslookup(a->q_user);
        if (p == NULL)
                return;
 
        if (p == NULL)
                return;
 
@@ -222,11 +223,16 @@ initaliases(aliasfile, init)
                {
                        init = TRUE;
                        message(Arpa_Info, "rebuilding alias database");
                {
                        init = TRUE;
                        message(Arpa_Info, "rebuilding alias database");
+#ifdef LOG
+                       if (LogLevel >= 7)
+                               syslog(LOG_INFO, "rebuilding alias database");
+#endif LOG
                }
                else
                {
 #ifdef LOG
                }
                else
                {
 #ifdef LOG
-                       syslog(LOG_INFO, "alias database out of date");
+                       if (LogLevel >= 7)
+                               syslog(LOG_INFO, "alias database out of date");
 #endif LOG
                        message(Arpa_Info, "Warning: alias database out of date");
                }
 #endif LOG
                        message(Arpa_Info, "Warning: alias database out of date");
                }
@@ -459,8 +465,11 @@ readaliases(aliasfile, init)
                                        if (c == '\n')
                                                c = '\0';
                                        *p = '\0';
                                        if (c == '\n')
                                                c = '\0';
                                        *p = '\0';
-                                       if (*p2 != '\0')
-                                               (void) parseaddr(p2, &bl, -1, ',');
+                                       if (*p2 != '\0' &&
+                                           parseaddr(p2, &bl, -1, ',') == NULL)
+                                       {
+                                               usrerr("%s... bad address");
+                                       }
                                        if (c != '\0')
                                                *p++ = c;
                                }
                                        if (c != '\0')
                                                *p++ = c;
                                }
@@ -538,6 +547,11 @@ readaliases(aliasfile, init)
        FileName = NULL;
        message(Arpa_Info, "%d aliases, longest %d bytes, %d bytes total",
                        naliases, longest, bytes);
        FileName = NULL;
        message(Arpa_Info, "%d aliases, longest %d bytes, %d bytes total",
                        naliases, longest, bytes);
+# ifdef LOG
+       if (LogLevel >= 8)
+               syslog(LOG_INFO, "%d aliases, longest %d bytes, %d bytes total",
+                       naliases, longest, bytes);
+# endif LOG
 }
 \f/*
 **  FORWARD -- Try to forward mail
 }
 \f/*
 **  FORWARD -- Try to forward mail
index 6e04333..1c93d34 100644 (file)
@@ -9,11 +9,14 @@
 */
 
 #ifndef lint
 */
 
 #ifndef lint
-static char    SccsId[] = "@(#)conf.c  5.5 (Berkeley) %G%";
+static char    SccsId[] = "@(#)conf.c  5.3.1.1 (Berkeley) %G%";
 #endif not lint
 
 # include <pwd.h>
 # include <sys/ioctl.h>
 #endif not lint
 
 # include <pwd.h>
 # include <sys/ioctl.h>
+# ifdef sun
+# include <sys/param.h>
+# endif sun
 # include "sendmail.h"
 
 /*
 # include "sendmail.h"
 
 /*
@@ -113,12 +116,34 @@ char      *FreezeFile =   "/usr/lib/sendmail.fc"; /* frozen version of above */
 
 
 /*
 
 
 /*
-**  Some other configuration....
+**  Miscellaneous stuff.
 */
 
 */
 
-char   SpaceSub;               /* character to replace <lwsp> in addrs */
-int    QueueLA;                /* load avg > QueueLA -> just queue */
-int    RefuseLA;               /* load avg > RefuseLA -> refuse connections */
+int    DtableSize =    50;             /* max open files; reset in 4.2bsd */
+\f/*
+**  SETDEFAULTS -- set default values
+**
+**     Because of the way freezing is done, these must be initialized
+**     using direct code.
+**
+**     Parameters:
+**             none.
+**
+**     Returns:
+**             none.
+**
+**     Side Effects:
+**             Initializes a bunch of global variables to their
+**             default values.
+*/
+
+setdefaults()
+{
+       QueueLA = 8;
+       QueueFactor = 10000;
+       RefuseLA = 12;
+       SpaceSub = ' ';
+}
 \f
 # ifdef V6
 /*
 \f
 # ifdef V6
 /*
@@ -527,7 +552,11 @@ struct     nlist Nl[] =
 getla()
 {
        static int kmem = -1;
 getla()
 {
        static int kmem = -1;
+# ifdef sun
+       long avenrun[3];
+# else
        double avenrun[3];
        double avenrun[3];
+# endif
 
        if (kmem < 0)
        {
 
        if (kmem < 0)
        {
@@ -545,7 +574,11 @@ getla()
                /* thank you Ian */
                return (-1);
        }
                /* thank you Ian */
                return (-1);
        }
+# ifdef sun
+       return ((int) (avenrun[0] + FSCALE/2) >> FSHIFT);
+# else
        return ((int) (avenrun[0] + 0.5));
        return ((int) (avenrun[0] + 0.5));
+# endif
 }
 
 #else VMUNIX
 }
 
 #else VMUNIX
@@ -556,3 +589,68 @@ getla()
 }
 
 #endif VMUNIX
 }
 
 #endif VMUNIX
+\f/*
+**  SHOULDQUEUE -- should this message be queued or sent?
+**
+**     Compares the message cost to the load average to decide.
+**
+**     Parameters:
+**             pri -- the priority of the message in question.
+**
+**     Returns:
+**             TRUE -- if this message should be queued up for the
+**                     time being.
+**             FALSE -- if the load is low enough to send this message.
+**
+**     Side Effects:
+**             none.
+*/
+
+bool
+shouldqueue(pri)
+       long pri;
+{
+       int la;
+
+       la = getla();
+       if (la < QueueLA)
+               return (FALSE);
+       return (pri > (QueueFactor / (la - QueueLA + 1)));
+}
+\f/*
+**  SETPROCTITLE -- set process title for ps
+**
+**     Parameters:
+**             fmt -- a printf style format string.
+**             a, b, c -- possible parameters to fmt.
+**
+**     Returns:
+**             none.
+**
+**     Side Effects:
+**             Clobbers argv of our main procedure so ps(1) will
+**             display the title.
+*/
+
+/*VARARGS1*/
+setproctitle(fmt, a, b, c)
+       char *fmt;
+{
+# ifdef SETPROCTITLE
+       register char *p;
+       extern char **Argv;
+       extern char *LastArgv;
+
+       p = Argv[0];
+
+       /* make ps print "(sendmail)" */
+       *p++ = '-';
+
+       (void) sprintf(p, fmt, a, b, c);
+       p += strlen(p);
+
+       /* avoid confusing ps */
+       while (p < LastArgv)
+               *p++ = ' ';
+# endif SETPROCTITLE
+}
index a218f7c..596d4e1 100644 (file)
@@ -7,7 +7,7 @@
 **  All rights reserved.  The Berkeley software License Agreement
 **  specifies the terms and conditions for redistribution.
 **
 **  All rights reserved.  The Berkeley software License Agreement
 **  specifies the terms and conditions for redistribution.
 **
-**     @(#)conf.h      5.2 (Berkeley) %G%
+**     @(#)conf.h      5.1.1.1 (Berkeley) %G%
 */
 
 /*
 */
 
 /*
@@ -25,7 +25,7 @@
 # define MAXNAME       256             /* max length of a name */
 # define MAXFIELD      2500            /* max total length of a hdr field */
 # define MAXPV         40              /* max # of parms to mailers */
 # define MAXNAME       256             /* max length of a name */
 # define MAXFIELD      2500            /* max total length of a hdr field */
 # define MAXPV         40              /* max # of parms to mailers */
-# define MAXHOP                30              /* max value of HopCount */
+# define MAXHOP                17              /* max value of HopCount */
 # define MAXATOM       100             /* max atoms per address */
 # define MAXMAILERS    25              /* maximum mailers known to system */
 # define MAXRWSETS     30              /* max # of sets of rewriting rules */
 # define MAXATOM       100             /* max atoms per address */
 # define MAXMAILERS    25              /* maximum mailers known to system */
 # define MAXRWSETS     30              /* max # of sets of rewriting rules */
@@ -42,5 +42,6 @@
 #define SMTP           1       /* enable user and server SMTP */
 #define QUEUE          1       /* enable queueing */
 #define UGLYUUCP       1       /* output ugly UUCP From lines */
 #define SMTP           1       /* enable user and server SMTP */
 #define QUEUE          1       /* enable queueing */
 #define UGLYUUCP       1       /* output ugly UUCP From lines */
-#define DAEMON         1       /* include the daemon (requires IPC) */
+#define DAEMON         1       /* include the daemon (requires IPC & SMTP) */
 #define FLOCK          1       /* use flock file locking */
 #define FLOCK          1       /* use flock file locking */
+#define SETPROCTITLE   1       /* munge argv to display current status */
index 7908b39..42acec4 100644 (file)
 
 # ifndef DAEMON
 # ifndef lint
 
 # ifndef DAEMON
 # ifndef lint
-static char    SccsId[] = "@(#)daemon.c        5.8 (Berkeley) %G%      (w/o daemon mode)";
+static char    SccsId[] = "@(#)daemon.c        5.4.1.1 (Berkeley) %G%  (w/o daemon mode)";
 # endif not lint
 # else
 
 # endif not lint
 # else
 
-# include <sys/socket.h>
-# include <netinet/in.h>
 # include <netdb.h>
 # include <sys/signal.h>
 # include <sys/wait.h>
 # include <netdb.h>
 # include <sys/signal.h>
 # include <sys/wait.h>
@@ -28,7 +26,7 @@ static char   SccsId[] = "@(#)daemon.c        5.8 (Berkeley) %G%      (w/o daemon mode)";
 # include <sys/resource.h>
 
 # ifndef lint
 # include <sys/resource.h>
 
 # ifndef lint
-static char    SccsId[] = "@(#)daemon.c        5.8 (Berkeley) %G% (with daemon mode)";
+static char    SccsId[] = "@(#)daemon.c        5.4.1.1 (Berkeley) %G% (with daemon mode)";
 # endif not lint
 
 /*
 # endif not lint
 
 /*
index a8e61d1..6f3d9e5 100644 (file)
@@ -9,7 +9,7 @@
 */
 
 #ifndef lint
 */
 
 #ifndef lint
-static char    SccsId[] = "@(#)deliver.c       5.4 (Berkeley) %G%";
+static char    SccsId[] = "@(#)deliver.c       5.5 (Berkeley) %G%";
 #endif not lint
 
 # include <signal.h>
 #endif not lint
 
 # include <signal.h>
@@ -628,9 +628,9 @@ endmailer(pid, name)
        /* see if it died a horrid death */
        if ((st & 0377) != 0)
        {
        /* see if it died a horrid death */
        if ((st & 0377) != 0)
        {
-               syserr("endmailer %s: stat %o", name, st);
-               ExitStat = EX_UNAVAILABLE;
-               return (EX_UNAVAILABLE);
+               syserr("mailer %s died with signal %o", name, st);
+               ExitStat = EX_TEMPFAIL;
+               return (EX_TEMPFAIL);
        }
 
        /* normal death -- return status */
        }
 
        /* normal death -- return status */
@@ -702,6 +702,10 @@ openmailer(m, pvp, ctladdr, clever, pmfile, prfile)
 
        if (strcmp(m->m_mailer, "[IPC]") == 0)
        {
 
        if (strcmp(m->m_mailer, "[IPC]") == 0)
        {
+#ifdef HOSTINFO
+               register STAB *st;
+               extern STAB *stab();
+#endif HOSTINFO
 #ifdef DAEMON
                register int i;
                register u_short port;
 #ifdef DAEMON
                register int i;
                register u_short port;
@@ -712,9 +716,25 @@ openmailer(m, pvp, ctladdr, clever, pmfile, prfile)
                        port = atoi(pvp[2]);
                else
                        port = 0;
                        port = atoi(pvp[2]);
                else
                        port = 0;
+#ifdef HOSTINFO
+               /* see if we have already determined that this host is fried */
+               st = stab(pvp[1], ST_HOST, ST_FIND);
+               if (st == NULL || st->s_host.ho_exitstat == EX_OK)
+                       i = makeconnection(pvp[1], port, pmfile, prfile);
+               else
+                       i = st->s_host.ho_exitstat;
+#else HOSTINFO
                i = makeconnection(pvp[1], port, pmfile, prfile);
                i = makeconnection(pvp[1], port, pmfile, prfile);
+#endif HOSTINFO
                if (i != EX_OK)
                {
                if (i != EX_OK)
                {
+#ifdef HOSTINFO
+                       /* enter status of this host */
+                       if (st == NULL)
+                               st = stab(pvp[1], ST_HOST, ST_ENTER);
+                       st->s_host.ho_exitstat = i;
+                       st->s_host.ho_errno = errno;
+#endif HOSTINFO
                        ExitStat = i;
                        return (-1);
                }
                        ExitStat = i;
                        return (-1);
                }
@@ -772,6 +792,7 @@ openmailer(m, pvp, ctladdr, clever, pmfile, prfile)
        else if (pid == 0)
        {
                int i;
        else if (pid == 0)
        {
                int i;
+               extern int DtableSize;
 
                /* child -- set up input & exec mailer */
                /* make diagnostic output be standard output */
 
                /* child -- set up input & exec mailer */
                /* make diagnostic output be standard output */
@@ -820,7 +841,7 @@ openmailer(m, pvp, ctladdr, clever, pmfile, prfile)
                }
 
                /* arrange for all the files to be closed */
                }
 
                /* arrange for all the files to be closed */
-               for (i = 3; i < 50; i++)
+               for (i = 3; i < DtableSize; i++)
 #ifdef FIOCLEX
                        (void) ioctl(i, FIOCLEX, 0);
 #else FIOCLEX
 #ifdef FIOCLEX
                        (void) ioctl(i, FIOCLEX, 0);
 #else FIOCLEX
@@ -836,7 +857,8 @@ openmailer(m, pvp, ctladdr, clever, pmfile, prfile)
                printf("Cannot exec '%s' errno=%d\n", m->m_mailer, errno);
                (void) fflush(stdout);
 #endif FIOCLEX
                printf("Cannot exec '%s' errno=%d\n", m->m_mailer, errno);
                (void) fflush(stdout);
 #endif FIOCLEX
-               if (m == LocalMailer)
+               if (m == LocalMailer || errno == EIO || errno == EAGAIN ||
+                   errno == ENOMEM || errno == EPROCLIM)
                        _exit(EX_TEMPFAIL);
                else
                        _exit(EX_UNAVAILABLE);
                        _exit(EX_TEMPFAIL);
                else
                        _exit(EX_UNAVAILABLE);
@@ -1242,9 +1264,9 @@ sendall(e, mode)
        /* determine actual delivery mode */
        if (mode == SM_DEFAULT)
        {
        /* determine actual delivery mode */
        if (mode == SM_DEFAULT)
        {
-               extern int QueueLA;
+               extern bool shouldqueue();
 
 
-               if (getla() > QueueLA)
+               if (shouldqueue(e->e_msgpriority))
                        mode = SM_QUEUE;
                else
                        mode = SendMode;
                        mode = SM_QUEUE;
                else
                        mode = SendMode;
index ff2b5f2..a66d41a 100644 (file)
@@ -9,7 +9,7 @@
 */
 
 #ifndef lint
 */
 
 #ifndef lint
-static char    SccsId[] = "@(#)envelope.c      5.3 (Berkeley) %G%";
+static char    SccsId[] = "@(#)envelope.c      5.3.1.1 (Berkeley) %G%";
 #endif not lint
 
 #include <pwd.h>
 #endif not lint
 
 #include <pwd.h>
@@ -46,7 +46,10 @@ newenvelope(e)
        if (e == CurEnv)
                parent = e->e_parent;
        bzero((char *) e, sizeof *e);
        if (e == CurEnv)
                parent = e->e_parent;
        bzero((char *) e, sizeof *e);
-       bcopy((char *) &CurEnv->e_from, (char *) &e->e_from, sizeof e->e_from);
+       if (e == CurEnv)
+               bcopy((char *) &NullAddress, (char *) &e->e_from, sizeof e->e_from);
+       else
+               bcopy((char *) &CurEnv->e_from, (char *) &e->e_from, sizeof e->e_from);
        e->e_parent = parent;
        e->e_ctime = curtime();
        e->e_puthdr = putheader;
        e->e_parent = parent;
        e->e_ctime = curtime();
        e->e_puthdr = putheader;
@@ -140,8 +143,6 @@ dropenvelope(e)
        if ((!queueit && !bitset(EF_KEEPQUEUE, e->e_flags)) ||
            bitset(EF_CLRQUEUE, e->e_flags))
        {
        if ((!queueit && !bitset(EF_KEEPQUEUE, e->e_flags)) ||
            bitset(EF_CLRQUEUE, e->e_flags))
        {
-               if (e->e_dfp != NULL)
-                       (void) fclose(e->e_dfp);
                if (e->e_df != NULL)
                        xunlink(e->e_df);
                xunlink(queuename(e, 'q'));
                if (e->e_df != NULL)
                        xunlink(e->e_df);
                xunlink(queuename(e, 'q'));
@@ -161,6 +162,8 @@ dropenvelope(e)
 
        /* make sure that this envelope is marked unused */
        e->e_id = e->e_df = NULL;
 
        /* make sure that this envelope is marked unused */
        e->e_id = e->e_df = NULL;
+       if (e->e_dfp != NULL)
+               (void) fclose(e->e_dfp);
        e->e_dfp = NULL;
 }
 \f/*
        e->e_dfp = NULL;
 }
 \f/*
@@ -457,11 +460,18 @@ setsender(from)
                /* log garbage addresses for traceback */
                if (from != NULL)
                {
                /* log garbage addresses for traceback */
                if (from != NULL)
                {
-                       syslog(LOG_ERR, "Unparseable user %s wants to be %s",
-                                       realname, from);
+# ifdef LOG
+                       if (LogLevel >= 1)
+                               syslog(LOG_ERR, "Unparseable user %s wants to be %s",
+                                               realname, from);
+# endif LOG
                }
                from = newstr(realname);
                }
                from = newstr(realname);
-               (void) parseaddr(from, &CurEnv->e_from, 1, '\0');
+               if (parseaddr(from, &CurEnv->e_from, 1, '\0') == NULL &&
+                   parseaddr("postmaster", &CurEnv->e_from, 1, '\0') == NULL)
+               {
+                       syserr("setsender: can't even parse postmaster!");
+               }
        }
        else
                FromFlag = TRUE;
        }
        else
                FromFlag = TRUE;
@@ -536,7 +546,8 @@ setsender(from)
        define('f', newstr(buf), CurEnv);
 
        /* save the domain spec if this mailer wants it */
        define('f', newstr(buf), CurEnv);
 
        /* save the domain spec if this mailer wants it */
-       if (bitnset(M_CANONICAL, CurEnv->e_from.q_mailer->m_flags))
+       if (CurEnv->e_from.q_mailer != NULL &&
+           bitnset(M_CANONICAL, CurEnv->e_from.q_mailer->m_flags))
        {
                extern char **copyplist();
 
        {
                extern char **copyplist();
 
index a5836dd..87c050a 100644 (file)
@@ -9,10 +9,11 @@
 */
 
 #ifndef lint
 */
 
 #ifndef lint
-static char    SccsId[] = "@(#)err.c   5.3 (Berkeley) %G%";
+static char    SccsId[] = "@(#)err.c   5.2.1.1 (Berkeley) %G%";
 #endif not lint
 
 # include "sendmail.h"
 #endif not lint
 
 # include "sendmail.h"
+# include <errno.h>
 
 /*
 **  SYSERR -- Print error message.
 
 /*
 **  SYSERR -- Print error message.
@@ -141,7 +142,7 @@ message(num, msg, a, b, c, d, e)
 **     Parameters:
 **             num -- the default ARPANET error number (in ascii)
 **             msg -- the message (printf fmt) -- if it begins
 **     Parameters:
 **             num -- the default ARPANET error number (in ascii)
 **             msg -- the message (printf fmt) -- if it begins
-**                     with a digit, this number overrides num.
+**                     with three digits, this number overrides num.
 **             a, b, c, d, e -- printf arguments
 **
 **     Returns:
 **             a, b, c, d, e -- printf arguments
 **
 **     Returns:
@@ -250,7 +251,7 @@ fmtmsg(eb, to, num, eno, fmt, a, b, c, d, e)
        char del;
 
        /* output the reply code */
        char del;
 
        /* output the reply code */
-       if (isdigit(*fmt))
+       if (isdigit(fmt[0]) && isdigit(fmt[1]) && isdigit(fmt[2]))
        {
                num = fmt;
                fmt += 4;
        {
                num = fmt;
                fmt += 4;
@@ -310,7 +311,51 @@ errstring(errno)
 {
        extern char *sys_errlist[];
        extern int sys_nerr;
 {
        extern char *sys_errlist[];
        extern int sys_nerr;
-       static char buf[50];
+       static char buf[100];
+# ifdef SMTP
+       extern char *SmtpPhase;
+       extern char *RealHostName;
+# endif SMTP
+
+# ifdef DAEMON
+# ifdef VMUNIX
+       /*
+       **  Handle special network error codes.
+       **
+       **      These are 4.2/4.3bsd specific; they should be in daemon.c.
+       */
+
+       switch (errno)
+       {
+         case ETIMEDOUT:
+         case ECONNRESET:
+               (void) strcpy(buf, sys_errlist[errno]);
+               if (SmtpPhase != NULL)
+               {
+                       (void) strcat(buf, " during ");
+                       (void) strcat(buf, SmtpPhase);
+               }
+               if (RealHostName != NULL)
+               {
+                       (void) strcat(buf, " with ");
+                       (void) strcat(buf, RealHostName);
+               }
+               return (buf);
+
+         case EHOSTDOWN:
+               if (RealHostName == NULL)
+                       break;
+               (void) sprintf(buf, "Host %s is down", RealHostName);
+               return (buf);
+
+         case ECONNREFUSED:
+               if (RealHostName == NULL)
+                       break;
+               (void) sprintf(buf, "Connection refused by %s", RealHostName);
+               return (buf);
+       }
+# endif VMUNIX
+# endif DAEMON
 
        if (errno > 0 && errno < sys_nerr)
                return (sys_errlist[errno]);
 
        if (errno > 0 && errno < sys_nerr)
                return (sys_errlist[errno]);
index a033549..02f55eb 100644 (file)
@@ -9,7 +9,7 @@
 */
 
 #ifndef lint
 */
 
 #ifndef lint
-static char    SccsId[] = "@(#)headers.c       5.4.1.1 (Berkeley) %G%";
+static char    SccsId[] = "@(#)headers.c       5.5 (Berkeley) %G%";
 #endif not lint
 
 # include <errno.h>
 #endif not lint
 
 # include <errno.h>
@@ -111,7 +111,8 @@ chompheader(line, def)
                p += 7;
        if (!def && !QueueRun && strcmp(fname, p) == 0)
        {
                p += 7;
        if (!def && !QueueRun && strcmp(fname, p) == 0)
        {
-               if (strcmp(fvalue, CurEnv->e_from.q_paddr) == 0)
+               if (CurEnv->e_from.q_paddr != NULL &&
+                   strcmp(fvalue, CurEnv->e_from.q_paddr) == 0)
                        return (hi->hi_flags);
        }
 
                        return (hi->hi_flags);
        }
 
@@ -346,7 +347,9 @@ eatheader(e)
        if (p != NULL)
                e->e_class = priencode(p);
        if (!QueueRun)
        if (p != NULL)
                e->e_class = priencode(p);
        if (!QueueRun)
-               e->e_msgpriority = e->e_msgsize + e->e_ctime - e->e_class * WKPRIFACT;
+               e->e_msgpriority = e->e_msgsize + e->e_ctime
+                                - e->e_class * WKPRIFACT
+                                + e->e_nrcpts * WKRECIPFACT;
 
        /* return receipt to */
        p = hvalue("return-receipt-to");
 
        /* return receipt to */
        p = hvalue("return-receipt-to");
index ae6c22b..998bbfc 100644 (file)
@@ -9,7 +9,7 @@
 */
 
 #ifndef lint
 */
 
 #ifndef lint
-static char    SccsId[] = "@(#)macro.c 5.2 (Berkeley) %G%";
+static char    SccsId[] = "@(#)macro.c 5.3 (Berkeley) %G%";
 #endif not lint
 
 # include "sendmail.h"
 #endif not lint
 
 # include "sendmail.h"
@@ -47,7 +47,7 @@ expand(s, buf, buflim, e)
        extern char *macvalue();
 
 # ifdef DEBUG
        extern char *macvalue();
 
 # ifdef DEBUG
-       if (tTd(35, 4))
+       if (tTd(35, 24))
        {
                printf("expand(");
                xputs(s);
        {
                printf("expand(");
                xputs(s);
@@ -114,7 +114,7 @@ expand(s, buf, buflim, e)
        *xp = '\0';
 
 # ifdef DEBUG
        *xp = '\0';
 
 # ifdef DEBUG
-       if (tTd(35, 4))
+       if (tTd(35, 24))
        {
                printf("expand ==> ");
                xputs(xbuf);
        {
                printf("expand ==> ");
                xputs(xbuf);
@@ -202,7 +202,7 @@ define(n, v, e)
        register ENVELOPE *e;
 {
 # ifdef DEBUG
        register ENVELOPE *e;
 {
 # ifdef DEBUG
-       if (tTd(35, 3))
+       if (tTd(35, 9))
        {
                printf("define(%c as ", n);
                xputs(v);
        {
                printf("define(%c as ", n);
                xputs(v);
index 8ca2365..4805958 100644 (file)
@@ -15,7 +15,7 @@ char copyright[] =
 #endif not lint
 
 #ifndef lint
 #endif not lint
 
 #ifndef lint
-static char    SccsId[] = "@(#)main.c  5.5 (Berkeley) %G%";
+static char    SccsId[] = "@(#)main.c  5.4.1.1 (Berkeley) %G%";
 #endif not lint
 
 # define  _DEFINE
 #endif not lint
 
 # define  _DEFINE
@@ -24,7 +24,7 @@ static char   SccsId[] = "@(#)main.c  5.5 (Berkeley) %G%";
 # include "sendmail.h"
 
 # ifdef lint
 # include "sendmail.h"
 
 # ifdef lint
-char   edata;
+char   edata, end;
 # endif lint
 
 /*
 # endif lint
 
 /*
@@ -66,6 +66,20 @@ int          NextMailer;     /* "free" index into Mailer struct */
 char           *FullName;      /* sender's full name */
 ENVELOPE       BlankEnvelope;  /* a "blank" envelope */
 ENVELOPE       MainEnvelope;   /* the envelope around the basic letter */
 char           *FullName;      /* sender's full name */
 ENVELOPE       BlankEnvelope;  /* a "blank" envelope */
 ENVELOPE       MainEnvelope;   /* the envelope around the basic letter */
+ADDRESS                NullAddress =   /* a null address */
+               { "", "", "" };
+
+/*
+**  Pointers for setproctitle.
+**     This allows "ps" listings to give more useful information.
+**     These must be kept out of BSS for frozen configuration files
+**             to work.
+*/
+
+# ifdef SETPROCTITLE
+char           **Argv = NULL;          /* pointer to argument vector */
+char           *LastArgv = NULL;       /* end of argv */
+# endif SETPROCTITLE
 
 #ifdef DAEMON
 #ifndef SMTP
 
 #ifdef DAEMON
 #ifndef SMTP
@@ -120,6 +134,15 @@ main(argc, argv, envp)
        extern ADDRESS *recipient();
        bool canrename;
 
        extern ADDRESS *recipient();
        bool canrename;
 
+# ifdef SETPROCTITLE
+       /*
+       **  Save start and extent of argv for setproctitle.
+       */
+
+       Argv = argv;
+       LastArgv = argv[argc - 1] + strlen(argv[argc - 1]);
+# endif SETPROCTITLE
+
        /*
        **  Be sure we have enough file descriptors.
        */
        /*
        **  Be sure we have enough file descriptors.
        */
@@ -132,7 +155,9 @@ main(argc, argv, envp)
        BlankEnvelope.e_puthdr = putheader;
        BlankEnvelope.e_putbody = putbody;
        BlankEnvelope.e_xfp = NULL;
        BlankEnvelope.e_puthdr = putheader;
        BlankEnvelope.e_putbody = putbody;
        BlankEnvelope.e_xfp = NULL;
+       STRUCTCOPY(NullAddress, BlankEnvelope.e_from);
        CurEnv = &BlankEnvelope;
        CurEnv = &BlankEnvelope;
+       STRUCTCOPY(NullAddress, MainEnvelope.e_from);
 
        /*
        **  Do a quick prescan of the argument list.
 
        /*
        **  Do a quick prescan of the argument list.
@@ -289,7 +314,7 @@ main(argc, argv, envp)
                                syserr("More than one \"from\" person");
                                break;
                        }
                                syserr("More than one \"from\" person");
                                break;
                        }
-                       from = p;
+                       from = newstr(p);
                        break;
 
                  case 'F':     /* set full name */
                        break;
 
                  case 'F':     /* set full name */
@@ -300,7 +325,7 @@ main(argc, argv, envp)
                                av--;
                                break;
                        }
                                av--;
                                break;
                        }
-                       FullName = p;
+                       FullName = newstr(p);
                        break;
 
                  case 'h':     /* hop count */
                        break;
 
                  case 'h':     /* hop count */
@@ -605,7 +630,11 @@ main(argc, argv, envp)
 
        if (OpMode != MD_ARPAFTP && *av == NULL && !GrabTo)
        {
 
        if (OpMode != MD_ARPAFTP && *av == NULL && !GrabTo)
        {
-               usrerr("Usage: /usr/lib/sendmail [flags] addr...");
+               usrerr("Recipient names must be specified");
+
+               /* collect body for UUCP return */
+               if (OpMode != MD_VERIFY)
+                       collect(FALSE);
                finis();
        }
        if (OpMode == MD_VERIFY)
                finis();
        }
        if (OpMode == MD_VERIFY)
@@ -795,6 +824,8 @@ union frz
        {
                time_t  frzstamp;       /* timestamp on this freeze */
                char    *frzbrk;        /* the current break */
        {
                time_t  frzstamp;       /* timestamp on this freeze */
                char    *frzbrk;        /* the current break */
+               char    *frzedata;      /* address of edata */
+               char    *frzend;        /* address of end */
                char    frzver[252];    /* sendmail version */
        } frzinfo;
 };
                char    frzver[252];    /* sendmail version */
        } frzinfo;
 };
@@ -804,7 +835,7 @@ freeze(freezefile)
 {
        int f;
        union frz fhdr;
 {
        int f;
        union frz fhdr;
-       extern char edata;
+       extern char edata, end;
        extern char *sbrk();
        extern char Version[];
 
        extern char *sbrk();
        extern char Version[];
 
@@ -823,6 +854,8 @@ freeze(freezefile)
        /* build the freeze header */
        fhdr.frzinfo.frzstamp = curtime();
        fhdr.frzinfo.frzbrk = sbrk(0);
        /* build the freeze header */
        fhdr.frzinfo.frzstamp = curtime();
        fhdr.frzinfo.frzbrk = sbrk(0);
+       fhdr.frzinfo.frzedata = &edata;
+       fhdr.frzinfo.frzend = &end;
        (void) strcpy(fhdr.frzinfo.frzver, Version);
 
        /* write out the freeze header */
        (void) strcpy(fhdr.frzinfo.frzver, Version);
 
        /* write out the freeze header */
@@ -872,6 +905,8 @@ 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 ||
+           fhdr.frzinfo.frzedata != &edata ||
+           fhdr.frzinfo.frzend != &end ||
            strcmp(fhdr.frzinfo.frzver, Version) != 0)
        {
                (void) close(f);
            strcmp(fhdr.frzinfo.frzver, Version) != 0)
        {
                (void) close(f);
index a3a4f37..97ab383 100644 (file)
@@ -10,7 +10,7 @@
 */
 
 #ifndef lint
 */
 
 #ifndef lint
-static char    SccsId[] = "@(#)parseaddr.c     5.1 (Berkeley) %G%";
+static char    SccsId[] = "@(#)parseaddr.c     5.1.1.1 (Berkeley) %G%";
 #endif not lint
 
 # include "sendmail.h"
 #endif not lint
 
 # include "sendmail.h"
@@ -127,12 +127,15 @@ parseaddr(addr, a, copyf, delim)
        }
        else
                a->q_paddr = addr;
        }
        else
                a->q_paddr = addr;
+
+       if (a->q_user == NULL)
+               a->q_user = "";
+       if (a->q_host == NULL)
+               a->q_host = "";
+
        if (copyf >= 0)
        {
        if (copyf >= 0)
        {
-               if (a->q_host != NULL)
-                       a->q_host = newstr(a->q_host);
-               else
-                       a->q_host = "";
+               a->q_host = newstr(a->q_host);
                if (a->q_user != a->q_paddr)
                        a->q_user = newstr(a->q_user);
        }
                if (a->q_user != a->q_paddr)
                        a->q_user = newstr(a->q_user);
        }
@@ -316,7 +319,9 @@ prescan(addr, delim, pvpbuf)
                        *q = '\0';
                        if (bslashmode)
                        {
                        *q = '\0';
                        if (bslashmode)
                        {
-                               c |= 0200;
+                               /* kludge \! for naive users */
+                               if (c != '!')
+                                       c |= 0200;
                                bslashmode = FALSE;
                        }
                        else if (c == '\\')
                                bslashmode = FALSE;
                        }
                        else if (c == '\\')
@@ -938,7 +943,7 @@ buildaddr(tv, a)
        }
        if (m == NULL)
        {
        }
        if (m == NULL)
        {
-               syserr("buildaddr: unknown net %s", *tv);
+               syserr("buildaddr: unknown mailer %s", *tv);
                return (NULL);
        }
        a->q_mailer = m;
                return (NULL);
        }
        a->q_mailer = m;
index 9648219..5833d30 100644 (file)
 
 # ifndef QUEUE
 # ifndef lint
 
 # ifndef QUEUE
 # ifndef lint
-static char    SccsId[] = "@(#)queue.c 5.4 (Berkeley) %G%      (no queueing)";
+static char    SccsId[] = "@(#)queue.c 5.5 (Berkeley) %G%      (no queueing)";
 # endif not lint
 # else QUEUE
 
 # ifndef lint
 # endif not lint
 # else QUEUE
 
 # ifndef lint
-static char    SccsId[] = "@(#)queue.c 5.4 (Berkeley) %G%";
+static char    SccsId[] = "@(#)queue.c 5.5 (Berkeley) %G%";
 # endif not lint
 
 /*
 # endif not lint
 
 /*
@@ -33,6 +33,7 @@ struct work
 {
        char            *w_name;        /* name of control file */
        long            w_pri;          /* priority of message, see below */
 {
        char            *w_name;        /* name of control file */
        long            w_pri;          /* priority of message, see below */
+       long            w_ctime;        /* creation time of message */
        struct work     *w_next;        /* next in queue */
 };
 
        struct work     *w_next;        /* next in queue */
 };
 
@@ -242,7 +243,9 @@ queueup(e, queueall, announce)
 **     order and processes them.
 **
 **     Parameters:
 **     order and processes them.
 **
 **     Parameters:
-**             none.
+**             forkflag -- TRUE if the queue scanning should be done in
+**                     a child process.  We double-fork so it is not our
+**                     child and we don't have to clean up after it.
 **
 **     Returns:
 **             none.
 **
 **     Returns:
 **             none.
@@ -275,6 +278,9 @@ runqueue(forkflag)
                if (fork() != 0)
                        exit(EX_OK);
        }
                if (fork() != 0)
                        exit(EX_OK);
        }
+
+       setproctitle("running queue");
+
 # ifdef LOG
        if (LogLevel > 11)
                syslog(LOG_DEBUG, "runqueue %s, pid=%d", QueueDir, getpid());
 # ifdef LOG
        if (LogLevel > 11)
                syslog(LOG_DEBUG, "runqueue %s, pid=%d", QueueDir, getpid());
@@ -314,7 +320,10 @@ runqueue(forkflag)
 **  ORDERQ -- order the work queue.
 **
 **     Parameters:
 **  ORDERQ -- order the work queue.
 **
 **     Parameters:
-**             none.
+**             doall -- if set, include everything in the queue (even
+**                     the jobs that cannot be run because the load
+**                     average is too high).  Otherwise, exclude those
+**                     jobs.
 **
 **     Returns:
 **             The number of request in the queue (not necessarily
 **
 **     Returns:
 **             The number of request in the queue (not necessarily
@@ -335,7 +344,8 @@ static struct dir   dbuf;
 # define closedir(f)   fclose(f)
 # endif DIR
 
 # define closedir(f)   fclose(f)
 # endif DIR
 
-orderq()
+orderq(doall)
+       bool doall;
 {
        register struct direct *d;
        register WORK *w;
 {
        register struct direct *d;
        register WORK *w;
@@ -406,9 +416,14 @@ orderq()
                /* extract useful information */
                while (fgets(lbuf, sizeof lbuf, cf) != NULL)
                {
                /* extract useful information */
                while (fgets(lbuf, sizeof lbuf, cf) != NULL)
                {
-                       if (lbuf[0] == 'P')
+                       switch (lbuf[0])
                        {
                        {
-                               (void) sscanf(&lbuf[1], "%ld", &wlist[wn].w_pri);
+                         case 'P':
+                               wlist[wn].w_pri = atol(&lbuf[1]);
+                               break;
+
+                         case 'T':
+                               wlist[wn].w_ctime = atol(&lbuf[1]);
                                break;
                        }
                }
                                break;
                        }
                }
@@ -434,6 +449,7 @@ orderq()
                w = (WORK *) xalloc(sizeof *w);
                w->w_name = wlist[i].w_name;
                w->w_pri = wlist[i].w_pri;
                w = (WORK *) xalloc(sizeof *w);
                w->w_name = wlist[i].w_name;
                w->w_pri = wlist[i].w_pri;
+               w->w_ctime = wlist[i].w_ctime;
                w->w_next = NULL;
                *wp = w;
                wp = &w->w_next;
                w->w_next = NULL;
                *wp = w;
                wp = &w->w_next;
@@ -469,9 +485,12 @@ workcmpf(a, b)
        register WORK *a;
        register WORK *b;
 {
        register WORK *a;
        register WORK *b;
 {
-       if (a->w_pri == b->w_pri)
+       long pa = a->w_pri + a->w_ctime;
+       long pb = b->w_pri + b->w_ctime;
+
+       if (pa == pb)
                return (0);
                return (0);
-       else if (a->w_pri > b->w_pri)
+       else if (pa > pb)
                return (-1);
        else
                return (1);
                return (-1);
        else
                return (1);
@@ -493,6 +512,7 @@ dowork(w)
        register WORK *w;
 {
        register int i;
        register WORK *w;
 {
        register int i;
+       extern bool shouldqueue();
 
 # ifdef DEBUG
        if (tTd(40, 1))
 
 # ifdef DEBUG
        if (tTd(40, 1))
@@ -500,16 +520,34 @@ dowork(w)
 # endif DEBUG
 
        /*
 # endif DEBUG
 
        /*
-       **  Fork for work.
+       **  Ignore jobs that are too expensive for the moment.
        */
 
        */
 
-       i = fork();
-       if (i < 0)
+       if (shouldqueue(w->w_pri))
        {
        {
-               syserr("dowork: cannot fork");
+               if (Verbose)
+                       printf("\nSkipping %s\n", w->w_name);
                return;
        }
 
                return;
        }
 
+       /*
+       **  Fork for work.
+       */
+
+       if (ForkQueueRuns)
+       {
+               i = fork();
+               if (i < 0)
+               {
+                       syserr("dowork: cannot fork");
+                       return;
+               }
+       }
+       else
+       {
+               i = 0;
+       }
+
        if (i == 0)
        {
                /*
        if (i == 0)
        {
                /*
@@ -544,7 +582,10 @@ dowork(w)
                        if (LogLevel > 4)
                                syslog(LOG_DEBUG, "%s: locked", CurEnv->e_id);
 # endif LOG
                        if (LogLevel > 4)
                                syslog(LOG_DEBUG, "%s: locked", CurEnv->e_id);
 # endif LOG
-                       exit(EX_OK);
+                       if (ForkQueueRuns)
+                               exit(EX_OK);
+                       else
+                               return;
                }
 
                /* do basic system initialization */
                }
 
                /* do basic system initialization */
@@ -560,15 +601,20 @@ dowork(w)
                        sendall(CurEnv, SM_DELIVER);
 
                /* finish up and exit */
                        sendall(CurEnv, SM_DELIVER);
 
                /* finish up and exit */
-               finis();
+               if (ForkQueueRuns)
+                       finis();
+               else
+                       dropenvelope(CurEnv);
        }
        }
+       else
+       {
+               /*
+               **  Parent -- pick up results.
+               */
 
 
-       /*
-       **  Parent -- pick up results.
-       */
-
-       errno = 0;
-       (void) waitfor(i);
+               errno = 0;
+               (void) waitfor(i);
+       }
 }
 \f/*
 **  READQF -- read queue file and set up environment.
 }
 \f/*
 **  READQF -- read queue file and set up environment.
@@ -642,23 +688,39 @@ readqf(e, full)
                        break;
 
                  case 'T':             /* init time */
                        break;
 
                  case 'T':             /* init time */
-                       (void) sscanf(&buf[1], "%ld", &e->e_ctime);
+                       e->e_ctime = atol(&buf[1]);
                        break;
 
                  case 'P':             /* message priority */
                        break;
 
                  case 'P':             /* message priority */
-                       (void) sscanf(&buf[1], "%ld", &e->e_msgpriority);
+                       e->e_msgpriority = atol(&buf[1]);
 
                        /* make sure that big things get sent eventually */
                        e->e_msgpriority -= WKTIMEFACT;
                        break;
 
 
                        /* make sure that big things get sent eventually */
                        e->e_msgpriority -= WKTIMEFACT;
                        break;
 
+                 case '\0':            /* blank line; ignore */
+                       break;
+
                  default:
                  default:
-                       syserr("readqf(%s): bad line \"%s\"", e->e_id, buf);
+                       syserr("readqf(%s:%d): bad line \"%s\"", e->e_id,
+                               LineNumber, buf);
                        break;
                }
        }
 
                        break;
                }
        }
 
+       fclose(qfp);
        FileName = NULL;
        FileName = NULL;
+
+       /*
+       **  If we haven't read any lines, this queue file is empty.
+       **  Arrange to remove it without referencing any null pointers.
+       */
+
+       if (LineNumber == 0)
+       {
+               errno = 0;
+               e->e_flags |= EF_CLRQUEUE | EF_FATALERRS | EF_RESPONSE;
+       }
 }
 \f/*
 **  PRINTQUEUE -- print out a representation of the mail queue
 }
 \f/*
 **  PRINTQUEUE -- print out a representation of the mail queue
@@ -684,7 +746,7 @@ printqueue()
        **  Read and order the queue.
        */
 
        **  Read and order the queue.
        */
 
-       nrequests = orderq();
+       nrequests = orderq(TRUE);
 
        /*
        **  Print the work list that we have read.
 
        /*
        **  Print the work list that we have read.
@@ -708,6 +770,7 @@ printqueue()
                long dfsize = -1;
                char lf[20];
                char message[MAXLINE];
                long dfsize = -1;
                char lf[20];
                char message[MAXLINE];
+               extern bool shouldqueue();
 
                f = fopen(w->w_name, "r");
                if (f == NULL)
 
                f = fopen(w->w_name, "r");
                if (f == NULL)
@@ -720,6 +783,8 @@ printqueue()
                lf[0] = 'l';
                if (stat(lf, &st) >= 0)
                        printf("*");
                lf[0] = 'l';
                if (stat(lf, &st) >= 0)
                        printf("*");
+               else if (shouldqueue(w->w_pri))
+                       printf("X");
                else
                        printf(" ");
                errno = 0;
                else
                        printf(" ");
                errno = 0;
@@ -738,7 +803,7 @@ printqueue()
                                printf("%8ld %.16s %.45s", dfsize,
                                        ctime(&submittime), &buf[1]);
                                if (message[0] != '\0')
                                printf("%8ld %.16s %.45s", dfsize,
                                        ctime(&submittime), &buf[1]);
                                if (message[0] != '\0')
-                                       printf("\n\t\t\t\t  (%.43s)", message);
+                                       printf("\n\t\t (%.62s)", message);
                                break;
 
                          case 'R':     /* recipient name */
                                break;
 
                          case 'R':     /* recipient name */
@@ -746,7 +811,7 @@ printqueue()
                                break;
 
                          case 'T':     /* creation time */
                                break;
 
                          case 'T':     /* creation time */
-                               (void) sscanf(&buf[1], "%ld", &submittime);
+                               submittime = atol(&buf[1]);
                                break;
 
                          case 'D':     /* data file name */
                                break;
 
                          case 'D':     /* data file name */
index 6dd31d2..beafcef 100644 (file)
@@ -9,7 +9,7 @@
 */
 
 #ifndef lint
 */
 
 #ifndef lint
-static char    SccsId[] = "@(#)readcf.c        5.3 (Berkeley) %G%";
+static char    SccsId[] = "@(#)readcf.c        5.3.1.1 (Berkeley) %G%";
 #endif not lint
 
 # include "sendmail.h"
 #endif not lint
 
 # include "sendmail.h"
@@ -36,10 +36,8 @@ static char  SccsId[] = "@(#)readcf.c        5.3 (Berkeley) %G%";
 **             Sn              Use rewriting set n.
 **             Rlhs rhs        Rewrite addresses that match lhs to
 **                             be rhs.
 **             Sn              Use rewriting set n.
 **             Rlhs rhs        Rewrite addresses that match lhs to
 **                             be rhs.
-**             Mn p f s r a    Define mailer.  n - internal name,
-**                             p - pathname, f - flags, s - rewriting
-**                             ruleset for sender, s - rewriting ruleset
-**                             for recipients, a - argument vector.
+**             Mn arg=val...   Define mailer.  n is the internal name.
+**                             Args specify mailer parameters.
 **             Oxvalue         Set option x to value.
 **             Pname=value     Set precedence name to value.
 **
 **             Oxvalue         Set option x to value.
 **             Pname=value     Set precedence name to value.
 **
@@ -672,6 +670,10 @@ setoption(opt, val, sticky)
                NoConnect = atobool(val);
                break;
 
                NoConnect = atobool(val);
                break;
 
+         case 'C':             /* checkpoint after N connections */
+               CheckPointLimit = atoi(val);
+               break;
+
          case 'd':             /* delivery mode */
                switch (*val)
                {
          case 'd':             /* delivery mode */
                switch (*val)
                {
@@ -765,6 +767,14 @@ setoption(opt, val, sticky)
                        CurEnv->e_flags &= ~EF_OLDSTYLE;
                break;
 
                        CurEnv->e_flags &= ~EF_OLDSTYLE;
                break;
 
+         case 'P':             /* postmaster copy address for returned mail */
+               PostMasterCopy = newstr(val);
+               break;
+
+         case 'q':             /* slope of queue only function */
+               QueueFactor = atoi(val);
+               break;
+
          case 'Q':             /* queue directory */
                if (val[0] == '\0')
                        QueueDir = "mqueue";
          case 'Q':             /* queue directory */
                if (val[0] == '\0')
                        QueueDir = "mqueue";
index d445b1f..02da06b 100644 (file)
@@ -9,7 +9,7 @@
 */
 
 #ifndef lint
 */
 
 #ifndef lint
-static char    SccsId[] = "@(#)savemail.c      5.2 (Berkeley) %G%";
+static char    SccsId[] = "@(#)savemail.c      5.3 (Berkeley) %G%";
 #endif not lint
 
 # include <pwd.h>
 #endif not lint
 
 # include <pwd.h>
@@ -35,11 +35,24 @@ static char SccsId[] = "@(#)savemail.c      5.2 (Berkeley) %G%";
 **             directory.
 */
 
 **             directory.
 */
 
+/* defines for state machine */
+# define ESM_REPORT    0       /* report to sender's terminal */
+# define ESM_MAIL      1       /* mail back to sender */
+# define ESM_QUIET     2       /* messages have already been returned */
+# define ESM_DEADLETTER        3       /* save in ~/dead.letter */
+# define ESM_POSTMASTER        4       /* return to postmaster */
+# define ESM_USRTMP    5       /* save in /usr/tmp/dead.letter */
+# define ESM_PANIC     6       /* leave the locked queue/transcript files */
+# define ESM_DONE      7       /* the message is successfully delivered */
+
+
 savemail(e)
        register ENVELOPE *e;
 {
        register struct passwd *pw;
 savemail(e)
        register ENVELOPE *e;
 {
        register struct passwd *pw;
-       register FILE *xfile;
+       register FILE *fp;
+       int state;
+       auto ADDRESS *q;
        char buf[MAXLINE+1];
        extern struct passwd *getpwnam();
        register char *p;
        char buf[MAXLINE+1];
        extern struct passwd *getpwnam();
        register char *p;
@@ -79,49 +92,74 @@ savemail(e)
        e->e_to = NULL;
 
        /*
        e->e_to = NULL;
 
        /*
-       **  If called from Eric Schmidt's network, do special mailback.
-       **      Fundamentally, this is the mailback case except that
-       **      it returns an OK exit status (assuming the return
-       **      worked).
-       **  Also, if the from address is not local, mail it back.
+       **  Basic state machine.
+       **
+       **      This machine runs through the following states:
+       **
+       **      ESM_QUIET       Errors have already been printed iff the
+       **                      sender is local.
+       **      ESM_REPORT      Report directly to the sender's terminal.
+       **      ESM_MAIL        Mail response to the sender.
+       **      ESM_DEADLETTER  Save response in ~/dead.letter.
+       **      ESM_POSTMASTER  Mail response to the postmaster.
+       **      ESM_PANIC       Save response anywhere possible.
        */
 
        */
 
-       if (ErrorMode == EM_BERKNET)
+       /* determine starting state */
+       switch (ErrorMode)
        {
        {
+         case EM_WRITE:
+               state = ESM_REPORT;
+               break;
+
+         case EM_BERKNET:
+               /* mail back, but return o.k. exit status */
                ExitStat = EX_OK;
                ExitStat = EX_OK;
-               ErrorMode = EM_MAIL;
-       }
-       if (!bitset(M_LOCAL, CurEnv->e_returnto->q_mailer->m_flags))
-               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 not, mail back instead.
-       */
+               /* fall through.... */
 
 
-       if (ErrorMode == EM_WRITE)
+         case EM_MAIL:
+               state = ESM_MAIL;
+               break;
+
+         case EM_PRINT:
+               state = ESM_QUIET;
+               break;
+
+         case EM_QUIET:
+               /* no need to return anything at all */
+               return;
+       }
+
+       while (state != ESM_DONE)
        {
        {
-               p = ttypath();
-               if (p == NULL || freopen(p, "w", stdout) == NULL)
-               {
-                       ErrorMode = EM_MAIL;
-                       errno = 0;
-               }
-               else
+               switch (state)
                {
                {
+                 case ESM_REPORT:
+
+                       /*
+                       **  If the user is still logged in on the same terminal,
+                       **  then write the error messages back to hir (sic).
+                       */
+
+                       p = ttypath();
+                       if (p == NULL || freopen(p, "w", stdout) == NULL)
+                       {
+                               state = ESM_MAIL;
+                               break;
+                       }
+
                        expand("\001n", buf, &buf[sizeof buf - 1], e);
                        printf("\r\nMessage from %s...\r\n", buf);
                        printf("Errors occurred while sending mail.\r\n");
                        if (e->e_xfp != NULL)
                        {
                                (void) fflush(e->e_xfp);
                        expand("\001n", buf, &buf[sizeof buf - 1], e);
                        printf("\r\nMessage from %s...\r\n", buf);
                        printf("Errors occurred while sending mail.\r\n");
                        if (e->e_xfp != NULL)
                        {
                                (void) fflush(e->e_xfp);
-                               xfile = fopen(queuename(e, 'x'), "r");
+                               fp = fopen(queuename(e, 'x'), "r");
                        }
                        else
                        }
                        else
-                               xfile = NULL;
-                       if (xfile == NULL)
+                               fp = NULL;
+                       if (fp == NULL)
                        {
                                syserr("Cannot open %s", queuename(e, 'x'));
                                printf("Transcript of session is unavailable.\r\n");
                        {
                                syserr("Cannot open %s", queuename(e, 'x'));
                                printf("Transcript of session is unavailable.\r\n");
@@ -129,76 +167,142 @@ savemail(e)
                        else
                        {
                                printf("Transcript follows:\r\n");
                        else
                        {
                                printf("Transcript follows:\r\n");
-                               while (fgets(buf, sizeof buf, xfile) != NULL &&
+                               while (fgets(buf, sizeof buf, fp) != NULL &&
                                       !ferror(stdout))
                                        fputs(buf, stdout);
                                       !ferror(stdout))
                                        fputs(buf, stdout);
-                               (void) fclose(xfile);
+                               (void) fclose(fp);
                        }
                        }
+                       printf("Original message will be saved in dead.letter.\r\n");
                        if (ferror(stdout))
                                (void) syserr("savemail: stdout: write err");
                        if (ferror(stdout))
                                (void) syserr("savemail: stdout: write err");
-               }
-       }
+                       state = ESM_DEADLETTER;
+                       break;
+
+                 case ESM_MAIL:
+                 case ESM_POSTMASTER:
+                       /*
+                       **  If mailing back, do it.
+                       **      Throw away all further output.  Don't alias,
+                       **      since this could cause loops, e.g., if joe
+                       **      mails to joe@x, and for some reason the network
+                       **      for @x is down, then the response gets sent to
+                       **      joe@x, which gives a response, etc.  Also force
+                       **      the mail to be delivered even if a version of
+                       **      it has already been sent to the sender.
+                       */
+
+                       if (state == ESM_MAIL)
+                       {
+                               if (e->e_errorqueue == NULL)
+                                       sendtolist(e->e_from.q_paddr,
+                                               (ADDRESS *) NULL,
+                                               &e->e_errorqueue);
+                               q = e->e_errorqueue;
+                       }
+                       else
+                       {
+                               if (parseaddr("postmaster", &q, 0, '\0') == NULL)
+                               {
+                                       syserr("cannot parse postmaster!");
+                                       ExitStat = EX_SOFTWARE;
+                                       state = ESM_USRTMP;
+                                       break;
+                               }
+                       }
+                       if (returntosender(e->e_message != NULL ? e->e_message :
+                                          "Unable to deliver mail",
+                                          q, TRUE) == 0)
+                       {
+                               state = ESM_DONE;
+                               break;
+                       }
 
 
-       /*
-       **  If mailing back, do it.
-       **      Throw away all further output.  Don't do aliases, since
-       **      this could cause loops, e.g., if joe mails to x:joe,
-       **      and for some reason the network for x: is down, then
-       **      the response gets sent to x:joe, which gives a
-       **      response, etc.  Also force the mail to be delivered
-       **      even if a version of it has already been sent to the
-       **      sender.
-       */
+                       state = state == ESM_MAIL ? ESM_POSTMASTER : ESM_USRTMP;
+                       break;
+
+                 case ESM_DEADLETTER:
+                       /*
+                       **  Save the message in dead.letter.
+                       **      If we weren't mailing back, and the user is
+                       **      local, we 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 UNIX users are.
+                       */
+
+                       p = NULL;
+                       if (e->e_from.q_mailer == LocalMailer)
+                       {
+                               if (e->e_from.q_home != NULL)
+                                       p = e->e_from.q_home;
+                               else if ((pw = getpwnam(e->e_from.q_user)) != NULL)
+                                       p = pw->pw_dir;
+                       }
+                       if (p == NULL)
+                       {
+                               syserr("Can't return mail to %s", e->e_from.q_paddr);
+                               state = ESM_MAIL;
+                               break;
+                       }
+                       if (e->e_dfp != NULL)
+                       {
+                               auto ADDRESS *q;
+                               bool oldverb = Verbose;
+
+                               /* we have a home directory; open dead.letter */
+                               define('z', p, e);
+                               expand("\001z/dead.letter", buf, &buf[sizeof buf - 1], e);
+                               Verbose = TRUE;
+                               message(Arpa_Info, "Saving message in %s", buf);
+                               Verbose = oldverb;
+                               e->e_to = buf;
+                               q = NULL;
+                               sendtolist(buf, (ADDRESS *) NULL, &q);
+                               if (deliver(e, q) == 0)
+                                       state = ESM_DONE;
+                               else
+                                       state = ESM_MAIL;
+                       }
+                       break;
 
 
-       if (ErrorMode == EM_MAIL)
-       {
-               if (returntosender("Unable to deliver mail", CurEnv->e_returnto, TRUE) == 0)
-                       return;
-       }
+                 case ESM_USRTMP:
+                       /*
+                       **  Log the mail in /usr/tmp/dead.letter.
+                       */
 
 
-       /*
-       **  Save the message in dead.letter.
-       **      If we weren't mailing back, and the user is local, we
-       **      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.
-       */
+                       fp = dfopen("/usr/tmp/dead.letter", "a");
+                       if (fp == NULL)
+                       {
+                               state = ESM_PANIC;
+                               break;
+                       }
 
 
-       p = NULL;
-       if (CurEnv->e_returnto->q_mailer == LocalMailer)
-       {
-               if (CurEnv->e_returnto->q_home != NULL)
-                       p = CurEnv->e_returnto->q_home;
-               else if ((pw = getpwnam(CurEnv->e_returnto->q_user)) != NULL)
-                       p = pw->pw_dir;
-       }
-       if (p == NULL)
-       {
-               syserr("Can't return mail to %s", CurEnv->e_returnto->q_paddr);
-# ifdef DEBUG
-               p = "/usr/tmp";
-# endif
-       }
-       if (p != NULL && e->e_dfp != NULL)
-       {
-               auto ADDRESS *q;
-               bool oldverb = Verbose;
-
-               /* we have a home directory; open dead.letter */
-               define('z', p, e);
-               expand("\001z/dead.letter", buf, &buf[sizeof buf - 1], e);
-               Verbose = TRUE;
-               message(Arpa_Info, "Saving message in %s", buf);
-               Verbose = oldverb;
-               e->e_to = buf;
-               q = NULL;
-               sendtolist(buf, (ADDRESS *) NULL, &q);
-               (void) deliver(e, q);
-       }
+                       putfromline(fp, ProgMailer);
+                       (*e->e_puthdr)(fp, ProgMailer, e);
+                       putline("\n", fp, ProgMailer);
+                       (*e->e_putbody)(fp, ProgMailer, e);
+                       putline("\n", fp, ProgMailer);
+                       (void) fflush(fp);
+                       state = ferror(fp) ? ESM_PANIC : ESM_DONE;
+                       (void) fclose(fp);
+                       break;
+
+                 default:
+                       syserr("savemail: unknown state %d", state);
+
+                       /* fall through ... */
+
+                 case ESM_PANIC:
+                       syserr("savemail: HELP!!!!");
+# ifdef LOG
+                       if (LogLevel >= 1)
+                               syslog(LOG_ALERT, "savemail: HELP!!!!");
+# endif LOG
 
 
-       /* add terminator to writeback message */
-       if (ErrorMode == EM_WRITE)
-               printf("-----\r\n");
+                       /* leave the locked queue & transcript files around */
+                       exit(EX_SOFTWARE);
+               }
+       }
 }
 \f/*
 **  RETURNTOSENDER -- return a message to the sender with an error.
 }
 \f/*
 **  RETURNTOSENDER -- return a message to the sender with an error.
@@ -240,7 +344,7 @@ returntosender(msg, returnq, sendbody)
        {
                printf("Return To Sender: msg=\"%s\", depth=%d, CurEnv=%x,\n",
                       msg, returndepth, CurEnv);
        {
                printf("Return To Sender: msg=\"%s\", depth=%d, CurEnv=%x,\n",
                       msg, returndepth, CurEnv);
-               printf("\treturnto=");
+               printf("\treturnq=");
                printaddr(returnq, TRUE);
        }
 # endif DEBUG
                printaddr(returnq, TRUE);
        }
 # endif DEBUG
@@ -257,6 +361,7 @@ returntosender(msg, returnq, sendbody)
        SendBody = sendbody;
        define('g', "\001f", CurEnv);
        ee = newenvelope(&errenvelope);
        SendBody = sendbody;
        define('g', "\001f", CurEnv);
        ee = newenvelope(&errenvelope);
+       define('a', "\001b", ee);
        ee->e_puthdr = putheader;
        ee->e_putbody = errbody;
        ee->e_flags |= EF_RESPONSE;
        ee->e_puthdr = putheader;
        ee->e_putbody = errbody;
        ee->e_flags |= EF_RESPONSE;
@@ -267,6 +372,7 @@ returntosender(msg, returnq, sendbody)
                if (q->q_alias == NULL)
                        addheader("to", q->q_paddr, ee);
        }
                if (q->q_alias == NULL)
                        addheader("to", q->q_paddr, ee);
        }
+
        (void) sprintf(buf, "Returned mail: %s", msg);
        addheader("subject", buf, ee);
 
        (void) sprintf(buf, "Returned mail: %s", msg);
        addheader("subject", buf, ee);
 
index ce40c11..b397ca2 100644 (file)
@@ -7,7 +7,7 @@
 **  All rights reserved.  The Berkeley software License Agreement
 **  specifies the terms and conditions for redistribution.
 **
 **  All rights reserved.  The Berkeley software License Agreement
 **  specifies the terms and conditions for redistribution.
 **
-**     @(#)sendmail.h  5.2 (Berkeley) %G%
+**     @(#)sendmail.h  5.1.1.1 (Berkeley) %G%
 */
 
 /*
 */
 
 /*
@@ -19,7 +19,7 @@
 # ifdef _DEFINE
 # define EXTERN
 # ifndef lint
 # ifdef _DEFINE
 # define EXTERN
 # ifndef lint
-static char SmailSccsId[] =    "@(#)sendmail.h 5.2             %G%";
+static char SmailSccsId[] =    "@(#)sendmail.h 5.1.1.1         %G%";
 # endif lint
 # else  _DEFINE
 # define EXTERN extern
 # endif lint
 # else  _DEFINE
 # define EXTERN extern
@@ -36,6 +36,13 @@ static char SmailSccsId[] =  "@(#)sendmail.h 5.2             %G%";
 # include <sys/syslog.h>
 # endif LOG
 
 # include <sys/syslog.h>
 # endif LOG
 
+# ifdef DAEMON
+# ifdef VMUNIX
+# include <sys/socket.h>
+# include <netinet/in.h>
+# endif VMUNIX
+# endif DAEMON
+
 
 # define PSBUFSIZE     (MAXNAME + MAXATOM)     /* size of prescan buffer */
 
 
 # define PSBUFSIZE     (MAXNAME + MAXATOM)     /* size of prescan buffer */
 
@@ -224,6 +231,7 @@ struct envelope
        ADDRESS         *e_sendqueue;   /* list of message recipients */
        ADDRESS         *e_errorqueue;  /* the queue for error responses */
        long            e_msgsize;      /* size of the message in bytes */
        ADDRESS         *e_sendqueue;   /* list of message recipients */
        ADDRESS         *e_errorqueue;  /* the queue for error responses */
        long            e_msgsize;      /* size of the message in bytes */
+       int             e_nrcpts;       /* number of recipients */
        short           e_class;        /* msg class (priority, junk, etc.) */
        short           e_flags;        /* flags, see below */
        short           e_hopcount;     /* number of times processed */
        short           e_class;        /* msg class (priority, junk, etc.) */
        short           e_flags;        /* flags, see below */
        short           e_hopcount;     /* number of times processed */
@@ -262,7 +270,8 @@ EXTERN ENVELOPE     *CurEnv;        /* envelope currently being processed */
 **     by the message priority and the amount of time the message
 **     has been sitting around.  Each priority point is worth
 **     WKPRIFACT bytes of message, and each time we reprocess a
 **     by the message priority and the amount of time the message
 **     has been sitting around.  Each priority point is worth
 **     WKPRIFACT bytes of message, and each time we reprocess a
-**     message the size gets reduced by WKTIMEFACT.
+**     message the size gets reduced by WKTIMEFACT.  Recipients are
+**     worth WKRECIPFACT.
 **
 **     WKTIMEFACT is negative since jobs that fail once have a high
 **     probability of failing again.  Making it negative tends to force
 **
 **     WKTIMEFACT is negative since jobs that fail once have a high
 **     probability of failing again.  Making it negative tends to force
@@ -286,6 +295,7 @@ EXTERN int          NumPriorities;  /* pointer into Priorities */
 
 # define WKPRIFACT     1800            /* bytes each pri point is worth */
 # define WKTIMEFACT    (-600)          /* bytes each reprocessing is worth */
 
 # define WKPRIFACT     1800            /* bytes each pri point is worth */
 # define WKTIMEFACT    (-600)          /* bytes each reprocessing is worth */
+# define WKRECIPFACT   1000            /* bytes each recipient is worth */
 \f/*
 **  Rewrite rules.
 */
 \f/*
 **  Rewrite rules.
 */
@@ -334,6 +344,32 @@ EXTERN struct rewrite      *RewriteRules[MAXRWSETS];
 
 /* \001 is also reserved as the macro expansion character */
 \f/*
 
 /* \001 is also reserved as the macro expansion character */
 \f/*
+**  Information about hosts that we have looked up recently.
+**
+**     This stuff is 4.2/3bsd specific.
+*/
+
+# ifdef DAEMON
+# ifdef VMUNIX
+
+# define HOSTINFO      struct hostinfo
+
+HOSTINFO
+{
+       char            *ho_name;       /* name of this host */
+       struct in_addr  ho_inaddr;      /* internet address */
+       short           ho_flags;       /* flag bits, see below */
+       short           ho_errno;       /* error number on last connection */
+       short           ho_exitstat;    /* exit status from last connection */
+};
+
+
+/* flag bits */
+#define HOF_VALID      00001           /* this entry is valid */
+
+# endif VMUNIX
+# endif DAEMON
+\f/*
 **  Symbol table definitions
 */
 
 **  Symbol table definitions
 */
 
@@ -344,10 +380,13 @@ struct symtab
        struct symtab   *s_next;        /* pointer to next in chain */
        union
        {
        struct symtab   *s_next;        /* pointer to next in chain */
        union
        {
-               BITMAP  sv_class;       /* bit-map of word classes */
-               ADDRESS *sv_addr;       /* pointer to address header */
-               MAILER  *sv_mailer;     /* pointer to mailer */
-               char    *sv_alias;      /* alias */
+               BITMAP          sv_class;       /* bit-map of word classes */
+               ADDRESS         *sv_addr;       /* pointer to address header */
+               MAILER          *sv_mailer;     /* pointer to mailer */
+               char            *sv_alias;      /* alias */
+# ifdef HOSTINFO
+               HOSTINFO        sv_host;        /* host information */
+# endif HOSTINFO
        }       s_value;
 };
 
        }       s_value;
 };
 
@@ -359,11 +398,13 @@ typedef struct symtab     STAB;
 # define ST_ADDRESS    2       /* an address in parsed format */
 # define ST_MAILER     3       /* a mailer header */
 # define ST_ALIAS      4       /* an alias */
 # define ST_ADDRESS    2       /* an address in parsed format */
 # define ST_MAILER     3       /* a mailer header */
 # define ST_ALIAS      4       /* an alias */
+# define ST_HOST       5       /* host information */
 
 # define s_class       s_value.sv_class
 # define s_address     s_value.sv_addr
 # define s_mailer      s_value.sv_mailer
 # define s_alias       s_value.sv_alias
 
 # define s_class       s_value.sv_class
 # define s_address     s_value.sv_addr
 # define s_mailer      s_value.sv_mailer
 # define s_alias       s_value.sv_alias
+# define s_host                s_value.sv_host
 
 extern STAB    *stab();
 
 
 extern STAB    *stab();
 
@@ -457,6 +498,7 @@ EXTERN bool QueueRun;       /* currently running message from the queue */
 EXTERN bool    HoldErrs;       /* only output errors to transcript */
 EXTERN bool    NoConnect;      /* don't connect to non-local mailers */
 EXTERN bool    SuperSafe;      /* be extra careful, even if expensive */
 EXTERN bool    HoldErrs;       /* only output errors to transcript */
 EXTERN bool    NoConnect;      /* don't connect to non-local mailers */
 EXTERN bool    SuperSafe;      /* be extra careful, even if expensive */
+EXTERN bool    ForkQueueRuns;  /* fork for each job when running the queue */
 EXTERN bool    AutoRebuild;    /* auto-rebuild the alias database as needed */
 EXTERN int     SafeAlias;      /* minutes to wait until @:@ in alias file */
 EXTERN time_t  TimeOut;        /* time until timeout */
 EXTERN bool    AutoRebuild;    /* auto-rebuild the alias database as needed */
 EXTERN int     SafeAlias;      /* minutes to wait until @:@ in alias file */
 EXTERN time_t  TimeOut;        /* time until timeout */
@@ -475,6 +517,9 @@ EXTERN int  LineNumber;     /* line number in current input */
 EXTERN time_t  ReadTimeout;    /* timeout on reads */
 EXTERN int     LogLevel;       /* level of logging to perform */
 EXTERN int     FileMode;       /* mode on files */
 EXTERN time_t  ReadTimeout;    /* timeout on reads */
 EXTERN int     LogLevel;       /* level of logging to perform */
 EXTERN int     FileMode;       /* mode on files */
+EXTERN int     QueueLA;        /* load average starting forced queueing */
+EXTERN int     RefuseLA;       /* load average refusing connections are */
+EXTERN int     QueueFactor;    /* slope of queue function */
 EXTERN time_t  QueueIntvl;     /* intervals between running the queue */
 EXTERN char    *HostName;      /* name of this host for SMTP messages */
 EXTERN char    *AliasFile;     /* location of alias file */
 EXTERN time_t  QueueIntvl;     /* intervals between running the queue */
 EXTERN char    *HostName;      /* name of this host for SMTP messages */
 EXTERN char    *AliasFile;     /* location of alias file */
@@ -482,13 +527,18 @@ 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    *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 char    *SmtpPhase;     /* current phase in SMTP processing */
+EXTERN char    *RealHostName;  /* name of host we are talking to */
 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    *ConfFile;      /* location of configuration file [conf.c] */
 extern char    *FreezeFile;    /* location of frozen memory image [conf.c] */
 extern char    Arpa_Info[];    /* the reply code for Arpanet info [conf.c] */
 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    *ConfFile;      /* location of configuration file [conf.c] */
 extern char    *FreezeFile;    /* location of frozen memory image [conf.c] */
 extern char    Arpa_Info[];    /* the reply code for Arpanet info [conf.c] */
-extern char    SpaceSub;       /* substitution for <lwsp> [conf.c] */
+extern ADDRESS NullAddress;    /* a null (template) address [main.c] */
+EXTERN char    SpaceSub;       /* substitution for <lwsp> */
+EXTERN int     CheckPointLimit;        /* deliveries before checkpointing */
+EXTERN char    *PostMasterCopy;        /* address to get errs cc's */
+EXTERN char    *TrustedUsers[MAXTRUST+1];      /* list of trusted users */
 \f/*
 **  Trace information
 */
 \f/*
 **  Trace information
 */
@@ -517,6 +567,8 @@ EXTERN u_char       tTdvect[100];
 /* make a copy of a string */
 #define newstr(s)      strcpy(xalloc(strlen(s) + 1), s)
 
 /* make a copy of a string */
 #define newstr(s)      strcpy(xalloc(strlen(s) + 1), s)
 
+#define STRUCTCOPY(s, d)       d = s
+
 
 /*
 **  Declarations of useful functions
 
 /*
 **  Declarations of useful functions
index 3c55e0b..2436ee5 100644 (file)
 
 # ifndef SMTP
 # ifndef lint
 
 # ifndef SMTP
 # ifndef lint
-static char    SccsId[] = "@(#)srvrsmtp.c      5.7 (Berkeley) %G%      (no SMTP)";
+static char    SccsId[] = "@(#)srvrsmtp.c      5.5.1.1 (Berkeley) %G%  (no SMTP)";
 # endif not lint
 # else SMTP
 
 # ifndef lint
 # endif not lint
 # else SMTP
 
 # ifndef lint
-static char    SccsId[] = "@(#)srvrsmtp.c      5.7 (Berkeley) %G%";
+static char    SccsId[] = "@(#)srvrsmtp.c      5.5.1.1 (Berkeley) %G%";
 # endif not lint
 
 /*
 # endif not lint
 
 /*
@@ -93,7 +93,6 @@ bool  IsWiz = FALSE;                  /* set if we are a wizard */
 char   *WizWord;                       /* the wizard word to compare against */
 bool   InChild = FALSE;                /* true if running in a subprocess */
 bool   OneXact = FALSE;                /* one xaction only this run */
 char   *WizWord;                       /* the wizard word to compare against */
 bool   InChild = FALSE;                /* true if running in a subprocess */
 bool   OneXact = FALSE;                /* one xaction only this run */
-char   *RealHostName = NULL;           /* verified hostname, set in daemon.c */
 
 #define EX_QUIT                22              /* special code for QUIT command */
 
 
 #define EX_QUIT                22              /* special code for QUIT command */
 
@@ -120,6 +119,7 @@ smtp()
        settime();
        expand("\001e", inp, &inp[sizeof inp], CurEnv);
        message("220", inp);
        settime();
        expand("\001e", inp, &inp[sizeof inp], CurEnv);
        message("220", inp);
+       SmtpPhase = "startup";
        for (;;)
        {
                /* arrange for backout */
        for (;;)
        {
                /* arrange for backout */
@@ -171,6 +171,7 @@ smtp()
                switch (c->cmdcode)
                {
                  case CMDHELO:         /* hello -- introduce yourself */
                switch (c->cmdcode)
                {
                  case CMDHELO:         /* hello -- introduce yourself */
+                       SmtpPhase = "HELO";
                        if (sameword(p, HostName))
                        {
                                /* connected to an echo server */
                        if (sameword(p, HostName))
                        {
                                /* connected to an echo server */
@@ -191,6 +192,8 @@ smtp()
                        break;
 
                  case CMDMAIL:         /* mail -- designate sender */
                        break;
 
                  case CMDMAIL:         /* mail -- designate sender */
+                       SmtpPhase = "MAIL";
+
                        /* force a sending host even if no HELO given */
                        if (RealHostName != NULL && macvalue('s', CurEnv) == NULL)
                                define('s', RealHostName, CurEnv);
                        /* force a sending host even if no HELO given */
                        if (RealHostName != NULL && macvalue('s', CurEnv) == NULL)
                                define('s', RealHostName, CurEnv);
@@ -227,6 +230,7 @@ smtp()
                        break;
 
                  case CMDRCPT:         /* rcpt -- designate recipient */
                        break;
 
                  case CMDRCPT:         /* rcpt -- designate recipient */
+                       SmtpPhase = "RCPT";
                        if (setjmp(TopFrame) > 0)
                        {
                                CurEnv->e_flags &= ~EF_FATALERRS;
                        if (setjmp(TopFrame) > 0)
                        {
                                CurEnv->e_flags &= ~EF_FATALERRS;
@@ -258,18 +262,20 @@ smtp()
                        break;
 
                  case CMDDATA:         /* data -- text of mail */
                        break;
 
                  case CMDDATA:         /* data -- text of mail */
+                       SmtpPhase = "DATA";
                        if (!hasmail)
                        {
                                message("503", "Need MAIL command");
                                break;
                        }
                        if (!hasmail)
                        {
                                message("503", "Need MAIL command");
                                break;
                        }
-                       else if (rcps <= 0)
+                       else if (CurEnv->e_nrcpts <= 0)
                        {
                                message("503", "Need RCPT (recipient)");
                                break;
                        }
 
                        /* collect the text of the message */
                        {
                                message("503", "Need RCPT (recipient)");
                                break;
                        }
 
                        /* collect the text of the message */
+                       SmtpPhase = "collect";
                        collect(TRUE);
                        if (Errors != 0)
                                break;
                        collect(TRUE);
                        if (Errors != 0)
                                break;
@@ -292,7 +298,8 @@ smtp()
                        **      We goose error returns by clearing error bit.
                        */
 
                        **      We goose error returns by clearing error bit.
                        */
 
-                       if (rcps != 1)
+                       SmtpPhase = "delivery";
+                       if (CurEnv->e_nrcpts != 1)
                        {
                                HoldErrs = TRUE;
                                ErrorMode = EM_MAIL;
                        {
                                HoldErrs = TRUE;
                                ErrorMode = EM_MAIL;
@@ -316,6 +323,13 @@ smtp()
                        /* if in a child, pop back to our parent */
                        if (InChild)
                                finis();
                        /* if in a child, pop back to our parent */
                        if (InChild)
                                finis();
+
+                       /* clean up a bit */
+                       hasmail = 0;
+                       rcps = 0;
+                       dropenvelope(CurEnv);
+                       CurEnv = newenvelope(CurEnv);
+                       CurEnv->e_flags = BlankEnvelope.e_flags;
                        break;
 
                  case CMDRSET:         /* rset -- reset state */
                        break;
 
                  case CMDRSET:         /* rset -- reset state */
index 1e5f9ab..5ef88cd 100644 (file)
@@ -9,7 +9,7 @@
 */
 
 #ifndef lint
 */
 
 #ifndef lint
-static char    SccsId[] = "@(#)stats.c 5.5 (Berkeley) %G%";
+static char    SccsId[] = "@(#)stats.c 5.4.1.1 (Berkeley) %G%";
 #endif not lint
 
 # include "sendmail.h"
 #endif not lint
 
 # include "sendmail.h"
@@ -29,7 +29,9 @@ struct statistics
 };
 
 struct statistics      Stat;
 };
 
 struct statistics      Stat;
-extern long            kbytes();       /* for _bf, _bt */
+
+#define ONE_K          1000            /* one thousand (twenty-four?) */
+#define KBYTES(x)      (((x) + (ONE_K - 1)) / ONE_K)
 \f/*
 **  MARKSTATS -- mark statistics
 */
 \f/*
 **  MARKSTATS -- mark statistics
 */
@@ -54,7 +56,7 @@ markstats(e, to)
        else
        {
                Stat.stat_nt[to->q_mailer->m_mno]++;
        else
        {
                Stat.stat_nt[to->q_mailer->m_mno]++;
-               Stat.stat_bt[to->q_mailer->m_mno] += kbytes(CurEnv->e_msgsize);
+               Stat.stat_bt[to->q_mailer->m_mno] += KBYTES(CurEnv->e_msgsize);
        }
 }
 \f/*
        }
 }
 \f/*
@@ -111,31 +113,3 @@ poststats(sfile)
        (void) write(fd, (char *) &stat, sizeof stat);
        (void) close(fd);
 }
        (void) write(fd, (char *) &stat, sizeof stat);
        (void) close(fd);
 }
-\f/*
-**  KBYTES -- given a number, returns the number of Kbytes.
-**
-**     Used in statistics gathering of message sizes to try to avoid
-**     wraparound (at least for a while.....)
-**
-**     Parameters:
-**             bytes -- actual number of bytes.
-**
-**     Returns:
-**             number of kbytes.
-**
-**     Side Effects:
-**             none.
-**
-**     Notes:
-**             This function is actually a ceiling function to
-**                     the nearest K.
-**             Honestly folks, floating point might be better.
-**                     Or perhaps a "statistical" log method.
-*/
-
-long
-kbytes(bytes)
-       long bytes;
-{
-       return ((bytes + 999) / 1000);
-}
index 2e63381..f2a8fe3 100644 (file)
 
 # ifndef SMTP
 # ifndef lint
 
 # ifndef SMTP
 # ifndef lint
-static char    SccsId[] = "@(#)usersmtp.c      5.4 (Berkeley) %G%      (no SMTP)";
+static char    SccsId[] = "@(#)usersmtp.c      5.3.1.1 (Berkeley) %G%  (no SMTP)";
 # endif not lint
 # else SMTP
 
 # ifndef lint
 # endif not lint
 # else SMTP
 
 # ifndef lint
-static char    SccsId[] = "@(#)usersmtp.c      5.4 (Berkeley) %G%";
+static char    SccsId[] = "@(#)usersmtp.c      5.3.1.1 (Berkeley) %G%";
 # endif not lint
 
 
 # endif not lint
 
 
@@ -90,6 +90,7 @@ smtpinit(m, pvp)
        SmtpIn = SmtpOut = NULL;
        SmtpState = SMTP_CLOSED;
        SmtpError[0] = '\0';
        SmtpIn = SmtpOut = NULL;
        SmtpState = SMTP_CLOSED;
        SmtpError[0] = '\0';
+       SmtpPhase = "user open";
        SmtpPid = openmailer(m, pvp, (ADDRESS *) NULL, TRUE, &SmtpOut, &SmtpIn);
        if (SmtpPid < 0)
        {
        SmtpPid = openmailer(m, pvp, (ADDRESS *) NULL, TRUE, &SmtpOut, &SmtpIn);
        if (SmtpPid < 0)
        {
@@ -131,6 +132,7 @@ smtpinit(m, pvp)
        if (setjmp(CtxGreeting) != 0)
                goto tempfail;
        gte = setevent((time_t) 300, greettimeout, 0);
        if (setjmp(CtxGreeting) != 0)
                goto tempfail;
        gte = setevent((time_t) 300, greettimeout, 0);
+       SmtpPhase = "greeting wait";
        r = reply(m);
        clrevent(gte);
        if (r < 0 || REPLYTYPE(r) != 2)
        r = reply(m);
        clrevent(gte);
        if (r < 0 || REPLYTYPE(r) != 2)
@@ -142,6 +144,7 @@ smtpinit(m, pvp)
        */
 
        smtpmessage("HELO %s", m, HostName);
        */
 
        smtpmessage("HELO %s", m, HostName);
+       SmtpPhase = "HELO wait";
        r = reply(m);
        if (r < 0)
                goto tempfail;
        r = reply(m);
        if (r < 0)
                goto tempfail;
@@ -194,6 +197,7 @@ smtpinit(m, pvp)
                smtpmessage("MAIL From:<@%s%c%s>", m, HostName,
                        buf[0] == '@' ? ',' : ':', buf);
        }
                smtpmessage("MAIL From:<@%s%c%s>", m, HostName,
                        buf[0] == '@' ? ',' : ':', buf);
        }
+       SmtpPhase = "MAIL wait";
        r = reply(m);
        if (r < 0 || REPLYTYPE(r) == 4)
                goto tempfail;
        r = reply(m);
        if (r < 0 || REPLYTYPE(r) == 4)
                goto tempfail;
@@ -248,6 +252,7 @@ smtprcpt(to, m)
 
        smtpmessage("RCPT To:<%s>", m, remotename(to->q_user, m, FALSE, TRUE));
 
 
        smtpmessage("RCPT To:<%s>", m, remotename(to->q_user, m, FALSE, TRUE));
 
+       SmtpPhase = "RCPT wait";
        r = reply(m);
        if (r < 0 || REPLYTYPE(r) == 4)
                return (EX_TEMPFAIL);
        r = reply(m);
        if (r < 0 || REPLYTYPE(r) == 4)
                return (EX_TEMPFAIL);
@@ -289,6 +294,7 @@ smtpdata(m, e)
 
        /* send the command and check ok to proceed */
        smtpmessage("DATA", m);
 
        /* send the command and check ok to proceed */
        smtpmessage("DATA", m);
+       SmtpPhase = "DATA wait";
        r = reply(m);
        if (r < 0 || REPLYTYPE(r) == 4)
                return (EX_TEMPFAIL);
        r = reply(m);
        if (r < 0 || REPLYTYPE(r) == 4)
                return (EX_TEMPFAIL);
@@ -308,6 +314,7 @@ smtpdata(m, e)
                nmessage(Arpa_Info, ">>> .");
 
        /* check for the results of the transaction */
                nmessage(Arpa_Info, ">>> .");
 
        /* check for the results of the transaction */
+       SmtpPhase = "result wait";
        r = reply(m);
        if (r < 0 || REPLYTYPE(r) == 4)
                return (EX_TEMPFAIL);
        r = reply(m);
        if (r < 0 || REPLYTYPE(r) == 4)
                return (EX_TEMPFAIL);
index 7f66dad..f81d657 100644 (file)
@@ -9,7 +9,7 @@
 */
 
 #ifndef lint
 */
 
 #ifndef lint
-static char    SccsId[] = "@(#)util.c  5.5 (Berkeley) %G%";
+static char    SccsId[] = "@(#)util.c  5.6 (Berkeley) %G%";
 #endif not lint
 
 # include <stdio.h>
 #endif not lint
 
 # include <stdio.h>
@@ -620,7 +620,11 @@ sfgets(buf, siz, fp)
                if (setjmp(CtxReadTimeout) != 0)
                {
                        errno = ETIMEDOUT;
                if (setjmp(CtxReadTimeout) != 0)
                {
                        errno = ETIMEDOUT;
-                       syserr("sfgets: timeout on read (mailer may be hung)");
+                       if (RealHostName == NULL)
+                               syserr("timeout on read");
+                       else
+                               syserr("net timeout reading from %s", RealHostName);
+                       errno = ETIMEDOUT;
                        buf[0] = '\0';
                        return (NULL);
                }
                        buf[0] = '\0';
                        return (NULL);
                }