This commit was generated by cvs2svn to track changes on a CVS vendor
[unix-history] / usr.sbin / sendmail / src / headers.c
index 6679b50..b05876b 100644 (file)
@@ -33,7 +33,7 @@
  */
 
 #ifndef lint
  */
 
 #ifndef lint
-static char sccsid[] = "@(#)headers.c  8.2 (Berkeley) 7/11/93";
+static char sccsid[] = "@(#)headers.c  8.22 (Berkeley) 1/13/94";
 #endif /* not lint */
 
 # include <errno.h>
 #endif /* not lint */
 
 # include <errno.h>
@@ -70,6 +70,7 @@ chompheader(line, def, e)
        struct hdrinfo *hi;
        bool cond = FALSE;
        BITMAP mopts;
        struct hdrinfo *hi;
        bool cond = FALSE;
        BITMAP mopts;
+       char buf[MAXNAME];
 
        if (tTd(31, 6))
                printf("chompheader: %s\n", line);
 
        if (tTd(31, 6))
                printf("chompheader: %s\n", line);
@@ -96,16 +97,18 @@ chompheader(line, def, e)
 
        /* find canonical name */
        fname = p;
 
        /* find canonical name */
        fname = p;
-       p = strchr(p, ':');
-       if (p == NULL)
+       while (isascii(*p) && isgraph(*p) && *p != ':')
+               p++;
+       fvalue = p;
+       while (isascii(*p) && isspace(*p))
+               p++;
+       if (*p++ != ':' || fname == fvalue)
        {
                syserr("553 header syntax error, line \"%s\"", line);
                return (0);
        }
        {
                syserr("553 header syntax error, line \"%s\"", line);
                return (0);
        }
-       fvalue = &p[1];
-       while (isascii(*--p) && isspace(*p))
-               continue;
-       *++p = '\0';
+       *fvalue = '\0';
+       fvalue = p;
 
        /* strip field value on front */
        if (*fvalue == ' ')
 
        /* strip field value on front */
        if (*fvalue == ' ')
@@ -118,6 +121,14 @@ chompheader(line, def, e)
                        break;
        }
 
                        break;
        }
 
+       if (tTd(31, 9))
+       {
+               if (hi->hi_field == NULL)
+                       printf("no header match\n");
+               else
+                       printf("header match, hi_flags=%o\n", hi->hi_flags);
+       }
+
        /* see if this is a resent message */
        if (!def && bitset(H_RESENT, hi->hi_flags))
                e->e_flags |= EF_RESENT;
        /* see if this is a resent message */
        if (!def && bitset(H_RESENT, hi->hi_flags))
                e->e_flags |= EF_RESENT;
@@ -126,7 +137,12 @@ chompheader(line, def, e)
        if (bitset(H_EOH, hi->hi_flags))
                return (hi->hi_flags);
 
        if (bitset(H_EOH, hi->hi_flags))
                return (hi->hi_flags);
 
-       /* drop explicit From: if same as what we would generate -- for MH */
+       /*
+       **  Drop explicit From: if same as what we would generate.
+       **  This is to make MH (which doesn't always give a full name)
+       **  insert the full name information in all circumstances.
+       */
+
        p = "resent-from";
        if (!bitset(EF_RESENT, e->e_flags))
                p += 7;
        p = "resent-from";
        if (!bitset(EF_RESENT, e->e_flags))
                p += 7;
@@ -141,6 +157,36 @@ chompheader(line, def, e)
                    (strcmp(fvalue, e->e_from.q_paddr) == 0 ||
                     strcmp(fvalue, e->e_from.q_user) == 0))
                        return (hi->hi_flags);
                    (strcmp(fvalue, e->e_from.q_paddr) == 0 ||
                     strcmp(fvalue, e->e_from.q_user) == 0))
                        return (hi->hi_flags);
