1c2aa98e2SPeter Wemm /*
25dd76dd0SGregory Neil Shapiro * Copyright (c) 1998-2006, 2008, 2009, 2011 Proofpoint, Inc. and its suppliers.
306f25ae9SGregory Neil Shapiro * All rights reserved.
4c2aa98e2SPeter Wemm * Copyright (c) 1983, 1995-1997 Eric P. Allman. All rights reserved.
5c2aa98e2SPeter Wemm * Copyright (c) 1988, 1993
6c2aa98e2SPeter Wemm * The Regents of the University of California. All rights reserved.
7c2aa98e2SPeter Wemm *
8c2aa98e2SPeter Wemm * By using this file, you agree to the terms and conditions set
9c2aa98e2SPeter Wemm * forth in the LICENSE file which can be found at the top level of
10c2aa98e2SPeter Wemm * the sendmail distribution.
11c2aa98e2SPeter Wemm *
12c2aa98e2SPeter Wemm */
13c2aa98e2SPeter Wemm
1440266059SGregory Neil Shapiro #define _DEFINE
1540266059SGregory Neil Shapiro #include <sendmail.h>
16d0cef73dSGregory Neil Shapiro #include <sm/sendmail.h>
1740266059SGregory Neil Shapiro #include <sm/xtrap.h>
1840266059SGregory Neil Shapiro #include <sm/signal.h>
195b0945b5SGregory Neil Shapiro #include <tls.h>
202fb4f839SGregory Neil Shapiro #if _FFR_8BITENVADDR
212fb4f839SGregory Neil Shapiro # include <sm/ixlen.h>
222fb4f839SGregory Neil Shapiro #endif
232fb4f839SGregory Neil Shapiro #if _FFR_DMTRIGGER
242fb4f839SGregory Neil Shapiro # include <sm/notify.h>
252fb4f839SGregory Neil Shapiro #endif
2640266059SGregory Neil Shapiro
27c2aa98e2SPeter Wemm #ifndef lint
2840266059SGregory Neil Shapiro SM_UNUSED(static char copyright[]) =
295dd76dd0SGregory Neil Shapiro "@(#) Copyright (c) 1998-2013 Proofpoint, Inc. and its suppliers.\n\
3006f25ae9SGregory Neil Shapiro All rights reserved.\n\
31c2aa98e2SPeter Wemm Copyright (c) 1983, 1995-1997 Eric P. Allman. All rights reserved.\n\
32c2aa98e2SPeter Wemm Copyright (c) 1988, 1993\n\
33c2aa98e2SPeter Wemm The Regents of the University of California. All rights reserved.\n";
3406f25ae9SGregory Neil Shapiro #endif /* ! lint */
35c2aa98e2SPeter Wemm
364313cc83SGregory Neil Shapiro SM_RCSID("@(#)$Id: main.c,v 8.988 2013-11-23 02:52:37 gshapiro Exp $")
3706f25ae9SGregory Neil Shapiro
3806f25ae9SGregory Neil Shapiro
3906f25ae9SGregory Neil Shapiro #if NETINET || NETINET6
40c2aa98e2SPeter Wemm # include <arpa/inet.h>
415b0945b5SGregory Neil Shapiro # if DANE
425b0945b5SGregory Neil Shapiro # include "sm_resolve.h"
435b0945b5SGregory Neil Shapiro # endif
445b0945b5SGregory Neil Shapiro #endif
4506f25ae9SGregory Neil Shapiro
4640266059SGregory Neil Shapiro /* for getcfname() */
4740266059SGregory Neil Shapiro #include <sendmail/pathnames.h>
485b0945b5SGregory Neil Shapiro #include <ratectrl.h>
4940266059SGregory Neil Shapiro
5040266059SGregory Neil Shapiro static SM_DEBUG_T
5140266059SGregory Neil Shapiro DebugNoPRestart = SM_DEBUG_INITIALIZER("no_persistent_restart",
5240266059SGregory Neil Shapiro "@(#)$Debug: no_persistent_restart - don't restart, log only $");
5340266059SGregory Neil Shapiro
5406f25ae9SGregory Neil Shapiro static void dump_class __P((STAB *, int));
5506f25ae9SGregory Neil Shapiro static void obsolete __P((char **));
5606f25ae9SGregory Neil Shapiro static void testmodeline __P((char *, ENVELOPE *));
5740266059SGregory Neil Shapiro static char *getextenv __P((const char *));
5840266059SGregory Neil Shapiro static void sm_printoptions __P((char **));
5940266059SGregory Neil Shapiro static SIGFUNC_DECL intindebug __P((int));
6040266059SGregory Neil Shapiro static SIGFUNC_DECL sighup __P((int));
6140266059SGregory Neil Shapiro static SIGFUNC_DECL sigpipe __P((int));
6240266059SGregory Neil Shapiro static SIGFUNC_DECL sigterm __P((int));
6340266059SGregory Neil Shapiro #ifdef SIGUSR1
6440266059SGregory Neil Shapiro static SIGFUNC_DECL sigusr1 __P((int));
655b0945b5SGregory Neil Shapiro #endif
66c2aa98e2SPeter Wemm
67c2aa98e2SPeter Wemm /*
68c2aa98e2SPeter Wemm ** SENDMAIL -- Post mail to a set of destinations.
69c2aa98e2SPeter Wemm **
70c2aa98e2SPeter Wemm ** This is the basic mail router. All user mail programs should
71c2aa98e2SPeter Wemm ** call this routine to actually deliver mail. Sendmail in
72c2aa98e2SPeter Wemm ** turn calls a bunch of mail servers that do the real work of
73c2aa98e2SPeter Wemm ** delivering the mail.
74c2aa98e2SPeter Wemm **
7506f25ae9SGregory Neil Shapiro ** Sendmail is driven by settings read in from /etc/mail/sendmail.cf
76c2aa98e2SPeter Wemm ** (read by readcf.c).
77c2aa98e2SPeter Wemm **
78c2aa98e2SPeter Wemm ** Usage:
79c2aa98e2SPeter Wemm ** /usr/lib/sendmail [flags] addr ...
80c2aa98e2SPeter Wemm **
81c2aa98e2SPeter Wemm ** See the associated documentation for details.
82c2aa98e2SPeter Wemm **
8340266059SGregory Neil Shapiro ** Authors:
84c2aa98e2SPeter Wemm ** Eric Allman, UCB/INGRES (until 10/81).
85c2aa98e2SPeter Wemm ** Britton-Lee, Inc., purveyors of fine
86c2aa98e2SPeter Wemm ** database computers (11/81 - 10/88).
87c2aa98e2SPeter Wemm ** International Computer Science Institute
88c2aa98e2SPeter Wemm ** (11/88 - 9/89).
89c2aa98e2SPeter Wemm ** UCB/Mammoth Project (10/89 - 7/95).
90c2aa98e2SPeter Wemm ** InReference, Inc. (8/95 - 1/97).
915dd76dd0SGregory Neil Shapiro ** Sendmail, Inc. (1/98 - 9/13).
92d9986b26SGregory Neil Shapiro ** The support of my employers is gratefully acknowledged.
93c2aa98e2SPeter Wemm ** Few of them (Britton-Lee in particular) have had
94c2aa98e2SPeter Wemm ** anything to gain from my involvement in this project.
9540266059SGregory Neil Shapiro **
9640266059SGregory Neil Shapiro ** Gregory Neil Shapiro,
9740266059SGregory Neil Shapiro ** Worcester Polytechnic Institute (until 3/98).
985dd76dd0SGregory Neil Shapiro ** Sendmail, Inc. (3/98 - 10/13).
995dd76dd0SGregory Neil Shapiro ** Proofpoint, Inc. (10/13 - present).
10040266059SGregory Neil Shapiro **
10140266059SGregory Neil Shapiro ** Claus Assmann,
1025dd76dd0SGregory Neil Shapiro ** Sendmail, Inc. (12/98 - 10/13).
1035dd76dd0SGregory Neil Shapiro ** Proofpoint, Inc. (10/13 - present).
104c2aa98e2SPeter Wemm */
105c2aa98e2SPeter Wemm
106c2aa98e2SPeter Wemm char *FullName; /* sender's full name */
107c2aa98e2SPeter Wemm ENVELOPE BlankEnvelope; /* a "blank" envelope */
10806f25ae9SGregory Neil Shapiro static ENVELOPE MainEnvelope; /* the envelope around the basic letter */
109c2aa98e2SPeter Wemm ADDRESS NullAddress = /* a null address */
110c2aa98e2SPeter Wemm { "", "", NULL, "" };
111c2aa98e2SPeter Wemm char *CommandLineArgs; /* command line args for pid file */
11240266059SGregory Neil Shapiro bool Warn_Q_option = false; /* warn about Q option use */
11306f25ae9SGregory Neil Shapiro static int MissingFds = 0; /* bit map of fds missing on startup */
11440266059SGregory Neil Shapiro char *Mbdb = "pw"; /* mailbox database defaults to /etc/passwd */
115c2aa98e2SPeter Wemm
116c2aa98e2SPeter Wemm #ifdef NGROUPS_MAX
117c2aa98e2SPeter Wemm GIDSET_T InitialGidSet[NGROUPS_MAX];
1185b0945b5SGregory Neil Shapiro #endif
119c2aa98e2SPeter Wemm
12040266059SGregory Neil Shapiro #define MAXCONFIGLEVEL 10 /* highest config version level known */
12106f25ae9SGregory Neil Shapiro
12206f25ae9SGregory Neil Shapiro #if SASL
12306f25ae9SGregory Neil Shapiro static sasl_callback_t srvcallbacks[] =
12406f25ae9SGregory Neil Shapiro {
12535954bbaSHajimu UMEMOTO { SASL_CB_VERIFYFILE, (sasl_callback_ft)&safesaslfile, NULL },
12635954bbaSHajimu UMEMOTO { SASL_CB_PROXY_POLICY, (sasl_callback_ft)&proxy_policy, NULL },
12706f25ae9SGregory Neil Shapiro { SASL_CB_LIST_END, NULL, NULL }
12806f25ae9SGregory Neil Shapiro };
12906f25ae9SGregory Neil Shapiro #endif /* SASL */
13006f25ae9SGregory Neil Shapiro
13140266059SGregory Neil Shapiro unsigned int SubmitMode;
13240266059SGregory Neil Shapiro int SyslogPrefixLen; /* estimated length of syslog prefix */
13340266059SGregory Neil Shapiro #define PIDLEN 6 /* pid length for computing SyslogPrefixLen */
13440266059SGregory Neil Shapiro #ifndef SL_FUDGE
13540266059SGregory Neil Shapiro # define SL_FUDGE 10 /* fudge offset for SyslogPrefixLen */
1365b0945b5SGregory Neil Shapiro #endif
13740266059SGregory Neil Shapiro #define SLDLL 8 /* est. length of default syslog label */
13840266059SGregory Neil Shapiro
13940266059SGregory Neil Shapiro
14040266059SGregory Neil Shapiro /* Some options are dangerous to allow users to use in non-submit mode */
14140266059SGregory Neil Shapiro #define CHECK_AGAINST_OPMODE(cmd) \
14240266059SGregory Neil Shapiro { \
14340266059SGregory Neil Shapiro if (extraprivs && \
14440266059SGregory Neil Shapiro OpMode != MD_DELIVER && OpMode != MD_SMTP && \
1459bd497b8SGregory Neil Shapiro OpMode != MD_ARPAFTP && OpMode != MD_CHECKCONFIG && \
14640266059SGregory Neil Shapiro OpMode != MD_VERIFY && OpMode != MD_TEST) \
14740266059SGregory Neil Shapiro { \
14840266059SGregory Neil Shapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, \
14940266059SGregory Neil Shapiro "WARNING: Ignoring submission mode -%c option (not in submission mode)\n", \
15040266059SGregory Neil Shapiro (cmd)); \
15140266059SGregory Neil Shapiro break; \
15240266059SGregory Neil Shapiro } \
15340266059SGregory Neil Shapiro if (extraprivs && queuerun) \
15440266059SGregory Neil Shapiro { \
15540266059SGregory Neil Shapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, \
15640266059SGregory Neil Shapiro "WARNING: Ignoring submission mode -%c option with -q\n", \
15740266059SGregory Neil Shapiro (cmd)); \
15840266059SGregory Neil Shapiro break; \
15940266059SGregory Neil Shapiro } \
16040266059SGregory Neil Shapiro }
161c2aa98e2SPeter Wemm
162c2aa98e2SPeter Wemm int
main(argc,argv,envp)163c2aa98e2SPeter Wemm main(argc, argv, envp)
164c2aa98e2SPeter Wemm int argc;
165c2aa98e2SPeter Wemm char **argv;
166c2aa98e2SPeter Wemm char **envp;
167c2aa98e2SPeter Wemm {
1682fb4f839SGregory Neil Shapiro char *p;
169c2aa98e2SPeter Wemm char **av;
170c2aa98e2SPeter Wemm extern char Version[];
1712fb4f839SGregory Neil Shapiro char *ep, *fromaddr;
1722fb4f839SGregory Neil Shapiro #if USE_EAI
1732fb4f839SGregory Neil Shapiro char *fromaddr_x;
1742fb4f839SGregory Neil Shapiro #else
1752fb4f839SGregory Neil Shapiro # define fromaddr_x fromaddr
1762fb4f839SGregory Neil Shapiro #endif
177c2aa98e2SPeter Wemm STAB *st;
178c2aa98e2SPeter Wemm register int i;
179c2aa98e2SPeter Wemm int j;
18006f25ae9SGregory Neil Shapiro int dp;
18140266059SGregory Neil Shapiro int fill_errno;
18240266059SGregory Neil Shapiro int qgrp = NOQGRP; /* queue group to process */
18340266059SGregory Neil Shapiro bool safecf = true;
18406f25ae9SGregory Neil Shapiro BITMAP256 *p_flags = NULL; /* daemon flags */
18540266059SGregory Neil Shapiro bool warn_C_flag = false;
18640266059SGregory Neil Shapiro bool auth = true; /* whether to set e_auth_param */
187c2aa98e2SPeter Wemm char warn_f_flag = '\0';
18840266059SGregory Neil Shapiro bool run_in_foreground = false; /* -bD mode */
18940266059SGregory Neil Shapiro bool queuerun = false, debug = false;
190c2aa98e2SPeter Wemm struct passwd *pw;
191c2aa98e2SPeter Wemm struct hostent *hp;
192c2aa98e2SPeter Wemm char *nullserver = NULL;
19306f25ae9SGregory Neil Shapiro char *authinfo = NULL;
19406f25ae9SGregory Neil Shapiro char *sysloglabel = NULL; /* label for syslog */
19540266059SGregory Neil Shapiro char *conffile = NULL; /* name of .cf file */
19640266059SGregory Neil Shapiro char *queuegroup = NULL; /* queue group to process */
19740266059SGregory Neil Shapiro char *quarantining = NULL; /* quarantine queue items? */
19840266059SGregory Neil Shapiro bool extraprivs;
19940266059SGregory Neil Shapiro bool forged, negate;
20040266059SGregory Neil Shapiro bool queuepersistent = false; /* queue runner process runs forever */
20140266059SGregory Neil Shapiro bool foregroundqueue = false; /* queue run in foreground */
20240266059SGregory Neil Shapiro bool save_val; /* to save some bool var. */
20340266059SGregory Neil Shapiro int cftype; /* which cf file to use? */
204e92d3f3fSGregory Neil Shapiro SM_FILE_T *smdebug;
20540266059SGregory Neil Shapiro static time_t starttime = 0; /* when was process started */
20606f25ae9SGregory Neil Shapiro struct stat traf_st; /* for TrafficLog FIFO check */
20740266059SGregory Neil Shapiro char buf[MAXLINE];
208c2aa98e2SPeter Wemm char jbuf[MAXHOSTNAMELEN]; /* holds MyHostName */
2092fb4f839SGregory Neil Shapiro static char rnamebuf[MAXNAME]; /* holds RealUserName */ /* EAI:ok */
210c2aa98e2SPeter Wemm char *emptyenviron[1];
21142e5d165SGregory Neil Shapiro #if STARTTLS
21242e5d165SGregory Neil Shapiro bool tls_ok;
2135b0945b5SGregory Neil Shapiro #endif
214c2aa98e2SPeter Wemm QUEUE_CHAR *new;
21540266059SGregory Neil Shapiro ENVELOPE *e;
216c2aa98e2SPeter Wemm extern int DtableSize;
217c2aa98e2SPeter Wemm extern int optind;
218c2aa98e2SPeter Wemm extern int opterr;
219c2aa98e2SPeter Wemm extern char *optarg;
220c2aa98e2SPeter Wemm extern char **environ;
22140266059SGregory Neil Shapiro #if SASL
22240266059SGregory Neil Shapiro extern void sm_sasl_init __P((void));
2235b0945b5SGregory Neil Shapiro #endif
22440266059SGregory Neil Shapiro
22540266059SGregory Neil Shapiro #if USE_ENVIRON
22640266059SGregory Neil Shapiro envp = environ;
2275b0945b5SGregory Neil Shapiro #endif
22840266059SGregory Neil Shapiro
22940266059SGregory Neil Shapiro /* turn off profiling */
23040266059SGregory Neil Shapiro SM_PROF(0);
23140266059SGregory Neil Shapiro
23240266059SGregory Neil Shapiro /* install default exception handler */
23340266059SGregory Neil Shapiro sm_exc_newthread(fatal_error);
234c2aa98e2SPeter Wemm
23513bd1963SGregory Neil Shapiro /* set the default in/out channel so errors reported to screen */
23613bd1963SGregory Neil Shapiro InChannel = smioin;
23713bd1963SGregory Neil Shapiro OutChannel = smioout;
23813bd1963SGregory Neil Shapiro
239c2aa98e2SPeter Wemm /*
240c2aa98e2SPeter Wemm ** Check to see if we reentered.
241c2aa98e2SPeter Wemm ** This would normally happen if e_putheader or e_putbody
242c2aa98e2SPeter Wemm ** were NULL when invoked.
243c2aa98e2SPeter Wemm */
244c2aa98e2SPeter Wemm
24540266059SGregory Neil Shapiro if (starttime != 0)
246c2aa98e2SPeter Wemm {
247c2aa98e2SPeter Wemm syserr("main: reentered!");
248c2aa98e2SPeter Wemm abort();
249c2aa98e2SPeter Wemm }
25040266059SGregory Neil Shapiro starttime = curtime();
251c2aa98e2SPeter Wemm
252c2aa98e2SPeter Wemm /* avoid null pointer dereferences */
253d0cef73dSGregory Neil Shapiro TermEscape.te_rv_on = TermEscape.te_under_on = TermEscape.te_normal = "";
254c2aa98e2SPeter Wemm
25540266059SGregory Neil Shapiro RealUid = getuid();
25640266059SGregory Neil Shapiro RealGid = getgid();
25740266059SGregory Neil Shapiro
25840266059SGregory Neil Shapiro /* Check if sendmail is running with extra privs */
25940266059SGregory Neil Shapiro extraprivs = (RealUid != 0 &&
26040266059SGregory Neil Shapiro (geteuid() != getuid() || getegid() != getgid()));
26140266059SGregory Neil Shapiro
26240266059SGregory Neil Shapiro CurrentPid = getpid();
26340266059SGregory Neil Shapiro
26440266059SGregory Neil Shapiro /* get whatever .cf file is right for the opmode */
26540266059SGregory Neil Shapiro cftype = SM_GET_RIGHT_CF;
26640266059SGregory Neil Shapiro
26740266059SGregory Neil Shapiro /* in 4.4BSD, the table can be huge; impose a reasonable limit */
26840266059SGregory Neil Shapiro DtableSize = getdtsize();
26940266059SGregory Neil Shapiro if (DtableSize > 256)
27040266059SGregory Neil Shapiro DtableSize = 256;
27140266059SGregory Neil Shapiro
27240266059SGregory Neil Shapiro /*
27340266059SGregory Neil Shapiro ** Be sure we have enough file descriptors.
27440266059SGregory Neil Shapiro ** But also be sure that 0, 1, & 2 are open.
27540266059SGregory Neil Shapiro */
27640266059SGregory Neil Shapiro
27740266059SGregory Neil Shapiro /* reset errno and fill_errno; the latter is used way down below */
27840266059SGregory Neil Shapiro errno = fill_errno = 0;
27940266059SGregory Neil Shapiro fill_fd(STDIN_FILENO, NULL);
28040266059SGregory Neil Shapiro if (errno != 0)
28140266059SGregory Neil Shapiro fill_errno = errno;
28240266059SGregory Neil Shapiro fill_fd(STDOUT_FILENO, NULL);
28340266059SGregory Neil Shapiro if (errno != 0)
28440266059SGregory Neil Shapiro fill_errno = errno;
28540266059SGregory Neil Shapiro fill_fd(STDERR_FILENO, NULL);
28640266059SGregory Neil Shapiro if (errno != 0)
28740266059SGregory Neil Shapiro fill_errno = errno;
28840266059SGregory Neil Shapiro
289e92d3f3fSGregory Neil Shapiro sm_closefrom(STDERR_FILENO + 1, DtableSize);
29040266059SGregory Neil Shapiro errno = 0;
291e92d3f3fSGregory Neil Shapiro smdebug = NULL;
29240266059SGregory Neil Shapiro
29340266059SGregory Neil Shapiro #if LOG
29440266059SGregory Neil Shapiro # ifndef SM_LOG_STR
29540266059SGregory Neil Shapiro # define SM_LOG_STR "sendmail"
2965b0945b5SGregory Neil Shapiro # endif
29740266059SGregory Neil Shapiro # ifdef LOG_MAIL
29840266059SGregory Neil Shapiro openlog(SM_LOG_STR, LOG_PID, LOG_MAIL);
2995b0945b5SGregory Neil Shapiro # else
30040266059SGregory Neil Shapiro openlog(SM_LOG_STR, LOG_PID);
3015b0945b5SGregory Neil Shapiro # endif
30240266059SGregory Neil Shapiro #endif /* LOG */
30340266059SGregory Neil Shapiro
3048774250cSGregory Neil Shapiro /*
3058774250cSGregory Neil Shapiro ** Seed the random number generator.
3068774250cSGregory Neil Shapiro ** Used for queue file names, picking a queue directory, and
3078774250cSGregory Neil Shapiro ** MX randomization.
3088774250cSGregory Neil Shapiro */
3098774250cSGregory Neil Shapiro
3108774250cSGregory Neil Shapiro seed_random();
3118774250cSGregory Neil Shapiro
312c2aa98e2SPeter Wemm /* do machine-dependent initializations */
313c2aa98e2SPeter Wemm init_md(argc, argv);
314c2aa98e2SPeter Wemm
31506f25ae9SGregory Neil Shapiro
31640266059SGregory Neil Shapiro SyslogPrefixLen = PIDLEN + (MAXQFNAME - 3) + SL_FUDGE + SLDLL;
317c2aa98e2SPeter Wemm
318c2aa98e2SPeter Wemm /* reset status from syserr() calls for missing file descriptors */
319c2aa98e2SPeter Wemm Errors = 0;
320c2aa98e2SPeter Wemm ExitStat = EX_OK;
321c2aa98e2SPeter Wemm
32206f25ae9SGregory Neil Shapiro SubmitMode = SUBMIT_UNKNOWN;
323e3793f76SGregory Neil Shapiro #if _FFR_LOCAL_DAEMON
324e3793f76SGregory Neil Shapiro LocalDaemon = false;
3256f9c8e5bSGregory Neil Shapiro # if NETINET6
3266f9c8e5bSGregory Neil Shapiro V6LoopbackAddrFound = false;
3275b0945b5SGregory Neil Shapiro # endif
3285b0945b5SGregory Neil Shapiro #endif
329c2aa98e2SPeter Wemm checkfd012("after openlog");
33006f25ae9SGregory Neil Shapiro
331d0cef73dSGregory Neil Shapiro tTsetup(tTdvect, sizeof(tTdvect), "0-99.1,*_trace_*.1");
332c2aa98e2SPeter Wemm
333c2aa98e2SPeter Wemm #ifdef NGROUPS_MAX
334c2aa98e2SPeter Wemm /* save initial group set for future checks */
335c2aa98e2SPeter Wemm i = getgroups(NGROUPS_MAX, InitialGidSet);
33640266059SGregory Neil Shapiro if (i <= 0)
33740266059SGregory Neil Shapiro {
338c2aa98e2SPeter Wemm InitialGidSet[0] = (GID_T) -1;
33940266059SGregory Neil Shapiro i = 0;
34040266059SGregory Neil Shapiro }
341c2aa98e2SPeter Wemm while (i < NGROUPS_MAX)
342c2aa98e2SPeter Wemm InitialGidSet[i++] = InitialGidSet[0];
34306f25ae9SGregory Neil Shapiro #endif /* NGROUPS_MAX */
344c2aa98e2SPeter Wemm
345c2aa98e2SPeter Wemm /* drop group id privileges (RunAsUser not yet set) */
34640266059SGregory Neil Shapiro dp = drop_privileges(false);
34706f25ae9SGregory Neil Shapiro setstat(dp);
348c2aa98e2SPeter Wemm
349c2aa98e2SPeter Wemm #ifdef SIGUSR1
3508774250cSGregory Neil Shapiro /* Only allow root (or non-set-*-ID binaries) to use SIGUSR1 */
351605302a5SGregory Neil Shapiro if (!extraprivs)
3528774250cSGregory Neil Shapiro {
353c2aa98e2SPeter Wemm /* arrange to dump state on user-1 signal */
35440266059SGregory Neil Shapiro (void) sm_signal(SIGUSR1, sigusr1);
3558774250cSGregory Neil Shapiro }
356605302a5SGregory Neil Shapiro else
357605302a5SGregory Neil Shapiro {
358605302a5SGregory Neil Shapiro /* ignore user-1 signal */
359605302a5SGregory Neil Shapiro (void) sm_signal(SIGUSR1, SIG_IGN);
360605302a5SGregory Neil Shapiro }
36106f25ae9SGregory Neil Shapiro #endif /* SIGUSR1 */
362c2aa98e2SPeter Wemm
363c2aa98e2SPeter Wemm /* initialize for setproctitle */
364c2aa98e2SPeter Wemm initsetproctitle(argc, argv, envp);
365c2aa98e2SPeter Wemm
366c2aa98e2SPeter Wemm /* Handle any non-getoptable constructions. */
367c2aa98e2SPeter Wemm obsolete(argv);
368c2aa98e2SPeter Wemm
369c2aa98e2SPeter Wemm /*
370c2aa98e2SPeter Wemm ** Do a quick prescan of the argument list.
371c2aa98e2SPeter Wemm */
372c2aa98e2SPeter Wemm
37306f25ae9SGregory Neil Shapiro
37440266059SGregory Neil Shapiro /* find initial opMode */
37540266059SGregory Neil Shapiro OpMode = MD_DELIVER;
37640266059SGregory Neil Shapiro av = argv;
37740266059SGregory Neil Shapiro p = strrchr(*av, '/');
37840266059SGregory Neil Shapiro if (p++ == NULL)
37940266059SGregory Neil Shapiro p = *av;
38040266059SGregory Neil Shapiro if (strcmp(p, "newaliases") == 0)
38140266059SGregory Neil Shapiro OpMode = MD_INITALIAS;
38240266059SGregory Neil Shapiro else if (strcmp(p, "mailq") == 0)
38340266059SGregory Neil Shapiro OpMode = MD_PRINT;
38440266059SGregory Neil Shapiro else if (strcmp(p, "smtpd") == 0)
38540266059SGregory Neil Shapiro OpMode = MD_DAEMON;
38640266059SGregory Neil Shapiro else if (strcmp(p, "hoststat") == 0)
38740266059SGregory Neil Shapiro OpMode = MD_HOSTSTAT;
38840266059SGregory Neil Shapiro else if (strcmp(p, "purgestat") == 0)
38940266059SGregory Neil Shapiro OpMode = MD_PURGESTAT;
39040266059SGregory Neil Shapiro
391c2aa98e2SPeter Wemm #if defined(__osf__) || defined(_AIX3)
3922fb4f839SGregory Neil Shapiro # define OPTIONS "A:B:b:C:cD:d:e:F:f:Gh:IiL:M:mN:nO:o:p:Q:q:R:r:sTtUV:vX:x"
3932fb4f839SGregory Neil Shapiro #endif
394c2aa98e2SPeter Wemm #if defined(sony_news)
3952fb4f839SGregory Neil Shapiro # define OPTIONS "A:B:b:C:cD:d:E:e:F:f:Gh:IiJ:L:M:mN:nO:o:p:Q:q:R:r:sTtUV:vX:"
3962fb4f839SGregory Neil Shapiro #endif
397c2aa98e2SPeter Wemm #ifndef OPTIONS
3982fb4f839SGregory Neil Shapiro # define OPTIONS "A:B:b:C:cD:d:e:F:f:Gh:IiL:M:mN:nO:o:p:Q:q:R:r:sTtUV:vX:"
3995b0945b5SGregory Neil Shapiro #endif
40040266059SGregory Neil Shapiro
4015ef517c0SGregory Neil Shapiro /* Set to 0 to allow -b; need to check optarg before using it! */
402c2aa98e2SPeter Wemm opterr = 0;
403c2aa98e2SPeter Wemm while ((j = getopt(argc, argv, OPTIONS)) != -1)
404c2aa98e2SPeter Wemm {
405c2aa98e2SPeter Wemm switch (j)
406c2aa98e2SPeter Wemm {
40740266059SGregory Neil Shapiro case 'b': /* operations mode */
408605302a5SGregory Neil Shapiro j = (optarg == NULL) ? ' ' : *optarg;
409605302a5SGregory Neil Shapiro switch (j)
410c2aa98e2SPeter Wemm {
41140266059SGregory Neil Shapiro case MD_DAEMON:
41240266059SGregory Neil Shapiro case MD_FGDAEMON:
41340266059SGregory Neil Shapiro case MD_SMTP:
41440266059SGregory Neil Shapiro case MD_INITALIAS:
41540266059SGregory Neil Shapiro case MD_DELIVER:
41640266059SGregory Neil Shapiro case MD_VERIFY:
41740266059SGregory Neil Shapiro case MD_TEST:
41840266059SGregory Neil Shapiro case MD_PRINT:
41940266059SGregory Neil Shapiro case MD_PRINTNQE:
42040266059SGregory Neil Shapiro case MD_HOSTSTAT:
42140266059SGregory Neil Shapiro case MD_PURGESTAT:
42240266059SGregory Neil Shapiro case MD_ARPAFTP:
4239bd497b8SGregory Neil Shapiro case MD_CHECKCONFIG:
42440266059SGregory Neil Shapiro OpMode = j;
425c2aa98e2SPeter Wemm break;
42640266059SGregory Neil Shapiro
4272fb4f839SGregory Neil Shapiro case MD_SHOWCONFIG:
4282fb4f839SGregory Neil Shapiro showcfopts();
4292fb4f839SGregory Neil Shapiro return EX_OK;
430e3793f76SGregory Neil Shapiro #if _FFR_LOCAL_DAEMON
431e3793f76SGregory Neil Shapiro case MD_LOCAL:
432e3793f76SGregory Neil Shapiro OpMode = MD_DAEMON;
433e3793f76SGregory Neil Shapiro LocalDaemon = true;
434e3793f76SGregory Neil Shapiro break;
435e3793f76SGregory Neil Shapiro #endif /* _FFR_LOCAL_DAEMON */
436e3793f76SGregory Neil Shapiro
43740266059SGregory Neil Shapiro case MD_FREEZE:
43840266059SGregory Neil Shapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
43940266059SGregory Neil Shapiro "Frozen configurations unsupported\n");
44040266059SGregory Neil Shapiro return EX_USAGE;
44140266059SGregory Neil Shapiro
44240266059SGregory Neil Shapiro default:
44340266059SGregory Neil Shapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
44440266059SGregory Neil Shapiro "Invalid operation mode %c\n",
44540266059SGregory Neil Shapiro j);
44640266059SGregory Neil Shapiro return EX_USAGE;
447c2aa98e2SPeter Wemm }
44840266059SGregory Neil Shapiro break;
44940266059SGregory Neil Shapiro
450e92d3f3fSGregory Neil Shapiro case 'D':
451e92d3f3fSGregory Neil Shapiro if (debug)
452e92d3f3fSGregory Neil Shapiro {
453e92d3f3fSGregory Neil Shapiro errno = 0;
454e92d3f3fSGregory Neil Shapiro syserr("-D file must be before -d");
455e92d3f3fSGregory Neil Shapiro ExitStat = EX_USAGE;
456e92d3f3fSGregory Neil Shapiro break;
457e92d3f3fSGregory Neil Shapiro }
458e92d3f3fSGregory Neil Shapiro dp = drop_privileges(true);
459e92d3f3fSGregory Neil Shapiro setstat(dp);
460e92d3f3fSGregory Neil Shapiro smdebug = sm_io_open(SmFtStdio, SM_TIME_DEFAULT,
461e92d3f3fSGregory Neil Shapiro optarg, SM_IO_APPEND, NULL);
462e92d3f3fSGregory Neil Shapiro if (smdebug == NULL)
463e92d3f3fSGregory Neil Shapiro {
464e92d3f3fSGregory Neil Shapiro syserr("cannot open %s", optarg);
465e92d3f3fSGregory Neil Shapiro ExitStat = EX_CANTCREAT;
466e92d3f3fSGregory Neil Shapiro break;
467e92d3f3fSGregory Neil Shapiro }
468e92d3f3fSGregory Neil Shapiro sm_debug_setfile(smdebug);
469e92d3f3fSGregory Neil Shapiro break;
470e92d3f3fSGregory Neil Shapiro
47140266059SGregory Neil Shapiro case 'd':
47240266059SGregory Neil Shapiro debug = true;
473c2aa98e2SPeter Wemm tTflag(optarg);
474e92d3f3fSGregory Neil Shapiro (void) sm_io_setvbuf(sm_debug_file(), SM_TIME_DEFAULT,
47540266059SGregory Neil Shapiro (char *) NULL, SM_IO_NBF,
47640266059SGregory Neil Shapiro SM_IO_BUFSIZ);
477c2aa98e2SPeter Wemm break;
47806f25ae9SGregory Neil Shapiro
47906f25ae9SGregory Neil Shapiro case 'G': /* relay (gateway) submission */
48040266059SGregory Neil Shapiro SubmitMode = SUBMIT_MTA;
48106f25ae9SGregory Neil Shapiro break;
48206f25ae9SGregory Neil Shapiro
48306f25ae9SGregory Neil Shapiro case 'L':
4845ef517c0SGregory Neil Shapiro if (optarg == NULL)
4855ef517c0SGregory Neil Shapiro {
4865ef517c0SGregory Neil Shapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
4875ef517c0SGregory Neil Shapiro "option requires an argument -- '%c'",
4885ef517c0SGregory Neil Shapiro (char) j);
4895ef517c0SGregory Neil Shapiro return EX_USAGE;
4905ef517c0SGregory Neil Shapiro }
491e92d3f3fSGregory Neil Shapiro j = SM_MIN(strlen(optarg), 32) + 1;
4922fb4f839SGregory Neil Shapiro sysloglabel = sm_malloc_tagged_x(j, "sysloglabel", 0, 0);
49340266059SGregory Neil Shapiro (void) sm_strlcpy(sysloglabel, optarg, j);
49440266059SGregory Neil Shapiro SyslogPrefixLen = PIDLEN + (MAXQFNAME - 3) +
49540266059SGregory Neil Shapiro SL_FUDGE + j;
49606f25ae9SGregory Neil Shapiro break;
49706f25ae9SGregory Neil Shapiro
49840266059SGregory Neil Shapiro case 'Q':
49940266059SGregory Neil Shapiro case 'q':
50040266059SGregory Neil Shapiro /* just check if it is there */
50140266059SGregory Neil Shapiro queuerun = true;
50206f25ae9SGregory Neil Shapiro break;
503c2aa98e2SPeter Wemm }
504c2aa98e2SPeter Wemm }
505c2aa98e2SPeter Wemm opterr = 1;
506c2aa98e2SPeter Wemm
50740266059SGregory Neil Shapiro /* Don't leak queue information via debug flags */
50840266059SGregory Neil Shapiro if (extraprivs && queuerun && debug)
50940266059SGregory Neil Shapiro {
51040266059SGregory Neil Shapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
51140266059SGregory Neil Shapiro "WARNING: Can not use -d with -q. Disabling debugging.\n");
512e92d3f3fSGregory Neil Shapiro sm_debug_close();
51340266059SGregory Neil Shapiro sm_debug_setfile(NULL);
514d0cef73dSGregory Neil Shapiro (void) memset(tTdvect, '\0', sizeof(tTdvect));
51540266059SGregory Neil Shapiro }
51640266059SGregory Neil Shapiro
5178774250cSGregory Neil Shapiro #if LOG
51806f25ae9SGregory Neil Shapiro if (sysloglabel != NULL)
51906f25ae9SGregory Neil Shapiro {
5208774250cSGregory Neil Shapiro /* Sanitize the string */
5218774250cSGregory Neil Shapiro for (p = sysloglabel; *p != '\0'; p++)
5228774250cSGregory Neil Shapiro {
5238774250cSGregory Neil Shapiro if (!isascii(*p) || !isprint(*p) || *p == '%')
5248774250cSGregory Neil Shapiro *p = '*';
5258774250cSGregory Neil Shapiro }
52606f25ae9SGregory Neil Shapiro closelog();
52706f25ae9SGregory Neil Shapiro # ifdef LOG_MAIL
52806f25ae9SGregory Neil Shapiro openlog(sysloglabel, LOG_PID, LOG_MAIL);
5295b0945b5SGregory Neil Shapiro # else
53006f25ae9SGregory Neil Shapiro openlog(sysloglabel, LOG_PID);
5315b0945b5SGregory Neil Shapiro # endif
53206f25ae9SGregory Neil Shapiro }
5338774250cSGregory Neil Shapiro #endif /* LOG */
53406f25ae9SGregory Neil Shapiro
535c2aa98e2SPeter Wemm /* set up the blank envelope */
536c2aa98e2SPeter Wemm BlankEnvelope.e_puthdr = putheader;
537c2aa98e2SPeter Wemm BlankEnvelope.e_putbody = putbody;
538c2aa98e2SPeter Wemm BlankEnvelope.e_xfp = NULL;
539c2aa98e2SPeter Wemm STRUCTCOPY(NullAddress, BlankEnvelope.e_from);
540c2aa98e2SPeter Wemm CurEnv = &BlankEnvelope;
541c2aa98e2SPeter Wemm STRUCTCOPY(NullAddress, MainEnvelope.e_from);
542c2aa98e2SPeter Wemm
543c2aa98e2SPeter Wemm /*
544c2aa98e2SPeter Wemm ** Set default values for variables.
545c2aa98e2SPeter Wemm ** These cannot be in initialized data space.
546c2aa98e2SPeter Wemm */
547c2aa98e2SPeter Wemm
548c2aa98e2SPeter Wemm setdefaults(&BlankEnvelope);
54940266059SGregory Neil Shapiro initmacros(&BlankEnvelope);
550c2aa98e2SPeter Wemm
55140266059SGregory Neil Shapiro /* reset macro */
55240266059SGregory Neil Shapiro set_op_mode(OpMode);
553af9557fdSGregory Neil Shapiro if (OpMode == MD_DAEMON)
554af9557fdSGregory Neil Shapiro DaemonPid = CurrentPid; /* needed for finis() to work */
555c2aa98e2SPeter Wemm
556c2aa98e2SPeter Wemm pw = sm_getpwuid(RealUid);
557c2aa98e2SPeter Wemm if (pw != NULL)
558d0cef73dSGregory Neil Shapiro (void) sm_strlcpy(rnamebuf, pw->pw_name, sizeof(rnamebuf));
559c2aa98e2SPeter Wemm else
560d0cef73dSGregory Neil Shapiro (void) sm_snprintf(rnamebuf, sizeof(rnamebuf), "Unknown UID %d",
56106f25ae9SGregory Neil Shapiro (int) RealUid);
56206f25ae9SGregory Neil Shapiro
563c2aa98e2SPeter Wemm RealUserName = rnamebuf;
564c2aa98e2SPeter Wemm
565c2aa98e2SPeter Wemm if (tTd(0, 101))
566c2aa98e2SPeter Wemm {
56740266059SGregory Neil Shapiro sm_dprintf("Version %s\n", Version);
56840266059SGregory Neil Shapiro finis(false, true, EX_OK);
56940266059SGregory Neil Shapiro /* NOTREACHED */
570c2aa98e2SPeter Wemm }
571c2aa98e2SPeter Wemm
572c2aa98e2SPeter Wemm /*
57340266059SGregory Neil Shapiro ** if running non-set-user-ID binary as non-root, pretend
574c2aa98e2SPeter Wemm ** we are the RunAsUid
575c2aa98e2SPeter Wemm */
5768774250cSGregory Neil Shapiro
577c2aa98e2SPeter Wemm if (RealUid != 0 && geteuid() == RealUid)
578c2aa98e2SPeter Wemm {
579c2aa98e2SPeter Wemm if (tTd(47, 1))
58040266059SGregory Neil Shapiro sm_dprintf("Non-set-user-ID binary: RunAsUid = RealUid = %d\n",
581c2aa98e2SPeter Wemm (int) RealUid);
582c2aa98e2SPeter Wemm RunAsUid = RealUid;
583c2aa98e2SPeter Wemm }
584c2aa98e2SPeter Wemm else if (geteuid() != 0)
585c2aa98e2SPeter Wemm RunAsUid = geteuid();
586c2aa98e2SPeter Wemm
58740266059SGregory Neil Shapiro EffGid = getegid();
58840266059SGregory Neil Shapiro if (RealUid != 0 && EffGid == RealGid)
589c2aa98e2SPeter Wemm RunAsGid = RealGid;
590c2aa98e2SPeter Wemm
591c2aa98e2SPeter Wemm if (tTd(47, 5))
592c2aa98e2SPeter Wemm {
59340266059SGregory Neil Shapiro sm_dprintf("main: e/ruid = %d/%d e/rgid = %d/%d\n",
59406f25ae9SGregory Neil Shapiro (int) geteuid(), (int) getuid(),
59506f25ae9SGregory Neil Shapiro (int) getegid(), (int) getgid());
59640266059SGregory Neil Shapiro sm_dprintf("main: RunAsUser = %d:%d\n",
59706f25ae9SGregory Neil Shapiro (int) RunAsUid, (int) RunAsGid);
598c2aa98e2SPeter Wemm }
599c2aa98e2SPeter Wemm
600c2aa98e2SPeter Wemm /* save command line arguments */
60106f25ae9SGregory Neil Shapiro j = 0;
602c2aa98e2SPeter Wemm for (av = argv; *av != NULL; )
60306f25ae9SGregory Neil Shapiro j += strlen(*av++) + 1;
6042fb4f839SGregory Neil Shapiro SaveArgv = (char **) sm_malloc_tagged_x(sizeof(char *) * (argc + 1),
6052fb4f839SGregory Neil Shapiro "argv", 0, 0);
6062fb4f839SGregory Neil Shapiro CommandLineArgs = sm_malloc_tagged_x(j, "cliargs", 0, 0);
607c2aa98e2SPeter Wemm p = CommandLineArgs;
608c2aa98e2SPeter Wemm for (av = argv, i = 0; *av != NULL; )
609c2aa98e2SPeter Wemm {
61006f25ae9SGregory Neil Shapiro int h;
61106f25ae9SGregory Neil Shapiro
612c2aa98e2SPeter Wemm SaveArgv[i++] = newstr(*av);
613c2aa98e2SPeter Wemm if (av != argv)
614c2aa98e2SPeter Wemm *p++ = ' ';
61540266059SGregory Neil Shapiro (void) sm_strlcpy(p, *av++, j);
61606f25ae9SGregory Neil Shapiro h = strlen(p);
61706f25ae9SGregory Neil Shapiro p += h;
61806f25ae9SGregory Neil Shapiro j -= h + 1;
619c2aa98e2SPeter Wemm }
620c2aa98e2SPeter Wemm SaveArgv[i] = NULL;
621c2aa98e2SPeter Wemm
622c2aa98e2SPeter Wemm if (tTd(0, 1))
623c2aa98e2SPeter Wemm {
624c2aa98e2SPeter Wemm extern char *CompileOptions[];
625c2aa98e2SPeter Wemm
62640266059SGregory Neil Shapiro sm_dprintf("Version %s\n Compiled with:", Version);
62740266059SGregory Neil Shapiro sm_printoptions(CompileOptions);
628c2aa98e2SPeter Wemm }
629c2aa98e2SPeter Wemm if (tTd(0, 10))
630c2aa98e2SPeter Wemm {
631c2aa98e2SPeter Wemm extern char *OsCompileOptions[];
632c2aa98e2SPeter Wemm
63340266059SGregory Neil Shapiro sm_dprintf(" OS Defines:");
63440266059SGregory Neil Shapiro sm_printoptions(OsCompileOptions);
635c2aa98e2SPeter Wemm #ifdef _PATH_UNIX
63640266059SGregory Neil Shapiro sm_dprintf("Kernel symbols:\t%s\n", _PATH_UNIX);
6375b0945b5SGregory Neil Shapiro #endif
63840266059SGregory Neil Shapiro
63940266059SGregory Neil Shapiro sm_dprintf(" Conf file:\t%s (default for MSP)\n",
64040266059SGregory Neil Shapiro getcfname(OpMode, SubmitMode, SM_GET_SUBMIT_CF,
64140266059SGregory Neil Shapiro conffile));
64240266059SGregory Neil Shapiro sm_dprintf(" Conf file:\t%s (default for MTA)\n",
64340266059SGregory Neil Shapiro getcfname(OpMode, SubmitMode, SM_GET_SENDMAIL_CF,
64440266059SGregory Neil Shapiro conffile));
64540266059SGregory Neil Shapiro sm_dprintf(" Pid file:\t%s (default)\n", PidFile);
646c2aa98e2SPeter Wemm }
647c2aa98e2SPeter Wemm
64840266059SGregory Neil Shapiro if (tTd(0, 12))
64940266059SGregory Neil Shapiro {
65040266059SGregory Neil Shapiro extern char *SmCompileOptions[];
65140266059SGregory Neil Shapiro
65240266059SGregory Neil Shapiro sm_dprintf(" libsm Defines:");
65340266059SGregory Neil Shapiro sm_printoptions(SmCompileOptions);
65440266059SGregory Neil Shapiro }
65540266059SGregory Neil Shapiro
65640266059SGregory Neil Shapiro if (tTd(0, 13))
65740266059SGregory Neil Shapiro {
65840266059SGregory Neil Shapiro extern char *FFRCompileOptions[];
65940266059SGregory Neil Shapiro
66040266059SGregory Neil Shapiro sm_dprintf(" FFR Defines:");
66140266059SGregory Neil Shapiro sm_printoptions(FFRCompileOptions);
66240266059SGregory Neil Shapiro }
66340266059SGregory Neil Shapiro
664da7d7b9cSGregory Neil Shapiro #if STARTTLS
665da7d7b9cSGregory Neil Shapiro if (tTd(0, 14))
666da7d7b9cSGregory Neil Shapiro {
667da7d7b9cSGregory Neil Shapiro /* exit(EX_CONFIG) if different? */
668da7d7b9cSGregory Neil Shapiro sm_dprintf(" OpenSSL: compiled 0x%08x\n",
669da7d7b9cSGregory Neil Shapiro (uint) OPENSSL_VERSION_NUMBER);
670da7d7b9cSGregory Neil Shapiro sm_dprintf(" OpenSSL: linked 0x%08x\n",
6715b0945b5SGregory Neil Shapiro (uint) TLS_version_num());
672da7d7b9cSGregory Neil Shapiro }
673d39bd2c1SGregory Neil Shapiro # if defined(LIBRESSL_VERSION_NUMBER)
674d39bd2c1SGregory Neil Shapiro if (tTd(0, 15))
675d39bd2c1SGregory Neil Shapiro sm_dprintf(" LibreSSL: compiled 0x%08x\n",
676d39bd2c1SGregory Neil Shapiro (uint) LIBRESSL_VERSION_NUMBER);
677d39bd2c1SGregory Neil Shapiro # endif
678da7d7b9cSGregory Neil Shapiro #endif /* STARTTLS */
679da7d7b9cSGregory Neil Shapiro
680c2aa98e2SPeter Wemm /* clear sendmail's environment */
681c2aa98e2SPeter Wemm ExternalEnviron = environ;
682c2aa98e2SPeter Wemm emptyenviron[0] = NULL;
683c2aa98e2SPeter Wemm environ = emptyenviron;
684c2aa98e2SPeter Wemm
685c2aa98e2SPeter Wemm /*
686c2aa98e2SPeter Wemm ** restore any original TZ setting until TimeZoneSpec has been
687c2aa98e2SPeter Wemm ** determined - or early log messages may get bogus time stamps
688c2aa98e2SPeter Wemm */
68940266059SGregory Neil Shapiro
690c2aa98e2SPeter Wemm if ((p = getextenv("TZ")) != NULL)
691c2aa98e2SPeter Wemm {
692c2aa98e2SPeter Wemm char *tz;
693c2aa98e2SPeter Wemm int tzlen;
694c2aa98e2SPeter Wemm
69540266059SGregory Neil Shapiro /* XXX check for reasonable length? */
696c2aa98e2SPeter Wemm tzlen = strlen(p) + 4;
697c2aa98e2SPeter Wemm tz = xalloc(tzlen);
69840266059SGregory Neil Shapiro (void) sm_strlcpyn(tz, tzlen, 2, "TZ=", p);
69940266059SGregory Neil Shapiro
70040266059SGregory Neil Shapiro /* XXX check return code? */
70106f25ae9SGregory Neil Shapiro (void) putenv(tz);
702c2aa98e2SPeter Wemm }
703c2aa98e2SPeter Wemm
704c2aa98e2SPeter Wemm /* prime the child environment */
7054e4196cbSGregory Neil Shapiro sm_setuserenv("AGENT", "sendmail");
7068774250cSGregory Neil Shapiro
70740266059SGregory Neil Shapiro (void) sm_signal(SIGPIPE, SIG_IGN);
708c2aa98e2SPeter Wemm OldUmask = umask(022);
709c2aa98e2SPeter Wemm FullName = getextenv("NAME");
7106a2f2ff3SGregory Neil Shapiro if (FullName != NULL)
7116a2f2ff3SGregory Neil Shapiro FullName = newstr(FullName);
712c2aa98e2SPeter Wemm
713c2aa98e2SPeter Wemm /*
714c2aa98e2SPeter Wemm ** Initialize name server if it is going to be used.
715c2aa98e2SPeter Wemm */
716c2aa98e2SPeter Wemm
717c2aa98e2SPeter Wemm #if NAMED_BIND
718c2aa98e2SPeter Wemm if (!bitset(RES_INIT, _res.options))
71906f25ae9SGregory Neil Shapiro (void) res_init();
720c2aa98e2SPeter Wemm if (tTd(8, 8))
721c2aa98e2SPeter Wemm _res.options |= RES_DEBUG;
722c2aa98e2SPeter Wemm else
723c2aa98e2SPeter Wemm _res.options &= ~RES_DEBUG;
724c2aa98e2SPeter Wemm # ifdef RES_NOALIASES
725c2aa98e2SPeter Wemm _res.options |= RES_NOALIASES;
7265b0945b5SGregory Neil Shapiro # endif
72706f25ae9SGregory Neil Shapiro TimeOuts.res_retry[RES_TO_DEFAULT] = _res.retry;
72806f25ae9SGregory Neil Shapiro TimeOuts.res_retry[RES_TO_FIRST] = _res.retry;
72906f25ae9SGregory Neil Shapiro TimeOuts.res_retry[RES_TO_NORMAL] = _res.retry;
73006f25ae9SGregory Neil Shapiro TimeOuts.res_retrans[RES_TO_DEFAULT] = _res.retrans;
73106f25ae9SGregory Neil Shapiro TimeOuts.res_retrans[RES_TO_FIRST] = _res.retrans;
73206f25ae9SGregory Neil Shapiro TimeOuts.res_retrans[RES_TO_NORMAL] = _res.retrans;
73306f25ae9SGregory Neil Shapiro #endif /* NAMED_BIND */
734c2aa98e2SPeter Wemm
735c2aa98e2SPeter Wemm errno = 0;
7362fb4f839SGregory Neil Shapiro fromaddr = NULL;
737c2aa98e2SPeter Wemm
738c2aa98e2SPeter Wemm /* initialize some macros, etc. */
73940266059SGregory Neil Shapiro init_vendor_macros(&BlankEnvelope);
740c2aa98e2SPeter Wemm
741c2aa98e2SPeter Wemm /* version */
74240266059SGregory Neil Shapiro macdefine(&BlankEnvelope.e_macro, A_PERM, 'v', Version);
743c2aa98e2SPeter Wemm
744c2aa98e2SPeter Wemm /* hostname */
745d0cef73dSGregory Neil Shapiro hp = myhostname(jbuf, sizeof(jbuf));
746c2aa98e2SPeter Wemm if (jbuf[0] != '\0')
747c2aa98e2SPeter Wemm {
748c2aa98e2SPeter Wemm struct utsname utsname;
749c2aa98e2SPeter Wemm
750c2aa98e2SPeter Wemm if (tTd(0, 4))
75140266059SGregory Neil Shapiro sm_dprintf("Canonical name: %s\n", jbuf);
7522fb4f839SGregory Neil Shapiro #if USE_EAI
7532fb4f839SGregory Neil Shapiro if (!addr_is_ascii(jbuf))
7542fb4f839SGregory Neil Shapiro {
7552fb4f839SGregory Neil Shapiro usrerr("hostname %s must be ASCII", jbuf);
7562fb4f839SGregory Neil Shapiro finis(false, true, EX_CONFIG);
7572fb4f839SGregory Neil Shapiro /* NOTREACHED */
7582fb4f839SGregory Neil Shapiro }
7592fb4f839SGregory Neil Shapiro #endif
76040266059SGregory Neil Shapiro macdefine(&BlankEnvelope.e_macro, A_TEMP, 'w', jbuf);
76140266059SGregory Neil Shapiro macdefine(&BlankEnvelope.e_macro, A_TEMP, 'j', jbuf);
762c2aa98e2SPeter Wemm setclass('w', jbuf);
763c2aa98e2SPeter Wemm
764c2aa98e2SPeter Wemm p = strchr(jbuf, '.');
765e92d3f3fSGregory Neil Shapiro if (p != NULL && p[1] != '\0')
766e92d3f3fSGregory Neil Shapiro macdefine(&BlankEnvelope.e_macro, A_TEMP, 'm', &p[1]);
767c2aa98e2SPeter Wemm
768c2aa98e2SPeter Wemm if (uname(&utsname) >= 0)
769c2aa98e2SPeter Wemm p = utsname.nodename;
770c2aa98e2SPeter Wemm else
771c2aa98e2SPeter Wemm {
772c2aa98e2SPeter Wemm if (tTd(0, 22))
77340266059SGregory Neil Shapiro sm_dprintf("uname failed (%s)\n",
77440266059SGregory Neil Shapiro sm_errstring(errno));
775c2aa98e2SPeter Wemm p = jbuf;
7762fb4f839SGregory Neil Shapiro p = makelower_a(&p, NULL);
777c2aa98e2SPeter Wemm }
778c2aa98e2SPeter Wemm if (tTd(0, 4))
77940266059SGregory Neil Shapiro sm_dprintf(" UUCP nodename: %s\n", p);
78040266059SGregory Neil Shapiro macdefine(&BlankEnvelope.e_macro, A_TEMP, 'k', p);
781c2aa98e2SPeter Wemm setclass('k', p);
782c2aa98e2SPeter Wemm setclass('w', p);
7832fb4f839SGregory Neil Shapiro if (p != utsname.nodename && p != jbuf)
7842fb4f839SGregory Neil Shapiro SM_FREE(p);
785c2aa98e2SPeter Wemm }
786c2aa98e2SPeter Wemm if (hp != NULL)
787c2aa98e2SPeter Wemm {
788c2aa98e2SPeter Wemm for (av = hp->h_aliases; av != NULL && *av != NULL; av++)
789c2aa98e2SPeter Wemm {
790c2aa98e2SPeter Wemm if (tTd(0, 4))
79140266059SGregory Neil Shapiro sm_dprintf("\ta.k.a.: %s\n", *av);
792c2aa98e2SPeter Wemm setclass('w', *av);
793c2aa98e2SPeter Wemm }
79406f25ae9SGregory Neil Shapiro #if NETINET || NETINET6
79540266059SGregory Neil Shapiro for (i = 0; i >= 0 && hp->h_addr_list[i] != NULL; i++)
796c2aa98e2SPeter Wemm {
79706f25ae9SGregory Neil Shapiro # if NETINET6
79806f25ae9SGregory Neil Shapiro char *addr;
79906f25ae9SGregory Neil Shapiro char buf6[INET6_ADDRSTRLEN];
80006f25ae9SGregory Neil Shapiro struct in6_addr ia6;
80106f25ae9SGregory Neil Shapiro # endif /* NETINET6 */
80206f25ae9SGregory Neil Shapiro # if NETINET
80306f25ae9SGregory Neil Shapiro struct in_addr ia;
8045b0945b5SGregory Neil Shapiro # endif
805c2aa98e2SPeter Wemm char ipbuf[103];
806c2aa98e2SPeter Wemm
80706f25ae9SGregory Neil Shapiro ipbuf[0] = '\0';
80806f25ae9SGregory Neil Shapiro switch (hp->h_addrtype)
80906f25ae9SGregory Neil Shapiro {
81006f25ae9SGregory Neil Shapiro # if NETINET
81106f25ae9SGregory Neil Shapiro case AF_INET:
81206f25ae9SGregory Neil Shapiro if (hp->h_length != INADDRSZ)
81306f25ae9SGregory Neil Shapiro break;
81406f25ae9SGregory Neil Shapiro
81506f25ae9SGregory Neil Shapiro memmove(&ia, hp->h_addr_list[i], INADDRSZ);
816d0cef73dSGregory Neil Shapiro (void) sm_snprintf(ipbuf, sizeof(ipbuf),
81706f25ae9SGregory Neil Shapiro "[%.100s]", inet_ntoa(ia));
81806f25ae9SGregory Neil Shapiro break;
81906f25ae9SGregory Neil Shapiro # endif /* NETINET */
82006f25ae9SGregory Neil Shapiro
82106f25ae9SGregory Neil Shapiro # if NETINET6
82206f25ae9SGregory Neil Shapiro case AF_INET6:
82306f25ae9SGregory Neil Shapiro if (hp->h_length != IN6ADDRSZ)
82406f25ae9SGregory Neil Shapiro break;
82506f25ae9SGregory Neil Shapiro
82606f25ae9SGregory Neil Shapiro memmove(&ia6, hp->h_addr_list[i], IN6ADDRSZ);
827d0cef73dSGregory Neil Shapiro addr = anynet_ntop(&ia6, buf6, sizeof(buf6));
82806f25ae9SGregory Neil Shapiro if (addr != NULL)
829d0cef73dSGregory Neil Shapiro (void) sm_snprintf(ipbuf, sizeof(ipbuf),
83006f25ae9SGregory Neil Shapiro "[%.100s]", addr);
83106f25ae9SGregory Neil Shapiro break;
83206f25ae9SGregory Neil Shapiro # endif /* NETINET6 */
83306f25ae9SGregory Neil Shapiro }
83406f25ae9SGregory Neil Shapiro if (ipbuf[0] == '\0')
83506f25ae9SGregory Neil Shapiro break;
83606f25ae9SGregory Neil Shapiro
837c2aa98e2SPeter Wemm if (tTd(0, 4))
83840266059SGregory Neil Shapiro sm_dprintf("\ta.k.a.: %s\n", ipbuf);
839c2aa98e2SPeter Wemm setclass('w', ipbuf);
840c2aa98e2SPeter Wemm }
84106f25ae9SGregory Neil Shapiro #endif /* NETINET || NETINET6 */
84240266059SGregory Neil Shapiro #if NETINET6
843193538b7SGregory Neil Shapiro freehostent(hp);
844193538b7SGregory Neil Shapiro hp = NULL;
8455b0945b5SGregory Neil Shapiro #endif
846c2aa98e2SPeter Wemm }
847c2aa98e2SPeter Wemm
848c2aa98e2SPeter Wemm /* current time */
84940266059SGregory Neil Shapiro macdefine(&BlankEnvelope.e_macro, A_TEMP, 'b', arpadate((char *) NULL));
85040266059SGregory Neil Shapiro
85106f25ae9SGregory Neil Shapiro /* current load average */
85240266059SGregory Neil Shapiro sm_getla();
853c2aa98e2SPeter Wemm
854c2aa98e2SPeter Wemm QueueLimitRecipient = (QUEUE_CHAR *) NULL;
855c2aa98e2SPeter Wemm QueueLimitSender = (QUEUE_CHAR *) NULL;
856c2aa98e2SPeter Wemm QueueLimitId = (QUEUE_CHAR *) NULL;
85740266059SGregory Neil Shapiro QueueLimitQuarantine = (QUEUE_CHAR *) NULL;
858c2aa98e2SPeter Wemm
859c2aa98e2SPeter Wemm /*
860c2aa98e2SPeter Wemm ** Crack argv.
861c2aa98e2SPeter Wemm */
862c2aa98e2SPeter Wemm
863c2aa98e2SPeter Wemm optind = 1;
864c2aa98e2SPeter Wemm while ((j = getopt(argc, argv, OPTIONS)) != -1)
865c2aa98e2SPeter Wemm {
866c2aa98e2SPeter Wemm switch (j)
867c2aa98e2SPeter Wemm {
868c2aa98e2SPeter Wemm case 'b': /* operations mode */
86940266059SGregory Neil Shapiro /* already done */
870c2aa98e2SPeter Wemm break;
871c2aa98e2SPeter Wemm
87240266059SGregory Neil Shapiro case 'A': /* use Alternate sendmail/submit.cf */
87340266059SGregory Neil Shapiro cftype = optarg[0] == 'c' ? SM_GET_SUBMIT_CF
87440266059SGregory Neil Shapiro : SM_GET_SENDMAIL_CF;
875c2aa98e2SPeter Wemm break;
876c2aa98e2SPeter Wemm
877c2aa98e2SPeter Wemm case 'B': /* body type */
87840266059SGregory Neil Shapiro CHECK_AGAINST_OPMODE(j);
87940266059SGregory Neil Shapiro BlankEnvelope.e_bodytype = newstr(optarg);
880c2aa98e2SPeter Wemm break;
881c2aa98e2SPeter Wemm
882c2aa98e2SPeter Wemm case 'C': /* select configuration file (already done) */
883c2aa98e2SPeter Wemm if (RealUid != 0)
88440266059SGregory Neil Shapiro warn_C_flag = true;
88540266059SGregory Neil Shapiro conffile = newstr(optarg);
88640266059SGregory Neil Shapiro dp = drop_privileges(true);
88706f25ae9SGregory Neil Shapiro setstat(dp);
88840266059SGregory Neil Shapiro safecf = false;
889c2aa98e2SPeter Wemm break;
890c2aa98e2SPeter Wemm
891e92d3f3fSGregory Neil Shapiro case 'D':
89240266059SGregory Neil Shapiro case 'd': /* debugging */
89340266059SGregory Neil Shapiro /* already done */
894c2aa98e2SPeter Wemm break;
895c2aa98e2SPeter Wemm
8962fb4f839SGregory Neil Shapiro case 'f': /* fromaddr address */
897c2aa98e2SPeter Wemm case 'r': /* obsolete -f flag */
89840266059SGregory Neil Shapiro CHECK_AGAINST_OPMODE(j);
8992fb4f839SGregory Neil Shapiro if (fromaddr != NULL)
900c2aa98e2SPeter Wemm {
901c2aa98e2SPeter Wemm usrerr("More than one \"from\" person");
902c2aa98e2SPeter Wemm ExitStat = EX_USAGE;
903c2aa98e2SPeter Wemm break;
904c2aa98e2SPeter Wemm }
90513bd1963SGregory Neil Shapiro if (optarg[0] == '\0')
9062fb4f839SGregory Neil Shapiro fromaddr = newstr("<>");
90713bd1963SGregory Neil Shapiro else
9082fb4f839SGregory Neil Shapiro fromaddr = newstr(denlstring(optarg, true, true));
9092fb4f839SGregory Neil Shapiro if (strcmp(RealUserName, fromaddr) != 0)
910c2aa98e2SPeter Wemm warn_f_flag = j;
911c2aa98e2SPeter Wemm break;
912c2aa98e2SPeter Wemm
913c2aa98e2SPeter Wemm case 'F': /* set full name */
91440266059SGregory Neil Shapiro CHECK_AGAINST_OPMODE(j);
915c2aa98e2SPeter Wemm FullName = newstr(optarg);
916c2aa98e2SPeter Wemm break;
917c2aa98e2SPeter Wemm
91806f25ae9SGregory Neil Shapiro case 'G': /* relay (gateway) submission */
91906f25ae9SGregory Neil Shapiro /* already set */
92040266059SGregory Neil Shapiro CHECK_AGAINST_OPMODE(j);
92106f25ae9SGregory Neil Shapiro break;
92206f25ae9SGregory Neil Shapiro
923c2aa98e2SPeter Wemm case 'h': /* hop count */
92440266059SGregory Neil Shapiro CHECK_AGAINST_OPMODE(j);
92540266059SGregory Neil Shapiro BlankEnvelope.e_hopcount = (short) strtol(optarg, &ep,
92640266059SGregory Neil Shapiro 10);
927d0cef73dSGregory Neil Shapiro (void) sm_snprintf(buf, sizeof(buf), "%d",
92840266059SGregory Neil Shapiro BlankEnvelope.e_hopcount);
92940266059SGregory Neil Shapiro macdefine(&BlankEnvelope.e_macro, A_TEMP, 'c', buf);
93040266059SGregory Neil Shapiro
931c2aa98e2SPeter Wemm if (*ep)
932c2aa98e2SPeter Wemm {
933c2aa98e2SPeter Wemm usrerr("Bad hop count (%s)", optarg);
934c2aa98e2SPeter Wemm ExitStat = EX_USAGE;
935c2aa98e2SPeter Wemm }
936c2aa98e2SPeter Wemm break;
937c2aa98e2SPeter Wemm
93806f25ae9SGregory Neil Shapiro case 'L': /* program label */
93906f25ae9SGregory Neil Shapiro /* already set */
94006f25ae9SGregory Neil Shapiro break;
94106f25ae9SGregory Neil Shapiro
942c2aa98e2SPeter Wemm case 'n': /* don't alias */
94340266059SGregory Neil Shapiro CHECK_AGAINST_OPMODE(j);
94440266059SGregory Neil Shapiro NoAlias = true;
945c2aa98e2SPeter Wemm break;
946c2aa98e2SPeter Wemm
947c2aa98e2SPeter Wemm case 'N': /* delivery status notifications */
94840266059SGregory Neil Shapiro CHECK_AGAINST_OPMODE(j);
949c2aa98e2SPeter Wemm DefaultNotify |= QHASNOTIFY;
95040266059SGregory Neil Shapiro macdefine(&BlankEnvelope.e_macro, A_TEMP,
95140266059SGregory Neil Shapiro macid("{dsn_notify}"), optarg);
9522fb4f839SGregory Neil Shapiro if (SM_STRCASEEQ(optarg, "never"))
953c2aa98e2SPeter Wemm break;
954c2aa98e2SPeter Wemm for (p = optarg; p != NULL; optarg = p)
955c2aa98e2SPeter Wemm {
956c2aa98e2SPeter Wemm p = strchr(p, ',');
957c2aa98e2SPeter Wemm if (p != NULL)
958c2aa98e2SPeter Wemm *p++ = '\0';
9592fb4f839SGregory Neil Shapiro if (SM_STRCASEEQ(optarg, "success"))
960c2aa98e2SPeter Wemm DefaultNotify |= QPINGONSUCCESS;
9612fb4f839SGregory Neil Shapiro else if (SM_STRCASEEQ(optarg, "failure"))
962c2aa98e2SPeter Wemm DefaultNotify |= QPINGONFAILURE;
9632fb4f839SGregory Neil Shapiro else if (SM_STRCASEEQ(optarg, "delay"))
964c2aa98e2SPeter Wemm DefaultNotify |= QPINGONDELAY;
965c2aa98e2SPeter Wemm else
966c2aa98e2SPeter Wemm {
967c2aa98e2SPeter Wemm usrerr("Invalid -N argument");
968c2aa98e2SPeter Wemm ExitStat = EX_USAGE;
969c2aa98e2SPeter Wemm }
970c2aa98e2SPeter Wemm }
971c2aa98e2SPeter Wemm break;
972c2aa98e2SPeter Wemm
973c2aa98e2SPeter Wemm case 'o': /* set option */
97440266059SGregory Neil Shapiro setoption(*optarg, optarg + 1, false, true,
97540266059SGregory Neil Shapiro &BlankEnvelope);
976c2aa98e2SPeter Wemm break;
977c2aa98e2SPeter Wemm
978c2aa98e2SPeter Wemm case 'O': /* set option (long form) */
97940266059SGregory Neil Shapiro setoption(' ', optarg, false, true, &BlankEnvelope);
980c2aa98e2SPeter Wemm break;
981c2aa98e2SPeter Wemm
982c2aa98e2SPeter Wemm case 'p': /* set protocol */
98340266059SGregory Neil Shapiro CHECK_AGAINST_OPMODE(j);
984c2aa98e2SPeter Wemm p = strchr(optarg, ':');
985c2aa98e2SPeter Wemm if (p != NULL)
986c2aa98e2SPeter Wemm {
987c2aa98e2SPeter Wemm *p++ = '\0';
988c2aa98e2SPeter Wemm if (*p != '\0')
989c2aa98e2SPeter Wemm {
990a7ec597cSGregory Neil Shapiro i = strlen(p) + 1;
991a7ec597cSGregory Neil Shapiro ep = sm_malloc_x(i);
992a7ec597cSGregory Neil Shapiro cleanstrcpy(ep, p, i);
99340266059SGregory Neil Shapiro macdefine(&BlankEnvelope.e_macro,
99440266059SGregory Neil Shapiro A_HEAP, 's', ep);
995c2aa98e2SPeter Wemm }
996c2aa98e2SPeter Wemm }
997c2aa98e2SPeter Wemm if (*optarg != '\0')
998c2aa98e2SPeter Wemm {
999a7ec597cSGregory Neil Shapiro i = strlen(optarg) + 1;
1000a7ec597cSGregory Neil Shapiro ep = sm_malloc_x(i);
1001a7ec597cSGregory Neil Shapiro cleanstrcpy(ep, optarg, i);
100240266059SGregory Neil Shapiro macdefine(&BlankEnvelope.e_macro, A_HEAP,
100340266059SGregory Neil Shapiro 'r', ep);
1004c2aa98e2SPeter Wemm }
1005c2aa98e2SPeter Wemm break;
1006c2aa98e2SPeter Wemm
100740266059SGregory Neil Shapiro case 'Q': /* change quarantining on queued items */
100840266059SGregory Neil Shapiro /* sanity check */
100940266059SGregory Neil Shapiro if (OpMode != MD_DELIVER &&
101040266059SGregory Neil Shapiro OpMode != MD_QUEUERUN)
101140266059SGregory Neil Shapiro {
101240266059SGregory Neil Shapiro usrerr("Can not use -Q with -b%c", OpMode);
101340266059SGregory Neil Shapiro ExitStat = EX_USAGE;
101440266059SGregory Neil Shapiro break;
101540266059SGregory Neil Shapiro }
101640266059SGregory Neil Shapiro
101740266059SGregory Neil Shapiro if (OpMode == MD_DELIVER)
101840266059SGregory Neil Shapiro set_op_mode(MD_QUEUERUN);
101940266059SGregory Neil Shapiro
102040266059SGregory Neil Shapiro FullName = NULL;
102140266059SGregory Neil Shapiro
102240266059SGregory Neil Shapiro quarantining = newstr(optarg);
102340266059SGregory Neil Shapiro break;
102440266059SGregory Neil Shapiro
1025c2aa98e2SPeter Wemm case 'q': /* run queue files at intervals */
102606f25ae9SGregory Neil Shapiro /* sanity check */
102706f25ae9SGregory Neil Shapiro if (OpMode != MD_DELIVER &&
102806f25ae9SGregory Neil Shapiro OpMode != MD_DAEMON &&
102906f25ae9SGregory Neil Shapiro OpMode != MD_FGDAEMON &&
103006f25ae9SGregory Neil Shapiro OpMode != MD_PRINT &&
103140266059SGregory Neil Shapiro OpMode != MD_PRINTNQE &&
103206f25ae9SGregory Neil Shapiro OpMode != MD_QUEUERUN)
103306f25ae9SGregory Neil Shapiro {
103406f25ae9SGregory Neil Shapiro usrerr("Can not use -q with -b%c", OpMode);
103506f25ae9SGregory Neil Shapiro ExitStat = EX_USAGE;
103606f25ae9SGregory Neil Shapiro break;
103706f25ae9SGregory Neil Shapiro }
103806f25ae9SGregory Neil Shapiro
103906f25ae9SGregory Neil Shapiro /* don't override -bd, -bD or -bp */
104006f25ae9SGregory Neil Shapiro if (OpMode == MD_DELIVER)
104140266059SGregory Neil Shapiro set_op_mode(MD_QUEUERUN);
104206f25ae9SGregory Neil Shapiro
1043c2aa98e2SPeter Wemm FullName = NULL;
104440266059SGregory Neil Shapiro negate = optarg[0] == '!';
104540266059SGregory Neil Shapiro if (negate)
104640266059SGregory Neil Shapiro {
104740266059SGregory Neil Shapiro /* negate meaning of pattern match */
104840266059SGregory Neil Shapiro optarg++; /* skip '!' for next switch */
104940266059SGregory Neil Shapiro }
105006f25ae9SGregory Neil Shapiro
1051c2aa98e2SPeter Wemm switch (optarg[0])
1052c2aa98e2SPeter Wemm {
105340266059SGregory Neil Shapiro case 'G': /* Limit by queue group name */
105440266059SGregory Neil Shapiro if (negate)
105540266059SGregory Neil Shapiro {
105640266059SGregory Neil Shapiro usrerr("Can not use -q!G");
105740266059SGregory Neil Shapiro ExitStat = EX_USAGE;
105840266059SGregory Neil Shapiro break;
105940266059SGregory Neil Shapiro }
106040266059SGregory Neil Shapiro if (queuegroup != NULL)
106140266059SGregory Neil Shapiro {
106240266059SGregory Neil Shapiro usrerr("Can not use multiple -qG options");
106340266059SGregory Neil Shapiro ExitStat = EX_USAGE;
106440266059SGregory Neil Shapiro break;
106540266059SGregory Neil Shapiro }
106640266059SGregory Neil Shapiro queuegroup = newstr(&optarg[1]);
106740266059SGregory Neil Shapiro break;
106840266059SGregory Neil Shapiro
106940266059SGregory Neil Shapiro case 'I': /* Limit by ID */
1070d0cef73dSGregory Neil Shapiro new = (QUEUE_CHAR *) xalloc(sizeof(*new));
1071c2aa98e2SPeter Wemm new->queue_match = newstr(&optarg[1]);
107240266059SGregory Neil Shapiro new->queue_negate = negate;
1073c2aa98e2SPeter Wemm new->queue_next = QueueLimitId;
1074c2aa98e2SPeter Wemm QueueLimitId = new;
1075c2aa98e2SPeter Wemm break;
1076c2aa98e2SPeter Wemm
107740266059SGregory Neil Shapiro case 'R': /* Limit by recipient */
1078d0cef73dSGregory Neil Shapiro new = (QUEUE_CHAR *) xalloc(sizeof(*new));
1079c2aa98e2SPeter Wemm new->queue_match = newstr(&optarg[1]);
108040266059SGregory Neil Shapiro new->queue_negate = negate;
1081c2aa98e2SPeter Wemm new->queue_next = QueueLimitRecipient;
1082c2aa98e2SPeter Wemm QueueLimitRecipient = new;
1083c2aa98e2SPeter Wemm break;
1084c2aa98e2SPeter Wemm
108540266059SGregory Neil Shapiro case 'S': /* Limit by sender */
1086d0cef73dSGregory Neil Shapiro new = (QUEUE_CHAR *) xalloc(sizeof(*new));
1087c2aa98e2SPeter Wemm new->queue_match = newstr(&optarg[1]);
108840266059SGregory Neil Shapiro new->queue_negate = negate;
1089c2aa98e2SPeter Wemm new->queue_next = QueueLimitSender;
1090c2aa98e2SPeter Wemm QueueLimitSender = new;
1091c2aa98e2SPeter Wemm break;
1092c2aa98e2SPeter Wemm
109340266059SGregory Neil Shapiro case 'f': /* foreground queue run */
109440266059SGregory Neil Shapiro foregroundqueue = true;
109540266059SGregory Neil Shapiro break;
109640266059SGregory Neil Shapiro
109740266059SGregory Neil Shapiro case 'Q': /* Limit by quarantine message */
109840266059SGregory Neil Shapiro if (optarg[1] != '\0')
109940266059SGregory Neil Shapiro {
1100d0cef73dSGregory Neil Shapiro new = (QUEUE_CHAR *) xalloc(sizeof(*new));
110140266059SGregory Neil Shapiro new->queue_match = newstr(&optarg[1]);
110240266059SGregory Neil Shapiro new->queue_negate = negate;
110340266059SGregory Neil Shapiro new->queue_next = QueueLimitQuarantine;
110440266059SGregory Neil Shapiro QueueLimitQuarantine = new;
110540266059SGregory Neil Shapiro }
110640266059SGregory Neil Shapiro QueueMode = QM_QUARANTINE;
110740266059SGregory Neil Shapiro break;
110840266059SGregory Neil Shapiro
110940266059SGregory Neil Shapiro case 'L': /* act on lost items */
111040266059SGregory Neil Shapiro QueueMode = QM_LOST;
111140266059SGregory Neil Shapiro break;
111240266059SGregory Neil Shapiro
111340266059SGregory Neil Shapiro case 'p': /* Persistent queue */
111440266059SGregory Neil Shapiro queuepersistent = true;
111540266059SGregory Neil Shapiro if (QueueIntvl == 0)
111640266059SGregory Neil Shapiro QueueIntvl = 1;
111740266059SGregory Neil Shapiro if (optarg[1] == '\0')
111840266059SGregory Neil Shapiro break;
111940266059SGregory Neil Shapiro ++optarg;
112040266059SGregory Neil Shapiro /* FALLTHROUGH */
112140266059SGregory Neil Shapiro
1122c2aa98e2SPeter Wemm default:
112306f25ae9SGregory Neil Shapiro i = Errors;
1124c2aa98e2SPeter Wemm QueueIntvl = convtime(optarg, 'm');
1125739ac4d4SGregory Neil Shapiro if (QueueIntvl < 0)
1126739ac4d4SGregory Neil Shapiro {
1127739ac4d4SGregory Neil Shapiro usrerr("Invalid -q value");
1128739ac4d4SGregory Neil Shapiro ExitStat = EX_USAGE;
1129739ac4d4SGregory Neil Shapiro }
113006f25ae9SGregory Neil Shapiro
113106f25ae9SGregory Neil Shapiro /* check for bad conversion */
113206f25ae9SGregory Neil Shapiro if (i < Errors)
113306f25ae9SGregory Neil Shapiro ExitStat = EX_USAGE;
1134c2aa98e2SPeter Wemm break;
1135c2aa98e2SPeter Wemm }
1136c2aa98e2SPeter Wemm break;
1137c2aa98e2SPeter Wemm
1138c2aa98e2SPeter Wemm case 'R': /* DSN RET: what to return */
113940266059SGregory Neil Shapiro CHECK_AGAINST_OPMODE(j);
114040266059SGregory Neil Shapiro if (bitset(EF_RET_PARAM, BlankEnvelope.e_flags))
1141c2aa98e2SPeter Wemm {
1142c2aa98e2SPeter Wemm usrerr("Duplicate -R flag");
1143c2aa98e2SPeter Wemm ExitStat = EX_USAGE;
1144c2aa98e2SPeter Wemm break;
1145c2aa98e2SPeter Wemm }
114640266059SGregory Neil Shapiro BlankEnvelope.e_flags |= EF_RET_PARAM;
11472fb4f839SGregory Neil Shapiro if (SM_STRCASEEQ(optarg, "hdrs"))
114840266059SGregory Neil Shapiro BlankEnvelope.e_flags |= EF_NO_BODY_RETN;
11492fb4f839SGregory Neil Shapiro else if (!SM_STRCASEEQ(optarg, "full"))
1150c2aa98e2SPeter Wemm {
1151c2aa98e2SPeter Wemm usrerr("Invalid -R value");
1152c2aa98e2SPeter Wemm ExitStat = EX_USAGE;
1153c2aa98e2SPeter Wemm }
115440266059SGregory Neil Shapiro macdefine(&BlankEnvelope.e_macro, A_TEMP,
115540266059SGregory Neil Shapiro macid("{dsn_ret}"), optarg);
1156c2aa98e2SPeter Wemm break;
1157c2aa98e2SPeter Wemm
1158c2aa98e2SPeter Wemm case 't': /* read recipients from message */
115940266059SGregory Neil Shapiro CHECK_AGAINST_OPMODE(j);
116040266059SGregory Neil Shapiro GrabTo = true;
1161c2aa98e2SPeter Wemm break;
1162c2aa98e2SPeter Wemm
11632fb4f839SGregory Neil Shapiro #if USE_EAI
11642fb4f839SGregory Neil Shapiro case 'U':
11652fb4f839SGregory Neil Shapiro CHECK_AGAINST_OPMODE(j);
11662fb4f839SGregory Neil Shapiro BlankEnvelope.e_smtputf8 = true;
11672fb4f839SGregory Neil Shapiro break;
11682fb4f839SGregory Neil Shapiro #endif
11692fb4f839SGregory Neil Shapiro
1170c2aa98e2SPeter Wemm case 'V': /* DSN ENVID: set "original" envelope id */
117140266059SGregory Neil Shapiro CHECK_AGAINST_OPMODE(j);
1172c2aa98e2SPeter Wemm if (!xtextok(optarg))
1173c2aa98e2SPeter Wemm {
1174c2aa98e2SPeter Wemm usrerr("Invalid syntax in -V flag");
1175c2aa98e2SPeter Wemm ExitStat = EX_USAGE;
1176c2aa98e2SPeter Wemm }
1177c2aa98e2SPeter Wemm else
117806f25ae9SGregory Neil Shapiro {
117940266059SGregory Neil Shapiro BlankEnvelope.e_envid = newstr(optarg);
118040266059SGregory Neil Shapiro macdefine(&BlankEnvelope.e_macro, A_TEMP,
118140266059SGregory Neil Shapiro macid("{dsn_envid}"), optarg);
118206f25ae9SGregory Neil Shapiro }
1183c2aa98e2SPeter Wemm break;
1184c2aa98e2SPeter Wemm
1185c2aa98e2SPeter Wemm case 'X': /* traffic log file */
118640266059SGregory Neil Shapiro dp = drop_privileges(true);
118706f25ae9SGregory Neil Shapiro setstat(dp);
118806f25ae9SGregory Neil Shapiro if (stat(optarg, &traf_st) == 0 &&
118906f25ae9SGregory Neil Shapiro S_ISFIFO(traf_st.st_mode))
119040266059SGregory Neil Shapiro TrafficLogFile = sm_io_open(SmFtStdio,
119140266059SGregory Neil Shapiro SM_TIME_DEFAULT,
119240266059SGregory Neil Shapiro optarg,
119340266059SGregory Neil Shapiro SM_IO_WRONLY, NULL);
119406f25ae9SGregory Neil Shapiro else
119540266059SGregory Neil Shapiro TrafficLogFile = sm_io_open(SmFtStdio,
119640266059SGregory Neil Shapiro SM_TIME_DEFAULT,
119740266059SGregory Neil Shapiro optarg,
119840266059SGregory Neil Shapiro SM_IO_APPEND, NULL);
1199c2aa98e2SPeter Wemm if (TrafficLogFile == NULL)
1200c2aa98e2SPeter Wemm {
1201c2aa98e2SPeter Wemm syserr("cannot open %s", optarg);
1202c2aa98e2SPeter Wemm ExitStat = EX_CANTCREAT;
1203c2aa98e2SPeter Wemm break;
1204c2aa98e2SPeter Wemm }
120540266059SGregory Neil Shapiro (void) sm_io_setvbuf(TrafficLogFile, SM_TIME_DEFAULT,
120640266059SGregory Neil Shapiro NULL, SM_IO_LBF, 0);
1207c2aa98e2SPeter Wemm break;
1208c2aa98e2SPeter Wemm
1209c2aa98e2SPeter Wemm /* compatibility flags */
1210c2aa98e2SPeter Wemm case 'c': /* connect to non-local mailers */
1211c2aa98e2SPeter Wemm case 'i': /* don't let dot stop me */
1212c2aa98e2SPeter Wemm case 'm': /* send to me too */
1213c2aa98e2SPeter Wemm case 'T': /* set timeout interval */
1214c2aa98e2SPeter Wemm case 'v': /* give blow-by-blow description */
121540266059SGregory Neil Shapiro setoption(j, "T", false, true, &BlankEnvelope);
1216c2aa98e2SPeter Wemm break;
1217c2aa98e2SPeter Wemm
1218c2aa98e2SPeter Wemm case 'e': /* error message disposition */
1219c2aa98e2SPeter Wemm case 'M': /* define macro */
122040266059SGregory Neil Shapiro setoption(j, optarg, false, true, &BlankEnvelope);
1221c2aa98e2SPeter Wemm break;
1222c2aa98e2SPeter Wemm
1223c2aa98e2SPeter Wemm case 's': /* save From lines in headers */
122440266059SGregory Neil Shapiro setoption('f', "T", false, true, &BlankEnvelope);
1225c2aa98e2SPeter Wemm break;
1226c2aa98e2SPeter Wemm
1227c2aa98e2SPeter Wemm #ifdef DBM
1228c2aa98e2SPeter Wemm case 'I': /* initialize alias DBM file */
122940266059SGregory Neil Shapiro set_op_mode(MD_INITALIAS);
1230c2aa98e2SPeter Wemm break;
1231c2aa98e2SPeter Wemm #endif /* DBM */
1232c2aa98e2SPeter Wemm
1233c2aa98e2SPeter Wemm #if defined(__osf__) || defined(_AIX3)
1234c2aa98e2SPeter Wemm case 'x': /* random flag that OSF/1 & AIX mailx passes */
1235c2aa98e2SPeter Wemm break;
12365b0945b5SGregory Neil Shapiro #endif
1237c2aa98e2SPeter Wemm #if defined(sony_news)
1238c2aa98e2SPeter Wemm case 'E':
1239c2aa98e2SPeter Wemm case 'J': /* ignore flags for Japanese code conversion
124006f25ae9SGregory Neil Shapiro implemented on Sony NEWS */
1241c2aa98e2SPeter Wemm break;
124206f25ae9SGregory Neil Shapiro #endif /* defined(sony_news) */
1243c2aa98e2SPeter Wemm
1244c2aa98e2SPeter Wemm default:
124540266059SGregory Neil Shapiro finis(true, true, EX_USAGE);
124640266059SGregory Neil Shapiro /* NOTREACHED */
1247c2aa98e2SPeter Wemm break;
1248c2aa98e2SPeter Wemm }
1249c2aa98e2SPeter Wemm }
1250c2aa98e2SPeter Wemm
125140266059SGregory Neil Shapiro /* if we've had errors so far, exit now */
12529bd497b8SGregory Neil Shapiro if ((ExitStat != EX_OK && OpMode != MD_TEST && OpMode != MD_CHECKCONFIG) ||
125340266059SGregory Neil Shapiro ExitStat == EX_OSERR)
125406f25ae9SGregory Neil Shapiro {
125540266059SGregory Neil Shapiro finis(false, true, ExitStat);
125640266059SGregory Neil Shapiro /* NOTREACHED */
125706f25ae9SGregory Neil Shapiro }
125806f25ae9SGregory Neil Shapiro
125940266059SGregory Neil Shapiro if (bitset(SUBMIT_MTA, SubmitMode))
126006f25ae9SGregory Neil Shapiro {
1261739ac4d4SGregory Neil Shapiro /* If set daemon_flags on command line, don't reset it */
1262739ac4d4SGregory Neil Shapiro if (macvalue(macid("{daemon_flags}"), &BlankEnvelope) == NULL)
126340266059SGregory Neil Shapiro macdefine(&BlankEnvelope.e_macro, A_PERM,
126440266059SGregory Neil Shapiro macid("{daemon_flags}"), "CC f");
126506f25ae9SGregory Neil Shapiro }
126640266059SGregory Neil Shapiro else if (OpMode == MD_DELIVER || OpMode == MD_SMTP)
126706f25ae9SGregory Neil Shapiro {
126840266059SGregory Neil Shapiro SubmitMode = SUBMIT_MSA;
1269739ac4d4SGregory Neil Shapiro
1270739ac4d4SGregory Neil Shapiro /* If set daemon_flags on command line, don't reset it */
1271739ac4d4SGregory Neil Shapiro if (macvalue(macid("{daemon_flags}"), &BlankEnvelope) == NULL)
127240266059SGregory Neil Shapiro macdefine(&BlankEnvelope.e_macro, A_PERM,
127340266059SGregory Neil Shapiro macid("{daemon_flags}"), "c u");
127406f25ae9SGregory Neil Shapiro }
127506f25ae9SGregory Neil Shapiro
1276c2aa98e2SPeter Wemm /*
1277c2aa98e2SPeter Wemm ** Do basic initialization.
1278c2aa98e2SPeter Wemm ** Read system control file.
1279c2aa98e2SPeter Wemm ** Extract special fields for local use.
1280c2aa98e2SPeter Wemm */
1281c2aa98e2SPeter Wemm
1282c2aa98e2SPeter Wemm checkfd012("before readcf");
128340266059SGregory Neil Shapiro vendor_pre_defaults(&BlankEnvelope);
128406f25ae9SGregory Neil Shapiro
128540266059SGregory Neil Shapiro readcf(getcfname(OpMode, SubmitMode, cftype, conffile),
128640266059SGregory Neil Shapiro safecf, &BlankEnvelope);
128740266059SGregory Neil Shapiro #if !defined(_USE_SUN_NSSWITCH_) && !defined(_USE_DEC_SVC_CONF_)
128840266059SGregory Neil Shapiro ConfigFileRead = true;
12895b0945b5SGregory Neil Shapiro #endif
129040266059SGregory Neil Shapiro vendor_post_defaults(&BlankEnvelope);
129140266059SGregory Neil Shapiro
129240266059SGregory Neil Shapiro /* now we can complain about missing fds */
129340266059SGregory Neil Shapiro if (MissingFds != 0 && LogLevel > 8)
129440266059SGregory Neil Shapiro {
129540266059SGregory Neil Shapiro char mbuf[MAXLINE];
129640266059SGregory Neil Shapiro
129740266059SGregory Neil Shapiro mbuf[0] = '\0';
129840266059SGregory Neil Shapiro if (bitset(1 << STDIN_FILENO, MissingFds))
1299d0cef73dSGregory Neil Shapiro (void) sm_strlcat(mbuf, ", stdin", sizeof(mbuf));
130040266059SGregory Neil Shapiro if (bitset(1 << STDOUT_FILENO, MissingFds))
1301d0cef73dSGregory Neil Shapiro (void) sm_strlcat(mbuf, ", stdout", sizeof(mbuf));
130240266059SGregory Neil Shapiro if (bitset(1 << STDERR_FILENO, MissingFds))
1303d0cef73dSGregory Neil Shapiro (void) sm_strlcat(mbuf, ", stderr", sizeof(mbuf));
130440266059SGregory Neil Shapiro
130540266059SGregory Neil Shapiro /* Notice: fill_errno is from high above: fill_fd() */
130640266059SGregory Neil Shapiro sm_syslog(LOG_WARNING, NOQID,
130740266059SGregory Neil Shapiro "File descriptors missing on startup: %s; %s",
130840266059SGregory Neil Shapiro &mbuf[2], sm_errstring(fill_errno));
130940266059SGregory Neil Shapiro }
1310c2aa98e2SPeter Wemm
13118774250cSGregory Neil Shapiro /* Remove the ability for a normal user to send signals */
131240266059SGregory Neil Shapiro if (RealUid != 0 && RealUid != geteuid())
13138774250cSGregory Neil Shapiro {
13148774250cSGregory Neil Shapiro uid_t new_uid = geteuid();
13158774250cSGregory Neil Shapiro
13168774250cSGregory Neil Shapiro #if HASSETREUID
13178774250cSGregory Neil Shapiro /*
13188774250cSGregory Neil Shapiro ** Since we can differentiate between uid and euid,
13198774250cSGregory Neil Shapiro ** make the uid a different user so the real user
13208774250cSGregory Neil Shapiro ** can't send signals. However, it doesn't need to be
13218774250cSGregory Neil Shapiro ** root (euid has root).
13228774250cSGregory Neil Shapiro */
13238774250cSGregory Neil Shapiro
13248774250cSGregory Neil Shapiro if (new_uid == 0)
13258774250cSGregory Neil Shapiro new_uid = DefUid;
13268774250cSGregory Neil Shapiro if (tTd(47, 5))
132740266059SGregory Neil Shapiro sm_dprintf("Changing real uid to %d\n", (int) new_uid);
13288774250cSGregory Neil Shapiro if (setreuid(new_uid, geteuid()) < 0)
13298774250cSGregory Neil Shapiro {
13308774250cSGregory Neil Shapiro syserr("main: setreuid(%d, %d) failed",
13318774250cSGregory Neil Shapiro (int) new_uid, (int) geteuid());
133240266059SGregory Neil Shapiro finis(false, true, EX_OSERR);
13338774250cSGregory Neil Shapiro /* NOTREACHED */
13348774250cSGregory Neil Shapiro }
13358774250cSGregory Neil Shapiro if (tTd(47, 10))
133640266059SGregory Neil Shapiro sm_dprintf("Now running as e/ruid %d:%d\n",
13378774250cSGregory Neil Shapiro (int) geteuid(), (int) getuid());
13388774250cSGregory Neil Shapiro #else /* HASSETREUID */
13398774250cSGregory Neil Shapiro /*
13408774250cSGregory Neil Shapiro ** Have to change both effective and real so need to
13418774250cSGregory Neil Shapiro ** change them both to effective to keep privs.
13428774250cSGregory Neil Shapiro */
13438774250cSGregory Neil Shapiro
13448774250cSGregory Neil Shapiro if (tTd(47, 5))
134540266059SGregory Neil Shapiro sm_dprintf("Changing uid to %d\n", (int) new_uid);
13468774250cSGregory Neil Shapiro if (setuid(new_uid) < 0)
13478774250cSGregory Neil Shapiro {
13488774250cSGregory Neil Shapiro syserr("main: setuid(%d) failed", (int) new_uid);
134940266059SGregory Neil Shapiro finis(false, true, EX_OSERR);
13508774250cSGregory Neil Shapiro /* NOTREACHED */
13518774250cSGregory Neil Shapiro }
13528774250cSGregory Neil Shapiro if (tTd(47, 10))
135340266059SGregory Neil Shapiro sm_dprintf("Now running as e/ruid %d:%d\n",
13548774250cSGregory Neil Shapiro (int) geteuid(), (int) getuid());
13558774250cSGregory Neil Shapiro #endif /* HASSETREUID */
13568774250cSGregory Neil Shapiro }
13578774250cSGregory Neil Shapiro
135840266059SGregory Neil Shapiro #if NAMED_BIND
1359e92d3f3fSGregory Neil Shapiro if (FallbackMX != NULL)
1360e92d3f3fSGregory Neil Shapiro (void) getfallbackmxrr(FallbackMX);
13615b0945b5SGregory Neil Shapiro #endif
136240266059SGregory Neil Shapiro
13636f9c8e5bSGregory Neil Shapiro if (SuperSafe == SAFE_INTERACTIVE && !SM_IS_INTERACTIVE(CurEnv->e_sendmode))
136440266059SGregory Neil Shapiro {
136540266059SGregory Neil Shapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
136640266059SGregory Neil Shapiro "WARNING: SuperSafe=interactive should only be used with\n DeliveryMode=interactive\n");
136740266059SGregory Neil Shapiro }
136840266059SGregory Neil Shapiro
136940266059SGregory Neil Shapiro if (UseMSP && (OpMode == MD_DAEMON || OpMode == MD_FGDAEMON))
137040266059SGregory Neil Shapiro {
137140266059SGregory Neil Shapiro usrerr("Mail submission program cannot be used as daemon");
137240266059SGregory Neil Shapiro finis(false, true, EX_USAGE);
137340266059SGregory Neil Shapiro }
137440266059SGregory Neil Shapiro
137540266059SGregory Neil Shapiro if (OpMode == MD_DELIVER || OpMode == MD_SMTP ||
137640266059SGregory Neil Shapiro OpMode == MD_QUEUERUN || OpMode == MD_ARPAFTP ||
137740266059SGregory Neil Shapiro OpMode == MD_DAEMON || OpMode == MD_FGDAEMON)
137840266059SGregory Neil Shapiro makeworkgroups();
137940266059SGregory Neil Shapiro
13802fb4f839SGregory Neil Shapiro #if USE_EAI
1381d39bd2c1SGregory Neil Shapiro if (!SMTP_UTF8 && MainEnvelope.e_smtputf8)
13822fb4f839SGregory Neil Shapiro {
13832fb4f839SGregory Neil Shapiro usrerr("-U requires SMTPUTF8");
13842fb4f839SGregory Neil Shapiro finis(false, true, EX_USAGE);
13852fb4f839SGregory Neil Shapiro }
13862fb4f839SGregory Neil Shapiro #endif
13872fb4f839SGregory Neil Shapiro
13888774250cSGregory Neil Shapiro /* set up the basic signal handlers */
138940266059SGregory Neil Shapiro if (sm_signal(SIGINT, SIG_IGN) != SIG_IGN)
139040266059SGregory Neil Shapiro (void) sm_signal(SIGINT, intsig);
139140266059SGregory Neil Shapiro (void) sm_signal(SIGTERM, intsig);
13928774250cSGregory Neil Shapiro
1393c2aa98e2SPeter Wemm /* Enforce use of local time (null string overrides this) */
1394c2aa98e2SPeter Wemm if (TimeZoneSpec == NULL)
1395c2aa98e2SPeter Wemm unsetenv("TZ");
1396c2aa98e2SPeter Wemm else if (TimeZoneSpec[0] != '\0')
13974e4196cbSGregory Neil Shapiro sm_setuserenv("TZ", TimeZoneSpec);
1398c2aa98e2SPeter Wemm else
13994e4196cbSGregory Neil Shapiro sm_setuserenv("TZ", NULL);
1400c2aa98e2SPeter Wemm tzset();
1401c2aa98e2SPeter Wemm
140240266059SGregory Neil Shapiro /* initialize mailbox database */
140340266059SGregory Neil Shapiro i = sm_mbdb_initialize(Mbdb);
140440266059SGregory Neil Shapiro if (i != EX_OK)
140540266059SGregory Neil Shapiro {
140640266059SGregory Neil Shapiro usrerr("Can't initialize mailbox database \"%s\": %s",
140740266059SGregory Neil Shapiro Mbdb, sm_strexit(i));
140840266059SGregory Neil Shapiro ExitStat = i;
140940266059SGregory Neil Shapiro }
141040266059SGregory Neil Shapiro
1411c2aa98e2SPeter Wemm /* avoid denial-of-service attacks */
1412c2aa98e2SPeter Wemm resetlimits();
1413c2aa98e2SPeter Wemm
141440266059SGregory Neil Shapiro if (OpMode == MD_TEST)
141540266059SGregory Neil Shapiro {
141640266059SGregory Neil Shapiro /* can't be done after readcf if RunAs* is used */
141740266059SGregory Neil Shapiro dp = drop_privileges(true);
141840266059SGregory Neil Shapiro if (dp != EX_OK)
141940266059SGregory Neil Shapiro {
142040266059SGregory Neil Shapiro finis(false, true, dp);
142140266059SGregory Neil Shapiro /* NOTREACHED */
142240266059SGregory Neil Shapiro }
142340266059SGregory Neil Shapiro }
142440266059SGregory Neil Shapiro else if (OpMode != MD_DAEMON && OpMode != MD_FGDAEMON)
1425c2aa98e2SPeter Wemm {
1426c2aa98e2SPeter Wemm /* drop privileges -- daemon mode done after socket/bind */
142740266059SGregory Neil Shapiro dp = drop_privileges(false);
142806f25ae9SGregory Neil Shapiro setstat(dp);
142940266059SGregory Neil Shapiro if (dp == EX_OK && UseMSP && (geteuid() == 0 || getuid() == 0))
143040266059SGregory Neil Shapiro {
143140266059SGregory Neil Shapiro usrerr("Mail submission program must have RunAsUser set to non root user");
143240266059SGregory Neil Shapiro finis(false, true, EX_CONFIG);
143340266059SGregory Neil Shapiro /* NOTREACHED */
143440266059SGregory Neil Shapiro }
1435c2aa98e2SPeter Wemm }
1436c2aa98e2SPeter Wemm
143706f25ae9SGregory Neil Shapiro #if NAMED_BIND
143806f25ae9SGregory Neil Shapiro _res.retry = TimeOuts.res_retry[RES_TO_DEFAULT];
143906f25ae9SGregory Neil Shapiro _res.retrans = TimeOuts.res_retrans[RES_TO_DEFAULT];
14405b0945b5SGregory Neil Shapiro #endif
144106f25ae9SGregory Neil Shapiro
1442c2aa98e2SPeter Wemm /*
1443c2aa98e2SPeter Wemm ** Find our real host name for future logging.
1444c2aa98e2SPeter Wemm */
1445c2aa98e2SPeter Wemm
144606f25ae9SGregory Neil Shapiro authinfo = getauthinfo(STDIN_FILENO, &forged);
144740266059SGregory Neil Shapiro macdefine(&BlankEnvelope.e_macro, A_TEMP, '_', authinfo);
1448c2aa98e2SPeter Wemm
1449c2aa98e2SPeter Wemm /* suppress error printing if errors mailed back or whatever */
145040266059SGregory Neil Shapiro if (BlankEnvelope.e_errormode != EM_PRINT)
145140266059SGregory Neil Shapiro HoldErrs = true;
1452c2aa98e2SPeter Wemm
1453c2aa98e2SPeter Wemm /* set up the $=m class now, after .cf has a chance to redefine $m */
1454d0cef73dSGregory Neil Shapiro expand("\201m", jbuf, sizeof(jbuf), &BlankEnvelope);
1455602a2b1bSGregory Neil Shapiro if (jbuf[0] != '\0')
1456c2aa98e2SPeter Wemm setclass('m', jbuf);
1457c2aa98e2SPeter Wemm
1458c2aa98e2SPeter Wemm /* probe interfaces and locate any additional names */
145940266059SGregory Neil Shapiro if (DontProbeInterfaces != DPI_PROBENONE)
1460c2aa98e2SPeter Wemm load_if_names();
1461c2aa98e2SPeter Wemm
146240266059SGregory Neil Shapiro if (tTd(0, 10))
146340266059SGregory Neil Shapiro {
146413bd1963SGregory Neil Shapiro char pidpath[MAXPATHLEN];
146513bd1963SGregory Neil Shapiro
146640266059SGregory Neil Shapiro /* Now we know which .cf file we use */
146740266059SGregory Neil Shapiro sm_dprintf(" Conf file:\t%s (selected)\n",
146840266059SGregory Neil Shapiro getcfname(OpMode, SubmitMode, cftype, conffile));
1469d0cef73dSGregory Neil Shapiro expand(PidFile, pidpath, sizeof(pidpath), &BlankEnvelope);
147013bd1963SGregory Neil Shapiro sm_dprintf(" Pid file:\t%s (selected)\n", pidpath);
147140266059SGregory Neil Shapiro }
147240266059SGregory Neil Shapiro
1473c2aa98e2SPeter Wemm if (tTd(0, 1))
1474c2aa98e2SPeter Wemm {
147540266059SGregory Neil Shapiro sm_dprintf("\n============ SYSTEM IDENTITY (after readcf) ============");
147640266059SGregory Neil Shapiro sm_dprintf("\n (short domain name) $w = ");
1477e92d3f3fSGregory Neil Shapiro xputs(sm_debug_file(), macvalue('w', &BlankEnvelope));
147840266059SGregory Neil Shapiro sm_dprintf("\n (canonical domain name) $j = ");
1479e92d3f3fSGregory Neil Shapiro xputs(sm_debug_file(), macvalue('j', &BlankEnvelope));
148040266059SGregory Neil Shapiro sm_dprintf("\n (subdomain name) $m = ");
1481e92d3f3fSGregory Neil Shapiro xputs(sm_debug_file(), macvalue('m', &BlankEnvelope));
148240266059SGregory Neil Shapiro sm_dprintf("\n (node name) $k = ");
1483e92d3f3fSGregory Neil Shapiro xputs(sm_debug_file(), macvalue('k', &BlankEnvelope));
148440266059SGregory Neil Shapiro sm_dprintf("\n========================================================\n\n");
1485c2aa98e2SPeter Wemm }
1486c2aa98e2SPeter Wemm
1487c2aa98e2SPeter Wemm /*
1488c2aa98e2SPeter Wemm ** Do more command line checking -- these are things that
1489c2aa98e2SPeter Wemm ** have to modify the results of reading the config file.
1490c2aa98e2SPeter Wemm */
1491c2aa98e2SPeter Wemm
1492c2aa98e2SPeter Wemm /* process authorization warnings from command line */
1493c2aa98e2SPeter Wemm if (warn_C_flag)
149440266059SGregory Neil Shapiro auth_warning(&BlankEnvelope, "Processed by %s with -C %s",
149540266059SGregory Neil Shapiro RealUserName, conffile);
149606f25ae9SGregory Neil Shapiro if (Warn_Q_option && !wordinclass(RealUserName, 't'))
149740266059SGregory Neil Shapiro auth_warning(&BlankEnvelope, "Processed from queue %s",
149840266059SGregory Neil Shapiro QueueDir);
149940266059SGregory Neil Shapiro if (sysloglabel != NULL && !wordinclass(RealUserName, 't') &&
150040266059SGregory Neil Shapiro RealUid != 0 && RealUid != TrustedUid && LogLevel > 1)
150140266059SGregory Neil Shapiro sm_syslog(LOG_WARNING, NOQID, "user %d changed syslog label",
150240266059SGregory Neil Shapiro (int) RealUid);
1503c2aa98e2SPeter Wemm
1504c2aa98e2SPeter Wemm /* check body type for legality */
150540266059SGregory Neil Shapiro i = check_bodytype(BlankEnvelope.e_bodytype);
150640266059SGregory Neil Shapiro if (i == BODYTYPE_ILLEGAL)
1507c2aa98e2SPeter Wemm {
150840266059SGregory Neil Shapiro usrerr("Illegal body type %s", BlankEnvelope.e_bodytype);
150940266059SGregory Neil Shapiro BlankEnvelope.e_bodytype = NULL;
1510c2aa98e2SPeter Wemm }
1511d39bd2c1SGregory Neil Shapiro else if (BODYTYPE_7BIT == i)
1512d39bd2c1SGregory Neil Shapiro BlankEnvelope.e_flags |= EF_7BITBODY;
1513c2aa98e2SPeter Wemm
1514c2aa98e2SPeter Wemm /* tweak default DSN notifications */
1515c2aa98e2SPeter Wemm if (DefaultNotify == 0)
1516c2aa98e2SPeter Wemm DefaultNotify = QPINGONFAILURE|QPINGONDELAY;
1517c2aa98e2SPeter Wemm
1518c2aa98e2SPeter Wemm /* check for sane configuration level */
1519c2aa98e2SPeter Wemm if (ConfigLevel > MAXCONFIGLEVEL)
1520c2aa98e2SPeter Wemm {
1521c2aa98e2SPeter Wemm syserr("Warning: .cf version level (%d) exceeds sendmail version %s functionality (%d)",
1522c2aa98e2SPeter Wemm ConfigLevel, Version, MAXCONFIGLEVEL);
1523c2aa98e2SPeter Wemm }
1524c2aa98e2SPeter Wemm
1525c2aa98e2SPeter Wemm /* need MCI cache to have persistence */
1526c2aa98e2SPeter Wemm if (HostStatDir != NULL && MaxMciCache == 0)
1527c2aa98e2SPeter Wemm {
1528c2aa98e2SPeter Wemm HostStatDir = NULL;
152940266059SGregory Neil Shapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
153040266059SGregory Neil Shapiro "Warning: HostStatusDirectory disabled with ConnectionCacheSize = 0\n");
1531c2aa98e2SPeter Wemm }
1532c2aa98e2SPeter Wemm
1533c2aa98e2SPeter Wemm /* need HostStatusDir in order to have SingleThreadDelivery */
1534c2aa98e2SPeter Wemm if (SingleThreadDelivery && HostStatDir == NULL)
1535c2aa98e2SPeter Wemm {
153640266059SGregory Neil Shapiro SingleThreadDelivery = false;
153740266059SGregory Neil Shapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
153840266059SGregory Neil Shapiro "Warning: HostStatusDirectory required for SingleThreadDelivery\n");
1539c2aa98e2SPeter Wemm }
1540c2aa98e2SPeter Wemm
15414e4196cbSGregory Neil Shapiro #if _FFR_MEMSTAT
15424e4196cbSGregory Neil Shapiro j = sm_memstat_open();
15434e4196cbSGregory Neil Shapiro if (j < 0 && (RefuseLowMem > 0 || QueueLowMem > 0) && LogLevel > 4)
15444e4196cbSGregory Neil Shapiro {
15454e4196cbSGregory Neil Shapiro sm_syslog(LOG_WARNING, NOQID,
15464e4196cbSGregory Neil Shapiro "cannot get memory statistics, settings ignored, error=%d"
15474e4196cbSGregory Neil Shapiro , j);
15484e4196cbSGregory Neil Shapiro }
15494e4196cbSGregory Neil Shapiro #endif /* _FFR_MEMSTAT */
15504e4196cbSGregory Neil Shapiro
1551c2aa98e2SPeter Wemm /* check for permissions */
155240266059SGregory Neil Shapiro if (RealUid != 0 &&
1553065a643dSPeter Wemm RealUid != TrustedUid)
1554c2aa98e2SPeter Wemm {
155540266059SGregory Neil Shapiro char *action = NULL;
155640266059SGregory Neil Shapiro
155740266059SGregory Neil Shapiro switch (OpMode)
155840266059SGregory Neil Shapiro {
155940266059SGregory Neil Shapiro case MD_QUEUERUN:
156040266059SGregory Neil Shapiro if (quarantining != NULL)
156140266059SGregory Neil Shapiro action = "quarantine jobs";
156240266059SGregory Neil Shapiro else
1563e92d3f3fSGregory Neil Shapiro {
156440266059SGregory Neil Shapiro /* Normal users can do a single queue run */
156540266059SGregory Neil Shapiro if (QueueIntvl == 0)
156640266059SGregory Neil Shapiro break;
1567e92d3f3fSGregory Neil Shapiro }
156840266059SGregory Neil Shapiro
156940266059SGregory Neil Shapiro /* but not persistent queue runners */
157040266059SGregory Neil Shapiro if (action == NULL)
157140266059SGregory Neil Shapiro action = "start a queue runner daemon";
157240266059SGregory Neil Shapiro /* FALLTHROUGH */
157340266059SGregory Neil Shapiro
157440266059SGregory Neil Shapiro case MD_PURGESTAT:
157540266059SGregory Neil Shapiro if (action == NULL)
157640266059SGregory Neil Shapiro action = "purge host status";
157740266059SGregory Neil Shapiro /* FALLTHROUGH */
157840266059SGregory Neil Shapiro
157940266059SGregory Neil Shapiro case MD_DAEMON:
158040266059SGregory Neil Shapiro case MD_FGDAEMON:
158140266059SGregory Neil Shapiro if (action == NULL)
158240266059SGregory Neil Shapiro action = "run daemon";
158340266059SGregory Neil Shapiro
158440266059SGregory Neil Shapiro if (tTd(65, 1))
158540266059SGregory Neil Shapiro sm_dprintf("Deny user %d attempt to %s\n",
158640266059SGregory Neil Shapiro (int) RealUid, action);
158740266059SGregory Neil Shapiro
1588c2aa98e2SPeter Wemm if (LogLevel > 1)
1589c2aa98e2SPeter Wemm sm_syslog(LOG_ALERT, NOQID,
1590c2aa98e2SPeter Wemm "user %d attempted to %s",
159140266059SGregory Neil Shapiro (int) RealUid, action);
159240266059SGregory Neil Shapiro HoldErrs = false;
159340266059SGregory Neil Shapiro usrerr("Permission denied (real uid not trusted)");
159440266059SGregory Neil Shapiro finis(false, true, EX_USAGE);
159540266059SGregory Neil Shapiro /* NOTREACHED */
159640266059SGregory Neil Shapiro break;
159740266059SGregory Neil Shapiro
159840266059SGregory Neil Shapiro case MD_VERIFY:
159940266059SGregory Neil Shapiro if (bitset(PRIV_RESTRICTEXPAND, PrivacyFlags))
1600b518ca7dSPeter Wemm {
160140266059SGregory Neil Shapiro /*
160240266059SGregory Neil Shapiro ** If -bv and RestrictExpand,
160340266059SGregory Neil Shapiro ** drop privs to prevent normal
160440266059SGregory Neil Shapiro ** users from reading private
160540266059SGregory Neil Shapiro ** aliases/forwards/:include:s
160640266059SGregory Neil Shapiro */
160740266059SGregory Neil Shapiro
160840266059SGregory Neil Shapiro if (tTd(65, 1))
160940266059SGregory Neil Shapiro sm_dprintf("Drop privs for user %d attempt to expand (RestrictExpand)\n",
161040266059SGregory Neil Shapiro (int) RealUid);
161140266059SGregory Neil Shapiro
161240266059SGregory Neil Shapiro dp = drop_privileges(true);
161340266059SGregory Neil Shapiro
161440266059SGregory Neil Shapiro /* Fake address safety */
161540266059SGregory Neil Shapiro if (tTd(65, 1))
161640266059SGregory Neil Shapiro sm_dprintf("Faking DontBlameSendmail=NonRootSafeAddr\n");
161740266059SGregory Neil Shapiro setbitn(DBS_NONROOTSAFEADDR, DontBlameSendmail);
161840266059SGregory Neil Shapiro
161940266059SGregory Neil Shapiro if (dp != EX_OK)
162040266059SGregory Neil Shapiro {
162140266059SGregory Neil Shapiro if (tTd(65, 1))
162240266059SGregory Neil Shapiro sm_dprintf("Failed to drop privs for user %d attempt to expand, exiting\n",
162340266059SGregory Neil Shapiro (int) RealUid);
162440266059SGregory Neil Shapiro CurEnv->e_id = NULL;
162540266059SGregory Neil Shapiro finis(true, true, dp);
162640266059SGregory Neil Shapiro /* NOTREACHED */
162740266059SGregory Neil Shapiro }
162840266059SGregory Neil Shapiro }
162940266059SGregory Neil Shapiro break;
163040266059SGregory Neil Shapiro
163140266059SGregory Neil Shapiro case MD_TEST:
16329bd497b8SGregory Neil Shapiro case MD_CHECKCONFIG:
163340266059SGregory Neil Shapiro case MD_PRINT:
163440266059SGregory Neil Shapiro case MD_PRINTNQE:
163540266059SGregory Neil Shapiro case MD_FREEZE:
163640266059SGregory Neil Shapiro case MD_HOSTSTAT:
163740266059SGregory Neil Shapiro /* Nothing special to check */
163840266059SGregory Neil Shapiro break;
163940266059SGregory Neil Shapiro
164040266059SGregory Neil Shapiro case MD_INITALIAS:
164140266059SGregory Neil Shapiro if (!wordinclass(RealUserName, 't'))
164240266059SGregory Neil Shapiro {
164340266059SGregory Neil Shapiro if (tTd(65, 1))
164440266059SGregory Neil Shapiro sm_dprintf("Deny user %d attempt to rebuild the alias map\n",
164540266059SGregory Neil Shapiro (int) RealUid);
1646b518ca7dSPeter Wemm if (LogLevel > 1)
1647b518ca7dSPeter Wemm sm_syslog(LOG_ALERT, NOQID,
1648b518ca7dSPeter Wemm "user %d attempted to rebuild the alias map",
164940266059SGregory Neil Shapiro (int) RealUid);
165040266059SGregory Neil Shapiro HoldErrs = false;
165140266059SGregory Neil Shapiro usrerr("Permission denied (real uid not trusted)");
165240266059SGregory Neil Shapiro finis(false, true, EX_USAGE);
165340266059SGregory Neil Shapiro /* NOTREACHED */
165440266059SGregory Neil Shapiro }
165540266059SGregory Neil Shapiro if (UseMSP)
165640266059SGregory Neil Shapiro {
165740266059SGregory Neil Shapiro HoldErrs = false;
165840266059SGregory Neil Shapiro usrerr("User %d cannot rebuild aliases in mail submission program",
165940266059SGregory Neil Shapiro (int) RealUid);
166040266059SGregory Neil Shapiro finis(false, true, EX_USAGE);
166140266059SGregory Neil Shapiro /* NOTREACHED */
166240266059SGregory Neil Shapiro }
166340266059SGregory Neil Shapiro /* FALLTHROUGH */
166440266059SGregory Neil Shapiro
166540266059SGregory Neil Shapiro default:
166640266059SGregory Neil Shapiro if (bitset(PRIV_RESTRICTEXPAND, PrivacyFlags) &&
166740266059SGregory Neil Shapiro Verbose != 0)
166840266059SGregory Neil Shapiro {
166940266059SGregory Neil Shapiro /*
167040266059SGregory Neil Shapiro ** If -v and RestrictExpand, reset
167140266059SGregory Neil Shapiro ** Verbose to prevent normal users
167240266059SGregory Neil Shapiro ** from seeing the expansion of
167340266059SGregory Neil Shapiro ** aliases/forwards/:include:s
167440266059SGregory Neil Shapiro */
167540266059SGregory Neil Shapiro
167640266059SGregory Neil Shapiro if (tTd(65, 1))
167740266059SGregory Neil Shapiro sm_dprintf("Dropping verbosity for user %d (RestrictExpand)\n",
167840266059SGregory Neil Shapiro (int) RealUid);
167940266059SGregory Neil Shapiro Verbose = 0;
168040266059SGregory Neil Shapiro }
168140266059SGregory Neil Shapiro break;
168240266059SGregory Neil Shapiro }
1683b518ca7dSPeter Wemm }
1684c2aa98e2SPeter Wemm
1685c2aa98e2SPeter Wemm if (MeToo)
1686c2aa98e2SPeter Wemm BlankEnvelope.e_flags |= EF_METOO;
1687c2aa98e2SPeter Wemm
1688c2aa98e2SPeter Wemm switch (OpMode)
1689c2aa98e2SPeter Wemm {
1690c2aa98e2SPeter Wemm case MD_TEST:
1691c2aa98e2SPeter Wemm /* don't have persistent host status in test mode */
1692c2aa98e2SPeter Wemm HostStatDir = NULL;
16939bd497b8SGregory Neil Shapiro /* FALLTHROUGH */
16949bd497b8SGregory Neil Shapiro
16959bd497b8SGregory Neil Shapiro case MD_CHECKCONFIG:
1696c2aa98e2SPeter Wemm if (Verbose == 0)
1697c2aa98e2SPeter Wemm Verbose = 2;
169840266059SGregory Neil Shapiro BlankEnvelope.e_errormode = EM_PRINT;
169940266059SGregory Neil Shapiro HoldErrs = false;
1700c2aa98e2SPeter Wemm break;
1701c2aa98e2SPeter Wemm
1702c2aa98e2SPeter Wemm case MD_VERIFY:
170340266059SGregory Neil Shapiro BlankEnvelope.e_errormode = EM_PRINT;
170440266059SGregory Neil Shapiro HoldErrs = false;
1705c2aa98e2SPeter Wemm /* arrange to exit cleanly on hangup signal */
170640266059SGregory Neil Shapiro if (sm_signal(SIGHUP, SIG_IGN) == (sigfunc_t) SIG_DFL)
170740266059SGregory Neil Shapiro (void) sm_signal(SIGHUP, intsig);
170840266059SGregory Neil Shapiro if (geteuid() != 0)
170940266059SGregory Neil Shapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
171040266059SGregory Neil Shapiro "Notice: -bv may give misleading output for non-privileged user\n");
1711c2aa98e2SPeter Wemm break;
1712c2aa98e2SPeter Wemm
1713c2aa98e2SPeter Wemm case MD_FGDAEMON:
171440266059SGregory Neil Shapiro run_in_foreground = true;
171540266059SGregory Neil Shapiro set_op_mode(MD_DAEMON);
171606f25ae9SGregory Neil Shapiro /* FALLTHROUGH */
1717c2aa98e2SPeter Wemm
1718c2aa98e2SPeter Wemm case MD_DAEMON:
171940266059SGregory Neil Shapiro vendor_daemon_setup(&BlankEnvelope);
1720c2aa98e2SPeter Wemm
1721c2aa98e2SPeter Wemm /* remove things that don't make sense in daemon mode */
1722c2aa98e2SPeter Wemm FullName = NULL;
172340266059SGregory Neil Shapiro GrabTo = false;
1724c2aa98e2SPeter Wemm
1725c2aa98e2SPeter Wemm /* arrange to restart on hangup signal */
1726c2aa98e2SPeter Wemm if (SaveArgv[0] == NULL || SaveArgv[0][0] != '/')
1727c2aa98e2SPeter Wemm sm_syslog(LOG_WARNING, NOQID,
1728c2aa98e2SPeter Wemm "daemon invoked without full pathname; kill -1 won't work");
1729c2aa98e2SPeter Wemm break;
1730c2aa98e2SPeter Wemm
1731c2aa98e2SPeter Wemm case MD_INITALIAS:
1732c2aa98e2SPeter Wemm Verbose = 2;
173340266059SGregory Neil Shapiro BlankEnvelope.e_errormode = EM_PRINT;
173440266059SGregory Neil Shapiro HoldErrs = false;
173506f25ae9SGregory Neil Shapiro /* FALLTHROUGH */
1736c2aa98e2SPeter Wemm
1737c2aa98e2SPeter Wemm default:
1738c2aa98e2SPeter Wemm /* arrange to exit cleanly on hangup signal */
173940266059SGregory Neil Shapiro if (sm_signal(SIGHUP, SIG_IGN) == (sigfunc_t) SIG_DFL)
174040266059SGregory Neil Shapiro (void) sm_signal(SIGHUP, intsig);
1741c2aa98e2SPeter Wemm break;
1742c2aa98e2SPeter Wemm }
1743c2aa98e2SPeter Wemm
1744c2aa98e2SPeter Wemm /* special considerations for FullName */
1745c2aa98e2SPeter Wemm if (FullName != NULL)
1746c2aa98e2SPeter Wemm {
1747c2aa98e2SPeter Wemm char *full = NULL;
1748c2aa98e2SPeter Wemm
1749c2aa98e2SPeter Wemm /* full names can't have newlines */
1750c2aa98e2SPeter Wemm if (strchr(FullName, '\n') != NULL)
1751c2aa98e2SPeter Wemm {
175240266059SGregory Neil Shapiro full = newstr(denlstring(FullName, true, true));
1753602a2b1bSGregory Neil Shapiro FullName = full;
1754c2aa98e2SPeter Wemm }
1755602a2b1bSGregory Neil Shapiro
1756c2aa98e2SPeter Wemm /* check for characters that may have to be quoted */
1757c2aa98e2SPeter Wemm if (!rfc822_string(FullName))
1758c2aa98e2SPeter Wemm {
1759c2aa98e2SPeter Wemm /*
1760c2aa98e2SPeter Wemm ** Quote a full name with special characters
1761c2aa98e2SPeter Wemm ** as a comment so crackaddr() doesn't destroy
1762c2aa98e2SPeter Wemm ** the name portion of the address.
1763c2aa98e2SPeter Wemm */
1764602a2b1bSGregory Neil Shapiro
176540266059SGregory Neil Shapiro FullName = addquotes(FullName, NULL);
1766c2aa98e2SPeter Wemm if (full != NULL)
176740266059SGregory Neil Shapiro sm_free(full); /* XXX */
1768c2aa98e2SPeter Wemm }
1769c2aa98e2SPeter Wemm }
1770c2aa98e2SPeter Wemm
1771c2aa98e2SPeter Wemm /* do heuristic mode adjustment */
1772c2aa98e2SPeter Wemm if (Verbose)
1773c2aa98e2SPeter Wemm {
1774c2aa98e2SPeter Wemm /* turn off noconnect option */
177540266059SGregory Neil Shapiro setoption('c', "F", true, false, &BlankEnvelope);
1776c2aa98e2SPeter Wemm
1777c2aa98e2SPeter Wemm /* turn on interactive delivery */
177840266059SGregory Neil Shapiro setoption('d', "", true, false, &BlankEnvelope);
1779c2aa98e2SPeter Wemm }
1780c2aa98e2SPeter Wemm
1781065a643dSPeter Wemm #ifdef VENDOR_CODE
1782065a643dSPeter Wemm /* check for vendor mismatch */
1783065a643dSPeter Wemm if (VendorCode != VENDOR_CODE)
1784065a643dSPeter Wemm {
1785065a643dSPeter Wemm message("Warning: .cf file vendor code mismatch: sendmail expects vendor %s, .cf file vendor is %s",
1786065a643dSPeter Wemm getvendor(VENDOR_CODE), getvendor(VendorCode));
1787065a643dSPeter Wemm }
178806f25ae9SGregory Neil Shapiro #endif /* VENDOR_CODE */
1789065a643dSPeter Wemm
1790c2aa98e2SPeter Wemm /* check for out of date configuration level */
1791c2aa98e2SPeter Wemm if (ConfigLevel < MAXCONFIGLEVEL)
1792c2aa98e2SPeter Wemm {
1793c2aa98e2SPeter Wemm message("Warning: .cf file is out of date: sendmail %s supports version %d, .cf file is version %d",
1794c2aa98e2SPeter Wemm Version, MAXCONFIGLEVEL, ConfigLevel);
1795c2aa98e2SPeter Wemm }
1796c2aa98e2SPeter Wemm
1797c2aa98e2SPeter Wemm if (ConfigLevel < 3)
179840266059SGregory Neil Shapiro UseErrorsTo = true;
1799c2aa98e2SPeter Wemm
1800c2aa98e2SPeter Wemm /* set options that were previous macros */
1801c2aa98e2SPeter Wemm if (SmtpGreeting == NULL)
1802c2aa98e2SPeter Wemm {
180340266059SGregory Neil Shapiro if (ConfigLevel < 7 &&
180440266059SGregory Neil Shapiro (p = macvalue('e', &BlankEnvelope)) != NULL)
1805c2aa98e2SPeter Wemm SmtpGreeting = newstr(p);
1806c2aa98e2SPeter Wemm else
1807c2aa98e2SPeter Wemm SmtpGreeting = "\201j Sendmail \201v ready at \201b";
1808c2aa98e2SPeter Wemm }
1809c2aa98e2SPeter Wemm if (UnixFromLine == NULL)
1810c2aa98e2SPeter Wemm {
181140266059SGregory Neil Shapiro if (ConfigLevel < 7 &&
181240266059SGregory Neil Shapiro (p = macvalue('l', &BlankEnvelope)) != NULL)
1813c2aa98e2SPeter Wemm UnixFromLine = newstr(p);
1814c2aa98e2SPeter Wemm else
1815c2aa98e2SPeter Wemm UnixFromLine = "From \201g \201d";
1816c2aa98e2SPeter Wemm }
181706f25ae9SGregory Neil Shapiro SmtpError[0] = '\0';
1818c2aa98e2SPeter Wemm
1819c2aa98e2SPeter Wemm /* our name for SMTP codes */
1820d0cef73dSGregory Neil Shapiro expand("\201j", jbuf, sizeof(jbuf), &BlankEnvelope);
1821602a2b1bSGregory Neil Shapiro if (jbuf[0] == '\0')
182240266059SGregory Neil Shapiro PSTRSET(MyHostName, "localhost");
1823602a2b1bSGregory Neil Shapiro else
182440266059SGregory Neil Shapiro PSTRSET(MyHostName, jbuf);
1825602a2b1bSGregory Neil Shapiro if (strchr(MyHostName, '.') == NULL)
1826e92d3f3fSGregory Neil Shapiro message("WARNING: local host name (%s) is not qualified; see cf/README: WHO AM I?",
1827602a2b1bSGregory Neil Shapiro MyHostName);
1828c2aa98e2SPeter Wemm
1829c2aa98e2SPeter Wemm /* make certain that this name is part of the $=w class */
1830c2aa98e2SPeter Wemm setclass('w', MyHostName);
1831c2aa98e2SPeter Wemm
183240266059SGregory Neil Shapiro /* fill in the structure of the *default* queue */
183340266059SGregory Neil Shapiro st = stab("mqueue", ST_QUEUE, ST_FIND);
183440266059SGregory Neil Shapiro if (st == NULL)
183540266059SGregory Neil Shapiro syserr("No default queue (mqueue) defined");
183640266059SGregory Neil Shapiro else
183740266059SGregory Neil Shapiro set_def_queueval(st->s_quegrp, true);
183840266059SGregory Neil Shapiro
1839c2aa98e2SPeter Wemm /* the indices of built-in mailers */
1840c2aa98e2SPeter Wemm st = stab("local", ST_MAILER, ST_FIND);
1841c2aa98e2SPeter Wemm if (st != NULL)
1842c2aa98e2SPeter Wemm LocalMailer = st->s_mailer;
1843c2aa98e2SPeter Wemm else if (OpMode != MD_TEST || !warn_C_flag)
1844c2aa98e2SPeter Wemm syserr("No local mailer defined");
1845c2aa98e2SPeter Wemm
1846c2aa98e2SPeter Wemm st = stab("prog", ST_MAILER, ST_FIND);
1847c2aa98e2SPeter Wemm if (st == NULL)
1848c2aa98e2SPeter Wemm syserr("No prog mailer defined");
1849c2aa98e2SPeter Wemm else
1850c2aa98e2SPeter Wemm {
1851c2aa98e2SPeter Wemm ProgMailer = st->s_mailer;
1852c2aa98e2SPeter Wemm clrbitn(M_MUSER, ProgMailer->m_flags);
1853c2aa98e2SPeter Wemm }
1854c2aa98e2SPeter Wemm
1855c2aa98e2SPeter Wemm st = stab("*file*", ST_MAILER, ST_FIND);
1856c2aa98e2SPeter Wemm if (st == NULL)
1857c2aa98e2SPeter Wemm syserr("No *file* mailer defined");
1858c2aa98e2SPeter Wemm else
1859c2aa98e2SPeter Wemm {
1860c2aa98e2SPeter Wemm FileMailer = st->s_mailer;
1861c2aa98e2SPeter Wemm clrbitn(M_MUSER, FileMailer->m_flags);
1862c2aa98e2SPeter Wemm }
1863c2aa98e2SPeter Wemm
1864c2aa98e2SPeter Wemm st = stab("*include*", ST_MAILER, ST_FIND);
1865c2aa98e2SPeter Wemm if (st == NULL)
1866c2aa98e2SPeter Wemm syserr("No *include* mailer defined");
1867c2aa98e2SPeter Wemm else
1868c2aa98e2SPeter Wemm InclMailer = st->s_mailer;
1869c2aa98e2SPeter Wemm
1870c2aa98e2SPeter Wemm if (ConfigLevel < 6)
1871c2aa98e2SPeter Wemm {
1872c2aa98e2SPeter Wemm /* heuristic tweaking of local mailer for back compat */
1873c2aa98e2SPeter Wemm if (LocalMailer != NULL)
1874c2aa98e2SPeter Wemm {
1875c2aa98e2SPeter Wemm setbitn(M_ALIASABLE, LocalMailer->m_flags);
1876c2aa98e2SPeter Wemm setbitn(M_HASPWENT, LocalMailer->m_flags);
1877c2aa98e2SPeter Wemm setbitn(M_TRYRULESET5, LocalMailer->m_flags);
1878c2aa98e2SPeter Wemm setbitn(M_CHECKINCLUDE, LocalMailer->m_flags);
1879c2aa98e2SPeter Wemm setbitn(M_CHECKPROG, LocalMailer->m_flags);
1880c2aa98e2SPeter Wemm setbitn(M_CHECKFILE, LocalMailer->m_flags);
1881c2aa98e2SPeter Wemm setbitn(M_CHECKUDB, LocalMailer->m_flags);
1882c2aa98e2SPeter Wemm }
1883c2aa98e2SPeter Wemm if (ProgMailer != NULL)
1884c2aa98e2SPeter Wemm setbitn(M_RUNASRCPT, ProgMailer->m_flags);
1885c2aa98e2SPeter Wemm if (FileMailer != NULL)
1886c2aa98e2SPeter Wemm setbitn(M_RUNASRCPT, FileMailer->m_flags);
1887c2aa98e2SPeter Wemm }
1888c2aa98e2SPeter Wemm if (ConfigLevel < 7)
1889c2aa98e2SPeter Wemm {
1890c2aa98e2SPeter Wemm if (LocalMailer != NULL)
1891c2aa98e2SPeter Wemm setbitn(M_VRFY250, LocalMailer->m_flags);
1892c2aa98e2SPeter Wemm if (ProgMailer != NULL)
1893c2aa98e2SPeter Wemm setbitn(M_VRFY250, ProgMailer->m_flags);
1894c2aa98e2SPeter Wemm if (FileMailer != NULL)
1895c2aa98e2SPeter Wemm setbitn(M_VRFY250, FileMailer->m_flags);
1896c2aa98e2SPeter Wemm }
1897c2aa98e2SPeter Wemm
1898c2aa98e2SPeter Wemm /* MIME Content-Types that cannot be transfer encoded */
1899c2aa98e2SPeter Wemm setclass('n', "multipart/signed");
1900c2aa98e2SPeter Wemm
1901c2aa98e2SPeter Wemm /* MIME message/xxx subtypes that can be treated as messages */
1902c2aa98e2SPeter Wemm setclass('s', "rfc822");
19032fb4f839SGregory Neil Shapiro #if USE_EAI
19045b0945b5SGregory Neil Shapiro setclass('s', "global");
19055b0945b5SGregory Neil Shapiro #endif
1906c2aa98e2SPeter Wemm
1907c2aa98e2SPeter Wemm /* MIME Content-Transfer-Encodings that can be encoded */
1908c2aa98e2SPeter Wemm setclass('e', "7bit");
1909c2aa98e2SPeter Wemm setclass('e', "8bit");
1910c2aa98e2SPeter Wemm setclass('e', "binary");
1911c2aa98e2SPeter Wemm
1912c2aa98e2SPeter Wemm #ifdef USE_B_CLASS
1913c2aa98e2SPeter Wemm /* MIME Content-Types that should be treated as binary */
1914c2aa98e2SPeter Wemm setclass('b', "image");
1915c2aa98e2SPeter Wemm setclass('b', "audio");
1916c2aa98e2SPeter Wemm setclass('b', "video");
1917c2aa98e2SPeter Wemm setclass('b', "application/octet-stream");
191806f25ae9SGregory Neil Shapiro #endif /* USE_B_CLASS */
1919c2aa98e2SPeter Wemm
1920065a643dSPeter Wemm /* MIME headers which have fields to check for overflow */
192140266059SGregory Neil Shapiro setclass(macid("{checkMIMEFieldHeaders}"), "content-disposition");
192240266059SGregory Neil Shapiro setclass(macid("{checkMIMEFieldHeaders}"), "content-type");
1923065a643dSPeter Wemm
1924065a643dSPeter Wemm /* MIME headers to check for length overflow */
192540266059SGregory Neil Shapiro setclass(macid("{checkMIMETextHeaders}"), "content-description");
1926065a643dSPeter Wemm
1927065a643dSPeter Wemm /* MIME headers to check for overflow and rebalance */
192840266059SGregory Neil Shapiro setclass(macid("{checkMIMEHeaders}"), "content-disposition");
192940266059SGregory Neil Shapiro setclass(macid("{checkMIMEHeaders}"), "content-id");
193040266059SGregory Neil Shapiro setclass(macid("{checkMIMEHeaders}"), "content-transfer-encoding");
193140266059SGregory Neil Shapiro setclass(macid("{checkMIMEHeaders}"), "content-type");
193240266059SGregory Neil Shapiro setclass(macid("{checkMIMEHeaders}"), "mime-version");
193306f25ae9SGregory Neil Shapiro
193440266059SGregory Neil Shapiro /* Macros to save in the queue file -- don't remove any */
193540266059SGregory Neil Shapiro setclass(macid("{persistentMacros}"), "r");
193640266059SGregory Neil Shapiro setclass(macid("{persistentMacros}"), "s");
193740266059SGregory Neil Shapiro setclass(macid("{persistentMacros}"), "_");
193840266059SGregory Neil Shapiro setclass(macid("{persistentMacros}"), "{if_addr}");
193940266059SGregory Neil Shapiro setclass(macid("{persistentMacros}"), "{daemon_flags}");
1940065a643dSPeter Wemm
1941c2aa98e2SPeter Wemm /* operate in queue directory */
194240266059SGregory Neil Shapiro if (QueueDir == NULL || *QueueDir == '\0')
1943c2aa98e2SPeter Wemm {
1944c2aa98e2SPeter Wemm if (OpMode != MD_TEST)
1945c2aa98e2SPeter Wemm {
1946c2aa98e2SPeter Wemm syserr("QueueDirectory (Q) option must be set");
1947c2aa98e2SPeter Wemm ExitStat = EX_CONFIG;
1948c2aa98e2SPeter Wemm }
1949c2aa98e2SPeter Wemm }
1950c2aa98e2SPeter Wemm else
1951c2aa98e2SPeter Wemm {
195206f25ae9SGregory Neil Shapiro if (OpMode != MD_TEST)
195340266059SGregory Neil Shapiro setup_queues(OpMode == MD_DAEMON);
1954c2aa98e2SPeter Wemm }
1955c2aa98e2SPeter Wemm
1956c2aa98e2SPeter Wemm /* check host status directory for validity */
195740266059SGregory Neil Shapiro if (HostStatDir != NULL && !path_is_dir(HostStatDir, false))
1958c2aa98e2SPeter Wemm {
1959c2aa98e2SPeter Wemm /* cannot use this value */
196040266059SGregory Neil Shapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
196140266059SGregory Neil Shapiro "Warning: Cannot use HostStatusDirectory = %s: %s\n",
196240266059SGregory Neil Shapiro HostStatDir, sm_errstring(errno));
1963c2aa98e2SPeter Wemm HostStatDir = NULL;
1964c2aa98e2SPeter Wemm }
1965c2aa98e2SPeter Wemm
196640266059SGregory Neil Shapiro if (OpMode == MD_QUEUERUN &&
196740266059SGregory Neil Shapiro RealUid != 0 && bitset(PRIV_RESTRICTQRUN, PrivacyFlags))
1968c2aa98e2SPeter Wemm {
1969c2aa98e2SPeter Wemm struct stat stbuf;
1970c2aa98e2SPeter Wemm
1971c2aa98e2SPeter Wemm /* check to see if we own the queue directory */
1972c2aa98e2SPeter Wemm if (stat(".", &stbuf) < 0)
1973c2aa98e2SPeter Wemm syserr("main: cannot stat %s", QueueDir);
1974c2aa98e2SPeter Wemm if (stbuf.st_uid != RealUid)
1975c2aa98e2SPeter Wemm {
1976c2aa98e2SPeter Wemm /* nope, really a botch */
197740266059SGregory Neil Shapiro HoldErrs = false;
1978c2aa98e2SPeter Wemm usrerr("You do not have permission to process the queue");
197940266059SGregory Neil Shapiro finis(false, true, EX_NOPERM);
198040266059SGregory Neil Shapiro /* NOTREACHED */
1981c2aa98e2SPeter Wemm }
1982c2aa98e2SPeter Wemm }
1983c2aa98e2SPeter Wemm
198440266059SGregory Neil Shapiro #if MILTER
198506f25ae9SGregory Neil Shapiro /* sanity checks on milter filters */
198606f25ae9SGregory Neil Shapiro if (OpMode == MD_DAEMON || OpMode == MD_SMTP)
198740266059SGregory Neil Shapiro {
198840266059SGregory Neil Shapiro milter_config(InputFilterList, InputFilters, MAXFILTERS);
198940266059SGregory Neil Shapiro setup_daemon_milters();
199040266059SGregory Neil Shapiro }
199140266059SGregory Neil Shapiro #endif /* MILTER */
199206f25ae9SGregory Neil Shapiro
199340266059SGregory Neil Shapiro /* Convert queuegroup string to qgrp number */
199440266059SGregory Neil Shapiro if (queuegroup != NULL)
199540266059SGregory Neil Shapiro {
199640266059SGregory Neil Shapiro qgrp = name2qid(queuegroup);
199740266059SGregory Neil Shapiro if (qgrp == NOQGRP)
199840266059SGregory Neil Shapiro {
199940266059SGregory Neil Shapiro HoldErrs = false;
200040266059SGregory Neil Shapiro usrerr("Queue group %s unknown", queuegroup);
200140266059SGregory Neil Shapiro finis(false, true, ExitStat);
200240266059SGregory Neil Shapiro /* NOTREACHED */
200340266059SGregory Neil Shapiro }
200440266059SGregory Neil Shapiro }
200542e5d165SGregory Neil Shapiro
20069bd497b8SGregory Neil Shapiro /* if checking config or have had errors so far, exit now */
20079bd497b8SGregory Neil Shapiro if (OpMode == MD_CHECKCONFIG || (ExitStat != EX_OK && OpMode != MD_TEST))
200840266059SGregory Neil Shapiro {
200940266059SGregory Neil Shapiro finis(false, true, ExitStat);
201040266059SGregory Neil Shapiro /* NOTREACHED */
201140266059SGregory Neil Shapiro }
201240266059SGregory Neil Shapiro
201340266059SGregory Neil Shapiro #if SASL
201440266059SGregory Neil Shapiro /* sendmail specific SASL initialization */
201540266059SGregory Neil Shapiro sm_sasl_init();
20165b0945b5SGregory Neil Shapiro #endif
2017c2aa98e2SPeter Wemm
2018c2aa98e2SPeter Wemm checkfd012("before main() initmaps");
2019c2aa98e2SPeter Wemm
2020c2aa98e2SPeter Wemm /*
2021c2aa98e2SPeter Wemm ** Do operation-mode-dependent initialization.
2022c2aa98e2SPeter Wemm */
2023c2aa98e2SPeter Wemm
2024c2aa98e2SPeter Wemm switch (OpMode)
2025c2aa98e2SPeter Wemm {
2026c2aa98e2SPeter Wemm case MD_PRINT:
2027c2aa98e2SPeter Wemm /* print the queue */
202840266059SGregory Neil Shapiro HoldErrs = false;
20299bd497b8SGregory Neil Shapiro (void) dropenvelope(&BlankEnvelope, true, false);
203040266059SGregory Neil Shapiro (void) sm_signal(SIGPIPE, sigpipe);
203140266059SGregory Neil Shapiro if (qgrp != NOQGRP)
203240266059SGregory Neil Shapiro {
203340266059SGregory Neil Shapiro /* Selecting a particular queue group to run */
203440266059SGregory Neil Shapiro for (j = 0; j < Queue[qgrp]->qg_numqueues; j++)
203540266059SGregory Neil Shapiro {
203640266059SGregory Neil Shapiro if (StopRequest)
203740266059SGregory Neil Shapiro stop_sendmail();
203840266059SGregory Neil Shapiro (void) print_single_queue(qgrp, j);
203940266059SGregory Neil Shapiro }
204040266059SGregory Neil Shapiro finis(false, true, EX_OK);
204140266059SGregory Neil Shapiro /* NOTREACHED */
204240266059SGregory Neil Shapiro }
2043c2aa98e2SPeter Wemm printqueue();
204440266059SGregory Neil Shapiro finis(false, true, EX_OK);
204540266059SGregory Neil Shapiro /* NOTREACHED */
2046065a643dSPeter Wemm break;
2047c2aa98e2SPeter Wemm
204840266059SGregory Neil Shapiro case MD_PRINTNQE:
204940266059SGregory Neil Shapiro /* print number of entries in queue */
20509bd497b8SGregory Neil Shapiro (void) dropenvelope(&BlankEnvelope, true, false);
205140266059SGregory Neil Shapiro (void) sm_signal(SIGPIPE, sigpipe);
205240266059SGregory Neil Shapiro printnqe(smioout, NULL);
205340266059SGregory Neil Shapiro finis(false, true, EX_OK);
205440266059SGregory Neil Shapiro /* NOTREACHED */
205540266059SGregory Neil Shapiro break;
205640266059SGregory Neil Shapiro
205740266059SGregory Neil Shapiro case MD_QUEUERUN:
205840266059SGregory Neil Shapiro /* only handle quarantining here */
205940266059SGregory Neil Shapiro if (quarantining == NULL)
206040266059SGregory Neil Shapiro break;
206140266059SGregory Neil Shapiro
206240266059SGregory Neil Shapiro if (QueueMode != QM_QUARANTINE &&
206340266059SGregory Neil Shapiro QueueMode != QM_NORMAL)
206440266059SGregory Neil Shapiro {
206540266059SGregory Neil Shapiro HoldErrs = false;
206640266059SGregory Neil Shapiro usrerr("Can not use -Q with -q%c", QueueMode);
206740266059SGregory Neil Shapiro ExitStat = EX_USAGE;
206840266059SGregory Neil Shapiro finis(false, true, ExitStat);
206940266059SGregory Neil Shapiro /* NOTREACHED */
207040266059SGregory Neil Shapiro }
207140266059SGregory Neil Shapiro quarantine_queue(quarantining, qgrp);
207240266059SGregory Neil Shapiro finis(false, true, EX_OK);
207340266059SGregory Neil Shapiro break;
207440266059SGregory Neil Shapiro
2075c2aa98e2SPeter Wemm case MD_HOSTSTAT:
207640266059SGregory Neil Shapiro (void) sm_signal(SIGPIPE, sigpipe);
207706f25ae9SGregory Neil Shapiro (void) mci_traverse_persistent(mci_print_persistent, NULL);
207840266059SGregory Neil Shapiro finis(false, true, EX_OK);
207940266059SGregory Neil Shapiro /* NOTREACHED */
2080c2aa98e2SPeter Wemm break;
2081c2aa98e2SPeter Wemm
2082c2aa98e2SPeter Wemm case MD_PURGESTAT:
208306f25ae9SGregory Neil Shapiro (void) mci_traverse_persistent(mci_purge_persistent, NULL);
208440266059SGregory Neil Shapiro finis(false, true, EX_OK);
208540266059SGregory Neil Shapiro /* NOTREACHED */
2086c2aa98e2SPeter Wemm break;
2087c2aa98e2SPeter Wemm
2088c2aa98e2SPeter Wemm case MD_INITALIAS:
2089065a643dSPeter Wemm /* initialize maps */
209006f25ae9SGregory Neil Shapiro initmaps();
209140266059SGregory Neil Shapiro finis(false, true, ExitStat);
209240266059SGregory Neil Shapiro /* NOTREACHED */
2093065a643dSPeter Wemm break;
2094c2aa98e2SPeter Wemm
2095c2aa98e2SPeter Wemm case MD_SMTP:
2096c2aa98e2SPeter Wemm case MD_DAEMON:
2097c2aa98e2SPeter Wemm /* reset DSN parameters */
2098c2aa98e2SPeter Wemm DefaultNotify = QPINGONFAILURE|QPINGONDELAY;
209940266059SGregory Neil Shapiro macdefine(&BlankEnvelope.e_macro, A_PERM,
210040266059SGregory Neil Shapiro macid("{dsn_notify}"), NULL);
210140266059SGregory Neil Shapiro BlankEnvelope.e_envid = NULL;
210240266059SGregory Neil Shapiro macdefine(&BlankEnvelope.e_macro, A_PERM,
210340266059SGregory Neil Shapiro macid("{dsn_envid}"), NULL);
210440266059SGregory Neil Shapiro BlankEnvelope.e_flags &= ~(EF_RET_PARAM|EF_NO_BODY_RETN);
210540266059SGregory Neil Shapiro macdefine(&BlankEnvelope.e_macro, A_PERM,
210640266059SGregory Neil Shapiro macid("{dsn_ret}"), NULL);
2107c2aa98e2SPeter Wemm
2108065a643dSPeter Wemm /* don't open maps for daemon -- done below in child */
2109c2aa98e2SPeter Wemm break;
2110c2aa98e2SPeter Wemm }
2111c2aa98e2SPeter Wemm
2112c2aa98e2SPeter Wemm if (tTd(0, 15))
2113c2aa98e2SPeter Wemm {
2114c2aa98e2SPeter Wemm /* print configuration table (or at least part of it) */
2115c2aa98e2SPeter Wemm if (tTd(0, 90))
2116c2aa98e2SPeter Wemm printrules();
2117c2aa98e2SPeter Wemm for (i = 0; i < MAXMAILERS; i++)
2118c2aa98e2SPeter Wemm {
2119c2aa98e2SPeter Wemm if (Mailer[i] != NULL)
2120e92d3f3fSGregory Neil Shapiro printmailer(sm_debug_file(), Mailer[i]);
2121c2aa98e2SPeter Wemm }
2122c2aa98e2SPeter Wemm }
2123c2aa98e2SPeter Wemm
2124c2aa98e2SPeter Wemm /*
2125c2aa98e2SPeter Wemm ** Switch to the main envelope.
2126c2aa98e2SPeter Wemm */
2127c2aa98e2SPeter Wemm
212840266059SGregory Neil Shapiro CurEnv = newenvelope(&MainEnvelope, &BlankEnvelope,
212940266059SGregory Neil Shapiro sm_rpool_new_x(NULL));
2130c2aa98e2SPeter Wemm MainEnvelope.e_flags = BlankEnvelope.e_flags;
2131c2aa98e2SPeter Wemm
2132c2aa98e2SPeter Wemm /*
2133c2aa98e2SPeter Wemm ** If test mode, read addresses from stdin and process.
2134c2aa98e2SPeter Wemm */
2135c2aa98e2SPeter Wemm
2136c2aa98e2SPeter Wemm if (OpMode == MD_TEST)
2137c2aa98e2SPeter Wemm {
213840266059SGregory Neil Shapiro if (isatty(sm_io_getinfo(smioin, SM_IO_WHAT_FD, NULL)))
2139c2aa98e2SPeter Wemm Verbose = 2;
2140c2aa98e2SPeter Wemm
2141c2aa98e2SPeter Wemm if (Verbose)
2142c2aa98e2SPeter Wemm {
214340266059SGregory Neil Shapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
214440266059SGregory Neil Shapiro "ADDRESS TEST MODE (ruleset 3 NOT automatically invoked)\n");
214540266059SGregory Neil Shapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
214640266059SGregory Neil Shapiro "Enter <ruleset> <address>\n");
2147c2aa98e2SPeter Wemm }
214840266059SGregory Neil Shapiro macdefine(&(MainEnvelope.e_macro), A_PERM,
214940266059SGregory Neil Shapiro macid("{addr_type}"), "e r");
2150c2aa98e2SPeter Wemm for (;;)
2151c2aa98e2SPeter Wemm {
215240266059SGregory Neil Shapiro SM_TRY
215340266059SGregory Neil Shapiro {
215440266059SGregory Neil Shapiro (void) sm_signal(SIGINT, intindebug);
215540266059SGregory Neil Shapiro (void) sm_releasesignal(SIGINT);
2156c2aa98e2SPeter Wemm if (Verbose == 2)
215740266059SGregory Neil Shapiro (void) sm_io_fprintf(smioout,
215840266059SGregory Neil Shapiro SM_TIME_DEFAULT,
215940266059SGregory Neil Shapiro "> ");
216040266059SGregory Neil Shapiro (void) sm_io_flush(smioout, SM_TIME_DEFAULT);
216140266059SGregory Neil Shapiro if (sm_io_fgets(smioin, SM_TIME_DEFAULT, buf,
2162552d4955SGregory Neil Shapiro sizeof(buf)) < 0)
216340266059SGregory Neil Shapiro testmodeline("/quit", &MainEnvelope);
2164c2aa98e2SPeter Wemm p = strchr(buf, '\n');
2165c2aa98e2SPeter Wemm if (p != NULL)
2166c2aa98e2SPeter Wemm *p = '\0';
2167c2aa98e2SPeter Wemm if (Verbose < 2)
216840266059SGregory Neil Shapiro (void) sm_io_fprintf(smioout,
216940266059SGregory Neil Shapiro SM_TIME_DEFAULT,
217040266059SGregory Neil Shapiro "> %s\n", buf);
217140266059SGregory Neil Shapiro testmodeline(buf, &MainEnvelope);
217240266059SGregory Neil Shapiro }
217340266059SGregory Neil Shapiro SM_EXCEPT(exc, "[!F]*")
217440266059SGregory Neil Shapiro {
217540266059SGregory Neil Shapiro /*
217640266059SGregory Neil Shapiro ** 8.10 just prints \n on interrupt.
217740266059SGregory Neil Shapiro ** I'm printing the exception here in case
217840266059SGregory Neil Shapiro ** sendmail is extended to raise additional
217940266059SGregory Neil Shapiro ** exceptions in this context.
218040266059SGregory Neil Shapiro */
218140266059SGregory Neil Shapiro
218240266059SGregory Neil Shapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
218340266059SGregory Neil Shapiro "\n");
218440266059SGregory Neil Shapiro sm_exc_print(exc, smioout);
218540266059SGregory Neil Shapiro }
218640266059SGregory Neil Shapiro SM_END_TRY
2187c2aa98e2SPeter Wemm }
2188c2aa98e2SPeter Wemm }
2189c2aa98e2SPeter Wemm
219006f25ae9SGregory Neil Shapiro #if STARTTLS
219140266059SGregory Neil Shapiro tls_ok = true;
2192d0cef73dSGregory Neil Shapiro if (OpMode == MD_QUEUERUN || OpMode == MD_DELIVER ||
2193d0cef73dSGregory Neil Shapiro OpMode == MD_ARPAFTP)
219440266059SGregory Neil Shapiro {
219540266059SGregory Neil Shapiro /* check whether STARTTLS is turned off for the client */
219640266059SGregory Neil Shapiro if (chkclientmodifiers(D_NOTLS))
219740266059SGregory Neil Shapiro tls_ok = false;
219840266059SGregory Neil Shapiro }
219940266059SGregory Neil Shapiro else if (OpMode == MD_DAEMON || OpMode == MD_FGDAEMON ||
220040266059SGregory Neil Shapiro OpMode == MD_SMTP)
220140266059SGregory Neil Shapiro {
22029bd497b8SGregory Neil Shapiro /* check whether STARTTLS is turned off */
22039bd497b8SGregory Neil Shapiro if (chkdaemonmodifiers(D_NOTLS) && chkclientmodifiers(D_NOTLS))
220440266059SGregory Neil Shapiro tls_ok = false;
220540266059SGregory Neil Shapiro }
220640266059SGregory Neil Shapiro else /* other modes don't need STARTTLS */
220740266059SGregory Neil Shapiro tls_ok = false;
220806f25ae9SGregory Neil Shapiro
220940266059SGregory Neil Shapiro if (tls_ok)
221040266059SGregory Neil Shapiro {
221140266059SGregory Neil Shapiro /* basic TLS initialization */
22125b0945b5SGregory Neil Shapiro j = init_tls_library(FipsMode);
22135b0945b5SGregory Neil Shapiro if (j < 0)
2214552d4955SGregory Neil Shapiro {
2215552d4955SGregory Neil Shapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
22165b0945b5SGregory Neil Shapiro "ERROR: TLS failed to initialize\n");
2217552d4955SGregory Neil Shapiro exit(EX_USAGE);
2218552d4955SGregory Neil Shapiro }
22195b0945b5SGregory Neil Shapiro if (j > 0)
22205b0945b5SGregory Neil Shapiro tls_ok = false;
222140266059SGregory Neil Shapiro }
222240266059SGregory Neil Shapiro
222340266059SGregory Neil Shapiro if (!tls_ok && (OpMode == MD_QUEUERUN || OpMode == MD_DELIVER))
222440266059SGregory Neil Shapiro {
222540266059SGregory Neil Shapiro /* disable TLS for client */
222640266059SGregory Neil Shapiro setclttls(false);
222740266059SGregory Neil Shapiro }
222840266059SGregory Neil Shapiro #endif /* STARTTLS */
222940266059SGregory Neil Shapiro
2230c2aa98e2SPeter Wemm /*
2231c2aa98e2SPeter Wemm ** If collecting stuff from the queue, go start doing that.
2232c2aa98e2SPeter Wemm */
2233c2aa98e2SPeter Wemm
223406f25ae9SGregory Neil Shapiro if (OpMode == MD_QUEUERUN && QueueIntvl == 0)
2235c2aa98e2SPeter Wemm {
223640266059SGregory Neil Shapiro pid_t pid = -1;
223740266059SGregory Neil Shapiro
223806f25ae9SGregory Neil Shapiro #if STARTTLS
223906f25ae9SGregory Neil Shapiro /* init TLS for client, ignore result for now */
224040266059SGregory Neil Shapiro (void) initclttls(tls_ok);
22415b0945b5SGregory Neil Shapiro #endif
224240266059SGregory Neil Shapiro
224340266059SGregory Neil Shapiro /*
224440266059SGregory Neil Shapiro ** The parent process of the caller of runqueue() needs
224540266059SGregory Neil Shapiro ** to stay around for a possible SIGTERM. The SIGTERM will
224640266059SGregory Neil Shapiro ** tell this process that all of the queue runners children
224740266059SGregory Neil Shapiro ** need to be sent SIGTERM as well. At the same time, we
224840266059SGregory Neil Shapiro ** want to return control to the command line. So we do an
224940266059SGregory Neil Shapiro ** extra fork().
225040266059SGregory Neil Shapiro */
225140266059SGregory Neil Shapiro
225240266059SGregory Neil Shapiro if (Verbose || foregroundqueue || (pid = fork()) <= 0)
225340266059SGregory Neil Shapiro {
225440266059SGregory Neil Shapiro /*
225540266059SGregory Neil Shapiro ** If the fork() failed we should still try to do
225640266059SGregory Neil Shapiro ** the queue run. If it succeeded then the child
225740266059SGregory Neil Shapiro ** is going to start the run and wait for all
225840266059SGregory Neil Shapiro ** of the children to finish.
225940266059SGregory Neil Shapiro */
226040266059SGregory Neil Shapiro
226140266059SGregory Neil Shapiro if (pid == 0)
226240266059SGregory Neil Shapiro {
226340266059SGregory Neil Shapiro /* Reset global flags */
226440266059SGregory Neil Shapiro RestartRequest = NULL;
226540266059SGregory Neil Shapiro ShutdownRequest = NULL;
226640266059SGregory Neil Shapiro PendingSignal = 0;
226740266059SGregory Neil Shapiro
226840266059SGregory Neil Shapiro /* disconnect from terminal */
226940266059SGregory Neil Shapiro disconnect(2, CurEnv);
2270c2aa98e2SPeter Wemm }
227140266059SGregory Neil Shapiro
227240266059SGregory Neil Shapiro CurrentPid = getpid();
227340266059SGregory Neil Shapiro if (qgrp != NOQGRP)
227440266059SGregory Neil Shapiro {
227513bd1963SGregory Neil Shapiro int rwgflags = RWG_NONE;
227613bd1963SGregory Neil Shapiro
227740266059SGregory Neil Shapiro /*
227840266059SGregory Neil Shapiro ** To run a specific queue group mark it to
227940266059SGregory Neil Shapiro ** be run, select the work group it's in and
228040266059SGregory Neil Shapiro ** increment the work counter.
228140266059SGregory Neil Shapiro */
228240266059SGregory Neil Shapiro
2283605302a5SGregory Neil Shapiro for (i = 0; i < NumQueue && Queue[i] != NULL;
2284605302a5SGregory Neil Shapiro i++)
2285605302a5SGregory Neil Shapiro Queue[i]->qg_nextrun = (time_t) -1;
2286605302a5SGregory Neil Shapiro Queue[qgrp]->qg_nextrun = 0;
228713bd1963SGregory Neil Shapiro if (Verbose)
228813bd1963SGregory Neil Shapiro rwgflags |= RWG_VERBOSE;
228913bd1963SGregory Neil Shapiro if (queuepersistent)
229013bd1963SGregory Neil Shapiro rwgflags |= RWG_PERSISTENT;
229113bd1963SGregory Neil Shapiro rwgflags |= RWG_FORCE;
229240266059SGregory Neil Shapiro (void) run_work_group(Queue[qgrp]->qg_wgrp,
229313bd1963SGregory Neil Shapiro rwgflags);
229440266059SGregory Neil Shapiro }
229540266059SGregory Neil Shapiro else
229640266059SGregory Neil Shapiro (void) runqueue(false, Verbose,
229740266059SGregory Neil Shapiro queuepersistent, true);
229840266059SGregory Neil Shapiro
229940266059SGregory Neil Shapiro /* set the title to make it easier to find */
230040266059SGregory Neil Shapiro sm_setproctitle(true, CurEnv, "Queue control");
230140266059SGregory Neil Shapiro (void) sm_signal(SIGCHLD, SIG_DFL);
230240266059SGregory Neil Shapiro while (CurChildren > 0)
230340266059SGregory Neil Shapiro {
230440266059SGregory Neil Shapiro int status;
230540266059SGregory Neil Shapiro pid_t ret;
230640266059SGregory Neil Shapiro
2307323f6dcbSGregory Neil Shapiro errno = 0;
230840266059SGregory Neil Shapiro while ((ret = sm_wait(&status)) <= 0)
2309323f6dcbSGregory Neil Shapiro {
2310323f6dcbSGregory Neil Shapiro if (errno == ECHILD)
2311323f6dcbSGregory Neil Shapiro {
2312323f6dcbSGregory Neil Shapiro /*
2313323f6dcbSGregory Neil Shapiro ** Oops... something got messed
2314323f6dcbSGregory Neil Shapiro ** up really bad. Waiting for
2315323f6dcbSGregory Neil Shapiro ** non-existent children
2316323f6dcbSGregory Neil Shapiro ** shouldn't happen. Let's get
2317323f6dcbSGregory Neil Shapiro ** out of here.
2318323f6dcbSGregory Neil Shapiro */
2319323f6dcbSGregory Neil Shapiro
2320323f6dcbSGregory Neil Shapiro CurChildren = 0;
2321323f6dcbSGregory Neil Shapiro break;
2322323f6dcbSGregory Neil Shapiro }
232340266059SGregory Neil Shapiro continue;
2324323f6dcbSGregory Neil Shapiro }
2325323f6dcbSGregory Neil Shapiro
2326323f6dcbSGregory Neil Shapiro /* something is really really wrong */
2327323f6dcbSGregory Neil Shapiro if (errno == ECHILD)
2328323f6dcbSGregory Neil Shapiro {
2329323f6dcbSGregory Neil Shapiro sm_syslog(LOG_ERR, NOQID,
2330323f6dcbSGregory Neil Shapiro "queue control process: lost all children: wait returned ECHILD");
2331323f6dcbSGregory Neil Shapiro break;
2332323f6dcbSGregory Neil Shapiro }
233340266059SGregory Neil Shapiro
233440266059SGregory Neil Shapiro /* Only drop when a child gives status */
233540266059SGregory Neil Shapiro if (WIFSTOPPED(status))
233640266059SGregory Neil Shapiro continue;
233740266059SGregory Neil Shapiro
233840266059SGregory Neil Shapiro proc_list_drop(ret, status, NULL);
233940266059SGregory Neil Shapiro }
234040266059SGregory Neil Shapiro }
234140266059SGregory Neil Shapiro finis(true, true, ExitStat);
234240266059SGregory Neil Shapiro /* NOTREACHED */
234340266059SGregory Neil Shapiro }
2344c2aa98e2SPeter Wemm
2345193538b7SGregory Neil Shapiro #if SASL
2346193538b7SGregory Neil Shapiro if (OpMode == MD_SMTP || OpMode == MD_DAEMON)
2347193538b7SGregory Neil Shapiro {
234840266059SGregory Neil Shapiro /* check whether AUTH is turned off for the server */
234940266059SGregory Neil Shapiro if (!chkdaemonmodifiers(D_NOAUTH) &&
235040266059SGregory Neil Shapiro (i = sasl_server_init(srvcallbacks, "Sendmail")) != SASL_OK)
2351193538b7SGregory Neil Shapiro syserr("!sasl_server_init failed! [%s]",
2352193538b7SGregory Neil Shapiro sasl_errstring(i, NULL, NULL));
2353193538b7SGregory Neil Shapiro }
2354193538b7SGregory Neil Shapiro #endif /* SASL */
2355193538b7SGregory Neil Shapiro
23562fb4f839SGregory Neil Shapiro #if _FFR_DMTRIGGER
23572fb4f839SGregory Neil Shapiro if (OpMode == MD_DAEMON && SM_TRIGGER == BlankEnvelope.e_sendmode)
23582fb4f839SGregory Neil Shapiro {
23592fb4f839SGregory Neil Shapiro i = sm_notify_init(0);
23602fb4f839SGregory Neil Shapiro if (i != 0)
23612fb4f839SGregory Neil Shapiro syserr("sm_notify_init() failed=%d", i);
23622fb4f839SGregory Neil Shapiro }
23632fb4f839SGregory Neil Shapiro #endif
23642fb4f839SGregory Neil Shapiro
236540266059SGregory Neil Shapiro if (OpMode == MD_SMTP)
236640266059SGregory Neil Shapiro {
236740266059SGregory Neil Shapiro proc_list_add(CurrentPid, "Sendmail SMTP Agent",
2368e92d3f3fSGregory Neil Shapiro PROC_DAEMON, 0, -1, NULL);
236940266059SGregory Neil Shapiro
237040266059SGregory Neil Shapiro /* clean up background delivery children */
237140266059SGregory Neil Shapiro (void) sm_signal(SIGCHLD, reapchild);
237240266059SGregory Neil Shapiro }
237340266059SGregory Neil Shapiro
2374c2aa98e2SPeter Wemm /*
2375c2aa98e2SPeter Wemm ** If a daemon, wait for a request.
23762fb4f839SGregory Neil Shapiro ** getrequests() will return in a child (unless -d93.100 is used).
23772fb4f839SGregory Neil Shapiro ** If we should also be processing the queue,
23782fb4f839SGregory Neil Shapiro ** start doing it in background.
2379c2aa98e2SPeter Wemm ** We check for any errors that might have happened
2380c2aa98e2SPeter Wemm ** during startup.
2381c2aa98e2SPeter Wemm */
2382c2aa98e2SPeter Wemm
2383739ac4d4SGregory Neil Shapiro if (OpMode == MD_DAEMON || QueueIntvl > 0)
2384c2aa98e2SPeter Wemm {
2385c2aa98e2SPeter Wemm char dtype[200];
2386c2aa98e2SPeter Wemm
23873a3ef73dSGregory Neil Shapiro /* avoid cleanup in finis(), DaemonPid will be set below */
23883a3ef73dSGregory Neil Shapiro DaemonPid = 0;
2389c2aa98e2SPeter Wemm if (!run_in_foreground && !tTd(99, 100))
2390c2aa98e2SPeter Wemm {
2391c2aa98e2SPeter Wemm /* put us in background */
2392c2aa98e2SPeter Wemm i = fork();
2393c2aa98e2SPeter Wemm if (i < 0)
2394c2aa98e2SPeter Wemm syserr("daemon: cannot fork");
2395c2aa98e2SPeter Wemm if (i != 0)
239640266059SGregory Neil Shapiro {
239740266059SGregory Neil Shapiro finis(false, true, EX_OK);
239840266059SGregory Neil Shapiro /* NOTREACHED */
239940266059SGregory Neil Shapiro }
240040266059SGregory Neil Shapiro
240140266059SGregory Neil Shapiro /*
240240266059SGregory Neil Shapiro ** Initialize exception stack and default exception
240340266059SGregory Neil Shapiro ** handler for child process.
240440266059SGregory Neil Shapiro */
240540266059SGregory Neil Shapiro
240640266059SGregory Neil Shapiro /* Reset global flags */
240740266059SGregory Neil Shapiro RestartRequest = NULL;
240840266059SGregory Neil Shapiro RestartWorkGroup = false;
240940266059SGregory Neil Shapiro ShutdownRequest = NULL;
241040266059SGregory Neil Shapiro PendingSignal = 0;
241140266059SGregory Neil Shapiro CurrentPid = getpid();
241240266059SGregory Neil Shapiro
241340266059SGregory Neil Shapiro sm_exc_newthread(fatal_error);
2414c2aa98e2SPeter Wemm
2415c2aa98e2SPeter Wemm /* disconnect from our controlling tty */
241640266059SGregory Neil Shapiro disconnect(2, &MainEnvelope);
2417c2aa98e2SPeter Wemm }
2418c2aa98e2SPeter Wemm
2419c2aa98e2SPeter Wemm dtype[0] = '\0';
2420c2aa98e2SPeter Wemm if (OpMode == MD_DAEMON)
24213a3ef73dSGregory Neil Shapiro {
2422d0cef73dSGregory Neil Shapiro (void) sm_strlcat(dtype, "+SMTP", sizeof(dtype));
24233a3ef73dSGregory Neil Shapiro DaemonPid = CurrentPid;
24243a3ef73dSGregory Neil Shapiro }
2425739ac4d4SGregory Neil Shapiro if (QueueIntvl > 0)
2426c2aa98e2SPeter Wemm {
242740266059SGregory Neil Shapiro (void) sm_strlcat2(dtype,
242840266059SGregory Neil Shapiro queuepersistent
242940266059SGregory Neil Shapiro ? "+persistent-queueing@"
243040266059SGregory Neil Shapiro : "+queueing@",
243140266059SGregory Neil Shapiro pintvl(QueueIntvl, true),
2432d0cef73dSGregory Neil Shapiro sizeof(dtype));
2433c2aa98e2SPeter Wemm }
2434c2aa98e2SPeter Wemm if (tTd(0, 1))
2435d0cef73dSGregory Neil Shapiro (void) sm_strlcat(dtype, "+debugging", sizeof(dtype));
2436c2aa98e2SPeter Wemm
2437c2aa98e2SPeter Wemm sm_syslog(LOG_INFO, NOQID,
2438c2aa98e2SPeter Wemm "starting daemon (%s): %s", Version, dtype + 1);
243940266059SGregory Neil Shapiro #if XLA
2440c2aa98e2SPeter Wemm xla_create_file();
24415b0945b5SGregory Neil Shapiro #endif
244206f25ae9SGregory Neil Shapiro
244306f25ae9SGregory Neil Shapiro /* save daemon type in a macro for possible PidFile use */
244440266059SGregory Neil Shapiro macdefine(&BlankEnvelope.e_macro, A_TEMP,
244540266059SGregory Neil Shapiro macid("{daemon_info}"), dtype + 1);
244606f25ae9SGregory Neil Shapiro
244706f25ae9SGregory Neil Shapiro /* save queue interval in a macro for possible PidFile use */
244840266059SGregory Neil Shapiro macdefine(&MainEnvelope.e_macro, A_TEMP,
244940266059SGregory Neil Shapiro macid("{queue_interval}"), pintvl(QueueIntvl, true));
2450c2aa98e2SPeter Wemm
245140266059SGregory Neil Shapiro /* workaround: can't seem to release the signal in the parent */
245240266059SGregory Neil Shapiro (void) sm_signal(SIGHUP, sighup);
245340266059SGregory Neil Shapiro (void) sm_releasesignal(SIGHUP);
245440266059SGregory Neil Shapiro (void) sm_signal(SIGTERM, sigterm);
245540266059SGregory Neil Shapiro
24562fb4f839SGregory Neil Shapiro #if _FFR_DMTRIGGER
24572fb4f839SGregory Neil Shapiro if (SM_TRIGGER == BlankEnvelope.e_sendmode)
24582fb4f839SGregory Neil Shapiro qm();
24592fb4f839SGregory Neil Shapiro #endif
24602fb4f839SGregory Neil Shapiro
2461739ac4d4SGregory Neil Shapiro if (QueueIntvl > 0)
2462c2aa98e2SPeter Wemm {
2463ffb83623SGregory Neil Shapiro #if _FFR_RUNPQG
2464ffb83623SGregory Neil Shapiro if (qgrp != NOQGRP)
2465ffb83623SGregory Neil Shapiro {
2466ffb83623SGregory Neil Shapiro int rwgflags = RWG_NONE;
2467ffb83623SGregory Neil Shapiro
2468ffb83623SGregory Neil Shapiro /*
2469ffb83623SGregory Neil Shapiro ** To run a specific queue group mark it to
2470ffb83623SGregory Neil Shapiro ** be run, select the work group it's in and
2471ffb83623SGregory Neil Shapiro ** increment the work counter.
2472ffb83623SGregory Neil Shapiro */
2473ffb83623SGregory Neil Shapiro
2474ffb83623SGregory Neil Shapiro for (i = 0; i < NumQueue && Queue[i] != NULL;
2475ffb83623SGregory Neil Shapiro i++)
2476ffb83623SGregory Neil Shapiro Queue[i]->qg_nextrun = (time_t) -1;
2477ffb83623SGregory Neil Shapiro Queue[qgrp]->qg_nextrun = 0;
2478ffb83623SGregory Neil Shapiro if (Verbose)
2479ffb83623SGregory Neil Shapiro rwgflags |= RWG_VERBOSE;
2480ffb83623SGregory Neil Shapiro if (queuepersistent)
2481ffb83623SGregory Neil Shapiro rwgflags |= RWG_PERSISTENT;
2482ffb83623SGregory Neil Shapiro rwgflags |= RWG_FORCE;
2483ffb83623SGregory Neil Shapiro (void) run_work_group(Queue[qgrp]->qg_wgrp,
2484ffb83623SGregory Neil Shapiro rwgflags);
2485ffb83623SGregory Neil Shapiro }
2486ffb83623SGregory Neil Shapiro else
2487ffb83623SGregory Neil Shapiro #endif /* _FFR_RUNPQG */
2488ffb83623SGregory Neil Shapiro (void) runqueue(true, false, queuepersistent,
2489ffb83623SGregory Neil Shapiro true);
249040266059SGregory Neil Shapiro
249140266059SGregory Neil Shapiro /*
249240266059SGregory Neil Shapiro ** If queuepersistent but not in daemon mode then
249340266059SGregory Neil Shapiro ** we're going to do the queue runner monitoring here.
249440266059SGregory Neil Shapiro ** If in daemon mode then the monitoring will happen
249540266059SGregory Neil Shapiro ** elsewhere.
249640266059SGregory Neil Shapiro */
249740266059SGregory Neil Shapiro
249840266059SGregory Neil Shapiro if (OpMode != MD_DAEMON && queuepersistent)
249940266059SGregory Neil Shapiro {
2500e92d3f3fSGregory Neil Shapiro /*
2501e92d3f3fSGregory Neil Shapiro ** Write the pid to file
2502e92d3f3fSGregory Neil Shapiro ** XXX Overwrites sendmail.pid
2503e92d3f3fSGregory Neil Shapiro */
2504e92d3f3fSGregory Neil Shapiro
2505e92d3f3fSGregory Neil Shapiro log_sendmail_pid(&MainEnvelope);
2506e92d3f3fSGregory Neil Shapiro
250740266059SGregory Neil Shapiro /* set the title to make it easier to find */
250840266059SGregory Neil Shapiro sm_setproctitle(true, CurEnv, "Queue control");
250940266059SGregory Neil Shapiro (void) sm_signal(SIGCHLD, SIG_DFL);
251040266059SGregory Neil Shapiro while (CurChildren > 0)
251140266059SGregory Neil Shapiro {
251240266059SGregory Neil Shapiro int status;
251340266059SGregory Neil Shapiro pid_t ret;
251440266059SGregory Neil Shapiro int group;
251540266059SGregory Neil Shapiro
2516a7ec597cSGregory Neil Shapiro CHECK_RESTART;
2517323f6dcbSGregory Neil Shapiro errno = 0;
251840266059SGregory Neil Shapiro while ((ret = sm_wait(&status)) <= 0)
2519323f6dcbSGregory Neil Shapiro {
2520323f6dcbSGregory Neil Shapiro /*
2521323f6dcbSGregory Neil Shapiro ** Waiting for non-existent
2522323f6dcbSGregory Neil Shapiro ** children shouldn't happen.
2523323f6dcbSGregory Neil Shapiro ** Let's get out of here if
2524323f6dcbSGregory Neil Shapiro ** it occurs.
2525323f6dcbSGregory Neil Shapiro */
2526323f6dcbSGregory Neil Shapiro
2527323f6dcbSGregory Neil Shapiro if (errno == ECHILD)
2528323f6dcbSGregory Neil Shapiro {
2529323f6dcbSGregory Neil Shapiro CurChildren = 0;
2530323f6dcbSGregory Neil Shapiro break;
2531323f6dcbSGregory Neil Shapiro }
253240266059SGregory Neil Shapiro continue;
2533323f6dcbSGregory Neil Shapiro }
2534323f6dcbSGregory Neil Shapiro
2535323f6dcbSGregory Neil Shapiro /* something is really really wrong */
2536323f6dcbSGregory Neil Shapiro if (errno == ECHILD)
2537323f6dcbSGregory Neil Shapiro {
2538323f6dcbSGregory Neil Shapiro sm_syslog(LOG_ERR, NOQID,
2539323f6dcbSGregory Neil Shapiro "persistent queue runner control process: lost all children: wait returned ECHILD");
2540323f6dcbSGregory Neil Shapiro break;
2541323f6dcbSGregory Neil Shapiro }
254240266059SGregory Neil Shapiro
254340266059SGregory Neil Shapiro if (WIFSTOPPED(status))
254440266059SGregory Neil Shapiro continue;
254540266059SGregory Neil Shapiro
254640266059SGregory Neil Shapiro /* Probe only on a child status */
254740266059SGregory Neil Shapiro proc_list_drop(ret, status, &group);
254840266059SGregory Neil Shapiro
254940266059SGregory Neil Shapiro if (WIFSIGNALED(status))
255040266059SGregory Neil Shapiro {
255140266059SGregory Neil Shapiro if (WCOREDUMP(status))
255240266059SGregory Neil Shapiro {
255340266059SGregory Neil Shapiro sm_syslog(LOG_ERR, NOQID,
255440266059SGregory Neil Shapiro "persistent queue runner=%d core dumped, signal=%d",
255540266059SGregory Neil Shapiro group, WTERMSIG(status));
255640266059SGregory Neil Shapiro
2557a7ec597cSGregory Neil Shapiro /* don't restart this */
2558a7ec597cSGregory Neil Shapiro mark_work_group_restart(
2559a7ec597cSGregory Neil Shapiro group, -1);
256040266059SGregory Neil Shapiro continue;
256140266059SGregory Neil Shapiro }
256240266059SGregory Neil Shapiro
256340266059SGregory Neil Shapiro sm_syslog(LOG_ERR, NOQID,
2564d0cef73dSGregory Neil Shapiro "persistent queue runner=%d died, pid=%ld, signal=%d",
2565d0cef73dSGregory Neil Shapiro group, (long) ret,
2566d0cef73dSGregory Neil Shapiro WTERMSIG(status));
256740266059SGregory Neil Shapiro }
256840266059SGregory Neil Shapiro
256940266059SGregory Neil Shapiro /*
257040266059SGregory Neil Shapiro ** When debugging active, don't
257140266059SGregory Neil Shapiro ** restart the persistent queues.
257240266059SGregory Neil Shapiro ** But do log this as info.
257340266059SGregory Neil Shapiro */
257440266059SGregory Neil Shapiro
257540266059SGregory Neil Shapiro if (sm_debug_active(&DebugNoPRestart,
257640266059SGregory Neil Shapiro 1))
257740266059SGregory Neil Shapiro {
257840266059SGregory Neil Shapiro sm_syslog(LOG_DEBUG, NOQID,
257940266059SGregory Neil Shapiro "persistent queue runner=%d, exited",
258040266059SGregory Neil Shapiro group);
2581a7ec597cSGregory Neil Shapiro mark_work_group_restart(group,
2582a7ec597cSGregory Neil Shapiro -1);
258340266059SGregory Neil Shapiro }
2584d0cef73dSGregory Neil Shapiro CHECK_RESTART;
258540266059SGregory Neil Shapiro }
258640266059SGregory Neil Shapiro finis(true, true, ExitStat);
258740266059SGregory Neil Shapiro /* NOTREACHED */
258840266059SGregory Neil Shapiro }
258940266059SGregory Neil Shapiro
2590c2aa98e2SPeter Wemm if (OpMode != MD_DAEMON)
2591c2aa98e2SPeter Wemm {
259240266059SGregory Neil Shapiro char qtype[200];
259340266059SGregory Neil Shapiro
259440266059SGregory Neil Shapiro /*
259540266059SGregory Neil Shapiro ** Write the pid to file
259640266059SGregory Neil Shapiro ** XXX Overwrites sendmail.pid
259740266059SGregory Neil Shapiro */
259840266059SGregory Neil Shapiro
259940266059SGregory Neil Shapiro log_sendmail_pid(&MainEnvelope);
260040266059SGregory Neil Shapiro
260140266059SGregory Neil Shapiro /* set the title to make it easier to find */
260240266059SGregory Neil Shapiro qtype[0] = '\0';
2603d0cef73dSGregory Neil Shapiro (void) sm_strlcpyn(qtype, sizeof(qtype), 4,
260440266059SGregory Neil Shapiro "Queue runner@",
260540266059SGregory Neil Shapiro pintvl(QueueIntvl, true),
260640266059SGregory Neil Shapiro " for ",
260740266059SGregory Neil Shapiro QueueDir);
260840266059SGregory Neil Shapiro sm_setproctitle(true, CurEnv, qtype);
2609c2aa98e2SPeter Wemm for (;;)
2610c2aa98e2SPeter Wemm {
261106f25ae9SGregory Neil Shapiro (void) pause();
2612e92d3f3fSGregory Neil Shapiro
2613a7ec597cSGregory Neil Shapiro CHECK_RESTART;
2614e92d3f3fSGregory Neil Shapiro
261540266059SGregory Neil Shapiro if (doqueuerun())
261640266059SGregory Neil Shapiro (void) runqueue(true, false,
261740266059SGregory Neil Shapiro false, false);
261840266059SGregory Neil Shapiro }
261940266059SGregory Neil Shapiro }
262040266059SGregory Neil Shapiro }
26219bd497b8SGregory Neil Shapiro (void) dropenvelope(&MainEnvelope, true, false);
262240266059SGregory Neil Shapiro
262306f25ae9SGregory Neil Shapiro #if STARTTLS
262406f25ae9SGregory Neil Shapiro /* init TLS for server, ignore result for now */
262540266059SGregory Neil Shapiro (void) initsrvtls(tls_ok);
26265b0945b5SGregory Neil Shapiro #endif
262740266059SGregory Neil Shapiro nextreq:
262840266059SGregory Neil Shapiro p_flags = getrequests(&MainEnvelope);
2629c2aa98e2SPeter Wemm
2630c2aa98e2SPeter Wemm /* drop privileges */
263140266059SGregory Neil Shapiro (void) drop_privileges(false);
2632c2aa98e2SPeter Wemm
2633c2aa98e2SPeter Wemm /*
2634c2aa98e2SPeter Wemm ** Get authentication data
263540266059SGregory Neil Shapiro ** Set _ macro in BlankEnvelope before calling newenvelope().
2636c2aa98e2SPeter Wemm */
2637c2aa98e2SPeter Wemm
2638da7d7b9cSGregory Neil Shapiro #if _FFR_XCNCT
2639da7d7b9cSGregory Neil Shapiro if (bitnset(D_XCNCT, *p_flags) || bitnset(D_XCNCT_M, *p_flags))
2640da7d7b9cSGregory Neil Shapiro {
2641da7d7b9cSGregory Neil Shapiro /* copied from getauthinfo() */
2642da7d7b9cSGregory Neil Shapiro if (RealHostName == NULL)
2643da7d7b9cSGregory Neil Shapiro {
2644da7d7b9cSGregory Neil Shapiro RealHostName = newstr(hostnamebyanyaddr(&RealHostAddr));
2645da7d7b9cSGregory Neil Shapiro if (strlen(RealHostName) > MAXNAME)
2646da7d7b9cSGregory Neil Shapiro RealHostName[MAXNAME] = '\0'; /* XXX - 1 ? */
2647da7d7b9cSGregory Neil Shapiro }
2648da7d7b9cSGregory Neil Shapiro snprintf(buf, sizeof(buf), "%s [%s]",
2649da7d7b9cSGregory Neil Shapiro RealHostName, anynet_ntoa(&RealHostAddr));
2650da7d7b9cSGregory Neil Shapiro
2651da7d7b9cSGregory Neil Shapiro forged = bitnset(D_XCNCT_M, *p_flags);
2652da7d7b9cSGregory Neil Shapiro if (forged)
2653da7d7b9cSGregory Neil Shapiro {
2654da7d7b9cSGregory Neil Shapiro (void) sm_strlcat(buf, " (may be forged)",
2655da7d7b9cSGregory Neil Shapiro sizeof(buf));
2656da7d7b9cSGregory Neil Shapiro macdefine(&BlankEnvelope.e_macro, A_PERM,
2657da7d7b9cSGregory Neil Shapiro macid("{client_resolve}"), "FORGED");
2658da7d7b9cSGregory Neil Shapiro }
2659da7d7b9cSGregory Neil Shapiro
2660da7d7b9cSGregory Neil Shapiro /* HACK! variable used only two times right below */
2661da7d7b9cSGregory Neil Shapiro authinfo = buf;
2662da7d7b9cSGregory Neil Shapiro if (tTd(75, 9))
2663da7d7b9cSGregory Neil Shapiro sm_syslog(LOG_INFO, NOQID,
2664d39bd2c1SGregory Neil Shapiro "main: where=not_calling_getauthinfo, RealHostAddr=%s, RealHostName=%s",
2665d39bd2c1SGregory Neil Shapiro anynet_ntoa(&RealHostAddr), RealHostName);
2666da7d7b9cSGregory Neil Shapiro }
2667da7d7b9cSGregory Neil Shapiro else
2668da7d7b9cSGregory Neil Shapiro /* WARNING: "non-braced" else */
2669da7d7b9cSGregory Neil Shapiro #endif /* _FFR_XCNCT */
267040266059SGregory Neil Shapiro authinfo = getauthinfo(sm_io_getinfo(InChannel, SM_IO_WHAT_FD,
267140266059SGregory Neil Shapiro NULL), &forged);
267240266059SGregory Neil Shapiro macdefine(&BlankEnvelope.e_macro, A_TEMP, '_', authinfo);
2673ba00ec3dSGregory Neil Shapiro if (tTd(75, 9))
2674ba00ec3dSGregory Neil Shapiro sm_syslog(LOG_INFO, NOQID,
2675ba00ec3dSGregory Neil Shapiro "main: where=after_getauthinfo, RealHostAddr=%s",
2676ba00ec3dSGregory Neil Shapiro anynet_ntoa(&RealHostAddr));
267740266059SGregory Neil Shapiro
267840266059SGregory Neil Shapiro /* at this point we are in a child: reset state */
267940266059SGregory Neil Shapiro sm_rpool_free(MainEnvelope.e_rpool);
268040266059SGregory Neil Shapiro (void) newenvelope(&MainEnvelope, &MainEnvelope,
268140266059SGregory Neil Shapiro sm_rpool_new_x(NULL));
2682c2aa98e2SPeter Wemm }
2683c2aa98e2SPeter Wemm
268406f25ae9SGregory Neil Shapiro if (LogLevel > 9)
268506f25ae9SGregory Neil Shapiro {
26865b0945b5SGregory Neil Shapiro p = authinfo;
26875b0945b5SGregory Neil Shapiro if (NULL == p)
26885b0945b5SGregory Neil Shapiro {
26895b0945b5SGregory Neil Shapiro if (NULL != RealHostName)
26905b0945b5SGregory Neil Shapiro p = RealHostName;
26915b0945b5SGregory Neil Shapiro else
26925b0945b5SGregory Neil Shapiro p = anynet_ntoa(&RealHostAddr);
26935b0945b5SGregory Neil Shapiro if (NULL == p)
26945b0945b5SGregory Neil Shapiro p = "unknown";
26955b0945b5SGregory Neil Shapiro }
26965b0945b5SGregory Neil Shapiro
269706f25ae9SGregory Neil Shapiro /* log connection information */
26985b0945b5SGregory Neil Shapiro sm_syslog(LOG_INFO, NULL, "connect from %s", p);
269906f25ae9SGregory Neil Shapiro }
270006f25ae9SGregory Neil Shapiro
2701c2aa98e2SPeter Wemm /*
2702c2aa98e2SPeter Wemm ** If running SMTP protocol, start collecting and executing
2703c2aa98e2SPeter Wemm ** commands. This will never return.
2704c2aa98e2SPeter Wemm */
2705c2aa98e2SPeter Wemm
2706c2aa98e2SPeter Wemm if (OpMode == MD_SMTP || OpMode == MD_DAEMON)
2707c2aa98e2SPeter Wemm {
2708c2aa98e2SPeter Wemm char pbuf[20];
2709c2aa98e2SPeter Wemm
2710c2aa98e2SPeter Wemm /*
2711c2aa98e2SPeter Wemm ** Save some macros for check_* rulesets.
2712c2aa98e2SPeter Wemm */
2713c2aa98e2SPeter Wemm
2714c2aa98e2SPeter Wemm if (forged)
2715c2aa98e2SPeter Wemm {
2716c2aa98e2SPeter Wemm char ipbuf[103];
2717c2aa98e2SPeter Wemm
2718d0cef73dSGregory Neil Shapiro (void) sm_snprintf(ipbuf, sizeof(ipbuf), "[%.100s]",
271906f25ae9SGregory Neil Shapiro anynet_ntoa(&RealHostAddr));
272040266059SGregory Neil Shapiro macdefine(&BlankEnvelope.e_macro, A_TEMP,
272140266059SGregory Neil Shapiro macid("{client_name}"), ipbuf);
2722c2aa98e2SPeter Wemm }
2723c2aa98e2SPeter Wemm else
272440266059SGregory Neil Shapiro macdefine(&BlankEnvelope.e_macro, A_PERM,
272540266059SGregory Neil Shapiro macid("{client_name}"), RealHostName);
2726e92d3f3fSGregory Neil Shapiro macdefine(&BlankEnvelope.e_macro, A_PERM,
2727e92d3f3fSGregory Neil Shapiro macid("{client_ptr}"), RealHostName);
272840266059SGregory Neil Shapiro macdefine(&BlankEnvelope.e_macro, A_TEMP,
272940266059SGregory Neil Shapiro macid("{client_addr}"), anynet_ntoa(&RealHostAddr));
273040266059SGregory Neil Shapiro sm_getla();
2731c2aa98e2SPeter Wemm
273206f25ae9SGregory Neil Shapiro switch (RealHostAddr.sa.sa_family)
273306f25ae9SGregory Neil Shapiro {
273406f25ae9SGregory Neil Shapiro #if NETINET
273506f25ae9SGregory Neil Shapiro case AF_INET:
2736d0cef73dSGregory Neil Shapiro (void) sm_snprintf(pbuf, sizeof(pbuf), "%d",
2737da7d7b9cSGregory Neil Shapiro ntohs(RealHostAddr.sin.sin_port));
273806f25ae9SGregory Neil Shapiro break;
273906f25ae9SGregory Neil Shapiro #endif /* NETINET */
274006f25ae9SGregory Neil Shapiro #if NETINET6
274106f25ae9SGregory Neil Shapiro case AF_INET6:
2742d0cef73dSGregory Neil Shapiro (void) sm_snprintf(pbuf, sizeof(pbuf), "%d",
2743da7d7b9cSGregory Neil Shapiro ntohs(RealHostAddr.sin6.sin6_port));
274406f25ae9SGregory Neil Shapiro break;
274506f25ae9SGregory Neil Shapiro #endif /* NETINET6 */
274606f25ae9SGregory Neil Shapiro default:
2747d0cef73dSGregory Neil Shapiro (void) sm_snprintf(pbuf, sizeof(pbuf), "0");
274806f25ae9SGregory Neil Shapiro break;
274906f25ae9SGregory Neil Shapiro }
275040266059SGregory Neil Shapiro macdefine(&BlankEnvelope.e_macro, A_TEMP,
275140266059SGregory Neil Shapiro macid("{client_port}"), pbuf);
275206f25ae9SGregory Neil Shapiro
2753c2aa98e2SPeter Wemm if (OpMode == MD_DAEMON)
2754c2aa98e2SPeter Wemm {
2755d0cef73dSGregory Neil Shapiro ENVELOPE *saved_env;
2756d0cef73dSGregory Neil Shapiro
2757c2aa98e2SPeter Wemm /* validate the connection */
275840266059SGregory Neil Shapiro HoldErrs = true;
2759d0cef73dSGregory Neil Shapiro saved_env = CurEnv;
2760d0cef73dSGregory Neil Shapiro CurEnv = &BlankEnvelope;
2761c2aa98e2SPeter Wemm nullserver = validate_connection(&RealHostAddr,
2762e92d3f3fSGregory Neil Shapiro macvalue(macid("{client_name}"),
2763d0cef73dSGregory Neil Shapiro &BlankEnvelope),
2764d0cef73dSGregory Neil Shapiro &BlankEnvelope);
2765d0cef73dSGregory Neil Shapiro if (bitset(EF_DISCARD, BlankEnvelope.e_flags))
2766d0cef73dSGregory Neil Shapiro MainEnvelope.e_flags |= EF_DISCARD;
2767d0cef73dSGregory Neil Shapiro CurEnv = saved_env;
276840266059SGregory Neil Shapiro HoldErrs = false;
2769c2aa98e2SPeter Wemm }
277006f25ae9SGregory Neil Shapiro else if (p_flags == NULL)
277106f25ae9SGregory Neil Shapiro {
2772d0cef73dSGregory Neil Shapiro p_flags = (BITMAP256 *) xalloc(sizeof(*p_flags));
277306f25ae9SGregory Neil Shapiro clrbitmap(p_flags);
277406f25ae9SGregory Neil Shapiro }
277506f25ae9SGregory Neil Shapiro #if STARTTLS
277606f25ae9SGregory Neil Shapiro if (OpMode == MD_SMTP)
277740266059SGregory Neil Shapiro (void) initsrvtls(tls_ok);
27785b0945b5SGregory Neil Shapiro #endif
2779193538b7SGregory Neil Shapiro
278040266059SGregory Neil Shapiro /* turn off profiling */
278140266059SGregory Neil Shapiro SM_PROF(1);
278240266059SGregory Neil Shapiro smtp(nullserver, *p_flags, &MainEnvelope);
278313bd1963SGregory Neil Shapiro
278413bd1963SGregory Neil Shapiro if (tTd(93, 100))
278513bd1963SGregory Neil Shapiro {
278640266059SGregory Neil Shapiro /* turn off profiling */
278740266059SGregory Neil Shapiro SM_PROF(0);
278840266059SGregory Neil Shapiro if (OpMode == MD_DAEMON)
278940266059SGregory Neil Shapiro goto nextreq;
279013bd1963SGregory Neil Shapiro }
2791c2aa98e2SPeter Wemm }
2792c2aa98e2SPeter Wemm
279340266059SGregory Neil Shapiro sm_rpool_free(MainEnvelope.e_rpool);
279440266059SGregory Neil Shapiro clearenvelope(&MainEnvelope, false, sm_rpool_new_x(NULL));
2795c2aa98e2SPeter Wemm if (OpMode == MD_VERIFY)
2796c2aa98e2SPeter Wemm {
279740266059SGregory Neil Shapiro set_delivery_mode(SM_VERIFY, &MainEnvelope);
2798c2aa98e2SPeter Wemm PostMasterCopy = NULL;
2799c2aa98e2SPeter Wemm }
2800c2aa98e2SPeter Wemm else
2801c2aa98e2SPeter Wemm {
2802c2aa98e2SPeter Wemm /* interactive -- all errors are global */
280340266059SGregory Neil Shapiro MainEnvelope.e_flags |= EF_GLOBALERRS|EF_LOGSENDER;
2804c2aa98e2SPeter Wemm }
2805c2aa98e2SPeter Wemm
2806c2aa98e2SPeter Wemm /*
2807c2aa98e2SPeter Wemm ** Do basic system initialization and set the sender
2808c2aa98e2SPeter Wemm */
2809c2aa98e2SPeter Wemm
281040266059SGregory Neil Shapiro initsys(&MainEnvelope);
281140266059SGregory Neil Shapiro macdefine(&MainEnvelope.e_macro, A_PERM, macid("{ntries}"), "0");
281240266059SGregory Neil Shapiro macdefine(&MainEnvelope.e_macro, A_PERM, macid("{nrcpts}"), "0");
28132fb4f839SGregory Neil Shapiro #if USE_EAI
28142fb4f839SGregory Neil Shapiro fromaddr_x = fromaddr; /* for logging - see below -- just in case */
28152fb4f839SGregory Neil Shapiro if (fromaddr != NULL && (MainEnvelope.e_smtputf8 ||
28162fb4f839SGregory Neil Shapiro (MainEnvelope.e_smtputf8 = !asciistr(fromaddr))))
28172fb4f839SGregory Neil Shapiro {
28182fb4f839SGregory Neil Shapiro /* not very efficient: asciistr() may be called above already */
2819d39bd2c1SGregory Neil Shapiro if (!SMTP_UTF8 && !asciistr(fromaddr))
28202fb4f839SGregory Neil Shapiro {
28212fb4f839SGregory Neil Shapiro usrerr("non-ASCII sender address %s requires SMTPUTF8",
28222fb4f839SGregory Neil Shapiro fromaddr);
28232fb4f839SGregory Neil Shapiro finis(false, true, EX_USAGE);
28242fb4f839SGregory Neil Shapiro }
28252fb4f839SGregory Neil Shapiro j = 0;
28262fb4f839SGregory Neil Shapiro fromaddr = quote_internal_chars(fromaddr, NULL, &j, NULL);
28272fb4f839SGregory Neil Shapiro }
28282fb4f839SGregory Neil Shapiro #endif
28292fb4f839SGregory Neil Shapiro setsender(fromaddr, &MainEnvelope, NULL, '\0', false);
283006f25ae9SGregory Neil Shapiro if (warn_f_flag != '\0' && !wordinclass(RealUserName, 't') &&
283140266059SGregory Neil Shapiro (!bitnset(M_LOCALMAILER, MainEnvelope.e_from.q_mailer->m_flags) ||
283240266059SGregory Neil Shapiro strcmp(MainEnvelope.e_from.q_user, RealUserName) != 0))
283306f25ae9SGregory Neil Shapiro {
283440266059SGregory Neil Shapiro auth_warning(&MainEnvelope, "%s set sender to %s using -%c",
28352fb4f839SGregory Neil Shapiro RealUserName, fromaddr_x, warn_f_flag);
283606f25ae9SGregory Neil Shapiro #if SASL
283740266059SGregory Neil Shapiro auth = false;
28385b0945b5SGregory Neil Shapiro #endif
283906f25ae9SGregory Neil Shapiro }
284006f25ae9SGregory Neil Shapiro if (auth)
284106f25ae9SGregory Neil Shapiro {
284206f25ae9SGregory Neil Shapiro char *fv;
284306f25ae9SGregory Neil Shapiro
284406f25ae9SGregory Neil Shapiro /* set the initial sender for AUTH= to $f@$j */
284540266059SGregory Neil Shapiro fv = macvalue('f', &MainEnvelope);
284606f25ae9SGregory Neil Shapiro if (fv == NULL || *fv == '\0')
284740266059SGregory Neil Shapiro MainEnvelope.e_auth_param = NULL;
284806f25ae9SGregory Neil Shapiro else
284906f25ae9SGregory Neil Shapiro {
285006f25ae9SGregory Neil Shapiro if (strchr(fv, '@') == NULL)
285106f25ae9SGregory Neil Shapiro {
285240266059SGregory Neil Shapiro i = strlen(fv) + strlen(macvalue('j',
285340266059SGregory Neil Shapiro &MainEnvelope)) + 2;
285440266059SGregory Neil Shapiro p = sm_malloc_x(i);
285540266059SGregory Neil Shapiro (void) sm_strlcpyn(p, i, 3, fv, "@",
285640266059SGregory Neil Shapiro macvalue('j',
285740266059SGregory Neil Shapiro &MainEnvelope));
285806f25ae9SGregory Neil Shapiro }
285906f25ae9SGregory Neil Shapiro else
286040266059SGregory Neil Shapiro p = sm_strdup_x(fv);
286140266059SGregory Neil Shapiro MainEnvelope.e_auth_param = sm_rpool_strdup_x(MainEnvelope.e_rpool,
286240266059SGregory Neil Shapiro xtextify(p, "="));
286340266059SGregory Neil Shapiro sm_free(p); /* XXX */
286406f25ae9SGregory Neil Shapiro }
286506f25ae9SGregory Neil Shapiro }
286640266059SGregory Neil Shapiro if (macvalue('s', &MainEnvelope) == NULL)
286740266059SGregory Neil Shapiro macdefine(&MainEnvelope.e_macro, A_PERM, 's', RealHostName);
2868c2aa98e2SPeter Wemm
286940266059SGregory Neil Shapiro av = argv + optind;
2870c2aa98e2SPeter Wemm if (*av == NULL && !GrabTo)
2871c2aa98e2SPeter Wemm {
287240266059SGregory Neil Shapiro MainEnvelope.e_to = NULL;
287340266059SGregory Neil Shapiro MainEnvelope.e_flags |= EF_GLOBALERRS;
287440266059SGregory Neil Shapiro HoldErrs = false;
287540266059SGregory Neil Shapiro SuperSafe = SAFE_NO;
2876c2aa98e2SPeter Wemm usrerr("Recipient names must be specified");
2877c2aa98e2SPeter Wemm
2878c2aa98e2SPeter Wemm /* collect body for UUCP return */
2879c2aa98e2SPeter Wemm if (OpMode != MD_VERIFY)
2880d39bd2c1SGregory Neil Shapiro collect(InChannel, SMTPMODE_NO, NULL, &MainEnvelope,
2881d39bd2c1SGregory Neil Shapiro true);
288240266059SGregory Neil Shapiro finis(true, true, EX_USAGE);
288340266059SGregory Neil Shapiro /* NOTREACHED */
2884c2aa98e2SPeter Wemm }
2885c2aa98e2SPeter Wemm
2886c2aa98e2SPeter Wemm /*
2887c2aa98e2SPeter Wemm ** Scan argv and deliver the message to everyone.
2888c2aa98e2SPeter Wemm */
2889c2aa98e2SPeter Wemm
289040266059SGregory Neil Shapiro save_val = LogUsrErrs;
289140266059SGregory Neil Shapiro LogUsrErrs = true;
289240266059SGregory Neil Shapiro sendtoargv(av, &MainEnvelope);
289340266059SGregory Neil Shapiro LogUsrErrs = save_val;
2894c2aa98e2SPeter Wemm
2895c2aa98e2SPeter Wemm /* if we have had errors sofar, arrange a meaningful exit stat */
2896c2aa98e2SPeter Wemm if (Errors > 0 && ExitStat == EX_OK)
2897c2aa98e2SPeter Wemm ExitStat = EX_USAGE;
2898c2aa98e2SPeter Wemm
2899c2aa98e2SPeter Wemm #if _FFR_FIX_DASHT
2900c2aa98e2SPeter Wemm /*
2901c2aa98e2SPeter Wemm ** If using -t, force not sending to argv recipients, even
2902c2aa98e2SPeter Wemm ** if they are mentioned in the headers.
2903c2aa98e2SPeter Wemm */
2904c2aa98e2SPeter Wemm
2905c2aa98e2SPeter Wemm if (GrabTo)
2906c2aa98e2SPeter Wemm {
2907c2aa98e2SPeter Wemm ADDRESS *q;
2908c2aa98e2SPeter Wemm
290940266059SGregory Neil Shapiro for (q = MainEnvelope.e_sendqueue; q != NULL; q = q->q_next)
291006f25ae9SGregory Neil Shapiro q->q_state = QS_REMOVED;
2911c2aa98e2SPeter Wemm }
291206f25ae9SGregory Neil Shapiro #endif /* _FFR_FIX_DASHT */
2913c2aa98e2SPeter Wemm
2914c2aa98e2SPeter Wemm /*
2915c2aa98e2SPeter Wemm ** Read the input mail.
2916c2aa98e2SPeter Wemm */
2917c2aa98e2SPeter Wemm
291840266059SGregory Neil Shapiro MainEnvelope.e_to = NULL;
2919c2aa98e2SPeter Wemm if (OpMode != MD_VERIFY || GrabTo)
2920c2aa98e2SPeter Wemm {
292140266059SGregory Neil Shapiro int savederrors;
292240266059SGregory Neil Shapiro unsigned long savedflags;
2923c2aa98e2SPeter Wemm
292440266059SGregory Neil Shapiro savederrors = Errors;
292540266059SGregory Neil Shapiro savedflags = MainEnvelope.e_flags & EF_FATALERRS;
292640266059SGregory Neil Shapiro MainEnvelope.e_flags |= EF_GLOBALERRS;
292740266059SGregory Neil Shapiro MainEnvelope.e_flags &= ~EF_FATALERRS;
292806f25ae9SGregory Neil Shapiro Errors = 0;
292906f25ae9SGregory Neil Shapiro buffer_errors();
2930d39bd2c1SGregory Neil Shapiro collect(InChannel, SMTPMODE_NO, NULL, &MainEnvelope, true);
2931c2aa98e2SPeter Wemm
293206f25ae9SGregory Neil Shapiro /* header checks failed */
293306f25ae9SGregory Neil Shapiro if (Errors > 0)
2934c2aa98e2SPeter Wemm {
293540266059SGregory Neil Shapiro giveup:
293640266059SGregory Neil Shapiro if (!GrabTo)
293740266059SGregory Neil Shapiro {
293806f25ae9SGregory Neil Shapiro /* Log who the mail would have gone to */
293940266059SGregory Neil Shapiro logundelrcpts(&MainEnvelope,
294040266059SGregory Neil Shapiro MainEnvelope.e_message,
294140266059SGregory Neil Shapiro 8, false);
294206f25ae9SGregory Neil Shapiro }
294340266059SGregory Neil Shapiro flush_errors(true);
294440266059SGregory Neil Shapiro finis(true, true, ExitStat);
2945c2aa98e2SPeter Wemm /* NOTREACHED */
2946c2aa98e2SPeter Wemm return -1;
2947c2aa98e2SPeter Wemm }
294806f25ae9SGregory Neil Shapiro
294906f25ae9SGregory Neil Shapiro /* bail out if message too large */
295040266059SGregory Neil Shapiro if (bitset(EF_CLRQUEUE, MainEnvelope.e_flags))
295106f25ae9SGregory Neil Shapiro {
295240266059SGregory Neil Shapiro finis(true, true, ExitStat != EX_OK ? ExitStat
295340266059SGregory Neil Shapiro : EX_DATAERR);
295406f25ae9SGregory Neil Shapiro /* NOTREACHED */
295506f25ae9SGregory Neil Shapiro return -1;
295606f25ae9SGregory Neil Shapiro }
295794c01205SGregory Neil Shapiro
295894c01205SGregory Neil Shapiro /* set message size */
2959d0cef73dSGregory Neil Shapiro (void) sm_snprintf(buf, sizeof(buf), "%ld",
2960ba00ec3dSGregory Neil Shapiro PRT_NONNEGL(MainEnvelope.e_msgsize));
296194c01205SGregory Neil Shapiro macdefine(&MainEnvelope.e_macro, A_TEMP,
296294c01205SGregory Neil Shapiro macid("{msg_size}"), buf);
296394c01205SGregory Neil Shapiro
296406f25ae9SGregory Neil Shapiro Errors = savederrors;
296540266059SGregory Neil Shapiro MainEnvelope.e_flags |= savedflags;
2966c2aa98e2SPeter Wemm }
2967c2aa98e2SPeter Wemm errno = 0;
2968c2aa98e2SPeter Wemm
2969c2aa98e2SPeter Wemm if (tTd(1, 1))
297040266059SGregory Neil Shapiro sm_dprintf("From person = \"%s\"\n",
297140266059SGregory Neil Shapiro MainEnvelope.e_from.q_paddr);
297240266059SGregory Neil Shapiro
297340266059SGregory Neil Shapiro /* Check if quarantining stats should be updated */
297440266059SGregory Neil Shapiro if (MainEnvelope.e_quarmsg != NULL)
297540266059SGregory Neil Shapiro markstats(&MainEnvelope, NULL, STATS_QUARANTINE);
2976c2aa98e2SPeter Wemm
2977c2aa98e2SPeter Wemm /*
2978c2aa98e2SPeter Wemm ** Actually send everything.
2979c2aa98e2SPeter Wemm ** If verifying, just ack.
2980c2aa98e2SPeter Wemm */
2981c2aa98e2SPeter Wemm
298240266059SGregory Neil Shapiro if (Errors == 0)
298340266059SGregory Neil Shapiro {
298440266059SGregory Neil Shapiro if (!split_by_recipient(&MainEnvelope) &&
298540266059SGregory Neil Shapiro bitset(EF_FATALERRS, MainEnvelope.e_flags))
298640266059SGregory Neil Shapiro goto giveup;
298740266059SGregory Neil Shapiro }
298840266059SGregory Neil Shapiro
298940266059SGregory Neil Shapiro /* make sure we deliver at least the first envelope */
299040266059SGregory Neil Shapiro i = FastSplit > 0 ? 0 : -1;
299140266059SGregory Neil Shapiro for (e = &MainEnvelope; e != NULL; e = e->e_sibling, i++)
299240266059SGregory Neil Shapiro {
299340266059SGregory Neil Shapiro ENVELOPE *next;
299440266059SGregory Neil Shapiro
299540266059SGregory Neil Shapiro e->e_from.q_state = QS_SENDER;
2996c2aa98e2SPeter Wemm if (tTd(1, 5))
2997c2aa98e2SPeter Wemm {
299840266059SGregory Neil Shapiro sm_dprintf("main[%d]: QS_SENDER ", i);
2999e92d3f3fSGregory Neil Shapiro printaddr(sm_debug_file(), &e->e_from, false);
3000c2aa98e2SPeter Wemm }
300140266059SGregory Neil Shapiro e->e_to = NULL;
300240266059SGregory Neil Shapiro sm_getla();
300340266059SGregory Neil Shapiro GrabTo = false;
300406f25ae9SGregory Neil Shapiro #if NAMED_BIND
300506f25ae9SGregory Neil Shapiro _res.retry = TimeOuts.res_retry[RES_TO_FIRST];
300606f25ae9SGregory Neil Shapiro _res.retrans = TimeOuts.res_retrans[RES_TO_FIRST];
30075b0945b5SGregory Neil Shapiro #endif
300840266059SGregory Neil Shapiro next = e->e_sibling;
300940266059SGregory Neil Shapiro e->e_sibling = NULL;
301040266059SGregory Neil Shapiro
301140266059SGregory Neil Shapiro /* after FastSplit envelopes: queue up */
301240266059SGregory Neil Shapiro sendall(e, i >= FastSplit ? SM_QUEUE : SM_DEFAULT);
301340266059SGregory Neil Shapiro e->e_sibling = next;
301440266059SGregory Neil Shapiro }
3015c2aa98e2SPeter Wemm
3016c2aa98e2SPeter Wemm /*
3017c2aa98e2SPeter Wemm ** All done.
3018c2aa98e2SPeter Wemm ** Don't send return error message if in VERIFY mode.
3019c2aa98e2SPeter Wemm */
3020c2aa98e2SPeter Wemm
302140266059SGregory Neil Shapiro finis(true, true, ExitStat);
3022c2aa98e2SPeter Wemm /* NOTREACHED */
302306f25ae9SGregory Neil Shapiro return ExitStat;
3024c2aa98e2SPeter Wemm }
302540266059SGregory Neil Shapiro /*
30268774250cSGregory Neil Shapiro ** STOP_SENDMAIL -- Stop the running program
30278774250cSGregory Neil Shapiro **
30288774250cSGregory Neil Shapiro ** Parameters:
30298774250cSGregory Neil Shapiro ** none.
30308774250cSGregory Neil Shapiro **
30318774250cSGregory Neil Shapiro ** Returns:
30328774250cSGregory Neil Shapiro ** none.
30338774250cSGregory Neil Shapiro **
30348774250cSGregory Neil Shapiro ** Side Effects:
30358774250cSGregory Neil Shapiro ** exits.
30368774250cSGregory Neil Shapiro */
30378774250cSGregory Neil Shapiro
30388774250cSGregory Neil Shapiro void
stop_sendmail()30398774250cSGregory Neil Shapiro stop_sendmail()
30408774250cSGregory Neil Shapiro {
30418774250cSGregory Neil Shapiro /* reset uid for process accounting */
30428774250cSGregory Neil Shapiro endpwent();
30438774250cSGregory Neil Shapiro (void) setuid(RealUid);
30448774250cSGregory Neil Shapiro exit(EX_OK);
3045065a643dSPeter Wemm }
304640266059SGregory Neil Shapiro /*
304740266059SGregory Neil Shapiro ** FINIS -- Clean up and exit.
304840266059SGregory Neil Shapiro **
304940266059SGregory Neil Shapiro ** Parameters:
305040266059SGregory Neil Shapiro ** drop -- whether or not to drop CurEnv envelope
305140266059SGregory Neil Shapiro ** cleanup -- call exit() or _exit()?
305240266059SGregory Neil Shapiro ** exitstat -- exit status to use for exit() call
305340266059SGregory Neil Shapiro **
305440266059SGregory Neil Shapiro ** Returns:
305540266059SGregory Neil Shapiro ** never
305640266059SGregory Neil Shapiro **
305740266059SGregory Neil Shapiro ** Side Effects:
305840266059SGregory Neil Shapiro ** exits sendmail
305940266059SGregory Neil Shapiro */
3060c2aa98e2SPeter Wemm
306140266059SGregory Neil Shapiro void
finis(drop,cleanup,exitstat)306240266059SGregory Neil Shapiro finis(drop, cleanup, exitstat)
306340266059SGregory Neil Shapiro bool drop;
306440266059SGregory Neil Shapiro bool cleanup;
306540266059SGregory Neil Shapiro volatile int exitstat;
306640266059SGregory Neil Shapiro {
3067e92d3f3fSGregory Neil Shapiro char pidpath[MAXPATHLEN];
3068af9557fdSGregory Neil Shapiro pid_t pid;
306994c01205SGregory Neil Shapiro
307040266059SGregory Neil Shapiro /* Still want to process new timeouts added below */
307140266059SGregory Neil Shapiro sm_clear_events();
307240266059SGregory Neil Shapiro (void) sm_releasesignal(SIGALRM);
307340266059SGregory Neil Shapiro
30745b0945b5SGregory Neil Shapiro #if RATECTL_DEBUG || _FFR_OCC
30755b0945b5SGregory Neil Shapiro /* do this only in "main" process */
30765b0945b5SGregory Neil Shapiro if (DaemonPid == getpid())
30775b0945b5SGregory Neil Shapiro {
30785b0945b5SGregory Neil Shapiro SM_FILE_T *fp;
30795b0945b5SGregory Neil Shapiro
30805b0945b5SGregory Neil Shapiro fp = sm_debug_file();
30815b0945b5SGregory Neil Shapiro if (fp != NULL)
30825b0945b5SGregory Neil Shapiro dump_ch(fp);
30835b0945b5SGregory Neil Shapiro }
30842fb4f839SGregory Neil Shapiro #endif /* RATECTL_DEBUG || _FFR_OCC */
30852fb4f839SGregory Neil Shapiro #if _FFR_DMTRIGGER
30862fb4f839SGregory Neil Shapiro if (OpMode == MD_DAEMON && SM_TRIGGER == BlankEnvelope.e_sendmode)
30872fb4f839SGregory Neil Shapiro sm_notify_stop(DaemonPid == getpid(), 0);
30885b0945b5SGregory Neil Shapiro #endif
308940266059SGregory Neil Shapiro if (tTd(2, 1))
309040266059SGregory Neil Shapiro {
309140266059SGregory Neil Shapiro sm_dprintf("\n====finis: stat %d e_id=%s e_flags=",
309240266059SGregory Neil Shapiro exitstat,
309340266059SGregory Neil Shapiro CurEnv->e_id == NULL ? "NOQUEUE" : CurEnv->e_id);
309440266059SGregory Neil Shapiro printenvflags(CurEnv);
309540266059SGregory Neil Shapiro }
309640266059SGregory Neil Shapiro if (tTd(2, 9))
309740266059SGregory Neil Shapiro printopenfds(false);
309840266059SGregory Neil Shapiro
309940266059SGregory Neil Shapiro SM_TRY
310040266059SGregory Neil Shapiro /*
310140266059SGregory Neil Shapiro ** Clean up. This might raise E:mta.quickabort
310240266059SGregory Neil Shapiro */
310340266059SGregory Neil Shapiro
310440266059SGregory Neil Shapiro /* clean up temp files */
310540266059SGregory Neil Shapiro CurEnv->e_to = NULL;
310640266059SGregory Neil Shapiro if (drop)
310740266059SGregory Neil Shapiro {
310840266059SGregory Neil Shapiro if (CurEnv->e_id != NULL)
310940266059SGregory Neil Shapiro {
31109bd497b8SGregory Neil Shapiro int r;
31119bd497b8SGregory Neil Shapiro
31129bd497b8SGregory Neil Shapiro r = dropenvelope(CurEnv, true, false);
31139bd497b8SGregory Neil Shapiro if (exitstat == EX_OK)
31149bd497b8SGregory Neil Shapiro exitstat = r;
311540266059SGregory Neil Shapiro sm_rpool_free(CurEnv->e_rpool);
311640266059SGregory Neil Shapiro CurEnv->e_rpool = NULL;
31173a3ef73dSGregory Neil Shapiro
3118d0cef73dSGregory Neil Shapiro /* these may have pointed to the rpool */
31193a3ef73dSGregory Neil Shapiro CurEnv->e_to = NULL;
3120d0cef73dSGregory Neil Shapiro CurEnv->e_message = NULL;
3121d0cef73dSGregory Neil Shapiro CurEnv->e_statmsg = NULL;
3122d0cef73dSGregory Neil Shapiro CurEnv->e_quarmsg = NULL;
3123d0cef73dSGregory Neil Shapiro CurEnv->e_bodytype = NULL;
3124d0cef73dSGregory Neil Shapiro CurEnv->e_id = NULL;
3125d0cef73dSGregory Neil Shapiro CurEnv->e_envid = NULL;
3126d0cef73dSGregory Neil Shapiro CurEnv->e_auth_param = NULL;
312740266059SGregory Neil Shapiro }
312840266059SGregory Neil Shapiro else
312940266059SGregory Neil Shapiro poststats(StatFile);
313040266059SGregory Neil Shapiro }
313140266059SGregory Neil Shapiro
313240266059SGregory Neil Shapiro /* flush any cached connections */
313340266059SGregory Neil Shapiro mci_flush(true, NULL);
313440266059SGregory Neil Shapiro
313540266059SGregory Neil Shapiro /* close maps belonging to this pid */
313640266059SGregory Neil Shapiro closemaps(false);
313740266059SGregory Neil Shapiro
313840266059SGregory Neil Shapiro #if USERDB
313940266059SGregory Neil Shapiro /* close UserDatabase */
314040266059SGregory Neil Shapiro _udbx_close();
31415b0945b5SGregory Neil Shapiro #endif
314240266059SGregory Neil Shapiro
314340266059SGregory Neil Shapiro #if SASL
314440266059SGregory Neil Shapiro stop_sasl_client();
31455b0945b5SGregory Neil Shapiro #endif
314640266059SGregory Neil Shapiro
314740266059SGregory Neil Shapiro #if XLA
314840266059SGregory Neil Shapiro /* clean up extended load average stuff */
314940266059SGregory Neil Shapiro xla_all_end();
31505b0945b5SGregory Neil Shapiro #endif
315140266059SGregory Neil Shapiro
315240266059SGregory Neil Shapiro SM_FINALLY
315340266059SGregory Neil Shapiro /*
315440266059SGregory Neil Shapiro ** And exit.
315540266059SGregory Neil Shapiro */
315640266059SGregory Neil Shapiro
315740266059SGregory Neil Shapiro if (LogLevel > 78)
315840266059SGregory Neil Shapiro sm_syslog(LOG_DEBUG, CurEnv->e_id, "finis, pid=%d",
315940266059SGregory Neil Shapiro (int) CurrentPid);
316040266059SGregory Neil Shapiro if (exitstat == EX_TEMPFAIL ||
316140266059SGregory Neil Shapiro CurEnv->e_errormode == EM_BERKNET)
316240266059SGregory Neil Shapiro exitstat = EX_OK;
316340266059SGregory Neil Shapiro
316440266059SGregory Neil Shapiro /* XXX clean up queues and related data structures */
316540266059SGregory Neil Shapiro cleanup_queues();
3166af9557fdSGregory Neil Shapiro pid = getpid();
316740266059SGregory Neil Shapiro #if SM_CONF_SHM
3168af9557fdSGregory Neil Shapiro cleanup_shm(DaemonPid == pid);
31695b0945b5SGregory Neil Shapiro #endif
317040266059SGregory Neil Shapiro
3171e92d3f3fSGregory Neil Shapiro /* close locked pid file */
3172e92d3f3fSGregory Neil Shapiro close_sendmail_pid();
3173e92d3f3fSGregory Neil Shapiro
3174af9557fdSGregory Neil Shapiro if (DaemonPid == pid || PidFilePid == pid)
3175e92d3f3fSGregory Neil Shapiro {
3176e92d3f3fSGregory Neil Shapiro /* blow away the pid file */
3177d0cef73dSGregory Neil Shapiro expand(PidFile, pidpath, sizeof(pidpath), CurEnv);
3178e92d3f3fSGregory Neil Shapiro (void) unlink(pidpath);
3179e92d3f3fSGregory Neil Shapiro }
3180e92d3f3fSGregory Neil Shapiro
318140266059SGregory Neil Shapiro /* reset uid for process accounting */
318240266059SGregory Neil Shapiro endpwent();
318340266059SGregory Neil Shapiro sm_mbdb_terminate();
31844e4196cbSGregory Neil Shapiro #if _FFR_MEMSTAT
31854e4196cbSGregory Neil Shapiro (void) sm_memstat_close();
31865b0945b5SGregory Neil Shapiro #endif
318740266059SGregory Neil Shapiro (void) setuid(RealUid);
318840266059SGregory Neil Shapiro #if SM_HEAP_CHECK
31892fb4f839SGregory Neil Shapiro # if SM_HEAP_CHECK > 1
31902fb4f839SGregory Neil Shapiro /* seems this is not always free()? */
31912fb4f839SGregory Neil Shapiro sm_rpool_free(CurEnv->e_rpool);
31922fb4f839SGregory Neil Shapiro # endif
319340266059SGregory Neil Shapiro /* dump the heap, if we are checking for memory leaks */
319440266059SGregory Neil Shapiro if (sm_debug_active(&SmHeapCheck, 2))
319540266059SGregory Neil Shapiro sm_heap_report(smioout,
319640266059SGregory Neil Shapiro sm_debug_level(&SmHeapCheck) - 1);
31975b0945b5SGregory Neil Shapiro #endif
319840266059SGregory Neil Shapiro if (sm_debug_active(&SmXtrapReport, 1))
319940266059SGregory Neil Shapiro sm_dprintf("xtrap count = %d\n", SmXtrapCount);
320040266059SGregory Neil Shapiro if (cleanup)
320140266059SGregory Neil Shapiro exit(exitstat);
320240266059SGregory Neil Shapiro else
320340266059SGregory Neil Shapiro _exit(exitstat);
320440266059SGregory Neil Shapiro SM_END_TRY
320540266059SGregory Neil Shapiro }
320640266059SGregory Neil Shapiro /*
32078774250cSGregory Neil Shapiro ** INTINDEBUG -- signal handler for SIGINT in -bt mode
32088774250cSGregory Neil Shapiro **
32098774250cSGregory Neil Shapiro ** Parameters:
32108774250cSGregory Neil Shapiro ** sig -- incoming signal.
32118774250cSGregory Neil Shapiro **
32128774250cSGregory Neil Shapiro ** Returns:
32138774250cSGregory Neil Shapiro ** none.
32148774250cSGregory Neil Shapiro **
32158774250cSGregory Neil Shapiro ** Side Effects:
32168774250cSGregory Neil Shapiro ** longjmps back to test mode loop.
32178774250cSGregory Neil Shapiro **
32188774250cSGregory Neil Shapiro ** NOTE: THIS CAN BE CALLED FROM A SIGNAL HANDLER. DO NOT ADD
32198774250cSGregory Neil Shapiro ** ANYTHING TO THIS ROUTINE UNLESS YOU KNOW WHAT YOU ARE
32208774250cSGregory Neil Shapiro ** DOING.
32218774250cSGregory Neil Shapiro */
32228774250cSGregory Neil Shapiro
322340266059SGregory Neil Shapiro /* Type of an exception generated on SIGINT during address test mode. */
322440266059SGregory Neil Shapiro static const SM_EXC_TYPE_T EtypeInterrupt =
322540266059SGregory Neil Shapiro {
322640266059SGregory Neil Shapiro SmExcTypeMagic,
322740266059SGregory Neil Shapiro "S:mta.interrupt",
322840266059SGregory Neil Shapiro "",
322940266059SGregory Neil Shapiro sm_etype_printf,
323040266059SGregory Neil Shapiro "interrupt",
323140266059SGregory Neil Shapiro };
323240266059SGregory Neil Shapiro
3233c2aa98e2SPeter Wemm /* ARGSUSED */
32348774250cSGregory Neil Shapiro static SIGFUNC_DECL
intindebug(sig)3235c2aa98e2SPeter Wemm intindebug(sig)
3236c2aa98e2SPeter Wemm int sig;
3237c2aa98e2SPeter Wemm {
32388774250cSGregory Neil Shapiro int save_errno = errno;
32398774250cSGregory Neil Shapiro
32408774250cSGregory Neil Shapiro FIX_SYSV_SIGNAL(sig, intindebug);
32418774250cSGregory Neil Shapiro errno = save_errno;
32428774250cSGregory Neil Shapiro CHECK_CRITICAL(sig);
32438774250cSGregory Neil Shapiro errno = save_errno;
324440266059SGregory Neil Shapiro sm_exc_raisenew_x(&EtypeInterrupt);
324540266059SGregory Neil Shapiro errno = save_errno;
3246c2aa98e2SPeter Wemm return SIGFUNC_RETURN;
3247c2aa98e2SPeter Wemm }
324840266059SGregory Neil Shapiro /*
324940266059SGregory Neil Shapiro ** SIGTERM -- SIGTERM handler for the daemon
32508774250cSGregory Neil Shapiro **
32518774250cSGregory Neil Shapiro ** Parameters:
32528774250cSGregory Neil Shapiro ** sig -- signal number.
32538774250cSGregory Neil Shapiro **
32548774250cSGregory Neil Shapiro ** Returns:
32558774250cSGregory Neil Shapiro ** none.
32568774250cSGregory Neil Shapiro **
32578774250cSGregory Neil Shapiro ** Side Effects:
32588774250cSGregory Neil Shapiro ** Sets ShutdownRequest which will hopefully trigger
32598774250cSGregory Neil Shapiro ** the daemon to exit.
32608774250cSGregory Neil Shapiro **
32618774250cSGregory Neil Shapiro ** NOTE: THIS CAN BE CALLED FROM A SIGNAL HANDLER. DO NOT ADD
32628774250cSGregory Neil Shapiro ** ANYTHING TO THIS ROUTINE UNLESS YOU KNOW WHAT YOU ARE
32638774250cSGregory Neil Shapiro ** DOING.
32648774250cSGregory Neil Shapiro */
32658774250cSGregory Neil Shapiro
32668774250cSGregory Neil Shapiro /* ARGSUSED */
32678774250cSGregory Neil Shapiro static SIGFUNC_DECL
sigterm(sig)326840266059SGregory Neil Shapiro sigterm(sig)
32698774250cSGregory Neil Shapiro int sig;
32708774250cSGregory Neil Shapiro {
32718774250cSGregory Neil Shapiro int save_errno = errno;
32728774250cSGregory Neil Shapiro
327340266059SGregory Neil Shapiro FIX_SYSV_SIGNAL(sig, sigterm);
32748774250cSGregory Neil Shapiro ShutdownRequest = "signal";
32758774250cSGregory Neil Shapiro errno = save_errno;
3276d39bd2c1SGregory Neil Shapiro #if _FFR_DMTRIGGER
3277d39bd2c1SGregory Neil Shapiro /* temporary? */
3278d39bd2c1SGregory Neil Shapiro proc_list_signal(PROC_QM, sig);
3279d39bd2c1SGregory Neil Shapiro #endif
32808774250cSGregory Neil Shapiro return SIGFUNC_RETURN;
32818774250cSGregory Neil Shapiro }
328240266059SGregory Neil Shapiro /*
328340266059SGregory Neil Shapiro ** SIGHUP -- handle a SIGHUP signal
32848774250cSGregory Neil Shapiro **
32858774250cSGregory Neil Shapiro ** Parameters:
328640266059SGregory Neil Shapiro ** sig -- incoming signal.
32878774250cSGregory Neil Shapiro **
32888774250cSGregory Neil Shapiro ** Returns:
32898774250cSGregory Neil Shapiro ** none.
32908774250cSGregory Neil Shapiro **
32918774250cSGregory Neil Shapiro ** Side Effects:
329240266059SGregory Neil Shapiro ** Sets RestartRequest which should cause the daemon
329340266059SGregory Neil Shapiro ** to restart.
329440266059SGregory Neil Shapiro **
329540266059SGregory Neil Shapiro ** NOTE: THIS CAN BE CALLED FROM A SIGNAL HANDLER. DO NOT ADD
329640266059SGregory Neil Shapiro ** ANYTHING TO THIS ROUTINE UNLESS YOU KNOW WHAT YOU ARE
329740266059SGregory Neil Shapiro ** DOING.
32988774250cSGregory Neil Shapiro */
32998774250cSGregory Neil Shapiro
330040266059SGregory Neil Shapiro /* ARGSUSED */
330140266059SGregory Neil Shapiro static SIGFUNC_DECL
sighup(sig)330240266059SGregory Neil Shapiro sighup(sig)
330340266059SGregory Neil Shapiro int sig;
33048774250cSGregory Neil Shapiro {
330540266059SGregory Neil Shapiro int save_errno = errno;
33068774250cSGregory Neil Shapiro
330740266059SGregory Neil Shapiro FIX_SYSV_SIGNAL(sig, sighup);
330840266059SGregory Neil Shapiro RestartRequest = "signal";
330940266059SGregory Neil Shapiro errno = save_errno;
331040266059SGregory Neil Shapiro return SIGFUNC_RETURN;
33118774250cSGregory Neil Shapiro }
331240266059SGregory Neil Shapiro /*
331340266059SGregory Neil Shapiro ** SIGPIPE -- signal handler for SIGPIPE
331440266059SGregory Neil Shapiro **
331540266059SGregory Neil Shapiro ** Parameters:
331640266059SGregory Neil Shapiro ** sig -- incoming signal.
331740266059SGregory Neil Shapiro **
331840266059SGregory Neil Shapiro ** Returns:
331940266059SGregory Neil Shapiro ** none.
332040266059SGregory Neil Shapiro **
332140266059SGregory Neil Shapiro ** Side Effects:
332240266059SGregory Neil Shapiro ** Sets StopRequest which should cause the mailq/hoststatus
332340266059SGregory Neil Shapiro ** display to stop.
332440266059SGregory Neil Shapiro **
332540266059SGregory Neil Shapiro ** NOTE: THIS CAN BE CALLED FROM A SIGNAL HANDLER. DO NOT ADD
332640266059SGregory Neil Shapiro ** ANYTHING TO THIS ROUTINE UNLESS YOU KNOW WHAT YOU ARE
332740266059SGregory Neil Shapiro ** DOING.
332840266059SGregory Neil Shapiro */
332940266059SGregory Neil Shapiro
333040266059SGregory Neil Shapiro /* ARGSUSED */
333140266059SGregory Neil Shapiro static SIGFUNC_DECL
sigpipe(sig)333240266059SGregory Neil Shapiro sigpipe(sig)
333340266059SGregory Neil Shapiro int sig;
333440266059SGregory Neil Shapiro {
333540266059SGregory Neil Shapiro int save_errno = errno;
333640266059SGregory Neil Shapiro
333740266059SGregory Neil Shapiro FIX_SYSV_SIGNAL(sig, sigpipe);
333840266059SGregory Neil Shapiro StopRequest = true;
333940266059SGregory Neil Shapiro errno = save_errno;
334040266059SGregory Neil Shapiro return SIGFUNC_RETURN;
334140266059SGregory Neil Shapiro }
334240266059SGregory Neil Shapiro /*
3343c2aa98e2SPeter Wemm ** INTSIG -- clean up on interrupt
3344c2aa98e2SPeter Wemm **
334506f25ae9SGregory Neil Shapiro ** This just arranges to exit. It pessimizes in that it
3346c2aa98e2SPeter Wemm ** may resend a message.
3347c2aa98e2SPeter Wemm **
3348c2aa98e2SPeter Wemm ** Parameters:
33496f9c8e5bSGregory Neil Shapiro ** sig -- incoming signal.
3350c2aa98e2SPeter Wemm **
3351c2aa98e2SPeter Wemm ** Returns:
3352c2aa98e2SPeter Wemm ** none.
3353c2aa98e2SPeter Wemm **
3354c2aa98e2SPeter Wemm ** Side Effects:
3355c2aa98e2SPeter Wemm ** Unlocks the current job.
33568774250cSGregory Neil Shapiro **
33578774250cSGregory Neil Shapiro ** NOTE: THIS CAN BE CALLED FROM A SIGNAL HANDLER. DO NOT ADD
33588774250cSGregory Neil Shapiro ** ANYTHING TO THIS ROUTINE UNLESS YOU KNOW WHAT YOU ARE
33598774250cSGregory Neil Shapiro ** DOING.
3360c2aa98e2SPeter Wemm */
3361c2aa98e2SPeter Wemm
3362c2aa98e2SPeter Wemm /* ARGSUSED */
3363c2aa98e2SPeter Wemm SIGFUNC_DECL
intsig(sig)3364c2aa98e2SPeter Wemm intsig(sig)
3365c2aa98e2SPeter Wemm int sig;
3366c2aa98e2SPeter Wemm {
336740266059SGregory Neil Shapiro bool drop = false;
33688774250cSGregory Neil Shapiro int save_errno = errno;
336906f25ae9SGregory Neil Shapiro
33708774250cSGregory Neil Shapiro FIX_SYSV_SIGNAL(sig, intsig);
33718774250cSGregory Neil Shapiro errno = save_errno;
33728774250cSGregory Neil Shapiro CHECK_CRITICAL(sig);
337340266059SGregory Neil Shapiro sm_allsignals(true);
33746f9c8e5bSGregory Neil Shapiro IntSig = true;
337540266059SGregory Neil Shapiro
3376c2aa98e2SPeter Wemm FileName = NULL;
337706f25ae9SGregory Neil Shapiro
337806f25ae9SGregory Neil Shapiro /* Clean-up on aborted stdin message submission */
33796f9c8e5bSGregory Neil Shapiro if (OpMode == MD_SMTP ||
338006f25ae9SGregory Neil Shapiro OpMode == MD_DELIVER ||
33816f9c8e5bSGregory Neil Shapiro OpMode == MD_ARPAFTP)
338206f25ae9SGregory Neil Shapiro {
33836f9c8e5bSGregory Neil Shapiro if (CurEnv->e_id != NULL)
33846f9c8e5bSGregory Neil Shapiro {
33856f9c8e5bSGregory Neil Shapiro char *fn;
338606f25ae9SGregory Neil Shapiro
33876f9c8e5bSGregory Neil Shapiro fn = queuename(CurEnv, DATAFL_LETTER);
33886f9c8e5bSGregory Neil Shapiro if (fn != NULL)
33896f9c8e5bSGregory Neil Shapiro (void) unlink(fn);
33906f9c8e5bSGregory Neil Shapiro fn = queuename(CurEnv, ANYQFL_LETTER);
33916f9c8e5bSGregory Neil Shapiro if (fn != NULL)
33926f9c8e5bSGregory Neil Shapiro (void) unlink(fn);
339306f25ae9SGregory Neil Shapiro }
33946f9c8e5bSGregory Neil Shapiro _exit(EX_OK);
33956f9c8e5bSGregory Neil Shapiro /* NOTREACHED */
33966f9c8e5bSGregory Neil Shapiro }
33976f9c8e5bSGregory Neil Shapiro
33986f9c8e5bSGregory Neil Shapiro if (sig != 0 && LogLevel > 79)
33996f9c8e5bSGregory Neil Shapiro sm_syslog(LOG_DEBUG, CurEnv->e_id, "interrupt");
34006f9c8e5bSGregory Neil Shapiro if (OpMode != MD_TEST)
340106f25ae9SGregory Neil Shapiro unlockqueue(CurEnv);
3402c2aa98e2SPeter Wemm
340340266059SGregory Neil Shapiro finis(drop, false, EX_OK);
340440266059SGregory Neil Shapiro /* NOTREACHED */
3405c2aa98e2SPeter Wemm }
340640266059SGregory Neil Shapiro /*
3407c2aa98e2SPeter Wemm ** DISCONNECT -- remove our connection with any foreground process
3408c2aa98e2SPeter Wemm **
3409c2aa98e2SPeter Wemm ** Parameters:
3410c2aa98e2SPeter Wemm ** droplev -- how "deeply" we should drop the line.
3411c2aa98e2SPeter Wemm ** 0 -- ignore signals, mail back errors, make sure
3412c2aa98e2SPeter Wemm ** output goes to stdout.
341306f25ae9SGregory Neil Shapiro ** 1 -- also, make stdout go to /dev/null.
3414c2aa98e2SPeter Wemm ** 2 -- also, disconnect from controlling terminal
3415c2aa98e2SPeter Wemm ** (only for daemon mode).
3416c2aa98e2SPeter Wemm ** e -- the current envelope.
3417c2aa98e2SPeter Wemm **
3418c2aa98e2SPeter Wemm ** Returns:
3419c2aa98e2SPeter Wemm ** none
3420c2aa98e2SPeter Wemm **
3421c2aa98e2SPeter Wemm ** Side Effects:
3422d39bd2c1SGregory Neil Shapiro ** Try to insure that we are immune to vagaries of
3423c2aa98e2SPeter Wemm ** the controlling tty.
3424c2aa98e2SPeter Wemm */
3425c2aa98e2SPeter Wemm
3426c2aa98e2SPeter Wemm void
disconnect(droplev,e)3427c2aa98e2SPeter Wemm disconnect(droplev, e)
3428c2aa98e2SPeter Wemm int droplev;
3429c2aa98e2SPeter Wemm register ENVELOPE *e;
3430c2aa98e2SPeter Wemm {
34312fb4f839SGregory Neil Shapiro #define LOGID(e) (((e) != NULL && (e)->e_id != NULL) ? (e)->e_id : NOQID)
3432c2aa98e2SPeter Wemm int fd;
3433c2aa98e2SPeter Wemm
3434c2aa98e2SPeter Wemm if (tTd(52, 1))
343540266059SGregory Neil Shapiro sm_dprintf("disconnect: In %d Out %d, e=%p\n",
343640266059SGregory Neil Shapiro sm_io_getinfo(InChannel, SM_IO_WHAT_FD, NULL),
34375b0945b5SGregory Neil Shapiro sm_io_getinfo(OutChannel, SM_IO_WHAT_FD, NULL),
34385b0945b5SGregory Neil Shapiro (void *)e);
3439c2aa98e2SPeter Wemm if (tTd(52, 100))
3440c2aa98e2SPeter Wemm {
344140266059SGregory Neil Shapiro sm_dprintf("don't\n");
3442c2aa98e2SPeter Wemm return;
3443c2aa98e2SPeter Wemm }
3444c2aa98e2SPeter Wemm if (LogLevel > 93)
34452fb4f839SGregory Neil Shapiro sm_syslog(LOG_DEBUG, LOGID(e),
3446c2aa98e2SPeter Wemm "disconnect level %d",
3447c2aa98e2SPeter Wemm droplev);
3448c2aa98e2SPeter Wemm
3449c2aa98e2SPeter Wemm /* be sure we don't get nasty signals */
345040266059SGregory Neil Shapiro (void) sm_signal(SIGINT, SIG_IGN);
345140266059SGregory Neil Shapiro (void) sm_signal(SIGQUIT, SIG_IGN);
3452c2aa98e2SPeter Wemm
3453c2aa98e2SPeter Wemm /* we can't communicate with our caller, so.... */
345440266059SGregory Neil Shapiro HoldErrs = true;
3455c2aa98e2SPeter Wemm CurEnv->e_errormode = EM_MAIL;
3456c2aa98e2SPeter Wemm Verbose = 0;
345740266059SGregory Neil Shapiro DisConnected = true;
3458c2aa98e2SPeter Wemm
3459c2aa98e2SPeter Wemm /* all input from /dev/null */
346040266059SGregory Neil Shapiro if (InChannel != smioin)
3461c2aa98e2SPeter Wemm {
346240266059SGregory Neil Shapiro (void) sm_io_close(InChannel, SM_TIME_DEFAULT);
346340266059SGregory Neil Shapiro InChannel = smioin;
3464c2aa98e2SPeter Wemm }
346540266059SGregory Neil Shapiro if (sm_io_reopen(SmFtStdio, SM_TIME_DEFAULT, SM_PATH_DEVNULL,
346640266059SGregory Neil Shapiro SM_IO_RDONLY, NULL, smioin) == NULL)
34672fb4f839SGregory Neil Shapiro sm_syslog(LOG_ERR, LOGID(e),
346840266059SGregory Neil Shapiro "disconnect: sm_io_reopen(\"%s\") failed: %s",
346940266059SGregory Neil Shapiro SM_PATH_DEVNULL, sm_errstring(errno));
3470c2aa98e2SPeter Wemm
347140266059SGregory Neil Shapiro /*
347240266059SGregory Neil Shapiro ** output to the transcript
347340266059SGregory Neil Shapiro ** We also compare the fd numbers here since OutChannel
347440266059SGregory Neil Shapiro ** might be a layer on top of smioout due to encryption
347540266059SGregory Neil Shapiro ** (see sfsasl.c).
347640266059SGregory Neil Shapiro */
347740266059SGregory Neil Shapiro
347840266059SGregory Neil Shapiro if (OutChannel != smioout &&
347940266059SGregory Neil Shapiro sm_io_getinfo(OutChannel, SM_IO_WHAT_FD, NULL) !=
348040266059SGregory Neil Shapiro sm_io_getinfo(smioout, SM_IO_WHAT_FD, NULL))
3481c2aa98e2SPeter Wemm {
348240266059SGregory Neil Shapiro (void) sm_io_close(OutChannel, SM_TIME_DEFAULT);
348340266059SGregory Neil Shapiro OutChannel = smioout;
348440266059SGregory Neil Shapiro
348540266059SGregory Neil Shapiro #if 0
348640266059SGregory Neil Shapiro /*
348740266059SGregory Neil Shapiro ** Has smioout been closed? Reopen it.
348840266059SGregory Neil Shapiro ** This shouldn't happen anymore, the code is here
348940266059SGregory Neil Shapiro ** just as a reminder.
349040266059SGregory Neil Shapiro */
349140266059SGregory Neil Shapiro
349240266059SGregory Neil Shapiro if (smioout->sm_magic == NULL &&
349340266059SGregory Neil Shapiro sm_io_reopen(SmFtStdio, SM_TIME_DEFAULT, SM_PATH_DEVNULL,
349440266059SGregory Neil Shapiro SM_IO_WRONLY, NULL, smioout) == NULL)
34952fb4f839SGregory Neil Shapiro sm_syslog(LOG_ERR, LOGID(e),
349640266059SGregory Neil Shapiro "disconnect: sm_io_reopen(\"%s\") failed: %s",
349740266059SGregory Neil Shapiro SM_PATH_DEVNULL, sm_errstring(errno));
349840266059SGregory Neil Shapiro #endif /* 0 */
3499c2aa98e2SPeter Wemm }
3500c2aa98e2SPeter Wemm if (droplev > 0)
3501c2aa98e2SPeter Wemm {
350240266059SGregory Neil Shapiro fd = open(SM_PATH_DEVNULL, O_WRONLY, 0666);
3503c2aa98e2SPeter Wemm if (fd == -1)
3504af9557fdSGregory Neil Shapiro {
35052fb4f839SGregory Neil Shapiro sm_syslog(LOG_ERR, LOGID(e),
350640266059SGregory Neil Shapiro "disconnect: open(\"%s\") failed: %s",
350740266059SGregory Neil Shapiro SM_PATH_DEVNULL, sm_errstring(errno));
3508af9557fdSGregory Neil Shapiro }
350940266059SGregory Neil Shapiro (void) sm_io_flush(smioout, SM_TIME_DEFAULT);
3510af9557fdSGregory Neil Shapiro if (fd >= 0)
3511af9557fdSGregory Neil Shapiro {
351206f25ae9SGregory Neil Shapiro (void) dup2(fd, STDOUT_FILENO);
351306f25ae9SGregory Neil Shapiro (void) dup2(fd, STDERR_FILENO);
351406f25ae9SGregory Neil Shapiro (void) close(fd);
3515c2aa98e2SPeter Wemm }
3516af9557fdSGregory Neil Shapiro }
3517c2aa98e2SPeter Wemm
3518c2aa98e2SPeter Wemm /* drop our controlling TTY completely if possible */
3519c2aa98e2SPeter Wemm if (droplev > 1)
3520c2aa98e2SPeter Wemm {
3521c2aa98e2SPeter Wemm (void) setsid();
3522c2aa98e2SPeter Wemm errno = 0;
3523c2aa98e2SPeter Wemm }
3524c2aa98e2SPeter Wemm
3525c2aa98e2SPeter Wemm checkfd012("disconnect");
3526c2aa98e2SPeter Wemm
3527c2aa98e2SPeter Wemm if (LogLevel > 71)
35282fb4f839SGregory Neil Shapiro sm_syslog(LOG_DEBUG, LOGID(e), "in background, pid=%d",
352940266059SGregory Neil Shapiro (int) CurrentPid);
3530c2aa98e2SPeter Wemm
3531c2aa98e2SPeter Wemm errno = 0;
3532c2aa98e2SPeter Wemm }
3533c2aa98e2SPeter Wemm
3534c2aa98e2SPeter Wemm static void
obsolete(argv)3535c2aa98e2SPeter Wemm obsolete(argv)
3536c2aa98e2SPeter Wemm char *argv[];
3537c2aa98e2SPeter Wemm {
3538c2aa98e2SPeter Wemm register char *ap;
3539c2aa98e2SPeter Wemm register char *op;
3540c2aa98e2SPeter Wemm
3541c2aa98e2SPeter Wemm while ((ap = *++argv) != NULL)
3542c2aa98e2SPeter Wemm {
3543c2aa98e2SPeter Wemm /* Return if "--" or not an option of any form. */
3544c2aa98e2SPeter Wemm if (ap[0] != '-' || ap[1] == '-')
3545c2aa98e2SPeter Wemm return;
3546c2aa98e2SPeter Wemm
354740266059SGregory Neil Shapiro /* Don't allow users to use "-Q." or "-Q ." */
354840266059SGregory Neil Shapiro if ((ap[1] == 'Q' && ap[2] == '.') ||
354940266059SGregory Neil Shapiro (ap[1] == 'Q' && argv[1] != NULL &&
355040266059SGregory Neil Shapiro argv[1][0] == '.' && argv[1][1] == '\0'))
355140266059SGregory Neil Shapiro {
355240266059SGregory Neil Shapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
355340266059SGregory Neil Shapiro "Can not use -Q.\n");
355440266059SGregory Neil Shapiro exit(EX_USAGE);
355540266059SGregory Neil Shapiro }
355640266059SGregory Neil Shapiro
3557c2aa98e2SPeter Wemm /* skip over options that do have a value */
3558c2aa98e2SPeter Wemm op = strchr(OPTIONS, ap[1]);
3559c2aa98e2SPeter Wemm if (op != NULL && *++op == ':' && ap[2] == '\0' &&
3560c2aa98e2SPeter Wemm ap[1] != 'd' &&
3561c2aa98e2SPeter Wemm #if defined(sony_news)
3562c2aa98e2SPeter Wemm ap[1] != 'E' && ap[1] != 'J' &&
35635b0945b5SGregory Neil Shapiro #endif
3564c2aa98e2SPeter Wemm argv[1] != NULL && argv[1][0] != '-')
3565c2aa98e2SPeter Wemm {
3566c2aa98e2SPeter Wemm argv++;
3567c2aa98e2SPeter Wemm continue;
3568c2aa98e2SPeter Wemm }
3569c2aa98e2SPeter Wemm
3570c2aa98e2SPeter Wemm /* If -C doesn't have an argument, use sendmail.cf. */
3571c2aa98e2SPeter Wemm #define __DEFPATH "sendmail.cf"
3572c2aa98e2SPeter Wemm if (ap[1] == 'C' && ap[2] == '\0')
3573c2aa98e2SPeter Wemm {
3574c2aa98e2SPeter Wemm *argv = xalloc(sizeof(__DEFPATH) + 2);
357540266059SGregory Neil Shapiro (void) sm_strlcpyn(argv[0], sizeof(__DEFPATH) + 2, 2,
357640266059SGregory Neil Shapiro "-C", __DEFPATH);
3577c2aa98e2SPeter Wemm }
3578c2aa98e2SPeter Wemm
3579c2aa98e2SPeter Wemm /* If -q doesn't have an argument, run it once. */
3580c2aa98e2SPeter Wemm if (ap[1] == 'q' && ap[2] == '\0')
3581c2aa98e2SPeter Wemm *argv = "-q0";
3582c2aa98e2SPeter Wemm
358340266059SGregory Neil Shapiro /* If -Q doesn't have an argument, disable quarantining */
358440266059SGregory Neil Shapiro if (ap[1] == 'Q' && ap[2] == '\0')
358540266059SGregory Neil Shapiro *argv = "-Q.";
358640266059SGregory Neil Shapiro
3587c2aa98e2SPeter Wemm /* if -d doesn't have an argument, use 0-99.1 */
3588c2aa98e2SPeter Wemm if (ap[1] == 'd' && ap[2] == '\0')
3589c2aa98e2SPeter Wemm *argv = "-d0-99.1";
3590c2aa98e2SPeter Wemm
3591c2aa98e2SPeter Wemm #if defined(sony_news)
3592c2aa98e2SPeter Wemm /* if -E doesn't have an argument, use -EC */
3593c2aa98e2SPeter Wemm if (ap[1] == 'E' && ap[2] == '\0')
3594c2aa98e2SPeter Wemm *argv = "-EC";
3595c2aa98e2SPeter Wemm
3596c2aa98e2SPeter Wemm /* if -J doesn't have an argument, use -JJ */
3597c2aa98e2SPeter Wemm if (ap[1] == 'J' && ap[2] == '\0')
3598c2aa98e2SPeter Wemm *argv = "-JJ";
359906f25ae9SGregory Neil Shapiro #endif /* defined(sony_news) */
3600c2aa98e2SPeter Wemm }
3601c2aa98e2SPeter Wemm }
360240266059SGregory Neil Shapiro /*
3603c2aa98e2SPeter Wemm ** AUTH_WARNING -- specify authorization warning
3604c2aa98e2SPeter Wemm **
3605c2aa98e2SPeter Wemm ** Parameters:
3606c2aa98e2SPeter Wemm ** e -- the current envelope.
3607c2aa98e2SPeter Wemm ** msg -- the text of the message.
3608c2aa98e2SPeter Wemm ** args -- arguments to the message.
3609c2aa98e2SPeter Wemm **
3610c2aa98e2SPeter Wemm ** Returns:
3611c2aa98e2SPeter Wemm ** none.
3612c2aa98e2SPeter Wemm */
3613c2aa98e2SPeter Wemm
3614c2aa98e2SPeter Wemm void
3615c2aa98e2SPeter Wemm #ifdef __STDC__
auth_warning(register ENVELOPE * e,const char * msg,...)3616c2aa98e2SPeter Wemm auth_warning(register ENVELOPE *e, const char *msg, ...)
361706f25ae9SGregory Neil Shapiro #else /* __STDC__ */
3618c2aa98e2SPeter Wemm auth_warning(e, msg, va_alist)
3619c2aa98e2SPeter Wemm register ENVELOPE *e;
3620c2aa98e2SPeter Wemm const char *msg;
3621c2aa98e2SPeter Wemm va_dcl
362206f25ae9SGregory Neil Shapiro #endif /* __STDC__ */
3623c2aa98e2SPeter Wemm {
3624c2aa98e2SPeter Wemm char buf[MAXLINE];
362540266059SGregory Neil Shapiro SM_VA_LOCAL_DECL
36262fb4f839SGregory Neil Shapiro char *p;
3627c2aa98e2SPeter Wemm static char hostbuf[48];
3628c2aa98e2SPeter Wemm
36292fb4f839SGregory Neil Shapiro if (!bitset(PRIV_AUTHWARNINGS, PrivacyFlags))
36302fb4f839SGregory Neil Shapiro return;
36312fb4f839SGregory Neil Shapiro
3632c2aa98e2SPeter Wemm if (hostbuf[0] == '\0')
3633193538b7SGregory Neil Shapiro {
3634193538b7SGregory Neil Shapiro struct hostent *hp;
3635193538b7SGregory Neil Shapiro
3636d0cef73dSGregory Neil Shapiro hp = myhostname(hostbuf, sizeof(hostbuf));
363740266059SGregory Neil Shapiro #if NETINET6
3638193538b7SGregory Neil Shapiro if (hp != NULL)
3639193538b7SGregory Neil Shapiro {
3640193538b7SGregory Neil Shapiro freehostent(hp);
3641193538b7SGregory Neil Shapiro hp = NULL;
3642193538b7SGregory Neil Shapiro }
364340266059SGregory Neil Shapiro #endif /* NETINET6 */
3644193538b7SGregory Neil Shapiro }
3645c2aa98e2SPeter Wemm
3646d0cef73dSGregory Neil Shapiro (void) sm_strlcpyn(buf, sizeof(buf), 2, hostbuf, ": ");
3647c2aa98e2SPeter Wemm p = &buf[strlen(buf)];
364840266059SGregory Neil Shapiro SM_VA_START(ap, msg);
364940266059SGregory Neil Shapiro (void) sm_vsnprintf(p, SPACELEFT(buf, p), msg, ap);
365040266059SGregory Neil Shapiro SM_VA_END(ap);
3651d0cef73dSGregory Neil Shapiro addheader("X-Authentication-Warning", buf, 0, e, true);
3652c2aa98e2SPeter Wemm if (LogLevel > 3)
3653c2aa98e2SPeter Wemm sm_syslog(LOG_INFO, e->e_id,
36542fb4f839SGregory Neil Shapiro "Authentication-Warning: %.400s", buf);
3655c2aa98e2SPeter Wemm }
365640266059SGregory Neil Shapiro /*
3657c2aa98e2SPeter Wemm ** GETEXTENV -- get from external environment
3658c2aa98e2SPeter Wemm **
3659c2aa98e2SPeter Wemm ** Parameters:
3660c2aa98e2SPeter Wemm ** envar -- the name of the variable to retrieve
3661c2aa98e2SPeter Wemm **
3662c2aa98e2SPeter Wemm ** Returns:
3663c2aa98e2SPeter Wemm ** The value, if any.
3664c2aa98e2SPeter Wemm */
3665c2aa98e2SPeter Wemm
366640266059SGregory Neil Shapiro static char *
getextenv(envar)3667c2aa98e2SPeter Wemm getextenv(envar)
3668c2aa98e2SPeter Wemm const char *envar;
3669c2aa98e2SPeter Wemm {
3670c2aa98e2SPeter Wemm char **envp;
3671c2aa98e2SPeter Wemm int l;
3672c2aa98e2SPeter Wemm
3673c2aa98e2SPeter Wemm l = strlen(envar);
3674959366dcSGregory Neil Shapiro for (envp = ExternalEnviron; envp != NULL && *envp != NULL; envp++)
3675c2aa98e2SPeter Wemm {
3676c2aa98e2SPeter Wemm if (strncmp(*envp, envar, l) == 0 && (*envp)[l] == '=')
3677c2aa98e2SPeter Wemm return &(*envp)[l + 1];
3678c2aa98e2SPeter Wemm }
3679c2aa98e2SPeter Wemm return NULL;
3680c2aa98e2SPeter Wemm }
368140266059SGregory Neil Shapiro /*
36824e4196cbSGregory Neil Shapiro ** SM_SETUSERENV -- set an environment variable in the propagated environment
3683c2aa98e2SPeter Wemm **
3684c2aa98e2SPeter Wemm ** Parameters:
3685c2aa98e2SPeter Wemm ** envar -- the name of the environment variable.
3686c2aa98e2SPeter Wemm ** value -- the value to which it should be set. If
3687c2aa98e2SPeter Wemm ** null, this is extracted from the incoming
3688c2aa98e2SPeter Wemm ** environment. If that is not set, the call
36894e4196cbSGregory Neil Shapiro ** to sm_setuserenv is ignored.
3690c2aa98e2SPeter Wemm **
3691c2aa98e2SPeter Wemm ** Returns:
3692c2aa98e2SPeter Wemm ** none.
3693c2aa98e2SPeter Wemm */
3694c2aa98e2SPeter Wemm
3695c2aa98e2SPeter Wemm void
sm_setuserenv(envar,value)36964e4196cbSGregory Neil Shapiro sm_setuserenv(envar, value)
3697c2aa98e2SPeter Wemm const char *envar;
3698c2aa98e2SPeter Wemm const char *value;
3699c2aa98e2SPeter Wemm {
370006f25ae9SGregory Neil Shapiro int i, l;
3701c2aa98e2SPeter Wemm char **evp = UserEnviron;
3702c2aa98e2SPeter Wemm char *p;
3703c2aa98e2SPeter Wemm
3704c2aa98e2SPeter Wemm if (value == NULL)
3705c2aa98e2SPeter Wemm {
3706c2aa98e2SPeter Wemm value = getextenv(envar);
3707c2aa98e2SPeter Wemm if (value == NULL)
3708c2aa98e2SPeter Wemm return;
3709c2aa98e2SPeter Wemm }
3710c2aa98e2SPeter Wemm
371140266059SGregory Neil Shapiro /* XXX enforce reasonable size? */
371206f25ae9SGregory Neil Shapiro i = strlen(envar) + 1;
371306f25ae9SGregory Neil Shapiro l = strlen(value) + i + 1;
37142fb4f839SGregory Neil Shapiro p = (char *) sm_malloc_tagged_x(l, "setuserenv", 0, 0);
371540266059SGregory Neil Shapiro (void) sm_strlcpyn(p, l, 3, envar, "=", value);
3716c2aa98e2SPeter Wemm
3717c2aa98e2SPeter Wemm while (*evp != NULL && strncmp(*evp, p, i) != 0)
3718c2aa98e2SPeter Wemm evp++;
3719c2aa98e2SPeter Wemm if (*evp != NULL)
3720c2aa98e2SPeter Wemm {
3721c2aa98e2SPeter Wemm *evp++ = p;
3722c2aa98e2SPeter Wemm }
3723c2aa98e2SPeter Wemm else if (evp < &UserEnviron[MAXUSERENVIRON])
3724c2aa98e2SPeter Wemm {
3725c2aa98e2SPeter Wemm *evp++ = p;
3726c2aa98e2SPeter Wemm *evp = NULL;
3727c2aa98e2SPeter Wemm }
3728c2aa98e2SPeter Wemm
3729c2aa98e2SPeter Wemm /* make sure it is in our environment as well */
3730c2aa98e2SPeter Wemm if (putenv(p) < 0)
37314e4196cbSGregory Neil Shapiro syserr("sm_setuserenv: putenv(%s) failed", p);
3732c2aa98e2SPeter Wemm }
373340266059SGregory Neil Shapiro /*
3734c2aa98e2SPeter Wemm ** DUMPSTATE -- dump state
3735c2aa98e2SPeter Wemm **
3736c2aa98e2SPeter Wemm ** For debugging.
3737c2aa98e2SPeter Wemm */
3738c2aa98e2SPeter Wemm
3739c2aa98e2SPeter Wemm void
dumpstate(when)3740c2aa98e2SPeter Wemm dumpstate(when)
3741c2aa98e2SPeter Wemm char *when;
3742c2aa98e2SPeter Wemm {
3743c2aa98e2SPeter Wemm register char *j = macvalue('j', CurEnv);
3744c2aa98e2SPeter Wemm int rs;
374506f25ae9SGregory Neil Shapiro extern int NextMacroId;
3746c2aa98e2SPeter Wemm
3747c2aa98e2SPeter Wemm sm_syslog(LOG_DEBUG, CurEnv->e_id,
3748c2aa98e2SPeter Wemm "--- dumping state on %s: $j = %s ---",
3749c2aa98e2SPeter Wemm when,
3750c2aa98e2SPeter Wemm j == NULL ? "<NULL>" : j);
3751c2aa98e2SPeter Wemm if (j != NULL)
3752c2aa98e2SPeter Wemm {
3753c2aa98e2SPeter Wemm if (!wordinclass(j, 'w'))
3754c2aa98e2SPeter Wemm sm_syslog(LOG_DEBUG, CurEnv->e_id,
3755c2aa98e2SPeter Wemm "*** $j not in $=w ***");
3756c2aa98e2SPeter Wemm }
3757c2aa98e2SPeter Wemm sm_syslog(LOG_DEBUG, CurEnv->e_id, "CurChildren = %d", CurChildren);
375840266059SGregory Neil Shapiro sm_syslog(LOG_DEBUG, CurEnv->e_id, "NextMacroId = %d (Max %d)",
375906f25ae9SGregory Neil Shapiro NextMacroId, MAXMACROID);
3760c2aa98e2SPeter Wemm sm_syslog(LOG_DEBUG, CurEnv->e_id, "--- open file descriptors: ---");
376140266059SGregory Neil Shapiro printopenfds(true);
3762c2aa98e2SPeter Wemm sm_syslog(LOG_DEBUG, CurEnv->e_id, "--- connection cache: ---");
3763e92d3f3fSGregory Neil Shapiro mci_dump_all(smioout, true);
3764c2aa98e2SPeter Wemm rs = strtorwset("debug_dumpstate", NULL, ST_FIND);
3765c2aa98e2SPeter Wemm if (rs > 0)
3766c2aa98e2SPeter Wemm {
376706f25ae9SGregory Neil Shapiro int status;
3768c2aa98e2SPeter Wemm register char **pvp;
3769c2aa98e2SPeter Wemm char *pv[MAXATOM + 1];
3770c2aa98e2SPeter Wemm
3771c2aa98e2SPeter Wemm pv[0] = NULL;
377240266059SGregory Neil Shapiro status = REWRITE(pv, rs, CurEnv);
3773c2aa98e2SPeter Wemm sm_syslog(LOG_DEBUG, CurEnv->e_id,
3774c2aa98e2SPeter Wemm "--- ruleset debug_dumpstate returns stat %d, pv: ---",
377506f25ae9SGregory Neil Shapiro status);
3776c2aa98e2SPeter Wemm for (pvp = pv; *pvp != NULL; pvp++)
3777c2aa98e2SPeter Wemm sm_syslog(LOG_DEBUG, CurEnv->e_id, "%s", *pvp);
3778c2aa98e2SPeter Wemm }
3779c2aa98e2SPeter Wemm sm_syslog(LOG_DEBUG, CurEnv->e_id, "--- end of state dump ---");
3780c2aa98e2SPeter Wemm }
378140266059SGregory Neil Shapiro
378213058a91SGregory Neil Shapiro #ifdef SIGUSR1
378340266059SGregory Neil Shapiro /*
37848774250cSGregory Neil Shapiro ** SIGUSR1 -- Signal a request to dump state.
37858774250cSGregory Neil Shapiro **
37868774250cSGregory Neil Shapiro ** Parameters:
37878774250cSGregory Neil Shapiro ** sig -- calling signal.
37888774250cSGregory Neil Shapiro **
37898774250cSGregory Neil Shapiro ** Returns:
37908774250cSGregory Neil Shapiro ** none.
37918774250cSGregory Neil Shapiro **
37928774250cSGregory Neil Shapiro ** NOTE: THIS CAN BE CALLED FROM A SIGNAL HANDLER. DO NOT ADD
37938774250cSGregory Neil Shapiro ** ANYTHING TO THIS ROUTINE UNLESS YOU KNOW WHAT YOU ARE
37948774250cSGregory Neil Shapiro ** DOING.
37958774250cSGregory Neil Shapiro **
37968774250cSGregory Neil Shapiro ** XXX: More work is needed for this signal handler.
37978774250cSGregory Neil Shapiro */
3798c2aa98e2SPeter Wemm
3799c2aa98e2SPeter Wemm /* ARGSUSED */
38008774250cSGregory Neil Shapiro static SIGFUNC_DECL
sigusr1(sig)3801c2aa98e2SPeter Wemm sigusr1(sig)
3802c2aa98e2SPeter Wemm int sig;
3803c2aa98e2SPeter Wemm {
38048774250cSGregory Neil Shapiro int save_errno = errno;
38058774250cSGregory Neil Shapiro
38068774250cSGregory Neil Shapiro FIX_SYSV_SIGNAL(sig, sigusr1);
38078774250cSGregory Neil Shapiro errno = save_errno;
38088774250cSGregory Neil Shapiro CHECK_CRITICAL(sig);
3809c2aa98e2SPeter Wemm dumpstate("user signal");
381040266059SGregory Neil Shapiro # if SM_HEAP_CHECK
381140266059SGregory Neil Shapiro dumpstab();
38125b0945b5SGregory Neil Shapiro # endif
38138774250cSGregory Neil Shapiro errno = save_errno;
3814c2aa98e2SPeter Wemm return SIGFUNC_RETURN;
3815c2aa98e2SPeter Wemm }
381613058a91SGregory Neil Shapiro #endif /* SIGUSR1 */
381740266059SGregory Neil Shapiro
381840266059SGregory Neil Shapiro /*
3819c2aa98e2SPeter Wemm ** DROP_PRIVILEGES -- reduce privileges to those of the RunAsUser option
3820c2aa98e2SPeter Wemm **
3821c2aa98e2SPeter Wemm ** Parameters:
3822c2aa98e2SPeter Wemm ** to_real_uid -- if set, drop to the real uid instead
3823c2aa98e2SPeter Wemm ** of the RunAsUser.
3824c2aa98e2SPeter Wemm **
3825c2aa98e2SPeter Wemm ** Returns:
3826c2aa98e2SPeter Wemm ** EX_OSERR if the setuid failed.
3827c2aa98e2SPeter Wemm ** EX_OK otherwise.
3828c2aa98e2SPeter Wemm */
3829c2aa98e2SPeter Wemm
3830c2aa98e2SPeter Wemm int
drop_privileges(to_real_uid)3831c2aa98e2SPeter Wemm drop_privileges(to_real_uid)
3832c2aa98e2SPeter Wemm bool to_real_uid;
3833c2aa98e2SPeter Wemm {
3834c2aa98e2SPeter Wemm int rval = EX_OK;
3835c2aa98e2SPeter Wemm GIDSET_T emptygidset[1];
3836c2aa98e2SPeter Wemm
3837c2aa98e2SPeter Wemm if (tTd(47, 1))
3838da7d7b9cSGregory Neil Shapiro sm_dprintf("drop_privileges(%d): Real[UG]id=%ld:%ld, get[ug]id=%ld:%ld, gete[ug]id=%ld:%ld, RunAs[UG]id=%ld:%ld\n",
383940266059SGregory Neil Shapiro (int) to_real_uid,
3840da7d7b9cSGregory Neil Shapiro (long) RealUid, (long) RealGid,
3841da7d7b9cSGregory Neil Shapiro (long) getuid(), (long) getgid(),
3842da7d7b9cSGregory Neil Shapiro (long) geteuid(), (long) getegid(),
3843da7d7b9cSGregory Neil Shapiro (long) RunAsUid, (long) RunAsGid);
3844c2aa98e2SPeter Wemm
3845c2aa98e2SPeter Wemm if (to_real_uid)
3846c2aa98e2SPeter Wemm {
3847c2aa98e2SPeter Wemm RunAsUserName = RealUserName;
3848c2aa98e2SPeter Wemm RunAsUid = RealUid;
3849c2aa98e2SPeter Wemm RunAsGid = RealGid;
3850605302a5SGregory Neil Shapiro EffGid = RunAsGid;
3851c2aa98e2SPeter Wemm }
3852c2aa98e2SPeter Wemm
3853c2aa98e2SPeter Wemm /* make sure no one can grab open descriptors for secret files */
3854c2aa98e2SPeter Wemm endpwent();
385540266059SGregory Neil Shapiro sm_mbdb_terminate();
3856c2aa98e2SPeter Wemm
3857c2aa98e2SPeter Wemm /* reset group permissions; these can be set later */
3858c2aa98e2SPeter Wemm emptygidset[0] = (to_real_uid || RunAsGid != 0) ? RunAsGid : getegid();
385940266059SGregory Neil Shapiro
386040266059SGregory Neil Shapiro /*
386140266059SGregory Neil Shapiro ** Notice: on some OS (Linux...) the setgroups() call causes
386240266059SGregory Neil Shapiro ** a logfile entry if sendmail is not run by root.
386340266059SGregory Neil Shapiro ** However, it is unclear (no POSIX standard) whether
386440266059SGregory Neil Shapiro ** setgroups() can only succeed if executed by root.
386540266059SGregory Neil Shapiro ** So for now we keep it as it is; if you want to change it, use
386640266059SGregory Neil Shapiro ** if (geteuid() == 0 && setgroups(1, emptygidset) == -1)
386740266059SGregory Neil Shapiro */
386840266059SGregory Neil Shapiro
3869c2aa98e2SPeter Wemm if (setgroups(1, emptygidset) == -1 && geteuid() == 0)
387006f25ae9SGregory Neil Shapiro {
387106f25ae9SGregory Neil Shapiro syserr("drop_privileges: setgroups(1, %d) failed",
387206f25ae9SGregory Neil Shapiro (int) emptygidset[0]);
3873c2aa98e2SPeter Wemm rval = EX_OSERR;
387406f25ae9SGregory Neil Shapiro }
3875c2aa98e2SPeter Wemm
387640266059SGregory Neil Shapiro /* reset primary group id */
387740266059SGregory Neil Shapiro if (to_real_uid)
387806f25ae9SGregory Neil Shapiro {
387940266059SGregory Neil Shapiro /*
388040266059SGregory Neil Shapiro ** Drop gid to real gid.
388140266059SGregory Neil Shapiro ** On some OS we must reset the effective[/real[/saved]] gid,
388240266059SGregory Neil Shapiro ** and then use setgid() to finally drop all group privileges.
388340266059SGregory Neil Shapiro ** Later on we check whether we can get back the
388440266059SGregory Neil Shapiro ** effective gid.
388540266059SGregory Neil Shapiro */
388640266059SGregory Neil Shapiro
388740266059SGregory Neil Shapiro #if HASSETEGID
388840266059SGregory Neil Shapiro if (setegid(RunAsGid) < 0)
388940266059SGregory Neil Shapiro {
389040266059SGregory Neil Shapiro syserr("drop_privileges: setegid(%d) failed",
389140266059SGregory Neil Shapiro (int) RunAsGid);
3892c2aa98e2SPeter Wemm rval = EX_OSERR;
389306f25ae9SGregory Neil Shapiro }
389440266059SGregory Neil Shapiro #else /* HASSETEGID */
389540266059SGregory Neil Shapiro # if HASSETREGID
389640266059SGregory Neil Shapiro if (setregid(RunAsGid, RunAsGid) < 0)
389740266059SGregory Neil Shapiro {
389840266059SGregory Neil Shapiro syserr("drop_privileges: setregid(%d, %d) failed",
389940266059SGregory Neil Shapiro (int) RunAsGid, (int) RunAsGid);
390040266059SGregory Neil Shapiro rval = EX_OSERR;
390140266059SGregory Neil Shapiro }
390240266059SGregory Neil Shapiro # else /* HASSETREGID */
390340266059SGregory Neil Shapiro # if HASSETRESGID
390440266059SGregory Neil Shapiro if (setresgid(RunAsGid, RunAsGid, RunAsGid) < 0)
390540266059SGregory Neil Shapiro {
390640266059SGregory Neil Shapiro syserr("drop_privileges: setresgid(%d, %d, %d) failed",
390740266059SGregory Neil Shapiro (int) RunAsGid, (int) RunAsGid, (int) RunAsGid);
390840266059SGregory Neil Shapiro rval = EX_OSERR;
390940266059SGregory Neil Shapiro }
391040266059SGregory Neil Shapiro # endif /* HASSETRESGID */
391140266059SGregory Neil Shapiro # endif /* HASSETREGID */
391240266059SGregory Neil Shapiro #endif /* HASSETEGID */
391340266059SGregory Neil Shapiro }
391440266059SGregory Neil Shapiro if (rval == EX_OK && (to_real_uid || RunAsGid != 0))
391540266059SGregory Neil Shapiro {
391640266059SGregory Neil Shapiro if (setgid(RunAsGid) < 0 && (!UseMSP || getegid() != RunAsGid))
391740266059SGregory Neil Shapiro {
3918da7d7b9cSGregory Neil Shapiro syserr("drop_privileges: setgid(%ld) failed",
3919da7d7b9cSGregory Neil Shapiro (long) RunAsGid);
392040266059SGregory Neil Shapiro rval = EX_OSERR;
392140266059SGregory Neil Shapiro }
392240266059SGregory Neil Shapiro errno = 0;
392340266059SGregory Neil Shapiro if (rval == EX_OK && getegid() != RunAsGid)
392440266059SGregory Neil Shapiro {
3925da7d7b9cSGregory Neil Shapiro syserr("drop_privileges: Unable to set effective gid=%ld to RunAsGid=%ld",
3926da7d7b9cSGregory Neil Shapiro (long) getegid(), (long) RunAsGid);
392740266059SGregory Neil Shapiro rval = EX_OSERR;
392840266059SGregory Neil Shapiro }
392940266059SGregory Neil Shapiro }
393040266059SGregory Neil Shapiro
393140266059SGregory Neil Shapiro /* fiddle with uid */
393206f25ae9SGregory Neil Shapiro if (to_real_uid || RunAsUid != 0)
393306f25ae9SGregory Neil Shapiro {
3934605302a5SGregory Neil Shapiro uid_t euid;
393506f25ae9SGregory Neil Shapiro
393640266059SGregory Neil Shapiro /*
393740266059SGregory Neil Shapiro ** Try to setuid(RunAsUid).
393840266059SGregory Neil Shapiro ** euid must be RunAsUid,
3939605302a5SGregory Neil Shapiro ** ruid must be RunAsUid unless (e|r)uid wasn't 0
3940605302a5SGregory Neil Shapiro ** and we didn't have to drop privileges to the real uid.
394140266059SGregory Neil Shapiro */
394240266059SGregory Neil Shapiro
394340266059SGregory Neil Shapiro if (setuid(RunAsUid) < 0 ||
3944605302a5SGregory Neil Shapiro geteuid() != RunAsUid ||
394540266059SGregory Neil Shapiro (getuid() != RunAsUid &&
3946605302a5SGregory Neil Shapiro (to_real_uid || geteuid() == 0 || getuid() == 0)))
394740266059SGregory Neil Shapiro {
394840266059SGregory Neil Shapiro #if HASSETREUID
394940266059SGregory Neil Shapiro /*
395040266059SGregory Neil Shapiro ** if ruid != RunAsUid, euid == RunAsUid, then
395140266059SGregory Neil Shapiro ** try resetting just the real uid, then using
395240266059SGregory Neil Shapiro ** setuid() to drop the saved-uid as well.
395340266059SGregory Neil Shapiro */
395440266059SGregory Neil Shapiro
3955605302a5SGregory Neil Shapiro if (geteuid() == RunAsUid)
395640266059SGregory Neil Shapiro {
395740266059SGregory Neil Shapiro if (setreuid(RunAsUid, -1) < 0)
395840266059SGregory Neil Shapiro {
395940266059SGregory Neil Shapiro syserr("drop_privileges: setreuid(%d, -1) failed",
396040266059SGregory Neil Shapiro (int) RunAsUid);
396140266059SGregory Neil Shapiro rval = EX_OSERR;
396240266059SGregory Neil Shapiro }
396306f25ae9SGregory Neil Shapiro if (setuid(RunAsUid) < 0)
396406f25ae9SGregory Neil Shapiro {
396540266059SGregory Neil Shapiro syserr("drop_privileges: second setuid(%d) attempt failed",
396640266059SGregory Neil Shapiro (int) RunAsUid);
396740266059SGregory Neil Shapiro rval = EX_OSERR;
396840266059SGregory Neil Shapiro }
396940266059SGregory Neil Shapiro }
397040266059SGregory Neil Shapiro else
397140266059SGregory Neil Shapiro #endif /* HASSETREUID */
397240266059SGregory Neil Shapiro {
397306f25ae9SGregory Neil Shapiro syserr("drop_privileges: setuid(%d) failed",
397406f25ae9SGregory Neil Shapiro (int) RunAsUid);
3975c2aa98e2SPeter Wemm rval = EX_OSERR;
397606f25ae9SGregory Neil Shapiro }
397740266059SGregory Neil Shapiro }
3978605302a5SGregory Neil Shapiro euid = geteuid();
397940266059SGregory Neil Shapiro if (RunAsUid != 0 && setuid(0) == 0)
398006f25ae9SGregory Neil Shapiro {
398106f25ae9SGregory Neil Shapiro /*
398206f25ae9SGregory Neil Shapiro ** Believe it or not, the Linux capability model
398306f25ae9SGregory Neil Shapiro ** allows a non-root process to override setuid()
398406f25ae9SGregory Neil Shapiro ** on a process running as root and prevent that
398506f25ae9SGregory Neil Shapiro ** process from dropping privileges.
398606f25ae9SGregory Neil Shapiro */
398706f25ae9SGregory Neil Shapiro
398806f25ae9SGregory Neil Shapiro syserr("drop_privileges: setuid(0) succeeded (when it should not)");
398906f25ae9SGregory Neil Shapiro rval = EX_OSERR;
399006f25ae9SGregory Neil Shapiro }
399106f25ae9SGregory Neil Shapiro else if (RunAsUid != euid && setuid(euid) == 0)
399206f25ae9SGregory Neil Shapiro {
399306f25ae9SGregory Neil Shapiro /*
399406f25ae9SGregory Neil Shapiro ** Some operating systems will keep the saved-uid
399506f25ae9SGregory Neil Shapiro ** if a non-root effective-uid calls setuid(real-uid)
399606f25ae9SGregory Neil Shapiro ** making it possible to set it back again later.
399706f25ae9SGregory Neil Shapiro */
399806f25ae9SGregory Neil Shapiro
399940266059SGregory Neil Shapiro syserr("drop_privileges: Unable to drop non-root set-user-ID privileges");
400006f25ae9SGregory Neil Shapiro rval = EX_OSERR;
400106f25ae9SGregory Neil Shapiro }
400206f25ae9SGregory Neil Shapiro }
400340266059SGregory Neil Shapiro
400440266059SGregory Neil Shapiro if ((to_real_uid || RunAsGid != 0) &&
400540266059SGregory Neil Shapiro rval == EX_OK && RunAsGid != EffGid &&
400640266059SGregory Neil Shapiro getuid() != 0 && geteuid() != 0)
400740266059SGregory Neil Shapiro {
400840266059SGregory Neil Shapiro errno = 0;
400940266059SGregory Neil Shapiro if (setgid(EffGid) == 0)
401040266059SGregory Neil Shapiro {
401140266059SGregory Neil Shapiro syserr("drop_privileges: setgid(%d) succeeded (when it should not)",
401240266059SGregory Neil Shapiro (int) EffGid);
401340266059SGregory Neil Shapiro rval = EX_OSERR;
401440266059SGregory Neil Shapiro }
401540266059SGregory Neil Shapiro }
401640266059SGregory Neil Shapiro
4017c2aa98e2SPeter Wemm if (tTd(47, 5))
4018c2aa98e2SPeter Wemm {
401940266059SGregory Neil Shapiro sm_dprintf("drop_privileges: e/ruid = %d/%d e/rgid = %d/%d\n",
402006f25ae9SGregory Neil Shapiro (int) geteuid(), (int) getuid(),
402106f25ae9SGregory Neil Shapiro (int) getegid(), (int) getgid());
402240266059SGregory Neil Shapiro sm_dprintf("drop_privileges: RunAsUser = %d:%d\n",
402306f25ae9SGregory Neil Shapiro (int) RunAsUid, (int) RunAsGid);
402406f25ae9SGregory Neil Shapiro if (tTd(47, 10))
402540266059SGregory Neil Shapiro sm_dprintf("drop_privileges: rval = %d\n", rval);
4026c2aa98e2SPeter Wemm }
4027c2aa98e2SPeter Wemm return rval;
4028c2aa98e2SPeter Wemm }
402940266059SGregory Neil Shapiro /*
4030c2aa98e2SPeter Wemm ** FILL_FD -- make sure a file descriptor has been properly allocated
4031c2aa98e2SPeter Wemm **
4032c2aa98e2SPeter Wemm ** Used to make sure that stdin/out/err are allocated on startup
4033c2aa98e2SPeter Wemm **
4034c2aa98e2SPeter Wemm ** Parameters:
4035c2aa98e2SPeter Wemm ** fd -- the file descriptor to be filled.
4036c2aa98e2SPeter Wemm ** where -- a string used for logging. If NULL, this is
4037c2aa98e2SPeter Wemm ** being called on startup, and logging should
4038c2aa98e2SPeter Wemm ** not be done.
4039c2aa98e2SPeter Wemm **
4040c2aa98e2SPeter Wemm ** Returns:
4041c2aa98e2SPeter Wemm ** none
404240266059SGregory Neil Shapiro **
404340266059SGregory Neil Shapiro ** Side Effects:
404440266059SGregory Neil Shapiro ** possibly changes MissingFds
4045c2aa98e2SPeter Wemm */
4046c2aa98e2SPeter Wemm
4047c2aa98e2SPeter Wemm void
fill_fd(fd,where)4048c2aa98e2SPeter Wemm fill_fd(fd, where)
4049c2aa98e2SPeter Wemm int fd;
4050c2aa98e2SPeter Wemm char *where;
4051c2aa98e2SPeter Wemm {
4052c2aa98e2SPeter Wemm int i;
4053c2aa98e2SPeter Wemm struct stat stbuf;
4054c2aa98e2SPeter Wemm
4055c2aa98e2SPeter Wemm if (fstat(fd, &stbuf) >= 0 || errno != EBADF)
4056c2aa98e2SPeter Wemm return;
4057c2aa98e2SPeter Wemm
4058c2aa98e2SPeter Wemm if (where != NULL)
4059c2aa98e2SPeter Wemm syserr("fill_fd: %s: fd %d not open", where, fd);
4060c2aa98e2SPeter Wemm else
4061c2aa98e2SPeter Wemm MissingFds |= 1 << fd;
406240266059SGregory Neil Shapiro i = open(SM_PATH_DEVNULL, fd == 0 ? O_RDONLY : O_WRONLY, 0666);
4063c2aa98e2SPeter Wemm if (i < 0)
4064c2aa98e2SPeter Wemm {
406540266059SGregory Neil Shapiro syserr("!fill_fd: %s: cannot open %s",
406640266059SGregory Neil Shapiro where == NULL ? "startup" : where, SM_PATH_DEVNULL);
4067c2aa98e2SPeter Wemm }
4068c2aa98e2SPeter Wemm if (fd != i)
4069c2aa98e2SPeter Wemm {
4070c2aa98e2SPeter Wemm (void) dup2(i, fd);
4071c2aa98e2SPeter Wemm (void) close(i);
4072c2aa98e2SPeter Wemm }
4073c2aa98e2SPeter Wemm }
407440266059SGregory Neil Shapiro /*
407540266059SGregory Neil Shapiro ** SM_PRINTOPTIONS -- print options
407640266059SGregory Neil Shapiro **
407740266059SGregory Neil Shapiro ** Parameters:
407840266059SGregory Neil Shapiro ** options -- array of options.
407940266059SGregory Neil Shapiro **
408040266059SGregory Neil Shapiro ** Returns:
408140266059SGregory Neil Shapiro ** none.
408240266059SGregory Neil Shapiro */
408340266059SGregory Neil Shapiro
408440266059SGregory Neil Shapiro static void
sm_printoptions(options)408540266059SGregory Neil Shapiro sm_printoptions(options)
408640266059SGregory Neil Shapiro char **options;
408740266059SGregory Neil Shapiro {
408840266059SGregory Neil Shapiro int ll;
408940266059SGregory Neil Shapiro char **av;
409040266059SGregory Neil Shapiro
409140266059SGregory Neil Shapiro av = options;
409240266059SGregory Neil Shapiro ll = 7;
409340266059SGregory Neil Shapiro while (*av != NULL)
409440266059SGregory Neil Shapiro {
409540266059SGregory Neil Shapiro if (ll + strlen(*av) > 63)
409640266059SGregory Neil Shapiro {
409740266059SGregory Neil Shapiro sm_dprintf("\n");
409840266059SGregory Neil Shapiro ll = 0;
409940266059SGregory Neil Shapiro }
410040266059SGregory Neil Shapiro if (ll == 0)
410140266059SGregory Neil Shapiro sm_dprintf("\t\t");
410240266059SGregory Neil Shapiro else
410340266059SGregory Neil Shapiro sm_dprintf(" ");
410440266059SGregory Neil Shapiro sm_dprintf("%s", *av);
410540266059SGregory Neil Shapiro ll += strlen(*av++) + 1;
410640266059SGregory Neil Shapiro }
410740266059SGregory Neil Shapiro sm_dprintf("\n");
410840266059SGregory Neil Shapiro }
4109d0cef73dSGregory Neil Shapiro
4110d0cef73dSGregory Neil Shapiro /*
4111d0cef73dSGregory Neil Shapiro ** TO8BIT -- convert \octal sequences in a test mode input line
4112d0cef73dSGregory Neil Shapiro **
4113d0cef73dSGregory Neil Shapiro ** Parameters:
4114d0cef73dSGregory Neil Shapiro ** str -- the input line.
41152fb4f839SGregory Neil Shapiro ** mq -- "quote" meta chars?
4116d0cef73dSGregory Neil Shapiro **
4117d0cef73dSGregory Neil Shapiro ** Returns:
41182fb4f839SGregory Neil Shapiro ** meta quoting performed?
4119d0cef73dSGregory Neil Shapiro **
4120d0cef73dSGregory Neil Shapiro ** Side Effects:
41212fb4f839SGregory Neil Shapiro ** replaces \0octal in str with octal value,
41222fb4f839SGregory Neil Shapiro ** optionally (meta) quotes meta chars.
4123d0cef73dSGregory Neil Shapiro */
4124d0cef73dSGregory Neil Shapiro
41252fb4f839SGregory Neil Shapiro static bool to8bit __P((char *, bool));
4126d0cef73dSGregory Neil Shapiro
4127d0cef73dSGregory Neil Shapiro static bool
to8bit(str,mq)41282fb4f839SGregory Neil Shapiro to8bit(str, mq)
4129d0cef73dSGregory Neil Shapiro char *str;
41302fb4f839SGregory Neil Shapiro bool mq;
4131d0cef73dSGregory Neil Shapiro {
4132d0cef73dSGregory Neil Shapiro int c, len;
4133d0cef73dSGregory Neil Shapiro char *out, *in;
4134d0cef73dSGregory Neil Shapiro
4135d0cef73dSGregory Neil Shapiro if (str == NULL)
4136d0cef73dSGregory Neil Shapiro return false;
4137d0cef73dSGregory Neil Shapiro in = out = str;
4138d0cef73dSGregory Neil Shapiro len = 0;
4139d0cef73dSGregory Neil Shapiro while ((c = (*str++ & 0377)) != '\0')
4140d0cef73dSGregory Neil Shapiro {
4141d0cef73dSGregory Neil Shapiro int oct, nxtc;
4142d0cef73dSGregory Neil Shapiro
4143d0cef73dSGregory Neil Shapiro ++len;
4144d0cef73dSGregory Neil Shapiro if (c == '\\' &&
4145d0cef73dSGregory Neil Shapiro (nxtc = (*str & 0377)) == '0')
4146d0cef73dSGregory Neil Shapiro {
4147d0cef73dSGregory Neil Shapiro oct = 0;
4148d0cef73dSGregory Neil Shapiro while ((nxtc = (*str & 0377)) != '\0' &&
4149d0cef73dSGregory Neil Shapiro isascii(nxtc) && isdigit(nxtc))
4150d0cef73dSGregory Neil Shapiro {
4151d0cef73dSGregory Neil Shapiro oct <<= 3;
4152d0cef73dSGregory Neil Shapiro oct += nxtc - '0';
4153d0cef73dSGregory Neil Shapiro ++str;
4154d0cef73dSGregory Neil Shapiro ++len;
4155d0cef73dSGregory Neil Shapiro }
41562fb4f839SGregory Neil Shapiro mq = true;
4157d0cef73dSGregory Neil Shapiro c = oct;
4158d0cef73dSGregory Neil Shapiro }
4159d0cef73dSGregory Neil Shapiro *out++ = c;
4160d0cef73dSGregory Neil Shapiro }
4161d0cef73dSGregory Neil Shapiro *out++ = c;
41622fb4f839SGregory Neil Shapiro if (mq)
4163d0cef73dSGregory Neil Shapiro {
4164d0cef73dSGregory Neil Shapiro char *q;
4165d0cef73dSGregory Neil Shapiro
41662fb4f839SGregory Neil Shapiro q = quote_internal_chars(in, in, &len, NULL);
4167d0cef73dSGregory Neil Shapiro if (q != in)
4168d0cef73dSGregory Neil Shapiro sm_strlcpy(in, q, len);
4169d0cef73dSGregory Neil Shapiro }
41702fb4f839SGregory Neil Shapiro return mq;
4171d0cef73dSGregory Neil Shapiro }
4172d0cef73dSGregory Neil Shapiro
417340266059SGregory Neil Shapiro /*
4174c2aa98e2SPeter Wemm ** TESTMODELINE -- process a test mode input line
4175c2aa98e2SPeter Wemm **
4176c2aa98e2SPeter Wemm ** Parameters:
4177c2aa98e2SPeter Wemm ** line -- the input line.
4178c2aa98e2SPeter Wemm ** e -- the current environment.
4179c2aa98e2SPeter Wemm ** Syntax:
4180c2aa98e2SPeter Wemm ** # a comment
4181c2aa98e2SPeter Wemm ** .X process X as a configuration line
4182c2aa98e2SPeter Wemm ** =X dump a configuration item (such as mailers)
4183c2aa98e2SPeter Wemm ** $X dump a macro or class
4184c2aa98e2SPeter Wemm ** /X try an activity
4185c2aa98e2SPeter Wemm ** X normal process through rule set X
4186c2aa98e2SPeter Wemm */
4187c2aa98e2SPeter Wemm
418806f25ae9SGregory Neil Shapiro static void
testmodeline(line,e)4189c2aa98e2SPeter Wemm testmodeline(line, e)
4190c2aa98e2SPeter Wemm char *line;
4191c2aa98e2SPeter Wemm ENVELOPE *e;
4192c2aa98e2SPeter Wemm {
4193c2aa98e2SPeter Wemm register char *p;
4194c2aa98e2SPeter Wemm char *q;
4195c2aa98e2SPeter Wemm auto char *delimptr;
4196c2aa98e2SPeter Wemm int mid;
4197c2aa98e2SPeter Wemm int i, rs;
4198c2aa98e2SPeter Wemm STAB *map;
4199c2aa98e2SPeter Wemm char **s;
4200c2aa98e2SPeter Wemm struct rewrite *rw;
4201c2aa98e2SPeter Wemm ADDRESS a;
4202d0cef73dSGregory Neil Shapiro char *lbp;
4203d0cef73dSGregory Neil Shapiro auto int lbs;
4204c2aa98e2SPeter Wemm static int tryflags = RF_COPYNONE;
4205c2aa98e2SPeter Wemm char exbuf[MAXLINE];
4206d0cef73dSGregory Neil Shapiro char lbuf[MAXLINE];
420740266059SGregory Neil Shapiro extern unsigned char TokTypeNoC[];
4208d0cef73dSGregory Neil Shapiro bool eightbit;
42092fb4f839SGregory Neil Shapiro #if _FFR_8BITENVADDR
42102fb4f839SGregory Neil Shapiro int len = sizeof(exbuf);
42112fb4f839SGregory Neil Shapiro #endif
4212d39bd2c1SGregory Neil Shapiro #if _FFR_TESTS
4213d39bd2c1SGregory Neil Shapiro extern void t_hostsig __P((ADDRESS *, char *, MAILER *));
4214d39bd2c1SGregory Neil Shapiro extern void t_parsehostsig __P((char *, MAILER *));
4215d39bd2c1SGregory Neil Shapiro #endif
421642e5d165SGregory Neil Shapiro
421742e5d165SGregory Neil Shapiro /* skip leading spaces */
421842e5d165SGregory Neil Shapiro while (*line == ' ')
421942e5d165SGregory Neil Shapiro line++;
422042e5d165SGregory Neil Shapiro
4221d0cef73dSGregory Neil Shapiro lbp = NULL;
4222d0cef73dSGregory Neil Shapiro eightbit = false;
4223d39bd2c1SGregory Neil Shapiro maps_reset_chged("testmodeline");
4224c2aa98e2SPeter Wemm switch (line[0])
4225c2aa98e2SPeter Wemm {
4226c2aa98e2SPeter Wemm case '#':
422706f25ae9SGregory Neil Shapiro case '\0':
4228c2aa98e2SPeter Wemm return;
4229c2aa98e2SPeter Wemm
4230c2aa98e2SPeter Wemm case '?':
423106f25ae9SGregory Neil Shapiro help("-bt", e);
4232c2aa98e2SPeter Wemm return;
4233c2aa98e2SPeter Wemm
4234c2aa98e2SPeter Wemm case '.': /* config-style settings */
4235c2aa98e2SPeter Wemm switch (line[1])
4236c2aa98e2SPeter Wemm {
4237c2aa98e2SPeter Wemm case 'D':
423840266059SGregory Neil Shapiro mid = macid_parse(&line[2], &delimptr);
4239193538b7SGregory Neil Shapiro if (mid == 0)
4240c2aa98e2SPeter Wemm return;
4241d0cef73dSGregory Neil Shapiro lbs = sizeof(lbuf);
4242d0cef73dSGregory Neil Shapiro lbp = translate_dollars(delimptr, lbuf, &lbs);
4243d0cef73dSGregory Neil Shapiro macdefine(&e->e_macro, A_TEMP, mid, lbp);
4244d0cef73dSGregory Neil Shapiro if (lbp != lbuf)
4245d0cef73dSGregory Neil Shapiro SM_FREE(lbp);
4246c2aa98e2SPeter Wemm break;
4247c2aa98e2SPeter Wemm
4248c2aa98e2SPeter Wemm case 'C':
4249c2aa98e2SPeter Wemm if (line[2] == '\0') /* not to call syserr() */
4250c2aa98e2SPeter Wemm return;
4251c2aa98e2SPeter Wemm
425240266059SGregory Neil Shapiro mid = macid_parse(&line[2], &delimptr);
4253193538b7SGregory Neil Shapiro if (mid == 0)
4254c2aa98e2SPeter Wemm return;
4255d0cef73dSGregory Neil Shapiro lbs = sizeof(lbuf);
4256d0cef73dSGregory Neil Shapiro lbp = translate_dollars(delimptr, lbuf, &lbs);
4257d0cef73dSGregory Neil Shapiro expand(lbp, exbuf, sizeof(exbuf), e);
4258d0cef73dSGregory Neil Shapiro if (lbp != lbuf)
4259d0cef73dSGregory Neil Shapiro SM_FREE(lbp);
4260c2aa98e2SPeter Wemm p = exbuf;
4261c2aa98e2SPeter Wemm while (*p != '\0')
4262c2aa98e2SPeter Wemm {
4263c2aa98e2SPeter Wemm register char *wd;
4264c2aa98e2SPeter Wemm char delim;
4265c2aa98e2SPeter Wemm
42665b0945b5SGregory Neil Shapiro while (*p != '\0' && SM_ISSPACE(*p))
4267c2aa98e2SPeter Wemm p++;
4268c2aa98e2SPeter Wemm wd = p;
42695b0945b5SGregory Neil Shapiro while (*p != '\0' && !(SM_ISSPACE(*p)))
4270c2aa98e2SPeter Wemm p++;
4271c2aa98e2SPeter Wemm delim = *p;
4272c2aa98e2SPeter Wemm *p = '\0';
4273c2aa98e2SPeter Wemm if (wd[0] != '\0')
4274c2aa98e2SPeter Wemm setclass(mid, wd);
4275c2aa98e2SPeter Wemm *p = delim;
4276c2aa98e2SPeter Wemm }
4277c2aa98e2SPeter Wemm break;
4278c2aa98e2SPeter Wemm
4279c2aa98e2SPeter Wemm case '\0':
428040266059SGregory Neil Shapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
428140266059SGregory Neil Shapiro "Usage: .[DC]macro value(s)\n");
4282c2aa98e2SPeter Wemm break;
4283c2aa98e2SPeter Wemm
4284c2aa98e2SPeter Wemm default:
428540266059SGregory Neil Shapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
428640266059SGregory Neil Shapiro "Unknown \".\" command %s\n", line);
4287c2aa98e2SPeter Wemm break;
4288c2aa98e2SPeter Wemm }
4289c2aa98e2SPeter Wemm return;
4290c2aa98e2SPeter Wemm
4291c2aa98e2SPeter Wemm case '=': /* config-style settings */
4292c2aa98e2SPeter Wemm switch (line[1])
4293c2aa98e2SPeter Wemm {
4294c2aa98e2SPeter Wemm case 'S': /* dump rule set */
4295c2aa98e2SPeter Wemm rs = strtorwset(&line[2], NULL, ST_FIND);
4296c2aa98e2SPeter Wemm if (rs < 0)
4297c2aa98e2SPeter Wemm {
429840266059SGregory Neil Shapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
429940266059SGregory Neil Shapiro "Undefined ruleset %s\n", &line[2]);
4300c2aa98e2SPeter Wemm return;
4301c2aa98e2SPeter Wemm }
4302c2aa98e2SPeter Wemm rw = RewriteRules[rs];
4303c2aa98e2SPeter Wemm if (rw == NULL)
4304c2aa98e2SPeter Wemm return;
4305c2aa98e2SPeter Wemm do
4306c2aa98e2SPeter Wemm {
430740266059SGregory Neil Shapiro (void) sm_io_putc(smioout, SM_TIME_DEFAULT,
430840266059SGregory Neil Shapiro 'R');
4309c2aa98e2SPeter Wemm s = rw->r_lhs;
4310c2aa98e2SPeter Wemm while (*s != NULL)
4311c2aa98e2SPeter Wemm {
4312e92d3f3fSGregory Neil Shapiro xputs(smioout, *s++);
431340266059SGregory Neil Shapiro (void) sm_io_putc(smioout,
431440266059SGregory Neil Shapiro SM_TIME_DEFAULT, ' ');
4315c2aa98e2SPeter Wemm }
431640266059SGregory Neil Shapiro (void) sm_io_putc(smioout, SM_TIME_DEFAULT,
431740266059SGregory Neil Shapiro '\t');
431840266059SGregory Neil Shapiro (void) sm_io_putc(smioout, SM_TIME_DEFAULT,
431940266059SGregory Neil Shapiro '\t');
4320c2aa98e2SPeter Wemm s = rw->r_rhs;
4321c2aa98e2SPeter Wemm while (*s != NULL)
4322c2aa98e2SPeter Wemm {
4323e92d3f3fSGregory Neil Shapiro xputs(smioout, *s++);
432440266059SGregory Neil Shapiro (void) sm_io_putc(smioout,
432540266059SGregory Neil Shapiro SM_TIME_DEFAULT, ' ');
4326c2aa98e2SPeter Wemm }
432740266059SGregory Neil Shapiro (void) sm_io_putc(smioout, SM_TIME_DEFAULT,
432840266059SGregory Neil Shapiro '\n');
4329c2aa98e2SPeter Wemm } while ((rw = rw->r_next) != NULL);
4330c2aa98e2SPeter Wemm break;
4331c2aa98e2SPeter Wemm
4332c2aa98e2SPeter Wemm case 'M':
4333c2aa98e2SPeter Wemm for (i = 0; i < MAXMAILERS; i++)
4334c2aa98e2SPeter Wemm {
4335c2aa98e2SPeter Wemm if (Mailer[i] != NULL)
4336e92d3f3fSGregory Neil Shapiro printmailer(smioout, Mailer[i]);
4337c2aa98e2SPeter Wemm }
4338c2aa98e2SPeter Wemm break;
4339c2aa98e2SPeter Wemm
4340c2aa98e2SPeter Wemm case '\0':
434140266059SGregory Neil Shapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
434240266059SGregory Neil Shapiro "Usage: =Sruleset or =M\n");
4343c2aa98e2SPeter Wemm break;
4344c2aa98e2SPeter Wemm
4345c2aa98e2SPeter Wemm default:
434640266059SGregory Neil Shapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
434740266059SGregory Neil Shapiro "Unknown \"=\" command %s\n", line);
4348c2aa98e2SPeter Wemm break;
4349c2aa98e2SPeter Wemm }
4350c2aa98e2SPeter Wemm return;
4351c2aa98e2SPeter Wemm
4352c2aa98e2SPeter Wemm case '-': /* set command-line-like opts */
4353c2aa98e2SPeter Wemm switch (line[1])
4354c2aa98e2SPeter Wemm {
4355c2aa98e2SPeter Wemm case 'd':
4356c2aa98e2SPeter Wemm tTflag(&line[2]);
4357c2aa98e2SPeter Wemm break;
4358c2aa98e2SPeter Wemm
4359c2aa98e2SPeter Wemm case '\0':
436040266059SGregory Neil Shapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
436140266059SGregory Neil Shapiro "Usage: -d{debug arguments}\n");
4362c2aa98e2SPeter Wemm break;
4363c2aa98e2SPeter Wemm
4364c2aa98e2SPeter Wemm default:
436540266059SGregory Neil Shapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
436640266059SGregory Neil Shapiro "Unknown \"-\" command %s\n", line);
4367c2aa98e2SPeter Wemm break;
4368c2aa98e2SPeter Wemm }
4369c2aa98e2SPeter Wemm return;
4370c2aa98e2SPeter Wemm
4371c2aa98e2SPeter Wemm case '$':
4372c2aa98e2SPeter Wemm if (line[1] == '=')
4373c2aa98e2SPeter Wemm {
4374d39bd2c1SGregory Neil Shapiro #if _FFR_DYN_CLASS
4375d39bd2c1SGregory Neil Shapiro MAP *dynmap;
4376d39bd2c1SGregory Neil Shapiro STAB *st;
4377d39bd2c1SGregory Neil Shapiro #endif
4378d39bd2c1SGregory Neil Shapiro
437940266059SGregory Neil Shapiro mid = macid(&line[2]);
4380d39bd2c1SGregory Neil Shapiro #if _FFR_DYN_CLASS
4381d39bd2c1SGregory Neil Shapiro if (mid != 0 &&
4382d39bd2c1SGregory Neil Shapiro (st = stab(macname(mid), ST_DYNMAP, ST_FIND)) != NULL)
4383d39bd2c1SGregory Neil Shapiro {
4384d39bd2c1SGregory Neil Shapiro dynmap = &st->s_dynclass;
4385d39bd2c1SGregory Neil Shapiro q = dynmap->map_class->map_cname;
4386d39bd2c1SGregory Neil Shapiro if (SM_IS_EMPTY(q))
4387d39bd2c1SGregory Neil Shapiro q = "implicit";
4388d39bd2c1SGregory Neil Shapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
4389d39bd2c1SGregory Neil Shapiro "$=%s not possible for a dynamic class, use\n",
4390d39bd2c1SGregory Neil Shapiro line + 2);
4391d39bd2c1SGregory Neil Shapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
4392d39bd2c1SGregory Neil Shapiro "makemap -u %s %s",
4393d39bd2c1SGregory Neil Shapiro q, dynmap->map_file);
4394d39bd2c1SGregory Neil Shapiro if (!SM_IS_EMPTY(dynmap->map_tag))
4395d39bd2c1SGregory Neil Shapiro {
4396d39bd2c1SGregory Neil Shapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
4397d39bd2c1SGregory Neil Shapiro " | grep -i '^%s:'",
4398d39bd2c1SGregory Neil Shapiro dynmap->map_tag);
4399d39bd2c1SGregory Neil Shapiro }
4400d39bd2c1SGregory Neil Shapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, "\n");
4401d39bd2c1SGregory Neil Shapiro return;
4402d39bd2c1SGregory Neil Shapiro }
4403d39bd2c1SGregory Neil Shapiro #endif
4404193538b7SGregory Neil Shapiro if (mid != 0)
4405c2aa98e2SPeter Wemm stabapply(dump_class, mid);
4406c2aa98e2SPeter Wemm return;
4407c2aa98e2SPeter Wemm }
440840266059SGregory Neil Shapiro mid = macid(&line[1]);
4409193538b7SGregory Neil Shapiro if (mid == 0)
4410c2aa98e2SPeter Wemm return;
4411c2aa98e2SPeter Wemm p = macvalue(mid, e);
4412c2aa98e2SPeter Wemm if (p == NULL)
441340266059SGregory Neil Shapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
441440266059SGregory Neil Shapiro "Undefined\n");
4415c2aa98e2SPeter Wemm else
4416c2aa98e2SPeter Wemm {
4417e92d3f3fSGregory Neil Shapiro xputs(smioout, p);
441840266059SGregory Neil Shapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
441940266059SGregory Neil Shapiro "\n");
4420c2aa98e2SPeter Wemm }
4421c2aa98e2SPeter Wemm return;
4422c2aa98e2SPeter Wemm
4423c2aa98e2SPeter Wemm case '/': /* miscellaneous commands */
4424c2aa98e2SPeter Wemm p = &line[strlen(line)];
44255b0945b5SGregory Neil Shapiro while (--p >= line && SM_ISSPACE(*p))
4426c2aa98e2SPeter Wemm *p = '\0';
4427c2aa98e2SPeter Wemm p = strpbrk(line, " \t");
4428c2aa98e2SPeter Wemm if (p != NULL)
4429c2aa98e2SPeter Wemm {
44305b0945b5SGregory Neil Shapiro while (SM_ISSPACE(*p))
4431c2aa98e2SPeter Wemm *p++ = '\0';
4432c2aa98e2SPeter Wemm }
4433c2aa98e2SPeter Wemm else
4434c2aa98e2SPeter Wemm p = "";
4435c2aa98e2SPeter Wemm if (line[1] == '\0')
4436c2aa98e2SPeter Wemm {
443740266059SGregory Neil Shapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
443840266059SGregory Neil Shapiro "Usage: /[canon|map|mx|parse|try|tryflags]\n");
4439c2aa98e2SPeter Wemm return;
4440c2aa98e2SPeter Wemm }
44412fb4f839SGregory Neil Shapiro if (SM_STRCASEEQ(&line[1], "quit"))
444206f25ae9SGregory Neil Shapiro {
444306f25ae9SGregory Neil Shapiro CurEnv->e_id = NULL;
444440266059SGregory Neil Shapiro finis(true, true, ExitStat);
444540266059SGregory Neil Shapiro /* NOTREACHED */
444606f25ae9SGregory Neil Shapiro }
44472fb4f839SGregory Neil Shapiro if (SM_STRCASEEQ(&line[1], "mx"))
4448c2aa98e2SPeter Wemm {
4449c2aa98e2SPeter Wemm #if NAMED_BIND
4450c2aa98e2SPeter Wemm /* look up MX records */
4451c2aa98e2SPeter Wemm int nmx;
4452c2aa98e2SPeter Wemm auto int rcode;
4453c2aa98e2SPeter Wemm char *mxhosts[MAXMXHOSTS + 1];
4454c2aa98e2SPeter Wemm
4455c2aa98e2SPeter Wemm if (*p == '\0')
4456c2aa98e2SPeter Wemm {
445740266059SGregory Neil Shapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
445840266059SGregory Neil Shapiro "Usage: /mx address\n");
4459c2aa98e2SPeter Wemm return;
4460c2aa98e2SPeter Wemm }
44615b0945b5SGregory Neil Shapiro nmx = getmxrr(p, mxhosts, NULL, TRYFALLBACK, &rcode,
4462d39bd2c1SGregory Neil Shapiro NULL, -1, NULL);
44635b0945b5SGregory Neil Shapiro if (nmx == NULLMX)
44645b0945b5SGregory Neil Shapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
44655b0945b5SGregory Neil Shapiro "getmxrr(%s) returns null MX (See RFC7505)\n",
44665b0945b5SGregory Neil Shapiro p);
44675b0945b5SGregory Neil Shapiro else
446840266059SGregory Neil Shapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
446940266059SGregory Neil Shapiro "getmxrr(%s) returns %d value(s):\n",
447040266059SGregory Neil Shapiro p, nmx);
4471c2aa98e2SPeter Wemm for (i = 0; i < nmx; i++)
447240266059SGregory Neil Shapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
447340266059SGregory Neil Shapiro "\t%s\n", mxhosts[i]);
447406f25ae9SGregory Neil Shapiro #else /* NAMED_BIND */
447540266059SGregory Neil Shapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
447640266059SGregory Neil Shapiro "No MX code compiled in\n");
447706f25ae9SGregory Neil Shapiro #endif /* NAMED_BIND */
4478c2aa98e2SPeter Wemm }
44792fb4f839SGregory Neil Shapiro else if (SM_STRCASEEQ(&line[1], "canon"))
4480c2aa98e2SPeter Wemm {
4481c2aa98e2SPeter Wemm char host[MAXHOSTNAMELEN];
4482c2aa98e2SPeter Wemm
4483c2aa98e2SPeter Wemm if (*p == '\0')
4484c2aa98e2SPeter Wemm {
448540266059SGregory Neil Shapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
448640266059SGregory Neil Shapiro "Usage: /canon address\n");
4487c2aa98e2SPeter Wemm return;
4488c2aa98e2SPeter Wemm }
4489d0cef73dSGregory Neil Shapiro else if (sm_strlcpy(host, p, sizeof(host)) >= sizeof(host))
4490c2aa98e2SPeter Wemm {
449140266059SGregory Neil Shapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
449240266059SGregory Neil Shapiro "Name too long\n");
4493c2aa98e2SPeter Wemm return;
4494c2aa98e2SPeter Wemm }
4495d0cef73dSGregory Neil Shapiro (void) getcanonname(host, sizeof(host), !HasWildcardMX,
449640266059SGregory Neil Shapiro NULL);
449740266059SGregory Neil Shapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
449840266059SGregory Neil Shapiro "getcanonname(%s) returns %s\n",
449940266059SGregory Neil Shapiro p, host);
4500c2aa98e2SPeter Wemm }
45012fb4f839SGregory Neil Shapiro else if (SM_STRCASEEQ(&line[1], "map"))
4502c2aa98e2SPeter Wemm {
4503c2aa98e2SPeter Wemm auto int rcode = EX_OK;
4504c2aa98e2SPeter Wemm char *av[2];
4505c2aa98e2SPeter Wemm
4506c2aa98e2SPeter Wemm if (*p == '\0')
4507c2aa98e2SPeter Wemm {
450840266059SGregory Neil Shapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
450940266059SGregory Neil Shapiro "Usage: /map mapname key\n");
4510c2aa98e2SPeter Wemm return;
4511c2aa98e2SPeter Wemm }
45125b0945b5SGregory Neil Shapiro for (q = p; *q != '\0' && !(SM_ISSPACE(*q)); q++)
4513c2aa98e2SPeter Wemm continue;
4514c2aa98e2SPeter Wemm if (*q == '\0')
4515c2aa98e2SPeter Wemm {
451640266059SGregory Neil Shapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
451740266059SGregory Neil Shapiro "No key specified\n");
4518c2aa98e2SPeter Wemm return;
4519c2aa98e2SPeter Wemm }
4520c2aa98e2SPeter Wemm *q++ = '\0';
4521c2aa98e2SPeter Wemm map = stab(p, ST_MAP, ST_FIND);
4522c2aa98e2SPeter Wemm if (map == NULL)
4523c2aa98e2SPeter Wemm {
452440266059SGregory Neil Shapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
452540266059SGregory Neil Shapiro "Map named \"%s\" not found\n", p);
4526c2aa98e2SPeter Wemm return;
4527c2aa98e2SPeter Wemm }
452806f25ae9SGregory Neil Shapiro if (!bitset(MF_OPEN, map->s_map.map_mflags) &&
452906f25ae9SGregory Neil Shapiro !openmap(&(map->s_map)))
4530c2aa98e2SPeter Wemm {
453140266059SGregory Neil Shapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
453240266059SGregory Neil Shapiro "Map named \"%s\" not open\n", p);
4533c2aa98e2SPeter Wemm return;
4534c2aa98e2SPeter Wemm }
453540266059SGregory Neil Shapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
453640266059SGregory Neil Shapiro "map_lookup: %s (%s) ", p, q);
4537c2aa98e2SPeter Wemm av[0] = q;
4538c2aa98e2SPeter Wemm av[1] = NULL;
4539c2aa98e2SPeter Wemm p = (*map->s_map.map_class->map_lookup)
4540c2aa98e2SPeter Wemm (&map->s_map, q, av, &rcode);
4541c2aa98e2SPeter Wemm if (p == NULL)
454240266059SGregory Neil Shapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
454340266059SGregory Neil Shapiro "no match (%d)\n",
454440266059SGregory Neil Shapiro rcode);
4545c2aa98e2SPeter Wemm else
454640266059SGregory Neil Shapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
454740266059SGregory Neil Shapiro "returns %s (%d)\n", p,
454840266059SGregory Neil Shapiro rcode);
4549c2aa98e2SPeter Wemm }
45502fb4f839SGregory Neil Shapiro else if (SM_STRCASEEQ(&line[1], "sender"))
45512fb4f839SGregory Neil Shapiro {
45522fb4f839SGregory Neil Shapiro setsender(p, CurEnv, NULL, '\0', false);
45532fb4f839SGregory Neil Shapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
45542fb4f839SGregory Neil Shapiro "addr=%s\n",
45552fb4f839SGregory Neil Shapiro e->e_from.q_user);
45562fb4f839SGregory Neil Shapiro }
45572fb4f839SGregory Neil Shapiro else if (SM_STRCASEEQ(&line[1], "expand"))
45582fb4f839SGregory Neil Shapiro {
45592fb4f839SGregory Neil Shapiro if (*p == '\0')
45602fb4f839SGregory Neil Shapiro {
45612fb4f839SGregory Neil Shapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
45622fb4f839SGregory Neil Shapiro "Usage: /expand string\n");
45632fb4f839SGregory Neil Shapiro return;
45642fb4f839SGregory Neil Shapiro }
45652fb4f839SGregory Neil Shapiro expand(p, exbuf, sizeof(exbuf), CurEnv);
45662fb4f839SGregory Neil Shapiro xputs(smioout, exbuf);
45672fb4f839SGregory Neil Shapiro }
45682fb4f839SGregory Neil Shapiro else if (SM_STRCASEEQ(&line[1], "try"))
4569c2aa98e2SPeter Wemm {
4570c2aa98e2SPeter Wemm MAILER *m;
457106f25ae9SGregory Neil Shapiro STAB *st;
4572c2aa98e2SPeter Wemm auto int rcode = EX_OK;
4573c2aa98e2SPeter Wemm
4574c2aa98e2SPeter Wemm q = strpbrk(p, " \t");
4575c2aa98e2SPeter Wemm if (q != NULL)
4576c2aa98e2SPeter Wemm {
45775b0945b5SGregory Neil Shapiro while (SM_ISSPACE(*q))
4578c2aa98e2SPeter Wemm *q++ = '\0';
4579c2aa98e2SPeter Wemm }
4580c2aa98e2SPeter Wemm if (q == NULL || *q == '\0')
4581c2aa98e2SPeter Wemm {
458240266059SGregory Neil Shapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
458340266059SGregory Neil Shapiro "Usage: /try mailer address\n");
4584c2aa98e2SPeter Wemm return;
4585c2aa98e2SPeter Wemm }
458606f25ae9SGregory Neil Shapiro st = stab(p, ST_MAILER, ST_FIND);
458706f25ae9SGregory Neil Shapiro if (st == NULL)
4588c2aa98e2SPeter Wemm {
458940266059SGregory Neil Shapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
459040266059SGregory Neil Shapiro "Unknown mailer %s\n", p);
4591c2aa98e2SPeter Wemm return;
4592c2aa98e2SPeter Wemm }
459306f25ae9SGregory Neil Shapiro m = st->s_mailer;
459440266059SGregory Neil Shapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
459540266059SGregory Neil Shapiro "Trying %s %s address %s for mailer %s\n",
459640266059SGregory Neil Shapiro bitset(RF_HEADERADDR, tryflags) ? "header"
459740266059SGregory Neil Shapiro : "envelope",
459840266059SGregory Neil Shapiro bitset(RF_SENDERADDR, tryflags) ? "sender"
459940266059SGregory Neil Shapiro : "recipient", q, p);
46002fb4f839SGregory Neil Shapiro #if _FFR_8BITENVADDR
46012fb4f839SGregory Neil Shapiro q = quote_internal_chars(q, exbuf, &len, NULL);
46022fb4f839SGregory Neil Shapiro #endif
4603c2aa98e2SPeter Wemm p = remotename(q, m, tryflags, &rcode, CurEnv);
46042fb4f839SGregory Neil Shapiro #if _FFR_8BITENVADDR
46052fb4f839SGregory Neil Shapiro dequote_internal_chars(p, exbuf, sizeof(exbuf));
46062fb4f839SGregory Neil Shapiro p = exbuf;
46072fb4f839SGregory Neil Shapiro #endif
460840266059SGregory Neil Shapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
460940266059SGregory Neil Shapiro "Rcode = %d, addr = %s\n",
4610c2aa98e2SPeter Wemm rcode, p == NULL ? "<NULL>" : p);
4611c2aa98e2SPeter Wemm e->e_to = NULL;
4612c2aa98e2SPeter Wemm }
46132fb4f839SGregory Neil Shapiro else if (SM_STRCASEEQ(&line[1], "tryflags"))
4614c2aa98e2SPeter Wemm {
4615c2aa98e2SPeter Wemm if (*p == '\0')
4616c2aa98e2SPeter Wemm {
461740266059SGregory Neil Shapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
461840266059SGregory Neil Shapiro "Usage: /tryflags [Hh|Ee][Ss|Rr]\n");
4619c2aa98e2SPeter Wemm return;
4620c2aa98e2SPeter Wemm }
4621c2aa98e2SPeter Wemm for (; *p != '\0'; p++)
4622c2aa98e2SPeter Wemm {
4623c2aa98e2SPeter Wemm switch (*p)
4624c2aa98e2SPeter Wemm {
4625c2aa98e2SPeter Wemm case 'H':
4626c2aa98e2SPeter Wemm case 'h':
4627c2aa98e2SPeter Wemm tryflags |= RF_HEADERADDR;
4628c2aa98e2SPeter Wemm break;
4629c2aa98e2SPeter Wemm
4630c2aa98e2SPeter Wemm case 'E':
4631c2aa98e2SPeter Wemm case 'e':
4632c2aa98e2SPeter Wemm tryflags &= ~RF_HEADERADDR;
4633c2aa98e2SPeter Wemm break;
4634c2aa98e2SPeter Wemm
4635c2aa98e2SPeter Wemm case 'S':
4636c2aa98e2SPeter Wemm case 's':
4637c2aa98e2SPeter Wemm tryflags |= RF_SENDERADDR;
4638c2aa98e2SPeter Wemm break;
4639c2aa98e2SPeter Wemm
4640c2aa98e2SPeter Wemm case 'R':
4641c2aa98e2SPeter Wemm case 'r':
4642c2aa98e2SPeter Wemm tryflags &= ~RF_SENDERADDR;
4643c2aa98e2SPeter Wemm break;
4644c2aa98e2SPeter Wemm }
4645c2aa98e2SPeter Wemm }
464606f25ae9SGregory Neil Shapiro exbuf[0] = bitset(RF_HEADERADDR, tryflags) ? 'h' : 'e';
464706f25ae9SGregory Neil Shapiro exbuf[1] = ' ';
464806f25ae9SGregory Neil Shapiro exbuf[2] = bitset(RF_SENDERADDR, tryflags) ? 's' : 'r';
464906f25ae9SGregory Neil Shapiro exbuf[3] = '\0';
465040266059SGregory Neil Shapiro macdefine(&e->e_macro, A_TEMP,
465140266059SGregory Neil Shapiro macid("{addr_type}"), exbuf);
4652c2aa98e2SPeter Wemm }
4653d39bd2c1SGregory Neil Shapiro else if (SM_STRCASEEQ(&line[1], "parse")
4654d39bd2c1SGregory Neil Shapiro #if _FFR_TESTS
4655d39bd2c1SGregory Neil Shapiro || SM_STRCASEEQ(&line[1], "hostsig")
4656d39bd2c1SGregory Neil Shapiro #endif
4657d39bd2c1SGregory Neil Shapiro )
4658c2aa98e2SPeter Wemm {
4659c2aa98e2SPeter Wemm if (*p == '\0')
4660c2aa98e2SPeter Wemm {
466140266059SGregory Neil Shapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
466240266059SGregory Neil Shapiro "Usage: /parse address\n");
4663c2aa98e2SPeter Wemm return;
4664c2aa98e2SPeter Wemm }
46652fb4f839SGregory Neil Shapiro #if _FFR_8BITENVADDR
46662fb4f839SGregory Neil Shapiro p = quote_internal_chars(p, exbuf, &len, NULL);
46672fb4f839SGregory Neil Shapiro #endif
4668d9986b26SGregory Neil Shapiro q = crackaddr(p, e);
466940266059SGregory Neil Shapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
467040266059SGregory Neil Shapiro "Cracked address = ");
4671e92d3f3fSGregory Neil Shapiro xputs(smioout, q);
467240266059SGregory Neil Shapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
467340266059SGregory Neil Shapiro "\nParsing %s %s address\n",
467440266059SGregory Neil Shapiro bitset(RF_HEADERADDR, tryflags) ?
467540266059SGregory Neil Shapiro "header" : "envelope",
467640266059SGregory Neil Shapiro bitset(RF_SENDERADDR, tryflags) ?
467740266059SGregory Neil Shapiro "sender" : "recipient");
46782fb4f839SGregory Neil Shapiro /* XXX p must be [i] */
467940266059SGregory Neil Shapiro if (parseaddr(p, &a, tryflags, '\0', NULL, e, true)
468040266059SGregory Neil Shapiro == NULL)
468140266059SGregory Neil Shapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
468240266059SGregory Neil Shapiro "Cannot parse\n");
4683c2aa98e2SPeter Wemm else if (a.q_host != NULL && a.q_host[0] != '\0')
4684d39bd2c1SGregory Neil Shapiro {
4685d39bd2c1SGregory Neil Shapiro #if _FFR_TESTS
4686d39bd2c1SGregory Neil Shapiro if (SM_STRCASEEQ(&line[1], "hostsig"))
4687d39bd2c1SGregory Neil Shapiro t_hostsig(&a, NULL, NULL);
4688d39bd2c1SGregory Neil Shapiro else
4689d39bd2c1SGregory Neil Shapiro #endif /* _FFR_TESTS */
4690d39bd2c1SGregory Neil Shapiro {
469140266059SGregory Neil Shapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
469240266059SGregory Neil Shapiro "mailer %s, host %s, user %s\n",
469340266059SGregory Neil Shapiro a.q_mailer->m_name,
469440266059SGregory Neil Shapiro a.q_host,
469540266059SGregory Neil Shapiro a.q_user);
4696d39bd2c1SGregory Neil Shapiro }
4697d39bd2c1SGregory Neil Shapiro }
4698c2aa98e2SPeter Wemm else
469940266059SGregory Neil Shapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
470040266059SGregory Neil Shapiro "mailer %s, user %s\n",
470140266059SGregory Neil Shapiro a.q_mailer->m_name,
470240266059SGregory Neil Shapiro a.q_user);
4703c2aa98e2SPeter Wemm e->e_to = NULL;
4704c2aa98e2SPeter Wemm }
47052fb4f839SGregory Neil Shapiro else if (SM_STRCASEEQ(&line[1], "header"))
4706d0cef73dSGregory Neil Shapiro {
4707d0cef73dSGregory Neil Shapiro unsigned long ul;
4708d0cef73dSGregory Neil Shapiro
4709d0cef73dSGregory Neil Shapiro ul = chompheader(p, CHHDR_CHECK|CHHDR_USER, NULL, e);
4710d0cef73dSGregory Neil Shapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
47112fb4f839SGregory Neil Shapiro "ul = %#0.8lx\n", ul);
4712d0cef73dSGregory Neil Shapiro }
47135dd76dd0SGregory Neil Shapiro #if NETINET || NETINET6
47142fb4f839SGregory Neil Shapiro else if (SM_STRCASEEQ(&line[1], "gethostbyname"))
47155dd76dd0SGregory Neil Shapiro {
47165dd76dd0SGregory Neil Shapiro int family = AF_INET;
47175dd76dd0SGregory Neil Shapiro
47185dd76dd0SGregory Neil Shapiro q = strpbrk(p, " \t");
47195dd76dd0SGregory Neil Shapiro if (q != NULL)
47205dd76dd0SGregory Neil Shapiro {
47215b0945b5SGregory Neil Shapiro while (SM_ISSPACE(*q))
47225dd76dd0SGregory Neil Shapiro *q++ = '\0';
47235dd76dd0SGregory Neil Shapiro # if NETINET6
47245dd76dd0SGregory Neil Shapiro if (*q != '\0' && (strcmp(q, "inet6") == 0 ||
47255dd76dd0SGregory Neil Shapiro strcmp(q, "AAAA") == 0))
47265dd76dd0SGregory Neil Shapiro family = AF_INET6;
47275dd76dd0SGregory Neil Shapiro # endif /* NETINET6 */
47285dd76dd0SGregory Neil Shapiro }
47295dd76dd0SGregory Neil Shapiro (void) sm_gethostbyname(p, family);
47305dd76dd0SGregory Neil Shapiro }
47315dd76dd0SGregory Neil Shapiro #endif /* NETINET || NETINET6 */
47325b0945b5SGregory Neil Shapiro #if DANE
47332fb4f839SGregory Neil Shapiro else if (SM_STRCASEEQ(&line[1], "dnslookup"))
47345b0945b5SGregory Neil Shapiro {
47355b0945b5SGregory Neil Shapiro DNS_REPLY_T *r;
47365b0945b5SGregory Neil Shapiro int rr_type, family;
47375b0945b5SGregory Neil Shapiro unsigned int flags;
47385b0945b5SGregory Neil Shapiro
47395b0945b5SGregory Neil Shapiro rr_type = T_A;
47405b0945b5SGregory Neil Shapiro family = AF_INET;
47415b0945b5SGregory Neil Shapiro flags = RR_AS_TEXT;
47425b0945b5SGregory Neil Shapiro q = strpbrk(p, " \t");
47435b0945b5SGregory Neil Shapiro if (q != NULL)
47445b0945b5SGregory Neil Shapiro {
47455b0945b5SGregory Neil Shapiro char *pflags;
47465b0945b5SGregory Neil Shapiro
47475b0945b5SGregory Neil Shapiro while (SM_ISSPACE(*q))
47485b0945b5SGregory Neil Shapiro *q++ = '\0';
47495b0945b5SGregory Neil Shapiro pflags = strpbrk(q, " \t");
47505b0945b5SGregory Neil Shapiro if (pflags != NULL)
47515b0945b5SGregory Neil Shapiro {
47525b0945b5SGregory Neil Shapiro while (SM_ISSPACE(*pflags))
47535b0945b5SGregory Neil Shapiro *pflags++ = '\0';
47545b0945b5SGregory Neil Shapiro }
47555b0945b5SGregory Neil Shapiro rr_type = dns_string_to_type(q);
47565b0945b5SGregory Neil Shapiro if (rr_type == T_A)
47575b0945b5SGregory Neil Shapiro family = AF_INET;
47585b0945b5SGregory Neil Shapiro # if NETINET6
47595b0945b5SGregory Neil Shapiro if (rr_type == T_AAAA)
47605b0945b5SGregory Neil Shapiro family = AF_INET6;
47615b0945b5SGregory Neil Shapiro # endif
47625b0945b5SGregory Neil Shapiro while (pflags != NULL && *pflags != '\0' &&
47635b0945b5SGregory Neil Shapiro !SM_ISSPACE(*pflags))
47645b0945b5SGregory Neil Shapiro {
47655b0945b5SGregory Neil Shapiro if (*pflags == 'c')
47665b0945b5SGregory Neil Shapiro flags |= RR_NO_CNAME;
47675b0945b5SGregory Neil Shapiro else if (*pflags == 'o')
47685b0945b5SGregory Neil Shapiro flags |= RR_ONLY_CNAME;
47695b0945b5SGregory Neil Shapiro else if (*pflags == 'T')
47705b0945b5SGregory Neil Shapiro flags &= ~RR_AS_TEXT;
47715b0945b5SGregory Neil Shapiro ++pflags;
47725b0945b5SGregory Neil Shapiro }
47735b0945b5SGregory Neil Shapiro }
47745b0945b5SGregory Neil Shapiro r = dns_lookup_int(p, C_IN, rr_type,
47755b0945b5SGregory Neil Shapiro 0, 0, 0, flags, NULL, NULL);
47765b0945b5SGregory Neil Shapiro if (r != NULL && family >= 0)
47775b0945b5SGregory Neil Shapiro {
47785b0945b5SGregory Neil Shapiro (void) dns2he(r, family);
47795b0945b5SGregory Neil Shapiro dns_free_data(r);
47805b0945b5SGregory Neil Shapiro r = NULL;
47815b0945b5SGregory Neil Shapiro }
47825b0945b5SGregory Neil Shapiro }
4783d39bd2c1SGregory Neil Shapiro # if _FFR_TESTS
4784d39bd2c1SGregory Neil Shapiro else if (SM_STRCASEEQ(&line[1], "hostsignature"))
4785d39bd2c1SGregory Neil Shapiro {
4786d39bd2c1SGregory Neil Shapiro STAB *st;
4787d39bd2c1SGregory Neil Shapiro MAILER *m;
4788d39bd2c1SGregory Neil Shapiro
4789d39bd2c1SGregory Neil Shapiro st = stab("esmtp", ST_MAILER, ST_FIND);
4790d39bd2c1SGregory Neil Shapiro if (NULL == st)
4791d39bd2c1SGregory Neil Shapiro {
4792d39bd2c1SGregory Neil Shapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
4793d39bd2c1SGregory Neil Shapiro "Unknown mailer esmtp\n");
4794d39bd2c1SGregory Neil Shapiro return;
4795d39bd2c1SGregory Neil Shapiro }
4796d39bd2c1SGregory Neil Shapiro m = st->s_mailer;
4797d39bd2c1SGregory Neil Shapiro if (NULL == m)
4798d39bd2c1SGregory Neil Shapiro {
4799d39bd2c1SGregory Neil Shapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
4800d39bd2c1SGregory Neil Shapiro "Unknown mailer esmtp\n");
4801d39bd2c1SGregory Neil Shapiro return;
4802d39bd2c1SGregory Neil Shapiro }
4803d39bd2c1SGregory Neil Shapiro t_hostsig(NULL, p, m);
4804d39bd2c1SGregory Neil Shapiro }
4805d39bd2c1SGregory Neil Shapiro else if (SM_STRCASEEQ(&line[1], "parsesig"))
4806d39bd2c1SGregory Neil Shapiro t_parsehostsig(p, NULL);
4807d39bd2c1SGregory Neil Shapiro # endif /* _FFR_TESTS */
48085b0945b5SGregory Neil Shapiro #endif /* DANE */
4809c2aa98e2SPeter Wemm else
4810c2aa98e2SPeter Wemm {
481140266059SGregory Neil Shapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
481240266059SGregory Neil Shapiro "Unknown \"/\" command %s\n",
481340266059SGregory Neil Shapiro line);
4814c2aa98e2SPeter Wemm }
4815d0cef73dSGregory Neil Shapiro (void) sm_io_flush(smioout, SM_TIME_DEFAULT);
4816c2aa98e2SPeter Wemm return;
4817c2aa98e2SPeter Wemm }
48185b0945b5SGregory Neil Shapiro for (p = line; SM_ISSPACE(*p); p++)
4819c2aa98e2SPeter Wemm continue;
4820c2aa98e2SPeter Wemm q = p;
48215b0945b5SGregory Neil Shapiro while (*p != '\0' && !(SM_ISSPACE(*p)))
4822c2aa98e2SPeter Wemm p++;
4823c2aa98e2SPeter Wemm if (*p == '\0')
4824c2aa98e2SPeter Wemm {
482540266059SGregory Neil Shapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
482640266059SGregory Neil Shapiro "No address!\n");
4827c2aa98e2SPeter Wemm return;
4828c2aa98e2SPeter Wemm }
4829c2aa98e2SPeter Wemm *p = '\0';
4830d0cef73dSGregory Neil Shapiro if (tTd(23, 101))
48312fb4f839SGregory Neil Shapiro eightbit = to8bit(p + 1, tTd(23, 102));
483240266059SGregory Neil Shapiro if (invalidaddr(p + 1, NULL, true))
4833c2aa98e2SPeter Wemm return;
4834c2aa98e2SPeter Wemm do
4835c2aa98e2SPeter Wemm {
4836c2aa98e2SPeter Wemm register char **pvp;
4837c2aa98e2SPeter Wemm char pvpbuf[PSBUFSIZE];
4838c2aa98e2SPeter Wemm
4839d0cef73dSGregory Neil Shapiro pvp = prescan(++p, ',', pvpbuf, sizeof(pvpbuf), &delimptr,
48402fb4f839SGregory Neil Shapiro tTd(23, 103) ? ExtTokenTab :
4841d0cef73dSGregory Neil Shapiro ConfigLevel >= 9 ? TokTypeNoC : ExtTokenTab, false);
4842c2aa98e2SPeter Wemm if (pvp == NULL)
4843c2aa98e2SPeter Wemm continue;
4844c2aa98e2SPeter Wemm p = q;
4845c2aa98e2SPeter Wemm while (*p != '\0')
4846c2aa98e2SPeter Wemm {
484706f25ae9SGregory Neil Shapiro int status;
4848c2aa98e2SPeter Wemm
4849c2aa98e2SPeter Wemm rs = strtorwset(p, NULL, ST_FIND);
4850c2aa98e2SPeter Wemm if (rs < 0)
4851c2aa98e2SPeter Wemm {
485240266059SGregory Neil Shapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
485340266059SGregory Neil Shapiro "Undefined ruleset %s\n",
485440266059SGregory Neil Shapiro p);
4855c2aa98e2SPeter Wemm break;
4856c2aa98e2SPeter Wemm }
485740266059SGregory Neil Shapiro status = REWRITE(pvp, rs, e);
485806f25ae9SGregory Neil Shapiro if (status != EX_OK)
485940266059SGregory Neil Shapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
486040266059SGregory Neil Shapiro "== Ruleset %s (%d) status %d\n",
486106f25ae9SGregory Neil Shapiro p, rs, status);
4862d0cef73dSGregory Neil Shapiro else if (eightbit)
4863d0cef73dSGregory Neil Shapiro {
4864d0cef73dSGregory Neil Shapiro cataddr(pvp, NULL, exbuf, sizeof(exbuf), '\0',
4865d0cef73dSGregory Neil Shapiro true);
4866d0cef73dSGregory Neil Shapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
4867d0cef73dSGregory Neil Shapiro "cataddr: %s\n",
4868d0cef73dSGregory Neil Shapiro str2prt(exbuf));
4869d0cef73dSGregory Neil Shapiro }
4870c2aa98e2SPeter Wemm while (*p != '\0' && *p++ != ',')
4871c2aa98e2SPeter Wemm continue;
4872c2aa98e2SPeter Wemm }
4873c2aa98e2SPeter Wemm } while (*(p = delimptr) != '\0');
4874d0cef73dSGregory Neil Shapiro (void) sm_io_flush(smioout, SM_TIME_DEFAULT);
4875c2aa98e2SPeter Wemm }
4876c2aa98e2SPeter Wemm
487706f25ae9SGregory Neil Shapiro static void
dump_class(s,id)4878c2aa98e2SPeter Wemm dump_class(s, id)
4879c2aa98e2SPeter Wemm register STAB *s;
4880c2aa98e2SPeter Wemm int id;
4881c2aa98e2SPeter Wemm {
488240266059SGregory Neil Shapiro if (s->s_symtype != ST_CLASS)
4883c2aa98e2SPeter Wemm return;
4884193538b7SGregory Neil Shapiro if (bitnset(bitidx(id), s->s_class))
488540266059SGregory Neil Shapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
488640266059SGregory Neil Shapiro "%s\n", s->s_name);
4887c2aa98e2SPeter Wemm }
488840266059SGregory Neil Shapiro
488940266059SGregory Neil Shapiro /*
489040266059SGregory Neil Shapiro ** An exception type used to create QuickAbort exceptions.
489140266059SGregory Neil Shapiro ** This is my first cut at converting QuickAbort from longjmp to exceptions.
489240266059SGregory Neil Shapiro ** These exceptions have a single integer argument, which is the argument
489340266059SGregory Neil Shapiro ** to longjmp in the original code (either 1 or 2). I don't know the
489440266059SGregory Neil Shapiro ** significance of 1 vs 2: the calls to setjmp don't care.
489540266059SGregory Neil Shapiro */
489640266059SGregory Neil Shapiro
489740266059SGregory Neil Shapiro const SM_EXC_TYPE_T EtypeQuickAbort =
489840266059SGregory Neil Shapiro {
489940266059SGregory Neil Shapiro SmExcTypeMagic,
490040266059SGregory Neil Shapiro "E:mta.quickabort",
490140266059SGregory Neil Shapiro "i",
490240266059SGregory Neil Shapiro sm_etype_printf,
490340266059SGregory Neil Shapiro "quick abort %0",
490440266059SGregory Neil Shapiro };
4905