implement arpatounix; log more info; allow nested $?...$|...$.;
authorEric Allman <eric@ucbvax.Berkeley.EDU>
Tue, 19 Jan 1993 06:32:29 +0000 (22:32 -0800)
committerEric Allman <eric@ucbvax.Berkeley.EDU>
Tue, 19 Jan 1993 06:32:29 +0000 (22:32 -0800)
POSIX compatibility; handle SMTP MAIL command errors properly;
do early diagnosis of .cf errors; adjust checkpointing; misc bugs

SCCS-vsn: usr.sbin/sendmail/src/headers.c 6.4
SCCS-vsn: usr.sbin/sendmail/src/macro.c 6.2
SCCS-vsn: usr.sbin/sendmail/src/main.c 6.7
SCCS-vsn: usr.sbin/sendmail/src/envelope.c 6.2
SCCS-vsn: usr.sbin/sendmail/src/arpadate.c 6.2
SCCS-vsn: usr.sbin/sendmail/src/version.c 6.10
SCCS-vsn: usr.sbin/sendmail/src/util.c 6.3
SCCS-vsn: usr.sbin/sendmail/src/readcf.c 6.4
SCCS-vsn: usr.sbin/sendmail/src/deliver.c 6.9
SCCS-vsn: usr.sbin/sendmail/src/queue.c 6.4

usr/src/usr.sbin/sendmail/src/arpadate.c
usr/src/usr.sbin/sendmail/src/deliver.c
usr/src/usr.sbin/sendmail/src/envelope.c
usr/src/usr.sbin/sendmail/src/headers.c
usr/src/usr.sbin/sendmail/src/macro.c
usr/src/usr.sbin/sendmail/src/main.c
usr/src/usr.sbin/sendmail/src/queue.c
usr/src/usr.sbin/sendmail/src/readcf.c
usr/src/usr.sbin/sendmail/src/util.c
usr/src/usr.sbin/sendmail/src/version.c

index cc4a93a..51f0e02 100644 (file)
@@ -7,13 +7,11 @@
  */
 
 #ifndef lint
  */
 
 #ifndef lint
-static char sccsid[] = "@(#)arpadate.c 6.1 (Berkeley) %G%";
+static char sccsid[] = "@(#)arpadate.c 6.2 (Berkeley) %G%";
 #endif /* not lint */
 
 #endif /* not lint */
 
-# include "conf.h"
-# include <time.h>
+# include "sendmail.h"
 # include <sys/types.h>
 # include <sys/types.h>
