install correct aliases file
[unix-history] / usr / src / usr.sbin / sendmail / src / deliver.c
index 0d66949..82a8d86 100644 (file)
@@ -1,9 +1,35 @@
-# include <signal.h>
-# include <errno.h>
-# include "sendmail.h"
-# include <sys/stat.h>
-
-SCCSID(@(#)deliver.c   4.9             %G%);
+/*
+ * Copyright (c) 1983 Eric P. Allman
+ * Copyright (c) 1988 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that the above copyright notice and this paragraph are
+ * duplicated in all such forms and that any documentation,
+ * advertising materials, and other materials related to such
+ * distribution and use acknowledge that the software was developed
+ * by the University of California, Berkeley.  The name of the
+ * University may not be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#ifndef lint
+static char sccsid[] = "@(#)deliver.c  5.25 (Berkeley) %G%";
+#endif /* not lint */
+
+#include <sendmail.h>
+#include <sys/signal.h>
+#include <sys/stat.h>
+#include <netdb.h>
+#include <fcntl.h>
+#include <errno.h>
+#ifdef NAMED_BIND
+#include <arpa/nameser.h>
+#include <resolv.h>
+#endif
 
 /*
 **  DELIVER -- Deliver a message to a list of addresses.
 
 /*
 **  DELIVER -- Deliver a message to a list of addresses.
@@ -41,7 +67,7 @@ deliver(e, firstto)
        register ADDRESS *to = firstto;
        bool clever = FALSE;            /* running user smtp to this mailer */
        ADDRESS *tochain = NULL;        /* chain of users in this mailer call */
        register ADDRESS *to = firstto;
        bool clever = FALSE;            /* running user smtp to this mailer */
        ADDRESS *tochain = NULL;        /* chain of users in this mailer call */
-       register int rcode;             /* response code */
+       int rcode;              /* response code */
        char *pv[MAXPV+1];
        char tobuf[MAXLINE-50];         /* text line of to people */
        char buf[MAXNAME];
        char *pv[MAXPV+1];
        char tobuf[MAXLINE-50];         /* text line of to people */
        char buf[MAXNAME];
@@ -54,6 +80,14 @@ deliver(e, firstto)
        if (!ForceMail && bitset(QDONTSEND|QPSEUDO, to->q_flags))
                return (0);
 
        if (!ForceMail && bitset(QDONTSEND|QPSEUDO, to->q_flags))
                return (0);
 
+#ifdef NAMED_BIND
+       /* unless interactive, try twice, over a minute */
+       if (OpMode == MD_DAEMON || OpMode == MD_SMTP) {
+               _res.retrans = 30;
+               _res.retry = 2;
+       }
+#endif NAMED_BIND
+
        m = to->q_mailer;
        host = to->q_host;
 
        m = to->q_mailer;
        host = to->q_host;
 
@@ -215,8 +249,8 @@ deliver(e, firstto)
 
                if (m->m_maxsize != 0 && e->e_msgsize > m->m_maxsize)
                {
 
                if (m->m_maxsize != 0 && e->e_msgsize > m->m_maxsize)
                {
-                       usrerr("Message is too large; %ld bytes max", m->m_maxsize);
                        NoReturn = TRUE;
                        NoReturn = TRUE;
+                       usrerr("Message is too large; %ld bytes max", m->m_maxsize);
                        giveresponse(EX_UNAVAILABLE, m, e);
                        continue;
                }
                        giveresponse(EX_UNAVAILABLE, m, e);
                        continue;
                }
@@ -341,54 +375,71 @@ deliver(e, firstto)
        **      If we are running SMTP, we just need to clean up.
        */
 
        **      If we are running SMTP, we just need to clean up.
        */
 
-       message(Arpa_Info, "Connecting to %s.%s...", host, m->m_name);
-
        if (ctladdr == NULL)
                ctladdr = &e->e_from;
        if (ctladdr == NULL)
                ctladdr = &e->e_from;
-# ifdef SMTP
+#ifdef NAMED_BIND
+       _res.options &= ~(RES_DEFNAMES | RES_DNSRCH);           /* XXX */
+#endif
+#ifdef SMTP
        if (clever)
        {
        if (clever)
        {
-               /* send the initial SMTP protocol */
-               rcode = smtpinit(m, pv);
-
-               if (rcode == EX_OK)
+               expand("\001w", buf, &buf[sizeof(buf) - 1], e);
+               rcode = EX_OK;
+#ifdef NAMED_BIND
+               if (host[0] != '[')
                {
                {
-                       /* send the recipient list */
-                       tobuf[0] = '\0';
-                       for (to = tochain; to != NULL; to = to->q_tchain)
-                       {
-                               int i;
-
-                               e->e_to = to->q_paddr;
-                               i = smtprcpt(to, m);
-                               if (i != EX_OK)
-                               {
-                                       markfailure(e, to, i);
-                                       giveresponse(i, m, e);
+                       Nmx = getmxrr(host, MxHosts, buf, &rcode);
+               }
+               else
+#endif
+               {
+                       Nmx = 1;
+                       MxHosts[0] = host;
+               }
+               if (Nmx >= 0)
+               {
+                       message(Arpa_Info, "Connecting to %s (%s)...",
+                           MxHosts[0], m->m_name);
+                       if ((rcode = smtpinit(m, pv)) == EX_OK) {
+                               register char *t = tobuf;
+                               register int i;
+
+                               /* send the recipient list */
+                               tobuf[0] = '\0';
+                               for (to = tochain; to; to = to->q_tchain) {
+                                       e->e_to = to->q_paddr;
+                                       if ((i = smtprcpt(to, m)) != EX_OK) {
+                                               markfailure(e, to, i);
+                                               giveresponse(i, m, e);
+                                       }
+                                       else {
+                                               *t++ = ',';
+                                               for (p = to->q_paddr; *p; *t++ = *p++);
+                                       }
                                }
                                }
-                               else
-                               {
-                                       strcat(tobuf, ",");
-                                       strcat(tobuf, to->q_paddr);
+
+                               /* now send the data */
+                               if (tobuf[0] == '\0')
+                                       e->e_to = NULL;
+                               else {
+                                       e->e_to = tobuf + 1;
+                                       rcode = smtpdata(m, e);
                                }
                                }
-                       }
 
 
-                       /* now send the data */
-                       if (tobuf[0] == '\0')
-                               e->e_to = NULL;
-                       else
-                       {
-                               e->e_to = tobuf + 1;
-                               rcode = smtpdata(m, e);
+                               /* now close the connection */
+                               smtpquit(m);
                        }
                        }
-
-                       /* now close the connection */
-                       smtpquit(m);
                }
        }
        else
                }
        }
        else
-# endif SMTP
+#endif /* SMTP */
+       {
+               message(Arpa_Info, "Connecting to %s (%s)...", host, m->m_name);
                rcode = sendoff(e, m, pv, ctladdr);
                rcode = sendoff(e, m, pv, ctladdr);
+       }
+#ifdef NAMED_BIND
+       _res.options |= RES_DEFNAMES | RES_DNSRCH;      /* XXX */
+#endif
 
        /*
        **  Do final status disposal.
 
        /*
        **  Do final status disposal.
@@ -400,10 +451,8 @@ deliver(e, firstto)
        if (tobuf[0] != '\0')
                giveresponse(rcode, m, e);
        if (rcode != EX_OK)
        if (tobuf[0] != '\0')
                giveresponse(rcode, m, e);
        if (rcode != EX_OK)
-       {
                for (to = tochain; to != NULL; to = to->q_tchain)
                        markfailure(e, to, rcode);
                for (to = tochain; to != NULL; to = to->q_tchain)
                        markfailure(e, to, rcode);
-       }
 
        errno = 0;
        define('g', (char *) NULL, e);
 
        errno = 0;
        define('g', (char *) NULL, e);
@@ -488,12 +537,13 @@ markfailure(e, q, rcode)
 {\
        register int i;\
 \
 {\
        register int i;\
 \
-       for (i = NFORKTRIES; i-- > 0; )\
+       for (i = NFORKTRIES; --i >= 0; )\
        {\
                pid = fORKfN();\
                if (pid >= 0)\
                        break;\
        {\
                pid = fORKfN();\
                if (pid >= 0)\
                        break;\
-               sleep(NFORKTRIES - i);\
+               if (i > 0)\
+                       sleep((unsigned) NFORKTRIES - i);\
        }\
 }
 \f/*
        }\
 }
 \f/*
@@ -534,7 +584,7 @@ dofork()
 **     Side Effects:
 **             none.
 */
 **     Side Effects:
 **             none.
 */
-
+static
 sendoff(e, m, pvp, ctladdr)
        register ENVELOPE *e;
        MAILER *m;
 sendoff(e, m, pvp, ctladdr)
        register ENVELOPE *e;
        MAILER *m;
@@ -615,9 +665,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 */
@@ -668,6 +718,8 @@ openmailer(m, pvp, ctladdr, clever, pmfile, prfile)
 # endif DEBUG
        errno = 0;
 
 # endif DEBUG
        errno = 0;
 
+       CurHostName = m->m_mailer;
+
        /*
        **  Deal with the special case of mail handled through an IPC
        **  connection.
        /*
        **  Deal with the special case of mail handled through an IPC
        **  connection.
@@ -689,24 +741,58 @@ 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
 #ifdef DAEMON
-               register int i;
+               register int i, j;
                register u_short port;
 
                register u_short port;
 
+               CurHostName = pvp[1];
                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;
-               i = makeconnection(pvp[1], port, pmfile, prfile);
-               if (i != EX_OK)
+               for (j = 0; j < Nmx; j++)
                {
                {
-                       ExitStat = i;
-                       return (-1);
+                       CurHostName = MxHosts[j];
+#ifdef HOSTINFO
+               /* see if we have already determined that this host is fried */
+                       st = stab(MxHosts[j], ST_HOST, ST_FIND);
+                       if (st == NULL || st->s_host.ho_exitstat == EX_OK) {
+                               if (j > 1)
+                                       message(Arpa_Info,
+                                           "Connecting to %s (%s)...",
+                                           MxHosts[j], m->m_name);
+                               i = makeconnection(MxHosts[j], port, pmfile, prfile);
+                       }
+                       else
+                       {
+                               i = st->s_host.ho_exitstat;
+                               errno = st->s_host.ho_errno;
+                       }
+#else HOSTINFO
+                       i = makeconnection(MxHosts[j], port, pmfile, prfile);
+#endif HOSTINFO
+                       if (i != EX_OK)
+                       {
+#ifdef HOSTINFO
+                               /* enter status of this host */
+                               if (st == NULL)
+                                       st = stab(MxHosts[j], ST_HOST, ST_ENTER);
+                               st->s_host.ho_exitstat = i;
+                               st->s_host.ho_errno = errno;
+#endif HOSTINFO
+                               ExitStat = i;
+                               continue;
+                       }
+                       else
+                               return (0);
                }
                }
