huge number of changes for 8.2, including IRIX & Solaris portability;
authorEric Allman <eric@ucbvax.Berkeley.EDU>
Sun, 11 Jul 1993 21:53:00 +0000 (13:53 -0800)
committerEric Allman <eric@ucbvax.Berkeley.EDU>
Sun, 11 Jul 1993 21:53:00 +0000 (13:53 -0800)
improved error checking; fix -m flag and add -O flag in maps; fix long
DNS timeouts; relax safefile restrictions; add -X command line flag; etc.

SCCS-vsn: usr.sbin/sendmail/src/READ_ME 8.2
SCCS-vsn: usr.sbin/sendmail/src/usersmtp.c 8.2
SCCS-vsn: usr.sbin/sendmail/src/stats.c 8.2
SCCS-vsn: usr.sbin/sendmail/src/headers.c 8.2
SCCS-vsn: usr.sbin/sendmail/src/recipient.c 8.2
SCCS-vsn: usr.sbin/sendmail/src/main.c 8.2
SCCS-vsn: usr.sbin/sendmail/src/envelope.c 8.2
SCCS-vsn: usr.sbin/sendmail/src/conf.h 8.2
SCCS-vsn: usr.sbin/sendmail/src/parseaddr.c 8.2
SCCS-vsn: usr.sbin/sendmail/src/err.c 8.2
SCCS-vsn: usr.sbin/sendmail/src/sendmail.h 8.2
SCCS-vsn: usr.sbin/sendmail/src/savemail.c 8.2
SCCS-vsn: usr.sbin/sendmail/src/srvrsmtp.c 8.2
SCCS-vsn: usr.sbin/sendmail/src/util.c 8.2
SCCS-vsn: usr.sbin/sendmail/src/deliver.c 8.2
SCCS-vsn: usr.sbin/sendmail/src/queue.c 8.2
SCCS-vsn: usr.sbin/sendmail/src/conf.c 8.2
SCCS-vsn: usr.sbin/sendmail/src/alias.c 8.2
SCCS-vsn: usr.sbin/sendmail/src/map.c 8.2
SCCS-vsn: usr.sbin/sendmail/src/mci.c 8.2
SCCS-vsn: usr.sbin/sendmail/src/TRACEFLAGS 8.2

21 files changed:
usr/src/usr.sbin/sendmail/src/READ_ME
usr/src/usr.sbin/sendmail/src/TRACEFLAGS
usr/src/usr.sbin/sendmail/src/alias.c
usr/src/usr.sbin/sendmail/src/conf.c
usr/src/usr.sbin/sendmail/src/conf.h
usr/src/usr.sbin/sendmail/src/deliver.c
usr/src/usr.sbin/sendmail/src/envelope.c
usr/src/usr.sbin/sendmail/src/err.c
usr/src/usr.sbin/sendmail/src/headers.c
usr/src/usr.sbin/sendmail/src/main.c
usr/src/usr.sbin/sendmail/src/map.c
usr/src/usr.sbin/sendmail/src/mci.c
usr/src/usr.sbin/sendmail/src/parseaddr.c
usr/src/usr.sbin/sendmail/src/queue.c
usr/src/usr.sbin/sendmail/src/recipient.c
usr/src/usr.sbin/sendmail/src/savemail.c
usr/src/usr.sbin/sendmail/src/sendmail.h
usr/src/usr.sbin/sendmail/src/srvrsmtp.c
usr/src/usr.sbin/sendmail/src/stats.c
usr/src/usr.sbin/sendmail/src/usersmtp.c
usr/src/usr.sbin/sendmail/src/util.c

index c7d07d7..f80d571 100644 (file)
@@ -4,7 +4,7 @@
 #
 # %sccs.include.redist.sh%
 #
 #
 # %sccs.include.redist.sh%
 #
-#      @(#)READ_ME     8.1 (Berkeley) %G%
+#      @(#)READ_ME     8.2 (Berkeley) %G%
 #
 
 This directory contains the source files for sendmail.
 #
 
 This directory contains the source files for sendmail.
@@ -34,7 +34,8 @@ symbols availble, requiring the following compilation flags in the
 Makefile:
 
 SOLARIS                Define this if you are running Solaris 2.0 or higher.
 Makefile:
 
 SOLARIS                Define this if you are running Solaris 2.0 or higher.
-NeXT           Define this if you are on a NeXT box.
+__NeXT__       Define this if you are on a NeXT box.  (This one may
+               be pre-defined for you.)
 _AIX3          Define this if you are IBM AIX 3.x.
 
 If you are a system that sendmail has already been ported to, you
 _AIX3          Define this if you are IBM AIX 3.x.
 
 If you are a system that sendmail has already been ported to, you
@@ -62,6 +63,9 @@ HASUSTAT      Define this if you have the ustat(2) system call.  It's
 HASSETSID      Define this if you have the setsid(2) system call.  This
                is implied if your system appears to be POSIX compliant.
 HASINITGROUPS  Define this if you have the initgroups(3) routine.
 HASSETSID      Define this if you have the setsid(2) system call.  This
                is implied if your system appears to be POSIX compliant.
 HASINITGROUPS  Define this if you have the initgroups(3) routine.
+HASSETVBUF     Define this if you have the setvbuf(3) library call.
+               If you don't, setlinebuf will be used instead.  This
+               defaults on if your compiler defines __STDC__.
 LA_TYPE                The type of load average your kernel supports.  These
                can be LA_SUBR (4) if you have the getloadavg(3) routine,
                LA_FLOAT (3) if you read kmem and interpret the value
 LA_TYPE                The type of load average your kernel supports.  These
                can be LA_SUBR (4) if you have the getloadavg(3) routine,
                LA_FLOAT (3) if you read kmem and interpret the value
@@ -129,6 +133,9 @@ files fail in bizarre ways and you will open up several security holes.
 
 If you are compiling on OSF/1 (DEC Alpha), you must use -lmld.
 
 
 If you are compiling on OSF/1 (DEC Alpha), you must use -lmld.
 
+If you are compiling on NeXT, you will have to create an empty file
+"unistd.h".
+
 If you use both -DNDBM and -DNEWDB, you must delete the module ndbm.o
 from libdb.a and delete the file "ndbm.h" from the files that get
 installed (that is, use the OLD ndbm.h, not the new ndbm.h).  This
 If you use both -DNDBM and -DNEWDB, you must delete the module ndbm.o
 from libdb.a and delete the file "ndbm.h" from the files that get
 installed (that is, use the OLD ndbm.h, not the new ndbm.h).  This
@@ -197,4 +204,4 @@ version.c   The version number and information about this
 
 Eric Allman
 
 
 Eric Allman
 
-(Version 8.1, last update %G% 10:27:15)
+(Version 8.2, last update %G% 06:52:16)
index e6514ac..3fd00b7 100644 (file)
@@ -21,8 +21,7 @@
 16     daemon.c        makeconnection
 17     deliver.c       hostsignature
 17     domain.c        mxrand
 16     daemon.c        makeconnection
 17     deliver.c       hostsignature
 17     domain.c        mxrand
-17     usersmtp.c      smtpinit, smtpmailfrom
-18     usersmtp.c      reply, smtpmessage
+18     usersmtp.c      reply, smtpmessage, smtpinit, smtpmailfrom
 19     srvrsmtp.c      smtp
 20     parseaddr.c     parseaddr
 21     parseaddr.c     rewrite
 19     srvrsmtp.c      smtp
 20     parseaddr.c     parseaddr
 21     parseaddr.c     rewrite
index 1dbd044..b53f8d5 100644 (file)
@@ -11,7 +11,7 @@
 # include <pwd.h>
 
 #ifndef lint
 # include <pwd.h>
 
 #ifndef lint
-static char sccsid[] = "@(#)alias.c    8.1 (Berkeley) %G%";
+static char sccsid[] = "@(#)alias.c    8.2 (Berkeley) %G%";
 #endif /* not lint */
 
 
 #endif /* not lint */
 
 