-# include "useful.h"
 
 /*
 **  ARPADATE -- Create date in ARPANET format
 
 /*
 **  ARPADATE -- Create date in ARPANET format
@@ -151,3 +149,335 @@ arpadate(ud)
 
        return (b);
 }
 
        return (b);
 }
+
+/*
+**  NEXTATOM -- Return pointer to next atom in header
+**             (skip whitespace and comments)
+**
+**     Parameters:
+**             s -- pointer to header string
+**
+**     Returns:
+**             pointer advanced to next non-comment header atom
+**
+**     Side Effects:
+**             none
+*/
+
+static char *
+nextatom(s)
+       char *s;
+{
+       char *p;
+
+       for (p = s;
+            *p && (*p == ' ' || *p == '\t' || *p == '\n' || *p == '(');
+            p++)
+       {
+               if (*p == '(')
+               {
+                       int nested = 0;
+
+                       /* ignore comments */
+                       p++;
+                       for (; *p; p++)
+                       {
+                               if (*p == '(')
+                                       nested++;
+                               else if (*p == ')')
+                                       if (!nested)
+                                               break;
+                                       else
+                                               nested--;
+                       }
+               }
+       }
+       return (p);
+}
+
+/*
+**  ARPATOUNIX -- Convert RFC-822/1123 date-time specification to ctime format.
+**
+**     Parameters:
+**             s -- pointer to date string
+**
+**     Returns:
+**             pointer to a string in ctime format
+**
+**     Side Effects:
+**             Calls asctime() which modifies its static area.
+**
+**     Syntax:
+**             date-time field specification from RFC822
+**             as amended by RFC 1123:
+**
+**                     [ day "," ] 1*2DIGIT month 2*4DIGIT \
+**                     2DIGIT ":" 2DIGIT [ ":" 2DIGIT  ] zone
+**
+**             Day can be "Mon" "Tue" "Wed" "Thu" "Fri" "Sat" "Sun"
+**                     (case-insensitive)
+**             Month can be "Jan" "Feb" "Mar" "Apr" "May" "Jun" "Jul"
+**                     "Aug" "Sep" "Oct" "Nov" "Dec" (also case-insensitive)
+**             Zone can be "UT" "GMT" "EST" "EDT" "CST" "CDT" "MST" "MDT"
+**                     "PST" "PDT" or "+"4*DIGIT or "-"4*DIGIT
+**                     (case-insensitive; military zones not useful
+**                     per RFC1123)
+**             Additional whitespace or comments may occur.
+*/
+
+static char MonthDays[] = {
+       31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
+};
+
+char *
+arpatounix(s, e)
+       char    *s;
+       ENVELOPE *e;
+{
+       char *p;
+       char *n;
+       int h_offset = 0;               /* hours */
+       int m_offset = 0;               /* minutes */
+       struct tm tm;
+       extern char *DowList[];         /* defined in collect.c */
+       extern char *MonthList[];       /* defined in collect.c */
+
+       bzero((char *) &tm, sizeof tm);
+       tm.tm_wday = -1;        /* impossible value */
+       p = nextatom (s);
+
+       /* next atom must be a day or a date */
+       if (isalpha((int) *p))
+       {
+               /* day */
+               for (tm.tm_wday = 0; DowList[tm.tm_wday]; tm.tm_wday++)
+               {
+                       if (strncasecmp (p, DowList[tm.tm_wday], 3))
+                               continue;
+                       else
+                       {
+                               p += 3;
+                               break;
+                       }
+               }
+               p = nextatom(p);                /* ',' */
+               if (*p == ',')
+                       p = nextatom(++p);
+       }
+
+       /* now must have date */
+       tm.tm_mday = atoi(p);
+       while (isdigit((int) *p))               /* skip over date */
+               p++;
+       p = nextatom(p);                        /* point to month name */
+       for (tm.tm_mon = 0; MonthList[tm.tm_mon]; tm.tm_mon++)
+       {
+               if (strncasecmp(p, MonthList[tm.tm_mon], 3) == 0)
+               {
+                       p += 3;
+                       break;
+               }
+       }
+       p = nextatom(p);                        /* year */
+       tm.tm_year = atoi(p);
+
+       /* if this was 4 digits, subtract 1900 */
+       if (tm.tm_year > 999)
+               tm.tm_year -= 1900;
+       else
+       {
+               /* if 2 or 3 digits, guess which century and convert */
+               time_t now;
+               struct tm *gmt;
+
+               (void) time(&now);
+               gmt = gmtime(&now);
+
+               /* more likely +1 day than -100(0) years */
+               if (gmt->tm_mon == 11 && gmt->tm_mday == 31 &&
+                   tm.tm_mon == 0 && tm.tm_mday == 1)
+                       gmt->tm_year++;
+               if (tm.tm_year > 99)
+               {
+                       /* 3 digits */
+                       tm.tm_year += ((gmt->tm_year + 900 - tm.tm_year) / 1000) * 1000;
+               }
+               else
+               {
+                       /* 2 digits */
+                       tm.tm_year += ((gmt->tm_year - tm.tm_year) / 100) * 100;
+               }
+       }
+       while (isdigit((int) *p))       /* skip over year */
+               p++;
+       p = nextatom(p);                /* hours */
+       tm.tm_hour = atoi(p);
+       while (isdigit((int) *p))       /* skip over hours */
+               p++;
+       p = nextatom(p);                /* colon */
+       if (*p == ':')
+               p = nextatom(++p);
+       p = nextatom(p);                /* minutes */
+       tm.tm_min = atoi(p);
+       while (isdigit((int) *p))       /* skip over minutes */
+               p++;
+       p = nextatom(p);                /* colon or zone */
+       if (*p == ':')                  /* have seconds field */
+       {
+               p = nextatom(++p);
+               tm.tm_sec = atoi(p);
+               while (isdigit((int) *p))       /* skip over seconds */
+                       p++;
+       }
+       p = nextatom(p);                /* zone */
+       if (!strncasecmp(p, "UT", 2) || !strncasecmp(p, "GMT", 3))
+               ;
+       else if (!strncasecmp(p, "EDT", 3))
+               h_offset = -4;
+       else if (!strncasecmp(p, "EST", 3))
+       {
+               h_offset = -5;
+               tm.tm_isdst = 1;
+       }
+       else if (!strncasecmp(p, "CDT", 3))
+               h_offset = -5;
+       else if (!strncasecmp(p, "CST", 3))
+       {
+               h_offset = -6;
+               tm.tm_isdst = 1;
+       }
+       else if (!strncasecmp(p, "MDT", 3))
+               h_offset = -6;
+       else if (!strncasecmp(p, "MST", 3))
+       {
+               h_offset = -7;
+               tm.tm_isdst = 1;
+       }
+       else if (!strncasecmp(p, "PDT", 3))
+               h_offset = -7;
+       else if (!strncasecmp(p, "PST", 3))
+       {
+               h_offset = -8;
+               tm.tm_isdst = 1;
+       }
+       else if (*p == '+')
+       {
+               int off;
+
+               off = atoi(++p);
+               h_offset = off / 100;
+               m_offset = off % 100;
+       }
+       else if (*p == '-')
+       {
+               int off;
+
+               off = atoi(++p);
+               h_offset = off / -100;
+               m_offset = -1 * (off % 100);
+       }
+       else
+       {
+#ifdef LOG
+               if (LogLevel > 0)
+                       syslog(LOG_NOTICE, "%s: arpatounix: unparseable date: %s",
+                               e->e_id, s);
+#endif /* LOG */
+               return(NULL);
+       }
+
+       /* is the year a leap year? */
+       if ((tm.tm_year % 4 == 0) &&
+           ((tm.tm_year % 100 != 0) || (tm.tm_year % 400 == 0)))
+               MonthDays[2] = 29;
+       else
+               MonthDays[2] = 28;
+
+       /* apply offset */
+       if (h_offset || m_offset)
+       {
+               tm.tm_min += m_offset;
+               tm.tm_hour += h_offset;
+
+               /* normalize */
+               if (tm.tm_min < 0)
+               {
+                       tm.tm_hour--;
+                       tm.tm_min += 60;
+               }
+               else if (tm.tm_min > 59)
+               {
+                       tm.tm_hour++;
+                       tm.tm_min -= 60;
+               }
+               if (tm.tm_hour < 0)
+               {
+                       tm.tm_mday--;
+                       tm.tm_wday--;
+                       tm.tm_hour += 24;
+               }
+               else if (tm.tm_hour > 23)
+               {
+                       tm.tm_mday++;
+                       tm.tm_wday++;
+                       tm.tm_hour -= 24;
+               }
+               if (tm.tm_mday < 1)
+               {
+                       if (--tm.tm_mon == -1)
+                       {
+                               tm.tm_mon = 11;
+                               tm.tm_year--;
+
+                               /* is the year a leap year? */
+                               if ((tm.tm_year % 4 == 0) &&
+                                   ((tm.tm_year % 100 != 0) || (tm.tm_year % 400 == 0)))
+                                       MonthDays[2] = 29;
+                               else
+                                       MonthDays[2] = 28;
+                       }
+                       tm.tm_mday += MonthDays[tm.tm_mon];
+               }
+               else if (tm.tm_mday > MonthDays[tm.tm_mon])
+               {
+                       tm.tm_mday -= MonthDays[tm.tm_mon++];
+                       if (tm.tm_mon > 11)
+                       {
+                               tm.tm_mon = 0;
+                               tm.tm_year++;
+
+                               /*
+                               * Don't have to worry about leap years in
+                               * January.
+                               */
+                       }
+               }
+       }
+
+       /* determine day of week if not set from RFC822/1123 line */
+       if (tm.tm_wday < 0)
+       {
+               int i;
+
+               for (i = 0; i < tm.tm_mon; i++)
+                       tm.tm_yday += MonthDays[i];
+               tm.tm_yday += tm.tm_mday;
+
+               /* I wouldn't change these constants if I were you... */
+               tm.tm_wday = (int) (((((tm.tm_year + 699L) * 146097L) / 400L) + tm.tm_yday) % 7);
+       }
+
+       /* now get UT */
+       if ((p = asctime(&tm)) == NULL || *p == '\0' || strlen(p) < 25)
+       {
+#ifdef LOG
+               if (LogLevel > 0)
+                       syslog(LOG_NOTICE, "%s: arpatounix: asctime failed: %s",
+                               e->e_id, s);
+#endif /* LOG */
+               return(NULL);
+       }
+       if ((n = index(p, '\n')) != NULL)
+               *n = '\0';
+       return(p);
+}
index 43c42f7..9aa9cca 100644 (file)
@@ -7,7 +7,7 @@
  */
 
 #ifndef lint
  */
 
 #ifndef lint
