allow error mailer to take DSN status code
authorEric Allman <eric@ucbvax.Berkeley.EDU>
Sun, 23 Apr 1995 02:07:06 +0000 (18:07 -0800)
committerEric Allman <eric@ucbvax.Berkeley.EDU>
Sun, 23 Apr 1995 02:07:06 +0000 (18:07 -0800)
SCCS-vsn: usr.sbin/sendmail/src/sysexits.c 8.3
SCCS-vsn: usr.sbin/sendmail/src/parseaddr.c 8.66

usr/src/usr.sbin/sendmail/src/parseaddr.c
usr/src/usr.sbin/sendmail/src/sysexits.c

index 8fd2b5a..f8943db 100644 (file)
@@ -7,7 +7,7 @@
  */
 
 #ifndef lint
  */
 
 #ifndef lint
-static char sccsid[] = "@(#)parseaddr.c        8.65 (Berkeley) %G%";
+static char sccsid[] = "@(#)parseaddr.c        8.66 (Berkeley) %G%";
 #endif /* not lint */
 
 #include "sendmail.h"
 #endif /* not lint */
 
 #include "sendmail.h"
@@ -1705,11 +1705,14 @@ buildaddr(tv, a, flags, e)
 {
        struct mailer **mp;
        register struct mailer *m;
 {
        struct mailer **mp;
        register struct mailer *m;
+       register char *p;
        char *bp;
        char *bp;
-       int spaceleft;
+       char *mname;
+       char **hostp;
+       char hbuf[MAXNAME + 1];
        static MAILER errormailer;
        static char *errorargv[] = { "ERROR", NULL };
        static MAILER errormailer;
        static char *errorargv[] = { "ERROR", NULL };
-       static char buf[MAXNAME + 1];
+       static char ubuf[MAXNAME + 1];
 
        if (tTd(24, 5))
        {
 
        if (tTd(24, 5))
        {
@@ -1740,25 +1743,47 @@ badaddr:
                }
                return a;
        }
                }
                return a;
        }
-       tv++;
-       if (strcasecmp(*tv, "error") == 0)
+       mname = *++tv;
+
+       /* extract host and user portions */
+       if ((**++tv & 0377) == CANONHOST)
+               hostp = ++tv;
+       else
+               hostp = NULL;
+       while (*tv != NULL && (**tv & 0377) != CANONUSER)
+               tv++;
+       if (*tv == NULL)
+       {
+               syserr("554 buildaddr: no user");
+               goto badaddr;
+       }
+       if (hostp != NULL)
+               cataddr(hostp, tv - 1, hbuf, sizeof hbuf, '\0');
+       cataddr(++tv, NULL, ubuf, sizeof ubuf, '\0');
+
+       /* save away the host name */
+       if (strcasecmp(mname, "error") == 0)
        {
        {
-               if ((**++tv & 0377) == CANONHOST)
+               if (hostp != NULL)
                {
                        register struct errcodes *ep;
 
                {
                        register struct errcodes *ep;
 
-                       if (isascii(**++tv) && isdigit(**tv))
+                       if (strchr(hbuf, '.') != NULL)
+                       {
+                               a->q_status = newstr(hbuf);
+                               setstat(dsntoexitstat(hbuf));
+                       }
+                       else if (isascii(hbuf[0]) && isdigit(hbuf[0]))
                        {
                        {
-                               setstat(atoi(*tv));
+                               setstat(atoi(hbuf));
                        }
                        else
                        {
                                for (ep = ErrorCodes; ep->ec_name != NULL; ep++)
                        }
                        else
                        {
                                for (ep = ErrorCodes; ep->ec_name != NULL; ep++)
-                                       if (strcasecmp(ep->ec_name, *tv) == 0)
+                                       if (strcasecmp(ep->ec_name, hbuf) == 0)
                                                break;
                                setstat(ep->ec_code);
                        }
                                                break;
                                setstat(ep->ec_code);
                        }
-                       tv++;
                }
                else
                        setstat(EX_UNAVAILABLE);
                }
                else
                        setstat(EX_UNAVAILABLE);
@@ -1769,25 +1794,17 @@ badaddr:
                                (void) strcat(buf, " ");
                        (void) strcat(buf, *tv);
                }
                                (void) strcat(buf, " ");
                        (void) strcat(buf, *tv);
                }
