aboutsummaryrefslogtreecommitdiff
path: root/usr.sbin/sendmail/src/main.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr.sbin/sendmail/src/main.c')
-rw-r--r--usr.sbin/sendmail/src/main.c458
1 files changed, 366 insertions, 92 deletions
diff --git a/usr.sbin/sendmail/src/main.c b/usr.sbin/sendmail/src/main.c
index e19efa489aef..504fba3a9525 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, 1995, 1996 Eric P. Allman
* Copyright (c) 1988, 1993
* The Regents of the University of California. All rights reserved.
*
@@ -39,12 +39,13 @@ static char copyright[] =
#endif /* not lint */
#ifndef lint
-static char sccsid[] = "@(#)main.c 8.162.1.3 (Berkeley) 9/16/96";
+static char sccsid[] = "@(#)main.c 8.211 (Berkeley) 10/12/96";
#endif /* not lint */
#define _DEFINE
#include "sendmail.h"
+#include <arpa/inet.h>
#if NAMED_BIND
#include <resolv.h>
#endif
@@ -75,14 +76,16 @@ char edata, end;
** See the associated documentation for details.
**
** Author:
-** Eric Allman, UCB/INGRES (until 10/81)
+** Eric Allman, UCB/INGRES (until 10/81).
** Britton-Lee, Inc., purveyors of fine
-** database computers (from 11/81)
-** Now back at UCB at the Mammoth project.
-** 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.
+** database computers (11/81 - 10/88).
+** International Computer Science Institute
+** (11/88 - 9/89).
+** UCB/Mammoth Project (10/89 - 7/95).
+** InReference, Inc. (8/95 - present).
+** The support of the my employers is gratefully acknowledged.
+** Few of them (Britton-Lee in particular) have had
+** anything to gain from my involvement in this project.
*/
@@ -97,6 +100,8 @@ bool Warn_Q_option = FALSE; /* warn about Q option use */
char **SaveArgv; /* argument vector for re-execing */
static void obsolete();
+extern void printmailer __P((MAILER *));
+extern void tTflag __P((char *));
#ifdef DAEMON
#ifndef SMTP
@@ -104,7 +109,7 @@ ERROR %%%% Cannot have daemon mode without SMTP %%%% ERROR
#endif /* SMTP */
#endif /* DAEMON */
-#define MAXCONFIGLEVEL 6 /* highest config version level known */
+#define MAXCONFIGLEVEL 7 /* highest config version level known */
int
main(argc, argv, envp)
@@ -124,26 +129,40 @@ main(argc, argv, envp)
bool safecf = TRUE;
bool warn_C_flag = FALSE;
char warn_f_flag = '\0';
+ bool run_in_foreground = FALSE; /* -bD mode */
static bool reenter = FALSE;
struct passwd *pw;
struct stat stb;
struct hostent *hp;
+ bool nullserver;
char jbuf[MAXHOSTNAMELEN]; /* holds MyHostName */
static char rnamebuf[MAXNAME]; /* holds RealUserName */
+ char *emptyenviron[1];
extern int DtableSize;
extern int optind;
extern int opterr;
+ extern char *optarg;
+ extern char **environ;
extern time_t convtime();
extern void intsig();
extern struct hostent *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 *));
+ extern void init_md __P((int, char **));
+ extern int getdtsize __P((void));
+ extern void tTsetup __P((u_char *, int, char *));
+ extern void setdefaults __P((ENVELOPE *));
+ extern void initsetproctitle __P((int, char **, char **));
+ extern void init_vendor_macros __P((ENVELOPE *));
+ extern void load_if_names __P((void));
+ extern void vendor_pre_defaults __P((ENVELOPE *));
+ extern void vendor_post_defaults __P((ENVELOPE *));
+ extern void readcf __P((char *, bool, ENVELOPE *));
+ extern void printqueue __P((void));
+ extern void sendtoargv __P((char **, ENVELOPE *));
extern void resetlimits __P((void));
/*
@@ -159,6 +178,9 @@ main(argc, argv, envp)
}
reenter = TRUE;
+ /* avoid null pointer dereferences */
+ TermEscape.te_rv_on = TermEscape.te_rv_off = "";
+
/* do machine-dependent initializations */
init_md(argc, argv);
@@ -205,6 +227,42 @@ main(argc, argv, envp)
tTsetup(tTdvect, sizeof tTdvect, "0-99.1");
+ /* Handle any non-getoptable constructions. */
+ obsolete(argv);
+
+ /*
+ ** Do a quick prescan of the argument list.
+ */
+
+#if defined(__osf__) || defined(_AIX3)
+# define OPTIONS "B:b:C:cd:e:F:f:h:IiM:mN:nO:o:p:q:R:r:sTtUV:vX:x"
+#endif
+#if defined(sony_news)
+# define OPTIONS "B:b:C:cd:E:e:F:f:h:IiJ:M:mN:nO:o:p:q:R:r:sTtUV:vX:"
+#endif
+#ifndef OPTIONS
+# define OPTIONS "B:b:C:cd:e:F:f:h:IiM:mN:nO:o:p:q:R:r:sTtUV:vX:"
+#endif
+ opterr = 0;
+ while ((j = getopt(argc, argv, OPTIONS)) != EOF)
+ {
+ switch (j)
+ {
+ case 'd':
+ /* hack attack -- see if should use ANSI mode */
+ if (strcmp(optarg, "ANSI") == 0)
+ {
+ TermEscape.te_rv_on = "\033[7m";
+ TermEscape.te_rv_off = "\033[0m";
+ break;
+ }
+ tTflag(optarg);
+ setbuf(stdout, (char *) NULL);
+ break;
+ }
+ }
+ opterr = 1;
+
/* set up the blank envelope */
BlankEnvelope.e_puthdr = putheader;
BlankEnvelope.e_putbody = putbody;
@@ -247,35 +305,6 @@ main(argc, argv, envp)
}
SaveArgv[i] = NULL;
- /* Handle any non-getoptable constructions. */
- obsolete(argv);
-
- /*
- ** Do a quick prescan of the argument list.
- */
-
-#if defined(__osf__) || defined(_AIX3)
-# define OPTIONS "B:b:C:cd:e:F:f:h:IiM:mnO:o:p:q:r:sTtvX:x"
-#endif
-#if defined(sony_news)
-# define OPTIONS "B:b:C:cd:E:e:F:f:h:IiJ:M:mnO:o:p:q:r:sTtvX:"
-#endif
-#ifndef OPTIONS
-# define OPTIONS "B:b:C:cd:e:F:f:h:IiM:mnO:o:p:q:r:sTtvX:"
-#endif
- opterr = 0;
- while ((j = getopt(argc, argv, OPTIONS)) != EOF)
- {
- switch (j)
- {
- case 'd':
- tTflag(optarg);
- setbuf(stdout, (char *) NULL);
- break;
- }
- }
- opterr = 1;
-
if (tTd(0, 1))
{
int ll;
@@ -308,7 +337,7 @@ main(argc, argv, envp)
int ll;
extern char *OsCompileOptions[];
- printf(" OS Defines:", Version);
+ printf(" OS Defines:");
av = OsCompileOptions;
ll = 7;
while (*av != NULL)
@@ -332,7 +361,7 @@ main(argc, argv, envp)
#ifdef _PATH_UNIX
printf("Kernel symbols:\t%s\n", _PATH_UNIX);
#endif
- printf(" Config file:\t%s\n", getcfname());
+ printf(" Def Conf file:\t%s\n", getcfname());
printf(" Pid file:\t%s\n", PidFile);
}
@@ -342,6 +371,11 @@ main(argc, argv, envp)
/* initialize for setproctitle */
initsetproctitle(argc, argv, envp);
+ /* clear sendmail's environment */
+ ExternalEnviron = environ;
+ emptyenviron[0] = NULL;
+ environ = emptyenviron;
+
/* prime the child environment */
setuserenv("AGENT", "sendmail");
@@ -351,7 +385,7 @@ main(argc, argv, envp)
(void) setsignal(SIGPIPE, SIG_IGN);
OldUmask = umask(022);
OpMode = MD_DELIVER;
- FullName = getenv("NAME");
+ FullName = getextenv("NAME");
#if NAMED_BIND
if (tTd(8, 8))
@@ -393,6 +427,8 @@ main(argc, argv, envp)
while (p != NULL && strchr(&p[1], '.') != NULL)
{
*p = '\0';
+ if (tTd(0, 4))
+ printf("\ta.k.a.: %s\n", jbuf);
setclass('w', jbuf);
*p++ = '.';
p = strchr(p, '.');
@@ -449,13 +485,6 @@ main(argc, argv, envp)
define('b', arpadate((char *) NULL), CurEnv);
/*
- ** Find our real host name for future logging.
- */
-
- p = getauthinfo(STDIN_FILENO);
- define('_', p, CurEnv);
-
- /*
** Crack argv.
*/
@@ -469,6 +498,10 @@ main(argc, argv, envp)
OpMode = MD_PRINT;
else if (strcmp(p, "smtpd") == 0)
OpMode = MD_DAEMON;
+ else if (strcmp(p, "hoststat") == 0)
+ OpMode = MD_HOSTSTAT;
+ else if (strcmp(p, "purgestat") == 0)
+ OpMode = MD_PURGESTAT;
optind = 1;
while ((j = getopt(argc, argv, OPTIONS)) != EOF)
@@ -479,12 +512,15 @@ main(argc, argv, envp)
switch (j = *optarg)
{
case MD_DAEMON:
+ case MD_FGDAEMON:
# ifdef DAEMON
- if (RealUid != 0) {
+ if (RealUid != 0)
+ {
usrerr("Permission denied");
- exit (EX_USAGE);
+ exit(EX_USAGE);
}
- (void) unsetenv("HOSTALIASES");
+ vendor_daemon_setup(CurEnv);
+ /* fall through ... */
# else
usrerr("Daemon mode not implemented");
ExitStat = EX_USAGE;
@@ -496,11 +532,16 @@ main(argc, argv, envp)
ExitStat = EX_USAGE;
break;
# endif /* SMTP */
+
+ case MD_INITALIAS:
+ /* fall through ... */
+
case MD_DELIVER:
case MD_VERIFY:
case MD_TEST:
- case MD_INITALIAS:
case MD_PRINT:
+ case MD_HOSTSTAT:
+ case MD_PURGESTAT:
case MD_ARPAFTP:
OpMode = j;
break;
@@ -557,7 +598,6 @@ main(argc, argv, envp)
{
usrerr("Bad hop count (%s)", optarg);
ExitStat = EX_USAGE;
- break;
}
break;
@@ -565,6 +605,29 @@ main(argc, argv, envp)
NoAlias = TRUE;
break;
+ case 'N': /* delivery status notifications */
+ DefaultNotify |= QHASNOTIFY;
+ if (strcasecmp(optarg, "never") == 0)
+ break;
+ for (p = optarg; p != NULL; optarg = p)
+ {
+ p = strchr(p, ',');
+ if (p != NULL)
+ *p++ = '\0';
+ if (strcasecmp(optarg, "success") == 0)
+ DefaultNotify |= QPINGONSUCCESS;
+ else if (strcasecmp(optarg, "failure") == 0)
+ DefaultNotify |= QPINGONFAILURE;
+ else if (strcasecmp(optarg, "delay") == 0)
+ DefaultNotify |= QPINGONDELAY;
+ else
+ {
+ usrerr("Invalid -N argument");
+ ExitStat = EX_USAGE;
+ }
+ }
+ break;
+
case 'o': /* set option */
setoption(*optarg, optarg + 1, FALSE, TRUE, CurEnv);
break;
@@ -595,7 +658,6 @@ main(argc, argv, envp)
case 'q': /* run queue files at intervals */
# ifdef QUEUE
- (void) unsetenv("HOSTALIASES");
FullName = NULL;
queuemode = TRUE;
switch (optarg[0])
@@ -622,10 +684,41 @@ main(argc, argv, envp)
# endif /* QUEUE */
break;
+ case 'R': /* DSN RET: what to return */
+ if (bitset(EF_RET_PARAM, CurEnv->e_flags))
+ {
+ usrerr("Duplicate -R flag");
+ ExitStat = EX_USAGE;
+ break;
+ }
+ CurEnv->e_flags |= EF_RET_PARAM;
+ if (strcasecmp(optarg, "hdrs") == 0)
+ CurEnv->e_flags |= EF_NO_BODY_RETN;
+ else if (strcasecmp(optarg, "full") != 0)
+ {
+ usrerr("Invalid -R value");
+ ExitStat = EX_USAGE;
+ }
+ break;
+
case 't': /* read recipients from message */
GrabTo = TRUE;
break;
+ case 'U': /* initial (user) submission */
+ UserSubmission = TRUE;
+ break;
+
+ case 'V': /* DSN ENVID: set "original" envelope id */
+ if (!xtextok(optarg))
+ {
+ usrerr("Invalid syntax in -V flag");
+ ExitStat = EX_USAGE;
+ }
+ else
+ CurEnv->e_envid = newstr(optarg);
+ break;
+
case 'X': /* traffic log file */
endpwent();
setgid(RealGid);
@@ -634,6 +727,7 @@ main(argc, argv, envp)
if (TrafficLogFile == NULL)
{
syserr("cannot open %s", optarg);
+ ExitStat = EX_CANTCREAT;
break;
}
#ifdef HASSETVBUF
@@ -706,11 +800,28 @@ main(argc, argv, envp)
#endif
vendor_pre_defaults(CurEnv);
readcf(getcfname(), safecf, CurEnv);
+ ConfigFileRead = TRUE;
vendor_post_defaults(CurEnv);
/* avoid denial-of-service attacks */
resetlimits();
+ if (OpMode != MD_DAEMON && OpMode != MD_FGDAEMON)
+ {
+ /* drop privileges -- daemon mode done after socket/bind */
+ if (RunAsGid != 0)
+ (void) setgid(RunAsGid);
+ if (RunAsUid != 0)
+ (void) setuid(RunAsUid);
+ }
+
+ /*
+ ** Find our real host name for future logging.
+ */
+
+ p = getauthinfo(STDIN_FILENO);
+ define('_', p, CurEnv);
+
/* suppress error printing if errors mailed back or whatever */
if (CurEnv->e_errormode != EM_PRINT)
HoldErrs = TRUE;
@@ -770,6 +881,10 @@ main(argc, argv, envp)
CurEnv->e_bodytype = NULL;
}
+ /* tweak default DSN notifications */
+ if (DefaultNotify == 0)
+ DefaultNotify = QPINGONFAILURE|QPINGONDELAY;
+
/* Enforce use of local time (null string overrides this) */
if (TimeZoneSpec == NULL)
unsetenv("TZ");
@@ -786,18 +901,49 @@ main(argc, argv, envp)
ConfigLevel, MAXCONFIGLEVEL);
}
+ /* need MCI cache to have persistence */
+ if (HostStatDir != NULL && MaxMciCache == 0)
+ {
+ HostStatDir = NULL;
+ printf("Warning: HostStatusDirectory disabled with ConnectionCacheSize = 0\n");
+ }
+
+ /* need HostStatusDir in order to have SingleThreadDelivery */
+ if (SingleThreadDelivery && HostStatDir == NULL)
+ {
+ SingleThreadDelivery = FALSE;
+ printf("Warning: HostStatusDirectory required for SingleThreadDelivery\n");
+ }
+
if (MeToo)
BlankEnvelope.e_flags |= EF_METOO;
switch (OpMode)
{
+ case MD_TEST:
+ /* don't have persistent host status in test mode */
+ HostStatDir = NULL;
+ break;
+
+ case MD_FGDAEMON:
+ run_in_foreground = TRUE;
+ OpMode = MD_DAEMON;
+ /* fall through ... */
+
case MD_DAEMON:
/* remove things that don't make sense in daemon mode */
FullName = NULL;
GrabTo = FALSE;
/* arrange to restart on hangup signal */
+#ifdef LOG
+ if (SaveArgv[0] == NULL || SaveArgv[0][0] != '/')
+ syslog(LOG_WARNING, "daemon invoked without full pathname; kill -1 won't work");
+#endif
setsignal(SIGHUP, sighup);
+
+ /* workaround: can't seem to release the signal in the parent */
+ releasesignal(SIGHUP);
break;
case MD_INITALIAS:
@@ -908,11 +1054,20 @@ main(argc, argv, envp)
setuserenv("ISP", NULL);
setuserenv("SYSTYPE", NULL);
}
+ if (ConfigLevel < 7)
+ {
+ if (LocalMailer != NULL)
+ setbitn(M_VRFY250, LocalMailer->m_flags);
+ if (ProgMailer != NULL)
+ setbitn(M_VRFY250, ProgMailer->m_flags);
+ if (FileMailer != NULL)
+ setbitn(M_VRFY250, FileMailer->m_flags);
+ }
/* MIME Content-Types that cannot be transfer encoded */
setclass('n', "multipart/signed");
- /* MIME message/* subtypes that can be treated as messages */
+ /* MIME message/xxx subtypes that can be treated as messages */
setclass('s', "rfc822");
/* MIME Content-Transfer-Encodings that can be encoded */
@@ -920,11 +1075,36 @@ main(argc, argv, envp)
setclass('e', "8bit");
setclass('e', "binary");
+#ifdef USE_B_CLASS
+ /* MIME Content-Types that should be treated as binary */
+ setclass('b', "image");
+ setclass('b', "audio");
+ setclass('b', "video");
+ setclass('b', "application/octet-stream");
+#endif
+
/* operate in queue directory */
- if (OpMode != MD_TEST && chdir(QueueDir) < 0)
+ if (OpMode == MD_TEST)
+ /* nothing -- just avoid further if clauses */ ;
+ else if (QueueDir == NULL)
+ {
+ syserr("QueueDirectory (Q) option must be set");
+ ExitStat = EX_CONFIG;
+ }
+ else if (chdir(QueueDir) < 0)
{
syserr("cannot chdir(%s)", QueueDir);
- ExitStat = EX_SOFTWARE;
+ ExitStat = EX_CONFIG;
+ }
+
+ /* check host status directory for validity */
+ if (HostStatDir != NULL && !path_is_dir(HostStatDir, FALSE))
+ {
+ /* cannot use this value */
+ if (tTd(0, 2))
+ printf("Cannot use HostStatusDirectory = %s: %s\n",
+ HostStatDir, errstring(errno));
+ HostStatDir = NULL;
}
# ifdef QUEUE
@@ -965,7 +1145,7 @@ main(argc, argv, envp)
case MD_PRINT:
/* print the queue */
#ifdef QUEUE
- dropenvelope(CurEnv);
+ dropenvelope(CurEnv, TRUE);
printqueue();
endpwent();
setuid(RealUid);
@@ -975,15 +1155,33 @@ main(argc, argv, envp)
finis();
#endif /* QUEUE */
+ case MD_HOSTSTAT:
+ mci_traverse_persistent(mci_print_persistent, NULL);
+ exit(EX_OK);
+ break;
+
+ case MD_PURGESTAT:
+ mci_traverse_persistent(mci_purge_persistent, NULL);
+ exit(EX_OK);
+ break;
+
case MD_INITALIAS:
/* initialize alias database */
initmaps(TRUE, CurEnv);
endpwent();
setuid(RealUid);
- exit(EX_OK);
+ exit(ExitStat);
- case MD_DAEMON:
case MD_SMTP:
+ nullserver = FALSE;
+ /* fall through... */
+
+ case MD_DAEMON:
+ /* reset DSN parameters */
+ DefaultNotify = QPINGONFAILURE|QPINGONDELAY;
+ CurEnv->e_envid = NULL;
+ CurEnv->e_flags &= ~(EF_RET_PARAM|EF_NO_BODY_RETN);
+
/* don't open alias database -- done in srvrsmtp */
break;
@@ -995,6 +1193,8 @@ main(argc, argv, envp)
if (tTd(0, 15))
{
+ extern void printrules __P((void));
+
/* print configuration table (or at least part of it) */
if (tTd(0, 90))
printrules();
@@ -1075,8 +1275,9 @@ main(argc, argv, envp)
if (OpMode == MD_DAEMON || QueueIntvl != 0)
{
char dtype[200];
+ extern bool getrequests __P((ENVELOPE *));
- if (!tTd(99, 100))
+ if (!run_in_foreground && !tTd(99, 100))
{
/* put us in background */
i = fork();
@@ -1116,10 +1317,16 @@ main(argc, argv, envp)
pause();
}
# endif /* QUEUE */
- dropenvelope(CurEnv);
+ dropenvelope(CurEnv, TRUE);
#ifdef DAEMON
- getrequests();
+ nullserver = getrequests(CurEnv);
+
+ /* drop privileges */
+ if (RunAsGid != 0)
+ (void) setgid(RunAsGid);
+ if (RunAsUid != 0)
+ (void) setuid(RunAsUid);
/* at this point we are in a child: reset state */
(void) newenvelope(CurEnv, CurEnv);
@@ -1129,8 +1336,7 @@ main(argc, argv, envp)
*/
p = getauthinfo(fileno(InChannel));
- define('_', p, CurEnv);
-
+ define('_', p, &BlankEnvelope);
#endif /* DAEMON */
}
@@ -1141,14 +1347,34 @@ main(argc, argv, envp)
*/
if (OpMode == MD_SMTP || OpMode == MD_DAEMON)
- smtp(CurEnv);
+ {
+ char pbuf[20];
+ extern void smtp __P((bool, ENVELOPE *));
+
+ /*
+ ** Save some macros for check_* rulesets.
+ */
+
+ define(macid("{client_name}", NULL), RealHostName, &BlankEnvelope);
+ define(macid("{client_addr}", NULL),
+ newstr(anynet_ntoa(&RealHostAddr)), &BlankEnvelope);
+ if (RealHostAddr.sa.sa_family == AF_INET)
+ snprintf(pbuf, sizeof pbuf, "%d", RealHostAddr.sin.sin_port);
+ else
+ snprintf(pbuf, sizeof pbuf, "0");
+ define(macid("{client_port}", NULL), newstr(pbuf), &BlankEnvelope);
+
+ smtp(nullserver, CurEnv);
+ }
# endif /* SMTP */
+ clearenvelope(CurEnv, FALSE);
if (OpMode == MD_VERIFY)
{
CurEnv->e_sendmode = SM_VERIFY;
- CurEnv->e_errormode = EM_QUIET;
+ CurEnv->e_errormode = EM_PRINT;
PostMasterCopy = NULL;
+ HoldErrs = FALSE;
}
else
{
@@ -1224,6 +1450,8 @@ main(argc, argv, envp)
*/
finis();
+ /*NOTREACHED*/
+ return -1;
}
@@ -1264,7 +1492,8 @@ finis()
/* clean up temp files */
CurEnv->e_to = NULL;
- dropenvelope(CurEnv);
+ if (CurEnv->e_id != NULL)
+ dropenvelope(CurEnv, TRUE);
/* flush any cached connections */
mci_flush(TRUE, NULL);
@@ -1307,6 +1536,11 @@ finis()
void
intsig()
{
+#ifdef LOG
+ if (LogLevel > 79)
+ syslog(LOG_DEBUG, "%s: interrupt",
+ CurEnv->e_id == NULL ? "[NOQUEUE]" : CurEnv->e_id);
+#endif
FileName = NULL;
unlockqueue(CurEnv);
#ifdef XLA
@@ -1338,24 +1572,24 @@ intsig()
struct metamac MetaMacros[] =
{
/* LHS pattern matching characters */
- '*', MATCHZANY, '+', MATCHANY, '-', MATCHONE,
- '=', MATCHCLASS, '~', MATCHNCLASS,
+ { '*', MATCHZANY }, { '+', MATCHANY }, { '-', MATCHONE },
+ { '=', MATCHCLASS }, { '~', MATCHNCLASS },
/* these are RHS metasymbols */
- '#', CANONNET, '@', CANONHOST, ':', CANONUSER,
- '>', CALLSUBR,
+ { '#', CANONNET }, { '@', CANONHOST }, { ':', CANONUSER },
+ { '>', CALLSUBR },
/* the conditional operations */
- '?', CONDIF, '|', CONDELSE, '.', CONDFI,
+ { '?', CONDIF }, { '|', CONDELSE }, { '.', CONDFI },
/* the hostname lookup characters */
- '[', HOSTBEGIN, ']', HOSTEND,
- '(', LOOKUPBEGIN, ')', LOOKUPEND,
+ { '[', HOSTBEGIN }, { ']', HOSTEND },
+ { '(', LOOKUPBEGIN }, { ')', LOOKUPEND },
/* miscellaneous control characters */
- '&', MACRODEXPAND,
+ { '&', MACRODEXPAND },
- '\0'
+ { '\0' }
};
#define MACBINDING(name, mid) \
@@ -1427,6 +1661,11 @@ disconnect(droplev, e)
printf("don't\n");
return;
}
+#ifdef LOG
+ if (LogLevel > 93)
+ syslog(LOG_DEBUG, "%s: disconnect level %d",
+ e->e_id == NULL ? "[NOQUEUE]" : e->e_id, droplev);
+#endif
/* be sure we don't get nasty signals */
(void) setsignal(SIGINT, SIG_IGN);
@@ -1576,7 +1815,7 @@ auth_warning(e, msg, va_alist)
(void) snprintf(buf, sizeof buf, "%s: ", hostbuf);
p = &buf[strlen(buf)];
VA_START(msg);
- vsnprintf(p, sizeof buf - (p - buf), msg, ap);
+ vsnprintf(p, SPACELEFT(buf, p), msg, ap);
VA_END;
addheader("X-Authentication-Warning", buf, &e->e_header);
#ifdef LOG
@@ -1587,6 +1826,31 @@ auth_warning(e, msg, va_alist)
}
}
/*
+** GETEXTENV -- get from external environment
+**
+** Parameters:
+** envar -- the name of the variable to retrieve
+**
+** Returns:
+** The value, if any.
+*/
+
+char *
+getextenv(envar)
+ const char *envar;
+{
+ char **envp;
+ int l;
+
+ l = strlen(envar);
+ for (envp = ExternalEnviron; *envp != NULL; envp++)
+ {
+ if (strncmp(*envp, envar, l) == 0 && (*envp)[l] == '=')
+ return &(*envp)[l + 1];
+ }
+ return NULL;
+}
+ /*
** SETUSERENV -- set an environment in the propogated environment
**
** Parameters:
@@ -1611,7 +1875,7 @@ setuserenv(envar, value)
if (value == NULL)
{
- value = getenv(envar);
+ value = getextenv(envar);
if (value == NULL)
return;
}
@@ -1650,6 +1914,7 @@ dumpstate(when)
{
#ifdef LOG
register char *j = macvalue('j', CurEnv);
+ int rs;
syslog(LOG_DEBUG, "--- dumping state on %s: $j = %s ---",
when,
@@ -1664,16 +1929,18 @@ dumpstate(when)
printopenfds(TRUE);
syslog(LOG_DEBUG, "--- connection cache: ---");
mci_dump_all(TRUE);
- if (RewriteRules[89] != NULL)
+ rs = strtorwset("debug_dumpstate", NULL, ST_FIND);
+ if (rs > 0)
{
int stat;
register char **pvp;
char *pv[MAXATOM + 1];
pv[0] = NULL;
- stat = rewrite(pv, 89, 0, CurEnv);
- syslog(LOG_DEBUG, "--- ruleset 89 returns stat %d, pv: ---",
- stat);
+ stat = rewrite(pv, rs, 0, CurEnv);
+ syslog(LOG_DEBUG,
+ "--- ruleset debug_dumpstate returns stat %d, pv: ---",
+ stat);
for (pvp = pv; *pvp != NULL; pvp++)
syslog(LOG_DEBUG, "%s", *pvp);
}
@@ -1739,6 +2006,7 @@ testmodeline(line, e)
extern char *crackaddr __P((char *));
extern void dump_class __P((STAB *, int));
extern void translate_dollars __P((char *));
+ extern void help __P((char *));
switch (line[0])
{
@@ -1805,7 +2073,10 @@ testmodeline(line, e)
case 'S': /* dump rule set */
rs = strtorwset(&line[2], NULL, ST_FIND);
if (rs < 0)
+ {
+ printf("Undefined ruleset %s\n", &line[2]);
return;
+ }
rw = RewriteRules[rs];
if (rw == NULL)
return;
@@ -1827,7 +2098,7 @@ testmodeline(line, e)
putchar(' ');
}
putchar('\n');
- } while (rw = rw->r_next);
+ } while ((rw = rw->r_next) != NULL);
break;
case 'M':
@@ -1926,7 +2197,6 @@ testmodeline(line, e)
}
else if (strcasecmp(&line[1], "canon") == 0)
{
- auto int rcode = EX_OK;
char host[MAXHOSTNAMELEN];
if (*p == '\0')
@@ -1940,9 +2210,8 @@ testmodeline(line, e)
return;
}
strcpy(host, p);
- getcanonname(host, sizeof(host), HasWildcardMX, &rcode);
- printf("getcanonname(%s) returns %s (%d)\n",
- p, host, rcode);
+ (void) getcanonname(host, sizeof(host), HasWildcardMX);
+ printf("getcanonname(%s) returns %s\n", p, host);
}
else if (strcasecmp(&line[1], "map") == 0)
{
@@ -2006,6 +2275,7 @@ testmodeline(line, e)
p = remotename(q, m, tryflags, &rcode, CurEnv);
printf("Rcode = %d, addr = %s\n",
rcode, p == NULL ? "<NULL>" : p);
+ e->e_to = NULL;
}
else if (strcasecmp(&line[1], "tryflags") == 0)
{
@@ -2061,6 +2331,7 @@ testmodeline(line, e)
else
printf("mailer %s, user %s\n",
a.q_mailer->m_name, a.q_user);
+ e->e_to = NULL;
}
else
{
@@ -2098,7 +2369,10 @@ testmodeline(line, e)
int rs = strtorwset(p, NULL, ST_FIND);
if (rs < 0)
+ {
+ printf("Undefined ruleset %s\n", p);
break;
+ }
stat = rewrite(pvp, rs, 0, e);
if (stat != EX_OK)
printf("== Ruleset %s (%d) status %d\n",