diff options
Diffstat (limited to 'usr.sbin/sendmail/src/main.c')
-rw-r--r-- | usr.sbin/sendmail/src/main.c | 1087 |
1 files changed, 242 insertions, 845 deletions
diff --git a/usr.sbin/sendmail/src/main.c b/usr.sbin/sendmail/src/main.c index 5e352f2..bae41d5 100644 --- a/usr.sbin/sendmail/src/main.c +++ b/usr.sbin/sendmail/src/main.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1983, 1995 Eric P. Allman + * Copyright (c) 1983 Eric P. Allman * Copyright (c) 1988, 1993 * The Regents of the University of California. All rights reserved. * @@ -39,15 +39,17 @@ static char copyright[] = #endif /* not lint */ #ifndef lint -static char sccsid[] = "@(#)main.c 8.162 (Berkeley) 11/18/95"; +static char sccsid[] = "@(#)main.c 8.55.1.7 (Berkeley) 3/5/95"; #endif /* not lint */ #define _DEFINE #include "sendmail.h" #if NAMED_BIND +#include <arpa/nameser.h> #include <resolv.h> #endif +#include <pwd.h> # ifdef lint char edata, end; @@ -92,9 +94,21 @@ ENVELOPE BlankEnvelope; /* a "blank" envelope */ 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 */ + +/* +** Pointers for setproctitle. +** This allows "ps" listings to give more useful information. +*/ + +# ifdef SETPROCTITLE +char **Argv = NULL; /* pointer to argument vector */ +char *LastArgv = NULL; /* end of argv */ +# endif /* SETPROCTITLE */ static void obsolete(); @@ -104,9 +118,8 @@ ERROR %%%% Cannot have daemon mode without SMTP %%%% ERROR #endif /* SMTP */ #endif /* DAEMON */ -#define MAXCONFIGLEVEL 6 /* highest config version level known */ +#define MAXCONFIGLEVEL 5 /* highest config version level known */ -int main(argc, argv, envp) int argc; char **argv; @@ -114,6 +127,7 @@ main(argc, argv, envp) { register char *p; char **av; + extern int finis(); extern char Version[]; char *ep, *from; typedef int (*fnptr)(); @@ -125,25 +139,22 @@ main(argc, argv, envp) 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 */ - static char rnamebuf[MAXNAME]; /* holds RealUserName */ extern int DtableSize; extern int optind; - extern int opterr; extern time_t convtime(); + extern putheader(), putbody(); extern void intsig(); - extern struct hostent *myhostname(); + extern char **myhostname(); extern char *arpadate(); extern char *getauthinfo(); extern char *getcfname(); extern char *optarg; extern char **environ; extern void sigusr1(); - extern void sighup(); - extern void initmacros __P((ENVELOPE *)); /* ** Check to see if we reentered. @@ -161,8 +172,8 @@ main(argc, argv, envp) /* do machine-dependent initializations */ init_md(argc, argv); + /* arrange to dump state on signal */ #ifdef SIGUSR1 - /* arrange to dump state on user-1 signal */ setsignal(SIGUSR1, sigusr1); #endif @@ -197,12 +208,10 @@ main(argc, argv, envp) #ifdef LOG # ifdef LOG_MAIL openlog("sendmail", LOG_PID, LOG_MAIL); -# else +# else openlog("sendmail", LOG_PID); # endif -#endif - - tTsetup(tTdvect, sizeof tTdvect, "0-99.1"); +#endif /* set up the blank envelope */ BlankEnvelope.e_puthdr = putheader; @@ -222,29 +231,25 @@ main(argc, argv, envp) RealUid = getuid(); RealGid = getgid(); - pw = sm_getpwuid(RealUid); + pw = getpwuid(RealUid); if (pw != NULL) - (void) strcpy(rnamebuf, pw->pw_name); + (void) strcpy(RealUserName, pw->pw_name); else - (void) sprintf(rnamebuf, "Unknown UID %d", RealUid); - RealUserName = rnamebuf; + (void) sprintf(RealUserName, "Unknown UID %d", RealUid); /* save command line arguments */ i = 0; for (av = argv; *av != NULL; ) i += strlen(*av++) + 1; - SaveArgv = (char **) xalloc(sizeof (char *) * (argc + 1)); CommandLineArgs = xalloc(i); p = CommandLineArgs; - for (av = argv, i = 0; *av != NULL; ) + for (av = argv; *av != NULL; ) { - SaveArgv[i++] = newstr(*av); if (av != argv) *p++ = ' '; strcpy(p, *av++); p += strlen(p); } - SaveArgv[i] = NULL; /* Handle any non-getoptable constructions. */ obsolete(argv); @@ -254,98 +259,63 @@ main(argc, argv, envp) */ #if defined(__osf__) || defined(_AIX3) -# define OPTIONS "B:b:C:cd:e:F:f:h:IiM:mnO:o:p:q:r:sTtvX:x" +# define OPTIONS "B:b:C:cd:e:F:f:h:Iimno:p:q:r:sTtvX:x" +#endif +#if defined(ultrix) +# define OPTIONS "B:b:C:cd:e:F:f:h:IiM:mno:p:q:r:sTtvX:" #endif -#if defined(sony_news) -# define OPTIONS "B:b:C:cd:E:e:F:f:h:IiJ:M:mnO:o:p:q:r:sTtvX:" +#if defined(NeXT) +# define OPTIONS "B:b:C:cd:e:F:f:h:IimnOo:p:q:r:sTtvX:" #endif #ifndef OPTIONS -# define OPTIONS "B:b:C:cd:e:F:f:h:IiM:mnO:o:p:q:r:sTtvX:" +# define OPTIONS "B:b:C:cd:e:F:f:h:Iimno:p:q:r:sTtvX:" #endif - opterr = 0; while ((j = getopt(argc, argv, OPTIONS)) != EOF) { switch (j) { case 'd': + tTsetup(tTdvect, sizeof tTdvect, "0-99.1"); tTflag(optarg); setbuf(stdout, (char *) NULL); + printf("Version %s\n", Version); break; } } - opterr = 1; - if (tTd(0, 1)) - { - int ll; - extern char *CompileOptions[]; + InChannel = stdin; + OutChannel = stdout; - printf("Version %s\n Compiled with:", Version); - av = CompileOptions; - ll = 7; - while (*av != NULL) - { - if (ll + strlen(*av) > 63) - { - putchar('\n'); - ll = 0; - } - if (ll == 0) - { - putchar('\t'); - putchar('\t'); - } - else - putchar(' '); - printf("%s", *av); - ll += strlen(*av++) + 1; - } - putchar('\n'); - } - if (tTd(0, 10)) - { - int ll; - extern char *OsCompileOptions[]; + /* + ** Move the environment so setproctitle can use the space at + ** the top of memory. + */ - printf(" OS Defines:", Version); - av = OsCompileOptions; - ll = 7; - while (*av != NULL) - { - if (ll + strlen(*av) > 63) - { - putchar('\n'); - ll = 0; - } - if (ll == 0) - { - putchar('\t'); - putchar('\t'); - } - else - putchar(' '); - printf("%s", *av); - ll += strlen(*av++) + 1; - } - putchar('\n'); -#ifdef _PATH_UNIX - printf("Kernel symbols:\t%s\n", _PATH_UNIX); -#endif - printf(" Config file:\t%s\n", getcfname()); - printf(" Pid file:\t%s\n", PidFile); + 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; - InChannel = stdin; - OutChannel = stdout; - - /* initialize for setproctitle */ - initsetproctitle(argc, argv, envp); +# ifdef SETPROCTITLE + /* + ** Save start and extent of argv for setproctitle. + */ - /* prime the child environment */ - setuserenv("AGENT", "sendmail"); + Argv = argv; + if (i > 0) + LastArgv = envp[i - 1] + strlen(envp[i - 1]); + else + LastArgv = argv[argc - 1] + strlen(argv[argc - 1]); +# endif /* SETPROCTITLE */ if (setsignal(SIGINT, SIG_IGN) != SIG_IGN) (void) setsignal(SIGINT, intsig); + if (setsignal(SIGHUP, SIG_IGN) != SIG_IGN) + (void) setsignal(SIGHUP, intsig); (void) setsignal(SIGTERM, intsig); (void) setsignal(SIGPIPE, SIG_IGN); OldUmask = umask(022); @@ -365,13 +335,12 @@ main(argc, argv, envp) /* initialize some macros, etc. */ initmacros(CurEnv); - init_vendor_macros(CurEnv); /* version */ define('v', Version, CurEnv); /* hostname */ - hp = myhostname(jbuf, sizeof jbuf); + av = myhostname(jbuf, sizeof jbuf); if (jbuf[0] != '\0') { struct utsname utsname; @@ -388,6 +357,7 @@ main(argc, argv, envp) if (p[1] != '\0') { define('m', newstr(&p[1]), CurEnv); + setclass('m', &p[1]); } while (p != NULL && strchr(&p[1], '.') != NULL) { @@ -408,42 +378,19 @@ main(argc, argv, envp) p = jbuf; } if (tTd(0, 4)) - printf(" UUCP nodename: %s\n", p); + printf("UUCP nodename: %s\n", p); p = newstr(p); define('k', p, CurEnv); setclass('k', p); setclass('w', p); } - if (hp != NULL) + while (av != NULL && *av != NULL) { - for (av = hp->h_aliases; av != NULL && *av != NULL; av++) - { - if (tTd(0, 4)) - printf("\ta.k.a.: %s\n", *av); - setclass('w', *av); - } -#if NETINET - if (hp->h_addrtype == AF_INET && hp->h_length == INADDRSZ) - { - register int i; - - for (i = 0; hp->h_addr_list[i] != NULL; i++) - { - char ipbuf[103]; - - sprintf(ipbuf, "[%.100s]", - inet_ntoa(*((struct in_addr *) hp->h_addr_list[i]))); - if (tTd(0, 4)) - printf("\ta.k.a.: %s\n", ipbuf); - setclass('w', ipbuf); - } - } -#endif + if (tTd(0, 4)) + printf("\ta.k.a.: %s\n", *av); + setclass('w', *av++); } - /* probe interfaces and locate any additional names */ - load_if_names(); - /* current time */ define('b', arpadate((char *) NULL), CurEnv); @@ -500,7 +447,9 @@ main(argc, argv, envp) case MD_TEST: case MD_INITALIAS: case MD_PRINT: +#ifdef MAYBE_NEXT_RELEASE case MD_ARPAFTP: +#endif OpMode = j; break; @@ -517,14 +466,17 @@ main(argc, argv, envp) break; case 'B': /* body type */ - CurEnv->e_bodytype = optarg; + if (strcasecmp(optarg, "7bit") == 0 || + strcasecmp(optarg, "8bitmime") == 0) + CurEnv->e_bodytype = newstr(optarg); + else + usrerr("Illegal body type %s", optarg); break; case 'C': /* select configuration file (already done) */ if (RealUid != 0) warn_C_flag = TRUE; ConfFile = optarg; - endpwent(); (void) setgid(RealGid); (void) setuid(RealUid); safecf = FALSE; @@ -559,7 +511,7 @@ main(argc, argv, envp) break; } break; - + case 'n': /* don't alias */ NoAlias = TRUE; break; @@ -568,10 +520,6 @@ main(argc, argv, envp) setoption(*optarg, optarg + 1, FALSE, TRUE, CurEnv); break; - case 'O': /* set option (long form) */ - setoption(' ', optarg, FALSE, TRUE, CurEnv); - break; - case 'p': /* set protocol */ p = strchr(optarg, ':'); if (p != NULL) @@ -626,7 +574,6 @@ main(argc, argv, envp) break; case 'X': /* traffic log file */ - endpwent(); setgid(RealGid); setuid(RealUid); TrafficLogFile = fopen(optarg, "a"); @@ -652,7 +599,9 @@ main(argc, argv, envp) break; case 'e': /* error message disposition */ +# if defined(ultrix) case 'M': /* define macro */ +# endif setoption(j, optarg, FALSE, TRUE, CurEnv); break; @@ -670,10 +619,8 @@ main(argc, argv, envp) case 'x': /* random flag that OSF/1 & AIX mailx passes */ break; # endif -# if defined(sony_news) - case 'E': - case 'J': /* ignore flags for Japanese code conversion - impremented on Sony NEWS */ +# if defined(NeXT) + case 'O': /* random flag that NeXT Mail.app passes */ break; # endif @@ -691,42 +638,23 @@ main(argc, argv, envp) ** Extract special fields for local use. */ - /* set up ${opMode} for use in config file */ - { - char mbuf[2]; - - mbuf[0] = OpMode; - mbuf[1] = '\0'; - define(MID_OPMODE, newstr(mbuf), CurEnv); - } - -#if XDEBUG +#ifdef XDEBUG checkfd012("before readcf"); #endif - vendor_pre_defaults(CurEnv); readcf(getcfname(), safecf, CurEnv); - vendor_post_defaults(CurEnv); - - /* suppress error printing if errors mailed back or whatever */ - if (CurEnv->e_errormode != EM_PRINT) - HoldErrs = TRUE; - - /* 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)) { - printf("\n============ SYSTEM IDENTITY (after readcf) ============"); - printf("\n (short domain name) $w = "); + printf("SYSTEM IDENTITY (after readcf):"); + printf("\n\t (short domain name) $w = "); xputs(macvalue('w', CurEnv)); - printf("\n (canonical domain name) $j = "); + printf("\n\t(canonical domain name) $j = "); xputs(macvalue('j', CurEnv)); - printf("\n (subdomain name) $m = "); + printf("\n\t (subdomain name) $m = "); xputs(macvalue('m', CurEnv)); - printf("\n (node name) $k = "); + printf("\n\t (node name) $k = "); xputs(macvalue('k', CurEnv)); - printf("\n========================================================\n\n"); + printf("\n"); } /* @@ -734,48 +662,47 @@ main(argc, argv, envp) */ #if NAMED_BIND - if (UseNameServer && !bitset(RES_INIT, _res.options)) + if (!bitset(RES_INIT, _res.options)) res_init(); -# ifdef RES_NOALIASES - _res.options |= RES_NOALIASES; -# endif #endif /* - ** Do more command line checking -- these are things that - ** have to modify the results of reading the config file. + ** Process authorization warnings from command line. */ - /* process authorization warnings from command line */ if (warn_C_flag) auth_warning(CurEnv, "Processed by %s with -C %s", RealUserName, ConfFile); +/* + if (warn_f_flag != '\0') + auth_warning(CurEnv, "%s set sender to %s using -%c", + RealUserName, from, warn_f_flag); +*/ if (Warn_Q_option) auth_warning(CurEnv, "Processed from queue %s", QueueDir); - /* check body type for legality */ - if (CurEnv->e_bodytype == NULL) - /* nothing */ ; - else if (strcasecmp(CurEnv->e_bodytype, "7BIT") == 0) - SevenBitInput = TRUE; - else if (strcasecmp(CurEnv->e_bodytype, "8BITMIME") == 0) - SevenBitInput = FALSE; - else - { - usrerr("Illegal body type %s", CurEnv->e_bodytype); - CurEnv->e_bodytype = NULL; - } - /* Enforce use of local time (null string overrides this) */ if (TimeZoneSpec == NULL) unsetenv("TZ"); else if (TimeZoneSpec[0] != '\0') - setuserenv("TZ", TimeZoneSpec); - else - setuserenv("TZ", NULL); - tzset(); + { + 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); + } - /* check for sane configuration level */ if (ConfigLevel > MAXCONFIGLEVEL) { syserr("Warning: .cf version level (%d) exceeds program functionality (%d)", @@ -785,24 +712,32 @@ main(argc, argv, envp) if (MeToo) BlankEnvelope.e_flags |= EF_METOO; - switch (OpMode) +# ifdef QUEUE + if (queuemode && RealUid != 0 && bitset(PRIV_RESTRICTQRUN, PrivacyFlags)) { - case MD_DAEMON: - /* remove things that don't make sense in daemon mode */ - FullName = NULL; - GrabTo = FALSE; + struct stat stbuf; - /* arrange to restart on hangup signal */ - setsignal(SIGHUP, sighup); - break; + /* check to see if we own the queue directory */ + if (stat(QueueDir, &stbuf) < 0) + syserr("main: cannot stat %s", QueueDir); + if (stbuf.st_uid != RealUid) + { + /* nope, really a botch */ + usrerr("You do not have permission to process the queue"); + exit (EX_NOPERM); + } + } +# endif /* QUEUE */ + switch (OpMode) + { case MD_INITALIAS: Verbose = TRUE; - /* fall through... */ + break; - default: - /* arrange to exit cleanly on hangup signal */ - setsignal(SIGHUP, intsig); + case MD_DAEMON: + /* remove things that don't make sense in daemon mode */ + FullName = NULL; break; } @@ -825,56 +760,31 @@ main(argc, argv, envp) UseErrorsTo = TRUE; } - /* set options that were previous macros */ - if (SmtpGreeting == NULL) - { - if (ConfigLevel < 7 && (p = macvalue('e', CurEnv)) != NULL) - SmtpGreeting = newstr(p); - else - SmtpGreeting = "\201j Sendmail \201v ready at \201b"; - } - if (UnixFromLine == NULL) - { - if (ConfigLevel < 7 && (p = macvalue('l', CurEnv)) != NULL) - UnixFromLine = newstr(p); - else - UnixFromLine = "From \201g \201d"; - } - /* our name for SMTP codes */ - expand("\201j", jbuf, sizeof jbuf, CurEnv); + expand("\201j", jbuf, &jbuf[sizeof jbuf - 1], CurEnv); MyHostName = jbuf; - if (strchr(jbuf, '.') == NULL) - message("WARNING: local host name (%s) is not qualified; fix $j in config file", - jbuf); /* make certain that this name is part of the $=w class */ setclass('w', MyHostName); /* the indices of built-in mailers */ st = stab("local", ST_MAILER, ST_FIND); - if (st != NULL) - LocalMailer = st->s_mailer; - else if (OpMode != MD_TEST || !warn_C_flag) + if (st == NULL) syserr("No local mailer defined"); + else + LocalMailer = st->s_mailer; st = stab("prog", ST_MAILER, ST_FIND); if (st == NULL) syserr("No prog mailer defined"); else - { 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 - { FileMailer = st->s_mailer; - clrbitn(M_MUSER, FileMailer->m_flags); - } st = stab("*include*", ST_MAILER, ST_FIND); if (st == NULL) @@ -882,39 +792,6 @@ main(argc, argv, envp) else InclMailer = st->s_mailer; - if (ConfigLevel < 6) - { - /* heuristic tweaking of local mailer for back compat */ - if (LocalMailer != NULL) - { - setbitn(M_ALIASABLE, LocalMailer->m_flags); - setbitn(M_HASPWENT, LocalMailer->m_flags); - setbitn(M_TRYRULESET5, LocalMailer->m_flags); - setbitn(M_CHECKINCLUDE, LocalMailer->m_flags); - setbitn(M_CHECKPROG, LocalMailer->m_flags); - setbitn(M_CHECKFILE, LocalMailer->m_flags); - setbitn(M_CHECKUDB, LocalMailer->m_flags); - } - if (ProgMailer != NULL) - 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); - } - - /* MIME Content-Types that cannot be transfer encoded */ - setclass('n', "multipart/signed"); - - /* MIME message/* subtypes that can be treated as messages */ - setclass('s', "rfc822"); - - /* 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) @@ -923,32 +800,14 @@ main(argc, argv, envp) ExitStat = EX_SOFTWARE; } -# ifdef QUEUE - if (queuemode && RealUid != 0 && bitset(PRIV_RESTRICTQRUN, PrivacyFlags)) - { - struct stat stbuf; - - /* check to see if we own the queue directory */ - if (stat(".", &stbuf) < 0) - syserr("main: cannot stat %s", QueueDir); - if (stbuf.st_uid != RealUid) - { - /* nope, really a botch */ - usrerr("You do not have permission to process the queue"); - exit (EX_NOPERM); - } - } -# endif /* QUEUE */ - /* if we've had errors so far, exit now */ if (ExitStat != EX_OK && OpMode != MD_TEST) { - endpwent(); setuid(RealUid); exit(ExitStat); } -#if XDEBUG +#ifdef XDEBUG checkfd012("before main() initmaps"); #endif @@ -963,7 +822,6 @@ main(argc, argv, envp) #ifdef QUEUE dropenvelope(CurEnv); printqueue(); - endpwent(); setuid(RealUid); exit(EX_OK); #else /* QUEUE */ @@ -974,12 +832,10 @@ main(argc, argv, envp) case MD_INITALIAS: /* initialize alias database */ initmaps(TRUE, CurEnv); - endpwent(); setuid(RealUid); exit(EX_OK); case MD_DAEMON: - case MD_SMTP: /* don't open alias database -- done in srvrsmtp */ break; @@ -992,12 +848,35 @@ main(argc, argv, envp) if (tTd(0, 15)) { /* print configuration table (or at least part of it) */ - if (tTd(0, 90)) - printrules(); + printrules(); for (i = 0; i < MAXMAILERS; i++) { - if (Mailer[i] != NULL) - printmailer(Mailer[i]); + register struct mailer *m = Mailer[i]; + int j; + + if (m == NULL) + continue; + printf("mailer %d (%s): P=%s S=%d/%d R=%d/%d M=%ld F=", i, m->m_name, + m->m_mailer, m->m_se_rwset, m->m_sh_rwset, + m->m_re_rwset, m->m_rh_rwset, m->m_maxsize); + for (j = '\0'; j <= '\177'; j++) + if (bitnset(j, m->m_flags)) + (void) putchar(j); + printf(" E="); + xputs(m->m_eol); + if (m->m_argv != NULL) + { + char **a = m->m_argv; + + printf(" A="); + while (*a != NULL) + { + if (a != m->m_argv) + printf(" "); + xputs(*a++); + } + } + printf("\n"); } } @@ -1015,7 +894,6 @@ main(argc, argv, envp) if (OpMode == MD_TEST) { char buf[MAXLINE]; - void intindebug(); if (isatty(fileno(stdin))) Verbose = TRUE; @@ -1025,24 +903,69 @@ main(argc, argv, envp) printf("ADDRESS TEST MODE (ruleset 3 NOT automatically invoked)\n"); printf("Enter <ruleset> <address>\n"); } - if (setjmp(TopFrame) > 0) - printf("\n"); - (void) setsignal(SIGINT, intindebug); for (;;) { - extern void testmodeline __P((char *, ENVELOPE *)); + register char **pvp; + char *q; + auto char *delimptr; + extern bool invalidaddr(); + extern char *crackaddr(); 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) - printf("> %s\n", buf); - testmodeline(buf, CurEnv); + printf("> %s", buf); + switch (buf[0]) + { + case '#': + continue; + +#ifdef MAYBENEXTRELEASE + case 'C': /* try crackaddr */ + q = crackaddr(&buf[1]); + xputs(q); + printf("\n"); + continue; +#endif + } + + for (p = buf; isascii(*p) && isspace(*p); p++) + continue; + q = p; + while (*p != '\0' && !(isascii(*p) && isspace(*p))) + p++; + if (*p == '\0') + { + printf("No address!\n"); + continue; + } + *p = '\0'; + if (invalidaddr(p + 1, NULL)) + continue; + do + { + char pvpbuf[PSBUFSIZE]; + + pvp = prescan(++p, ',', pvpbuf, sizeof pvpbuf, + &delimptr); + if (pvp == NULL) + continue; + p = q; + while (*p != '\0') + { + int stat; + + stat = rewrite(pvp, atoi(p), 0, CurEnv); + if (stat != EX_OK) + printf("== Ruleset %s status %d\n", + p, stat); + while (*p != '\0' && *p++ != ',') + continue; + } + } while (*(p = delimptr) != '\0'); } } @@ -1053,7 +976,6 @@ main(argc, argv, envp) if (queuemode && OpMode != MD_DAEMON && QueueIntvl == 0) { - (void) unsetenv("HOSTALIASES"); runqueue(FALSE); finis(); } @@ -1072,7 +994,7 @@ main(argc, argv, envp) { char dtype[200]; - if (!tTd(99, 100)) + if (!tTd(0, 1)) { /* put us in background */ i = fork(); @@ -1129,7 +1051,7 @@ main(argc, argv, envp) #endif /* DAEMON */ } - + # ifdef SMTP /* ** If running SMTP protocol, start collecting and executing @@ -1144,12 +1066,11 @@ main(argc, argv, envp) { CurEnv->e_sendmode = SM_VERIFY; CurEnv->e_errormode = EM_QUIET; - PostMasterCopy = NULL; } else { /* interactive -- all errors are global */ - CurEnv->e_flags |= EF_GLOBALERRS|EF_LOGSENDER; + CurEnv->e_flags |= EF_GLOBALERRS; } /* @@ -1157,9 +1078,6 @@ main(argc, argv, envp) */ initsys(CurEnv); - if (warn_f_flag != '\0' && !wordinclass(RealUserName, 't')) - auth_warning(CurEnv, "%s set sender to %s using -%c", - RealUserName, from, warn_f_flag); setsender(from, CurEnv, NULL, FALSE); if (macvalue('s', CurEnv) == NULL) define('s', RealHostName, CurEnv); @@ -1171,7 +1089,7 @@ main(argc, argv, envp) /* collect body for UUCP return */ if (OpMode != MD_VERIFY) - collect(InChannel, FALSE, FALSE, NULL, CurEnv); + collect(FALSE, FALSE, CurEnv); finis(); } @@ -1193,7 +1111,7 @@ main(argc, argv, envp) if (OpMode != MD_VERIFY || GrabTo) { CurEnv->e_flags |= EF_GLOBALERRS; - collect(InChannel, FALSE, FALSE, NULL, CurEnv); + collect(FALSE, FALSE, CurEnv); } errno = 0; @@ -1221,15 +1139,6 @@ main(argc, argv, envp) finis(); } - - -void -intindebug() -{ - longjmp(TopFrame, 1); -} - - /* ** FINIS -- Clean up and exit. ** @@ -1243,18 +1152,12 @@ intindebug() ** exits sendmail */ -void finis() { if (tTd(2, 1)) - { - extern void printenvflags(); - - printf("\n====finis: stat %d e_id=%s e_flags=", - ExitStat, + printf("\n====finis: stat %d e_flags %o, e_id=%s\n", + ExitStat, CurEnv->e_flags, CurEnv->e_id == NULL ? "NOQUEUE" : CurEnv->e_id); - printenvflags(CurEnv); - } if (tTd(2, 9)) printopenfds(FALSE); @@ -1275,11 +1178,10 @@ finis() if (LogLevel > 78) syslog(LOG_DEBUG, "finis, pid=%d", getpid()); # endif /* LOG */ - if (ExitStat == EX_TEMPFAIL || CurEnv->e_errormode == EM_BERKNET) + if (ExitStat == EX_TEMPFAIL) ExitStat = EX_OK; /* reset uid for process accounting */ - endpwent(); setuid(RealUid); exit(ExitStat); @@ -1310,7 +1212,6 @@ intsig() #endif /* reset uid for process accounting */ - endpwent(); setuid(RealUid); exit(EX_OK); @@ -1354,18 +1255,12 @@ struct metamac MetaMacros[] = '\0' }; -#define MACBINDING(name, mid) \ - stab(name, ST_MACRO, ST_ENTER)->s_macro = mid; \ - MacroName[mid] = name; - -void initmacros(e) register ENVELOPE *e; { register struct metamac *m; - register int c; char buf[5]; - extern char *MacroName[256]; + register int c; for (m = MetaMacros; m->metaname != '\0'; m++) { @@ -1382,11 +1277,11 @@ initmacros(e) } /* set defaults for some macros sendmail will use later */ + define('e', "\201j Sendmail \201v ready at \201b", e); + define('l', "From \201g \201d", e); define('n', "MAILER-DAEMON", e); - - /* set up external names for some internal macros */ - MACBINDING("opMode", MID_OPMODE); - /*XXX should probably add equivalents for all short macros here XXX*/ + define('o', ".:@[]", e); + define('q', "<\201g>", e); } /* ** DISCONNECT -- remove our connection with any foreground process @@ -1408,7 +1303,6 @@ initmacros(e) ** the controlling tty. */ -void disconnect(droplev, e) int droplev; register ENVELOPE *e; @@ -1418,13 +1312,14 @@ disconnect(droplev, e) if (tTd(52, 1)) printf("disconnect: In %d Out %d, e=%x\n", fileno(InChannel), fileno(OutChannel), e); - if (tTd(52, 100)) + if (tTd(52, 5)) { printf("don't\n"); return; } /* be sure we don't get nasty signals */ + (void) setsignal(SIGHUP, SIG_IGN); (void) setsignal(SIGINT, SIG_IGN); (void) setsignal(SIGQUIT, SIG_IGN); @@ -1468,7 +1363,7 @@ disconnect(droplev, e) errno = 0; } -#if XDEBUG +#ifdef XDEBUG checkfd012("disconnect"); #endif @@ -1496,11 +1391,7 @@ obsolete(argv) /* skip over options that do have a value */ op = strchr(OPTIONS, ap[1]); if (op != NULL && *++op == ':' && ap[2] == '\0' && - ap[1] != 'd' && -#if defined(sony_news) - ap[1] != 'E' && ap[1] != 'J' && -#endif - argv[1] != NULL && argv[1][0] != '-') + ap[1] != 'd' && argv[1] != NULL && argv[1][0] != '-') { argv++; continue; @@ -1523,16 +1414,6 @@ obsolete(argv) /* if -d doesn't have an argument, use 0-99.1 */ if (ap[1] == 'd' && ap[2] == '\0') *argv = "-d0-99.1"; - -# if defined(sony_news) - /* if -E doesn't have an argument, use -EC */ - if (ap[1] == 'E' && ap[2] == '\0') - *argv = "-EC"; - - /* if -J doesn't have an argument, use -JJ */ - if (ap[1] == 'J' && ap[2] == '\0') - *argv = "-JJ"; -# endif } } /* @@ -1564,7 +1445,7 @@ auth_warning(e, msg, va_alist) { register char *p; static char hostbuf[48]; - extern struct hostent *myhostname(); + extern char **myhostname(); if (hostbuf[0] == '\0') (void) myhostname(hostbuf, sizeof hostbuf); @@ -1572,69 +1453,12 @@ auth_warning(e, msg, va_alist) (void) sprintf(buf, "%s: ", hostbuf); p = &buf[strlen(buf)]; VA_START(msg); - vsnprintf(p, sizeof buf - (p - buf), msg, ap); + vsprintf(p, msg, ap); VA_END; - addheader("X-Authentication-Warning", buf, &e->e_header); -#ifdef LOG - if (LogLevel > 3) - syslog(LOG_INFO, "%s: Authentication-Warning: %.400s", - e->e_id == NULL ? "[NOQUEUE]" : e->e_id, buf); -#endif + addheader("X-Authentication-Warning", buf, e); } } /* -** 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); -} -/* ** DUMPSTATE -- dump state ** ** For debugging. @@ -1646,16 +1470,17 @@ dumpstate(when) { #ifdef LOG register char *j = macvalue('j', CurEnv); + register STAB *s; syslog(LOG_DEBUG, "--- dumping state on %s: $j = %s ---", when, j == NULL ? "<NULL>" : j); if (j != NULL) { - if (!wordinclass(j, 'w')) + s = stab(j, ST_CLASS, ST_FIND); + if (s == NULL || !bitnset('w', s->s_class)) syslog(LOG_DEBUG, "*** $j not in $=w ***"); } - syslog(LOG_DEBUG, "CurChildren = %d", CurChildren); syslog(LOG_DEBUG, "--- open file descriptors: ---"); printopenfds(TRUE); syslog(LOG_DEBUG, "--- connection cache: ---"); @@ -1683,431 +1508,3 @@ sigusr1() { dumpstate("user signal"); } - - -void -sighup() -{ -#ifdef LOG - if (LogLevel > 3) - syslog(LOG_INFO, "restarting %s on signal", SaveArgv[0]); -#endif - releasesignal(SIGHUP); - execv(SaveArgv[0], (ARGV_T) SaveArgv); -#ifdef LOG - if (LogLevel > 0) - syslog(LOG_ALERT, "could not exec %s: %m", SaveArgv[0]); -#endif - exit(EX_OSFILE); -} -/* -** TESTMODELINE -- process a test mode input line -** -** Parameters: -** line -- the input line. -** e -- the current environment. -** Syntax: -** # a comment -** .X process X as a configuration line -** =X dump a configuration item (such as mailers) -** $X dump a macro or class -** /X try an activity -** X normal process through rule set X -*/ - -void -testmodeline(line, e) - char *line; - ENVELOPE *e; -{ - register char *p; - char *q; - auto char *delimptr; - int mid; - int i, rs; - STAB *map; - char **s; - struct rewrite *rw; - ADDRESS a; - static int tryflags = RF_COPYNONE; - char exbuf[MAXLINE]; - extern bool invalidaddr __P((char *, char *)); - extern char *crackaddr __P((char *)); - extern void dump_class __P((STAB *, int)); - extern void translate_dollars __P((char *)); - - switch (line[0]) - { - case '#': - case 0: - return; - - case '?': - help("-bt"); - return; - - case '.': /* config-style settings */ - switch (line[1]) - { - case 'D': - mid = macid(&line[2], &delimptr); - if (mid == '\0') - return; - translate_dollars(delimptr); - define(mid, newstr(delimptr), e); - break; - - case 'C': - if (line[2] == '\0') /* not to call syserr() */ - return; - - mid = macid(&line[2], &delimptr); - if (mid == '\0') - return; - translate_dollars(delimptr); - expand(delimptr, exbuf, sizeof exbuf, e); - p = exbuf; - while (*p != '\0') - { - register char *wd; - char delim; - - while (*p != '\0' && isascii(*p) && isspace(*p)) - p++; - wd = p; - while (*p != '\0' && !(isascii(*p) && isspace(*p))) - p++; - delim = *p; - *p = '\0'; - if (wd[0] != '\0') - setclass(mid, wd); - *p = delim; - } - break; - - case '\0': - printf("Usage: .[DC]macro value(s)\n"); - break; - - default: - printf("Unknown \".\" command %s\n", line); - break; - } - return; - - case '=': /* config-style settings */ - switch (line[1]) - { - case 'S': /* dump rule set */ - rs = strtorwset(&line[2], NULL, ST_FIND); - if (rs < 0) - return; - rw = RewriteRules[rs]; - if (rw == NULL) - return; - do - { - putchar('R'); - s = rw->r_lhs; - while (*s != NULL) - { - xputs(*s++); - putchar(' '); - } - putchar('\t'); - putchar('\t'); - s = rw->r_rhs; - while (*s != NULL) - { - xputs(*s++); - putchar(' '); - } - putchar('\n'); - } while (rw = rw->r_next); - break; - - case 'M': - for (i = 0; i < MAXMAILERS; i++) - { - if (Mailer[i] != NULL) - printmailer(Mailer[i]); - } - break; - - case '\0': - printf("Usage: =Sruleset or =M\n"); - break; - - default: - printf("Unknown \"=\" command %s\n", line); - break; - } - return; - - case '-': /* set command-line-like opts */ - switch (line[1]) - { - case 'd': - tTflag(&line[2]); - break; - - case '\0': - printf("Usage: -d{debug arguments}\n"); - break; - - default: - printf("Unknown \"-\" command %s\n", line); - break; - } - return; - - case '$': - if (line[1] == '=') - { - mid = macid(&line[2], NULL); - if (mid != '\0') - stabapply(dump_class, mid); - return; - } - mid = macid(&line[1], NULL); - if (mid == '\0') - return; - p = macvalue(mid, e); - if (p == NULL) - printf("Undefined\n"); - else - { - 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) - { - while (isascii(*p) && isspace(*p)) - *p++ = '\0'; - } - else - p = ""; - if (line[1] == '\0') - { - printf("Usage: /[canon|map|mx|parse|try|tryflags]\n"); - return; - } - if (strcasecmp(&line[1], "mx") == 0) - { -#if NAMED_BIND - /* look up MX records */ - int nmx; - auto int rcode; - char *mxhosts[MAXMXHOSTS + 1]; - - if (*p == '\0') - { - printf("Usage: /mx address\n"); - return; - } - nmx = getmxrr(p, mxhosts, FALSE, &rcode); - 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 - } - else if (strcasecmp(&line[1], "canon") == 0) - { - auto int rcode = EX_OK; - char host[MAXHOSTNAMELEN]; - - if (*p == '\0') - { - printf("Usage: /canon address\n"); - return; - } - strcpy(host, p); - getcanonname(host, sizeof(host), HasWildcardMX, &rcode); - printf("getcanonname(%s) returns %s (%d)\n", - p, host, rcode); - } - else if (strcasecmp(&line[1], "map") == 0) - { - auto int rcode = EX_OK; - - if (*p == '\0') - { - printf("Usage: /map mapname key\n"); - return; - } - for (q = p; *q != '\0' && !isspace(*q); q++) - continue; - if (*q == '\0') - { - printf("No key specified\n"); - return; - } - *q++ = '\0'; - map = stab(p, ST_MAP, ST_FIND); - if (map == NULL) - { - printf("Map named \"%s\" not found\n", p); - return; - } - printf("map_lookup: %s (%s) ", p, q); - p = (*map->s_map.map_class->map_lookup) - (&map->s_map, q, NULL, &rcode); - if (p == NULL) - printf("no match (%d)\n", rcode); - else - printf("returns %s (%d)\n", p, rcode); - } - else if (strcasecmp(&line[1], "try") == 0) - { - MAILER *m; - STAB *s; - auto int rcode = EX_OK; - - q = strpbrk(p, " \t"); - if (q != NULL) - { - while (isascii(*q) && isspace(*q)) - *q++ = '\0'; - } - if (q == NULL || *q == '\0') - { - printf("Usage: /try mailer address\n"); - return; - } - s = stab(p, ST_MAILER, ST_FIND); - if (s == NULL) - { - printf("Unknown mailer %s\n", p); - return; - } - m = s->s_mailer; - printf("Trying %s %s address %s for mailer %s\n", - bitset(RF_HEADERADDR, tryflags) ? "header" : "envelope", - bitset(RF_SENDERADDR, tryflags) ? "sender" : "recipient", - q, p); - p = remotename(q, m, tryflags, &rcode, CurEnv); - printf("Rcode = %d, addr = %s\n", - rcode, p == NULL ? "<NULL>" : p); - } - else if (strcasecmp(&line[1], "tryflags") == 0) - { - if (*p == '\0') - { - printf("Usage: /tryflags [Hh|Ee][Ss|Rr]\n"); - return; - } - for (; *p != '\0'; p++) - { - switch (*p) - { - case 'H': - case 'h': - tryflags |= RF_HEADERADDR; - break; - - case 'E': - case 'e': - tryflags &= ~RF_HEADERADDR; - break; - - case 'S': - case 's': - tryflags |= RF_SENDERADDR; - break; - - case 'R': - case 'r': - tryflags &= ~RF_SENDERADDR; - break; - } - } - } - else if (strcasecmp(&line[1], "parse") == 0) - { - if (*p == '\0') - { - printf("Usage: /parse address\n"); - return; - } - q = crackaddr(p); - printf("Cracked address = "); - xputs(q); - printf("\nParsing %s %s address\n", - bitset(RF_HEADERADDR, tryflags) ? "header" : "envelope", - bitset(RF_SENDERADDR, tryflags) ? "sender" : "recipient"); - if (parseaddr(p, &a, tryflags, '\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 \"/\" command %s\n", line); - } - return; - } - - for (p = line; isascii(*p) && isspace(*p); p++) - continue; - q = p; - while (*p != '\0' && !(isascii(*p) && isspace(*p))) - p++; - if (*p == '\0') - { - printf("No address!\n"); - return; - } - *p = '\0'; - if (invalidaddr(p + 1, NULL)) - return; - do - { - register char **pvp; - char pvpbuf[PSBUFSIZE]; - - pvp = prescan(++p, ',', pvpbuf, sizeof pvpbuf, - &delimptr, NULL); - if (pvp == NULL) - continue; - p = q; - while (*p != '\0') - { - int stat; - int rs = strtorwset(p, NULL, ST_FIND); - - if (rs < 0) - break; - stat = rewrite(pvp, rs, 0, e); - if (stat != EX_OK) - printf("== Ruleset %s (%d) status %d\n", - p, rs, stat); - while (*p != '\0' && *p++ != ',') - continue; - } - } while (*(p = delimptr) != '\0'); -} - - -void -dump_class(s, id) - register STAB *s; - int id; -{ - if (s->s_type != ST_CLASS) - return; - if (bitnset(id & 0xff, s->s_class)) - printf("%s\n", s->s_name); -} |