-               if ((**tv & 0377) != CANONUSER)
-                       syserr("554 buildaddr: error: no user");
-               cataddr(++tv, NULL, buf, sizeof buf, ' ');
-               stripquotes(buf);
-#ifdef LOG
-               if (LogLevel > 8)
-                       syslog (LOG_DEBUG, "%s: Trace: $#ERROR $: %s",
-                               CurEnv->e_id, buf);
-#endif /* LOG */
-               if (isascii(buf[0]) && isdigit(buf[0]) &&
-                   isascii(buf[1]) && isdigit(buf[1]) &&
-                   isascii(buf[2]) && isdigit(buf[2]) &&
-                   buf[3] == ' ')
+               stripquotes(ubuf);
+               if (isascii(ubuf[0]) && isdigit(ubuf[0]) &&
+                   isascii(ubuf[1]) && isdigit(ubuf[1]) &&
+                   isascii(ubuf[2]) && isdigit(ubuf[2]) &&
+                   ubuf[3] == ' ')
                {
                        char fmt[10];
 
                {
                        char fmt[10];
 
-                       strncpy(fmt, buf, 3);
+                       strncpy(fmt, ubuf, 3);
                        strcpy(&fmt[3], " %s");
                        strcpy(&fmt[3], " %s");
-                       usrerr(fmt, buf + 4);
+                       usrerr(fmt, ubuf + 4);
 
                        /*
                        **  If this is a 4xx code and we aren't running
 
                        /*
                        **  If this is a 4xx code and we aren't running
@@ -1803,19 +1820,19 @@ badaddr:
                }
                else
                {
                }
                else
                {
-                       usrerr("553 %s", buf);
+                       usrerr("553 %s", ubuf);
                }
                goto badaddr;
        }
 
        for (mp = Mailer; (m = *mp++) != NULL; )
        {
                }
                goto badaddr;
        }
 
        for (mp = Mailer; (m = *mp++) != NULL; )
        {
-               if (strcasecmp(m->m_name, *tv) == 0)
+               if (strcasecmp(m->m_name, mname) == 0)
                        break;
        }
        if (m == NULL)
        {
                        break;
        }
        if (m == NULL)
        {
-               syserr("554 buildaddr: unknown mailer %s", *tv);
+               syserr("554 buildaddr: unknown mailer %s", mname);
                goto badaddr;
        }
        a->q_mailer = m;
                goto badaddr;
        }
        a->q_mailer = m;
@@ -1832,49 +1849,33 @@ badaddr:
        }
        else
        {
        }
        else
        {
-               while (*++tv != NULL && **tv != CANONUSER)
-                       (void) strcat(buf, *tv);
-               a->q_host = newstr(buf);
-       }
 
        /* figure out the user */
 
        /* figure out the user */
-       if (*tv == NULL || (**tv & 0377) != CANONUSER)
-       {
-               syserr("554 buildaddr: no user");
-               goto badaddr;
-       }
-       tv++;
-
-       if (bitnset(M_CHECKUDB, m->m_flags) && *tv != NULL &&
-           strcmp(*tv, "@") == 0)
+       p = ubuf;
+       if (bitnset(M_CHECKUDB, m->m_flags) && *p == '@')
        {
        {
+               p++;
                tv++;
                a->q_flags |= QNOTREMOTE;
        }
 
        /* do special mapping for local mailer */
                tv++;
                a->q_flags |= QNOTREMOTE;
        }
 
        /* do special mapping for local mailer */
-       if (*tv != NULL)
+       if (*p == '"')
+               p++;
+       if (*p == '|' && bitnset(M_CHECKPROG, m->m_flags))
+               a->q_mailer = m = ProgMailer;
+       else if (*p == '/' && bitnset(M_CHECKFILE, m->m_flags))
+               a->q_mailer = m = FileMailer;
+       else if (*p == ':' && bitnset(M_CHECKINCLUDE, m->m_flags))
        {
        {
-               register char *p = *tv;
-
-               if (*p == '"')
-                       p++;
-               if (*p == '|' && bitnset(M_CHECKPROG, m->m_flags))
-                       a->q_mailer = m = ProgMailer;
-               else if (*p == '/' && bitnset(M_CHECKFILE, m->m_flags))
-                       a->q_mailer = m = FileMailer;
-               else if (*p == ':' && bitnset(M_CHECKINCLUDE, m->m_flags))
+               /* may be :include: */
+               stripquotes(ubuf);
+               if (strncasecmp(ubuf, ":include:", 9) == 0)
                {
                {
-                       /* may be :include: */
-                       cataddr(tv, NULL, buf, sizeof buf, '\0');
-                       stripquotes(buf);
-                       if (strncasecmp(buf, ":include:", 9) == 0)
-                       {
-                               /* if :include:, don't need further rewriting */
-                               a->q_mailer = m = InclMailer;
-                               a->q_user = &buf[9];
-                               return (a);
-                       }
+                       /* if :include:, don't need further rewriting */
+                       a->q_mailer = m = InclMailer;
+                       a->q_user = newstr(&ubuf[9]);
+                       return a;
                }
        }
 
                }
        }
 
@@ -1883,8 +1884,8 @@ badaddr:
        (void) rewrite(tv, 4, 0, e);
 
        /* save the result for the command line/RCPT argument */
        (void) rewrite(tv, 4, 0, e);
 
        /* save the result for the command line/RCPT argument */
-       cataddr(tv, NULL, buf, sizeof buf, '\0');
-       a->q_user = buf;
+       cataddr(tv, NULL, ubuf, sizeof ubuf, '\0');
+       a->q_user = ubuf;
 
        /*
        **  Do mapping to lower case as requested by mailer
 
        /*
        **  Do mapping to lower case as requested by mailer
@@ -1895,7 +1896,7 @@ badaddr:
        if (!bitnset(M_USR_UPPER, m->m_flags))
                makelower(a->q_user);
 
        if (!bitnset(M_USR_UPPER, m->m_flags))
                makelower(a->q_user);
 
-       return (a);
+       return a;
 }
 \f/*
 **  CATADDR -- concatenate pieces of addresses (putting in <LWSP> subs)
 }
 \f/*
 **  CATADDR -- concatenate pieces of addresses (putting in <LWSP> subs)
index bec4a3a..3cd0123 100644 (file)
@@ -7,7 +7,7 @@
  */
 
 #ifndef lint
  */
 
 #ifndef lint
-static char sccsid[] = "@(#)sysexits.c 8.2 (Berkeley) %G%";
+static char sccsid[] = "@(#)sysexits.c 8.3 (Berkeley) %G%";
 #endif /* not lint */
 
 #include <sysexits.h>
 #endif /* not lint */
 
 #include <sysexits.h>
@@ -39,3 +39,118 @@ char *SysExMsg[] =
 };
 
 int N_SysEx = sizeof(SysExMsg) / sizeof(SysExMsg[0]);
 };
 
 int N_SysEx = sizeof(SysExMsg) / sizeof(SysExMsg[0]);
