ignore -t in -bd mode
[unix-history] / usr / src / usr.sbin / sendmail / src / main.c
index 14cf676..f142636 100644 (file)
@@ -1,5 +1,5 @@
 /*
 /*
- * Copyright (c) 1983 Eric P. Allman
+ * Copyright (c) 1983, 1995 Eric P. Allman
  * Copyright (c) 1988, 1993
  *     The Regents of the University of California.  All rights reserved.
  *
  * Copyright (c) 1988, 1993
  *     The Regents of the University of California.  All rights reserved.
  *
@@ -13,7 +13,7 @@ static char copyright[] =
 #endif /* not lint */
 
 #ifndef lint
 #endif /* not lint */
 
 #ifndef lint
-static char sccsid[] = "@(#)main.c     8.101 (Berkeley) %G%";
+static char sccsid[] = "@(#)main.c     8.123 (Berkeley) %G%";
 #endif /* not lint */
 
 #define        _DEFINE
 #endif /* not lint */
 
 #define        _DEFINE
@@ -66,9 +66,6 @@ ENVELOPE      BlankEnvelope;  /* a "blank" envelope */
 ENVELOPE       MainEnvelope;   /* the envelope around the basic letter */
 ADDRESS                NullAddress =   /* a null address */
                { "", "", NULL, "" };
 ENVELOPE       MainEnvelope;   /* the envelope around the basic letter */
 ADDRESS                NullAddress =   /* a null address */
                { "", "", NULL, "" };
-char           *UserEnviron[MAXUSERENVIRON + 2];
-                               /* saved user environment */
-char           RealUserName[256];      /* the actual user id on this host */
 char           *CommandLineArgs;       /* command line args for pid file */
 bool           Warn_Q_option = FALSE;  /* warn about Q option use */
 char           **SaveArgv;     /* argument vector for re-execing */
 char           *CommandLineArgs;       /* command line args for pid file */
 bool           Warn_Q_option = FALSE;  /* warn about Q option use */
 char           **SaveArgv;     /* argument vector for re-execing */
@@ -91,6 +88,7 @@ ERROR %%%%   Cannot have daemon mode without SMTP   %%%% ERROR
 
 #define MAXCONFIGLEVEL 6       /* highest config version level known */
 
 
 #define MAXCONFIGLEVEL 6       /* highest config version level known */
 
+int
 main(argc, argv, envp)
        int argc;
        char **argv;
 main(argc, argv, envp)
        int argc;
        char **argv;
@@ -110,15 +108,14 @@ main(argc, argv, envp)
        bool warn_C_flag = FALSE;
        char warn_f_flag = '\0';
        static bool reenter = FALSE;
        bool warn_C_flag = FALSE;
        char warn_f_flag = '\0';
        static bool reenter = FALSE;
-       char *argv0 = argv[0];
        struct passwd *pw;
        struct stat stb;
        struct hostent *hp;
        char jbuf[MAXHOSTNAMELEN];      /* holds MyHostName */
        struct passwd *pw;
        struct stat stb;
        struct hostent *hp;
        char jbuf[MAXHOSTNAMELEN];      /* holds MyHostName */
+       static char rnamebuf[MAXNAME];  /* holds RealUserName */
        extern int DtableSize;
        extern int optind;
        extern time_t convtime();
        extern int DtableSize;
        extern int optind;
        extern time_t convtime();
-       extern putheader(), putbody();
        extern void intsig();
        extern struct hostent *myhostname();
        extern char *arpadate();
        extern void intsig();
        extern struct hostent *myhostname();
        extern char *arpadate();
@@ -128,6 +125,7 @@ main(argc, argv, envp)
        extern char **environ;
        extern void sigusr1();
        extern void sighup();
        extern char **environ;
        extern void sigusr1();
        extern void sighup();
+       extern void initmacros __P((ENVELOPE *));
 
        /*
        **  Check to see if we reentered.
 
        /*
        **  Check to see if we reentered.
@@ -210,9 +208,10 @@ main(argc, argv, envp)
 
        pw = sm_getpwuid(RealUid);
        if (pw != NULL)
 
        pw = sm_getpwuid(RealUid);
        if (pw != NULL)
-               (void) strcpy(RealUserName, pw->pw_name);
+               (void) strcpy(rnamebuf, pw->pw_name);
        else
        else
-               (void) sprintf(RealUserName, "Unknown UID %d", RealUid);
+               (void) sprintf(rnamebuf, "Unknown UID %d", RealUid);
+       RealUserName = rnamebuf;
 
        /* save command line arguments */
        i = 0;
 
        /* save command line arguments */
        i = 0;