-static char sccsid[] = "@(#)deliver.c  6.8 (Berkeley) %G%";
+static char sccsid[] = "@(#)deliver.c  6.9 (Berkeley) %G%";
 #endif /* not lint */
 
 #include "sendmail.h"
 #endif /* not lint */
 
 #include "sendmail.h"
@@ -494,7 +494,10 @@ deliver(e, firstto)
                if (rcode != EX_OK)
                        markfailure(e, to, rcode);
                else
                if (rcode != EX_OK)
                        markfailure(e, to, rcode);
                else
+               {
                        to->q_flags |= QSENT;
                        to->q_flags |= QSENT;
+                       e->e_nsent++;
+               }
        }
 
        /*
        }
 
        /*
@@ -1430,7 +1433,6 @@ sendall(e, mode)
        register ADDRESS *q;
        bool oldverbose;
        int pid;
        register ADDRESS *q;
        bool oldverbose;
        int pid;
-       int nsent;
 # ifdef LOCKF
        struct flock lfd;
 # endif
 # ifdef LOCKF
        struct flock lfd;
 # endif
@@ -1464,7 +1466,8 @@ sendall(e, mode)
        {
                errno = 0;
                syserr("sendall: too many hops %d (%d max): from %s, to %s",
        {
                errno = 0;
                syserr("sendall: too many hops %d (%d max): from %s, to %s",
-                       e->e_hopcount, MaxHopCount, e->e_from.q_paddr, e->e_to);
+                       e->e_hopcount, MaxHopCount, e->e_from.q_paddr,
+                       e->e_sendqueue->q_paddr);
                return;
        }
 
                return;
        }
 
@@ -1565,7 +1568,7 @@ sendall(e, mode)
        **  Run through the list and send everything.
        */
 
        **  Run through the list and send everything.
        */
 
