open connection caching
authorEric Allman <eric@ucbvax.Berkeley.EDU>
Sun, 12 Jul 1992 09:51:58 +0000 (01:51 -0800)
committerEric Allman <eric@ucbvax.Berkeley.EDU>
Sun, 12 Jul 1992 09:51:58 +0000 (01:51 -0800)
SCCS-vsn: usr.sbin/sendmail/src/usersmtp.c 5.22
SCCS-vsn: usr.sbin/sendmail/src/main.c 5.50
SCCS-vsn: usr.sbin/sendmail/src/version.c 5.101
SCCS-vsn: usr.sbin/sendmail/src/sendmail.h 5.34
SCCS-vsn: usr.sbin/sendmail/src/savemail.c 5.17
SCCS-vsn: usr.sbin/sendmail/src/daemon.c 5.46
SCCS-vsn: usr.sbin/sendmail/src/Makefile 5.25
SCCS-vsn: usr.sbin/sendmail/src/readcf.c 5.39
SCCS-vsn: usr.sbin/sendmail/src/deliver.c 5.57
SCCS-vsn: usr.sbin/sendmail/src/queue.c 5.40
SCCS-vsn: usr.sbin/sendmail/src/conf.c 5.37
SCCS-vsn: usr.sbin/sendmail/src/mci.c 5.2

12 files changed:
usr/src/usr.sbin/sendmail/src/Makefile
usr/src/usr.sbin/sendmail/src/conf.c
usr/src/usr.sbin/sendmail/src/daemon.c
usr/src/usr.sbin/sendmail/src/deliver.c
usr/src/usr.sbin/sendmail/src/main.c
usr/src/usr.sbin/sendmail/src/mci.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/usersmtp.c
usr/src/usr.sbin/sendmail/src/version.c

index 563cd57..2df4732 100644 (file)
@@ -1,16 +1,16 @@
-#      @(#)Makefile    5.24 (Berkeley) %G%
+#      @(#)Makefile    5.25 (Berkeley) %G%
 
 PROG=  sendmail
 
 CFLAGS+=-I${.CURDIR}
 
 SRCS=  alias.c arpadate.c clock.c collect.c conf.c convtime.c daemon.c \
 
 PROG=  sendmail
 
 CFLAGS+=-I${.CURDIR}
 
 SRCS=  alias.c arpadate.c clock.c collect.c conf.c convtime.c daemon.c \
-       deliver.c domain.c envelope.c err.c headers.c macro.c main.c \
+       deliver.c domain.c envelope.c err.c headers.c macro.c main.c mci.c \
        parseaddr.c queue.c readcf.c recipient.c savemail.c srvrsmtp.c \
        stab.c stats.c sysexits.c trace.c udb.c usersmtp.c \
        util.c version.c
 DPADD= ${LIBDBM} ${LIBCOMPAT} ${LIBUTIL}
        parseaddr.c queue.c readcf.c recipient.c savemail.c srvrsmtp.c \
        stab.c stats.c sysexits.c trace.c udb.c usersmtp.c \
        util.c version.c
 DPADD= ${LIBDBM} ${LIBCOMPAT} ${LIBUTIL}
-LDADD= -ldbm -lcompat -lutil
+LDADD= -ldbm -lcompat -lutil -lkvm
 MAN1=  newaliases.0
 MAN5=  aliases.0
 MAN8=  sendmail.0 
 MAN1=  newaliases.0
 MAN5=  aliases.0
 MAN8=  sendmail.0 
index 713fc36..589981c 100644 (file)
@@ -7,7 +7,7 @@
  */
 
 #ifndef lint
  */
 
 #ifndef lint
-static char sccsid[] = "@(#)conf.c     5.36 (Berkeley) %G%";
+static char sccsid[] = "@(#)conf.c     5.37 (Berkeley) %G%";
 #endif /* not lint */
 
 # include <sys/ioctl.h>
 #endif /* not lint */
 
 # include <sys/ioctl.h>
@@ -145,6 +145,8 @@ setdefaults()
        SendMode = SM_FORK;
        ErrorMode = EM_PRINT;
        EightBit = FALSE;
        SendMode = SM_FORK;
        ErrorMode = EM_PRINT;
        EightBit = FALSE;
+       MaxMciCache = 1;
+       MciCacheTimeout = 300;
        setdefuser();
        setupmaps();
 }
        setdefuser();
        setupmaps();
 }
index 66f604c..0be083d 100644 (file)
@@ -12,9 +12,9 @@
 
 #ifndef lint
 #ifdef DAEMON
 
 #ifndef lint
 #ifdef DAEMON
-static char sccsid[] = "@(#)daemon.c   5.45 (Berkeley) %G% (with daemon mode)";
+static char sccsid[] = "@(#)daemon.c   5.46 (Berkeley) %G% (with daemon mode)";
 #else
 #else
-static char sccsid[] = "@(#)daemon.c   5.45 (Berkeley) %G% (without daemon mode)";
+static char sccsid[] = "@(#)daemon.c   5.46 (Berkeley) %G% (without daemon mode)";
 #endif
 #endif /* not lint */
 
 #endif
 #endif /* not lint */
 
@@ -167,10 +167,11 @@ getrequests()
 **             none.
 */
 
 **             none.
 */
 
+int
 makeconnection(host, port, mci, usesecureport)
        char *host;
        u_short port;
 makeconnection(host, port, mci, usesecureport)
        char *host;
        u_short port;
-       register MCONINFO *mci;
+       register MCI *mci;
        bool usesecureport;
 {
        register int i, s;
        bool usesecureport;
 {
        register int i, s;
@@ -284,7 +285,7 @@ again:
        }
 
        if (tTd(16, 1))
        }
 
        if (tTd(16, 1))
-               printf("makeconnection: %d\n", s);
+               printf("makeconnection: fd=%d\n", s);
 
        /* turn on network debugging? */
        if (tTd(16, 14))
 
        /* turn on network debugging? */
        if (tTd(16, 14))
index b5d583f..2f4519e 100644 (file)
@@ -7,7 +7,7 @@
  */
 
 #ifndef lint
  */
 
 #ifndef lint
-static char sccsid[] = "@(#)deliver.c  5.56 (Berkeley) %G%";
+static char sccsid[] = "@(#)deliver.c  5.57 (Berkeley) %G%";
 #endif /* not lint */
 
 #include "sendmail.h"
 #endif /* not lint */
 
 #include "sendmail.h"
@@ -55,6 +55,7 @@ deliver(e, firstto)
        register char *p;
        register MAILER *m;             /* mailer for this recipient */
        ADDRESS *ctladdr;
        register char *p;
        register MAILER *m;             /* mailer for this recipient */
        ADDRESS *ctladdr;
+       register MCI *mci;
        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 */
@@ -68,6 +69,7 @@ deliver(e, firstto)
        extern bool checkcompat();
        extern ADDRESS *getctladdr();
        extern char *remotename();
        extern bool checkcompat();
        extern ADDRESS *getctladdr();
        extern char *remotename();
+       extern MCI *openmailer();
 
        errno = 0;
        if (!ForceMail && bitset(QDONTSEND|QPSEUDO, to->q_flags))
 
        errno = 0;
        if (!ForceMail && bitset(QDONTSEND|QPSEUDO, to->q_flags))
@@ -109,7 +111,7 @@ deliver(e, firstto)
                        e->e_to = to->q_paddr;
                        message(Arpa_Info, "queued");
                        if (LogLevel > 4)
                        e->e_to = to->q_paddr;
                        message(Arpa_Info, "queued");
                        if (LogLevel > 4)
-                               logdelivery("queued");
+                               logdelivery("queued", e);
                }
                e->e_to = NULL;
                return (0);
                }
                e->e_to = NULL;
                return (0);
