summaryrefslogtreecommitdiff
path: root/usr.sbin/sendmail/src/main.c
diff options
context:
space:
mode:
authorPeter Wemm <peter@FreeBSD.org>1997-06-27 14:53:01 +0000
committerPeter Wemm <peter@FreeBSD.org>1997-06-27 14:53:01 +0000
commitf3a1fc342b4423150f71e23e50f24d073a6d238b (patch)
treea5e7dee2f9ff41f2d43580f859a6e8970722fa7d /usr.sbin/sendmail/src/main.c
parent52c4d6f5d6bb1ffd8b30c0429fc18d371856a062 (diff)
Notes
Diffstat (limited to 'usr.sbin/sendmail/src/main.c')
-rw-r--r--usr.sbin/sendmail/src/main.c193
1 files changed, 116 insertions, 77 deletions
diff --git a/usr.sbin/sendmail/src/main.c b/usr.sbin/sendmail/src/main.c
index 3c30fb3e6173..880b181ca25f 100644
--- a/usr.sbin/sendmail/src/main.c
+++ b/usr.sbin/sendmail/src/main.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1983, 1995, 1996 Eric P. Allman
+ * Copyright (c) 1983, 1995-1997 Eric P. Allman
* Copyright (c) 1988, 1993
* The Regents of the University of California. All rights reserved.
*
@@ -39,7 +39,7 @@ static char copyright[] =
#endif /* not lint */
#ifndef lint
-static char sccsid[] = "@(#)main.c 8.230 (Berkeley) 1/17/97";
+static char sccsid[] = "@(#)main.c 8.246 (Berkeley) 6/11/97";
#endif /* not lint */
#define _DEFINE
@@ -62,13 +62,8 @@ char edata, end;
** turn calls a bunch of mail servers that do the real work of
** delivering the mail.
**
-** Sendmail is driven by tables read in from /usr/lib/sendmail.cf
-** (read by readcf.c). Some more static configuration info,
-** including some code that you may want to tailor for your
-** installation, is in conf.c. You may also want to touch
-** daemon.c (if you have some other IPC mechanism), acct.c
-** (to change your accounting), names.c (to adjust the name
-** server mechanism).
+** Sendmail is driven by settings read in from /etc/sendmail.cf
+** (read by readcf.c).
**
** Usage:
** /usr/lib/sendmail [flags] addr ...
@@ -82,7 +77,7 @@ char edata, end;
** International Computer Science Institute
** (11/88 - 9/89).
** UCB/Mammoth Project (10/89 - 7/95).
-** InReference, Inc. (8/95 - present).
+** InReference, Inc. (8/95 - 1/97).
** 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.
@@ -99,6 +94,10 @@ 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 */
+#ifdef NGROUPS_MAX
+GIDSET_T InitialGidSet[NGROUPS_MAX];
+#endif
+
static void obsolete();
extern void printmailer __P((MAILER *));
extern void tTflag __P((char *));
@@ -219,7 +218,7 @@ main(argc, argv, envp)
}
errno = 0;
-#ifdef LOG
+#if LOG
# ifdef LOG_MAIL
openlog("sendmail", LOG_PID, LOG_MAIL);
# else
@@ -229,6 +228,15 @@ main(argc, argv, envp)
tTsetup(tTdvect, sizeof tTdvect, "0-99.1");
+#ifdef NGROUPS_MAX
+ /* save initial group set for future checks */
+ i = getgroups(NGROUPS_MAX, InitialGidSet);
+ if (i == 0)
+ InitialGidSet[0] = (GID_T) -1;
+ while (i < NGROUPS_MAX)
+ InitialGidSet[i++] = InitialGidSet[0];
+#endif
+
/* drop group id privileges (RunAsUser not yet set) */
drop_privileges();
@@ -489,9 +497,6 @@ main(argc, argv, envp)
#endif
}
- /* probe interfaces and locate any additional names */
- load_if_names();
-
/* current time */
define('b', arpadate((char *) NULL), CurEnv);
@@ -828,6 +833,10 @@ main(argc, argv, envp)
expand("\201m", jbuf, sizeof jbuf, CurEnv);
setclass('m', jbuf);
+ /* probe interfaces and locate any additional names */
+ if (!DontProbeInterfaces)
+ load_if_names();
+
if (tTd(0, 1))
{
printf("\n============ SYSTEM IDENTITY (after readcf) ============");
@@ -880,6 +889,10 @@ main(argc, argv, envp)
setuserenv("TZ", NULL);
tzset();
+ /* be sure we don't pick up bogus HOSTALIASES environment variable */
+ if (queuemode && RealUid != 0)
+ (void) unsetenv("HOSTALIASES");
+
/* check for sane configuration level */
if (ConfigLevel > MAXCONFIGLEVEL)
{
@@ -904,13 +917,12 @@ main(argc, argv, envp)
/* check for permissions */
if ((OpMode == MD_DAEMON || OpMode == MD_PURGESTAT) && RealUid != 0)
{
-#ifdef LOG
if (LogLevel > 1)
- syslog(LOG_ALERT, "user %d attempted to %s",
+ sm_syslog(LOG_ALERT, NOQID,
+ "user %d attempted to %s",
RealUid,
OpMode == MD_DAEMON ? "run daemon"
: "purge host status");
-#endif
usrerr("Permission denied");
exit(EX_USAGE);
}
@@ -923,6 +935,8 @@ main(argc, argv, envp)
case MD_TEST:
/* don't have persistent host status in test mode */
HostStatDir = NULL;
+ Verbose = 2;
+ CurEnv->e_errormode = EM_PRINT;
break;
case MD_FGDAEMON:
@@ -938,10 +952,9 @@ main(argc, argv, envp)
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
+ sm_syslog(LOG_WARNING, NOQID,
+ "daemon invoked without full pathname; kill -1 won't work");
setsignal(SIGHUP, sighup);
/* workaround: can't seem to release the signal in the parent */
@@ -949,7 +962,8 @@ main(argc, argv, envp)
break;
case MD_INITALIAS:
- Verbose = TRUE;
+ Verbose = 2;
+ CurEnv->e_errormode = EM_PRINT;
/* fall through... */
case MD_PRINT:
@@ -1088,17 +1102,23 @@ main(argc, argv, envp)
#endif
/* operate in queue directory */
- if (OpMode == MD_TEST)
- /* nothing -- just avoid further if clauses */ ;
- else if (QueueDir == NULL)
+ if (QueueDir == NULL)
{
- syserr("QueueDirectory (Q) option must be set");
- ExitStat = EX_CONFIG;
+ if (OpMode != MD_TEST)
+ {
+ syserr("QueueDirectory (Q) option must be set");
+ ExitStat = EX_CONFIG;
+ }
}
- else if (chdir(QueueDir) < 0)
+ else
{
- syserr("cannot chdir(%s)", QueueDir);
- ExitStat = EX_CONFIG;
+ /* test path to get warning messages */
+ (void) safedirpath(QueueDir, (uid_t) 0, (gid_t) 0, NULL, SFF_ANYFILE);
+ if (OpMode != MD_TEST && chdir(QueueDir) < 0)
+ {
+ syserr("cannot chdir(%s)", QueueDir);
+ ExitStat = EX_CONFIG;
+ }
}
/* check host status directory for validity */
@@ -1226,7 +1246,7 @@ main(argc, argv, envp)
SIGFUNC_DECL intindebug __P((int));
if (isatty(fileno(stdin)))
- Verbose = TRUE;
+ Verbose = 2;
if (Verbose)
{
@@ -1261,7 +1281,6 @@ main(argc, argv, envp)
if (queuemode && OpMode != MD_DAEMON && QueueIntvl == 0)
{
- (void) unsetenv("HOSTALIASES");
(void) runqueue(FALSE, Verbose);
finis();
}
@@ -1305,9 +1324,8 @@ main(argc, argv, envp)
if (tTd(0, 1))
strcat(dtype, "+debugging");
-#ifdef LOG
- syslog(LOG_INFO, "starting daemon (%s): %s", Version, dtype + 1);
-#endif
+ sm_syslog(LOG_INFO, NOQID,
+ "starting daemon (%s): %s", Version, dtype + 1);
#ifdef XLA
xla_create_file();
#endif
@@ -1317,8 +1335,14 @@ main(argc, argv, envp)
{
(void) runqueue(TRUE, FALSE);
if (OpMode != MD_DAEMON)
+ {
for (;;)
+ {
pause();
+ if (DoQueueRun)
+ (void) runqueue(TRUE, FALSE);
+ }
+ }
}
# endif /* QUEUE */
dropenvelope(CurEnv, TRUE);
@@ -1402,7 +1426,7 @@ main(argc, argv, envp)
/* collect body for UUCP return */
if (OpMode != MD_VERIFY)
- collect(InChannel, FALSE, FALSE, NULL, CurEnv);
+ collect(InChannel, FALSE, NULL, CurEnv);
finis();
}
@@ -1423,8 +1447,21 @@ main(argc, argv, envp)
CurEnv->e_to = NULL;
if (OpMode != MD_VERIFY || GrabTo)
{
+ long savedflags = CurEnv->e_flags & EF_FATALERRS;
+
CurEnv->e_flags |= EF_GLOBALERRS;
- collect(InChannel, FALSE, FALSE, NULL, CurEnv);
+ CurEnv->e_flags &= ~EF_FATALERRS;
+ collect(InChannel, FALSE, NULL, CurEnv);
+
+ /* bail out if there were fatal errors in collect */
+ if (OpMode != MD_VERIFY && bitset(EF_FATALERRS, CurEnv->e_flags))
+ {
+ CurEnv->e_flags |= EF_CLRQUEUE;
+ finis();
+ /*NOTREACHED*/
+ return -1;
+ }
+ CurEnv->e_flags |= savedflags;
}
errno = 0;
@@ -1443,6 +1480,7 @@ main(argc, argv, envp)
printaddr(&CurEnv->e_from, FALSE);
}
CurEnv->e_to = NULL;
+ CurrentLA = getla();
sendall(CurEnv, SM_DEFAULT);
/*
@@ -1493,6 +1531,13 @@ finis()
if (tTd(2, 9))
printopenfds(FALSE);
+ /* if we fail in finis(), just exit */
+ if (setjmp(TopFrame) != 0)
+ {
+ /* failed -- just give it up */
+ goto forceexit;
+ }
+
/* clean up temp files */
CurEnv->e_to = NULL;
if (CurEnv->e_id != NULL)
@@ -1507,10 +1552,11 @@ finis()
# endif
/* and exit */
-# ifdef LOG
+ forceexit:
if (LogLevel > 78)
- syslog(LOG_DEBUG, "finis, pid=%d", getpid());
-# endif /* LOG */
+ sm_syslog(LOG_DEBUG, CurEnv->e_id,
+ "finis, pid=%d",
+ getpid());
if (ExitStat == EX_TEMPFAIL || CurEnv->e_errormode == EM_BERKNET)
ExitStat = EX_OK;
@@ -1540,11 +1586,8 @@ SIGFUNC_DECL
intsig(sig)
int sig;
{
-#ifdef LOG
if (LogLevel > 79)
- syslog(LOG_DEBUG, "%s: interrupt",
- CurEnv->e_id == NULL ? "[NOQUEUE]" : CurEnv->e_id);
-#endif
+ sm_syslog(LOG_DEBUG, CurEnv->e_id, "interrupt");
FileName = NULL;
unlockqueue(CurEnv);
#ifdef XLA
@@ -1665,11 +1708,10 @@ 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
+ sm_syslog(LOG_DEBUG, e->e_id,
+ "disconnect level %d",
+ droplev);
/* be sure we don't get nasty signals */
(void) setsignal(SIGINT, SIG_IGN);
@@ -1678,7 +1720,7 @@ disconnect(droplev, e)
/* we can't communicate with our caller, so.... */
HoldErrs = TRUE;
CurEnv->e_errormode = EM_MAIL;
- Verbose = FALSE;
+ Verbose = 0;
DisConnected = TRUE;
/* all input from /dev/null */
@@ -1719,10 +1761,10 @@ disconnect(droplev, e)
checkfd012("disconnect");
#endif
-# ifdef LOG
if (LogLevel > 71)
- syslog(LOG_DEBUG, "in background, pid=%d", getpid());
-# endif /* LOG */
+ sm_syslog(LOG_DEBUG, e->e_id,
+ "in background, pid=%d",
+ getpid());
errno = 0;
}
@@ -1822,11 +1864,10 @@ auth_warning(e, msg, va_alist)
vsnprintf(p, SPACELEFT(buf, 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
+ sm_syslog(LOG_INFO, e->e_id,
+ "Authentication-Warning: %.400s",
+ buf);
}
}
/*
@@ -1916,22 +1957,23 @@ void
dumpstate(when)
char *when;
{
-#ifdef LOG
register char *j = macvalue('j', CurEnv);
int rs;
- syslog(LOG_DEBUG, "--- dumping state on %s: $j = %s ---",
+ sm_syslog(LOG_DEBUG, CurEnv->e_id,
+ "--- dumping state on %s: $j = %s ---",
when,
j == NULL ? "<NULL>" : j);
if (j != NULL)
{
if (!wordinclass(j, 'w'))
- syslog(LOG_DEBUG, "*** $j not in $=w ***");
+ sm_syslog(LOG_DEBUG, CurEnv->e_id,
+ "*** $j not in $=w ***");
}
- syslog(LOG_DEBUG, "CurChildren = %d", CurChildren);
- syslog(LOG_DEBUG, "--- open file descriptors: ---");
+ sm_syslog(LOG_DEBUG, CurEnv->e_id, "CurChildren = %d", CurChildren);
+ sm_syslog(LOG_DEBUG, CurEnv->e_id, "--- open file descriptors: ---");
printopenfds(TRUE);
- syslog(LOG_DEBUG, "--- connection cache: ---");
+ sm_syslog(LOG_DEBUG, CurEnv->e_id, "--- connection cache: ---");
mci_dump_all(TRUE);
rs = strtorwset("debug_dumpstate", NULL, ST_FIND);
if (rs > 0)
@@ -1942,14 +1984,13 @@ dumpstate(when)
pv[0] = NULL;
stat = rewrite(pv, rs, 0, CurEnv);
- syslog(LOG_DEBUG,
+ sm_syslog(LOG_DEBUG, CurEnv->e_id,
"--- ruleset debug_dumpstate returns stat %d, pv: ---",
stat);
for (pvp = pv; *pvp != NULL; pvp++)
- syslog(LOG_DEBUG, "%s", *pvp);
+ sm_syslog(LOG_DEBUG, CurEnv->e_id, "%s", *pvp);
}
- syslog(LOG_DEBUG, "--- end of state dump ---");
-#endif
+ sm_syslog(LOG_DEBUG, CurEnv->e_id, "--- end of state dump ---");
}
@@ -1968,31 +2009,24 @@ sighup(sig)
{
if (SaveArgv[0][0] != '/')
{
-#ifdef LOG
if (LogLevel > 3)
- syslog(LOG_INFO, "could not restart: need full path");
-#endif
+ sm_syslog(LOG_INFO, NOQID, "could not restart: need full path");
exit(EX_OSFILE);
}
-#ifdef LOG
if (LogLevel > 3)
- syslog(LOG_INFO, "restarting %s on signal", SaveArgv[0]);
-#endif
+ sm_syslog(LOG_INFO, NOQID, "restarting %s on signal", SaveArgv[0]);
+ alarm(0);
releasesignal(SIGHUP);
if (setgid(RealGid) < 0 || setuid(RealUid) < 0)
{
-#ifdef LOG
if (LogLevel > 0)
- syslog(LOG_ALERT, "could not set[ug]id(%d, %d): %m",
+ sm_syslog(LOG_ALERT, NOQID, "could not set[ug]id(%d, %d): %m",
RealUid, RealGid);
-#endif
exit(EX_OSERR);
}
execv(SaveArgv[0], (ARGV_T) SaveArgv);
-#ifdef LOG
if (LogLevel > 0)
- syslog(LOG_ALERT, "could not exec %s: %m", SaveArgv[0]);
-#endif
+ sm_syslog(LOG_ALERT, NOQID, "could not exec %s: %m", SaveArgv[0]);
exit(EX_OSFILE);
}
/*
@@ -2285,6 +2319,11 @@ testmodeline(line, e)
printf("Map named \"%s\" not found\n", p);
return;
}
+ if (!bitset(MF_OPEN, map->s_map.map_mflags))
+ {
+ printf("Map named \"%s\" not open\n", p);
+ return;
+ }
printf("map_lookup: %s (%s) ", p, q);
p = (*map->s_map.map_class->map_lookup)
(&map->s_map, q, NULL, &rcode);