Don't pass EX_TEMPFAIL code out (since we have already taken responsibility
[unix-history] / usr / src / usr.sbin / sendmail / src / main.c
index be4f8c3..371d1f2 100644 (file)
@@ -1,12 +1,10 @@
 # define  _DEFINE
 # include <signal.h>
 # define  _DEFINE
 # include <signal.h>
-# include <pwd.h>
-# include <time.h>
 # include <sys/ioctl.h>
 # include "sendmail.h"
 # include <sys/ioctl.h>
 # include "sendmail.h"
-# include <sys/stat.h>
+# include <sys/file.h>
 
 
-SCCSID(@(#)main.c      3.135           %G%);
+SCCSID(@(#)main.c      3.157           %G%);
 
 /*
 **  SENDMAIL -- Post mail to a set of destinations.
 
 /*
 **  SENDMAIL -- Post mail to a set of destinations.
@@ -25,82 +23,18 @@ SCCSID(@(#)main.c   3.135           %G%);
 **     server mechanism).
 **
 **     Usage:
 **     server mechanism).
 **
 **     Usage:
-**             /etc/sendmail [flags] addr ...
+**             /usr/lib/sendmail [flags] addr ...
 **
 **
-**     Positional Parameters:
-**             addr -- the address to deliver the mail to.  There
-**                     can be several.
-**
-**     Flags:
-**             -f name         The mail is from "name" -- used for
-**                             the header in local mail, and to
-**                             deliver reports of failures to.
-**             -r name         Same as -f; however, this flag is
-**                             reserved to indicate special processing
-**                             for remote mail delivery as needed
-**                             in the future.  So, network servers
-**                             should use -r.
-**             -Ffullname      Select what the full-name should be
-**                             listed as.
-**             -a              This mail should be in ARPANET std
-**                             format (obsolete version).
-**             -as             Speak SMTP.
-**             -n              Don't do aliasing.  This might be used
-**                             when delivering responses, for
-**                             instance.
-**             -dN             Run with debugging set to level N.
-**             -em             Mail back a response if there was an
-**                             error in processing.  This should be
-**                             used when the origin of this message
-**                             is another machine.
-**             -ew             Write back a response if the user is
-**                             still logged in, otherwise, act like
-**                             -em.
-**             -eq             Don't print any error message (just
-**                             return exit status).
-**             -ep             (default)  Print error messages
-**                             normally.
-**             -ee             Send BerkNet style errors.  This
-**                             is equivalent to MailBack except
-**                             that it has gives zero return code
-**                             (unless there were errors during
-**                             returning).  This used to be
-**                             "EchoBack", but you know how the old
-**                             software bounces.
-**             -m              In group expansion, send to the
-**                             sender also (stands for the Mail metoo
-**                             option.
-**             -i              Do not terminate mail on a line
-**                             containing just dot.
-**             -s              Save UNIX-like "From" lines on the
-**                             front of messages.
-**             -v              Give blow-by-blow description of
-**                             everything that happens.
-**             -t              Read "to" addresses from message.
-**                             Looks at To:, Cc:, and Bcc: lines.
-**             -I              Initialize the DBM alias files from
-**                             the text format files.
-**             -Cfilename      Use alternate configuration file.
-**             -Afilename      Use alternate alias file.
-**             -DXvalue        Define macro X to have value.
-**             -bv             Verify addresses only.
-**             -bd             Run as a daemon.  Berkeley 4.2 only.
-**             -bf             Fork after address verification.
-**             -bq             Queue up for later delivery.
-**             -ba             Process mail completely.
-**
-**     Return Codes:
-**             As defined in <sysexits.h>.
-**
-**             These codes are actually returned from the auxiliary
-**             mailers; it is their responsibility to make them
-**             correct.
-**
-**     Compilation Flags:
-**             LOG -- if set, everything is logged.
+**             See the associated documentation for details.
 **
 **     Author:
 **
 **     Author:
-**             Eric Allman, UCB/INGRES
+**             Eric Allman, UCB/INGRES (until 10/81)
+**                          Britton-Lee, Inc., purveyors of fine
+**                             database computers (from 11/81)
+**             The support of the INGRES Project and Britton-Lee is
+**                     gratefully acknowledged.  Britton-Lee in
+**                     particular had absolutely nothing to gain from
+**                     my involvement in this project.
 */
 
 
 */
 
 
@@ -108,7 +42,7 @@ SCCSID(@(#)main.c    3.135           %G%);
 
 
 int            NextMailer = 0; /* "free" index into Mailer struct */
 
 
 int            NextMailer = 0; /* "free" index into Mailer struct */
-static char    *FullName;      /* sender's full name */
+char           *FullName;      /* sender's full name */
 ENVELOPE       BlankEnvelope;  /* a "blank" envelope */
 ENVELOPE       MainEnvelope;   /* the envelope around the basic letter */
 
 ENVELOPE       BlankEnvelope;  /* a "blank" envelope */
 ENVELOPE       MainEnvelope;   /* the envelope around the basic letter */
 
@@ -128,7 +62,6 @@ main(argc, argv)
        char **argv;
 {
        register char *p;
        char **argv;
 {
        register char *p;
-       int ac;
        char **av;
        char *locname;
        extern int finis();
        char **av;
        char *locname;
        extern int finis();
@@ -137,7 +70,7 @@ main(argc, argv)
        typedef int (*fnptr)();
        STAB *st;
        register int i;
        typedef int (*fnptr)();
        STAB *st;
        register int i;
-       int pass = 0;
+       bool readconfig = FALSE;
        bool safecf = TRUE;             /* this conf file is sys default */
        bool queuemode = FALSE;         /* process queue requests */
        static bool reenter = FALSE;
        bool safecf = TRUE;             /* this conf file is sys default */
        bool queuemode = FALSE;         /* process queue requests */
        static bool reenter = FALSE;
@@ -147,6 +80,13 @@ main(argc, argv)
        extern putheader(), putbody();
        extern ENVELOPE *newenvelope();
        extern intsig();
        extern putheader(), putbody();
        extern ENVELOPE *newenvelope();
        extern intsig();
+       extern char **myhostname();
+
+       /*
+       **  Check to see if we reentered.
+       **      This would normally happen if e_putheader or e_putbody
+       **      were NULL when invoked.
+       */
 
        if (reenter)
        {
 
        if (reenter)
        {
@@ -157,7 +97,36 @@ main(argc, argv)
        extern ADDRESS *recipient();
        bool canrename;
 
        extern ADDRESS *recipient();
        bool canrename;
 
+       /*
+       **  Be sure we have enough file descriptors.
+       */
+
+       for (i = 3; i < 20; i++)
+               (void) close(i);
+       errno = 0;
+
+       /*
+       **  Do a quick prescan of the argument list.
+       **      We do this to find out if we can potentially thaw the
+       **      configuration file.  If not, we do the thaw now so that
+       **      the argument processing applies to this run rather than
+       **      to the run that froze the configuration.
+       */
+
        argv[argc] = NULL;
        argv[argc] = NULL;
+       av = argv;
+       while (*++av != NULL)
+       {
+               if (strncmp(*av, "-C", 2) == 0 || strncmp(*av, "-bz", 3) == 0)
+                       break;
+       }
+       if (*av == NULL)
+               readconfig = !thaw(FreezeFile);
+
+       /*
+       **  Now do basic initialization
+       */
+
        InChannel = stdin;
        OutChannel = stdout;
        if (signal(SIGINT, SIG_IGN) != SIG_IGN)
        InChannel = stdin;
        OutChannel = stdout;
        if (signal(SIGINT, SIG_IGN) != SIG_IGN)
@@ -165,6 +134,7 @@ main(argc, argv)
        if (signal(SIGHUP, SIG_IGN) != SIG_IGN)
                (void) signal(SIGHUP, intsig);
        (void) signal(SIGTERM, intsig);
        if (signal(SIGHUP, SIG_IGN) != SIG_IGN)
                (void) signal(SIGHUP, intsig);
        (void) signal(SIGTERM, intsig);
+       (void) signal(SIGPIPE, SIG_IGN);
        OldUmask = umask(0);
        OpMode = MD_DELIVER;
        MotherPid = getpid();
        OldUmask = umask(0);
        OpMode = MD_DELIVER;
        MotherPid = getpid();
@@ -175,24 +145,43 @@ main(argc, argv)
        /* set up the blank envelope */
        BlankEnvelope.e_puthdr = putheader;
        BlankEnvelope.e_putbody = putbody;
        /* set up the blank envelope */
        BlankEnvelope.e_puthdr = putheader;
        BlankEnvelope.e_putbody = putbody;
+       BlankEnvelope.e_xfp = NULL;
        CurEnv = &BlankEnvelope;
 
        CurEnv = &BlankEnvelope;
 
+       /* make sure we have a clean slate */
+       closeall();
+
 # ifdef LOG
 # ifdef LOG
-       openlog("sendmail", 0);
+       openlog("sendmail", LOG_PID);
 # endif LOG
 # endif LOG
-       Xscript = stderr;
        errno = 0;
        from = NULL;
        errno = 0;
        from = NULL;
+
+       /* initialize some macros, etc. */
        initmacros();
 
        initmacros();
 
+       /* hostname */
+       av = myhostname(jbuf);
+       if (jbuf[0] != '\0')
+       {
+               p = newstr(jbuf);
+               define('w', p, CurEnv);
+               setclass('w', p);
+       }
+       while (av != NULL && *av != NULL)
+               setclass('w', *av++);
+
+       /* version */
+       define('v', Version, CurEnv);
+
+       /* current time */
+       define('b', arpadate(NULL), CurEnv);
+
        /*
        ** Crack argv.
        */
 
        /*
        ** Crack argv.
        */
 
-  crackargs:
-       ac = argc;
        av = argv;
        av = argv;
-       pass++;
        p = rindex(*av, '/');
        if (p++ == NULL)
                p = *av;
        p = rindex(*av, '/');
        if (p++ == NULL)
                p = *av;
@@ -200,7 +189,7 @@ main(argc, argv)
                OpMode = MD_INITALIAS;
        else if (strcmp(p, "mailq") == 0)
                OpMode = MD_PRINT;
                OpMode = MD_INITALIAS;
        else if (strcmp(p, "mailq") == 0)
                OpMode = MD_PRINT;
-       while (--ac > 0 && (p = *++av)[0] == '-')
+       while ((p = *++av) != NULL && p[0] == '-')
        {
                switch (p[1])
                {
        {
                switch (p[1])
                {
@@ -252,18 +241,17 @@ main(argc, argv)
                  case 'f':     /* from address */
                  case 'r':     /* obsolete -f flag */
                        p += 2;
                  case 'f':     /* from address */
                  case 'r':     /* obsolete -f flag */
                        p += 2;
-                       if (*p == '\0')
+                       if (*p == '\0' && ((p = *++av) == NULL || *p == '-'))
                        {
                                p = *++av;
                        {
                                p = *++av;
-                               if (--ac <= 0 || *p == '-')
+                               if (p == NULL || *p == '-')
                                {
                                        syserr("No \"from\" person");
                                {
                                        syserr("No \"from\" person");
-                                       ac++;
                                        av--;
                                        break;
                                }
                        }
                                        av--;
                                        break;
                                }
                        }
-                       if (from != NULL && pass <= 1)
+                       if (from != NULL)
                        {
                                syserr("More than one \"from\" person");
                                break;
                        {
                                syserr("More than one \"from\" person");
                                break;
@@ -273,34 +261,24 @@ main(argc, argv)
 
                  case 'F':     /* set full name */
                        p += 2;
 
                  case 'F':     /* set full name */
                        p += 2;
-                       if (*p == '\0')
+                       if (*p == '\0' && ((p = *++av) == NULL || *p == '-'))
                        {
                        {
-                               p = *++av;
-                               if (--ac <= 0 || *p == '-')
-                               {
-                                       syserr("Bad -F flag");
-                                       ac++;
-                                       av--;
-                                       break;
-                               }
+                               syserr("Bad -F flag");
+                               av--;
+                               break;
                        }
                        FullName = p;
                        break;
 
                  case 'h':     /* hop count */
                        p += 2;
                        }
                        FullName = p;
                        break;
 
                  case 'h':     /* hop count */
                        p += 2;
-                       if (*p == '\0')
+                       if (*p == '\0' && ((p = *++av) == NULL || !isdigit(*p)))
                        {
                        {
-                               p = *++av;
-                               if (--ac <= 0 || *p < '0' || *p > '9')
-                               {
-                                       syserr("Bad hop count (%s)", p);
-                                       ac++;
-                                       av--;
-                                       break;
-                               }
+                               syserr("Bad hop count (%s)", p);
+                               av--;
+                               break;
                        }
                        }
-                       HopCount = atoi(p);
+                       CurEnv->e_hopcount = atoi(p);
                        break;
                
                  case 'n':     /* don't alias */
                        break;
                
                  case 'n':     /* don't alias */
@@ -352,26 +330,18 @@ main(argc, argv)
        **      Extract special fields for local use.
        */
 
        **      Extract special fields for local use.
        */
 
-       if (pass <= 1)
-       {
-               if (!safecf || OpMode == MD_FREEZE || !thaw())
-                       readcf(ConfFile, safecf);
-               else
-                       goto crackargs;
-       }
+       if (!safecf || OpMode == MD_FREEZE || readconfig)
+               readcf(ConfFile, safecf);
+
        switch (OpMode)
        {
          case MD_FREEZE:
        switch (OpMode)
        {
          case MD_FREEZE:
-               freeze();
+               freeze(FreezeFile);
                exit(EX_OK);
 
          case MD_INITALIAS:
                Verbose = TRUE;
                break;
                exit(EX_OK);
 
          case MD_INITALIAS:
                Verbose = TRUE;
                break;
-
-         case MD_PRINT:
-               usrerr("mailq mode not yet implemented");
-               finis();
        }
 
        /* do heuristic mode adjustment */
        }
 
        /* do heuristic mode adjustment */
@@ -407,15 +377,29 @@ main(argc, argv)
                exit(EX_SOFTWARE);
        }
 
                exit(EX_SOFTWARE);
        }
 
+       /*
+       **  If printing the queue, go off and do that.
+       */
+
+       if (OpMode == MD_PRINT)
+       {
+#ifdef QUEUE
+               dropenvelope(CurEnv);
+               printqueue();
+               exit(EX_OK);
+#else QUEUE
+               usrerr("No queue to print");
+               finis();
+#endif QUEUE
+       }
+
        /*
        **  Initialize aliases.
        */
 
        initaliases(AliasFile, OpMode == MD_INITALIAS);
        /*
        **  Initialize aliases.
        */
 
        initaliases(AliasFile, OpMode == MD_INITALIAS);
-# ifdef DBM
        if (OpMode == MD_INITALIAS)
                exit(EX_OK);
        if (OpMode == MD_INITALIAS)
                exit(EX_OK);
-# endif DBM
 
 # ifdef DEBUG
        if (tTd(0, 15))
 
 # ifdef DEBUG
        if (tTd(0, 15))
@@ -425,11 +409,19 @@ main(argc, argv)
                for (i = 0; i < MAXMAILERS; i++)
                {
                        register struct mailer *m = Mailer[i];
                for (i = 0; i < MAXMAILERS; i++)
                {
                        register struct mailer *m = Mailer[i];
+                       int j;
 
                        if (m == NULL)
                                continue;
 
                        if (m == NULL)
                                continue;
-                       printf("mailer %d: %s %s %lo %d %d\n", i, m->m_name,
-                              m->m_mailer, m->m_flags, m->m_s_rwset, m->m_r_rwset);
+                       printf("mailer %d (%s): P=%s S=%d R=%d M=%ld F=", i, m->m_name,
+                               m->m_mailer, m->m_s_rwset, m->m_r_rwset,
+                               m->m_maxsize);
+                       for (j = '\0'; j <= '\177'; j++)
+                               if (bitnset(j, m->m_flags))
+                                       putchar(j);
+                       printf(" E=");
+                       xputs(m->m_eol);
+                       printf("\n");
                }
        }
 # endif DEBUG
                }
        }
 # endif DEBUG
@@ -439,7 +431,7 @@ main(argc, argv)
        */
 
        CurEnv = newenvelope(&MainEnvelope);
        */
 
        CurEnv = newenvelope(&MainEnvelope);
-       MainEnvelope.e_oldstyle = BlankEnvelope.e_oldstyle;
+       MainEnvelope.e_flags = BlankEnvelope.e_flags;
 
        /*
        **  If test mode, read addresses from stdin and process.
 
        /*
        **  If test mode, read addresses from stdin and process.
@@ -455,7 +447,6 @@ main(argc, argv)
                        register char **pvp;
                        char *q;
                        extern char **prescan();
                        register char **pvp;
                        char *q;
                        extern char **prescan();
-                       extern char **rewrite();
                        extern char *DelimChar;
 
                        printf("> ");
                        extern char *DelimChar;
 
                        printf("> ");
@@ -492,14 +483,13 @@ main(argc, argv)
        **  If collecting stuff from the queue, go start doing that.
        */
 
        **  If collecting stuff from the queue, go start doing that.
        */
 
-       if (queuemode && OpMode != MD_DAEMON && QueueIntvl != 0)
+       if (queuemode && OpMode != MD_DAEMON && QueueIntvl == 0)
        {
                runqueue(FALSE);
                finis();
        }
 # endif QUEUE
 
        {
                runqueue(FALSE);
                finis();
        }
 # endif QUEUE
 
-#ifdef DAEMON
        /*
        **  If a daemon, wait for a request.
        **      getrequests will always return in a child.
        /*
        **  If a daemon, wait for a request.
        **      getrequests will always return in a child.
@@ -522,21 +512,11 @@ main(argc, argv)
 
                        /* get our pid right */
                        MotherPid = getpid();
 
                        /* get our pid right */
                        MotherPid = getpid();
-# ifdef LOG
-                       if (LogLevel > 11)
-                               syslog(LOG_DEBUG, "background daemon, pid=%d",
-                                      MotherPid);
-# endif LOG
 
                        /* disconnect from our controlling tty */
 
                        /* disconnect from our controlling tty */
-                       i = open("/dev/tty", 2);
-                       if (i >= 0)
-                       {
-                               (void) ioctl(i, TIOCNOTTY, 0);
-                               (void) close(i);
-                       }
-                       errno = 0;
+                       disconnect(TRUE);
                }
                }
+
 # ifdef QUEUE
                if (queuemode)
                {
 # ifdef QUEUE
                if (queuemode)
                {
@@ -546,20 +526,17 @@ main(argc, argv)
                                        pause();
                }
 # endif QUEUE
                                        pause();
                }
 # endif QUEUE
-               checkerrors(CurEnv);
+               dropenvelope(CurEnv);
+
+#ifdef DAEMON
                getrequests();
 
                /* at this point we are in a child: reset state */
                OpMode = MD_SMTP;
                getrequests();
 
                /* at this point we are in a child: reset state */
                OpMode = MD_SMTP;
-               dropenvelope(CurEnv);
-               CurEnv->e_id = CurEnv->e_qf = CurEnv->e_df = NULL;
-               FatalErrors = FALSE;
-               openxscrpt();
-       }
+               (void) newenvelope(CurEnv);
+               openxscript(CurEnv);
 #endif DAEMON
 #endif DAEMON
-
-       /* do basic system initialization */
-       initsys();
+       }
        
 # ifdef SMTP
        /*
        
 # ifdef SMTP
        /*
@@ -572,12 +549,13 @@ main(argc, argv)
 # endif SMTP
 
        /*
 # endif SMTP
 
        /*
-       **  Set the sender
+       **  Do basic system initialization and set the sender
        */
 
        */
 
+       initsys();
        setsender(from);
 
        setsender(from);
 
-       if (OpMode != MD_DAEMON && ac <= 0 && !GrabTo)
+       if (OpMode != MD_ARPAFTP && *av == NULL && !GrabTo)
        {
                usrerr("Usage: /etc/sendmail [flags] addr...");
                finis();
        {
                usrerr("Usage: /etc/sendmail [flags] addr...");
                finis();
@@ -585,25 +563,10 @@ main(argc, argv)
        if (OpMode == MD_VERIFY)
                SendMode = SM_VERIFY;
 
        if (OpMode == MD_VERIFY)
                SendMode = SM_VERIFY;
 
-       /*
-       **  Process Hop count.
-       **      The Hop count tells us how many times this message has
-       **      been processed by sendmail.  If it exceeds some
-       **      fairly large threshold, then we assume that we have
-       **      an infinite forwarding loop and die.
-       */
-
-       if (++HopCount > MAXHOP)
-               syserr("Infinite forwarding loop (%s->%s)", CurEnv->e_from.q_paddr, *av);
-
        /*
        **  Scan argv and deliver the message to everyone.
        /*
        **  Scan argv and deliver the message to everyone.
-       **      Actually, suppress delivery if we are taking To:
-       **      lines from the message.
        */
 
        */
 
-       if (GrabTo)
-               DontSend = TRUE;
        sendtoargv(av);
 
        /* if we have had errors sofar, arrange a meaningful exit stat */
        sendtoargv(av);
 
        /* if we have had errors sofar, arrange a meaningful exit stat */
@@ -614,202 +577,36 @@ main(argc, argv)
        **  Read the input mail.
        */
 
        **  Read the input mail.
        */
 
-       DontSend = FALSE;
        CurEnv->e_to = NULL;
        if (OpMode != MD_VERIFY || GrabTo)
                collect(FALSE);
        errno = 0;
 
        CurEnv->e_to = NULL;
        if (OpMode != MD_VERIFY || GrabTo)
                collect(FALSE);
        errno = 0;
 
-       initsys();
-
        /* collect statistics */
        /* collect statistics */
-       Stat.stat_nf[CurEnv->e_from.q_mailer->m_mno]++;
-       Stat.stat_bf[CurEnv->e_from.q_mailer->m_mno] += kbytes(CurEnv->e_msgsize);
-
-       /*
-       **  Arrange that the person who is sending the mail
-       **  will not be expanded (unless explicitly requested).
-       */
+       if (OpMode != MD_VERIFY)
+               markstats(CurEnv, (ADDRESS *) NULL);
 
 # ifdef DEBUG
        if (tTd(1, 1))
                printf("From person = \"%s\"\n", CurEnv->e_from.q_paddr);
 # endif DEBUG
 
 
 # ifdef DEBUG
        if (tTd(1, 1))
                printf("From person = \"%s\"\n", CurEnv->e_from.q_paddr);
 # endif DEBUG
 
-       CurEnv->e_from.q_flags |= QDONTSEND;
-       if (!MeToo)
-               recipient(&CurEnv->e_from, &CurEnv->e_sendqueue);
-       CurEnv->e_to = NULL;
-
        /*
        **  Actually send everything.
        **      If verifying, just ack.
        */
 
        /*
        **  Actually send everything.
        **      If verifying, just ack.
        */
 
+       CurEnv->e_from.q_flags |= QDONTSEND;
+       CurEnv->e_to = NULL;
        sendall(CurEnv, SendMode);
 
        /*
        ** All done.
        */
 
        sendall(CurEnv, SendMode);
 
        /*
        ** All done.
        */
 
-       CurEnv->e_to = NULL;
-       if (OpMode != MD_VERIFY)
-               poststats(StatFile);
        finis();
 }
 \f/*
        finis();
 }
 \f/*
-**  SETFROM -- set the person who this message is from
-**
-**     Under certain circumstances allow the user to say who
-**     s/he is (using -f or -r).  These are:
-**     1.  The user's uid is zero (root).
-**     2.  The user's login name is in an approved list (typically
-**         from a network server).
-**     3.  The address the user is trying to claim has a
-**         "!" character in it (since #2 doesn't do it for
-**         us if we are dialing out for UUCP).
-**     A better check to replace #3 would be if the
-**     effective uid is "UUCP" -- this would require me
-**     to rewrite getpwent to "grab" uucp as it went by,
-**     make getname more nasty, do another passwd file
-**     scan, or compile the UID of "UUCP" into the code,
-**     all of which are reprehensible.
-**
-**     Assuming all of these fail, we figure out something
-**     ourselves.
-**
-**     Parameters:
-**             from -- the person it is from.
-**             realname -- the actual person executing sendmail.
-**                     If NULL, then take whoever we previously
-**                     thought was the from person.
-**
-**     Returns:
-**             none.
-**
-**     Side Effects:
-**             sets sendmail's notion of who the from person is.
-*/
-
-setfrom(from, realname)
-       char *from;
-       char *realname;
-{
-       register char **pvp;
-       char frombuf[MAXNAME];
-       extern char **prescan();
-       extern char *index();
-
-       if (realname == NULL)
-               realname = CurEnv->e_from.q_paddr;
-
-# ifdef DEBUG
-       if (tTd(1, 1))
-               printf("setfrom(%s, %s)\n", from, realname);
-# endif DEBUG
-
-       /*
-       **  Do validation to determine whether this user is allowed
-       **  to change the sender name.
-       */
-
-       if (from != NULL)
-       {
-               extern bool trusteduser();
-
-               if (!trusteduser(realname) &&
-# ifdef DEBUG
-                   (!tTd(1, 9) || getuid() != geteuid()) &&
-# endif DEBUG
-                   index(from, '!') == NULL && getuid() != 0)
-               {
-                       /* network sends -r regardless (why why why?) */
-                       /* syserr("%s, you cannot use the -f flag", realname); */
-                       from = NULL;
-               }
-       }
-
-       /*
-       **  Parse the sender name.
-       **      Arrange to send return messages to the same person.
-       **      Set up some environment info.
-       */
-
-       SuprErrs = TRUE;
-       if (from == NULL || parse(from, &CurEnv->e_from, 1) == NULL)
-       {
-               from = newstr(realname);
-               (void) parse(from, &CurEnv->e_from, 1);
-       }
-       else
-               FromFlag = TRUE;
-       CurEnv->e_returnto = &CurEnv->e_from;
-       SuprErrs = FALSE;
-       CurEnv->e_from.q_uid = getuid();
-       CurEnv->e_from.q_gid = getgid();
-# ifndef V6
-       CurEnv->e_from.q_home = getenv("HOME");
-# endif V6
-       if (CurEnv->e_from.q_uid != 0)
-       {
-               DefUid = CurEnv->e_from.q_uid;
-               DefGid = CurEnv->e_from.q_gid;
-       }
-
-       /*
-       **  Rewrite the from person to dispose of possible implicit
-       **      links in the net.
-       */
-
-       pvp = prescan(from, '\0');
-       if (pvp == NULL)
-       {
-               syserr("cannot prescan from (%s)", from);
-               finis();
-       }
-       rewrite(pvp, 3);
-       rewrite(pvp, 1);
-       cataddr(pvp, frombuf, sizeof frombuf);
-       define('f', newstr(frombuf));
-
-       /* save the domain spec if this mailer wants it */
-       if (bitset(M_CANONICAL, CurEnv->e_from.q_mailer->m_flags))
-       {
-               extern char **copyplist();
-
-               while (*pvp != NULL && strcmp(*pvp, "@") != 0)
-                       pvp++;
-               if (*pvp != NULL)
-                       CurEnv->e_fromdomain = copyplist(pvp, TRUE);
-       }
-}
-\f/*
-**  TRUSTEDUSER -- tell us if this user is to be trusted.
-**
-**     Parameters:
-**             user -- the user to be checked.
-**
-**     Returns:
-**             TRUE if the user is in an approved list.
-**             FALSE otherwise.
-**
-**     Side Effects:
-**             none.
-*/
-
-bool
-trusteduser(user)
-       char *user;
-{
-       register char **ulist;
-       extern char *TrustedUsers[];
-
-       for (ulist = TrustedUsers; *ulist != NULL; ulist++)
-               if (strcmp(*ulist, user) == 0)
-                       return (TRUE);
-       return (FALSE);
-}
-\f/*
 **  FINIS -- Clean up and exit.
 **
 **     Parameters:
 **  FINIS -- Clean up and exit.
 **
 **     Parameters:
@@ -824,55 +621,32 @@ trusteduser(user)
 
 finis()
 {
 
 finis()
 {
-       CurEnv = &MainEnvelope;
-
 # ifdef DEBUG
        if (tTd(2, 1))
 # ifdef DEBUG
        if (tTd(2, 1))
-       {
-               printf("\n====finis: stat %d sendreceipt %d FatalErrors %d\n",
-                    ExitStat, CurEnv->e_sendreceipt, FatalErrors);
-       }
+               printf("\n====finis: stat %d e_flags %o\n", ExitStat, CurEnv->e_flags);
 # endif DEBUG
 
 # endif DEBUG
 
-       /*
-       **  Send back return receipts as requested.
-       */
-
-       if (CurEnv->e_receiptto != NULL &&
-           (CurEnv->e_sendreceipt || ExitStat != EX_OK))
-       {
-               auto ADDRESS *rlist;
-
-               sendto(CurEnv->e_receiptto, (ADDRESS *) NULL, &rlist);
-               (void) returntosender("Return receipt", rlist, FALSE);
-       }
-
-       /*
-       **  Arrange to return errors or queue up as appropriate.
-       **      If we are running a queue file and exiting abnormally,
-       **              be sure we save the queue file.
-       **      This clause will arrange to return error messages.
-       */
-
-       checkerrors(CurEnv);
+       /* clean up temp files */
+       CurEnv->e_to = NULL;
+       dropenvelope(CurEnv);
 
 
-       /*
-       **  Now clean up temp files and exit.
-       */
+       /* post statistics */
+       poststats(StatFile);
 
 
-       if (Transcript != NULL)
-               xunlink(Transcript);
-       dropenvelope(CurEnv);
+       /* and exit */
 # ifdef LOG
        if (LogLevel > 11)
                syslog(LOG_DEBUG, "finis, pid=%d", getpid());
 # endif LOG
 # ifdef LOG
        if (LogLevel > 11)
                syslog(LOG_DEBUG, "finis, pid=%d", getpid());
 # endif LOG
+       if (ExitStat == EX_TEMPFAIL)
+               ExitStat = EX_OK;
        exit(ExitStat);
 }
 \f/*
 **  INTSIG -- clean up on interrupt
 **
        exit(ExitStat);
 }
 \f/*
 **  INTSIG -- clean up on interrupt
 **
-**     This just arranges to call finis.
+**     This just arranges to exit.  It pessimises in that it
+**     may resend a message.
 **
 **     Parameters:
 **             none.
 **
 **     Parameters:
 **             none.
@@ -881,236 +655,14 @@ finis()
 **             none.
 **
 **     Side Effects:
 **             none.
 **
 **     Side Effects:
-**             Arranges to not unlink the qf and df files.
+**             Unlocks the current job.
 */
 
 intsig()
 {
 */
 
 intsig()
 {
-       CurEnv->e_df = CurEnv->e_qf = NULL;
-       finis();
-}
-\f/*
-**  OPENXSCRPT -- Open transcript file
-**
-**     Creates a transcript file for possible eventual mailing or
-**     sending back.
-**
-**     Parameters:
-**             none
-**
-**     Returns:
-**             none
-**
-**     Side Effects:
-**             Open the transcript file.
-*/
-
-openxscrpt()
-{
-       register char *p;
-
-       p = queuename(CurEnv, 'x');
-       Xscript = fopen(p, "w");
-       if (Xscript == NULL)
-       {
-               Xscript = stdout;
-               syserr("Can't create %s", p);
-       }
-       (void) chmod(p, 0644);
-       Transcript = newstr(p);
-}
-\f/*
-**  SETSENDER -- set sendmail's idea of the sender.
-**
-**     Parameters:
-**             from -- the person we would like to believe this
-**                     is from.
-**
-**     Returns:
-**             none.
-**
-**     Side Effects:
-**             Sets the idea of the sender.
-*/
-
-setsender(from)
-       char *from;
-{
-       register char *p;
-       extern char *getlogin();
-       register struct passwd *pw;
-       char *realname;
-       char cfbuf[40];
-       bool nofullname;
-       extern char *macvalue();
-
-       /*
-       **  Figure out the real user executing us.
-       **      Getlogin can return errno != 0 on non-errors.
-       */
-
-       if (OpMode != MD_SMTP && !QueueRun)
-       {
-               errno = 0;
-               p = getlogin();
-               errno = 0;
-               nofullname = (from != NULL);
-       }
-       else
-       {
-               p = from;
-               nofullname = FALSE;
-       }
-       if (p != NULL && p[0] != '\0')
-       {
-               extern struct passwd *getpwnam();
-
-               pw = getpwnam(p);
-               if (pw == NULL)
-               {
-                       if (OpMode != MD_SMTP && !QueueRun)
-                               syserr("Who are you? (name=%s)", p);
-                       p = NULL;
-               }
-       }
-       if (p == NULL || p[0] == '\0')
-       {
-               extern struct passwd *getpwuid();
-               int uid;
-
-               nofullname = TRUE;
-               uid = getruid();
-               pw = getpwuid(uid);
-               if (pw == NULL)
-                       syserr("Who are you? (uid=%d)", uid);
-               else
-                       p = pw->pw_name;
-       }
-       if (p == NULL || p[0] == '\0' || pw == NULL)
-               finis();
-
-       realname = p;
-
-       /*
-       **  Process passwd file entry.
-       */
-
-       /* run user's .mailcf file */
-       define('z', pw->pw_dir);
-       expand("$z/.mailcf", cfbuf, &cfbuf[sizeof cfbuf - 1], CurEnv);
-       if (!nofullname && safefile(cfbuf, getruid(), S_IREAD))
-               readcf(cfbuf, FALSE);
-
-       /* if the user has given fullname already, don't redefine */
-       if (FullName == NULL)
-               FullName = macvalue('x', CurEnv);
-
-       /* extract full name from passwd file */
-       if (!nofullname && (FullName == NULL || FullName[0] == '\0') &&
-           pw != NULL && pw->pw_gecos != NULL)
-       {
-               char nbuf[MAXNAME];
-
-               fullname(pw, nbuf);
-               if (nbuf[0] != '\0')
-                       FullName = newstr(nbuf);
-       }
-       if (FullName != NULL && FullName[0] != '\0')
-               define('x', FullName);
-
-       setfrom(from, realname);
-}
-\f/*
-**  INITSYS -- initialize instantiation of system
-**
-**     In Daemon mode, this is done in the child.
-**
-**     Parameters:
-**             none.
-**
-**     Returns:
-**             none.
-**
-**     Side Effects:
-**             Initializes the system macros, some global variables,
-**             etc.  In particular, the current time in various
-**             forms is set.
-*/
-
-initsys()
-{
-       static char cbuf[5];                    /* holds hop count */
-       static char dbuf[30];                   /* holds ctime(tbuf) */
-       static char pbuf[10];                   /* holds pid */
-       static char tbuf[20];                   /* holds "current" time */
-       static char ybuf[10];                   /* holds tty id */
-       register char *p;
-       extern char *ttyname();
-       extern char *arpadate();
-       register struct tm *tm;
-       extern struct tm *gmtime();
-       auto time_t now;
-
-       /*
-       **  Give this envelope a reality.
-       **      I.e., an id, a transcript, and a creation time.
-       */
-
-       openxscrpt();
-       CurEnv->e_ctime = curtime();
-
-       /*
-       **  Set OutChannel to something useful if stdout isn't it.
-       **      This arranges that any extra stuff the mailer produces
-       **      gets sent back to the user on error (because it is
-       **      tucked away in the transcript).
-       */
-
-       if (OpMode == MD_DAEMON && QueueRun)
-               OutChannel = Xscript;
-
-       /*
-       **  Set up some basic system macros.
-       */
-
-       /* process id */
-       (void) sprintf(pbuf, "%d", getpid());
-       define('p', pbuf);
-
-       /* hop count */
-       (void) sprintf(cbuf, "%d", HopCount);
-       define('c', cbuf);
-
-       /* time as integer, unix time, arpa time */
-       now = curtime();
-       tm = gmtime(&now);
-       (void) sprintf(tbuf, "%02d%02d%02d%02d%02d", tm->tm_year, tm->tm_mon,
-                       tm->tm_mday, tm->tm_hour, tm->tm_min);
-       define('t', tbuf);
-       (void) strcpy(dbuf, ctime(&now));
-       *index(dbuf, '\n') = '\0';
-       if (macvalue('d', CurEnv) == NULL)
-               define('d', dbuf);
-       p = newstr(arpadate(dbuf));
-       if (macvalue('a', CurEnv) == NULL)
-               define('a', p);
-       define('b', p);
-
-       /* version */
-       define('v', Version);
-
-       /* tty name */
-       if (macvalue('y', CurEnv) == NULL)
-       {
-               p = ttyname(2);
-               if (p != NULL)
-               {
-                       if (rindex(p, '/') != NULL)
-                               p = rindex(p, '/') + 1;
-                       (void) strcpy(ybuf, p);
-                       define('y', ybuf);
-               }
-       }
+       FileName = NULL;
+       unlockqueue(CurEnv);
+       exit(EX_OK);
 }
 \f/*
 **  INITMACROS -- initialize the macro system
 }
 \f/*
 **  INITMACROS -- initialize the macro system
@@ -1138,6 +690,7 @@ struct metamac     MetaMacros[] =
 {
        /* these are important on the LHS */
        '*', MATCHZANY, '+', MATCHANY,  '-', MATCHONE,  '=', MATCHCLASS,
 {
        /* these are important on the LHS */
        '*', MATCHZANY, '+', MATCHANY,  '-', MATCHONE,  '=', MATCHCLASS,
+       '~', MATCHNCLASS,
 
        /* these are RHS metasymbols */
        '#', CANONNET,  '@', CANONHOST, ':', CANONUSER, '>', CALLSUBR,
 
        /* these are RHS metasymbols */
        '#', CANONNET,  '@', CANONHOST, ':', CANONUSER, '>', CALLSUBR,
@@ -1158,209 +711,56 @@ initmacros()
        {
                buf[0] = m->metaval;
                buf[1] = '\0';
        {
                buf[0] = m->metaval;
                buf[1] = '\0';
-               define(m->metaname, newstr(buf));
+               define(m->metaname, newstr(buf), CurEnv);
        }
        buf[0] = MATCHREPL;
        buf[2] = '\0';
        for (c = '0'; c <= '9'; c++)
        {
                buf[1] = c;
        }
        buf[0] = MATCHREPL;
        buf[2] = '\0';
        for (c = '0'; c <= '9'; c++)
        {
                buf[1] = c;
-               define(c, newstr(buf));
+               define(c, newstr(buf), CurEnv);
        }
 }
 \f/*
        }
 }
 \f/*
-**  NEWENVELOPE -- allocate a new envelope
-**
-**     Supports inheritance.
-**
-**     Parameters:
-**             e -- the new envelope to fill in.
-**
-**     Returns:
-**             e.
-**
-**     Side Effects:
-**             none.
-*/
-
-ENVELOPE *
-newenvelope(e)
-       register ENVELOPE *e;
-{
-       register HDR *bh;
-       register HDR **nhp;
-
-       clear((char *) e, sizeof *e);
-       bmove(&CurEnv->e_from, &e->e_from, sizeof e->e_from);
-       e->e_parent = CurEnv;
-       e->e_ctime = curtime();
-       e->e_puthdr = CurEnv->e_puthdr;
-       e->e_putbody = CurEnv->e_putbody;
-       bh = BlankEnvelope.e_header;
-       nhp = &e->e_header;
-       while (bh != NULL)
-       {
-               *nhp = (HDR *) xalloc(sizeof *bh);
-               bmove((char *) bh, (char *) *nhp, sizeof *bh);
-               bh = bh->h_link;
-               nhp = &(*nhp)->h_link;
-       }
-
-       return (e);
-}
-\f/*
-**  DROPENVELOPE -- deallocate an envelope.
-**
-**     Parameters:
-**             e -- the envelope to deallocate.
-**
-**     Returns:
-**             none.
-**
-**     Side Effects:
-**             housekeeping necessary to dispose of an envelope.
-*/
-
-dropenvelope(e)
-       register ENVELOPE *e;
-{
-       if (e->e_df != NULL)
-               xunlink(e->e_df);
-       if (e->e_qf != NULL)
-               xunlink(e->e_qf);
-       if (e->e_id != NULL)
-               xunlink(queuename(e, 'l'));
-}
-\f/*
-**  QUEUENAME -- build a file name in the queue directory for this envelope.
-**
-**     Assigns an id code if one does not already exist.
-**     This code is very careful to avoid trashing existing files
-**     under any circumstances.
-**             We first create an nf file that is only used when
-**             assigning an id.  This file is always empty, so that
-**             we can never accidently truncate an lf file.
-**
-**     Parameters:
-**             e -- envelope to build it in/from.
-**             type -- the file type, used as the first character
-**                     of the file name.
-**
-**     Returns:
-**             a pointer to the new file name (in a static buffer).
-**
-**     Side Effects:
-**             Will create the lf and qf files if no id code is
-**             already assigned.  This will cause the envelope
-**             to be modified.
-*/
-
-char *
-queuename(e, type)
-       register ENVELOPE *e;
-       char type;
-{
-       static char buf[MAXNAME];
-
-       if (e->e_id == NULL)
-       {
-               char counter = 'A' - 1;
-               char qf[20];
-               char lf[20];
-               char nf[20];
-
-               /* find a unique id */
-               (void) sprintf(qf, "qf_%05d", getpid());
-               strcpy(lf, qf);
-               lf[0] = 'l';
-               strcpy(nf, qf);
-               nf[0] = 'n';
-
-               while (counter < '~')
-               {
-                       int i;
-
-                       qf[2] = lf[2] = nf[2] = ++counter;
-# ifdef DEBUG
-                       if (tTd(7, 20))
-                               printf("queuename: trying \"%s\"\n", nf);
-# endif DEBUG
-                       if (access(lf, 0) >= 0 || access(qf, 0) >= 0)
-                               continue;
-                       errno = 0;
-                       i = creat(nf, FileMode);
-                       if (i < 0)
-                       {
-                               (void) unlink(nf);      /* kernel bug */
-                               continue;
-                       }
-                       (void) close(i);
-                       i = link(nf, lf);
-                       (void) unlink(nf);
-                       if (i < 0)
-                               continue;
-                       if (link(lf, qf) >= 0)
-                               break;
-                       (void) unlink(lf);
-               }
-               if (counter >= '~')
-               {
-                       syserr("queuename: Cannot create \"%s\" in \"%s\"",
-                               lf, QueueDir);
-                       exit(EX_OSERR);
-               }
-               e->e_qf = newstr(qf);
-               e->e_id = &e->e_qf[2];
-               define('i', e->e_id);
-# ifdef DEBUG
-               if (tTd(7, 1))
-                       printf("queuename: assigned id %s, env=%x\n", e->e_id, e);
-# endif DEBUG
-       }
-
-       if (type == '\0')
-               return (NULL);
-       (void) sprintf(buf, "%cf%s", type, e->e_id);
-# ifdef DEBUG
-       if (tTd(7, 2))
-               printf("queuename: %s\n", buf);
-# endif DEBUG
-       return (buf);
-}
-\f/*
 **  FREEZE -- freeze BSS & allocated memory
 **
 **     This will be used to efficiently load the configuration file.
 **
 **     Parameters:
 **  FREEZE -- freeze BSS & allocated memory
 **
 **     This will be used to efficiently load the configuration file.
 **
 **     Parameters:
-**             none.
+**             freezefile -- the name of the file to freeze to.
 **
 **     Returns:
 **             none.
 **
 **     Side Effects:
 **
 **     Returns:
 **             none.
 **
 **     Side Effects:
-**             Writes BSS and malloc'ed memory to FreezeFile
+**             Writes BSS and malloc'ed memory to freezefile
 */
 
 */
 
-struct frz
+union frz
 {
 {
-       time_t  frzstamp;               /* timestamp on this freeze */
-       char    *frzbrk;                /* the current break */
-       char    frzver[252];            /* sendmail version */
+       char            frzpad[BUFSIZ]; /* insure we are on a BUFSIZ boundary */
+       struct
+       {
+               time_t  frzstamp;       /* timestamp on this freeze */
+               char    *frzbrk;        /* the current break */
+               char    frzver[252];    /* sendmail version */
+       } frzinfo;
 };
 
 };
 
-freeze()
+freeze(freezefile)
+       char *freezefile;
 {
        int f;
 {
        int f;
-       struct frz fhdr;
+       union frz fhdr;
        extern char edata;
        extern char *sbrk();
        extern char edata;
        extern char *sbrk();
+       extern char Version[];
 
 
-       if (FreezeFile == NULL)
+       if (freezefile == NULL)
                return;
 
        /* try to open the freeze file */
                return;
 
        /* try to open the freeze file */
-       f = open(FreezeFile, 1);
+       f = creat(freezefile, FileMode);
        if (f < 0)
        {
                syserr("Cannot freeze");
        if (f < 0)
        {
                syserr("Cannot freeze");
@@ -1369,14 +769,17 @@ freeze()
        }
 
        /* build the freeze header */
        }
 
        /* build the freeze header */
-       fhdr.frzstamp = curtime();
-       fhdr.frzbrk = sbrk(0);
-       strcpy(fhdr.frzver, Version);
+       fhdr.frzinfo.frzstamp = curtime();
+       fhdr.frzinfo.frzbrk = sbrk(0);
+       strcpy(fhdr.frzinfo.frzver, Version);
 
        /* write out the freeze header */
 
        /* write out the freeze header */
-       if (write(f, &fhdr, sizeof fhdr) != sizeof fhdr ||
-           write(f, &edata, fhdr.frzbrk - &edata) != (fhdr.frzbrk - &edata))
+       if (write(f, (char *) &fhdr, sizeof fhdr) != sizeof fhdr ||
+           write(f, (char *) &edata, fhdr.frzinfo.frzbrk - &edata) !=
+                                       (fhdr.frzinfo.frzbrk - &edata))
+       {
                syserr("Cannot freeze");
                syserr("Cannot freeze");
+       }
 
        /* fine, clean up */
        (void) close(f);
 
        /* fine, clean up */
        (void) close(f);
@@ -1385,27 +788,29 @@ freeze()
 **  THAW -- read in the frozen configuration file.
 **
 **     Parameters:
 **  THAW -- read in the frozen configuration file.
 **
 **     Parameters:
-**             none.
+**             freezefile -- the name of the file to thaw from.
 **
 **     Returns:
 **             TRUE if it successfully read the freeze file.
 **             FALSE otherwise.
 **
 **     Side Effects:
 **
 **     Returns:
 **             TRUE if it successfully read the freeze file.
 **             FALSE otherwise.
 **
 **     Side Effects:
-**             reads FreezeFile in to BSS area.
+**             reads freezefile in to BSS area.
 */
 
 */
 
-thaw()
+thaw(freezefile)
+       char *freezefile;
 {
        int f;
 {
        int f;
-       struct frz fhdr;
+       union frz fhdr;
        extern char edata;
        extern char edata;
+       extern char Version[];
 
 
-       if (FreezeFile == NULL)
+       if (freezefile == NULL)
                return (FALSE);
 
        /* open the freeze file */
                return (FALSE);
 
        /* open the freeze file */
-       f = open(FreezeFile, 0);
+       f = open(freezefile, 0);
        if (f < 0)
        {
                errno = 0;
        if (f < 0)
        {
                errno = 0;
@@ -1413,29 +818,116 @@ thaw()
        }
 
        /* read in the header */
        }
 
        /* read in the header */
-       if (read(f, &fhdr, sizeof fhdr) < sizeof fhdr ||
-           strcmp(fhdr.frzver, Version) != 0)
+       if (read(f, (char *) &fhdr, sizeof fhdr) < sizeof fhdr ||
+           strcmp(fhdr.frzinfo.frzver, Version) != 0)
        {
                (void) close(f);
                return (FALSE);
        }
 
        /* arrange to have enough space */
        {
                (void) close(f);
                return (FALSE);
        }
 
        /* arrange to have enough space */
-       if (brk(fhdr.frzbrk) < 0)
+       if (brk(fhdr.frzinfo.frzbrk) < 0)
        {
        {
-               syserr("Cannot break to %x", fhdr.frzbrk);
+               syserr("Cannot break to %x", fhdr.frzinfo.frzbrk);
                (void) close(f);
                return (FALSE);
        }
 
        /* now read in the freeze file */
                (void) close(f);
                return (FALSE);
        }
 
        /* now read in the freeze file */
-       if (read(f, &edata, fhdr.frzbrk - &edata) != (fhdr.frzbrk - &edata))
+       if (read(f, (char *) &edata, fhdr.frzinfo.frzbrk - &edata) !=
+                                       (fhdr.frzinfo.frzbrk - &edata))
        {
                /* oops!  we have trashed memory..... */
        {
                /* oops!  we have trashed memory..... */
-               fprintf(stderr, "Cannot read freeze file\n");
-               exit(EX_SOFTWARE);
+               write(2, "Cannot read freeze file\n", 24);
+               _exit(EX_SOFTWARE);
        }
 
        (void) close(f);
        return (TRUE);
 }
        }
 
        (void) close(f);
        return (TRUE);
 }
+\f/*
+**  DISCONNECT -- remove our connection with any foreground process
+**
+**     Parameters:
+**             fulldrop -- if set, we should also drop the controlling
+**                     TTY if possible -- this should only be done when
+**                     setting up the daemon since otherwise UUCP can
+**                     leave us trying to open a dialin, and we will
+**                     wait for the carrier.
+**
+**     Returns:
+**             none
+**
+**     Side Effects:
+**             Trys to insure that we are immune to vagaries of
+**             the controlling tty.
+*/
+
+disconnect(fulldrop)
+       bool fulldrop;
+{
+       int fd;
+
+#ifdef DEBUG
+       if (tTd(52, 1))
+               printf("disconnect: In %d Out %d\n", fileno(InChannel),
+                                               fileno(OutChannel));
+       if (tTd(52, 5))
+       {
+               printf("don't\n");
+               return;
+       }
+#endif DEBUG
+
+       /* be sure we don't get nasty signals */
+       signal(SIGHUP, SIG_IGN);
+       signal(SIGINT, SIG_IGN);
+       signal(SIGQUIT, SIG_IGN);
+
+       /* we can't communicate with our caller, so.... */
+       HoldErrs = TRUE;
+       ErrorMode = EM_MAIL;
+       Verbose = FALSE;
+
+       /* all input from /dev/null */
+       if (InChannel != stdin)
+       {
+               (void) fclose(InChannel);
+               InChannel = stdin;
+       }
+       (void) freopen("/dev/null", "r", stdin);
+
+       /* output to the transcript */
+       if (OutChannel != stdout)
+       {
+               (void) fclose(OutChannel);
+               OutChannel = stdout;
+       }
+       if (CurEnv->e_xfp == NULL)
+               CurEnv->e_xfp = fopen("/dev/null", "w");
+       (void) fflush(stdout);
+       (void) close(1);
+       (void) close(2);
+       while ((fd = dup(fileno(CurEnv->e_xfp))) < 2 && fd > 0)
+               continue;
+
+#ifdef TIOCNOTTY
+       /* drop our controlling TTY completely if possible */
+       if (fulldrop)
+       {
+               fd = open("/dev/tty", 2);
+               if (fd >= 0)
+               {
+                       (void) ioctl(fd, TIOCNOTTY, 0);
+                       (void) close(fd);
+               }
+       }
+#endif TIOCNOTTY
+
+# ifdef LOG
+       if (LogLevel > 11)
+               syslog(LOG_DEBUG, "in background, pid=%d", getpid());
+# endif LOG
+
+       errno = 0;
+}