@@ -266,9 +265,9 @@ main(argc, argv, envp)
                int ll;
                extern char *CompileOptions[];
 
                int ll;
                extern char *CompileOptions[];
 
-               printf("Version %s", Version);
+               printf("Version %s\nCompiled with:\t", Version);
                av = CompileOptions;
                av = CompileOptions;
-               ll = 100;
+               ll = 7;
                while (*av != NULL)
                {
                        if (ll + strlen(*av) > 63)
                while (*av != NULL)
                {
                        if (ll + strlen(*av) > 63)
@@ -277,13 +276,46 @@ main(argc, argv, envp)
                                ll = 0;
                        }
                        if (ll == 0)
                                ll = 0;
                        }
                        if (ll == 0)
+                       {
                                putchar('\t');
                                putchar('\t');
-                       else
-                               putchar(' ');
+                               putchar('\t');
+                       }
+                       putchar(' ');
+                       printf("%s", *av);
+                       ll += strlen(*av++) + 1;
+               }
+               putchar('\n');
+       }
+       if (tTd(0, 10))
+       {
+               int ll;
+               extern char *OsCompileOptions[];
+
+               printf("OS Defines:\t", Version);
+               av = OsCompileOptions;
+               ll = 7;
+               while (*av != NULL)
+               {
+                       if (ll + strlen(*av) > 63)
+                       {
+                               putchar('\n');
+                               ll = 0;
+                       }
+                       if (ll == 0)
+                       {
+                               putchar('\t');
+                               putchar('\t');
+                       }
+                       putchar(' ');
                        printf("%s", *av);
                        ll += strlen(*av++) + 1;
                }
                putchar('\n');
                        printf("%s", *av);
                        ll += strlen(*av++) + 1;
                }
                putchar('\n');
+#ifdef _PATH_UNIX
+               printf("Unix path:\t  %s\n", _PATH_UNIX);
+#endif
+               printf("Config file:\t  %s\n", getcfname());
+               printf("Proc Id file:\t  %s\n", PidFile);
        }
 
        InChannel = stdin;
        }
 
        InChannel = stdin;
@@ -294,14 +326,15 @@ main(argc, argv, envp)
        **  the top of memory.
        */
 
        **  the top of memory.
        */
 
-       for (i = j = 0; j < MAXUSERENVIRON && (p = envp[i]) != NULL; i++)
-       {
-               if (strncmp(p, "IFS=", 4) == 0 || strncmp(p, "LD_", 3) == 0)
-                       continue;
-               UserEnviron[j++] = newstr(p);
-       }
-       UserEnviron[j] = NULL;
-       environ = UserEnviron;
+       for (i = 0; envp[i] != NULL; i++)
+               continue;
+       environ = (char **) xalloc(sizeof (char *) * i);
+       for (i = 0; envp[i] != NULL; i++)
+               environ[i] = newstr(envp[i]);
+       environ[i] = NULL;
+
+       /* and prime the child environment */
+       setuserenv("AGENT", "sendmail");
 
        /*
        **  Save start and extent of argv for setproctitle.
 
        /*
        **  Save start and extent of argv for setproctitle.
@@ -360,7 +393,6 @@ main(argc, argv, envp)
                        if (p[1] != '\0')
                        {
                                define('m', newstr(&p[1]), CurEnv);
                        if (p[1] != '\0')
                        {
                                define('m', newstr(&p[1]), CurEnv);
-                               setclass('m', &p[1]);
                        }
                        while (p != NULL && strchr(&p[1], '.') != NULL)
                        {
                        }
                        while (p != NULL && strchr(&p[1], '.') != NULL)
                        {
@@ -412,6 +444,9 @@ main(argc, argv, envp)
                }
        }
 
                }
        }
 
+       /* probe interfaces and locate any additional names */
+       load_if_names();
+
        /* current time */
        define('b', arpadate((char *) NULL), CurEnv);
 
        /* current time */
        define('b', arpadate((char *) NULL), CurEnv);
 