@@ -670,6 +670,10 @@ forward(user, sendq, e)
 {
        char *pp;
        char *ep;
 {
        char *pp;
        char *ep;
+#ifdef _POSIX_SAVED_IDS
+       register ADDRESS *ca;
+       uid_t saveduid, uid;
+#endif
 
        if (tTd(27, 1))
                printf("forward(%s)\n", user->q_paddr);
 
        if (tTd(27, 1))
                printf("forward(%s)\n", user->q_paddr);
@@ -689,6 +693,14 @@ forward(user, sendq, e)
        if (ForwardPath == NULL)
                ForwardPath = newstr("\201z/.forward");
 
        if (ForwardPath == NULL)
                ForwardPath = newstr("\201z/.forward");
 
+#ifdef _POSIX_SAVED_IDS
+       ca = getctladdr(user);
+       if (ca != NULL)
+               uid = ca->q_uid;
+       else
+               uid = DefUid;
+#endif
+
        for (pp = ForwardPath; pp != NULL; pp = ep)
        {
                int err;
        for (pp = ForwardPath; pp != NULL; pp = ep)
        {
                int err;
@@ -702,7 +714,20 @@ forward(user, sendq, e)
                        *ep++ = ':';
                if (tTd(27, 3))
                        printf("forward: trying %s\n", buf);
                        *ep++ = ':';
                if (tTd(27, 3))
                        printf("forward: trying %s\n", buf);
+
+#ifdef _POSIX_SAVED_IDS
+               saveduid = geteuid();
+               if (saveduid == 0 && uid != 0)
+                       (void) seteuid(uid);
+#endif                   
+
                err = include(buf, TRUE, user, sendq, e);
                err = include(buf, TRUE, user, sendq, e);
+
+#ifdef _POSIX_SAVED_IDS
+               if (saveduid == 0 && uid != 0)
+                       (void) seteuid(saveduid);
+#endif
+
                if (err == 0)
                        break;
                if (transienterror(err))
                if (err == 0)
                        break;
                if (transienterror(err))
index 507605b..0821b4e 100644 (file)
@@ -7,7 +7,7 @@
  */
 
 #ifndef lint
  */
 
 #ifndef lint
-static char sccsid[] = "@(#)conf.c     8.1 (Berkeley) %G%";
+static char sccsid[] = "@(#)conf.c     8.2 (Berkeley) %G%";
 #endif /* not lint */
 
 # include <sys/ioctl.h>
 #endif /* not lint */
 
 # include <sys/ioctl.h>
@@ -91,7 +91,7 @@ struct hdrinfo        HdrInfo[] =
 
                /* miscellaneous fields */
        "comments",             H_FORCE,
 
                /* miscellaneous fields */
        "comments",             H_FORCE,
-       "return-path",          H_ACHECK,
+       "return-path",          H_FORCE|H_ACHECK,
 
        NULL,                   0,
 };
 
        NULL,                   0,
 };
@@ -573,6 +573,9 @@ rlsesigs()
 #    define LA_TYPE            LA_FLOAT
 #    define LA_AVENRUN         "avenrun"
 #  endif
 #    define LA_TYPE            LA_FLOAT
 #    define LA_AVENRUN         "avenrun"
 #  endif
+#  if defined(__NeXT__)
+#    define LA_TYPE            LA_ZERO
+#  endif
 
 /* now do the guesses based on general OS type */
 #  ifndef LA_TYPE
 
 /* now do the guesses based on general OS type */
 #  ifndef LA_TYPE
@@ -606,6 +609,10 @@ rlsesigs()
      /* powerful RISC/os */
 #    define _PATH_UNIX         "/unix"
 #  endif
      /* powerful RISC/os */
 #    define _PATH_UNIX         "/unix"
 #  endif
+#  if defined(Solaris2)
+     /* Solaris 2 */
+#    define _PATH_UNIX         "/kernel/unix"
+#  endif
 #  if defined(SYSTEM5)
 #    ifndef _PATH_UNIX
 #      define _PATH_UNIX       "/unix"
 #  if defined(SYSTEM5)
 #    ifndef _PATH_UNIX
 #      define _PATH_UNIX       "/unix"
@@ -902,7 +909,7 @@ setproctitle(fmt, va_alist)
 void
 reapchild()
 {
 void
 reapchild()
 {
-# ifdef WIFEXITED
+# if defined(WIFEXITED) && !defined(__NeXT__)
        auto int status;
        int count;
        int pid;
        auto int status;
        int count;
        int pid;
@@ -921,7 +928,7 @@ reapchild()
 # ifdef WNOHANG
        union wait status;
 
 # ifdef WNOHANG
        union wait status;
 
-       while (wait3((int *)&status, WNOHANG, (struct rusage *) NULL) > 0)
+       while (wait3(&status, WNOHANG, (struct rusage *) NULL) > 0)
                continue;
 # else /* WNOHANG */
        auto int status;
                continue;
 # else /* WNOHANG */
        auto int status;
@@ -1093,10 +1100,13 @@ initgroups(name, basegid)
 
 #ifndef HASSETSID
 
 
 #ifndef HASSETSID
 
-setsid()
+pid_t
+setsid __P ((void))
 {
 # ifdef SYSTEM5
 {
 # ifdef SYSTEM5
-       setpgrp();
+       return setpgrp();
+# else
+       return 0;
 # endif
 }
 
 # endif
 }
 
index f948a62..6d34c69 100644 (file)
@@ -5,7 +5,7 @@
  *
  * %sccs.include.redist.c%
  *
  *
  * %sccs.include.redist.c%
  *
- *     @(#)conf.h      8.1 (Berkeley) %G%
+ *     @(#)conf.h      8.2 (Berkeley) %G%
  */
 
 /*
  */
 
 /*
@@ -53,6 +53,7 @@
 # define SETPROCTITLE  1       /* munge argv to display current status */
 # define NAMED_BIND    1       /* use Berkeley Internet Domain Server */
 # define MATCHGECOS    1       /* match user names from gecos field */
 # define SETPROCTITLE  1       /* munge argv to display current status */
 # define NAMED_BIND    1       /* use Berkeley Internet Domain Server */
 # define MATCHGECOS    1       /* match user names from gecos field */
+# define XDEBUG                1       /* enable extended debugging */
 
 # ifdef NEWDB
 # define USERDB                1       /* look in user database (requires NEWDB) */
 
 # ifdef NEWDB
 # define USERDB                1       /* look in user database (requires NEWDB) */
 **     change these.
 */
 
 **     change these.
 */
 
+#ifdef __STDC__
+# define HASSETVBUF    1       /* yes, we have setvbuf in libc */
+#endif
+
 /* HP-UX -- tested for 8.07 */
 # ifdef __hpux
 # define SYSTEM5       1
 # define UNSETENV      1       /* need unsetenv(3) support */
 /* HP-UX -- tested for 8.07 */
 # ifdef __hpux
 # define SYSTEM5       1
 # define UNSETENV      1       /* need unsetenv(3) support */
+# define seteuid       setuid
+# define HASSETVBUF            /* we have setvbuf in libc (but not __STDC__) */
 # endif
 
 /* IBM AIX 3.x -- actually tested for 3.2.3 */
 # endif
 
 /* IBM AIX 3.x -- actually tested for 3.2.3 */
 # define LOCKF         1       /* use System V lockf instead of flock */
 # define FORK          fork    /* no vfork primitive available */
 # define UNSETENV      1       /* need unsetenv(3) support */
 # define LOCKF         1       /* use System V lockf instead of flock */
 # define FORK          fork    /* no vfork primitive available */
 # define UNSETENV      1       /* need unsetenv(3) support */
+# define SYS5TZ                1       /* use System V style timezones */
+# endif
+
+/* Silicon Graphics IRIX */
+# ifdef IRIX
+# define FORK          fork    /* no vfork primitive available */
+# define UNSETENV      1       /* need unsetenv(3) support */
+# define setpgrp       BSDsetpgrp
 # endif
 
 /* general System V defines */
 # endif
 
 /* general System V defines */
 # define HASSETSID     1       /* has setsid(2) call */
 #endif
 
 # define HASSETSID     1       /* has setsid(2) call */
 #endif
 
-#ifdef NeXT
-# define       sleep   sleepX
+#ifdef __NeXT__
+# define sleep         sleepX
+# define UNSETENV      1       /* need unsetenv(3) support */
 #endif
 
 #ifdef BSD4_4
 # include <sys/cdefs.h>
 #endif
 
 #ifdef BSD4_4
 # include <sys/cdefs.h>
+# ifndef _POSIX_SAVED_IDS
+#  define _POSIX_SAVED_IDS     /* safe because we actually use seteuid */
+# endif
 #endif
 
 /*
 #endif
 
 /*
index cde34c5..c182e2d 100644 (file)
@@ -7,7 +7,7 @@
  */
 
 #ifndef lint
  */
 
 #ifndef lint
-static char sccsid[] = "@(#)deliver.c  8.1 (Berkeley) %G%";
+static char sccsid[] = "@(#)deliver.c  8.2 (Berkeley) %G%";
 #endif /* not lint */
 
 #include "sendmail.h"
 #endif /* not lint */
 
 #include "sendmail.h"
@@ -17,6 +17,8 @@ static char sccsid[] = "@(#)deliver.c 8.1 (Berkeley) %G%";
 #ifdef NAMED_BIND
 #include <arpa/nameser.h>
 #include <resolv.h>
 #ifdef NAMED_BIND
 #include <arpa/nameser.h>
 #include <resolv.h>
+
+extern int     h_errno;
 #endif
 
 /*
 #endif
 
 /*
@@ -1009,10 +1011,16 @@ tryhost:
                                bitnset(M_SECURE_PORT, m->m_flags));
                        mci->mci_exitstat = i;
                        mci->mci_errno = errno;
                                bitnset(M_SECURE_PORT, m->m_flags));
                        mci->mci_exitstat = i;
                        mci->mci_errno = errno;
+#ifdef NAMED_BIND
+                       mci->mci_herrno = h_errno;
+#endif
                        if (i == EX_OK)
                        {
                                mci->mci_state = MCIS_OPENING;
                                mci_cache(mci);
                        if (i == EX_OK)
                        {
                                mci->mci_state = MCIS_OPENING;
                                mci_cache(mci);
+                               if (TrafficLogFile != NULL)
+                                       fprintf(TrafficLogFile, "%05d == CONNECT %s\n",
+                                               getpid(), hostbuf);
                                break;
                        }
                        else if (tTd(11, 1))
                                break;
                        }
                        else if (tTd(11, 1))
@@ -1033,26 +1041,22 @@ tryhost:
        }
        else
        {
        }
        else
        {
-               int i;
-               struct stat stbuf;
+#ifdef XDEBUG
+               char wbuf[MAXLINE];
 
                /* make absolutely certain 0, 1, and 2 are in use */
 
                /* make absolutely certain 0, 1, and 2 are in use */
-               for (i = 0; i < 3; i++)
+               sprintf(wbuf, "%s... openmailer(%s)", e->e_to, m->m_name);
+               checkfd012(wbuf);
+#endif
+
+               if (TrafficLogFile != NULL)
                {
                {
-                       if (fstat(i, &stbuf) < 0)
-                       {
-                               /* oops.... */
-                               int fd;
+                       char **av;
 
 
-                               syserr("%s... openmailer(%s): fd %d not open",
-                                       e->e_to, m->m_name, i);
-                               fd = open("/dev/null", O_RDONLY, 0666);
-                               if (fd != i)
-                               {
-                                       (void) dup2(fd, i);
-                                       (void) close(fd);
-                               }
-                       }
+                       fprintf(TrafficLogFile, "%05d === EXEC", getpid());
+                       for (av = pv; *av != NULL; av++)
+                               fprintf(TrafficLogFile, " %s", *av);
+                       fprintf(TrafficLogFile, "\n");
                }
 
                /* create a pipe to shove the mail through */
                }
 
                /* create a pipe to shove the mail through */
@@ -1278,6 +1282,9 @@ tryhost:
                /* couldn't open the mailer */
                rcode = mci->mci_exitstat;
                errno = mci->mci_errno;
                /* couldn't open the mailer */
                rcode = mci->mci_exitstat;
                errno = mci->mci_errno;
+#ifdef NAMED_BIND
+               h_errno = mci->mci_herrno;
+#endif
                if (rcode == EX_OK)
                {
                        /* shouldn't happen */
                if (rcode == EX_OK)
                {
                        /* shouldn't happen */
@@ -1434,49 +1441,10 @@ markfailure(e, q, rcode)
 
        if (rcode == EX_OK)
                return;
 
        if (rcode == EX_OK)
                return;
-       else if (rcode != EX_TEMPFAIL && rcode != EX_IOERR && rcode != EX_OSERR)
-               q->q_flags |= QBADADDR;
-       else if (curtime() > e->e_ctime + TimeOuts.to_q_return)
-       {
-               if (!bitset(EF_TIMEOUT, e->e_flags))
-               {
-                       (void) sprintf(buf, "Cannot send message for %s",
-                               pintvl(TimeOuts.to_q_return, FALSE));
-                       if (e->e_message != NULL)
-                               free(e->e_message);
-                       e->e_message = newstr(buf);
-                       message(buf);
-               }
-               q->q_flags |= QBADADDR;
-               e->e_flags |= EF_TIMEOUT;
-               fprintf(e->e_xfp, "421 %s... Message timed out\n", q->q_paddr);
-       }
-       else
-       {
+       else if (rcode == EX_TEMPFAIL)
                q->q_flags |= QQUEUEUP;
                q->q_flags |= QQUEUEUP;
-               if (TimeOuts.to_q_warning > 0 &&
-                   curtime() > e->e_ctime + TimeOuts.to_q_warning)
-               {
-                       if (!bitset(EF_WARNING, e->e_flags) &&
-                           e->e_class >= 0 &&
-                           strcmp(e->e_from.q_paddr, "<>") != 0)
-                       {
-                               (void) sprintf(buf,
-                                       "warning: cannot send message for %s",
-                                       pintvl(TimeOuts.to_q_warning, FALSE));
-                               if (e->e_message != NULL)
-                                       free(e->e_message);
-                               e->e_message = newstr(buf);
-                               message(buf);
-                               e->e_flags |= EF_WARNING|EF_TIMEOUT;
-                       }
-                       fprintf(e->e_xfp,
-                               "%s... Warning: message still undelivered after %s\n",
-                               q->q_paddr, pintvl(TimeOuts.to_q_warning, FALSE));
-                       fprintf(e->e_xfp, "Will keep trying until message is %s old\n",
-                               pintvl(TimeOuts.to_q_return, FALSE));
-               }
-       }
+       else if (rcode != EX_IOERR && rcode != EX_OSERR)
+               q->q_flags |= QBADADDR;
 }
 \f/*
 **  ENDMAILER -- Wait for mailer to terminate.
 }
 \f/*
 **  ENDMAILER -- Wait for mailer to terminate.
@@ -1580,9 +1548,6 @@ giveresponse(stat, m, mci, e)
        extern char *SysExMsg[];
        register int i;
        extern int N_SysEx;
        extern char *SysExMsg[];
        register int i;
        extern int N_SysEx;
-#ifdef NAMED_BIND
-       extern int h_errno;
-#endif
        char buf[MAXLINE];
 
        /*
        char buf[MAXLINE];
 
        /*
@@ -1634,6 +1599,14 @@ giveresponse(stat, m, mci, e)
                }
                statmsg = buf;
        }
                }
                statmsg = buf;
        }
+#ifdef NAMED_BIND
+       else if (stat == EX_NOHOST && h_errno != 0)
+       {
+               statmsg = errstring(h_errno + MAX_ERRNO);
+               (void) sprintf(buf, "%s (%s)", SysExMsg[i], statmsg);
+               statmsg = buf;
+       }
+#endif
        else
        {
                statmsg = SysExMsg[i];
        else
        {
                statmsg = SysExMsg[i];
@@ -1919,6 +1892,9 @@ mailfile(filename, ctladdr, e)
                printaddr(ctladdr, FALSE);
        }
 
                printaddr(ctladdr, FALSE);
        }
 
+       if (e->e_xfp != NULL)
+               fflush(e->e_xfp);
+
        /*
        **  Fork so we can change permissions here.
        **      Note that we MUST use fork, not vfork, because of
        /*
        **  Fork so we can change permissions here.
        **      Note that we MUST use fork, not vfork, because of
@@ -2122,6 +2098,9 @@ hostsignature(m, host, e)
                        mci = mci_get(hp, m);
                        mci->mci_exitstat = rcode;
                        mci->mci_errno = errno;
                        mci = mci_get(hp, m);
                        mci->mci_exitstat = rcode;
                        mci->mci_errno = errno;
+#ifdef NAMED_BIND
+                       mci->mci_herrno = h_errno;
+#endif
 
                        /* and return the original host name as the signature */
                        nmx = 1;
 
                        /* and return the original host name as the signature */
                        nmx = 1;
index 3976af4..32716bb 100644 (file)
@@ -7,7 +7,7 @@
  */
 
 #ifndef lint
  */
 
 #ifndef lint
-static char sccsid[] = "@(#)envelope.c 8.1 (Berkeley) %G%";
+static char sccsid[] = "@(#)envelope.c 8.2 (Berkeley) %G%";
 #endif /* not lint */
 
 #include "sendmail.h"
 #endif /* not lint */
 
 #include "sendmail.h"
@@ -77,12 +77,18 @@ dropenvelope(e)
        bool queueit = FALSE;
        register ADDRESS *q;
        char *id = e->e_id;
        bool queueit = FALSE;
        register ADDRESS *q;
        char *id = e->e_id;
+       char buf[MAXLINE];
 
        if (tTd(50, 1))
        {
                printf("dropenvelope %x: id=", e);
                xputs(e->e_id);
                printf(", flags=%o\n", e->e_flags);
 
        if (tTd(50, 1))
        {
                printf("dropenvelope %x: id=", e);
                xputs(e->e_id);
                printf(", flags=%o\n", e->e_flags);
+               if (tTd(50, 10))
+               {
+                       printf("sendq=");
+                       printaddr(e->e_sendqueue, TRUE);
+               }
        }
 
        /* we must have an id to remove disk files */
        }
 
        /* we must have an id to remove disk files */
@@ -95,6 +101,9 @@ dropenvelope(e)
                                  id, e->e_flags, getpid());
 #endif /* LOG */
 
                                  id, e->e_flags, getpid());
 #endif /* LOG */
 
+       /* post statistics */
+       poststats(StatFile);
+
        /*
        **  Extract state information from dregs of send list.
        */
        /*
        **  Extract state information from dregs of send list.
        */
@@ -105,6 +114,49 @@ dropenvelope(e)
                        queueit = TRUE;
        }
 
                        queueit = TRUE;
        }
 
+       /*
+       **  See if the message timed out.
+       */
+
+       if (!queueit)
+               /* nothing to do */ ;
+       else if (curtime() > e->e_ctime + TimeOuts.to_q_return)
+       {
+               if (!bitset(EF_TIMEOUT, e->e_flags))
+               {
+                       (void) sprintf(buf, "Cannot send message for %s",
+                               pintvl(TimeOuts.to_q_return, FALSE));
+                       if (e->e_message != NULL)
+                               free(e->e_message);
+                       e->e_message = newstr(buf);
+                       message(buf);
+               }
+               e->e_flags |= EF_TIMEOUT|EF_CLRQUEUE;
+               fprintf(e->e_xfp, "421 Message timed out\n");
+       }
+       else if (TimeOuts.to_q_warning > 0 &&
+           curtime() > e->e_ctime + TimeOuts.to_q_warning)
+       {
+               if (!bitset(EF_WARNING|EF_RESPONSE, e->e_flags) &&
+                   e->e_class >= 0 &&
+                   strcmp(e->e_from.q_paddr, "<>") != 0)
+               {
+                       (void) sprintf(buf,
+                               "warning: cannot send message for %s",
+                               pintvl(TimeOuts.to_q_warning, FALSE));
+                       if (e->e_message != NULL)
+                               free(e->e_message);
+                       e->e_message = newstr(buf);
+                       message(buf);
+                       e->e_flags |= EF_WARNING|EF_TIMEOUT;
+               }
+               fprintf(e->e_xfp,
+                       "Warning: message still undelivered after %s\n",
+                       pintvl(TimeOuts.to_q_warning, FALSE));
+               fprintf(e->e_xfp, "Will keep trying until message is %s old\n",
+                       pintvl(TimeOuts.to_q_return, FALSE));
+       }
+
        /*
        **  Send back return receipts as requested.
        */
        /*
        **  Send back return receipts as requested.
        */
@@ -132,6 +184,8 @@ dropenvelope(e)
        if ((!queueit && !bitset(EF_KEEPQUEUE, e->e_flags)) ||
            bitset(EF_CLRQUEUE, e->e_flags))
        {
        if ((!queueit && !bitset(EF_KEEPQUEUE, e->e_flags)) ||
            bitset(EF_CLRQUEUE, e->e_flags))
        {
+               if (tTd(50, 2))
+                       printf("Dropping envelope\n");
                if (e->e_df != NULL)
                        xunlink(e->e_df);
                xunlink(queuename(e, 'q'));
                if (e->e_df != NULL)
                        xunlink(e->e_df);
                xunlink(queuename(e, 'q'));
@@ -365,9 +419,13 @@ openxscript(e)
        p = queuename(e, 'x');
        fd = open(p, O_WRONLY|O_CREAT|O_APPEND, 0644);
        if (fd < 0)
        p = queuename(e, 'x');
        fd = open(p, O_WRONLY|O_CREAT|O_APPEND, 0644);
        if (fd < 0)
-               syserr("Can't create %s", p);
-       else
-               e->e_xfp = fdopen(fd, "w");
+       {
+               syserr("Can't create transcript file %s", p);
+               fd = open("/dev/null", O_WRONLY, 0644);
+               if (fd < 0)
+                       syserr("!Can't open /dev/null");
+       }
+       e->e_xfp = fdopen(fd, "w");
 }
 \f/*
 **  CLOSEXSCRIPT -- close the transcript file.
 }
 \f/*
 **  CLOSEXSCRIPT -- close the transcript file.
index 0174823..a8c4621 100644 (file)
@@ -7,7 +7,7 @@
  */
 
 #ifndef lint
  */
 
 #ifndef lint
-static char sccsid[] = "@(#)err.c      8.1 (Berkeley) %G%";
+static char sccsid[] = "@(#)err.c      8.2 (Berkeley) %G%";
 #endif /* not lint */
 
 # include "sendmail.h"
 #endif /* not lint */
 
 # include "sendmail.h"
@@ -180,7 +180,7 @@ message(msg, va_alist)
        VA_START(msg);
        fmtmsg(MsgBuf, CurEnv->e_to, "050", 0, msg, ap);
        VA_END;
        VA_START(msg);
        fmtmsg(MsgBuf, CurEnv->e_to, "050", 0, msg, ap);
        VA_END;
-       putmsg(MsgBuf, FALSE);
+       putoutmsg(MsgBuf, FALSE);
 }
 \f/*
 **  NMESSAGE -- print message (not necessarily an error)
 }
 \f/*
 **  NMESSAGE -- print message (not necessarily an error)
@@ -216,10 +216,10 @@ nmessage(msg, va_alist)
        VA_START(msg);
        fmtmsg(MsgBuf, (char *) NULL, "050", 0, msg, ap);
        VA_END;
        VA_START(msg);
        fmtmsg(MsgBuf, (char *) NULL, "050", 0, msg, ap);
        VA_END;
-       putmsg(MsgBuf, FALSE);
+       putoutmsg(MsgBuf, FALSE);
 }
 \f/*
 }
 \f/*
-**  PUTMSG -- output error message to transcript and channel
+**  PUTOUTMSG -- output error message to transcript and channel
 **
 **     Parameters:
 **             msg -- message to output (in SMTP format).
 **
 **     Parameters:
 **             msg -- message to output (in SMTP format).
@@ -235,7 +235,7 @@ nmessage(msg, va_alist)
 **             Deletes SMTP reply code number as appropriate.
 */
 
 **             Deletes SMTP reply code number as appropriate.
 */
 
-putmsg(msg, holdmsg)
+putoutmsg(msg, holdmsg)
        char *msg;
        bool holdmsg;
 {
        char *msg;
        bool holdmsg;
 {
@@ -252,6 +252,9 @@ putmsg(msg, holdmsg)
                fprintf(OutChannel, "%s\r\n", msg);
        else
                fprintf(OutChannel, "%s\n", &msg[4]);
                fprintf(OutChannel, "%s\r\n", msg);
        else
                fprintf(OutChannel, "%s\n", &msg[4]);
+       if (TrafficLogFile != NULL)
+               fprintf(TrafficLogFile, "%05d >>> %s\n", getpid(),
+                       OpMode == MD_SMTP ? msg : &msg[4]);
        if (msg[3] == ' ')
                (void) fflush(OutChannel);
        if (!ferror(OutChannel))
        if (msg[3] == ' ')
                (void) fflush(OutChannel);
        if (!ferror(OutChannel))
@@ -266,13 +269,13 @@ putmsg(msg, holdmsg)
 #ifdef LOG
        if (LogLevel > 0)
                syslog(LOG_CRIT,
 #ifdef LOG
        if (LogLevel > 0)
                syslog(LOG_CRIT,
-                       "%s: SYSERR: putmsg (%s): error on output channel sending \"%s\"",
+                       "%s: SYSERR: putoutmsg (%s): error on output channel sending \"%s\"",
                        CurEnv->e_id == NULL ? "NOQUEUE" : CurEnv->e_id,
                        CurHostName, msg);
 #endif
 }
 \f/*
                        CurEnv->e_id == NULL ? "NOQUEUE" : CurEnv->e_id,
                        CurHostName, msg);
 #endif
 }
 \f/*
-**  PUTERRMSG -- like putmsg, but does special processing for error messages
+**  PUTERRMSG -- like putoutmsg, but does special processing for error messages
 **
 **     Parameters:
 **             msg -- the message to output.
 **
 **     Parameters:
 **             msg -- the message to output.
@@ -288,7 +291,7 @@ puterrmsg(msg)
        char *msg;
 {
        /* output the message as usual */
        char *msg;
 {
        /* output the message as usual */
-       putmsg(msg, HoldErrs);
+       putoutmsg(msg, HoldErrs);
 
        /* signal the error */
        Errors++;
 
        /* signal the error */
        Errors++;
index f7bf1a6..bc7b572 100644 (file)
@@ -7,7 +7,7 @@
  */
 
 #ifndef lint
  */
 
 #ifndef lint
-static char sccsid[] = "@(#)headers.c  8.1 (Berkeley) %G%";
+static char sccsid[] = "@(#)headers.c  8.2 (Berkeley) %G%";
 #endif /* not lint */
 
 # include <errno.h>
 #endif /* not lint */
 
 # include <errno.h>
@@ -107,8 +107,14 @@ chompheader(line, def, e)
                p += 7;
        if (!def && !bitset(EF_QUEUERUN, e->e_flags) && strcasecmp(fname, p) == 0)
        {
                p += 7;
        if (!def && !bitset(EF_QUEUERUN, e->e_flags) && strcasecmp(fname, p) == 0)
        {
+               if (tTd(31, 2))
+               {
+                       printf("comparing header from (%s) against default (%s or %s)\n",
+                               fvalue, e->e_from.q_paddr, e->e_from.q_user);
+               }
                if (e->e_from.q_paddr != NULL &&
                if (e->e_from.q_paddr != NULL &&
-                   strcmp(fvalue, e->e_from.q_paddr) == 0)
+                   (strcmp(fvalue, e->e_from.q_paddr) == 0 ||
+                    strcmp(fvalue, e->e_from.q_user) == 0))
                        return (hi->hi_flags);
        }
 
                        return (hi->hi_flags);
        }
 
index d13c01e..1df525b 100644 (file)
@@ -13,7 +13,7 @@ static char copyright[] =
 #endif /* not lint */
 
 #ifndef lint
 #endif /* not lint */
 
 #ifndef lint
-static char sccsid[] = "@(#)main.c     8.1 (Berkeley) %G%";
+static char sccsid[] = "@(#)main.c     8.2 (Berkeley) %G%";
 #endif /* not lint */
 
 #define        _DEFINE
 #endif /* not lint */
 
 #define        _DEFINE
@@ -220,10 +220,10 @@ main(argc, argv, envp)
        **      to the run that froze the configuration.
        */
        nothaw = FALSE;
        **      to the run that froze the configuration.
        */
        nothaw = FALSE;
-#ifdef __osf__
-#define OPTIONS                "B:b:C:cd:e:F:f:h:Iimno:p:q:r:sTtvx"
+#if defined(__osf__) || defined(_AIX3)
+#define OPTIONS                "B:b:C:cd:e:F:f:h:Iimno:p:q:r:sTtvX:x"
 #else
 #else
-#define OPTIONS                "B:b:C:cd:e:F:f:h:Iimno:p:q:r:sTtv"
+#define OPTIONS                "B:b:C:cd:e:F:f:h:Iimno:p:q:r:sTtvX:"
 #endif
        while ((j = getopt(argc, argv, OPTIONS)) != EOF)
        {
 #endif
        while ((j = getopt(argc, argv, OPTIONS)) != EOF)
        {
@@ -528,6 +528,21 @@ main(argc, argv, envp)
                        GrabTo = TRUE;
                        break;
 
                        GrabTo = TRUE;
                        break;
 
+                 case 'X':     /* traffic log file */
+                       setuid(getuid());
+                       TrafficLogFile = fopen(optarg, "a");
+                       if (TrafficLogFile == NULL)
+                       {
+                               syserr("cannot open %s", optarg);
+                               break;
+                       }
+#ifdef HASSETVBUF
+                       setvbuf(TrafficLogFile, NULL, _IOLBF, BUFSIZ);
+#else
+                       setlinebuf(TrafficLogFile);
+#endif
+                       break;
+
                        /* compatibility flags */
                  case 'c':     /* connect to non-local mailers */
                  case 'i':     /* don't let dot stop me */
                        /* compatibility flags */
                  case 'c':     /* connect to non-local mailers */
                  case 'i':     /* don't let dot stop me */
@@ -551,8 +566,8 @@ main(argc, argv, envp)
                        break;
 # endif /* DBM */
 
                        break;
 # endif /* DBM */
 
-# ifdef __osf__
-                 case 'x':     /* random flag that DEC OSF/1 mailx passes */
+# if defined(__osf__) || defined(_AIX3)
+                 case 'x':     /* random flag that OSF/1 & AIX mailx passes */
                        break;
 # endif
 
                        break;
 # endif
 
@@ -591,6 +606,8 @@ main(argc, argv, envp)
                syserr("Warning: .cf version level (%d) exceeds program functionality (%d)",
                        ConfigLevel, MAXCONFIGLEVEL);
        }
                syserr("Warning: .cf version level (%d) exceeds program functionality (%d)",
                        ConfigLevel, MAXCONFIGLEVEL);
        }
+
+
 # ifdef QUEUE
        if (queuemode && getuid() != 0)
        {
 # ifdef QUEUE
        if (queuemode && getuid() != 0)
        {
@@ -648,6 +665,11 @@ main(argc, argv, envp)
                setoption('d', "", TRUE, FALSE, CurEnv);
        }
 
                setoption('d', "", TRUE, FALSE, CurEnv);
        }
 
+       if (ConfigLevel < 3)
+       {
+               UseErrorsTo = TRUE;
+       }
+
        /* our name for SMTP codes */
        expand("\201j", jbuf, &jbuf[sizeof jbuf - 1], CurEnv);
        MyHostName = jbuf;
        /* our name for SMTP codes */
        expand("\201j", jbuf, &jbuf[sizeof jbuf - 1], CurEnv);
        MyHostName = jbuf;
@@ -682,11 +704,11 @@ main(argc, argv, envp)
        if (chdir(QueueDir) < 0)
        {
                syserr("cannot chdir(%s)", QueueDir);
        if (chdir(QueueDir) < 0)
        {
                syserr("cannot chdir(%s)", QueueDir);
-               exit(EX_SOFTWARE);
+               ExitStat = EX_SOFTWARE;
        }
 
        /* if we've had errors so far, exit now */
        }
 
        /* if we've had errors so far, exit now */
-       if (ExitStat != EX_OK)
+       if (ExitStat != EX_OK && OpMode != MD_TEST)
                exit(ExitStat);
 
        /*
                exit(ExitStat);
 
        /*
@@ -930,9 +952,9 @@ main(argc, argv, envp)
 # ifdef _POSIX_JOB_CONTROL
        (void) setpgid(0, getpid());
 # else
 # ifdef _POSIX_JOB_CONTROL
        (void) setpgid(0, getpid());
 # else
-# ifndef SYSTEM5
+#  ifndef SYSTEM5
        (void) setpgrp(0, getpid());
        (void) setpgrp(0, getpid());
-# endif
+#  endif
 # endif
 
        initsys(CurEnv);
 # endif
 
        initsys(CurEnv);
@@ -1027,9 +1049,6 @@ finis()
        /* flush any cached connections */
        mci_flush(TRUE, NULL);
 
        /* flush any cached connections */
        mci_flush(TRUE, NULL);
 
-       /* post statistics */
-       poststats(StatFile);
-
 # ifdef XLA
        /* clean up extended load average stuff */
        xla_all_end();
 # ifdef XLA
        /* clean up extended load average stuff */
        xla_all_end();
index bf5268e..120501c 100644 (file)
@@ -7,7 +7,7 @@
  */
 
 #ifndef lint
  */
 
 #ifndef lint
-static char sccsid[] = "@(#)map.c      8.1 (Berkeley) %G%";
+static char sccsid[] = "@(#)map.c      8.2 (Berkeley) %G%";
 #endif /* not lint */
 
 #include "sendmail.h"
 #endif /* not lint */
 
 #include "sendmail.h"
@@ -83,6 +83,7 @@ map_parseargs(map, ap)
 {
        register char *p = ap;
 
 {
        register char *p = ap;
 
+       map->map_mflags |= MF_TRY0NULL | MF_TRY1NULL;
        for (;;)
        {
                while (isascii(*p) && isspace(*p))
        for (;;)
        {
                while (isascii(*p) && isspace(*p))
@@ -93,6 +94,11 @@ map_parseargs(map, ap)
                {
                  case 'N':
                        map->map_mflags |= MF_INCLNULL;
                {
                  case 'N':
                        map->map_mflags |= MF_INCLNULL;
+                       map->map_mflags &= ~MF_TRY0NULL;
+                       break;
+
+                 case 'O':
+                       map->map_mflags &= ~MF_TRY1NULL;
                        break;
 
                  case 'o':
                        break;
 
                  case 'o':
@@ -418,16 +424,28 @@ ndbm_map_lookup(map, name, av, statp)
                makelower(keybuf);
                key.dptr = keybuf;
        }
                makelower(keybuf);
                key.dptr = keybuf;
        }
-       if (bitset(MF_INCLNULL, map->map_mflags))
-               key.dsize++;
        (void) lockfile(dbm_dirfno((DBM *) map->map_db1), map->map_file, LOCK_SH);
        (void) lockfile(dbm_dirfno((DBM *) map->map_db1), map->map_file, LOCK_SH);
-       val = dbm_fetch((DBM *) map->map_db1, key);
+       val.dptr = NULL;
+       if (bitset(MF_TRY0NULL, map->map_mflags))
+       {
+               val = dbm_fetch((DBM *) map->map_db1, key);
+               if (val.dptr != NULL)
+                       map->map_mflags &= ~MF_TRY1NULL;
+       }
+       if (val.dptr == NULL && bitset(MF_TRY1NULL, map->map_mflags))
+       {
+               key.dsize++;
+               val = dbm_fetch((DBM *) map->map_db1, key);
+               if (val.dptr != NULL)
+                       map->map_mflags &= ~MF_TRY0NULL;
+       }
        (void) lockfile(dbm_dirfno((DBM *) map->map_db1), map->map_file, LOCK_UN);
        if (val.dptr == NULL)
                return NULL;
        if (bitset(MF_MATCHONLY, map->map_mflags))
        (void) lockfile(dbm_dirfno((DBM *) map->map_db1), map->map_file, LOCK_UN);
        if (val.dptr == NULL)
                return NULL;
        if (bitset(MF_MATCHONLY, map->map_mflags))
-               av = NULL;
-       return map_rewrite(map, val.dptr, val.dsize, av);
+               return map_rewrite(map, name, strlen(name), NULL);
+       else
+               return map_rewrite(map, val.dptr, val.dsize, av);
 }
 
 
 }
 
 
@@ -667,12 +685,23 @@ db_map_lookup(map, name, av, statp)
        bcopy(name, keybuf, key.size + 1);
        if (!bitset(MF_NOFOLDCASE, map->map_mflags))
                makelower(keybuf);
        bcopy(name, keybuf, key.size + 1);
        if (!bitset(MF_NOFOLDCASE, map->map_mflags))
                makelower(keybuf);
-       if (bitset(MF_INCLNULL, map->map_mflags))
-               key.size++;
 #ifndef OLD_NEWDB
        (void) lockfile(db->fd(db), map->map_file, LOCK_SH);
 #endif
 #ifndef OLD_NEWDB
        (void) lockfile(db->fd(db), map->map_file, LOCK_SH);
 #endif
-       st = db->get(db, &key, &val, 0);
+       st = 1;
+       if (bitset(MF_TRY0NULL, map->map_mflags))
+       {
+               st = db->get(db, &key, &val, 0);
+               if (st == 0)
+                       map->map_mflags &= ~MF_TRY1NULL;
+       }
+       if (st != 0 && bitset(MF_TRY1NULL, map->map_mflags))
+       {
+               key.size++;
+               st = db->get(db, &key, &val, 0);
+               if (st == 0)
+                       map->map_mflags &= ~MF_TRY0NULL;
+       }
        saveerrno = errno;
 #ifndef OLD_NEWDB
        (void) lockfile(db->fd(db), map->map_file, LOCK_UN);
        saveerrno = errno;
 #ifndef OLD_NEWDB
        (void) lockfile(db->fd(db), map->map_file, LOCK_UN);
@@ -685,8 +714,9 @@ db_map_lookup(map, name, av, statp)
                return NULL;
        }
        if (bitset(MF_MATCHONLY, map->map_mflags))
                return NULL;
        }
        if (bitset(MF_MATCHONLY, map->map_mflags))
-               av = NULL;
-       return map_rewrite(map, val.data, val.size, av);
+               return map_rewrite(map, name, strlen(name), NULL);
+       else
+               return map_rewrite(map, val.data, val.size, av);
 }
 
 
 }
 
 
@@ -842,10 +872,22 @@ nis_map_lookup(map, name, av, statp)
        bcopy(name, keybuf, buflen + 1);
        if (!bitset(MF_NOFOLDCASE, map->map_mflags))
                makelower(keybuf);
        bcopy(name, keybuf, buflen + 1);
        if (!bitset(MF_NOFOLDCASE, map->map_mflags))
                makelower(keybuf);
-       if (bitset(MF_INCLNULL, map->map_mflags))
+       yperr = YPERR_KEY;
+       if (bitset(MF_TRY0NULL, map->map_mflags))
+       {
+               yperr = yp_match(map->map_domain, map->map_file, keybuf, buflen,
+                            &vp, &vsize);
+               if (yperr == 0)
+                       map->map_mflags &= ~MF_TRY1NULL;
+       }
+       if (yperr == YPERR_KEY && bitset(MF_TRY1NULL, map->map_mflags))
+       {
                buflen++;
                buflen++;
-       yperr = yp_match(map->map_domain, map->map_file, keybuf, buflen,
-                    &vp, &vsize);
+               yperr = yp_match(map->map_domain, map->map_file, keybuf, buflen,
+                            &vp, &vsize);
+               if (yperr == 0)
+                       map->map_mflags &= ~MF_TRY0NULL;
+       }
        if (yperr != 0)
        {
                if (yperr != YPERR_KEY && yperr != YPERR_BUSY)
        if (yperr != 0)
        {
                if (yperr != YPERR_KEY && yperr != YPERR_BUSY)
@@ -853,8 +895,9 @@ nis_map_lookup(map, name, av, statp)
                return NULL;
        }
        if (bitset(MF_MATCHONLY, map->map_mflags))
                return NULL;
        }
        if (bitset(MF_MATCHONLY, map->map_mflags))
-               av = NULL;
-       return map_rewrite(map, vp, vsize, av);
+               return map_rewrite(map, name, strlen(name), NULL);
+       else
+               return map_rewrite(map, vp, vsize, av);
 }
 
 
 }
 
 
index 1480511..4999cf1 100644 (file)
@@ -7,7 +7,7 @@
  */
 
 #ifndef lint
  */
 
 #ifndef lint
-static char sccsid[] = "@(#)mci.c      8.1 (Berkeley) %G%";
+static char sccsid[] = "@(#)mci.c      8.2 (Berkeley) %G%";
 #endif /* not lint */
 
 #include "sendmail.h"
 #endif /* not lint */
 
 #include "sendmail.h"
@@ -280,10 +280,11 @@ mci_dump(mci)
                printf("NULL\n");
                return;
        }
                printf("NULL\n");
                return;
        }