-       nsent = 0;
+       e->e_nsent = 0;
        for (q = e->e_sendqueue; q != NULL; q = q->q_next)
        {
                if (mode == SM_VERIFY)
        for (q = e->e_sendqueue; q != NULL; q = q->q_next)
        {
                if (mode == SM_VERIFY)
@@ -1581,14 +1584,13 @@ sendall(e, mode)
                        **  Checkpoint the send list every few addresses
                        */
 
                        **  Checkpoint the send list every few addresses
                        */
 
-                       if (nsent >= CheckpointInterval)
+                       if (e->e_nsent >= CheckpointInterval)
                        {
                                queueup(e, TRUE, FALSE);
                        {
                                queueup(e, TRUE, FALSE);
-                               nsent = 0;
+                               e->e_nsent = 0;
                        }
 # endif /* QUEUE */
                        }
 # endif /* QUEUE */
-                       if (deliver(e, q) == EX_OK)
-                               nsent++;
+                       (void) deliver(e, q);
                }
        }
        Verbose = oldverbose;
                }
        }
        Verbose = oldverbose;
index c98075c..fd36612 100644 (file)
@@ -7,7 +7,7 @@
  */
 
 #ifndef lint
  */
 
 #ifndef lint
-static char sccsid[] = "@(#)envelope.c 6.1 (Berkeley) %G%";
+static char sccsid[] = "@(#)envelope.c 6.2 (Berkeley) %G%";
 #endif /* not lint */
 
 #include <sys/types.h>
 #endif /* not lint */
 
 #include <sys/types.h>