-               else
-                       return (0);
+               return (-1);
 #else DAEMON
                syserr("openmailer: no IPC");
                return (-1);
 #else DAEMON
                syserr("openmailer: no IPC");
                return (-1);
@@ -734,11 +820,17 @@ openmailer(m, pvp, ctladdr, clever, pmfile, prfile)
        /*
        **  Actually fork the mailer process.
        **      DOFORK is clever about retrying.
        /*
        **  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 (CurEnv->e_xfp != NULL)
                (void) fflush(CurEnv->e_xfp);           /* for debugging */
        (void) fflush(stdout);
+# ifdef SIGCHLD
+       (void) signal(SIGCHLD, SIG_DFL);
+# endif SIGCHLD
        DOFORK(XFORK);
        /* pid is set by DOFORK */
        if (pid < 0)
        DOFORK(XFORK);
        /* pid is set by DOFORK */
        if (pid < 0)
@@ -759,6 +851,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 */
@@ -807,23 +900,17 @@ 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++)
-#ifdef FIOCLEX
-                       (void) ioctl(i, FIOCLEX, 0);
-#else FIOCLEX
-                       (void) close(i);
-#endif FIOCLEX
+               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 */
 
                /* try to execute the mailer */
-               execv(m->m_mailer, pvp);
-
-#ifdef FIOCLEX
+               execve(m->m_mailer, pvp, UserEnviron);
                syserr("Cannot exec %s", m->m_mailer);
                syserr("Cannot exec %s", m->m_mailer);