+#ifdef MAYBENEXTRELEASE                /* XXX UNTESTED XXX UNTESTED XXX UNTESTED XXX */
+#ifdef USERDB
+               else
+               {
+                       auto ADDRESS a;
+                       char *fancy;
+                       extern char *crackaddr();
+                       extern char *udbsender();
+
+                       /*
+                       **  Try doing USERDB rewriting even on fully commented
+                       **  names; this saves the "comment" information (such
+                       **  as full name) and rewrites the electronic part.
+                       */
+
+                       fancy = crackaddr(fvalue);
+                       if (parseaddr(fvalue, &a, RF_COPYNONE, '\0', NULL, e) != NULL &&
+                           a.q_mailer == LocalMailer &&
+                           (p = udbsender(a.q_user)) != NULL)
+                       {
+                               char *oldg = macvalue('g', e);
+
+                               define('g', p, e);
+                               expand(fancy, buf, &buf[sizeof buf], e);
+                               define('g', oldg, e);
+                               fvalue = buf;
+                       }
+               }
+#endif
+#endif
        }
 
        /* delete default value for this header */
        }
 
        /* delete default value for this header */
@@ -155,7 +201,7 @@ chompheader(line, def, e)
        /* create a new node */
        h = (HDR *) xalloc(sizeof *h);
        h->h_field = newstr(fname);
        /* create a new node */
        h = (HDR *) xalloc(sizeof *h);
        h->h_field = newstr(fname);
-       h->h_value = NULL;
+       h->h_value = newstr(fvalue);
        h->h_link = NULL;
        bcopy((char *) mopts, (char *) h->h_mflags, sizeof mopts);
        *hp = h;
        h->h_link = NULL;
        bcopy((char *) mopts, (char *) h->h_mflags, sizeof mopts);
        *hp = h;
@@ -164,9 +210,6 @@ chompheader(line, def, e)
                h->h_flags |= H_DEFAULT;
        if (cond)
                h->h_flags |= H_CHECK;
                h->h_flags |= H_DEFAULT;
        if (cond)
                h->h_flags |= H_CHECK;