@@ -154,6 +154,11 @@ dropenvelope(e)
        if (e->e_dfp != NULL)
                (void) fclose(e->e_dfp);
        e->e_dfp = NULL;
        if (e->e_dfp != NULL)
                (void) fclose(e->e_dfp);
        e->e_dfp = NULL;
+
+#ifdef LOG
+       if (LogLevel >= 10)
+               syslog(LOG_INFO, "%s: done", e->e_id);
+#endif /* LOG */
 }
 \f/*
 **  CLEARENVELOPE -- clear an envelope without unlocking
 }
 \f/*
 **  CLEARENVELOPE -- clear an envelope without unlocking
@@ -459,7 +464,9 @@ setsender(from, e)
                }
        }
 
                }
        }
 
+/*
        SuprErrs = TRUE;
        SuprErrs = TRUE;
+*/
        if (from == NULL || parseaddr(from, &e->e_from, 1, '\0', e) == NULL)
        {
                /* log garbage addresses for traceback */
        if (from == NULL || parseaddr(from, &e->e_from, 1, '\0', e) == NULL)
        {
                /* log garbage addresses for traceback */
@@ -475,11 +482,14 @@ setsender(from, e)
                                from, realname, host);
                }
 # endif /* LOG */
                                from, realname, host);
                }
 # endif /* LOG */
-               from = newstr(realname);
-               if (parseaddr(from, &e->e_from, 1, '\0', e) == NULL &&
-                   parseaddr("postmaster", &e->e_from, 1, '\0', e) == NULL)
+               if (from != NULL)
+                       SuprErrs = TRUE;
+               if (from == realname ||
+                   parseaddr(from = newstr(realname), &e->e_from, 1, '\0', e) == NULL)
                {
                {
-                       syserr("setsender: can't even parse postmaster!");
+                       SuprErrs = TRUE;
+                       if (parseaddr("postmaster", &e->e_from, 1, '\0', e) == NULL)
+                               syserr("setsender: can't even parse postmaster!");
                }
        }
        else
                }
        }
        else
index 2dd0b30..7083971 100644 (file)
@@ -7,7 +7,7 @@
  */
 
 #ifndef lint
  */
 
 #ifndef lint
-static char sccsid[] = "@(#)headers.c  6.3 (Berkeley) %G%";
+static char sccsid[] = "@(#)headers.c  6.4 (Berkeley) %G%";
 #endif /* not lint */
 
 # include <errno.h>
 #endif /* not lint */
 
 # include <errno.h>
@@ -364,10 +364,11 @@ eatheader(e)
                p = hvalue("date", e);
        if (p != NULL)
        {
                p = hvalue("date", e);
        if (p != NULL)
        {
+               extern char *arpatounix();
+
                define('a', p, e);
                define('a', p, e);
-               /* we don't have a good way to do canonical conversion ....
-               define('d', newstr(arpatounix(p)), e);
-               .... so we will ignore the problem for the time being */
+               if ((p = arpatounix(p, e)) != NULL)
+                       define('d', newstr(p), e);
        }
 
        /*
        }
 
        /*
@@ -395,8 +396,9 @@ eatheader(e)
                }
 
                /* some versions of syslog only take 5 printf args */
                }
 
                /* some versions of syslog only take 5 printf args */
-               sprintf(sbuf, "from=%.200s, size=%ld, class=%d, msgid=%.100s",
-                   e->e_from.q_paddr, e->e_msgsize, e->e_class, msgid);
+               sprintf(sbuf, "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);
                syslog(LOG_INFO, "%s: %s, received from %s\n",
                    e->e_id, sbuf, name);
        }
                syslog(LOG_INFO, "%s: %s, received from %s\n",
                    e->e_id, sbuf, name);
        }
@@ -693,6 +695,13 @@ crackaddr(addr)
 **             none.
 */
 
 **             none.
 */
 