-       printf("flags=%o, errno=%d, exitstat=%d, state=%d, pid=%d, maxsize=%ld\n",
-               mci->mci_flags, mci->mci_errno, mci->mci_exitstat,
-               mci->mci_state, mci->mci_pid, mci->mci_maxsize);
-       printf("\tphase=%s, mailer=%s,\n",
+       printf("flags=%o, errno=%d, herrno=%d, exitstat=%d, state=%d, pid=%d,\n",
+               mci->mci_flags, mci->mci_errno, mci->mci_herrno,
+               mci->mci_exitstat, mci->mci_state, mci->mci_pid);
+       printf("\tmaxsize=%ld, phase=%s, mailer=%s,\n",
+               mci->mci_maxsize,
                mci->mci_phase == NULL ? "NULL" : mci->mci_phase,
                mci->mci_mailer == NULL ? "NULL" : mci->mci_mailer->m_name);
        printf("\thost=%s, lastuse=%s\n",
                mci->mci_phase == NULL ? "NULL" : mci->mci_phase,
                mci->mci_mailer == NULL ? "NULL" : mci->mci_mailer->m_name);
        printf("\thost=%s, lastuse=%s\n",
index 5bb1dea..83eed1a 100644 (file)
@@ -7,7 +7,7 @@
  */
 
 #ifndef lint
  */
 
 #ifndef lint
-static char sccsid[] = "@(#)parseaddr.c        8.1 (Berkeley) %G%";
+static char sccsid[] = "@(#)parseaddr.c        8.2 (Berkeley) %G%";
 #endif /* not lint */
 
 #include "sendmail.h"
 #endif /* not lint */
 
 #include "sendmail.h"
@@ -142,7 +142,7 @@ parseaddr(addr, a, copyf, delim, delimptr, e)
        if (pvp[0] == NULL || (pvp[0][0] & 0377) != CANONNET)
        {
                setstat(EX_USAGE);
        if (pvp[0] == NULL || (pvp[0][0] & 0377) != CANONNET)
        {
                setstat(EX_USAGE);
-               syserr("554 cannot resolve name");
+               syserr("554 cannot resolve name %s", addr);
                return (NULL);
        }
 
                return (NULL);
        }
 
index 810ecb6..3c8ae20 100644 (file)
@@ -10,9 +10,9 @@
 
 #ifndef lint
 #ifdef QUEUE
 
 #ifndef lint
 #ifdef QUEUE
-static char sccsid[] = "@(#)queue.c    8.1 (Berkeley) %G% (with queueing)";
+static char sccsid[] = "@(#)queue.c    8.2 (Berkeley) %G% (with queueing)";
 #else
 #else
-static char sccsid[] = "@(#)queue.c    8.1 (Berkeley) %G% (without queueing)";
+static char sccsid[] = "@(#)queue.c    8.2 (Berkeley) %G% (without queueing)";
 #endif
 #endif /* not lint */
 
 #endif
 #endif /* not lint */
 
@@ -261,12 +261,17 @@ notemp:
                else if (bitset(H_FROM|H_RCPT, h->h_flags))
                {
                        bool oldstyle = bitset(EF_OLDSTYLE, e->e_flags);
                else if (bitset(H_FROM|H_RCPT, h->h_flags))
                {
                        bool oldstyle = bitset(EF_OLDSTYLE, e->e_flags);
+                       FILE *savetrace = TrafficLogFile;
+
+                       TrafficLogFile = NULL;
 
                        if (bitset(H_FROM, h->h_flags))
                                oldstyle = FALSE;
 
                        commaize(h, h->h_value, tfp, oldstyle,
                                 &nullmailer, e);
 
                        if (bitset(H_FROM, h->h_flags))
                                oldstyle = FALSE;
 
                        commaize(h, h->h_value, tfp, oldstyle,
                                 &nullmailer, e);
+
+                       TrafficLogFile = savetrace;
                }
                else
                        fprintf(tfp, "%s: %s\n", h->h_field, h->h_value);
                }
                else
                        fprintf(tfp, "%s: %s\n", h->h_field, h->h_value);
@@ -926,6 +931,7 @@ readqf(e)
                if (tTd(40, 8))
                        printf("readqf(%s): bogus file\n", qf);
                fclose(qfp);
                if (tTd(40, 8))
                        printf("readqf(%s): bogus file\n", qf);
                fclose(qfp);
+               rename(qf, queuename(e, 'Q'));
                return FALSE;
        }
 
                return FALSE;
        }
 