-       if (h->h_value != NULL)
-               free((char *) h->h_value);
-       h->h_value = newstr(fvalue);
 
        /* hack to see if this is a new format message */
        if (!def && bitset(H_RCPT|H_FROM, h->h_flags) &&
 
        /* hack to see if this is a new format message */
        if (!def && bitset(H_RCPT|H_FROM, h->h_flags) &&
@@ -323,14 +366,30 @@ eatheader(e, full)
 
        define('f', e->e_sender, e);
        define('g', e->e_sender, e);
 
        define('f', e->e_sender, e);
        define('g', e->e_sender, e);
+       if (e->e_origrcpt != NULL && *e->e_origrcpt != '\0')
+               define('u', e->e_origrcpt, e);
+       else
+               define('u', NULL, e);
+
+       /* full name of from person */
+       p = hvalue("full-name", e);
+       if (p != NULL)
+               define('x', p, e);
 
        if (tTd(32, 1))
                printf("----- collected header -----\n");
        msgid = "<none>";
        for (h = e->e_header; h != NULL; h = h->h_link)
        {
 
        if (tTd(32, 1))
                printf("----- collected header -----\n");
        msgid = "<none>";
        for (h = e->e_header; h != NULL; h = h->h_link)
        {
+               if (h->h_value == NULL)
+               {
+                       if (tTd(32, 1))
+                               printf("%s: <NULL>\n", h->h_field);
+                       continue;
+               }
+
                /* do early binding */
                /* do early binding */
-               if (bitset(H_DEFAULT, h->h_flags) && h->h_value != NULL)
+               if (bitset(H_DEFAULT, h->h_flags))
                {
                        expand(h->h_value, buf, &buf[sizeof buf], e);
                        if (buf[0] != '\0')
                {
                        expand(h->h_value, buf, &buf[sizeof buf], e);
                        if (buf[0] != '\0')
@@ -341,7 +400,11 @@ eatheader(e, full)
                }
 
                if (tTd(32, 1))
                }
 
                if (tTd(32, 1))
-                       printf("%s: %s\n", h->h_field, h->h_value);
+               {
+                       printf("%s: ", h->h_field);
+                       xputs(h->h_value);
+                       printf("\n");
+               }
 
                /* count the number of times it has been processed */
                if (bitset(H_TRACE, h->h_flags))
 
                /* count the number of times it has been processed */
                if (bitset(H_TRACE, h->h_flags))
@@ -352,13 +415,18 @@ eatheader(e, full)
                    !bitset(H_DEFAULT, h->h_flags) &&
                    (!bitset(EF_RESENT, e->e_flags) || bitset(H_RESENT, h->h_flags)))
                {
                    !bitset(H_DEFAULT, h->h_flags) &&
                    (!bitset(EF_RESENT, e->e_flags) || bitset(H_RESENT, h->h_flags)))
                {
-                       (void) sendtolist(h->h_value, (ADDRESS *) NULL,
+                       int saveflags = e->e_flags;
+
+                       (void) sendtolist(h->h_value, NULLADDR,
                                          &e->e_sendqueue, e);
                                          &e->e_sendqueue, e);
+
+                       /* delete fatal errors generated by this address */
+                       if (!GrabTo && !bitset(EF_FATALERRS, saveflags))
+                               e->e_flags &= ~EF_FATALERRS;
                }
 
                /* save the message-id for logging */
                }
 
                /* save the message-id for logging */
-               if (full && h->h_value != NULL &&
-                   strcasecmp(h->h_field, "message-id") == 0)
+               if (full && strcasecmp(h->h_field, "message-id") == 0)
                {
                        msgid = h->h_value;
                        while (isascii(*msgid) && isspace(*msgid))
                {
                        msgid = h->h_value;
                        while (isascii(*msgid) && isspace(*msgid))
@@ -371,7 +439,7 @@ eatheader(e, full)
 
                /* see if this is an errors-to header */
                if (UseErrorsTo && bitset(H_ERRORSTO, h->h_flags))
 
                /* see if this is an errors-to header */
                if (UseErrorsTo && bitset(H_ERRORSTO, h->h_flags))
-                       (void) sendtolist(h->h_value, (ADDRESS *) NULL,
+                       (void) sendtolist(h->h_value, NULLADDR,
                                          &e->e_errorqueue, e);
        }
        if (tTd(32, 1))
                                          &e->e_errorqueue, e);
        }
        if (tTd(32, 1))
@@ -394,11 +462,6 @@ eatheader(e, full)
                                 - e->e_class * WkClassFact
                                 + e->e_nrcpts * WkRecipFact;
 
                                 - e->e_class * WkClassFact
                                 + e->e_nrcpts * WkRecipFact;
 
-       /* full name of from person */
-       p = hvalue("full-name", e);
-       if (p != NULL)
-               define('x', p, e);
-
        /* date message originated */
        p = hvalue("posted-date", e);
        if (p == NULL)
        /* date message originated */
        p = hvalue("posted-date", e);
        if (p == NULL)
@@ -412,48 +475,97 @@ eatheader(e, full)
 
 # ifdef LOG
        if (full && LogLevel > 4)
 
 # ifdef LOG
        if (full && LogLevel > 4)
+               logsender(e, msgid);
+# endif /* LOG */
+       e->e_flags &= ~EF_LOGSENDER;
+}
+\f/*
+**  LOGSENDER -- log sender information
+**
+**     Parameters:
+**             e -- the envelope to log
+**             msgid -- the message id
+**
+**     Returns:
+**             none
+*/
+
+logsender(e, msgid)
+       register ENVELOPE *e;
+       char *msgid;
+{
+       char *name;
+       register char *sbp;
+       register char *p;
+       char hbuf[MAXNAME];
+       char sbuf[MAXLINE];
+
+       if (bitset(EF_RESPONSE, e->e_flags))
+               name = "[RESPONSE]";
+       else if ((name = macvalue('_', e)) != NULL)
+               ;
+       else if (RealHostName[0] == '[')
+               name = RealHostName;
+       else
        {
        {
-               char *name;
-               register char *sbp;
-               char hbuf[MAXNAME];
-               char sbuf[MAXLINE];
-
-               if (bitset(EF_RESPONSE, e->e_flags))
-                       name = "[RESPONSE]";
-               else if ((name = macvalue('_', e)) != NULL)
-                       ;
-               else if (RealHostName[0] == '[')
-                       name = RealHostName;
-               else
+               name = hbuf;
+               (void) sprintf(hbuf, "%.80s", RealHostName);
+               if (RealHostAddr.sa.sa_family != 0)
                {
                {
-                       name = hbuf;
-                       (void) sprintf(hbuf, "%.80s", RealHostName);
-                       if (RealHostAddr.sa.sa_family != 0)
-                       {
-                               p = &hbuf[strlen(hbuf)];
-                               (void) sprintf(p, " (%s)",
-                                       anynet_ntoa(&RealHostAddr));
-                       }
+                       p = &hbuf[strlen(hbuf)];
+                       (void) sprintf(p, " (%s)",
+                               anynet_ntoa(&RealHostAddr));
                }
                }
+       }
 
 
-               /* some versions of syslog only take 5 printf args */
-               sbp = sbuf;
-               sprintf(sbp, "from=%.200s, size=%ld, class=%d, pri=%ld, nrcpts=%d, msgid=%.100s",
-                   e->e_from.q_paddr, e->e_msgsize, e->e_class,
-                   e->e_msgpriority, e->e_nrcpts, msgid);
+       /* some versions of syslog only take 5 printf args */
+#  if (SYSLOG_BUFSIZE) >= 256
+       sbp = sbuf;
+       sprintf(sbp, "from=%.200s, size=%ld, class=%d, pri=%ld, nrcpts=%d",
+           e->e_from.q_paddr, e->e_msgsize, e->e_class,
+           e->e_msgpriority, e->e_nrcpts);
+       sbp += strlen(sbp);
+       if (msgid != NULL)
+       {
+               sprintf(sbp, ", msgid=%.100s", msgid);
                sbp += strlen(sbp);
                sbp += strlen(sbp);
-               if (e->e_bodytype != NULL)
-               {
-                       (void) sprintf(sbp, ", bodytype=%.20s", e->e_bodytype);
-                       sbp += strlen(sbp);
-               }
-               p = macvalue('r', e);
-               if (p != NULL)
-                       (void) sprintf(sbp, ", proto=%.20s", p);
-               syslog(LOG_INFO, "%s: %s, relay=%s",
-                   e->e_id, sbuf, name);
        }
        }
-# endif /* LOG */
+       if (e->e_bodytype != NULL)
+       {
+               (void) sprintf(sbp, ", bodytype=%.20s", e->e_bodytype);
+               sbp += strlen(sbp);
+       }
+       p = macvalue('r', e);
+       if (p != NULL)
+               (void) sprintf(sbp, ", proto=%.20s", p);
+       syslog(LOG_INFO, "%s: %s, relay=%s",
+           e->e_id, sbuf, name);
+
+#  else                        /* short syslog buffer */
+
+       syslog(LOG_INFO, "%s: from=%s",
+               e->e_id, shortenstring(e->e_from.q_paddr, 83));
+       syslog(LOG_INFO, "%s: size=%ld, class=%ld, pri=%ld, nrcpts=%d",
+               e->e_id, e->e_msgsize, e->e_class,
+               e->e_msgpriority, e->e_nrcpts);
+       if (msgid != NULL)
+               syslog(LOG_INFO, "%s: msgid=%s", e->e_id, msgid);
+       sbp = sbuf;
+       sprintf(sbp, "%s:", e->e_id);
+       sbp += strlen(sbp);
+       if (e->e_bodytype != NULL)
+       {
+               sprintf(sbp, " bodytype=%s,", e->e_bodytype);
+               sbp += strlen(sbp);
+       }
+       p = macvalue('r', e);
+       if (p != NULL)
+       {
+               sprintf(sbp, " proto=%s,", p);
+               sbp += strlen(sbp);
+       }
+       syslog(LOG_INFO, "%s relay=%s", sbuf, name);
+#  endif
 }
 \f/*
 **  PRIENCODE -- encode external priority names into internal values.
 }
 \f/*
 **  PRIENCODE -- encode external priority names into internal values.
@@ -525,6 +637,7 @@ crackaddr(addr)
        bool skipping;
        bool putgmac = FALSE;
        bool quoteit = FALSE;
        bool skipping;
        bool putgmac = FALSE;
        bool quoteit = FALSE;
+       bool gotangle = FALSE;
        register char *bp;
        char *buflim;
        static char buf[MAXNAME];
        register char *bp;
        char *buflim;
        static char buf[MAXNAME];
@@ -579,7 +692,7 @@ crackaddr(addr)
                }
 
                /* check for quoted strings */
                }
 
                /* check for quoted strings */