+/*
+ * Macro for fast max (not available in e.g. DG/UX, 386/ix).
+ */
+#ifndef MAX
+# define MAX(a,b) (((a)>(b))?(a):(b))
+#endif
+
 putheader(fp, m, e)
        register FILE *fp;
        register MAILER *m;
 putheader(fp, m, e)
        register FILE *fp;
        register MAILER *m;
index 86453e2..6cce25a 100644 (file)
@@ -7,7 +7,7 @@
  */
 
 #ifndef lint
  */
 
 #ifndef lint
-static char sccsid[] = "@(#)macro.c    6.1 (Berkeley) %G%";
+static char sccsid[] = "@(#)macro.c    6.2 (Berkeley) %G%";
 #endif /* not lint */
 
 # include "sendmail.h"
 #endif /* not lint */
 
 # include "sendmail.h"
@@ -41,6 +41,7 @@ expand(s, buf, buflim, e)
        bool skipping;          /* set if conditionally skipping output */
        bool recurse = FALSE;   /* set if recursion required */
        int i;
        bool skipping;          /* set if conditionally skipping output */
        bool recurse = FALSE;   /* set if recursion required */
        int i;
+       int iflev;              /* if nesting level */
        char xbuf[BUFSIZ];
        extern char *macvalue();
 
        char xbuf[BUFSIZ];
        extern char *macvalue();
 
@@ -52,6 +53,7 @@ expand(s, buf, buflim, e)
        }
 
        skipping = FALSE;
        }
 
        skipping = FALSE;
+       iflev = 0;
        if (s == NULL)
                s = "";
        for (xp = xbuf; *s != '\0'; s++)
        if (s == NULL)
                s = "";
        for (xp = xbuf; *s != '\0'; s++)
@@ -68,17 +70,26 @@ expand(s, buf, buflim, e)
                switch (c)
                {
                  case CONDIF:          /* see if var set */
                switch (c)
                {
                  case CONDIF:          /* see if var set */
-                       c = *++s;
-                       skipping = macvalue(c, e) == NULL;
-                       continue;
+                       if (iflev++ <= 0)
+                       {
+                               c = *++s;
+                               skipping = macvalue(c, e) == NULL;
+                               continue;
+                       }
+                       break;
 
                  case CONDELSE:        /* change state of skipping */
 
                  case CONDELSE:        /* change state of skipping */
-                       skipping = !skipping;
+                       if (iflev == 1)
+                               skipping = !skipping;
                        continue;
 
                  case CONDFI:          /* stop skipping */
                        continue;
 
                  case CONDFI:          /* stop skipping */
-                       skipping = FALSE;
-                       continue;
+                       if (--iflev <= 0)
+                       {
+                               skipping = FALSE;
+                               continue;
+                       }
+                       break;
 
                  case '\001':          /* macro interpolation */
                        c = *++s;
 
                  case '\001':          /* macro interpolation */
                        c = *++s;
index 4b2dad8..e3e2284 100644 (file)
@@ -13,11 +13,12 @@ char copyright[] =
 #endif /* not lint */
 
 #ifndef lint
 #endif /* not lint */
 
 #ifndef lint
-static char sccsid[] = "@(#)main.c     6.6 (Berkeley) %G%";
+static char sccsid[] = "@(#)main.c     6.7 (Berkeley) %G%";
 #endif /* not lint */
 
 #define        _DEFINE
 
 #endif /* not lint */
 
 #define        _DEFINE
 
+#include <unistd.h>
 #include <sys/file.h>
 #include <sys/stat.h>
 #include <signal.h>
 #include <sys/file.h>
 #include <sys/stat.h>
 #include <signal.h>
@@ -174,8 +175,11 @@ main(argc, argv, envp)
                i = dup(i);
 
        i = DtableSize;
                i = dup(i);
 
        i = DtableSize;
-       while (--i > 2)
-               (void) close(i);
+       while (--i > 0)
+       {
+               if (i != STDIN_FILENO && i != STDOUT_FILENO && i != STDERR_FILENO)
+                       (void) close(i);
+       }
        errno = 0;
 
 #ifdef LOG_MAIL
        errno = 0;
 
 #ifdef LOG_MAIL
index c99a139..cddbd3c 100644 (file)
@@ -10,9 +10,9 @@
 
 #ifndef lint
 #ifdef QUEUE
 
 #ifndef lint
 #ifdef QUEUE
-static char sccsid[] = "@(#)queue.c    6.3 (Berkeley) %G% (with queueing)";
+static char sccsid[] = "@(#)queue.c    6.4 (Berkeley) %G% (with queueing)";
 #else
 #else
-static char sccsid[] = "@(#)queue.c    6.3 (Berkeley) %G% (without queueing)";
+static char sccsid[] = "@(#)queue.c    6.4 (Berkeley) %G% (without queueing)";
 #endif
 #endif /* not lint */
 
 #endif
 #endif /* not lint */
 
@@ -1283,6 +1283,7 @@ setctluser(user)
                a->q_ruser = newstr(DefUser);
        }
 
                a->q_ruser = newstr(DefUser);
        }
 