@@ -305,7 +307,7 @@ deliver(e, firstto)
                {
                        if (user[0] == '/')
                        {
                {
                        if (user[0] == '/')
                        {
-                               rcode = mailfile(user, getctladdr(to));
+                               rcode = mailfile(user, getctladdr(to), e);
                                giveresponse(rcode, m, e);
                                if (rcode == EX_OK)
                                        to->q_flags |= QSENT;
                                giveresponse(rcode, m, e);
                                if (rcode == EX_OK)
                                        to->q_flags |= QSENT;
@@ -382,81 +384,105 @@ deliver(e, firstto)
        if (ConfigLevel < 2)
                _res.options &= ~(RES_DEFNAMES | RES_DNSRCH);   /* XXX */
 #endif
        if (ConfigLevel < 2)
                _res.options &= ~(RES_DEFNAMES | RES_DNSRCH);   /* XXX */
 #endif
-#ifdef SMTP
-       if (clever)
+       mci = openmailer(m, pv, ctladdr, clever, e);
+       if (mci == NULL)
        {
        {
-               register MCONINFO *mci;
-
-               rcode = EX_OK;
-#ifdef NAMED_BIND
-               if (host[0] && host[0] != '[')
-               {
-                       expand("\001j", buf, &buf[sizeof(buf) - 1], e);
-                       Nmx = getmxrr(host, MxHosts, buf, &rcode);
-               }
-               else
-#endif
+               /* catastrophic error */
+               rcode = -1;
+               goto give_up;
+       }
+       else if (mci->mci_state != MCIS_OPEN)
+       {
+               /* couldn't open the mailer */
+               rcode = mci->mci_exitstat;
+               if (rcode == EX_OK)
                {
                {
-                       Nmx = 1;
-                       MxHosts[0] = host;
+                       /* shouldn't happen */
+                       rcode = EX_SOFTWARE;
                }
                }
-               if (Nmx >= 0)
+       }
+       else if (!clever)
+       {
+               /*
+               **  Format and send message.
+               */
+
+               putfromline(mci->mci_out, m, e);
+               (*e->e_puthdr)(mci->mci_out, m, e);
+               putline("\n", mci->mci_out, m);
+               (*e->e_putbody)(mci->mci_out, m, e);
+
+               /* get the exit status */
+               rcode = endmailer(mci, pv[0]);
+       }
+       else
+#ifdef SMTP
+       {
+               /*
+               **  Send the MAIL FROM: protocol
+               */
+
+               rcode = smtpmailfrom(m, mci, e);
+               if (rcode == EX_OK)
                {
                {
-                       extern MCONINFO *smtpinit();
+                       register char *t = tobuf;
+                       register int i;
 
 
-                       mci = smtpinit(m, pv, e);
-                       if (mci != NULL &&
-                           mci->mci_state == MCIS_OPEN &&
-                           mci->mci_exitstat == EX_OK &&
-                           smtpmailfrom(m, mci, e) == EX_OK)
+                       /* send the recipient list */
+                       tobuf[0] = '\0';
+                       for (to = tochain; to != NULL; to = to->q_tchain)
                        {
                        {
-                               register char *t = tobuf;
-                               register int i;
-
-                               /* send the recipient list */
-                               tobuf[0] = '\0';
-                               for (to = tochain; to != NULL; to = to->q_tchain)
+                               e->e_to = to->q_paddr;
+                               if ((i = smtprcpt(to, m, mci, e)) != EX_OK)
                                {
                                {
-                                       e->e_to = to->q_paddr;
-                                       if ((i = smtprcpt(to, m, mci, e)) != EX_OK)
-                                       {
-                                               markfailure(e, to, i);
-                                               giveresponse(i, m, e);
-                                       }
-                                       else
-                                       {
-                                               *t++ = ',';
-                                               for (p = to->q_paddr; *p; *t++ = *p++);
-                                       }
+                                       markfailure(e, to, i);
+                                       giveresponse(i, m, e);
                                }
                                }
-
-                               /* now send the data */
-                               if (tobuf[0] == '\0')
-                                       e->e_to = NULL;
                                else
                                {
                                else
                                {
-                                       e->e_to = tobuf + 1;
-                                       rcode = smtpdata(m, mci, e);
+                                       *t++ = ',';
+                                       for (p = to->q_paddr; *p; *t++ = *p++)
+                                               continue;
                                }
                                }
+                       }
 
 
-                               /* now close the connection */
-                               smtpquit(m, mci, e);
+                       /* now send the data */
+                       if (tobuf[0] == '\0')
+                       {
+                               e->e_to = NULL;
+                               if (bitset(MCIF_CACHED, mci->mci_flags))
+                                       smtprset(m, mci, e);
                        }
                        }
+                       else
+                       {
+                               e->e_to = tobuf + 1;
+                               rcode = smtpdata(m, mci, e);
+                       }
+
+                       /* now close the connection */
+                       if (!bitset(MCIF_CACHED, mci->mci_flags))
+                               smtpquit(m, mci, e);
                }
        }
                }
        }
-       else
-#endif /* SMTP */
+#else /* not SMTP */
        {
        {
-               static int sendoff();
-
-               message(Arpa_Info, "Connecting to %s (%s)...", host, m->m_name);
-               rcode = sendoff(e, m, pv, ctladdr);
+               syserr("deliver: need SMTP compiled to use clever mailer");
+               rcode = -1;
+               goto give_up;
        }
        }
+#endif /* SMTP */
 #ifdef NAMED_BIND
        if (ConfigLevel < 2)
                _res.options |= RES_DEFNAMES | RES_DNSRCH;      /* XXX */
 #endif
 
 #ifdef NAMED_BIND
        if (ConfigLevel < 2)
                _res.options |= RES_DEFNAMES | RES_DNSRCH;      /* XXX */
 #endif
 
+       /* arrange a return receipt if requested */
+       if (e->e_receiptto != NULL && bitnset(M_LOCAL, m->m_flags))
+       {
+               e->e_flags |= EF_SENDRECEIPT;
+               /* do we want to send back more info? */
+       }
+
        /*
        **  Do final status disposal.
        **      We check for something in tobuf for the SMTP case.
        /*
        **  Do final status disposal.
        **      We check for something in tobuf for the SMTP case.
@@ -464,13 +490,20 @@ deliver(e, firstto)
        **              addressees.
        */
 
        **              addressees.
        */
 
+  give_up:
        if (tobuf[0] != '\0')
                giveresponse(rcode, m, e);
        for (to = tochain; to != NULL; to = to->q_tchain)
        if (tobuf[0] != '\0')
                giveresponse(rcode, m, e);
        for (to = tochain; to != NULL; to = to->q_tchain)
+       {
                if (rcode != EX_OK)
                        markfailure(e, to, rcode);
                else
                        to->q_flags |= QSENT;
                if (rcode != EX_OK)
                        markfailure(e, to, rcode);
                else
                        to->q_flags |= QSENT;
+       }
+
+       /*
+       **  Restore state and return.
+       */
 
        errno = 0;
        define('g', (char *) NULL, e);
 
        errno = 0;
        define('g', (char *) NULL, e);
@@ -587,61 +620,6 @@ dofork()
        return (pid);
 }
 \f/*
        return (pid);
 }
 \f/*
-**  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
-**                     user/groupid etc. of the mailer.
-**
-**     Returns:
-**             exit status of mailer.
-**
-**     Side Effects:
-**             none.
-*/
-static
-sendoff(e, m, pvp, ctladdr)
-       register ENVELOPE *e;
-       MAILER *m;
-       char **pvp;
-       ADDRESS *ctladdr;
-{
-       register int i;
-       register MCONINFO *mci;
-       extern MCONINFO *openmailer();
-
-       /*
-       **  Create connection to mailer.
-       */
-
-       mci = openmailer(m, pvp, ctladdr, FALSE);
-       if (mci == NULL)
-               return (-1);
-
-       /*
-       **  Format and send message.
-       */
-
-       putfromline(mci->mci_out, m);
-       (*e->e_puthdr)(mci->mci_out, m, e);
-       putline("\n", mci->mci_out, m);
-       (*e->e_putbody)(mci->mci_out, m, e);
-
-       i = endmailer(mci, pvp[0]);
-
-       /* arrange a return receipt if requested */
-       if (e->e_receiptto != NULL && bitnset(M_LOCAL, m->m_flags))
-       {
-               e->e_flags |= EF_SENDRECEIPT;
-               /* do we want to send back more info? */
-       }
-
-       return (i);
-}
-\f/*
 **  ENDMAILER -- Wait for mailer to terminate.
 **
 **     We should never get fatal errors (e.g., segmentation
 **  ENDMAILER -- Wait for mailer to terminate.
 **
 **     We should never get fatal errors (e.g., segmentation
@@ -661,7 +639,7 @@ sendoff(e, m, pvp, ctladdr)
 */
 
 endmailer(mci, name)
 */
 
 endmailer(mci, name)
-       register MCONINFO *mci;
+       register MCI *mci;
        char *name;
 {
        int st;
        char *name;
 {
        int st;
@@ -673,8 +651,6 @@ endmailer(mci, name)
                (void) fclose(mci->mci_out);
        mci->mci_in = mci->mci_out = NULL;
        mci->mci_state = MCIS_CLOSED;
                (void) fclose(mci->mci_out);
        mci->mci_in = mci->mci_out = NULL;
        mci->mci_state = MCIS_CLOSED;
-       if (bitset(MCIF_TEMP, mci->mci_flags))
-               free(mci);
 
        /* in the IPC case there is nothing to wait for */
        if (mci->mci_pid == 0)
 
        /* in the IPC case there is nothing to wait for */
        if (mci->mci_pid == 0)
@@ -717,15 +693,16 @@ endmailer(mci, name)
 **             creates a mailer in a subprocess.
 */
 
 **             creates a mailer in a subprocess.
 */
 
-MCONINFO *
-openmailer(m, pvp, ctladdr, clever)
+MCI *
+openmailer(m, pvp, ctladdr, clever, e)
        MAILER *m;
        char **pvp;
        ADDRESS *ctladdr;
        bool clever;
        MAILER *m;
        char **pvp;
        ADDRESS *ctladdr;
        bool clever;
+       ENVELOPE *e;
 {
        int pid;
 {
        int pid;
-       register MCONINFO *mci;
+       register MCI *mci;
        int mpvect[2];
        int rpvect[2];
        extern FILE *fdopen();
        int mpvect[2];
        int rpvect[2];
        extern FILE *fdopen();
@@ -751,222 +728,250 @@ openmailer(m, pvp, ctladdr, clever)
        /* check for Local Person Communication -- not for mortals!!! */
        if (strcmp(m->m_mailer, "[LPC]") == 0)
        {
        /* check for Local Person Communication -- not for mortals!!! */
        if (strcmp(m->m_mailer, "[LPC]") == 0)
        {
-               mci = (MCONINFO *) xalloc(sizeof *mci);
+               mci = (MCI *) xalloc(sizeof *mci);
                mci->mci_in = stdin;
                mci->mci_out = stdout;
                mci->mci_pid = 0;
                mci->mci_in = stdin;
                mci->mci_out = stdout;
                mci->mci_pid = 0;
-               mci->mci_state = MCIS_OPEN;
+               mci->mci_state = clever ? MCIS_OPENING : MCIS_OPEN;
                mci->mci_mailer = m;
                mci->mci_mailer = m;
-               return mci;
+               mci->mci_flags = 0;
        }
        }
-
-       if (strcmp(m->m_mailer, "[IPC]") == 0 ||
-           strcmp(m->m_mailer, "[TCP]") == 0)
+       else if (strcmp(m->m_mailer, "[IPC]") == 0 ||
+                strcmp(m->m_mailer, "[TCP]") == 0)
        {
 #ifdef DAEMON
                register STAB *st;
                extern STAB *stab();
                register int i, j;
                register u_short port;
        {
 #ifdef DAEMON
                register STAB *st;
                extern STAB *stab();
                register int i, j;
                register u_short port;
+               int nmx;
+               char *mxhosts[MAXMXHOSTS + 1];
+               extern MCI *mci_get();
 
                CurHostName = pvp[1];
 
                CurHostName = pvp[1];
+#ifdef NAMED_BIND
+               if (CurHostName != NULL && CurHostName[0] != '\0' &&
+                   CurHostName[0] != '[')
+               {
+                       int rcode;
+                       char buf[MAXNAME];
+
+                       expand("\001j", buf, &buf[sizeof(buf) - 1], e);
+                       nmx = getmxrr(CurHostName, mxhosts, buf, &rcode);
+                       if (nmx < 0)
+                       {
+                               mci = mci_get(CurHostName, m);
+                               mci->mci_exitstat = rcode;
+                               mci->mci_errno = errno;
+                       }
+               }
+               else
+#endif
+               {
+                       nmx = 1;
+                       mxhosts[0] = CurHostName;
+               }
+
                if (!clever)
                        syserr("non-clever IPC");
                if (pvp[2] != NULL)
                        port = atoi(pvp[2]);
                else
                        port = 0;
                if (!clever)
                        syserr("non-clever IPC");
                if (pvp[2] != NULL)
                        port = atoi(pvp[2]);
                else
                        port = 0;
-               for (j = 0; j < Nmx; j++)
+               for (j = 0; j < nmx; j++)
                {
                        /* see if we already know that this host is fried */
                {
                        /* see if we already know that this host is fried */
-                       CurHostName = MxHosts[j];
-                       st = stab(CurHostName,
-                                 ST_MCONINFO + m->m_mno,
-                                 ST_ENTER);
-                       mci = &st->s_mci;
-                       if (mci->mci_state == MCIS_OPEN)
+                       CurHostName = mxhosts[j];
+                       mci = mci_get(CurHostName, m);
+                       if (mci->mci_state != MCIS_CLOSED)
                                return mci;
                        mci->mci_mailer = m;
                                return mci;
                        mci->mci_mailer = m;
-                       if (mci->mci_state == MCIS_CLOSED)
-                       {
-                               /* try the connection */
-                               message(Arpa_Info, "Connecting to %s (%s)...",
-                                       MxHosts[j], m->m_name);
-                               i = makeconnection(MxHosts[j], port, mci,
-                                       bitnset(M_SECURE_PORT, m->m_flags));
-                               mci->mci_exitstat = i;
-                               mci->mci_errno = errno;
-                               if (i == EX_TEMPFAIL)
-                                       mci->mci_state = MCIS_TEMPFAIL;
-                               else if (i != EX_OK)
-                                       mci->mci_state = MCIS_ERROR;
-                               else
-                                       mci->mci_state = MCIS_OPENING;
-                       }
-                       else
+                       if (mci->mci_exitstat != EX_OK)
+                               continue;
+
+                       /* try the connection */
+                       setproctitle("%s %s: %s", e->e_id, mxhosts[1], "user open");
+                       message(Arpa_Info, "Connecting to %s (%s)...",
+                               mxhosts[j], m->m_name);
+                       i = makeconnection(mxhosts[j], port, mci,
+                               bitnset(M_SECURE_PORT, m->m_flags));
+                       mci->mci_exitstat = i;
+                       mci->mci_errno = errno;
+                       if (i == EX_OK)
                        {
                        {
-                               i = mci->mci_exitstat;
-                               errno = mci->mci_errno;
+                               mci->mci_state = MCIS_OPENING;
+                               mci_cache(mci);
+                               break;
                        }
                        }
-                       if (i == EX_OK)
-                               return mci;
+                       else if (tTd(11, 1))
+                               printf("openmailer: makeconnection => stat=%d, errno=%d\n",
+                                       i, errno);
+
 
                        /* enter status of this host */
                        setstat(i);
                }
 
                        /* enter status of this host */
                        setstat(i);
                }
-               return NULL;
-#else DAEMON
+#else /* no DAEMON */
                syserr("openmailer: no IPC");
                return NULL;
                syserr("openmailer: no IPC");
                return NULL;
-#endif DAEMON
+#endif /* DAEMON */
        }
        }
-
-       /* create a pipe to shove the mail through */
-       if (pipe(mpvect) < 0)
+       else
        {
        {
-               syserr("openmailer: pipe (to mailer)");
-               return NULL;
-       }
+               /* create a pipe to shove the mail through */
+               if (pipe(mpvect) < 0)
+               {
+                       syserr("openmailer: pipe (to mailer)");
+                       return NULL;
+               }
 
 
-#ifdef SMTP
-       /* if this mailer speaks smtp, create a return pipe */
-       if (clever && pipe(rpvect) < 0)
-       {
-               syserr("openmailer: pipe (from mailer)");
-               (void) close(mpvect[0]);
-               (void) close(mpvect[1]);
-               return NULL;
-       }
-#endif SMTP
+               /* if this mailer speaks smtp, create a return pipe */
+               if (clever && pipe(rpvect) < 0)
+               {
+                       syserr("openmailer: pipe (from mailer)");
+                       (void) close(mpvect[0]);
+                       (void) close(mpvect[1]);
+                       return NULL;
+               }
 
 
-       /*
-       **  Actually fork the mailer process.
-       **      DOFORK is clever about retrying.
-       **
-       **      Dispose of SIGCHLD signal catchers that may be laying
-       **      around so that endmail will get it.
-       */
+               /*
+               **  Actually fork the mailer process.
+               **      DOFORK is clever about retrying.
+               **
+               **      Dispose of SIGCHLD signal catchers that may be laying
+               **      around so that endmail will get it.
+               */
 
 
-       if (CurEnv->e_xfp != NULL)
-               (void) fflush(CurEnv->e_xfp);           /* for debugging */
-       (void) fflush(stdout);
+               if (e->e_xfp != NULL)
+                       (void) fflush(e->e_xfp);                /* for debugging */
+               (void) fflush(stdout);
 # ifdef SIGCHLD
 # ifdef SIGCHLD
-       (void) signal(SIGCHLD, SIG_DFL);
+               (void) signal(SIGCHLD, SIG_DFL);
 # endif SIGCHLD
 # endif SIGCHLD
-       DOFORK(FORK);
-       /* pid is set by DOFORK */
-       if (pid < 0)
-       {
-               /* failure */
-               syserr("openmailer: cannot fork");
-               (void) close(mpvect[0]);
-               (void) close(mpvect[1]);
-#ifdef SMTP
-               if (clever)
+               DOFORK(FORK);
+               /* pid is set by DOFORK */
+               if (pid < 0)
                {
                {
-                       (void) close(rpvect[0]);
-                       (void) close(rpvect[1]);
+                       /* failure */
+                       syserr("openmailer: cannot fork");
+                       (void) close(mpvect[0]);
+                       (void) close(mpvect[1]);
+                       if (clever)
+                       {
+                               (void) close(rpvect[0]);
+                               (void) close(rpvect[1]);
+                       }
+                       return NULL;
                }
                }
-#endif SMTP
-               return NULL;
-       }
-       else if (pid == 0)
-       {
-               int i;
-               extern int DtableSize;
+               else if (pid == 0)
+               {
+                       int i;
+                       extern int DtableSize;
 
 
-               /* child -- set up input & exec mailer */
-               /* make diagnostic output be standard output */
-               (void) signal(SIGINT, SIG_IGN);
-               (void) signal(SIGHUP, SIG_IGN);
-               (void) signal(SIGTERM, SIG_DFL);
+                       /* child -- set up input & exec mailer */
+                       /* make diagnostic output be standard output */
+                       (void) signal(SIGINT, SIG_IGN);
+                       (void) signal(SIGHUP, SIG_IGN);
+                       (void) signal(SIGTERM, SIG_DFL);
 
 
-               /* arrange to filter standard & diag output of command */
-               if (clever)
-               {
-                       (void) close(rpvect[0]);
-                       (void) close(1);
-                       (void) dup(rpvect[1]);
-                       (void) close(rpvect[1]);
-               }
-               else if (OpMode == MD_SMTP || HoldErrs)
-               {
-                       /* put mailer output in transcript */
-                       (void) close(1);
-                       (void) dup(fileno(CurEnv->e_xfp));
-               }
-               (void) close(2);
-               (void) dup(1);
+                       /* arrange to filter std & diag output of command */
+                       if (clever)
+                       {
+                               (void) close(rpvect[0]);
+                               (void) close(1);
+                               (void) dup(rpvect[1]);
+                               (void) close(rpvect[1]);
+                       }
+                       else if (OpMode == MD_SMTP || HoldErrs)
+                       {
+                               /* put mailer output in transcript */
+                               (void) close(1);
+                               (void) dup(fileno(e->e_xfp));
+                       }
+                       (void) close(2);
+                       (void) dup(1);
 
 
-               /* arrange to get standard input */
-               (void) close(mpvect[1]);
-               (void) close(0);
-               if (dup(mpvect[0]) < 0)
-               {
-                       syserr("Cannot dup to zero!");
-                       _exit(EX_OSERR);
-               }
-               (void) close(mpvect[0]);
-               if (!bitnset(M_RESTR, m->m_flags))
-               {
-                       if (ctladdr == NULL || ctladdr->q_uid == 0)
+                       /* arrange to get standard input */
+                       (void) close(mpvect[1]);
+                       (void) close(0);
+                       if (dup(mpvect[0]) < 0)
                        {
                        {
-                               (void) setgid(DefGid);
-                               (void) initgroups(DefUser, DefGid);
-                               (void) setuid(DefUid);
+                               syserr("Cannot dup to zero!");
+                               _exit(EX_OSERR);
                        }
                        }
-                       else
+                       (void) close(mpvect[0]);
+                       if (!bitnset(M_RESTR, m->m_flags))
                        {
                        {
-                               (void) setgid(ctladdr->q_gid);
-                               (void) initgroups(ctladdr->q_ruser?
-                                       ctladdr->q_ruser: ctladdr->q_user,
-                                       ctladdr->q_gid);
-                               (void) setuid(ctladdr->q_uid);
+                               if (ctladdr == NULL || ctladdr->q_uid == 0)
+                               {
+                                       (void) setgid(DefGid);
+                                       (void) initgroups(DefUser, DefGid);
+                                       (void) setuid(DefUid);
+                               }
+                               else
+                               {
+                                       (void) setgid(ctladdr->q_gid);
+                                       (void) initgroups(ctladdr->q_ruser?
+                                               ctladdr->q_ruser: ctladdr->q_user,
+                                               ctladdr->q_gid);
+                                       (void) setuid(ctladdr->q_uid);
+                               }
                        }
                        }
-               }
 
 
-               /* arrange for all the files to be closed */
-               for (i = 3; i < DtableSize; i++) {
-                       register int j;
-                       if ((j = fcntl(i, F_GETFD, 0)) != -1)
-                               (void)fcntl(i, F_SETFD, j|1);
-               }
+                       /* arrange for all the files to be closed */
+                       for (i = 3; i < DtableSize; i++)
+                       {
+                               register int j;
+                               if ((j = fcntl(i, F_GETFD, 0)) != -1)
+                                       (void)fcntl(i, F_SETFD, j|1);
+                       }
 
 
-               /* try to execute the mailer */
-               execve(m->m_mailer, pvp, UserEnviron);
-               syserr("Cannot exec %s", m->m_mailer);
-               if (m == LocalMailer)
-                       _exit(EX_TEMPFAIL);
-               switch (errno)
-               {
-                 case EIO:
-                 case EAGAIN:
-                 case ENOMEM:
+                       /* try to execute the mailer */
+                       execve(m->m_mailer, pvp, UserEnviron);
+                       syserr("Cannot exec %s", m->m_mailer);
+                       if (m == LocalMailer)
+                               _exit(EX_TEMPFAIL);
+                       switch (errno)
+                       {
+                         case EIO:
+                         case EAGAIN:
+                         case ENOMEM:
 # ifdef EPROCLIM
 # ifdef EPROCLIM
-                 case EPROCLIM:
+                         case EPROCLIM:
 # endif
 # endif
-                       _exit(EX_TEMPFAIL);
+                               _exit(EX_TEMPFAIL);
+                       }
+                       _exit(EX_UNAVAILABLE);
+               }
+
+               /*
+               **  Set up return value.
+               */
+
+               mci = (MCI *) xalloc(sizeof *mci);
+               mci->mci_mailer = m;
+               mci->mci_state = clever ? MCIS_OPENING : MCIS_OPEN;
+               (void) close(mpvect[0]);
+               mci->mci_out = fdopen(mpvect[1], "w");
+               if (clever)
+               {
+                       (void) close(rpvect[1]);
+                       mci->mci_in = fdopen(rpvect[0], "r");
+               }
+               else
+               {
+                       mci->mci_flags |= MCIF_TEMP;
+                       mci->mci_in = NULL;
                }
                }
-               _exit(EX_UNAVAILABLE);
        }
 
        /*
        }
 
        /*
-       **  Set up return value.
+       **  If we are in SMTP opening state, send initial protocol.
        */
 
        */
 
-       mci = (MCONINFO *) xalloc(sizeof *mci);
-       mci->mci_mailer = m;
-       (void) close(mpvect[0]);
-       mci->mci_out = fdopen(mpvect[1], "w");
-       if (clever)
+       if (clever && mci->mci_state != MCIS_CLOSED)
        {
        {
-               (void) close(rpvect[1]);
-               mci->mci_in = fdopen(rpvect[0], "r");
-       }
-       else
-       {
-               mci->mci_flags |= MCIF_TEMP;
-               mci->mci_in = NULL;
+               smtpinit(m, mci, e);
        }
 
        return mci;
        }
 
        return mci;
@@ -1082,7 +1087,7 @@ giveresponse(stat, m, e)
        */
 
        if (LogLevel > ((stat == 0 || stat == EX_TEMPFAIL) ? 3 : 2))
        */
 
        if (LogLevel > ((stat == 0 || stat == EX_TEMPFAIL) ? 3 : 2))
-               logdelivery(&statmsg[4]);
+               logdelivery(&statmsg[4], e);
 
        if (stat != EX_TEMPFAIL)
                setstat(stat);
 
        if (stat != EX_TEMPFAIL)
                setstat(stat);
@@ -1110,14 +1115,15 @@ giveresponse(stat, m, e)
 **             none
 */
 
 **             none
 */
 
-logdelivery(stat)
+logdelivery(stat, e)
        char *stat;
        char *stat;
+       register ENVELOPE *e;
 {
        extern char *pintvl();
 
 # ifdef LOG
 {
        extern char *pintvl();
 
 # ifdef LOG
-       syslog(LOG_INFO, "%s: to=%s, delay=%s, stat=%s", CurEnv->e_id,
-              CurEnv->e_to, pintvl(curtime() - CurEnv->e_ctime, TRUE), stat);
+       syslog(LOG_INFO, "%s: to=%s, delay=%s, stat=%s", e->e_id,
+              e->e_to, pintvl(curtime() - e->e_ctime, TRUE), stat);
 # endif LOG
 }
 \f/*
 # endif LOG
 }
 \f/*
@@ -1143,9 +1149,10 @@ logdelivery(stat)
 **             outputs some text to fp.
 */
 
 **             outputs some text to fp.
 */
 
-putfromline(fp, m)
+putfromline(fp, m, e)
        register FILE *fp;
        register MAILER *m;
        register FILE *fp;
        register MAILER *m;
+       ENVELOPE *e;
 {
        char *template = "\001l\n";
        char buf[MAXLINE];
 {
        char *template = "\001l\n";
        char buf[MAXLINE];
@@ -1160,7 +1167,7 @@ putfromline(fp, m)
                char *bang;
                char xbuf[MAXLINE];
 
                char *bang;
                char xbuf[MAXLINE];
 
-               expand("\001<", buf, &buf[sizeof buf - 1], CurEnv);
+               expand("\001<", buf, &buf[sizeof buf - 1], e);
                bang = index(buf, '!');
                if (bang == NULL)
                        syserr("No ! in UUCP! (%s)", buf);
                bang = index(buf, '!');
                if (bang == NULL)
                        syserr("No ! in UUCP! (%s)", buf);
@@ -1172,7 +1179,7 @@ putfromline(fp, m)
                }
        }
 # endif UGLYUUCP
                }
        }
 # endif UGLYUUCP
-       expand(template, buf, &buf[sizeof buf - 1], CurEnv);
+       expand(template, buf, &buf[sizeof buf - 1], e);
        putline(buf, fp, m);
 }
 \f/*
        putline(buf, fp, m);
 }
 \f/*
@@ -1265,13 +1272,13 @@ putbody(fp, m, e)
 **             none.
 */
 
 **             none.
 */
 
-mailfile(filename, ctladdr)
+mailfile(filename, ctladdr, e)
        char *filename;
        ADDRESS *ctladdr;
        char *filename;
        ADDRESS *ctladdr;
+       register ENVELOPE *e;
 {
        register FILE *f;
        register int pid;
 {
        register FILE *f;
        register int pid;
-       ENVELOPE *e = CurEnv;
        int mode;
 
        /*
        int mode;
 
        /*
@@ -1354,7 +1361,7 @@ mailfile(filename, ctladdr)
                        exit(EX_CANTCREAT);
                }
 
                        exit(EX_CANTCREAT);
                }
 
-               putfromline(f, ProgMailer);
+               putfromline(f, ProgMailer, e);
                (*CurEnv->e_puthdr)(f, ProgMailer, CurEnv);
                putline("\n", f, ProgMailer);
                (*CurEnv->e_putbody)(f, ProgMailer, CurEnv);
                (*CurEnv->e_puthdr)(f, ProgMailer, CurEnv);
                putline("\n", f, ProgMailer);
                (*CurEnv->e_putbody)(f, ProgMailer, CurEnv);
@@ -1532,7 +1539,7 @@ sendall(e, mode)
 # ifdef LOG
                        if (LogLevel > 5)
                                syslog(LOG_NOTICE, "%s: lost lock: %m",
 # ifdef LOG
                        if (LogLevel > 5)
                                syslog(LOG_NOTICE, "%s: lost lock: %m",
-                                       CurEnv->e_id);
+                                       e->e_id);
 # endif /* LOG */
                        exit(EX_OK);
                }
 # endif /* LOG */
                        exit(EX_OK);
                }
index 74f0626..e402abe 100644 (file)
@@ -13,13 +13,14 @@ char copyright[] =
 #endif /* not lint */
 
 #ifndef lint
 #endif /* not lint */
 
 #ifndef lint
-static char sccsid[] = "@(#)main.c     5.49 (Berkeley) %G%";
+static char sccsid[] = "@(#)main.c     5.50 (Berkeley) %G%";
 #endif /* not lint */
 
 #define        _DEFINE
 
 #include <sys/param.h>
 #include <sys/file.h>
 #endif /* not lint */
 
 #define        _DEFINE
 
 #include <sys/param.h>
 #include <sys/file.h>
+#include <sys/stat.h>
 #include <signal.h>
 #include <sgtty.h>
 #include "sendmail.h"
 #include <signal.h>
 #include <sgtty.h>
 #include "sendmail.h"
@@ -427,9 +428,19 @@ main(argc, argv, envp)
 
                  case 'q':     /* run queue files at intervals */
 # ifdef QUEUE
 
                  case 'q':     /* run queue files at intervals */
 # ifdef QUEUE
-                       if (getuid() != 0) {
-                               usrerr("Permission denied");
-                               exit (EX_USAGE);
+                       if (getuid() != 0)
+                       {
+                               struct stat stbuf;
+
+                               /* check to see if we own the queue directory */
+                               if (stat(QueueDir, &stbuf) < 0)
+                                       syserr("main: cannot stat %s", QueueDir);
+                               if (stbuf.st_uid != getuid())
+                               {
+                                       /* nope, really a botch */
+                                       usrerr("Permission denied");
+                                       exit (EX_NOPERM);
+                               }
                        }
                        (void) unsetenv("HOSTALIASES");
                        queuemode = TRUE;
                        }
                        (void) unsetenv("HOSTALIASES");
                        queuemode = TRUE;
@@ -824,6 +835,9 @@ finis()
        CurEnv->e_to = NULL;
        dropenvelope(CurEnv);
 
        CurEnv->e_to = NULL;
        dropenvelope(CurEnv);
 
+       /* flush any cached connections */
+       mci_flush();
+
        /* post statistics */
        poststats(StatFile);
 
        /* post statistics */
        poststats(StatFile);
 
index f53fc48..2c8d5b5 100644 (file)
@@ -7,12 +7,39 @@
  */
 
 #ifndef lint
  */
 
 #ifndef lint
-static char sccsid[] = "@(#)mci.c      5.1 (Berkeley) %G%";
+static char sccsid[] = "@(#)mci.c      5.2 (Berkeley) %G%";
 #endif /* not lint */
 
 #include "sendmail.h"
 
 /*
 #endif /* not lint */
 
 #include "sendmail.h"
 
 /*
+**  Mail Connection Information (MCI) Caching Module.
+**
+**     There are actually two separate things cached.  The first is
+**     the set of all open connections -- these are stored in a
+**     (small) list.  The second is stored in the symbol table; it
+**     has the overall status for all hosts, whether or not there
+**     is a connection open currently.
+**
+**     There should never be too many connections open (since this
+**     could flood the socket table), nor should a connection be
+**     allowed to sit idly for too long.
+**
+**     MaxMciCache is the maximum number of open connections that
+**     will be supported.
+**
+**     MciCacheTimeout is the time (in seconds) that a connection
+**     is permitted to survive without activity.
+**
+**     We actually try any cached connections by sending a NOOP
+**     before we use them; if the NOOP fails we close down the
+**     connection and reopen it.  Note that this means that a
+**     server SMTP that doesn't support NOOP will hose the
+**     algorithm -- but that doesn't seem too likely.
+*/
+
+MCI    **MciCache;             /* the open connection cache */
+\f/*
 **  MCI_CACHE -- enter a connection structure into the open connection cache
 **
 **     This may cause something else to be flushed.
 **  MCI_CACHE -- enter a connection structure into the open connection cache
 **
 **     This may cause something else to be flushed.
@@ -25,10 +52,10 @@ static char sccsid[] = "@(#)mci.c   5.1 (Berkeley) %G%";
 */
 
 mci_cache(mci)
 */
 
 mci_cache(mci)
-       register MCONINFO *mci;
+       register MCI *mci;
 {
 {
-       register MCONINFO **mcislot;
-       extern MCONINFO **mci_scan();
+       register MCI **mcislot;
+       extern MCI **mci_scan();
 
        if (MaxMciCache <= 0)
        {
 
        if (MaxMciCache <= 0)
        {
@@ -64,21 +91,19 @@ mci_cache(mci)
 **             The LRU (or empty) slot.
 */
 
 **             The LRU (or empty) slot.
 */
 
-MCONINFO       **MciCache;
-
-MCONINFO **
+MCI **
 mci_scan(savemci)
 mci_scan(savemci)
-       MCONINFO *savemci;
+       MCI *savemci;
 {
        time_t now;
 {
        time_t now;
-       register MCONINFO **bestmci;
-       register MCONINFO *mci;
+       register MCI **bestmci;
+       register MCI *mci;
        register int i;
 
        if (MciCache == NULL)
        {
                /* first call */
        register int i;
 
        if (MciCache == NULL)
        {
                /* first call */
-               MciCache = (MCONINFO **) xalloc(MaxMciCache * sizeof *MciCache);
+               MciCache = (MCI **) xalloc(MaxMciCache * sizeof *MciCache);
                return (&MciCache[0]);
        }
 
                return (&MciCache[0]);
        }
 
@@ -119,9 +144,9 @@ mci_scan(savemci)
 */
 
 mci_uncache(mcislot)
 */
 
 mci_uncache(mcislot)
-       register MCONINFO **mcislot;
+       register MCI **mcislot;
 {
 {
-       register MCONINFO *mci;
+       register MCI *mci;
        extern ENVELOPE *BlankEnvelope;
 
        mci = *mcislot;
        extern ENVELOPE *BlankEnvelope;
 
        mci = *mcislot;
@@ -152,10 +177,29 @@ mci_flush()
 **  MCI_GET -- get information about a particular host
 */
 
 **  MCI_GET -- get information about a particular host
 */
 
-MCONINFO *
+MCI *
 mci_get(host, m)
        char *host;
        MAILER *m;
 {
 mci_get(host, m)
        char *host;
        MAILER *m;
 {
-       return &(stab(host, ST_MCONINFO + m->m_mno, ST_ENTER))->s_mci;
+       register MCI *mci;
+
+       mci = &(stab(host, ST_MCI + m->m_mno, ST_ENTER))->s_mci;
+
+       if (tTd(42, 2))
+       {
+               printf("mci_get(%s %s): mci_state=%d, _flags=%x, _exitstat=%d, _errno=%d\n",
+                       host, m->m_name, mci->mci_state, mci->mci_flags,
+                       mci->mci_exitstat, mci->mci_errno);
+       }
+
+       /* try poking this to see if it is still usable */
+       switch (mci->mci_state)
+       {
+         case MCIS_OPEN:
+               smtpnoop(mci);
+               break;
+       }
+
+       return mci;
 }
 }
index 8d04b4b..e0559c1 100644 (file)
@@ -10,9 +10,9 @@
 
 #ifndef lint
 #ifdef QUEUE
 
 #ifndef lint
 #ifdef QUEUE
-static char sccsid[] = "@(#)queue.c    5.39 (Berkeley) %G% (with queueing)";
+static char sccsid[] = "@(#)queue.c    5.40 (Berkeley) %G% (with queueing)";
 #else
 #else
-static char sccsid[] = "@(#)queue.c    5.39 (Berkeley) %G% (without queueing)";
+static char sccsid[] = "@(#)queue.c    5.40 (Berkeley) %G% (without queueing)";
 #endif
 #endif /* not lint */
 
 #endif
 #endif /* not lint */
 
@@ -197,7 +197,7 @@ queueup(e, queueall, announce)
                                e->e_to = q->q_paddr;
                                message(Arpa_Info, "queued");
                                if (LogLevel > 4)
                                e->e_to = q->q_paddr;
                                message(Arpa_Info, "queued");
                                if (LogLevel > 4)
-                                       logdelivery("queued");
+                                       logdelivery("queued", e);
                                e->e_to = NULL;
                        }
                        if (tTd(40, 1))
                                e->e_to = NULL;
                        }
                        if (tTd(40, 1))
index 9de1607..de42dee 100644 (file)
@@ -7,7 +7,7 @@
  */
 
 #ifndef lint
  */
 
 #ifndef lint
-static char sccsid[] = "@(#)readcf.c   5.38 (Berkeley) %G%";
+static char sccsid[] = "@(#)readcf.c   5.39 (Berkeley) %G%";
 #endif /* not lint */
 
 # include "sendmail.h"
 #endif /* not lint */
 
 # include "sendmail.h"
@@ -877,6 +877,16 @@ setoption(opt, val, sticky)
                IgnrDot = atobool(val);
                break;
 
                IgnrDot = atobool(val);
                break;
 
+         case 'k':             /* connection cache size */
+               MaxMciCache = atoi(val);
+               if (MaxMciCache <= 0)
+                       MaxMciCache = 1;
+               break;
+
+         case 'K':             /* connection cache timeout */
+               MciCacheTimeout = convtime(val);
+               break;
+
          case 'L':             /* log level */
                LogLevel = atoi(val);
                break;
          case 'L':             /* log level */
                LogLevel = atoi(val);
                break;
@@ -933,7 +943,7 @@ setoption(opt, val, sticky)
 
          case 'T':             /* queue timeout */
                TimeOut = convtime(val);
 
          case 'T':             /* queue timeout */
                TimeOut = convtime(val);
-               /*FALLTHROUGH*/
+               break;
 
          case 't':             /* time zone name */
                TimeZoneSpec = newstr(val);
 
          case 't':             /* time zone name */
                TimeZoneSpec = newstr(val);
index 6bd0ce1..bab7797 100644 (file)
@@ -7,7 +7,7 @@
  */
 
 #ifndef lint
  */
 
 #ifndef lint
-static char sccsid[] = "@(#)savemail.c 5.16 (Berkeley) %G%";
+static char sccsid[] = "@(#)savemail.c 5.17 (Berkeley) %G%";
 #endif /* not lint */
 
 # include <sys/types.h>
 #endif /* not lint */
 
 # include <sys/types.h>
@@ -299,7 +299,7 @@ savemail(e)
                                break;
                        }
 
                                break;
                        }
 
-                       putfromline(fp, ProgMailer);
+                       putfromline(fp, ProgMailer, e);
                        (*e->e_puthdr)(fp, ProgMailer, e);
                        putline("\n", fp, ProgMailer);
                        (*e->e_putbody)(fp, ProgMailer, e);
                        (*e->e_puthdr)(fp, ProgMailer, e);
                        putline("\n", fp, ProgMailer);
                        (*e->e_putbody)(fp, ProgMailer, e);
index f0e448c..3ca5dd6 100644 (file)
@@ -5,7 +5,7 @@
  *
  * %sccs.include.redist.c%
  *
  *
  * %sccs.include.redist.c%
  *
- *     @(#)sendmail.h  5.33 (Berkeley) %G%
+ *     @(#)sendmail.h  5.34 (Berkeley) %G%
  */
 
 /*
  */
 
 /*
@@ -15,7 +15,7 @@
 # ifdef _DEFINE
 # define EXTERN
 # ifndef lint
 # ifdef _DEFINE
 # define EXTERN
 # ifndef lint
-static char SmailSccsId[] =    "@(#)sendmail.h 5.33            %G%";
+static char SmailSccsId[] =    "@(#)sendmail.h 5.34            %G%";
 # endif lint
 # else  _DEFINE
 # define EXTERN extern
 # endif lint
 # else  _DEFINE
 # define EXTERN extern
@@ -362,9 +362,9 @@ struct metamac
 **  hosts that we have looked up recently.
 */
 
 **  hosts that we have looked up recently.
 */
 
-# define MCONINFO      struct mailer_con_info
+# define MCI   struct mailer_con_info
 
 
-MCONINFO
+MCI
 {
        short           mci_flags;      /* flag bits, see below */
        short           mci_errno;      /* error number on last connection */
 {
        short           mci_flags;      /* flag bits, see below */
        short           mci_errno;      /* error number on last connection */
@@ -382,15 +382,16 @@ MCONINFO
 /* flag bits */
 #define MCIF_VALID     00001           /* this entry is valid */
 #define MCIF_TEMP      00002           /* don't cache this connection */
 /* flag bits */
 #define MCIF_VALID     00001           /* this entry is valid */
 #define MCIF_TEMP      00002           /* don't cache this connection */
+#define MCIF_CACHED    00004           /* currently in open cache */
 
 /* states */
 #define MCIS_CLOSED    0               /* no traffic on this connection */
 #define MCIS_OPENING   1               /* sending initial protocol */
 #define MCIS_OPEN      2               /* open, initial protocol sent */
 #define MCIS_ACTIVE    3               /* message being sent */
 
 /* states */
 #define MCIS_CLOSED    0               /* no traffic on this connection */
 #define MCIS_OPENING   1               /* sending initial protocol */
 #define MCIS_OPEN      2               /* open, initial protocol sent */
 #define MCIS_ACTIVE    3               /* message being sent */
-#define MCIS_SSD       4               /* service shutting down */
-#define MCIS_ERROR     5               /* error state */
-#define MCIS_TEMPFAIL  6               /* temporary failure */
+#define MCIS_QUITING   4               /* running quit protocol */
+#define MCIS_SSD       5               /* service shutting down */
+#define MCIS_ERROR     6               /* I/O error on connection */
 \f/*
 **  Mapping functions
 **
 \f/*
 **  Mapping functions
 **
@@ -444,7 +445,7 @@ struct symtab
                char            *sv_alias;      /* alias */
                MAPCLASS        sv_mapclass;    /* mapping function class */
                MAP             sv_map;         /* mapping function */
                char            *sv_alias;      /* alias */
                MAPCLASS        sv_mapclass;    /* mapping function class */
                MAP             sv_map;         /* mapping function */
-               MCONINFO        sv_mci;         /* mailer connection info */
+               MCI             sv_mci;         /* mailer connection info */
        }       s_value;
 };
 
        }       s_value;
 };
 
@@ -458,7 +459,7 @@ typedef struct symtab       STAB;
 # define ST_ALIAS      4       /* an alias */
 # define ST_MAPCLASS   5       /* mapping function class */
 # define ST_MAP                6       /* mapping function */
 # define ST_ALIAS      4       /* an alias */
 # define ST_MAPCLASS   5       /* mapping function class */
 # define ST_MAP                6       /* mapping function */
-# define ST_MCONINFO   16      /* mailer connection info (offset) */
+# define ST_MCI                16      /* mailer connection info (offset) */
 
 # define s_class       s_value.sv_class
 # define s_address     s_value.sv_addr
 
 # define s_class       s_value.sv_class
 # define s_address     s_value.sv_addr
@@ -611,9 +612,7 @@ EXTERN char SpaceSub;       /* substitution for <lwsp> */
 EXTERN int     WkClassFact;    /* multiplier for message class -> priority */
 EXTERN int     WkRecipFact;    /* multiplier for # of recipients -> priority */
 EXTERN int     WkTimeFact;     /* priority offset each time this job is run */
 EXTERN int     WkClassFact;    /* multiplier for message class -> priority */
 EXTERN int     WkRecipFact;    /* multiplier for # of recipients -> priority */
 EXTERN int     WkTimeFact;     /* priority offset each time this job is run */
-EXTERN int     Nmx;            /* number of MX RRs */
 EXTERN char    *PostMasterCopy;        /* address to get errs cc's */
 EXTERN char    *PostMasterCopy;        /* address to get errs cc's */
-EXTERN char    *MxHosts[MAXMXHOSTS+1]; /* for MX RRs */
 EXTERN char    *TrustedUsers[MAXTRUST+1];      /* list of trusted users */
 EXTERN char    *UserEnviron[MAXUSERENVIRON+1]; /* saved user environment */
 EXTERN int     CheckpointInterval;     /* queue file checkpoint interval */
 EXTERN char    *TrustedUsers[MAXTRUST+1];      /* list of trusted users */
 EXTERN char    *UserEnviron[MAXUSERENVIRON+1]; /* saved user environment */
 EXTERN int     CheckpointInterval;     /* queue file checkpoint interval */
@@ -623,6 +622,8 @@ EXTERN int  MaxHopCount;    /* number of hops until we give an error */
 EXTERN int     ConfigLevel;    /* config file level -- what does .cf expect? */
 EXTERN char    *TimeZoneSpec;  /* override time zone specification */
 EXTERN bool    MatchGecos;     /* look for user names in gecos field */
 EXTERN int     ConfigLevel;    /* config file level -- what does .cf expect? */
 EXTERN char    *TimeZoneSpec;  /* override time zone specification */
 EXTERN bool    MatchGecos;     /* look for user names in gecos field */
+EXTERN int     MaxMciCache;    /* maximum entries in MCI cache */
+EXTERN time_t  MciCacheTimeout;        /* maximum idle time on connections */
 \f/*
 **  Trace information
 */
 \f/*
 **  Trace information
 */
index 2526afa..296d234 100644 (file)
@@ -10,9 +10,9 @@
 
 #ifndef lint
 #ifdef SMTP
 
 #ifndef lint
 #ifdef SMTP
-static char sccsid[] = "@(#)usersmtp.c 5.21 (Berkeley) %G% (with SMTP)";
+static char sccsid[] = "@(#)usersmtp.c 5.22 (Berkeley) %G% (with SMTP)";
 #else
 #else
-static char sccsid[] = "@(#)usersmtp.c 5.21 (Berkeley) %G% (without SMTP)";
+static char sccsid[] = "@(#)usersmtp.c 5.22 (Berkeley) %G% (without SMTP)";
 #endif
 #endif /* not lint */
 
 #endif
 #endif /* not lint */
 
@@ -46,8 +46,7 @@ int   SmtpPid;                        /* pid of mailer */
 **                     the mailer.
 **
 **     Returns:
 **                     the mailer.
 **
 **     Returns:
-**             appropriate exit status -- EX_OK on success.
-**             If not EX_OK, it should close the connection.
+**             none.
 **
 **     Side Effects:
 **             creates connection and sends initial protocol.
 **
 **     Side Effects:
 **             creates connection and sends initial protocol.
@@ -55,63 +54,48 @@ int SmtpPid;                        /* pid of mailer */
 
 jmp_buf        CtxGreeting;
 
 
 jmp_buf        CtxGreeting;
 
-MCONINFO *
-smtpinit(m, pvp, e)
+smtpinit(m, mci, e)
        struct mailer *m;
        struct mailer *m;
-       char **pvp;
+       register MCI *mci;
        ENVELOPE *e;
 {
        register int r;
        EVENT *gte;
        ENVELOPE *e;
 {
        register int r;
        EVENT *gte;
-       MCONINFO *mci;
        static int greettimeout();
        extern STAB *stab();
        static int greettimeout();
        extern STAB *stab();
-       extern MCONINFO *openmailer();
+       extern MCI *openmailer();
 
        /*
        **  Open the connection to the mailer.
        */
 
        SmtpError[0] = '\0';
 
        /*
        **  Open the connection to the mailer.
        */
 
        SmtpError[0] = '\0';
-       setproctitle("%s %s: %s", e->e_id, pvp[1], "user open");
-       mci = openmailer(m, pvp, (ADDRESS *) NULL, TRUE);
-       if (mci == NULL)
-               return NULL;
-       if (mci->mci_state != MCIS_OPENING && mci->mci_state != MCIS_CLOSED)
-               return mci;
-       mci->mci_phase = "user open";
-       mci->mci_state = MCIS_OPENING;
-       if (mci->mci_pid < 0)
+       switch (mci->mci_state)
        {
        {
-               if (tTd(18, 1))
-                       printf("smtpinit: cannot open %s: stat %d errno %d\n",
-                          pvp[0], ExitStat, errno);
-               if (e->e_xfp != NULL)
-               {
-                       register char *p;
-                       extern char *errstring();
-                       extern char *statstring();
+         case MCIS_ACTIVE:
+               /* need to clear old information */
+               smtprset(m, mci, e);
+               mci->mci_state = MCIS_OPEN;
 
 
-                       if (errno == 0)
-                       {
-                               p = statstring(ExitStat);
-                               fprintf(e->e_xfp,
-                                       "%.3s %s.%s... %s\n",
-                                       p, pvp[1], m->m_name, p);
-                       }
-                       else
-                       {
-                               r = errno;
-                               fprintf(e->e_xfp,
-                                       "421 %s.%s... Deferred: %s\n",
-                                       pvp[1], m->m_name, errstring(errno));
-                               errno = r;
-                       }
-               }
-               mci->mci_exitstat = ExitStat;
-               return mci;
+         case MCIS_OPEN:
+               return;
+
+         case MCIS_ERROR:
+         case MCIS_SSD:
+               /* shouldn't happen */
+               smtpquit(m, mci, e);
+
+         case MCIS_CLOSED:
+               syserr("smtpinit: state CLOSED");
+               return;
+
+         case MCIS_OPENING:
+               break;
        }
 
        }
 
+       mci->mci_phase = "user open";
+       mci->mci_state = MCIS_OPENING;
+
        /*
        **  Get the greeting message.
        **      This should appear spontaneously.  Give it five minutes to
        /*
        **  Get the greeting message.
        **      This should appear spontaneously.  Give it five minutes to
@@ -156,36 +140,28 @@ smtpinit(m, pvp, e)
                r = reply(m, mci, e);
                if (r < 0)
                        goto tempfail2;
                r = reply(m, mci, e);
                if (r < 0)
                        goto tempfail2;
-
-               /* tell it we will be sending one transaction only */
-               smtpmessage("ONEX", m, mci);
-               r = reply(m, mci, e);
-               if (r < 0)
-                       goto tempfail2;
        }
 
        mci->mci_state = MCIS_OPEN;
        }
 
        mci->mci_state = MCIS_OPEN;
-       return mci;
+       return;
 
   tempfail1:
   tempfail2:
        mci->mci_exitstat = EX_TEMPFAIL;
        mci->mci_errno = errno;
        smtpquit(m, mci, e);
 
   tempfail1:
   tempfail2:
        mci->mci_exitstat = EX_TEMPFAIL;
        mci->mci_errno = errno;
        smtpquit(m, mci, e);
-       mci->mci_state = MCIS_TEMPFAIL;
-       return mci;
+       return;
 
   unavailable:
        mci->mci_exitstat = EX_UNAVAILABLE;
        mci->mci_errno = errno;
        smtpquit(m, mci, e);
 
   unavailable:
        mci->mci_exitstat = EX_UNAVAILABLE;
        mci->mci_errno = errno;
        smtpquit(m, mci, e);
-       mci->mci_state = MCIS_ERROR;
-       return mci;
+       return;
 }
 
 smtpmailfrom(m, mci, e)
        struct mailer *m;
 }
 
 smtpmailfrom(m, mci, e)
        struct mailer *m;
-       MCONINFO *mci;
+       MCI *mci;
        ENVELOPE *e;
 {
        int r;
        ENVELOPE *e;
 {
        int r;
@@ -225,7 +201,6 @@ smtpmailfrom(m, mci, e)
                mci->mci_exitstat = EX_TEMPFAIL;
                mci->mci_errno = errno;
                smtpquit(m, mci, e);
                mci->mci_exitstat = EX_TEMPFAIL;
                mci->mci_errno = errno;
                smtpquit(m, mci, e);
-               mci->mci_state = MCIS_TEMPFAIL;
                return EX_TEMPFAIL;
        }
        else if (r == 250)
                return EX_TEMPFAIL;
        }
        else if (r == 250)
@@ -238,14 +213,12 @@ smtpmailfrom(m, mci, e)
                /* signal service unavailable */
                mci->mci_exitstat = EX_UNAVAILABLE;
                smtpquit(m, mci, e);
                /* signal service unavailable */
                mci->mci_exitstat = EX_UNAVAILABLE;
                smtpquit(m, mci, e);
-               mci->mci_state = MCIS_ERROR;
                return EX_UNAVAILABLE;
        }
 
        /* protocol error -- close up */
        smtpquit(m, mci, e);
        mci->mci_exitstat = EX_PROTOCOL;
                return EX_UNAVAILABLE;
        }
 
        /* protocol error -- close up */
        smtpquit(m, mci, e);
        mci->mci_exitstat = EX_PROTOCOL;
-       mci->mci_state = MCIS_ERROR;
        return EX_PROTOCOL;
 }
 
        return EX_PROTOCOL;
 }
 
@@ -273,7 +246,7 @@ greettimeout()
 smtprcpt(to, m, mci, e)
        ADDRESS *to;
        register MAILER *m;
 smtprcpt(to, m, mci, e)
        ADDRESS *to;
        register MAILER *m;
-       MCONINFO *mci;
+       MCI *mci;
        ENVELOPE *e;
 {
        register int r;
        ENVELOPE *e;
 {
        register int r;
@@ -310,7 +283,7 @@ smtprcpt(to, m, mci, e)
 
 smtpdata(m, mci, e)
        struct mailer *m;
 
 smtpdata(m, mci, e)
        struct mailer *m;
-       register MCONINFO *mci;
+       register MCI *mci;
        register ENVELOPE *e;
 {
        register int r;
        register ENVELOPE *e;
 {
        register int r;
@@ -375,16 +348,12 @@ smtpdata(m, mci, e)
 
 smtpquit(m, mci, e)
        register MAILER *m;
 
 smtpquit(m, mci, e)
        register MAILER *m;
-       register MCONINFO *mci;
+       register MCI *mci;
        ENVELOPE *e;
 {
        int i;
 
        ENVELOPE *e;
 {
        int i;
 
-       /* if the connection is already closed, don't bother */
-       if (mci->mci_state == MCIS_CLOSED)
-               return;
-
-       /* send the quit message if not a forced quit */
+       /* send the quit message if we haven't gotten I/O error */
        if (mci->mci_state != MCIS_ERROR)
        {
                smtpmessage("QUIT", m, mci);
        if (mci->mci_state != MCIS_ERROR)
        {
                smtpmessage("QUIT", m, mci);
@@ -399,6 +368,44 @@ smtpquit(m, mci, e)
                syserr("smtpquit %s: stat %d", m->m_argv[0], i);
 }
 \f/*
                syserr("smtpquit %s: stat %d", m->m_argv[0], i);
 }
 \f/*
+**  SMTPRSET -- send a RSET (reset) command
+*/
+
+smtprset(m, mci, e)
+       register MAILER *m;
+       register MCI *mci;
+       ENVELOPE *e;
+{
+       int r;
+
+       smtpmessage("RSET", m, mci);
+       r = reply(m, mci, e);
+       if (r < 0 || REPLYTYPE(r) == 4)
+               return EX_TEMPFAIL;
+       else if (REPLYTYPE(r) == 2)
+               return EX_OK;
+       else
+               return EX_PROTOCOL;
+}
+\f/*
+**  SMTPNOOP -- send a NOOP (no operation) command to check the connection state
+*/
+
+smtpnoop(mci)
+       register MCI *mci;
+{
+       int r;
+       MAILER *m = mci->mci_mailer;
+       extern ENVELOPE BlankEnvelope;
+       ENVELOPE *e = &BlankEnvelope;
+
+       smtpmessage("NOOP", m, mci);
+       r = reply(m, mci, e);
+       if (REPLYTYPE(r) != 2)
+               smtpquit(m, mci, e);
+       return r;
+}
+\f/*
 **  REPLY -- read arpanet reply
 **
 **     Parameters:
 **  REPLY -- read arpanet reply
 **
 **     Parameters:
@@ -413,7 +420,7 @@ smtpquit(m, mci, e)
 
 reply(m, mci, e)
        MAILER *m;
 
 reply(m, mci, e)
        MAILER *m;
-       MCONINFO *mci;
+       MCI *mci;
        ENVELOPE *e;
 {
        (void) fflush(mci->mci_out);
        ENVELOPE *e;
 {
        (void) fflush(mci->mci_out);
@@ -463,7 +470,7 @@ reply(m, mci, e)
 # ifdef LOG
                        syslog(LOG_INFO, "%s", &MsgBuf[4]);
 # endif LOG
 # ifdef LOG
                        syslog(LOG_INFO, "%s", &MsgBuf[4]);
 # endif LOG
-                       mci->mci_state = MCIS_CLOSED;
+                       mci->mci_state = MCIS_ERROR;
                        smtpquit(m, mci, e);
                        return (-1);
                }
                        smtpquit(m, mci, e);
                        return (-1);
                }
@@ -529,14 +536,14 @@ reply(m, mci, e)
 smtpmessage(f, m, mci, a, b, c)
        char *f;
        MAILER *m;
 smtpmessage(f, m, mci, a, b, c)
        char *f;
        MAILER *m;
-       MCONINFO *mci;
+       MCI *mci;
 {
        (void) sprintf(SmtpMsgBuffer, f, a, b, c);
        if (tTd(18, 1) || (Verbose && !HoldErrs))
                nmessage(Arpa_Info, ">>> %s", SmtpMsgBuffer);
        if (mci->mci_out != NULL)
                fprintf(mci->mci_out, "%s%s", SmtpMsgBuffer,
 {
        (void) sprintf(SmtpMsgBuffer, f, a, b, c);
        if (tTd(18, 1) || (Verbose && !HoldErrs))
                nmessage(Arpa_Info, ">>> %s", SmtpMsgBuffer);
        if (mci->mci_out != NULL)
                fprintf(mci->mci_out, "%s%s", SmtpMsgBuffer,
-                       m == 0 ? "\r\n" : m->m_eol);
+                       m == NULL ? "\r\n" : m->m_eol);
 }
 
 # endif SMTP
 }
 
 # endif SMTP
index 81af4db..e896b14 100644 (file)
@@ -7,7 +7,7 @@
  */
 
 #ifndef lint
  */
 
 #ifndef lint
-static char sccsid[] = "@(#)version.c  5.100 (Berkeley) %G%";
+static char sccsid[] = "@(#)version.c  5.101 (Berkeley) %G%";
 #endif /* not lint */
 
 #endif /* not lint */
 
-char   Version[] = "5.100";
+char   Version[] = "5.101";