-#else 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);
@@ -871,7 +958,7 @@ giveresponse(stat, m, e)
        register char *statmsg;
        extern char *SysExMsg[];
        register int i;
        register char *statmsg;
        extern char *SysExMsg[];
        register int i;
-       extern int N_SysEx;
+       extern int N_SysEx, h_errno;
        char buf[MAXLINE];
 
 #ifdef lint
        char buf[MAXLINE];
 
 #ifdef lint
@@ -895,17 +982,42 @@ giveresponse(stat, m, e)
        else if (stat == EX_TEMPFAIL)
        {
                (void) strcpy(buf, SysExMsg[i]);
        else if (stat == EX_TEMPFAIL)
        {
                (void) strcpy(buf, SysExMsg[i]);
-               if (errno != 0)
+               if (h_errno == TRY_AGAIN)
                {
                        extern char *errstring();
 
                {
                        extern char *errstring();
 
+                       statmsg = errstring(h_errno+MAX_ERRNO);
+               }
+               else
+               {
+                       if (errno != 0)
+                       {
+                               extern char *errstring();
+
+                               statmsg = errstring(errno);
+                       }
+                       else
+                       {
+#ifdef SMTP
+                               extern char SmtpError[];
+
+                               statmsg = SmtpError;
+#else SMTP
+                               statmsg = NULL;
+#endif SMTP
+                       }
+               }
+               if (statmsg != NULL && statmsg[0] != '\0')
+               {
                        (void) strcat(buf, ": ");
                        (void) strcat(buf, ": ");
-                       (void) strcat(buf, errstring(errno));
+                       (void) strcat(buf, statmsg);
                }
                statmsg = buf;
        }
        else
                }
                statmsg = buf;
        }
        else