-               if (c == '"')
+               if (c == '"' && cmtlev <= 0)
                {
                        qmode = !qmode;
                        if (copylev > 0 && !skipping)
                {
                        qmode = !qmode;
                        if (copylev > 0 && !skipping)
@@ -623,13 +736,12 @@ crackaddr(addr)
                else if (c == ')')
                {
                        /* syntax error: unmatched ) */
                else if (c == ')')
                {
                        /* syntax error: unmatched ) */
-                       if (!skipping)
+                       if (copylev > 0 && !skipping)
                                bp--;
                }
 
                                bp--;
                }
 
-
                /* check for characters that may have to be quoted */
                /* check for characters that may have to be quoted */
-               if (strchr(".'@,;:\\()", c) != NULL)
+               if (strchr(".'@,;:\\()[]", c) != NULL)
                {
                        /*
                        **  If these occur as the phrase part of a <>
                {
                        /*
                        **  If these occur as the phrase part of a <>
@@ -647,10 +759,15 @@ crackaddr(addr)
                {
                        register char *q;
 
                {
                        register char *q;
 
+                       /* assume first of two angles is bogus */
+                       if (gotangle)
+                               quoteit = TRUE;
+                       gotangle = TRUE;
+
                        /* oops -- have to change our mind */
                        /* oops -- have to change our mind */
-                       anglelev++;
+                       anglelev = 1;
                        if (!skipping)
                        if (!skipping)
-                               realanglelev++;
+                               realanglelev = 1;
 
                        bp = buf;
                        if (quoteit)
 
                        bp = buf;
                        if (quoteit)
@@ -675,7 +792,10 @@ crackaddr(addr)
                        }
                        if (quoteit)
                        {
                        }
                        if (quoteit)
                        {
-                               *bp++ = '"';
+                               if (bp == &buf[1])
+                                       bp--;
+                               else
+                                       *bp++ = '"';
                                while ((c = *p++) != '<')
                                {
                                        if (bp < buflim)
                                while ((c = *p++) != '<')
                                {
                                        if (bp < buflim)
@@ -704,6 +824,7 @@ crackaddr(addr)
                                /* syntax error: unmatched > */
                                if (copylev > 0)
                                        bp--;
                                /* syntax error: unmatched > */
                                if (copylev > 0)
                                        bp--;
+                               quoteit = TRUE;
                                continue;
                        }
                        if (copylev++ <= 0)
                                continue;
                        }
                        if (copylev++ <= 0)
@@ -795,19 +916,24 @@ putheader(fp, m, e)
                                printf(" (skipped (resent))\n");
                        continue;
                }
                                printf(" (skipped (resent))\n");
                        continue;
                }
-               if (tTd(34, 11))
-                       printf("\n");
 
 
+               /* macro expand value if generated internally */
                p = h->h_value;
                if (bitset(H_DEFAULT, h->h_flags))
                {
                p = h->h_value;
                if (bitset(H_DEFAULT, h->h_flags))
                {
-                       /* macro expand value if generated internally */
                        expand(p, buf, &buf[sizeof buf], e);
                        p = buf;
                        if (p == NULL || *p == '\0')
                        expand(p, buf, &buf[sizeof buf], e);
                        p = buf;
                        if (p == NULL || *p == '\0')
+                       {
+                               if (tTd(34, 11))
+                                       printf(" (skipped -- null value)\n");
                                continue;
                                continue;
+                       }
                }
 
                }
 
+               if (tTd(34, 11))
+                       printf("\n");
+
                if (bitset(H_FROM|H_RCPT, h->h_flags))
                {
                        /* address field */
                if (bitset(H_FROM|H_RCPT, h->h_flags))
                {
                        /* address field */
@@ -911,7 +1037,8 @@ commaize(h, p, fp, oldstyle, m, e)
                        auto char *oldp;
                        char pvpbuf[PSBUFSIZE];
 
                        auto char *oldp;
                        char pvpbuf[PSBUFSIZE];
 
-                       (void) prescan(p, oldstyle ? ' ' : ',', pvpbuf, &oldp);
+                       (void) prescan(p, oldstyle ? ' ' : ',', pvpbuf,
+                                      sizeof pvpbuf, &oldp);
                        p = oldp;
 
                        /* look to see if we have an at sign */
                        p = oldp;
 
                        /* look to see if we have an at sign */