+\f/*
+**  DSNTOEXITSTAT -- convert DSN-style error code to EX_ style.
+**
+**     Parameters:
+**             dsncode -- the text of the DSN-style code.
+**
+**     Returns:
+**             The corresponding exit status.
+*/
+
+int
+dsntoexitstat(dsncode)
+       char *dsncode;
+{
+       int code2, code3;
+
+       /* first the easy cases.... */
+       if (*dsncode == '2')
+               return EX_OK;
+       if (*dsncode == '4')
+               return EX_TEMPFAIL;
+
+       /* now decode the other two field parts */
+       if (*++dsncode == '.')
+               dsncode++;
+       code2 = atoi(dsncode);
+       while (*dsncode != '\0' && *dsncode != '.')
+               dsncode++;
+       if (*dsncode != '\0')
+               dsncode++;
+       code3 = atoi(dsncode);
+
+       /* and do a nested switch to work them out */
+       switch (code2)
+       {
+         case 0:       /* Other or Undefined status */
+               return EX_UNAVAILABLE;
+
+         case 1:       /* Address Status */
+               switch (code3)
+               {
+                 case 0:       /* Other Address Status */
+                       return EX_DATAERR;
+
+                 case 1:       /* Bad mailbox address */
+                 case 6:       /* Mailbox has moved, No forwarding address */
+                       return EX_NOUSER;
+
+                 case 2:       /* Bad system address */
+                       return EX_NOHOST;
+
+                 case 3:       /* Bad mailbox address syntax */
+                       return EX_USAGE;
+
+                 case 4:       /* Mailbox address ambiguous */
+                       return EX_UNAVAILABLE;
+
+                 case 5:       /* Address valid */
+                       return EX_OK;
+               }
+               break;
+
+         case 2:       /* Mailbox Status */
+               switch (code3)
+               {
+                 case 0:       /* Other or Undefined mailbox status */
+                 case 1:       /* Mailbox disabled, not acccepting messages */
+                 case 2:       /* Mailbox full */
+                 case 4:       /* Mailing list expansion problem */
+                       return EX_UNAVAILABLE;
+
+                 case 3:       /* Message length exceeds administrative lim */
+                       return EX_DATAERR;
+               }
+               break;
+
+         case 3:       /* System Status */
+               return EX_OSERR;
+
+         case 4:       /* Network and Routing Status */
+               switch (code3)
+               {
+                 case 0:       /* Other or undefined network or routing stat */
+                       return EX_IOERR;
+
+                 case 1:       /* No answer from host */
+                 case 3:       /* Routing server failure */
+                 case 5:       /* Network congestion */
+                       return EX_TEMPFAIL;
+
+                 case 2:       /* Bad connection */
+                       return EX_IOERR;
+
+                 case 4:       /* Unable to route */
+                       return EX_PROTOCOL;
+
+                 case 6:       /* Routing loop detected */
+                       return EX_CONFIG;
+
+                 case 7:       /* Delivery time expired */
+                       return EX_UNAVAILABLE;
+               }
+               break;
+
+         case 5:       /* Protocol Status */
+               return EX_PROTOCOL;
+
+         case 6:       /* Message Content or Media Status */
+               return EX_UNAVAILABLE;
+
+         case 7:       /* Security Status */
+               return EX_DATAERR;
+       }
+       return EX_CONFIG;
+}