+       a->q_user = a->q_ruser;
        a->q_flags |= QGOODUID;         /* flag as a "ctladdr"  */
        a->q_mailer = LocalMailer;
        return a;
        a->q_flags |= QGOODUID;         /* flag as a "ctladdr"  */
        a->q_mailer = LocalMailer;
        return a;
index cf88e08..6e1c56d 100644 (file)
@@ -7,7 +7,7 @@
  */
 
 #ifndef lint
  */
 
 #ifndef lint
-static char sccsid[] = "@(#)readcf.c   6.3 (Berkeley) %G%";
+static char sccsid[] = "@(#)readcf.c   6.4 (Berkeley) %G%";
 #endif /* not lint */
 
 # include "sendmail.h"
 #endif /* not lint */
 
 # include "sendmail.h"
@@ -73,6 +73,7 @@ readcf(cfname)
        char **pv;
        struct rewrite *rwp = NULL;
        char *bp;
        char **pv;
        struct rewrite *rwp = NULL;
        char *bp;
+       int nfuzzy;
        char buf[MAXLINE];
        register char *p;
        extern char **prescan();
        char buf[MAXLINE];
        register char *p;
        extern char **prescan();
@@ -208,8 +209,27 @@ readcf(cfname)
                        *p = '\0';
                        expand(&bp[1], exbuf, &exbuf[sizeof exbuf], e);
                        rwp->r_lhs = prescan(exbuf, '\t', pvpbuf);
                        *p = '\0';
                        expand(&bp[1], exbuf, &exbuf[sizeof exbuf], e);
                        rwp->r_lhs = prescan(exbuf, '\t', pvpbuf);
+                       nfuzzy = 0;
                        if (rwp->r_lhs != NULL)
                        if (rwp->r_lhs != NULL)
+                       {
+                               register char **ap;
+
                                rwp->r_lhs = copyplist(rwp->r_lhs, TRUE);
                                rwp->r_lhs = copyplist(rwp->r_lhs, TRUE);
+
+                               /* count the number of fuzzy matches in LHS */
+                               for (ap = rwp->r_lhs; *ap != NULL; ap++)
+                               {
+                                       switch (**ap)
+                                       {
+                                         case MATCHZANY:
+                                         case MATCHANY:
+                                         case MATCHONE:
+                                         case MATCHCLASS:
+                                         case MATCHNCLASS:
+                                               nfuzzy++;
+                                       }
+                               }
+                       }
                        else
                                syserr("R line: null LHS");
 
                        else
                                syserr("R line: null LHS");
 
@@ -223,7 +243,24 @@ readcf(cfname)
                        expand(q, exbuf, &exbuf[sizeof exbuf], e);
                        rwp->r_rhs = prescan(exbuf, '\t', pvpbuf);
                        if (rwp->r_rhs != NULL)
                        expand(q, exbuf, &exbuf[sizeof exbuf], e);
                        rwp->r_rhs = prescan(exbuf, '\t', pvpbuf);
                        if (rwp->r_rhs != NULL)