+       {
                statmsg = SysExMsg[i];
                statmsg = SysExMsg[i];
+       }
 
        /*
        **  Print the message as appropriate
 
        /*
        **  Print the message as appropriate
@@ -938,6 +1050,7 @@ giveresponse(stat, m, e)
                e->e_message = newstr(&statmsg[4]);
        }
        errno = 0;
                e->e_message = newstr(&statmsg[4]);
        }
        errno = 0;
+       h_errno = 0;
 }
 \f/*
 **  LOGDELIVERY -- log the delivery in the system log
 }
 \f/*
 **  LOGDELIVERY -- log the delivery in the system log
@@ -1061,7 +1174,7 @@ putbody(fp, m, e)
                {
                        if (buf[0] == 'F' && bitnset(M_ESCFROM, m->m_flags) &&
                            strncmp(buf, "From", 4) == 0)
                {
                        if (buf[0] == 'F' && bitnset(M_ESCFROM, m->m_flags) &&
                            strncmp(buf, "From", 4) == 0)
-                               putc('>', fp);
+                               (void) putc('>', fp);
                        putline(buf, fp, m);
                }
 
                        putline(buf, fp, m);
                }
 
@@ -1131,7 +1244,7 @@ mailfile(filename, ctladdr)
                (void) signal(SIGINT, SIG_DFL);
                (void) signal(SIGHUP, SIG_DFL);
                (void) signal(SIGTERM, SIG_DFL);
                (void) signal(SIGINT, SIG_DFL);
                (void) signal(SIGHUP, SIG_DFL);
                (void) signal(SIGTERM, SIG_DFL);
-               umask(OldUmask);
+               (void) umask(OldUmask);
                if (stat(filename, &stb) < 0)
                {
                        errno = 0;
                if (stat(filename, &stb) < 0)
                {
                        errno = 0;
@@ -1213,9 +1326,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;