@@ -1046,7 +1052,9 @@ readqf(e)
                  default:
                        syserr("readqf: bad line \"%s\"", e->e_id,
                                LineNumber, bp);
                  default:
                        syserr("readqf: bad line \"%s\"", e->e_id,
                                LineNumber, bp);
-                       break;
+                       fclose(qfp);
+                       rename(qf, queuename(e, 'Q'));
+                       return FALSE;
                }
 
                if (bp != buf)
                }
 
                if (bp != buf)
index afe30ee..e1fcfae 100644 (file)
@@ -7,7 +7,7 @@
  */
 
 #ifndef lint
  */
 
 #ifndef lint
-static char sccsid[] = "@(#)recipient.c        8.1 (Berkeley) %G%";
+static char sccsid[] = "@(#)recipient.c        8.2 (Berkeley) %G%";
 #endif /* not lint */
 
 # include "sendmail.h"
 #endif /* not lint */
 
 # include "sendmail.h"
@@ -352,7 +352,7 @@ recipient(a, sendq, e)
                        usrerr("550 Cannot mail directly to files");
                }
                else if ((stat(buf, &stb) >= 0) ? (!writable(&stb)) :
                        usrerr("550 Cannot mail directly to files");
                }
                else if ((stat(buf, &stb) >= 0) ? (!writable(&stb)) :
-                   (*p = '\0', safefile(buf, getruid(), S_IWRITE|S_IEXEC) != 0))
+                   (*p = '\0', safefile(buf, getruid(), TRUE, S_IWRITE|S_IEXEC) != 0))
                {
                        a->q_flags |= QBADADDR;
                        giveresponse(EX_CANTCREAT, m, NULL, e);
                {
                        a->q_flags |= QBADADDR;
                        giveresponse(EX_CANTCREAT, m, NULL, e);
@@ -682,7 +682,7 @@ include(fname, forwarding, ctladdr, sendq, e)
        ev = setevent((time_t) 60, includetimeout, 0);
 
        /* the input file must be marked safe */
        ev = setevent((time_t) 60, includetimeout, 0);
 
        /* the input file must be marked safe */
-       if ((ret = safefile(fname, uid, S_IREAD)) != 0)
+       if ((ret = safefile(fname, uid, forwarding, S_IREAD)) != 0)
        {
                /* don't use this .forward file */
                clrevent(ev);
        {
                /* don't use this .forward file */
                clrevent(ev);
index 98d7c00..777348a 100644 (file)
@@ -7,7 +7,7 @@
  */
 
 #ifndef lint
  */
 
 #ifndef lint
-static char sccsid[] = "@(#)savemail.c 8.1 (Berkeley) %G%";
+static char sccsid[] = "@(#)savemail.c 8.2 (Berkeley) %G%";
 #endif /* not lint */
 
 # include <pwd.h>
 #endif /* not lint */
 
 # include <pwd.h>
@@ -488,6 +488,9 @@ returntosender(msg, returnq, sendbody, e)
        define('x', "Mail Delivery Subsystem", ee);
        eatheader(ee, TRUE);
 
        define('x', "Mail Delivery Subsystem", ee);
        eatheader(ee, TRUE);
 
+       /* mark statistics */
+       markstats(ee, (ADDRESS *) NULL);
+
        /* actually deliver the error message */
        sendall(ee, SM_DEFAULT);
 
        /* actually deliver the error message */
        sendall(ee, SM_DEFAULT);
 
index 729fec9..278fadb 100644 (file)
@@ -5,7 +5,7 @@
  *
  * %sccs.include.redist.c%
  *
  *
  * %sccs.include.redist.c%
  *
- *     @(#)sendmail.h  8.1 (Berkeley) %G%
+ *     @(#)sendmail.h  8.2 (Berkeley) %G%
  */
 
 /*
  */
 
 /*
@@ -15,7 +15,7 @@
 # ifdef _DEFINE
 # define EXTERN
 # ifndef lint
 # ifdef _DEFINE
 # define EXTERN
 # ifndef lint
-static char SmailSccsId[] =    "@(#)sendmail.h 8.1             %G%";
+static char SmailSccsId[] =    "@(#)sendmail.h 8.2             %G%";
 # endif
 # else /*  _DEFINE */
 # define EXTERN extern
 # endif
 # else /*  _DEFINE */
 # define EXTERN extern
@@ -419,6 +419,7 @@ 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 */
+       short           mci_herrno;     /* h_errno from last DNS lookup */
        short           mci_exitstat;   /* exit status from last connection */
        short           mci_state;      /* SMTP state */
        long            mci_maxsize;    /* max size this server will accept */
        short           mci_exitstat;   /* exit status from last connection */
        short           mci_state;      /* SMTP state */
        long            mci_maxsize;    /* max size this server will accept */
@@ -509,6 +510,8 @@ MAP
 # define MF_OPEN       0x0020          /* this entry is open */
 # define MF_WRITABLE   0x0040          /* open for writing */
 # define MF_ALIAS      0x0080          /* this is an alias file */
 # define MF_OPEN       0x0020          /* this entry is open */
 # define MF_WRITABLE   0x0040          /* open for writing */
 # define MF_ALIAS      0x0080          /* this is an alias file */
+# define MF_TRY0NULL   0x0100          /* try with no null byte */
+# define MF_TRY1NULL   0x0200          /* try with the null byte */
 # define MF_IMPL_HASH  0x1000          /* implicit: underlying hash database */
 # define MF_IMPL_NDBM  0x2000          /* implicit: underlying NDBM database */
 
 # define MF_IMPL_HASH  0x1000          /* implicit: underlying hash database */
 # define MF_IMPL_NDBM  0x2000          /* implicit: underlying NDBM database */
 
@@ -802,6 +805,7 @@ EXTERN time_t       MciCacheTimeout;        /* maximum idle time on connections */
 EXTERN char    *QueueLimitRecipient;   /* limit queue runs to this recipient */
 EXTERN char    *QueueLimitSender;      /* limit queue runs to this sender */
 EXTERN char    *QueueLimitId;          /* limit queue runs to this id */
 EXTERN char    *QueueLimitRecipient;   /* limit queue runs to this recipient */
 EXTERN char    *QueueLimitSender;      /* limit queue runs to this sender */
 EXTERN char    *QueueLimitId;          /* limit queue runs to this id */
+EXTERN FILE    *TrafficLogFile;        /* file in which to log all traffic */
 
 
 /*
 
 
 /*
index 9d4b810..fd88e06 100644 (file)
@@ -10,9 +10,9 @@
 
 #ifndef lint
 #ifdef SMTP
 
 #ifndef lint
 #ifdef SMTP
-static char sccsid[] = "@(#)srvrsmtp.c 8.1 (Berkeley) %G% (with SMTP)";
+static char sccsid[] = "@(#)srvrsmtp.c 8.2 (Berkeley) %G% (with SMTP)";
 #else
 #else
-static char sccsid[] = "@(#)srvrsmtp.c 8.1 (Berkeley) %G% (without SMTP)";
+static char sccsid[] = "@(#)srvrsmtp.c 8.2 (Berkeley) %G% (without SMTP)";
 #endif
 #endif /* not lint */
 
 #endif
 #endif /* not lint */
 
@@ -238,12 +238,6 @@ smtp(e)
                                        message("503 Polite people say HELO first");
                                        break;
                                }
                                        message("503 Polite people say HELO first");
                                        break;
                                }
-                               else
-                               {
-                                       auth_warning(e,
-                                               "Host %s didn't use HELO protocol",
-                                               RealHostName);
-                               }
                        }
                        if (gotmail)
                        {
                        }
                        if (gotmail)
                        {
@@ -260,6 +254,12 @@ smtp(e)
                        /* fork a subprocess to process this command */
                        if (runinchild("SMTP-MAIL", e) > 0)
                                break;
                        /* fork a subprocess to process this command */
                        if (runinchild("SMTP-MAIL", e) > 0)
                                break;
+                       if (!gothello)
+                       {
+                               auth_warning(e,
+                                       "Host %s didn't use HELO protocol",
+                                       RealHostName);
+                       }
                        if (protocol == NULL)
                                protocol = "SMTP";
                        define('r', protocol, e);
                        if (protocol == NULL)
                                protocol = "SMTP";
                        define('r', protocol, e);
index 369e187..995f400 100644 (file)
@@ -7,7 +7,7 @@
  */
 
 #ifndef lint
  */
 
 #ifndef lint
-static char sccsid[] = "@(#)stats.c    8.1 (Berkeley) %G%";
+static char sccsid[] = "@(#)stats.c    8.2 (Berkeley) %G%";
 #endif /* not lint */
 
 # include "sendmail.h"
 #endif /* not lint */
 
 # include "sendmail.h"
@@ -15,6 +15,8 @@ static char sccsid[] = "@(#)stats.c   8.1 (Berkeley) %G%";
 
 struct statistics      Stat;
 
 
 struct statistics      Stat;
 
+bool   GotStats = FALSE;       /* set when we have stats to merge */
+
 #define ONE_K          1000            /* one thousand (twenty-four?) */
 #define KBYTES(x)      (((x) + (ONE_K - 1)) / ONE_K)
 \f/*
 #define ONE_K          1000            /* one thousand (twenty-four?) */
 #define KBYTES(x)      (((x) + (ONE_K - 1)) / ONE_K)
 \f/*
@@ -39,6 +41,7 @@ markstats(e, to)
                Stat.stat_nt[to->q_mailer->m_mno]++;
                Stat.stat_bt[to->q_mailer->m_mno] += KBYTES(e->e_msgsize);
        }
                Stat.stat_nt[to->q_mailer->m_mno]++;
                Stat.stat_bt[to->q_mailer->m_mno] += KBYTES(e->e_msgsize);
        }
+       GotStats = TRUE;
 }
 \f/*
 **  POSTSTATS -- post statistics in the statistics file
 }
 \f/*
 **  POSTSTATS -- post statistics in the statistics file
@@ -60,7 +63,7 @@ poststats(sfile)
        struct statistics stat;
        extern off_t lseek();
 
        struct statistics stat;
        extern off_t lseek();
 
-       if (sfile == NULL)
+       if (sfile == NULL || !GotStats)
                return;
 
        (void) time(&Stat.stat_itime);
                return;
 
        (void) time(&Stat.stat_itime);
@@ -93,4 +96,8 @@ poststats(sfile)
        (void) lseek(fd, (off_t) 0, 0);
        (void) write(fd, (char *) &stat, sizeof stat);
        (void) close(fd);
        (void) lseek(fd, (off_t) 0, 0);
        (void) write(fd, (char *) &stat, sizeof stat);
        (void) close(fd);
+
+       /* clear the structure to avoid future disappointment */
+       bzero(&Stat, sizeof stat);
+       GotStats = FALSE;
 }
 }
index f9a8948..0925096 100644 (file)
@@ -10,9 +10,9 @@
 
 #ifndef lint
 #ifdef SMTP
 
 #ifndef lint
 #ifdef SMTP
-static char sccsid[] = "@(#)usersmtp.c 8.1 (Berkeley) %G% (with SMTP)";
+static char sccsid[] = "@(#)usersmtp.c 8.2 (Berkeley) %G% (with SMTP)";
 #else
 #else
-static char sccsid[] = "@(#)usersmtp.c 8.1 (Berkeley) %G% (without SMTP)";
+static char sccsid[] = "@(#)usersmtp.c 8.2 (Berkeley) %G% (without SMTP)";
 #endif
 #endif /* not lint */
 
 #endif
 #endif /* not lint */
 
@@ -66,7 +66,7 @@ smtpinit(m, mci, e)
        extern void esmtp_check();
        extern void helo_options();
 
        extern void esmtp_check();
        extern void helo_options();
 
-       if (tTd(17, 1))
+       if (tTd(18, 1))
        {
                printf("smtpinit ");
                mci_dump(mci);
        {
                printf("smtpinit ");
                mci_dump(mci);
@@ -287,7 +287,7 @@ smtpmailfrom(m, mci, e)
        char buf[MAXNAME];
        char optbuf[MAXLINE];
 
        char buf[MAXNAME];
        char optbuf[MAXLINE];
 
-       if (tTd(17, 2))
+       if (tTd(18, 2))
                printf("smtpmailfrom: CurHost=%s\n", CurHostName);
 
        /* set up appropriate options to include */
                printf("smtpmailfrom: CurHost=%s\n", CurHostName);
 
        /* set up appropriate options to include */
@@ -424,12 +424,17 @@ smtprcpt(to, m, mci, e)
 **             none.
 */
 
 **             none.
 */
 
+static jmp_buf CtxDataTimeout;
+
 smtpdata(m, mci, e)
        struct mailer *m;
        register MCI *mci;
        register ENVELOPE *e;
 {
        register int r;
 smtpdata(m, mci, e)
        struct mailer *m;
        register MCI *mci;
        register ENVELOPE *e;
 {
        register int r;
+       register EVENT *ev;
+       time_t timeout;
+       static int datatimeout();
 
        /*
        **  Send the data.
 
        /*
        **  Send the data.
@@ -467,13 +472,36 @@ smtpdata(m, mci, e)
                return (EX_PROTOCOL);
        }
 
                return (EX_PROTOCOL);
        }
 
+       if (setjmp(CtxDataTimeout) != 0)
+       {
+               mci->mci_errno = errno;
+               mci->mci_exitstat = EX_TEMPFAIL;
+               mci->mci_state = MCIS_ERROR;
+#ifdef LOG
+               syslog(LOG_NOTICE, "%s: timeout writing message to %s",
+                       e->e_id, mci->mci_host);
+#endif
+               syserr("451 timeout writing message to %s", mci->mci_host);
+               smtpquit(m, mci, e);
+               return EX_TEMPFAIL;
+       }
+
+       timeout = e->e_msgsize / 64;
+       if (timeout < (time_t) 60)
+               timeout = 60;
+       ev = setevent(timeout, datatimeout, 0);
+
        /* now output the actual message */
        (*e->e_puthdr)(mci->mci_out, m, e);
        putline("\n", mci->mci_out, m);
        (*e->e_putbody)(mci->mci_out, m, e, NULL);
 
        /* now output the actual message */
        (*e->e_puthdr)(mci->mci_out, m, e);
        putline("\n", mci->mci_out, m);
        (*e->e_putbody)(mci->mci_out, m, e, NULL);
 
+       clrevent(ev);
+
        /* terminate the message */
        fprintf(mci->mci_out, ".%s", m->m_eol);
        /* terminate the message */
        fprintf(mci->mci_out, ".%s", m->m_eol);
+       if (TrafficLogFile != NULL)
+               fprintf(TrafficLogFile, "%05d >>> .\n", getpid());
        if (Verbose)
                nmessage(">>> .");
 
        if (Verbose)
                nmessage(">>> .");
 
@@ -503,6 +531,13 @@ smtpdata(m, mci, e)
 #endif
        return (EX_PROTOCOL);
 }
 #endif
        return (EX_PROTOCOL);
 }
+
+
+static int
+datatimeout()
+{
+       longjmp(CtxDataTimeout, 1);
+}
 \f/*
 **  SMTPQUIT -- close the SMTP connection.
 **
 \f/*
 **  SMTPQUIT -- close the SMTP connection.
 **
@@ -643,6 +678,7 @@ reply(m, mci, e, timeout, pfunc)
 
                if (p == NULL)
                {
 
                if (p == NULL)
                {
+                       bool oldholderrs;
                        extern char MsgBuf[];           /* err.c */
 
                        /* if the remote end closed early, fake an error */
                        extern char MsgBuf[];           /* err.c */
 
                        /* if the remote end closed early, fake an error */
@@ -655,23 +691,31 @@ reply(m, mci, e, timeout, pfunc)
 
                        mci->mci_errno = errno;
                        mci->mci_exitstat = EX_TEMPFAIL;
 
                        mci->mci_errno = errno;
                        mci->mci_exitstat = EX_TEMPFAIL;
-                       message("451 %s: reply: read error from %s",
-                               e->e_id == NULL ? "NOQUEUE" : e->e_id,
-                               mci->mci_host);
+                       oldholderrs = HoldErrs;
+                       HoldErrs = TRUE;
+                       usrerr("451 reply: read error from %s", mci->mci_host);
+
                        /* if debugging, pause so we can see state */
                        if (tTd(18, 100))
                                pause();
                        /* if debugging, pause so we can see state */
                        if (tTd(18, 100))
                                pause();
-# ifdef LOG
-                       if (LogLevel > 1)
-                               syslog(LOG_INFO, "%s", &MsgBuf[4]);
-# endif /* LOG */
                        mci->mci_state = MCIS_ERROR;
                        smtpquit(m, mci, e);
                        mci->mci_state = MCIS_ERROR;
                        smtpquit(m, mci, e);
+#ifdef XDEBUG
+                       {
+                               char wbuf[MAXLINE];
+                               sprintf(wbuf, "%s... reply(%s) during %s",
+                                       e->e_to, mci->mci_host, SmtpPhase);
+                               checkfd012(wbuf);
+                       }
+#endif
+                       HoldErrs = oldholderrs;
                        return (-1);
                }
                fixcrlf(bufp, TRUE);
 
                        return (-1);
                }
                fixcrlf(bufp, TRUE);
 
-               if (e->e_xfp != NULL && strchr("45", bufp[0]) != NULL)
+               /* EHLO failure is not a real error */
+               if (e->e_xfp != NULL && (bufp[0] == '4' ||
+                   (bufp[0] == '5' && strncmp(SmtpMsgBuffer, "EHLO", 4) != 0)))
                {
                        /* serious error -- log the previous command */
                        if (SmtpMsgBuffer[0] != '\0')
                {
                        /* serious error -- log the previous command */
                        if (SmtpMsgBuffer[0] != '\0')
@@ -761,6 +805,8 @@ smtpmessage(f, m, mci, va_alist)
 
        if (tTd(18, 1) || Verbose)
                nmessage(">>> %s", SmtpMsgBuffer);
 
        if (tTd(18, 1) || Verbose)
                nmessage(">>> %s", SmtpMsgBuffer);
+       if (TrafficLogFile != NULL)
+               fprintf(TrafficLogFile, "%05d >>> %s\n", getpid(), SmtpMsgBuffer);
        if (mci->mci_out != NULL)
        {
                fprintf(mci->mci_out, "%s%s", SmtpMsgBuffer,
        if (mci->mci_out != NULL)
        {
                fprintf(mci->mci_out, "%s%s", SmtpMsgBuffer,
index 44cb18d..0afa640 100644 (file)
@@ -7,7 +7,7 @@
  */
 
 #ifndef lint
  */
 
 #ifndef lint
-static char sccsid[] = "@(#)util.c     8.1 (Berkeley) %G%";
+static char sccsid[] = "@(#)util.c     8.2 (Berkeley) %G%";
 #endif /* not lint */
 
 # include "sendmail.h"
 #endif /* not lint */
 
 # include "sendmail.h"
@@ -375,6 +375,7 @@ fullname(pw, buf)
 **     Parameters:
 **             fn -- filename to check.
 **             uid -- uid to compare against.
 **     Parameters:
 **             fn -- filename to check.
 **             uid -- uid to compare against.
+**             mustown -- to be safe, this uid must own the file.
 **             mode -- mode bits that must match.
 **
 **     Returns:
 **             mode -- mode bits that must match.
 **
 **     Returns:
@@ -389,23 +390,30 @@ fullname(pw, buf)
 # define S_IXOTH       (S_IEXEC >> 6)
 #endif
 
 # define S_IXOTH       (S_IEXEC >> 6)
 #endif
 
+#ifndef S_IXUSR
+# define S_IXUSR       (S_IEXEC)
+#endif
+
 int
 int
-safefile(fn, uid, mode)
+safefile(fn, uid, mustown, mode)
        char *fn;
        uid_t uid;
        char *fn;
        uid_t uid;
+       bool mustown;
        int mode;
 {
        register char *p;
        struct stat stbuf;
 
        if (tTd(54, 4))
        int mode;
 {
        register char *p;
        struct stat stbuf;
 
        if (tTd(54, 4))
-               printf("safefile(%s, %d, %o): ", fn, uid, mode);
+               printf("safefile(%s, %d, %d, %o): ", fn, uid, mustown, mode);
        errno = 0;
 
        for (p = fn; (p = strchr(++p, '/')) != NULL; *p = '/')
        {
                *p = '\0';
        errno = 0;
 
        for (p = fn; (p = strchr(++p, '/')) != NULL; *p = '/')
        {
                *p = '\0';
-               if (stat(fn, &stbuf) < 0 || !bitset(S_IXOTH, stbuf.st_mode))
+               if (stat(fn, &stbuf) < 0 ||
+                   !bitset(stbuf.st_uid == uid ? S_IXUSR : S_IXOTH,
+                           stbuf.st_mode))
                {
                        int ret = errno;
 
                {
                        int ret = errno;
 
@@ -428,11 +436,11 @@ safefile(fn, uid, mode)
                errno = 0;
                return ret;
        }
                errno = 0;
                return ret;
        }
-       if (stbuf.st_uid != uid && uid == 0)
+       if (stbuf.st_uid != uid || uid == 0 || !mustown)
                mode >>= 6;
        if (tTd(54, 4))
                printf("[uid %d, stat %o] ", stbuf.st_uid, stbuf.st_mode);
                mode >>= 6;
        if (tTd(54, 4))
                printf("[uid %d, stat %o] ", stbuf.st_uid, stbuf.st_mode);
-       if ((stbuf.st_uid == uid || uid == 0) &&
+       if ((stbuf.st_uid == uid || uid == 0 || !mustown) &&
            (stbuf.st_mode & mode) == mode)
        {
                if (tTd(54, 4))
            (stbuf.st_mode & mode) == mode)
        {
                if (tTd(54, 4))
@@ -486,6 +494,10 @@ fixcrlf(line, stripnl)
 **     whatever), so this tries to get around it.
 */
 
 **     whatever), so this tries to get around it.
 */
 
+#ifndef O_ACCMODE
+# define O_ACCMODE     (O_RDONLY|O_WRONLY|O_RDWR)
+#endif
+
 struct omodes
 {
        int     mask;
 struct omodes
 {
        int     mask;
@@ -581,6 +593,9 @@ putline(l, fp, m)
                if (p == NULL)
                        p = &l[strlen(l)];
 
                if (p == NULL)
                        p = &l[strlen(l)];
 
+               if (TrafficLogFile != NULL)
+                       fprintf(TrafficLogFile, "%05d >>> ", getpid());
+
                /* check for line overflow */
                while (m->m_linelimit > 0 && (p - l) > m->m_linelimit)
                {
                /* check for line overflow */
                while (m->m_linelimit > 0 && (p - l) > m->m_linelimit)
                {
@@ -589,17 +604,30 @@ putline(l, fp, m)
                        svchar = *q;
                        *q = '\0';
                        if (l[0] == '.' && bitnset(M_XDOT, m->m_flags))
                        svchar = *q;
                        *q = '\0';
                        if (l[0] == '.' && bitnset(M_XDOT, m->m_flags))
+                       {
                                (void) putc('.', fp);
                                (void) putc('.', fp);
+                               if (TrafficLogFile != NULL)
+                                       (void) putc('.', TrafficLogFile);
+                       }
                        fputs(l, fp);
                        (void) putc('!', fp);
                        fputs(m->m_eol, fp);
                        fputs(l, fp);
                        (void) putc('!', fp);
                        fputs(m->m_eol, fp);
+                       if (TrafficLogFile != NULL)
+                               fprintf(TrafficLogFile, "%s!\n%05d >>> ",
+                                       l, getpid());
                        *q = svchar;
                        l = q;
                }
 
                /* output last part */
                if (l[0] == '.' && bitnset(M_XDOT, m->m_flags))
                        *q = svchar;
                        l = q;
                }
 
                /* output last part */
                if (l[0] == '.' && bitnset(M_XDOT, m->m_flags))
+               {
                        (void) putc('.', fp);
                        (void) putc('.', fp);
+                       if (TrafficLogFile != NULL)
+                               (void) putc('.', TrafficLogFile);
+               }
+               if (TrafficLogFile != NULL)
+                       fprintf(TrafficLogFile, "%.*s\n", p - l, l);
                for ( ; l < p; ++l)
                        (void) putc(*l, fp);
                fputs(m->m_eol, fp);
                for ( ; l < p; ++l)
                        (void) putc(*l, fp);
                fputs(m->m_eol, fp);
@@ -706,6 +734,9 @@ sfgets(buf, siz, fp, timeout, during)
                        usrerr("451 timeout waiting for input during %s",
                                during);
                        buf[0] = '\0';
                        usrerr("451 timeout waiting for input during %s",
                                during);
                        buf[0] = '\0';
+#ifdef XDEBUG
+                       checkfd012(during);
+#endif
                        return (NULL);
                }
                ev = setevent(timeout, readtimeout, 0);
                        return (NULL);
                }
                ev = setevent(timeout, readtimeout, 0);
@@ -729,8 +760,12 @@ sfgets(buf, siz, fp, timeout, during)
        if (p == NULL)
        {
                buf[0] = '\0';
        if (p == NULL)
        {
                buf[0] = '\0';
+               if (TrafficLogFile != NULL)
+                       fprintf(TrafficLogFile, "%05d <<< [EOF]\n", getpid());
                return (NULL);
        }
                return (NULL);
        }
+       if (TrafficLogFile != NULL)
+               fprintf(TrafficLogFile, "%05d <<< %s", getpid(), buf);
        if (SevenBit)
                for (p = buf; *p != '\0'; p++)
                        *p &= ~0200;
        if (SevenBit)
                for (p = buf; *p != '\0'; p++)
                        *p &= ~0200;
@@ -997,3 +1032,41 @@ strcontainedin(a, b)
                b++;
        }
 }
                b++;
        }
 }
+\f/*
+**  CHECKFD012 -- check low numbered file descriptors
+**
+**     File descriptors 0, 1, and 2 should be open at all times.
+**     This routine verifies that, and fixes it if not true.
+**
+**     Parameters:
+**             where -- a tag printed if the assertion failed
+**
+**     Returns:
+**             none
+*/
+
+checkfd012(where)
+       char *where;
+{
+#ifdef XDEBUG
+       register int i;
+       struct stat stbuf;
+
+       for (i = 0; i < 3; i++)
+       {
+               if (fstat(i, &stbuf) < 0)
+               {
+                       /* oops.... */
+                       int fd;
+
+                       syserr("%s: fd %d not open", where, i);
+                       fd = open("/dev/null", i == 0 ? O_RDONLY : O_WRONLY, 0666);
+                       if (fd != i)
+                       {
+                               (void) dup2(fd, i);
+                               (void) close(fd);
+                       }
+               }
+       }
+#endif XDEBUG
+}