+                       {
+                               register char **ap;
+
                                rwp->r_rhs = copyplist(rwp->r_rhs, TRUE);
                                rwp->r_rhs = copyplist(rwp->r_rhs, TRUE);
+
+                               /* check no out-of-bounds replacements */
+                               nfuzzy += '0';
+                               for (ap = rwp->r_rhs; *ap != NULL; ap++)
+                               {
+                                       if (**ap != MATCHREPL)
+                                               continue;
+                                       if ((*ap)[1] <= '0' || (*ap)[1] > nfuzzy)
+                                       {
+                                               syserr("replacement $%c out of bounds",
+                                                       (*ap)[1]);
+                                       }
+                               }
+                       }
                        else
                                syserr("R line: null RHS");
                        break;
                        else
                                syserr("R line: null RHS");
                        break;
index 9b94ef9..7044d1f 100644 (file)
@@ -7,7 +7,7 @@
  */
 
 #ifndef lint
  */
 
 #ifndef lint
-static char sccsid[] = "@(#)util.c     6.2 (Berkeley) %G%";
+static char sccsid[] = "@(#)util.c     6.3 (Berkeley) %G%";
 #endif /* not lint */
 
 # include <stdio.h>
 #endif /* not lint */
 
 # include <stdio.h>
@@ -239,21 +239,6 @@ xputs(s)
                printf("<null>");
                return;
        }
                printf("<null>");
                return;
        }
-       c = *s;
-       if (c == MATCHREPL && isdigit(s[1]) && s[2] == '\0')
-       {
-               printf("$%c", s[1]);
-               return;
-       }
-       for (mp = MetaMacros; mp->metaname != NULL; mp++)
-       {
-               if (mp->metaval == c)
-               {
-                       printf("$%c%s", mp->metaname, ++s);
-                       return;
-               }
-       }
-       (void) putchar('"');
        while ((c = *s++) != '\0')
        {
                if (!isascii(c))
        while ((c = *s++) != '\0')
        {
                if (!isascii(c))
@@ -261,36 +246,50 @@ xputs(s)
                        (void) putchar('\\');
                        c &= 0177;
                }
                        (void) putchar('\\');
                        c &= 0177;
                }
-               if (c < 040 || c >= 0177)
+               if (isprint(c))
+               {
+                       putchar(c);
+                       continue;
+               }
+               if (c == MATCHREPL || c == '\001')
+               {
+                       putchar('$');
+                       continue;
+               }
+               for (mp = MetaMacros; mp->metaname != NULL; mp++)
                {
                {
-                       switch (c)
+                       if (mp->metaval == c)
                        {
                        {
-                         case '\n':
-                               c = 'n';
+                               printf("$%c", mp->metaname);
+                               c = '\0';
                                break;
                                break;
+                       }
+               }
 
 
-                         case '\r':
-                               c = 'r';
-                               break;
+               /* wasn't a meta-macro -- find another way to print it */
+               switch (c)
+               {
+                 case '\0':
+                       continue;
 
 
-                         case '\t':
-                               c = 't';
-                               break;
+                 case '\n':
+                       c = 'n';
+                       break;
 
 
-                         case '\001':
-                               (void) putchar('$');
-                               continue;
+                 case '\r':
+                       c = 'r';
+                       break;
 
 
-                         default:
-                               (void) putchar('^');
-                               (void) putchar(c ^ 0100);
-                               continue;
-                       }
-                       (void) putchar('\\');
+                 case '\t':
+                       c = 't';
+                       break;
+
+                 default:
+                       (void) putchar('^');
+                       (void) putchar(c ^ 0100);
+                       continue;
                }
                }
-               (void) putchar(c);
        }
        }
-       (void) putchar('"');
        (void) fflush(stdout);
 }
 \f/*
        (void) fflush(stdout);
 }
 \f/*
index ee11f15..52a75ac 100644 (file)
@@ -7,7 +7,7 @@
  */
 
 #ifndef lint
  */
 
 #ifndef lint
-static char sccsid[] = "@(#)version.c  6.9 (Berkeley) %G%";
+static char sccsid[] = "@(#)version.c  6.10 (Berkeley) %G%";
 #endif /* not lint */
 
 #endif /* not lint */
 
-char   Version[] = "ALPHA-6.9";
+char   Version[] = "ALPHA-6.10";