@@ -664,7 +699,13 @@ main(argc, argv, envp)
 #ifdef XDEBUG
        checkfd012("before readcf");
 #endif
 #ifdef XDEBUG
        checkfd012("before readcf");
 #endif
+       vendor_pre_defaults(CurEnv);
        readcf(getcfname(), safecf, CurEnv);
        readcf(getcfname(), safecf, CurEnv);
+       vendor_post_defaults(CurEnv);
+
+       /* set up the $=m class now, after .cf has a chance to redefine $m */
+       expand("\201m", jbuf, sizeof jbuf, CurEnv);
+       setclass('m', jbuf);
 
        if (tTd(0, 1))
        {
 
        if (tTd(0, 1))
        {
@@ -705,9 +746,7 @@ main(argc, argv, envp)
        if (warn_C_flag)
                auth_warning(CurEnv, "Processed by %s with -C %s",
                        RealUserName, ConfFile);
        if (warn_C_flag)
                auth_warning(CurEnv, "Processed by %s with -C %s",
                        RealUserName, ConfFile);
-       if (warn_f_flag != '\0' &&
-           ((st = stab(RealUserName, ST_CLASS, ST_FIND)) == NULL ||
-            !bitnset('t', st->s_class)))
+       if (warn_f_flag != '\0' && !wordinclass(RealUserName, 't'))
                auth_warning(CurEnv, "%s set sender to %s using -%c",
                        RealUserName, from, warn_f_flag);
        if (Warn_Q_option)
                auth_warning(CurEnv, "%s set sender to %s using -%c",
                        RealUserName, from, warn_f_flag);
        if (Warn_Q_option)
@@ -721,23 +760,7 @@ main(argc, argv, envp)
        if (TimeZoneSpec == NULL)
                unsetenv("TZ");
        else if (TimeZoneSpec[0] != '\0')
        if (TimeZoneSpec == NULL)
                unsetenv("TZ");
        else if (TimeZoneSpec[0] != '\0')
-       {
-               char **evp = UserEnviron;
-               char tzbuf[100];
-
-               strcpy(tzbuf, "TZ=");
-               strcpy(&tzbuf[3], TimeZoneSpec);
-
-               while (*evp != NULL && strncmp(*evp, "TZ=", 3) != 0)
-                       evp++;
-               if (*evp == NULL)
-               {
-                       *evp++ = newstr(tzbuf);
-                       *evp = NULL;
-               }
-               else
-                       *evp++ = newstr(tzbuf);
-       }
+               setuserenv("TZ", TimeZoneSpec);
        tzset();
 
        if (ConfigLevel > MAXCONFIGLEVEL)
        tzset();
 
        if (ConfigLevel > MAXCONFIGLEVEL)
@@ -754,6 +777,7 @@ main(argc, argv, envp)
          case MD_DAEMON:
                /* remove things that don't make sense in daemon mode */
                FullName = NULL;
          case MD_DAEMON:
                /* remove things that don't make sense in daemon mode */
                FullName = NULL;
+               GrabTo = FALSE;
 
                /* arrange to restart on hangup signal */
                setsignal(SIGHUP, sighup);
 
                /* arrange to restart on hangup signal */
                setsignal(SIGHUP, sighup);
@@ -809,13 +833,19 @@ main(argc, argv, envp)
        if (st == NULL)
                syserr("No prog mailer defined");
        else
        if (st == NULL)
                syserr("No prog mailer defined");
        else
+       {
                ProgMailer = st->s_mailer;
                ProgMailer = st->s_mailer;
+               clrbitn(M_MUSER, ProgMailer->m_flags);
+       }
 
        st = stab("*file*", ST_MAILER, ST_FIND);
        if (st == NULL)
                syserr("No *file* mailer defined");
        else
 
        st = stab("*file*", ST_MAILER, ST_FIND);
        if (st == NULL)
                syserr("No *file* mailer defined");
        else
+       {
                FileMailer = st->s_mailer;
                FileMailer = st->s_mailer;
+               clrbitn(M_MUSER, FileMailer->m_flags);
+       }
 
        st = stab("*include*", ST_MAILER, ST_FIND);
        if (st == NULL)
 
        st = stab("*include*", ST_MAILER, ST_FIND);
        if (st == NULL)
@@ -825,9 +855,6 @@ main(argc, argv, envp)
 
        if (ConfigLevel < 6)
        {
 
        if (ConfigLevel < 6)
        {
-               /* need config support for group:; handling */
-               ColonOkInAddr = TRUE;
-
                /* heuristic tweaking of local mailer for back compat */
                if (LocalMailer != NULL)
                {
                /* heuristic tweaking of local mailer for back compat */
                if (LocalMailer != NULL)
                {
@@ -843,14 +870,20 @@ main(argc, argv, envp)
                        setbitn(M_RUNASRCPT, ProgMailer->m_flags);
                if (FileMailer != NULL)
                        setbitn(M_RUNASRCPT, FileMailer->m_flags);
                        setbitn(M_RUNASRCPT, ProgMailer->m_flags);
                if (FileMailer != NULL)
                        setbitn(M_RUNASRCPT, FileMailer->m_flags);
+
+               /* propogate some envariables into children */
+               setuserenv("ISP", NULL);
+               setuserenv("SYSTYPE", NULL);
        }
 
        }
 
-       /* initialize standard MIME classes */
-       setclass('n', "message/rfc822");
-       setclass('n', "message/partial");
-       setclass('n', "message/external-body");
+       /* MIME Content-Types that cannot be transfer encoded */
        setclass('n', "multipart/signed");
 
        setclass('n', "multipart/signed");
 
+       /* MIME Content-Transfer-Encodings that can be encoded */
+       setclass('e', "7bit");
+       setclass('e', "8bit");
+       setclass('e', "binary");
+
        /* operate in queue directory */
        if (OpMode != MD_TEST && chdir(QueueDir) < 0)
        {
        /* operate in queue directory */
        if (OpMode != MD_TEST && chdir(QueueDir) < 0)
        {
@@ -911,6 +944,7 @@ main(argc, argv, envp)
                exit(EX_OK);
 
          case MD_DAEMON:
                exit(EX_OK);
 
          case MD_DAEMON:
+         case MD_SMTP:
                /* don't open alias database -- done in srvrsmtp */
                break;
 
                /* don't open alias database -- done in srvrsmtp */
                break;
 
@@ -957,13 +991,18 @@ main(argc, argv, envp)
                }
                for (;;)
                {
                }
                for (;;)
                {
+                       extern void testmodeline __P((char *, ENVELOPE *));
+
                        if (Verbose)
                                printf("> ");
                        (void) fflush(stdout);
                        if (fgets(buf, sizeof buf, stdin) == NULL)
                                finis();
                        if (Verbose)
                                printf("> ");
                        (void) fflush(stdout);
                        if (fgets(buf, sizeof buf, stdin) == NULL)
                                finis();
+                       p = strchr(buf, '\n');
+                       if (p != NULL)
+                               *p = '\0';
                        if (!Verbose)
                        if (!Verbose)
-                               printf("> %s", buf);
+                               printf("> %s\n", buf);
                        testmodeline(buf, CurEnv);
                }
        }
                        testmodeline(buf, CurEnv);
                }
        }
@@ -993,7 +1032,7 @@ main(argc, argv, envp)
        {
                char dtype[200];
 
        {
                char dtype[200];
 
-               if (!tTd(0, 1))
+               if (!tTd(52, 100))
                {
                        /* put us in background */
                        i = fork();
                {
                        /* put us in background */
                        i = fork();
@@ -1065,6 +1104,7 @@ main(argc, argv, envp)
        {
                CurEnv->e_sendmode = SM_VERIFY;
                CurEnv->e_errormode = EM_QUIET;
        {
                CurEnv->e_sendmode = SM_VERIFY;
                CurEnv->e_errormode = EM_QUIET;
+               PostMasterCopy = NULL;
        }
        else
        {
        }
        else
        {
@@ -1183,7 +1223,7 @@ finis()
        if (LogLevel > 78)
                syslog(LOG_DEBUG, "finis, pid=%d", getpid());
 # endif /* LOG */
        if (LogLevel > 78)
                syslog(LOG_DEBUG, "finis, pid=%d", getpid());
 # endif /* LOG */
-       if (ExitStat == EX_TEMPFAIL)
+       if (ExitStat == EX_TEMPFAIL || CurEnv->e_errormode == EM_BERKNET)
                ExitStat = EX_OK;
 
        /* reset uid for process accounting */
                ExitStat = EX_OK;
 
        /* reset uid for process accounting */
@@ -1261,6 +1301,7 @@ struct metamac    MetaMacros[] =
        '\0'
 };
 
        '\0'
 };
 
+void
 initmacros(e)
        register ENVELOPE *e;
 {
 initmacros(e)
        register ENVELOPE *e;
 {
@@ -1309,6 +1350,7 @@ initmacros(e)
 **             the controlling tty.
 */
 
 **             the controlling tty.
 */
 
+void
 disconnect(droplev, e)
        int droplev;
        register ENVELOPE *e;
 disconnect(droplev, e)
        int droplev;
        register ENVELOPE *e;
@@ -1318,7 +1360,7 @@ disconnect(droplev, e)
        if (tTd(52, 1))
                printf("disconnect: In %d Out %d, e=%x\n",
                        fileno(InChannel), fileno(OutChannel), e);
        if (tTd(52, 1))
                printf("disconnect: In %d Out %d, e=%x\n",
                        fileno(InChannel), fileno(OutChannel), e);
-       if (tTd(52, 5))
+       if (tTd(52, 100))
        {
                printf("don't\n");
                return;
        {
                printf("don't\n");
                return;
@@ -1483,6 +1525,58 @@ auth_warning(e, msg, va_alist)
        }
 }
 \f/*
        }
 }
 \f/*
+**  SETUSERENV -- set an environment in the propogated environment
+**
+**     Parameters:
+**             envar -- the name of the environment variable.
+**             value -- the value to which it should be set.  If
+**                     null, this is extracted from the incoming
+**                     environment.  If that is not set, the call
+**                     to setuserenv is ignored.
+**
+**     Returns:
+**             none.
+*/
+
+void
+setuserenv(envar, value)
+       const char *envar;
+       const char *value;
+{
+       int i;
+       char **evp = UserEnviron;
+       char *p;
+
+       if (value == NULL)
+       {
+               value = getenv(envar);
+               if (value == NULL)
+                       return;
+       }
+
+       i = strlen(envar);
+       p = (char *) xalloc(strlen(value) + i + 2);
+       strcpy(p, envar);
+       p[i++] = '=';
+       strcpy(&p[i], value);
+
+       while (*evp != NULL && strncmp(*evp, p, i) != 0)
+               evp++;
+       if (*evp != NULL)
+       {
+               *evp++ = p;
+       }
+       else if (evp < &UserEnviron[MAXUSERENVIRON])
+       {
+               *evp++ = p;
+               *evp = NULL;
+       }
+
+       /* make sure it is in our environment as well */
+       if (putenv(p) < 0)
+               syserr("setuserenv: putenv(%s) failed", p);
+}
+\f/*
 **  DUMPSTATE -- dump state
 **
 **     For debugging.
 **  DUMPSTATE -- dump state
 **
 **     For debugging.
@@ -1554,6 +1648,7 @@ sighup()
 **             e -- the current environment.
 */
 
 **             e -- the current environment.
 */
 
+void
 testmodeline(line, e)
        char *line;
        ENVELOPE *e;
 testmodeline(line, e)
        char *line;
        ENVELOPE *e;
@@ -1561,6 +1656,8 @@ testmodeline(line, e)
        register char *p;
        char *q;
        auto char *delimptr;
        register char *p;
        char *q;
        auto char *delimptr;
+       int mid;
+       ADDRESS a;
        extern bool invalidaddr();
        extern char *crackaddr();
 
        extern bool invalidaddr();
        extern char *crackaddr();
 
@@ -1569,17 +1666,13 @@ testmodeline(line, e)
          case '#':
                return;
 
          case '#':
                return;
 
-         case '?':             /* try crackaddr */
-               q = crackaddr(&line[1]);
-               xputs(q);
-               printf("\n");
-               return;
-
          case '.':             /* config-style settings */
                switch (line[1])
                {
                  case 'D':
          case '.':             /* config-style settings */
                switch (line[1])
                {
                  case 'D':
-                       define(line[2], newstr(&line[3]), e);
+                       mid = macid(&line[2], &delimptr);
+                       if (mid != '\0')
+                               define(mid, newstr(delimptr), e);
                        break;
 
                  case 'C':
                        break;
 
                  case 'C':
@@ -1590,14 +1683,11 @@ testmodeline(line, e)
                        {
                                int rs;
                                struct rewrite *rw;
                        {
                                int rs;
                                struct rewrite *rw;
-                               char *cp;
                                STAB *s;
 
                                STAB *s;
 
-                               if ((cp = strchr(line, '\n')) != NULL)
-                                       *cp = '\0';
-                               if (cp == line+2)
+                               if (line[2] == '\0')
                                        return;
                                        return;
-                               s = stab(line+2, ST_RULESET, ST_FIND);
+                               s = stab(&line[2], ST_RULESET, ST_FIND);
                                if (s == NULL)
                                {
                                        if (!isdigit(line[2]))
                                if (s == NULL)
                                {
                                        if (!isdigit(line[2]))
@@ -1643,10 +1733,7 @@ testmodeline(line, e)
                switch (line[1])
                {
                  case 'd':
                switch (line[1])
                {
                  case 'd':
-                       if (line[2] == '\n')
-                               tTflag("");
-                       else
-                               tTflag(&line[2]);
+                       tTflag(&line[2]);
                        break;
 
                  default:
                        break;
 
                  default:
@@ -1655,13 +1742,24 @@ testmodeline(line, e)
                }
                return;
 
                }
                return;
 
-         case '/':             /* miscellaneous commands */
-               p = strchr(line, '\n');
-               if (p != NULL)
+         case '$':
+               mid = macid(&line[1], NULL);
+               if (mid == '\0')
+                       return;
+               p = macvalue(mid, e);
+               if (p == NULL)
+                       printf("Undefined\n");
+               else
                {
                {
-                       while (p >= line && isascii(*p) && isspace(*p))
-                               *p-- = '\0';
+                       xputs(p);
+                       printf("\n");
                }
                }
+               return;
+
+         case '/':             /* miscellaneous commands */
+               p = &line[strlen(line)];
+               while (--p >= line && isascii(*p) && isspace(*p))
+                       *p = '\0';
                p = strpbrk(line, " \t");
                if (p != NULL)
                {
                p = strpbrk(line, " \t");
                if (p != NULL)
                {
@@ -1680,13 +1778,28 @@ testmodeline(line, e)
                        char *mxhosts[MAXMXHOSTS + 1];
 
                        nmx = getmxrr(p, mxhosts, FALSE, &rcode);
                        char *mxhosts[MAXMXHOSTS + 1];
 
                        nmx = getmxrr(p, mxhosts, FALSE, &rcode);
-                       printf("%d MX records:\n", nmx);
+                       printf("getmxrr(%s) returns %d value(s):\n", p, nmx);
                        for (i = 0; i < nmx; i++)
                                printf("\t%s\n", mxhosts[i]);
 #else
                        printf("No MX code compiled in\n");
 #endif
                }
                        for (i = 0; i < nmx; i++)
                                printf("\t%s\n", mxhosts[i]);
 #else
                        printf("No MX code compiled in\n");
 #endif
                }
+               else if (strcasecmp(&line[1], "try") == 0)
+               {
+                       q = crackaddr(p);
+                       printf("Cracked address = ");
+                       xputs(q);
+                       printf("\n");
+                       if (parseaddr(p, &a, RF_COPYNONE, '\0', NULL, e) == NULL)
+                               printf("Cannot parse\n");
+                       else if (a.q_host != NULL && a.q_host[0] != '\0')
+                               printf("mailer %s, host %s, user %s\n",
+                                       a.q_mailer->m_name, a.q_host, a.q_user);
+                       else
+                               printf("mailer %s, user %s\n",
+                                       a.q_mailer->m_name, a.q_user);
+               }
                else
                {
                        printf("Unknown test command %s\n", line);
                else
                {
                        printf("Unknown test command %s\n", line);