1/*
2 * Copyright (c) 1998-2006, 2008, 2009, 2011 Proofpoint, Inc. and its suppliers.
3 *	All rights reserved.
4 * Copyright (c) 1983, 1995-1997 Eric P. Allman.  All rights reserved.
5 * Copyright (c) 1988, 1993
6 *	The Regents of the University of California.  All rights reserved.
7 *
8 * By using this file, you agree to the terms and conditions set
9 * forth in the LICENSE file which can be found at the top level of
10 * the sendmail distribution.
11 *
12 */
13
14#define _DEFINE
15#include <sendmail.h>
16#include <sm/sendmail.h>
17#include <sm/xtrap.h>
18#include <sm/signal.h>
19#include <tls.h>
20
21#ifndef lint
22SM_UNUSED(static char copyright[]) =
23"@(#) Copyright (c) 1998-2013 Proofpoint, Inc. and its suppliers.\n\
24	All rights reserved.\n\
25     Copyright (c) 1983, 1995-1997 Eric P. Allman.  All rights reserved.\n\
26     Copyright (c) 1988, 1993\n\
27	The Regents of the University of California.  All rights reserved.\n";
28#endif /* ! lint */
29
30SM_RCSID("@(#)$Id: main.c,v 8.988 2013-11-23 02:52:37 gshapiro Exp $")
31
32
33#if NETINET || NETINET6
34# include <arpa/inet.h>
35# if DANE
36#  include "sm_resolve.h"
37# endif
38#endif
39
40/* for getcfname() */
41#include <sendmail/pathnames.h>
42#include <ratectrl.h>
43
44static SM_DEBUG_T
45DebugNoPRestart = SM_DEBUG_INITIALIZER("no_persistent_restart",
46	"@(#)$Debug: no_persistent_restart - don't restart, log only $");
47
48static void	dump_class __P((STAB *, int));
49static void	obsolete __P((char **));
50static void	testmodeline __P((char *, ENVELOPE *));
51static char	*getextenv __P((const char *));
52static void	sm_printoptions __P((char **));
53static SIGFUNC_DECL	intindebug __P((int));
54static SIGFUNC_DECL	sighup __P((int));
55static SIGFUNC_DECL	sigpipe __P((int));
56static SIGFUNC_DECL	sigterm __P((int));
57#ifdef SIGUSR1
58static SIGFUNC_DECL	sigusr1 __P((int));
59#endif
60
61/*
62**  SENDMAIL -- Post mail to a set of destinations.
63**
64**	This is the basic mail router.  All user mail programs should
65**	call this routine to actually deliver mail.  Sendmail in
66**	turn calls a bunch of mail servers that do the real work of
67**	delivering the mail.
68**
69**	Sendmail is driven by settings read in from /etc/mail/sendmail.cf
70**	(read by readcf.c).
71**
72**	Usage:
73**		/usr/lib/sendmail [flags] addr ...
74**
75**		See the associated documentation for details.
76**
77**	Authors:
78**		Eric Allman, UCB/INGRES (until 10/81).
79**			     Britton-Lee, Inc., purveyors of fine
80**				database computers (11/81 - 10/88).
81**			     International Computer Science Institute
82**				(11/88 - 9/89).
83**			     UCB/Mammoth Project (10/89 - 7/95).
84**			     InReference, Inc. (8/95 - 1/97).
85**			     Sendmail, Inc. (1/98 - 9/13).
86**		The support of my employers is gratefully acknowledged.
87**			Few of them (Britton-Lee in particular) have had
88**			anything to gain from my involvement in this project.
89**
90**		Gregory Neil Shapiro,
91**			Worcester Polytechnic Institute	(until 3/98).
92**			Sendmail, Inc. (3/98 - 10/13).
93**			Proofpoint, Inc. (10/13 - present).
94**
95**		Claus Assmann,
96**			Sendmail, Inc. (12/98 - 10/13).
97**			Proofpoint, Inc. (10/13 - present).
98*/
99
100char		*FullName;	/* sender's full name */
101ENVELOPE	BlankEnvelope;	/* a "blank" envelope */
102static ENVELOPE	MainEnvelope;	/* the envelope around the basic letter */
103ADDRESS		NullAddress =	/* a null address */
104		{ "", "", NULL, "" };
105char		*CommandLineArgs;	/* command line args for pid file */
106bool		Warn_Q_option = false;	/* warn about Q option use */
107static int	MissingFds = 0;	/* bit map of fds missing on startup */
108char		*Mbdb = "pw";	/* mailbox database defaults to /etc/passwd */
109
110#ifdef NGROUPS_MAX
111GIDSET_T	InitialGidSet[NGROUPS_MAX];
112#endif
113
114#define MAXCONFIGLEVEL	10	/* highest config version level known */
115
116#if SASL
117static sasl_callback_t srvcallbacks[] =
118{
119	{	SASL_CB_VERIFYFILE,	(sasl_callback_ft)&safesaslfile,	NULL	},
120	{	SASL_CB_PROXY_POLICY,	(sasl_callback_ft)&proxy_policy,	NULL	},
121	{	SASL_CB_LIST_END,	NULL,		NULL	}
122};
123#endif /* SASL */
124
125unsigned int	SubmitMode;
126int		SyslogPrefixLen; /* estimated length of syslog prefix */
127#define PIDLEN		6	/* pid length for computing SyslogPrefixLen */
128#ifndef SL_FUDGE
129# define SL_FUDGE	10	/* fudge offset for SyslogPrefixLen */
130#endif
131#define SLDLL		8	/* est. length of default syslog label */
132
133
134/* Some options are dangerous to allow users to use in non-submit mode */
135#define CHECK_AGAINST_OPMODE(cmd)					\
136{									\
137	if (extraprivs &&						\
138	    OpMode != MD_DELIVER && OpMode != MD_SMTP &&		\
139	    OpMode != MD_ARPAFTP && OpMode != MD_CHECKCONFIG &&		\
140	    OpMode != MD_VERIFY && OpMode != MD_TEST)			\
141	{								\
142		(void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,		\
143				     "WARNING: Ignoring submission mode -%c option (not in submission mode)\n", \
144		       (cmd));						\
145		break;							\
146	}								\
147	if (extraprivs && queuerun)					\
148	{								\
149		(void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,		\
150				     "WARNING: Ignoring submission mode -%c option with -q\n", \
151		       (cmd));						\
152		break;							\
153	}								\
154}
155
156int
157main(argc, argv, envp)
158	int argc;
159	char **argv;
160	char **envp;
161{
162	register char *p;
163	char **av;
164	extern char Version[];
165	char *ep, *from;
166	STAB *st;
167	register int i;
168	int j;
169	int dp;
170	int fill_errno;
171	int qgrp = NOQGRP;		/* queue group to process */
172	bool safecf = true;
173	BITMAP256 *p_flags = NULL;	/* daemon flags */
174	bool warn_C_flag = false;
175	bool auth = true;		/* whether to set e_auth_param */
176	char warn_f_flag = '\0';
177	bool run_in_foreground = false;	/* -bD mode */
178	bool queuerun = false, debug = false;
179	struct passwd *pw;
180	struct hostent *hp;
181	char *nullserver = NULL;
182	char *authinfo = NULL;
183	char *sysloglabel = NULL;	/* label for syslog */
184	char *conffile = NULL;		/* name of .cf file */
185	char *queuegroup = NULL;	/* queue group to process */
186	char *quarantining = NULL;	/* quarantine queue items? */
187	bool extraprivs;
188	bool forged, negate;
189	bool queuepersistent = false;	/* queue runner process runs forever */
190	bool foregroundqueue = false;	/* queue run in foreground */
191	bool save_val;			/* to save some bool var. */
192	int cftype;			/* which cf file to use? */
193	SM_FILE_T *smdebug;
194	static time_t starttime = 0;	/* when was process started */
195	struct stat traf_st;		/* for TrafficLog FIFO check */
196	char buf[MAXLINE];
197	char jbuf[MAXHOSTNAMELEN];	/* holds MyHostName */
198	static char rnamebuf[MAXNAME];	/* holds RealUserName */
199	char *emptyenviron[1];
200#if STARTTLS
201	bool tls_ok;
202#endif
203	QUEUE_CHAR *new;
204	ENVELOPE *e;
205	extern int DtableSize;
206	extern int optind;
207	extern int opterr;
208	extern char *optarg;
209	extern char **environ;
210#if SASL
211	extern void sm_sasl_init __P((void));
212#endif
213
214#if USE_ENVIRON
215	envp = environ;
216#endif
217
218	/* turn off profiling */
219	SM_PROF(0);
220
221	/* install default exception handler */
222	sm_exc_newthread(fatal_error);
223
224	/* set the default in/out channel so errors reported to screen */
225	InChannel = smioin;
226	OutChannel = smioout;
227
228	/*
229	**  Check to see if we reentered.
230	**	This would normally happen if e_putheader or e_putbody
231	**	were NULL when invoked.
232	*/
233
234	if (starttime != 0)
235	{
236		syserr("main: reentered!");
237		abort();
238	}
239	starttime = curtime();
240
241	/* avoid null pointer dereferences */
242	TermEscape.te_rv_on = TermEscape.te_under_on = TermEscape.te_normal = "";
243
244	RealUid = getuid();
245	RealGid = getgid();
246
247	/* Check if sendmail is running with extra privs */
248	extraprivs = (RealUid != 0 &&
249		      (geteuid() != getuid() || getegid() != getgid()));
250
251	CurrentPid = getpid();
252
253	/* get whatever .cf file is right for the opmode */
254	cftype = SM_GET_RIGHT_CF;
255
256	/* in 4.4BSD, the table can be huge; impose a reasonable limit */
257	DtableSize = getdtsize();
258	if (DtableSize > 256)
259		DtableSize = 256;
260
261	/*
262	**  Be sure we have enough file descriptors.
263	**	But also be sure that 0, 1, & 2 are open.
264	*/
265
266	/* reset errno and fill_errno; the latter is used way down below */
267	errno = fill_errno = 0;
268	fill_fd(STDIN_FILENO, NULL);
269	if (errno != 0)
270		fill_errno = errno;
271	fill_fd(STDOUT_FILENO, NULL);
272	if (errno != 0)
273		fill_errno = errno;
274	fill_fd(STDERR_FILENO, NULL);
275	if (errno != 0)
276		fill_errno = errno;
277
278	sm_closefrom(STDERR_FILENO + 1, DtableSize);
279	errno = 0;
280	smdebug = NULL;
281
282#if LOG
283# ifndef SM_LOG_STR
284#  define SM_LOG_STR	"sendmail"
285# endif
286# ifdef LOG_MAIL
287	openlog(SM_LOG_STR, LOG_PID, LOG_MAIL);
288# else
289	openlog(SM_LOG_STR, LOG_PID);
290# endif
291#endif /* LOG */
292
293	/*
294	**  Seed the random number generator.
295	**  Used for queue file names, picking a queue directory, and
296	**  MX randomization.
297	*/
298
299	seed_random();
300
301	/* do machine-dependent initializations */
302	init_md(argc, argv);
303
304
305	SyslogPrefixLen = PIDLEN + (MAXQFNAME - 3) + SL_FUDGE + SLDLL;
306
307	/* reset status from syserr() calls for missing file descriptors */
308	Errors = 0;
309	ExitStat = EX_OK;
310
311	SubmitMode = SUBMIT_UNKNOWN;
312#if _FFR_LOCAL_DAEMON
313	LocalDaemon = false;
314# if NETINET6
315	V6LoopbackAddrFound = false;
316# endif
317#endif
318#if XDEBUG
319	checkfd012("after openlog");
320#endif
321
322	tTsetup(tTdvect, sizeof(tTdvect), "0-99.1,*_trace_*.1");
323
324#ifdef NGROUPS_MAX
325	/* save initial group set for future checks */
326	i = getgroups(NGROUPS_MAX, InitialGidSet);
327	if (i <= 0)
328	{
329		InitialGidSet[0] = (GID_T) -1;
330		i = 0;
331	}
332	while (i < NGROUPS_MAX)
333		InitialGidSet[i++] = InitialGidSet[0];
334#endif /* NGROUPS_MAX */
335
336	/* drop group id privileges (RunAsUser not yet set) */
337	dp = drop_privileges(false);
338	setstat(dp);
339
340#ifdef SIGUSR1
341	/* Only allow root (or non-set-*-ID binaries) to use SIGUSR1 */
342	if (!extraprivs)
343	{
344		/* arrange to dump state on user-1 signal */
345		(void) sm_signal(SIGUSR1, sigusr1);
346	}
347	else
348	{
349		/* ignore user-1 signal */
350		(void) sm_signal(SIGUSR1, SIG_IGN);
351	}
352#endif /* SIGUSR1 */
353
354	/* initialize for setproctitle */
355	initsetproctitle(argc, argv, envp);
356
357	/* Handle any non-getoptable constructions. */
358	obsolete(argv);
359
360	/*
361	**  Do a quick prescan of the argument list.
362	*/
363
364
365	/* find initial opMode */
366	OpMode = MD_DELIVER;
367	av = argv;
368	p = strrchr(*av, '/');
369	if (p++ == NULL)
370		p = *av;
371	if (strcmp(p, "newaliases") == 0)
372		OpMode = MD_INITALIAS;
373	else if (strcmp(p, "mailq") == 0)
374		OpMode = MD_PRINT;
375	else if (strcmp(p, "smtpd") == 0)
376		OpMode = MD_DAEMON;
377	else if (strcmp(p, "hoststat") == 0)
378		OpMode = MD_HOSTSTAT;
379	else if (strcmp(p, "purgestat") == 0)
380		OpMode = MD_PURGESTAT;
381
382#if defined(__osf__) || defined(_AIX3)
383# define OPTIONS	"A:B:b:C:cD:d:e:F:f:Gh:IiL:M:mN:nO:o:p:Q:q:R:r:sTtV:vX:x"
384#endif /* defined(__osf__) || defined(_AIX3) */
385#if defined(sony_news)
386# define OPTIONS	"A:B:b:C:cD:d:E:e:F:f:Gh:IiJ:L:M:mN:nO:o:p:Q:q:R:r:sTtV:vX:"
387#endif /* defined(sony_news) */
388#ifndef OPTIONS
389# define OPTIONS	"A:B:b:C:cD:d:e:F:f:Gh:IiL:M:mN:nO:o:p:Q:q:R:r:sTtV:vX:"
390#endif
391
392	/* Set to 0 to allow -b; need to check optarg before using it! */
393	opterr = 0;
394	while ((j = getopt(argc, argv, OPTIONS)) != -1)
395	{
396		switch (j)
397		{
398		  case 'b':	/* operations mode */
399			j = (optarg == NULL) ? ' ' : *optarg;
400			switch (j)
401			{
402			  case MD_DAEMON:
403			  case MD_FGDAEMON:
404			  case MD_SMTP:
405			  case MD_INITALIAS:
406			  case MD_DELIVER:
407			  case MD_VERIFY:
408			  case MD_TEST:
409			  case MD_PRINT:
410			  case MD_PRINTNQE:
411			  case MD_HOSTSTAT:
412			  case MD_PURGESTAT:
413			  case MD_ARPAFTP:
414			  case MD_CHECKCONFIG:
415				OpMode = j;
416				break;
417
418#if _FFR_LOCAL_DAEMON
419			  case MD_LOCAL:
420				OpMode = MD_DAEMON;
421				LocalDaemon = true;
422				break;
423#endif /* _FFR_LOCAL_DAEMON */
424
425			  case MD_FREEZE:
426				(void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
427						     "Frozen configurations unsupported\n");
428				return EX_USAGE;
429
430			  default:
431				(void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
432						     "Invalid operation mode %c\n",
433						     j);
434				return EX_USAGE;
435			}
436			break;
437
438		  case 'D':
439			if (debug)
440			{
441				errno = 0;
442				syserr("-D file must be before -d");
443				ExitStat = EX_USAGE;
444				break;
445			}
446			dp = drop_privileges(true);
447			setstat(dp);
448			smdebug = sm_io_open(SmFtStdio, SM_TIME_DEFAULT,
449					    optarg, SM_IO_APPEND, NULL);
450			if (smdebug == NULL)
451			{
452				syserr("cannot open %s", optarg);
453				ExitStat = EX_CANTCREAT;
454				break;
455			}
456			sm_debug_setfile(smdebug);
457			break;
458
459		  case 'd':
460			debug = true;
461			tTflag(optarg);
462			(void) sm_io_setvbuf(sm_debug_file(), SM_TIME_DEFAULT,
463					     (char *) NULL, SM_IO_NBF,
464					     SM_IO_BUFSIZ);
465			break;
466
467		  case 'G':	/* relay (gateway) submission */
468			SubmitMode = SUBMIT_MTA;
469			break;
470
471		  case 'L':
472			if (optarg == NULL)
473			{
474				(void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
475						     "option requires an argument -- '%c'",
476						     (char) j);
477				return EX_USAGE;
478			}
479			j = SM_MIN(strlen(optarg), 32) + 1;
480			sysloglabel = xalloc(j);
481			(void) sm_strlcpy(sysloglabel, optarg, j);
482			SyslogPrefixLen = PIDLEN + (MAXQFNAME - 3) +
483					  SL_FUDGE + j;
484			break;
485
486		  case 'Q':
487		  case 'q':
488			/* just check if it is there */
489			queuerun = true;
490			break;
491		}
492	}
493	opterr = 1;
494
495	/* Don't leak queue information via debug flags */
496	if (extraprivs && queuerun && debug)
497	{
498		(void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
499				     "WARNING: Can not use -d with -q.  Disabling debugging.\n");
500		sm_debug_close();
501		sm_debug_setfile(NULL);
502		(void) memset(tTdvect, '\0', sizeof(tTdvect));
503	}
504
505#if LOG
506	if (sysloglabel != NULL)
507	{
508		/* Sanitize the string */
509		for (p = sysloglabel; *p != '\0'; p++)
510		{
511			if (!isascii(*p) || !isprint(*p) || *p == '%')
512				*p = '*';
513		}
514		closelog();
515# ifdef LOG_MAIL
516		openlog(sysloglabel, LOG_PID, LOG_MAIL);
517# else
518		openlog(sysloglabel, LOG_PID);
519# endif
520	}
521#endif /* LOG */
522
523	/* set up the blank envelope */
524	BlankEnvelope.e_puthdr = putheader;
525	BlankEnvelope.e_putbody = putbody;
526	BlankEnvelope.e_xfp = NULL;
527	STRUCTCOPY(NullAddress, BlankEnvelope.e_from);
528	CurEnv = &BlankEnvelope;
529	STRUCTCOPY(NullAddress, MainEnvelope.e_from);
530
531	/*
532	**  Set default values for variables.
533	**	These cannot be in initialized data space.
534	*/
535
536	setdefaults(&BlankEnvelope);
537	initmacros(&BlankEnvelope);
538
539	/* reset macro */
540	set_op_mode(OpMode);
541	if (OpMode == MD_DAEMON)
542		DaemonPid = CurrentPid;	/* needed for finis() to work */
543
544	pw = sm_getpwuid(RealUid);
545	if (pw != NULL)
546		(void) sm_strlcpy(rnamebuf, pw->pw_name, sizeof(rnamebuf));
547	else
548		(void) sm_snprintf(rnamebuf, sizeof(rnamebuf), "Unknown UID %d",
549				   (int) RealUid);
550
551	RealUserName = rnamebuf;
552
553	if (tTd(0, 101))
554	{
555		sm_dprintf("Version %s\n", Version);
556		finis(false, true, EX_OK);
557		/* NOTREACHED */
558	}
559
560	/*
561	**  if running non-set-user-ID binary as non-root, pretend
562	**  we are the RunAsUid
563	*/
564
565	if (RealUid != 0 && geteuid() == RealUid)
566	{
567		if (tTd(47, 1))
568			sm_dprintf("Non-set-user-ID binary: RunAsUid = RealUid = %d\n",
569				   (int) RealUid);
570		RunAsUid = RealUid;
571	}
572	else if (geteuid() != 0)
573		RunAsUid = geteuid();
574
575	EffGid = getegid();
576	if (RealUid != 0 && EffGid == RealGid)
577		RunAsGid = RealGid;
578
579	if (tTd(47, 5))
580	{
581		sm_dprintf("main: e/ruid = %d/%d e/rgid = %d/%d\n",
582			   (int) geteuid(), (int) getuid(),
583			   (int) getegid(), (int) getgid());
584		sm_dprintf("main: RunAsUser = %d:%d\n",
585			   (int) RunAsUid, (int) RunAsGid);
586	}
587
588	/* save command line arguments */
589	j = 0;
590	for (av = argv; *av != NULL; )
591		j += strlen(*av++) + 1;
592	SaveArgv = (char **) xalloc(sizeof(char *) * (argc + 1));
593	CommandLineArgs = xalloc(j);
594	p = CommandLineArgs;
595	for (av = argv, i = 0; *av != NULL; )
596	{
597		int h;
598
599		SaveArgv[i++] = newstr(*av);
600		if (av != argv)
601			*p++ = ' ';
602		(void) sm_strlcpy(p, *av++, j);
603		h = strlen(p);
604		p += h;
605		j -= h + 1;
606	}
607	SaveArgv[i] = NULL;
608
609	if (tTd(0, 1))
610	{
611		extern char *CompileOptions[];
612
613		sm_dprintf("Version %s\n Compiled with:", Version);
614		sm_printoptions(CompileOptions);
615	}
616	if (tTd(0, 10))
617	{
618		extern char *OsCompileOptions[];
619
620		sm_dprintf("    OS Defines:");
621		sm_printoptions(OsCompileOptions);
622#ifdef _PATH_UNIX
623		sm_dprintf("Kernel symbols:\t%s\n", _PATH_UNIX);
624#endif
625
626		sm_dprintf("     Conf file:\t%s (default for MSP)\n",
627			   getcfname(OpMode, SubmitMode, SM_GET_SUBMIT_CF,
628				     conffile));
629		sm_dprintf("     Conf file:\t%s (default for MTA)\n",
630			   getcfname(OpMode, SubmitMode, SM_GET_SENDMAIL_CF,
631				     conffile));
632		sm_dprintf("      Pid file:\t%s (default)\n", PidFile);
633	}
634
635	if (tTd(0, 12))
636	{
637		extern char *SmCompileOptions[];
638
639		sm_dprintf(" libsm Defines:");
640		sm_printoptions(SmCompileOptions);
641	}
642
643	if (tTd(0, 13))
644	{
645		extern char *FFRCompileOptions[];
646
647		sm_dprintf("   FFR Defines:");
648		sm_printoptions(FFRCompileOptions);
649	}
650
651#if STARTTLS
652	if (tTd(0, 14))
653	{
654		/* exit(EX_CONFIG) if different? */
655		sm_dprintf("       OpenSSL: compiled 0x%08x\n",
656			   (uint) OPENSSL_VERSION_NUMBER);
657		sm_dprintf("       OpenSSL: linked   0x%08x\n",
658			   (uint) TLS_version_num());
659	}
660#endif /* STARTTLS */
661
662	/* clear sendmail's environment */
663	ExternalEnviron = environ;
664	emptyenviron[0] = NULL;
665	environ = emptyenviron;
666
667	/*
668	**  restore any original TZ setting until TimeZoneSpec has been
669	**  determined - or early log messages may get bogus time stamps
670	*/
671
672	if ((p = getextenv("TZ")) != NULL)
673	{
674		char *tz;
675		int tzlen;
676
677		/* XXX check for reasonable length? */
678		tzlen = strlen(p) + 4;
679		tz = xalloc(tzlen);
680		(void) sm_strlcpyn(tz, tzlen, 2, "TZ=", p);
681
682		/* XXX check return code? */
683		(void) putenv(tz);
684	}
685
686	/* prime the child environment */
687	sm_setuserenv("AGENT", "sendmail");
688
689	(void) sm_signal(SIGPIPE, SIG_IGN);
690	OldUmask = umask(022);
691	FullName = getextenv("NAME");
692	if (FullName != NULL)
693		FullName = newstr(FullName);
694
695	/*
696	**  Initialize name server if it is going to be used.
697	*/
698
699#if NAMED_BIND
700	if (!bitset(RES_INIT, _res.options))
701		(void) res_init();
702	if (tTd(8, 8))
703		_res.options |= RES_DEBUG;
704	else
705		_res.options &= ~RES_DEBUG;
706# ifdef RES_NOALIASES
707	_res.options |= RES_NOALIASES;
708# endif
709	TimeOuts.res_retry[RES_TO_DEFAULT] = _res.retry;
710	TimeOuts.res_retry[RES_TO_FIRST] = _res.retry;
711	TimeOuts.res_retry[RES_TO_NORMAL] = _res.retry;
712	TimeOuts.res_retrans[RES_TO_DEFAULT] = _res.retrans;
713	TimeOuts.res_retrans[RES_TO_FIRST] = _res.retrans;
714	TimeOuts.res_retrans[RES_TO_NORMAL] = _res.retrans;
715#endif /* NAMED_BIND */
716
717	errno = 0;
718	from = NULL;
719
720	/* initialize some macros, etc. */
721	init_vendor_macros(&BlankEnvelope);
722
723	/* version */
724	macdefine(&BlankEnvelope.e_macro, A_PERM, 'v', Version);
725
726	/* hostname */
727	hp = myhostname(jbuf, sizeof(jbuf));
728	if (jbuf[0] != '\0')
729	{
730		struct utsname utsname;
731
732		if (tTd(0, 4))
733			sm_dprintf("Canonical name: %s\n", jbuf);
734		macdefine(&BlankEnvelope.e_macro, A_TEMP, 'w', jbuf);
735		macdefine(&BlankEnvelope.e_macro, A_TEMP, 'j', jbuf);
736		setclass('w', jbuf);
737
738		p = strchr(jbuf, '.');
739		if (p != NULL && p[1] != '\0')
740			macdefine(&BlankEnvelope.e_macro, A_TEMP, 'm', &p[1]);
741
742		if (uname(&utsname) >= 0)
743			p = utsname.nodename;
744		else
745		{
746			if (tTd(0, 22))
747				sm_dprintf("uname failed (%s)\n",
748					   sm_errstring(errno));
749			makelower(jbuf);
750			p = jbuf;
751		}
752		if (tTd(0, 4))
753			sm_dprintf(" UUCP nodename: %s\n", p);
754		macdefine(&BlankEnvelope.e_macro, A_TEMP, 'k', p);
755		setclass('k', p);
756		setclass('w', p);
757	}
758	if (hp != NULL)
759	{
760		for (av = hp->h_aliases; av != NULL && *av != NULL; av++)
761		{
762			if (tTd(0, 4))
763				sm_dprintf("\ta.k.a.: %s\n", *av);
764			setclass('w', *av);
765		}
766#if NETINET || NETINET6
767		for (i = 0; i >= 0 && hp->h_addr_list[i] != NULL; i++)
768		{
769# if NETINET6
770			char *addr;
771			char buf6[INET6_ADDRSTRLEN];
772			struct in6_addr ia6;
773# endif /* NETINET6 */
774# if NETINET
775			struct in_addr ia;
776# endif
777			char ipbuf[103];
778
779			ipbuf[0] = '\0';
780			switch (hp->h_addrtype)
781			{
782# if NETINET
783			  case AF_INET:
784				if (hp->h_length != INADDRSZ)
785					break;
786
787				memmove(&ia, hp->h_addr_list[i], INADDRSZ);
788				(void) sm_snprintf(ipbuf, sizeof(ipbuf),
789						   "[%.100s]", inet_ntoa(ia));
790				break;
791# endif /* NETINET */
792
793# if NETINET6
794			  case AF_INET6:
795				if (hp->h_length != IN6ADDRSZ)
796					break;
797
798				memmove(&ia6, hp->h_addr_list[i], IN6ADDRSZ);
799				addr = anynet_ntop(&ia6, buf6, sizeof(buf6));
800				if (addr != NULL)
801					(void) sm_snprintf(ipbuf, sizeof(ipbuf),
802							   "[%.100s]", addr);
803				break;
804# endif /* NETINET6 */
805			}
806			if (ipbuf[0] == '\0')
807				break;
808
809			if (tTd(0, 4))
810				sm_dprintf("\ta.k.a.: %s\n", ipbuf);
811			setclass('w', ipbuf);
812		}
813#endif /* NETINET || NETINET6 */
814#if NETINET6
815		freehostent(hp);
816		hp = NULL;
817#endif
818	}
819
820	/* current time */
821	macdefine(&BlankEnvelope.e_macro, A_TEMP, 'b', arpadate((char *) NULL));
822
823	/* current load average */
824	sm_getla();
825
826	QueueLimitRecipient = (QUEUE_CHAR *) NULL;
827	QueueLimitSender = (QUEUE_CHAR *) NULL;
828	QueueLimitId = (QUEUE_CHAR *) NULL;
829	QueueLimitQuarantine = (QUEUE_CHAR *) NULL;
830
831	/*
832	**  Crack argv.
833	*/
834
835	optind = 1;
836	while ((j = getopt(argc, argv, OPTIONS)) != -1)
837	{
838		switch (j)
839		{
840		  case 'b':	/* operations mode */
841			/* already done */
842			break;
843
844		  case 'A':	/* use Alternate sendmail/submit.cf */
845			cftype = optarg[0] == 'c' ? SM_GET_SUBMIT_CF
846						  : SM_GET_SENDMAIL_CF;
847			break;
848
849		  case 'B':	/* body type */
850			CHECK_AGAINST_OPMODE(j);
851			BlankEnvelope.e_bodytype = newstr(optarg);
852			break;
853
854		  case 'C':	/* select configuration file (already done) */
855			if (RealUid != 0)
856				warn_C_flag = true;
857			conffile = newstr(optarg);
858			dp = drop_privileges(true);
859			setstat(dp);
860			safecf = false;
861			break;
862
863		  case 'D':
864		  case 'd':	/* debugging */
865			/* already done */
866			break;
867
868		  case 'f':	/* from address */
869		  case 'r':	/* obsolete -f flag */
870			CHECK_AGAINST_OPMODE(j);
871			if (from != NULL)
872			{
873				usrerr("More than one \"from\" person");
874				ExitStat = EX_USAGE;
875				break;
876			}
877			if (optarg[0] == '\0')
878				from = newstr("<>");
879			else
880				from = newstr(denlstring(optarg, true, true));
881			if (strcmp(RealUserName, from) != 0)
882				warn_f_flag = j;
883			break;
884
885		  case 'F':	/* set full name */
886			CHECK_AGAINST_OPMODE(j);
887			FullName = newstr(optarg);
888			break;
889
890		  case 'G':	/* relay (gateway) submission */
891			/* already set */
892			CHECK_AGAINST_OPMODE(j);
893			break;
894
895		  case 'h':	/* hop count */
896			CHECK_AGAINST_OPMODE(j);
897			BlankEnvelope.e_hopcount = (short) strtol(optarg, &ep,
898								  10);
899			(void) sm_snprintf(buf, sizeof(buf), "%d",
900					   BlankEnvelope.e_hopcount);
901			macdefine(&BlankEnvelope.e_macro, A_TEMP, 'c', buf);
902
903			if (*ep)
904			{
905				usrerr("Bad hop count (%s)", optarg);
906				ExitStat = EX_USAGE;
907			}
908			break;
909
910		  case 'L':	/* program label */
911			/* already set */
912			break;
913
914		  case 'n':	/* don't alias */
915			CHECK_AGAINST_OPMODE(j);
916			NoAlias = true;
917			break;
918
919		  case 'N':	/* delivery status notifications */
920			CHECK_AGAINST_OPMODE(j);
921			DefaultNotify |= QHASNOTIFY;
922			macdefine(&BlankEnvelope.e_macro, A_TEMP,
923				macid("{dsn_notify}"), optarg);
924			if (sm_strcasecmp(optarg, "never") == 0)
925				break;
926			for (p = optarg; p != NULL; optarg = p)
927			{
928				p = strchr(p, ',');
929				if (p != NULL)
930					*p++ = '\0';
931				if (sm_strcasecmp(optarg, "success") == 0)
932					DefaultNotify |= QPINGONSUCCESS;
933				else if (sm_strcasecmp(optarg, "failure") == 0)
934					DefaultNotify |= QPINGONFAILURE;
935				else if (sm_strcasecmp(optarg, "delay") == 0)
936					DefaultNotify |= QPINGONDELAY;
937				else
938				{
939					usrerr("Invalid -N argument");
940					ExitStat = EX_USAGE;
941				}
942			}
943			break;
944
945		  case 'o':	/* set option */
946			setoption(*optarg, optarg + 1, false, true,
947				  &BlankEnvelope);
948			break;
949
950		  case 'O':	/* set option (long form) */
951			setoption(' ', optarg, false, true, &BlankEnvelope);
952			break;
953
954		  case 'p':	/* set protocol */
955			CHECK_AGAINST_OPMODE(j);
956			p = strchr(optarg, ':');
957			if (p != NULL)
958			{
959				*p++ = '\0';
960				if (*p != '\0')
961				{
962					i = strlen(p) + 1;
963					ep = sm_malloc_x(i);
964					cleanstrcpy(ep, p, i);
965					macdefine(&BlankEnvelope.e_macro,
966						  A_HEAP, 's', ep);
967				}
968			}
969			if (*optarg != '\0')
970			{
971				i = strlen(optarg) + 1;
972				ep = sm_malloc_x(i);
973				cleanstrcpy(ep, optarg, i);
974				macdefine(&BlankEnvelope.e_macro, A_HEAP,
975					  'r', ep);
976			}
977			break;
978
979		  case 'Q':	/* change quarantining on queued items */
980			/* sanity check */
981			if (OpMode != MD_DELIVER &&
982			    OpMode != MD_QUEUERUN)
983			{
984				usrerr("Can not use -Q with -b%c", OpMode);
985				ExitStat = EX_USAGE;
986				break;
987			}
988
989			if (OpMode == MD_DELIVER)
990				set_op_mode(MD_QUEUERUN);
991
992			FullName = NULL;
993
994			quarantining = newstr(optarg);
995			break;
996
997		  case 'q':	/* run queue files at intervals */
998			/* sanity check */
999			if (OpMode != MD_DELIVER &&
1000			    OpMode != MD_DAEMON &&
1001			    OpMode != MD_FGDAEMON &&
1002			    OpMode != MD_PRINT &&
1003			    OpMode != MD_PRINTNQE &&
1004			    OpMode != MD_QUEUERUN)
1005			{
1006				usrerr("Can not use -q with -b%c", OpMode);
1007				ExitStat = EX_USAGE;
1008				break;
1009			}
1010
1011			/* don't override -bd, -bD or -bp */
1012			if (OpMode == MD_DELIVER)
1013				set_op_mode(MD_QUEUERUN);
1014
1015			FullName = NULL;
1016			negate = optarg[0] == '!';
1017			if (negate)
1018			{
1019				/* negate meaning of pattern match */
1020				optarg++; /* skip '!' for next switch */
1021			}
1022
1023			switch (optarg[0])
1024			{
1025			  case 'G': /* Limit by queue group name */
1026				if (negate)
1027				{
1028					usrerr("Can not use -q!G");
1029					ExitStat = EX_USAGE;
1030					break;
1031				}
1032				if (queuegroup != NULL)
1033				{
1034					usrerr("Can not use multiple -qG options");
1035					ExitStat = EX_USAGE;
1036					break;
1037				}
1038				queuegroup = newstr(&optarg[1]);
1039				break;
1040
1041			  case 'I': /* Limit by ID */
1042				new = (QUEUE_CHAR *) xalloc(sizeof(*new));
1043				new->queue_match = newstr(&optarg[1]);
1044				new->queue_negate = negate;
1045				new->queue_next = QueueLimitId;
1046				QueueLimitId = new;
1047				break;
1048
1049			  case 'R': /* Limit by recipient */
1050				new = (QUEUE_CHAR *) xalloc(sizeof(*new));
1051				new->queue_match = newstr(&optarg[1]);
1052				new->queue_negate = negate;
1053				new->queue_next = QueueLimitRecipient;
1054				QueueLimitRecipient = new;
1055				break;
1056
1057			  case 'S': /* Limit by sender */
1058				new = (QUEUE_CHAR *) xalloc(sizeof(*new));
1059				new->queue_match = newstr(&optarg[1]);
1060				new->queue_negate = negate;
1061				new->queue_next = QueueLimitSender;
1062				QueueLimitSender = new;
1063				break;
1064
1065			  case 'f': /* foreground queue run */
1066				foregroundqueue  = true;
1067				break;
1068
1069			  case 'Q': /* Limit by quarantine message */
1070				if (optarg[1] != '\0')
1071				{
1072					new = (QUEUE_CHAR *) xalloc(sizeof(*new));
1073					new->queue_match = newstr(&optarg[1]);
1074					new->queue_negate = negate;
1075					new->queue_next = QueueLimitQuarantine;
1076					QueueLimitQuarantine = new;
1077				}
1078				QueueMode = QM_QUARANTINE;
1079				break;
1080
1081			  case 'L': /* act on lost items */
1082				QueueMode = QM_LOST;
1083				break;
1084
1085			  case 'p': /* Persistent queue */
1086				queuepersistent = true;
1087				if (QueueIntvl == 0)
1088					QueueIntvl = 1;
1089				if (optarg[1] == '\0')
1090					break;
1091				++optarg;
1092				/* FALLTHROUGH */
1093
1094			  default:
1095				i = Errors;
1096				QueueIntvl = convtime(optarg, 'm');
1097				if (QueueIntvl < 0)
1098				{
1099					usrerr("Invalid -q value");
1100					ExitStat = EX_USAGE;
1101				}
1102
1103				/* check for bad conversion */
1104				if (i < Errors)
1105					ExitStat = EX_USAGE;
1106				break;
1107			}
1108			break;
1109
1110		  case 'R':	/* DSN RET: what to return */
1111			CHECK_AGAINST_OPMODE(j);
1112			if (bitset(EF_RET_PARAM, BlankEnvelope.e_flags))
1113			{
1114				usrerr("Duplicate -R flag");
1115				ExitStat = EX_USAGE;
1116				break;
1117			}
1118			BlankEnvelope.e_flags |= EF_RET_PARAM;
1119			if (sm_strcasecmp(optarg, "hdrs") == 0)
1120				BlankEnvelope.e_flags |= EF_NO_BODY_RETN;
1121			else if (sm_strcasecmp(optarg, "full") != 0)
1122			{
1123				usrerr("Invalid -R value");
1124				ExitStat = EX_USAGE;
1125			}
1126			macdefine(&BlankEnvelope.e_macro, A_TEMP,
1127				  macid("{dsn_ret}"), optarg);
1128			break;
1129
1130		  case 't':	/* read recipients from message */
1131			CHECK_AGAINST_OPMODE(j);
1132			GrabTo = true;
1133			break;
1134
1135		  case 'V':	/* DSN ENVID: set "original" envelope id */
1136			CHECK_AGAINST_OPMODE(j);
1137			if (!xtextok(optarg))
1138			{
1139				usrerr("Invalid syntax in -V flag");
1140				ExitStat = EX_USAGE;
1141			}
1142			else
1143			{
1144				BlankEnvelope.e_envid = newstr(optarg);
1145				macdefine(&BlankEnvelope.e_macro, A_TEMP,
1146					  macid("{dsn_envid}"), optarg);
1147			}
1148			break;
1149
1150		  case 'X':	/* traffic log file */
1151			dp = drop_privileges(true);
1152			setstat(dp);
1153			if (stat(optarg, &traf_st) == 0 &&
1154			    S_ISFIFO(traf_st.st_mode))
1155				TrafficLogFile = sm_io_open(SmFtStdio,
1156							    SM_TIME_DEFAULT,
1157							    optarg,
1158							    SM_IO_WRONLY, NULL);
1159			else
1160				TrafficLogFile = sm_io_open(SmFtStdio,
1161							    SM_TIME_DEFAULT,
1162							    optarg,
1163							    SM_IO_APPEND, NULL);
1164			if (TrafficLogFile == NULL)
1165			{
1166				syserr("cannot open %s", optarg);
1167				ExitStat = EX_CANTCREAT;
1168				break;
1169			}
1170			(void) sm_io_setvbuf(TrafficLogFile, SM_TIME_DEFAULT,
1171					     NULL, SM_IO_LBF, 0);
1172			break;
1173
1174			/* compatibility flags */
1175		  case 'c':	/* connect to non-local mailers */
1176		  case 'i':	/* don't let dot stop me */
1177		  case 'm':	/* send to me too */
1178		  case 'T':	/* set timeout interval */
1179		  case 'v':	/* give blow-by-blow description */
1180			setoption(j, "T", false, true, &BlankEnvelope);
1181			break;
1182
1183		  case 'e':	/* error message disposition */
1184		  case 'M':	/* define macro */
1185			setoption(j, optarg, false, true, &BlankEnvelope);
1186			break;
1187
1188		  case 's':	/* save From lines in headers */
1189			setoption('f', "T", false, true, &BlankEnvelope);
1190			break;
1191
1192#ifdef DBM
1193		  case 'I':	/* initialize alias DBM file */
1194			set_op_mode(MD_INITALIAS);
1195			break;
1196#endif /* DBM */
1197
1198#if defined(__osf__) || defined(_AIX3)
1199		  case 'x':	/* random flag that OSF/1 & AIX mailx passes */
1200			break;
1201#endif
1202#if defined(sony_news)
1203		  case 'E':
1204		  case 'J':	/* ignore flags for Japanese code conversion
1205				   implemented on Sony NEWS */
1206			break;
1207#endif /* defined(sony_news) */
1208
1209		  default:
1210			finis(true, true, EX_USAGE);
1211			/* NOTREACHED */
1212			break;
1213		}
1214	}
1215
1216	/* if we've had errors so far, exit now */
1217	if ((ExitStat != EX_OK && OpMode != MD_TEST && OpMode != MD_CHECKCONFIG) ||
1218	    ExitStat == EX_OSERR)
1219	{
1220		finis(false, true, ExitStat);
1221		/* NOTREACHED */
1222	}
1223
1224	if (bitset(SUBMIT_MTA, SubmitMode))
1225	{
1226		/* If set daemon_flags on command line, don't reset it */
1227		if (macvalue(macid("{daemon_flags}"), &BlankEnvelope) == NULL)
1228			macdefine(&BlankEnvelope.e_macro, A_PERM,
1229				  macid("{daemon_flags}"), "CC f");
1230	}
1231	else if (OpMode == MD_DELIVER || OpMode == MD_SMTP)
1232	{
1233		SubmitMode = SUBMIT_MSA;
1234
1235		/* If set daemon_flags on command line, don't reset it */
1236		if (macvalue(macid("{daemon_flags}"), &BlankEnvelope) == NULL)
1237			macdefine(&BlankEnvelope.e_macro, A_PERM,
1238				  macid("{daemon_flags}"), "c u");
1239	}
1240
1241	/*
1242	**  Do basic initialization.
1243	**	Read system control file.
1244	**	Extract special fields for local use.
1245	*/
1246
1247#if XDEBUG
1248	checkfd012("before readcf");
1249#endif
1250	vendor_pre_defaults(&BlankEnvelope);
1251
1252	readcf(getcfname(OpMode, SubmitMode, cftype, conffile),
1253			 safecf, &BlankEnvelope);
1254#if !defined(_USE_SUN_NSSWITCH_) && !defined(_USE_DEC_SVC_CONF_)
1255	ConfigFileRead = true;
1256#endif
1257	vendor_post_defaults(&BlankEnvelope);
1258
1259	/* now we can complain about missing fds */
1260	if (MissingFds != 0 && LogLevel > 8)
1261	{
1262		char mbuf[MAXLINE];
1263
1264		mbuf[0] = '\0';
1265		if (bitset(1 << STDIN_FILENO, MissingFds))
1266			(void) sm_strlcat(mbuf, ", stdin", sizeof(mbuf));
1267		if (bitset(1 << STDOUT_FILENO, MissingFds))
1268			(void) sm_strlcat(mbuf, ", stdout", sizeof(mbuf));
1269		if (bitset(1 << STDERR_FILENO, MissingFds))
1270			(void) sm_strlcat(mbuf, ", stderr", sizeof(mbuf));
1271
1272		/* Notice: fill_errno is from high above: fill_fd() */
1273		sm_syslog(LOG_WARNING, NOQID,
1274			  "File descriptors missing on startup: %s; %s",
1275			  &mbuf[2], sm_errstring(fill_errno));
1276	}
1277
1278	/* Remove the ability for a normal user to send signals */
1279	if (RealUid != 0 && RealUid != geteuid())
1280	{
1281		uid_t new_uid = geteuid();
1282
1283#if HASSETREUID
1284		/*
1285		**  Since we can differentiate between uid and euid,
1286		**  make the uid a different user so the real user
1287		**  can't send signals.  However, it doesn't need to be
1288		**  root (euid has root).
1289		*/
1290
1291		if (new_uid == 0)
1292			new_uid = DefUid;
1293		if (tTd(47, 5))
1294			sm_dprintf("Changing real uid to %d\n", (int) new_uid);
1295		if (setreuid(new_uid, geteuid()) < 0)
1296		{
1297			syserr("main: setreuid(%d, %d) failed",
1298			       (int) new_uid, (int) geteuid());
1299			finis(false, true, EX_OSERR);
1300			/* NOTREACHED */
1301		}
1302		if (tTd(47, 10))
1303			sm_dprintf("Now running as e/ruid %d:%d\n",
1304				   (int) geteuid(), (int) getuid());
1305#else /* HASSETREUID */
1306		/*
1307		**  Have to change both effective and real so need to
1308		**  change them both to effective to keep privs.
1309		*/
1310
1311		if (tTd(47, 5))
1312			sm_dprintf("Changing uid to %d\n", (int) new_uid);
1313		if (setuid(new_uid) < 0)
1314		{
1315			syserr("main: setuid(%d) failed", (int) new_uid);
1316			finis(false, true, EX_OSERR);
1317			/* NOTREACHED */
1318		}
1319		if (tTd(47, 10))
1320			sm_dprintf("Now running as e/ruid %d:%d\n",
1321				   (int) geteuid(), (int) getuid());
1322#endif /* HASSETREUID */
1323	}
1324
1325#if NAMED_BIND
1326	if (FallbackMX != NULL)
1327		(void) getfallbackmxrr(FallbackMX);
1328#endif
1329
1330	if (SuperSafe == SAFE_INTERACTIVE && !SM_IS_INTERACTIVE(CurEnv->e_sendmode))
1331	{
1332		(void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
1333				     "WARNING: SuperSafe=interactive should only be used with\n         DeliveryMode=interactive\n");
1334	}
1335
1336	if (UseMSP && (OpMode == MD_DAEMON || OpMode == MD_FGDAEMON))
1337	{
1338		usrerr("Mail submission program cannot be used as daemon");
1339		finis(false, true, EX_USAGE);
1340	}
1341
1342	if (OpMode == MD_DELIVER || OpMode == MD_SMTP ||
1343	    OpMode == MD_QUEUERUN || OpMode == MD_ARPAFTP ||
1344	    OpMode == MD_DAEMON || OpMode == MD_FGDAEMON)
1345		makeworkgroups();
1346
1347	/* set up the basic signal handlers */
1348	if (sm_signal(SIGINT, SIG_IGN) != SIG_IGN)
1349		(void) sm_signal(SIGINT, intsig);
1350	(void) sm_signal(SIGTERM, intsig);
1351
1352	/* Enforce use of local time (null string overrides this) */
1353	if (TimeZoneSpec == NULL)
1354		unsetenv("TZ");
1355	else if (TimeZoneSpec[0] != '\0')
1356		sm_setuserenv("TZ", TimeZoneSpec);
1357	else
1358		sm_setuserenv("TZ", NULL);
1359	tzset();
1360
1361	/* initialize mailbox database */
1362	i = sm_mbdb_initialize(Mbdb);
1363	if (i != EX_OK)
1364	{
1365		usrerr("Can't initialize mailbox database \"%s\": %s",
1366		       Mbdb, sm_strexit(i));
1367		ExitStat = i;
1368	}
1369
1370	/* avoid denial-of-service attacks */
1371	resetlimits();
1372
1373	if (OpMode == MD_TEST)
1374	{
1375		/* can't be done after readcf if RunAs* is used */
1376		dp = drop_privileges(true);
1377		if (dp != EX_OK)
1378		{
1379			finis(false, true, dp);
1380			/* NOTREACHED */
1381		}
1382	}
1383	else if (OpMode != MD_DAEMON && OpMode != MD_FGDAEMON)
1384	{
1385		/* drop privileges -- daemon mode done after socket/bind */
1386		dp = drop_privileges(false);
1387		setstat(dp);
1388		if (dp == EX_OK && UseMSP && (geteuid() == 0 || getuid() == 0))
1389		{
1390			usrerr("Mail submission program must have RunAsUser set to non root user");
1391			finis(false, true, EX_CONFIG);
1392			/* NOTREACHED */
1393		}
1394	}
1395
1396#if NAMED_BIND
1397	_res.retry = TimeOuts.res_retry[RES_TO_DEFAULT];
1398	_res.retrans = TimeOuts.res_retrans[RES_TO_DEFAULT];
1399#endif
1400
1401	/*
1402	**  Find our real host name for future logging.
1403	*/
1404
1405	authinfo = getauthinfo(STDIN_FILENO, &forged);
1406	macdefine(&BlankEnvelope.e_macro, A_TEMP, '_', authinfo);
1407
1408	/* suppress error printing if errors mailed back or whatever */
1409	if (BlankEnvelope.e_errormode != EM_PRINT)
1410		HoldErrs = true;
1411
1412	/* set up the $=m class now, after .cf has a chance to redefine $m */
1413	expand("\201m", jbuf, sizeof(jbuf), &BlankEnvelope);
1414	if (jbuf[0] != '\0')
1415		setclass('m', jbuf);
1416
1417	/* probe interfaces and locate any additional names */
1418	if (DontProbeInterfaces != DPI_PROBENONE)
1419		load_if_names();
1420
1421	if (tTd(0, 10))
1422	{
1423		char pidpath[MAXPATHLEN];
1424
1425		/* Now we know which .cf file we use */
1426		sm_dprintf("     Conf file:\t%s (selected)\n",
1427			   getcfname(OpMode, SubmitMode, cftype, conffile));
1428		expand(PidFile, pidpath, sizeof(pidpath), &BlankEnvelope);
1429		sm_dprintf("      Pid file:\t%s (selected)\n", pidpath);
1430	}
1431
1432	if (tTd(0, 1))
1433	{
1434		sm_dprintf("\n============ SYSTEM IDENTITY (after readcf) ============");
1435		sm_dprintf("\n      (short domain name) $w = ");
1436		xputs(sm_debug_file(), macvalue('w', &BlankEnvelope));
1437		sm_dprintf("\n  (canonical domain name) $j = ");
1438		xputs(sm_debug_file(), macvalue('j', &BlankEnvelope));
1439		sm_dprintf("\n         (subdomain name) $m = ");
1440		xputs(sm_debug_file(), macvalue('m', &BlankEnvelope));
1441		sm_dprintf("\n              (node name) $k = ");
1442		xputs(sm_debug_file(), macvalue('k', &BlankEnvelope));
1443		sm_dprintf("\n========================================================\n\n");
1444	}
1445
1446	/*
1447	**  Do more command line checking -- these are things that
1448	**  have to modify the results of reading the config file.
1449	*/
1450
1451	/* process authorization warnings from command line */
1452	if (warn_C_flag)
1453		auth_warning(&BlankEnvelope, "Processed by %s with -C %s",
1454			     RealUserName, conffile);
1455	if (Warn_Q_option && !wordinclass(RealUserName, 't'))
1456		auth_warning(&BlankEnvelope, "Processed from queue %s",
1457			     QueueDir);
1458	if (sysloglabel != NULL && !wordinclass(RealUserName, 't') &&
1459	    RealUid != 0 && RealUid != TrustedUid && LogLevel > 1)
1460		sm_syslog(LOG_WARNING, NOQID, "user %d changed syslog label",
1461			  (int) RealUid);
1462
1463	/* check body type for legality */
1464	i = check_bodytype(BlankEnvelope.e_bodytype);
1465	if (i == BODYTYPE_ILLEGAL)
1466	{
1467		usrerr("Illegal body type %s", BlankEnvelope.e_bodytype);
1468		BlankEnvelope.e_bodytype = NULL;
1469	}
1470	else if (i != BODYTYPE_NONE)
1471		SevenBitInput = (i == BODYTYPE_7BIT);
1472
1473	/* tweak default DSN notifications */
1474	if (DefaultNotify == 0)
1475		DefaultNotify = QPINGONFAILURE|QPINGONDELAY;
1476
1477	/* check for sane configuration level */
1478	if (ConfigLevel > MAXCONFIGLEVEL)
1479	{
1480		syserr("Warning: .cf version level (%d) exceeds sendmail version %s functionality (%d)",
1481		       ConfigLevel, Version, MAXCONFIGLEVEL);
1482	}
1483
1484	/* need MCI cache to have persistence */
1485	if (HostStatDir != NULL && MaxMciCache == 0)
1486	{
1487		HostStatDir = NULL;
1488		(void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
1489				     "Warning: HostStatusDirectory disabled with ConnectionCacheSize = 0\n");
1490	}
1491
1492	/* need HostStatusDir in order to have SingleThreadDelivery */
1493	if (SingleThreadDelivery && HostStatDir == NULL)
1494	{
1495		SingleThreadDelivery = false;
1496		(void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
1497				     "Warning: HostStatusDirectory required for SingleThreadDelivery\n");
1498	}
1499
1500#if _FFR_MEMSTAT
1501	j = sm_memstat_open();
1502	if (j < 0 && (RefuseLowMem > 0 || QueueLowMem > 0) && LogLevel > 4)
1503	{
1504		sm_syslog(LOG_WARNING, NOQID,
1505			  "cannot get memory statistics, settings ignored, error=%d"
1506			  , j);
1507	}
1508#endif /* _FFR_MEMSTAT */
1509
1510	/* check for permissions */
1511	if (RealUid != 0 &&
1512	    RealUid != TrustedUid)
1513	{
1514		char *action = NULL;
1515
1516		switch (OpMode)
1517		{
1518		  case MD_QUEUERUN:
1519			if (quarantining != NULL)
1520				action = "quarantine jobs";
1521			else
1522			{
1523				/* Normal users can do a single queue run */
1524				if (QueueIntvl == 0)
1525					break;
1526			}
1527
1528			/* but not persistent queue runners */
1529			if (action == NULL)
1530				action = "start a queue runner daemon";
1531			/* FALLTHROUGH */
1532
1533		  case MD_PURGESTAT:
1534			if (action == NULL)
1535				action = "purge host status";
1536			/* FALLTHROUGH */
1537
1538		  case MD_DAEMON:
1539		  case MD_FGDAEMON:
1540			if (action == NULL)
1541				action = "run daemon";
1542
1543			if (tTd(65, 1))
1544				sm_dprintf("Deny user %d attempt to %s\n",
1545					   (int) RealUid, action);
1546
1547			if (LogLevel > 1)
1548				sm_syslog(LOG_ALERT, NOQID,
1549					  "user %d attempted to %s",
1550					  (int) RealUid, action);
1551			HoldErrs = false;
1552			usrerr("Permission denied (real uid not trusted)");
1553			finis(false, true, EX_USAGE);
1554			/* NOTREACHED */
1555			break;
1556
1557		  case MD_VERIFY:
1558			if (bitset(PRIV_RESTRICTEXPAND, PrivacyFlags))
1559			{
1560				/*
1561				**  If -bv and RestrictExpand,
1562				**  drop privs to prevent normal
1563				**  users from reading private
1564				**  aliases/forwards/:include:s
1565				*/
1566
1567				if (tTd(65, 1))
1568					sm_dprintf("Drop privs for user %d attempt to expand (RestrictExpand)\n",
1569						   (int) RealUid);
1570
1571				dp = drop_privileges(true);
1572
1573				/* Fake address safety */
1574				if (tTd(65, 1))
1575					sm_dprintf("Faking DontBlameSendmail=NonRootSafeAddr\n");
1576				setbitn(DBS_NONROOTSAFEADDR, DontBlameSendmail);
1577
1578				if (dp != EX_OK)
1579				{
1580					if (tTd(65, 1))
1581						sm_dprintf("Failed to drop privs for user %d attempt to expand, exiting\n",
1582							   (int) RealUid);
1583					CurEnv->e_id = NULL;
1584					finis(true, true, dp);
1585					/* NOTREACHED */
1586				}
1587			}
1588			break;
1589
1590		  case MD_TEST:
1591		  case MD_CHECKCONFIG:
1592		  case MD_PRINT:
1593		  case MD_PRINTNQE:
1594		  case MD_FREEZE:
1595		  case MD_HOSTSTAT:
1596			/* Nothing special to check */
1597			break;
1598
1599		  case MD_INITALIAS:
1600			if (!wordinclass(RealUserName, 't'))
1601			{
1602				if (tTd(65, 1))
1603					sm_dprintf("Deny user %d attempt to rebuild the alias map\n",
1604						   (int) RealUid);
1605				if (LogLevel > 1)
1606					sm_syslog(LOG_ALERT, NOQID,
1607						  "user %d attempted to rebuild the alias map",
1608						  (int) RealUid);
1609				HoldErrs = false;
1610				usrerr("Permission denied (real uid not trusted)");
1611				finis(false, true, EX_USAGE);
1612				/* NOTREACHED */
1613			}
1614			if (UseMSP)
1615			{
1616				HoldErrs = false;
1617				usrerr("User %d cannot rebuild aliases in mail submission program",
1618				       (int) RealUid);
1619				finis(false, true, EX_USAGE);
1620				/* NOTREACHED */
1621			}
1622			/* FALLTHROUGH */
1623
1624		  default:
1625			if (bitset(PRIV_RESTRICTEXPAND, PrivacyFlags) &&
1626			    Verbose != 0)
1627			{
1628				/*
1629				**  If -v and RestrictExpand, reset
1630				**  Verbose to prevent normal users
1631				**  from seeing the expansion of
1632				**  aliases/forwards/:include:s
1633				*/
1634
1635				if (tTd(65, 1))
1636					sm_dprintf("Dropping verbosity for user %d (RestrictExpand)\n",
1637						   (int) RealUid);
1638				Verbose = 0;
1639			}
1640			break;
1641		}
1642	}
1643
1644	if (MeToo)
1645		BlankEnvelope.e_flags |= EF_METOO;
1646
1647	switch (OpMode)
1648	{
1649	  case MD_TEST:
1650		/* don't have persistent host status in test mode */
1651		HostStatDir = NULL;
1652		/* FALLTHROUGH */
1653
1654	  case MD_CHECKCONFIG:
1655		if (Verbose == 0)
1656			Verbose = 2;
1657		BlankEnvelope.e_errormode = EM_PRINT;
1658		HoldErrs = false;
1659		break;
1660
1661	  case MD_VERIFY:
1662		BlankEnvelope.e_errormode = EM_PRINT;
1663		HoldErrs = false;
1664		/* arrange to exit cleanly on hangup signal */
1665		if (sm_signal(SIGHUP, SIG_IGN) == (sigfunc_t) SIG_DFL)
1666			(void) sm_signal(SIGHUP, intsig);
1667		if (geteuid() != 0)
1668			(void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
1669					     "Notice: -bv may give misleading output for non-privileged user\n");
1670		break;
1671
1672	  case MD_FGDAEMON:
1673		run_in_foreground = true;
1674		set_op_mode(MD_DAEMON);
1675		/* FALLTHROUGH */
1676
1677	  case MD_DAEMON:
1678		vendor_daemon_setup(&BlankEnvelope);
1679
1680		/* remove things that don't make sense in daemon mode */
1681		FullName = NULL;
1682		GrabTo = false;
1683
1684		/* arrange to restart on hangup signal */
1685		if (SaveArgv[0] == NULL || SaveArgv[0][0] != '/')
1686			sm_syslog(LOG_WARNING, NOQID,
1687				  "daemon invoked without full pathname; kill -1 won't work");
1688		break;
1689
1690	  case MD_INITALIAS:
1691		Verbose = 2;
1692		BlankEnvelope.e_errormode = EM_PRINT;
1693		HoldErrs = false;
1694		/* FALLTHROUGH */
1695
1696	  default:
1697		/* arrange to exit cleanly on hangup signal */
1698		if (sm_signal(SIGHUP, SIG_IGN) == (sigfunc_t) SIG_DFL)
1699			(void) sm_signal(SIGHUP, intsig);
1700		break;
1701	}
1702
1703	/* special considerations for FullName */
1704	if (FullName != NULL)
1705	{
1706		char *full = NULL;
1707
1708		/* full names can't have newlines */
1709		if (strchr(FullName, '\n') != NULL)
1710		{
1711			full = newstr(denlstring(FullName, true, true));
1712			FullName = full;
1713		}
1714
1715		/* check for characters that may have to be quoted */
1716		if (!rfc822_string(FullName))
1717		{
1718			/*
1719			**  Quote a full name with special characters
1720			**  as a comment so crackaddr() doesn't destroy
1721			**  the name portion of the address.
1722			*/
1723
1724			FullName = addquotes(FullName, NULL);
1725			if (full != NULL)
1726				sm_free(full);  /* XXX */
1727		}
1728	}
1729
1730	/* do heuristic mode adjustment */
1731	if (Verbose)
1732	{
1733		/* turn off noconnect option */
1734		setoption('c', "F", true, false, &BlankEnvelope);
1735
1736		/* turn on interactive delivery */
1737		setoption('d', "", true, false, &BlankEnvelope);
1738	}
1739
1740#ifdef VENDOR_CODE
1741	/* check for vendor mismatch */
1742	if (VendorCode != VENDOR_CODE)
1743	{
1744		message("Warning: .cf file vendor code mismatch: sendmail expects vendor %s, .cf file vendor is %s",
1745			getvendor(VENDOR_CODE), getvendor(VendorCode));
1746	}
1747#endif /* VENDOR_CODE */
1748
1749	/* check for out of date configuration level */
1750	if (ConfigLevel < MAXCONFIGLEVEL)
1751	{
1752		message("Warning: .cf file is out of date: sendmail %s supports version %d, .cf file is version %d",
1753			Version, MAXCONFIGLEVEL, ConfigLevel);
1754	}
1755
1756	if (ConfigLevel < 3)
1757		UseErrorsTo = true;
1758
1759	/* set options that were previous macros */
1760	if (SmtpGreeting == NULL)
1761	{
1762		if (ConfigLevel < 7 &&
1763		    (p = macvalue('e', &BlankEnvelope)) != NULL)
1764			SmtpGreeting = newstr(p);
1765		else
1766			SmtpGreeting = "\201j Sendmail \201v ready at \201b";
1767	}
1768	if (UnixFromLine == NULL)
1769	{
1770		if (ConfigLevel < 7 &&
1771		    (p = macvalue('l', &BlankEnvelope)) != NULL)
1772			UnixFromLine = newstr(p);
1773		else
1774			UnixFromLine = "From \201g  \201d";
1775	}
1776	SmtpError[0] = '\0';
1777
1778	/* our name for SMTP codes */
1779	expand("\201j", jbuf, sizeof(jbuf), &BlankEnvelope);
1780	if (jbuf[0] == '\0')
1781		PSTRSET(MyHostName, "localhost");
1782	else
1783		PSTRSET(MyHostName, jbuf);
1784	if (strchr(MyHostName, '.') == NULL)
1785		message("WARNING: local host name (%s) is not qualified; see cf/README: WHO AM I?",
1786			MyHostName);
1787
1788	/* make certain that this name is part of the $=w class */
1789	setclass('w', MyHostName);
1790
1791	/* fill in the structure of the *default* queue */
1792	st = stab("mqueue", ST_QUEUE, ST_FIND);
1793	if (st == NULL)
1794		syserr("No default queue (mqueue) defined");
1795	else
1796		set_def_queueval(st->s_quegrp, true);
1797
1798	/* the indices of built-in mailers */
1799	st = stab("local", ST_MAILER, ST_FIND);
1800	if (st != NULL)
1801		LocalMailer = st->s_mailer;
1802	else if (OpMode != MD_TEST || !warn_C_flag)
1803		syserr("No local mailer defined");
1804
1805	st = stab("prog", ST_MAILER, ST_FIND);
1806	if (st == NULL)
1807		syserr("No prog mailer defined");
1808	else
1809	{
1810		ProgMailer = st->s_mailer;
1811		clrbitn(M_MUSER, ProgMailer->m_flags);
1812	}
1813
1814	st = stab("*file*", ST_MAILER, ST_FIND);
1815	if (st == NULL)
1816		syserr("No *file* mailer defined");
1817	else
1818	{
1819		FileMailer = st->s_mailer;
1820		clrbitn(M_MUSER, FileMailer->m_flags);
1821	}
1822
1823	st = stab("*include*", ST_MAILER, ST_FIND);
1824	if (st == NULL)
1825		syserr("No *include* mailer defined");
1826	else
1827		InclMailer = st->s_mailer;
1828
1829	if (ConfigLevel < 6)
1830	{
1831		/* heuristic tweaking of local mailer for back compat */
1832		if (LocalMailer != NULL)
1833		{
1834			setbitn(M_ALIASABLE, LocalMailer->m_flags);
1835			setbitn(M_HASPWENT, LocalMailer->m_flags);
1836			setbitn(M_TRYRULESET5, LocalMailer->m_flags);
1837			setbitn(M_CHECKINCLUDE, LocalMailer->m_flags);
1838			setbitn(M_CHECKPROG, LocalMailer->m_flags);
1839			setbitn(M_CHECKFILE, LocalMailer->m_flags);
1840			setbitn(M_CHECKUDB, LocalMailer->m_flags);
1841		}
1842		if (ProgMailer != NULL)
1843			setbitn(M_RUNASRCPT, ProgMailer->m_flags);
1844		if (FileMailer != NULL)
1845			setbitn(M_RUNASRCPT, FileMailer->m_flags);
1846	}
1847	if (ConfigLevel < 7)
1848	{
1849		if (LocalMailer != NULL)
1850			setbitn(M_VRFY250, LocalMailer->m_flags);
1851		if (ProgMailer != NULL)
1852			setbitn(M_VRFY250, ProgMailer->m_flags);
1853		if (FileMailer != NULL)
1854			setbitn(M_VRFY250, FileMailer->m_flags);
1855	}
1856
1857	/* MIME Content-Types that cannot be transfer encoded */
1858	setclass('n', "multipart/signed");
1859
1860	/* MIME message/xxx subtypes that can be treated as messages */
1861	setclass('s', "rfc822");
1862#if _FFR_EAI
1863	setclass('s', "global");
1864#endif
1865
1866	/* MIME Content-Transfer-Encodings that can be encoded */
1867	setclass('e', "7bit");
1868	setclass('e', "8bit");
1869	setclass('e', "binary");
1870
1871#ifdef USE_B_CLASS
1872	/* MIME Content-Types that should be treated as binary */
1873	setclass('b', "image");
1874	setclass('b', "audio");
1875	setclass('b', "video");
1876	setclass('b', "application/octet-stream");
1877#endif /* USE_B_CLASS */
1878
1879	/* MIME headers which have fields to check for overflow */
1880	setclass(macid("{checkMIMEFieldHeaders}"), "content-disposition");
1881	setclass(macid("{checkMIMEFieldHeaders}"), "content-type");
1882
1883	/* MIME headers to check for length overflow */
1884	setclass(macid("{checkMIMETextHeaders}"), "content-description");
1885
1886	/* MIME headers to check for overflow and rebalance */
1887	setclass(macid("{checkMIMEHeaders}"), "content-disposition");
1888	setclass(macid("{checkMIMEHeaders}"), "content-id");
1889	setclass(macid("{checkMIMEHeaders}"), "content-transfer-encoding");
1890	setclass(macid("{checkMIMEHeaders}"), "content-type");
1891	setclass(macid("{checkMIMEHeaders}"), "mime-version");
1892
1893	/* Macros to save in the queue file -- don't remove any */
1894	setclass(macid("{persistentMacros}"), "r");
1895	setclass(macid("{persistentMacros}"), "s");
1896	setclass(macid("{persistentMacros}"), "_");
1897	setclass(macid("{persistentMacros}"), "{if_addr}");
1898	setclass(macid("{persistentMacros}"), "{daemon_flags}");
1899
1900	/* operate in queue directory */
1901	if (QueueDir == NULL || *QueueDir == '\0')
1902	{
1903		if (OpMode != MD_TEST)
1904		{
1905			syserr("QueueDirectory (Q) option must be set");
1906			ExitStat = EX_CONFIG;
1907		}
1908	}
1909	else
1910	{
1911		if (OpMode != MD_TEST)
1912			setup_queues(OpMode == MD_DAEMON);
1913	}
1914
1915	/* check host status directory for validity */
1916	if (HostStatDir != NULL && !path_is_dir(HostStatDir, false))
1917	{
1918		/* cannot use this value */
1919		(void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
1920				     "Warning: Cannot use HostStatusDirectory = %s: %s\n",
1921				     HostStatDir, sm_errstring(errno));
1922		HostStatDir = NULL;
1923	}
1924
1925	if (OpMode == MD_QUEUERUN &&
1926	    RealUid != 0 && bitset(PRIV_RESTRICTQRUN, PrivacyFlags))
1927	{
1928		struct stat stbuf;
1929
1930		/* check to see if we own the queue directory */
1931		if (stat(".", &stbuf) < 0)
1932			syserr("main: cannot stat %s", QueueDir);
1933		if (stbuf.st_uid != RealUid)
1934		{
1935			/* nope, really a botch */
1936			HoldErrs = false;
1937			usrerr("You do not have permission to process the queue");
1938			finis(false, true, EX_NOPERM);
1939			/* NOTREACHED */
1940		}
1941	}
1942
1943#if MILTER
1944	/* sanity checks on milter filters */
1945	if (OpMode == MD_DAEMON || OpMode == MD_SMTP)
1946	{
1947		milter_config(InputFilterList, InputFilters, MAXFILTERS);
1948		setup_daemon_milters();
1949	}
1950#endif /* MILTER */
1951
1952	/* Convert queuegroup string to qgrp number */
1953	if (queuegroup != NULL)
1954	{
1955		qgrp = name2qid(queuegroup);
1956		if (qgrp == NOQGRP)
1957		{
1958			HoldErrs = false;
1959			usrerr("Queue group %s unknown", queuegroup);
1960			finis(false, true, ExitStat);
1961			/* NOTREACHED */
1962		}
1963	}
1964
1965	/* if checking config or have had errors so far, exit now */
1966	if (OpMode == MD_CHECKCONFIG || (ExitStat != EX_OK && OpMode != MD_TEST))
1967	{
1968		finis(false, true, ExitStat);
1969		/* NOTREACHED */
1970	}
1971
1972#if SASL
1973	/* sendmail specific SASL initialization */
1974	sm_sasl_init();
1975#endif
1976
1977#if XDEBUG
1978	checkfd012("before main() initmaps");
1979#endif
1980
1981	/*
1982	**  Do operation-mode-dependent initialization.
1983	*/
1984
1985	switch (OpMode)
1986	{
1987	  case MD_PRINT:
1988		/* print the queue */
1989		HoldErrs = false;
1990		(void) dropenvelope(&BlankEnvelope, true, false);
1991		(void) sm_signal(SIGPIPE, sigpipe);
1992		if (qgrp != NOQGRP)
1993		{
1994			/* Selecting a particular queue group to run */
1995			for (j = 0; j < Queue[qgrp]->qg_numqueues; j++)
1996			{
1997				if (StopRequest)
1998					stop_sendmail();
1999				(void) print_single_queue(qgrp, j);
2000			}
2001			finis(false, true, EX_OK);
2002			/* NOTREACHED */
2003		}
2004		printqueue();
2005		finis(false, true, EX_OK);
2006		/* NOTREACHED */
2007		break;
2008
2009	  case MD_PRINTNQE:
2010		/* print number of entries in queue */
2011		(void) dropenvelope(&BlankEnvelope, true, false);
2012		(void) sm_signal(SIGPIPE, sigpipe);
2013		printnqe(smioout, NULL);
2014		finis(false, true, EX_OK);
2015		/* NOTREACHED */
2016		break;
2017
2018	  case MD_QUEUERUN:
2019		/* only handle quarantining here */
2020		if (quarantining == NULL)
2021			break;
2022
2023		if (QueueMode != QM_QUARANTINE &&
2024		    QueueMode != QM_NORMAL)
2025		{
2026			HoldErrs = false;
2027			usrerr("Can not use -Q with -q%c", QueueMode);
2028			ExitStat = EX_USAGE;
2029			finis(false, true, ExitStat);
2030			/* NOTREACHED */
2031		}
2032		quarantine_queue(quarantining, qgrp);
2033		finis(false, true, EX_OK);
2034		break;
2035
2036	  case MD_HOSTSTAT:
2037		(void) sm_signal(SIGPIPE, sigpipe);
2038		(void) mci_traverse_persistent(mci_print_persistent, NULL);
2039		finis(false, true, EX_OK);
2040		/* NOTREACHED */
2041		break;
2042
2043	  case MD_PURGESTAT:
2044		(void) mci_traverse_persistent(mci_purge_persistent, NULL);
2045		finis(false, true, EX_OK);
2046		/* NOTREACHED */
2047		break;
2048
2049	  case MD_INITALIAS:
2050		/* initialize maps */
2051		initmaps();
2052		finis(false, true, ExitStat);
2053		/* NOTREACHED */
2054		break;
2055
2056	  case MD_SMTP:
2057	  case MD_DAEMON:
2058		/* reset DSN parameters */
2059		DefaultNotify = QPINGONFAILURE|QPINGONDELAY;
2060		macdefine(&BlankEnvelope.e_macro, A_PERM,
2061			  macid("{dsn_notify}"), NULL);
2062		BlankEnvelope.e_envid = NULL;
2063		macdefine(&BlankEnvelope.e_macro, A_PERM,
2064			  macid("{dsn_envid}"), NULL);
2065		BlankEnvelope.e_flags &= ~(EF_RET_PARAM|EF_NO_BODY_RETN);
2066		macdefine(&BlankEnvelope.e_macro, A_PERM,
2067			  macid("{dsn_ret}"), NULL);
2068
2069		/* don't open maps for daemon -- done below in child */
2070		break;
2071	}
2072
2073	if (tTd(0, 15))
2074	{
2075		/* print configuration table (or at least part of it) */
2076		if (tTd(0, 90))
2077			printrules();
2078		for (i = 0; i < MAXMAILERS; i++)
2079		{
2080			if (Mailer[i] != NULL)
2081				printmailer(sm_debug_file(), Mailer[i]);
2082		}
2083	}
2084
2085	/*
2086	**  Switch to the main envelope.
2087	*/
2088
2089	CurEnv = newenvelope(&MainEnvelope, &BlankEnvelope,
2090			     sm_rpool_new_x(NULL));
2091	MainEnvelope.e_flags = BlankEnvelope.e_flags;
2092
2093	/*
2094	**  If test mode, read addresses from stdin and process.
2095	*/
2096
2097	if (OpMode == MD_TEST)
2098	{
2099		if (isatty(sm_io_getinfo(smioin, SM_IO_WHAT_FD, NULL)))
2100			Verbose = 2;
2101
2102		if (Verbose)
2103		{
2104			(void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
2105				     "ADDRESS TEST MODE (ruleset 3 NOT automatically invoked)\n");
2106			(void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
2107				     "Enter <ruleset> <address>\n");
2108		}
2109		macdefine(&(MainEnvelope.e_macro), A_PERM,
2110			  macid("{addr_type}"), "e r");
2111		for (;;)
2112		{
2113			SM_TRY
2114			{
2115				(void) sm_signal(SIGINT, intindebug);
2116				(void) sm_releasesignal(SIGINT);
2117				if (Verbose == 2)
2118					(void) sm_io_fprintf(smioout,
2119							     SM_TIME_DEFAULT,
2120							     "> ");
2121				(void) sm_io_flush(smioout, SM_TIME_DEFAULT);
2122				if (sm_io_fgets(smioin, SM_TIME_DEFAULT, buf,
2123						sizeof(buf)) < 0)
2124					testmodeline("/quit", &MainEnvelope);
2125				p = strchr(buf, '\n');
2126				if (p != NULL)
2127					*p = '\0';
2128				if (Verbose < 2)
2129					(void) sm_io_fprintf(smioout,
2130							     SM_TIME_DEFAULT,
2131							     "> %s\n", buf);
2132				testmodeline(buf, &MainEnvelope);
2133			}
2134			SM_EXCEPT(exc, "[!F]*")
2135			{
2136				/*
2137				**  8.10 just prints \n on interrupt.
2138				**  I'm printing the exception here in case
2139				**  sendmail is extended to raise additional
2140				**  exceptions in this context.
2141				*/
2142
2143				(void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
2144						     "\n");
2145				sm_exc_print(exc, smioout);
2146			}
2147			SM_END_TRY
2148		}
2149	}
2150
2151#if STARTTLS
2152	tls_ok = true;
2153	if (OpMode == MD_QUEUERUN || OpMode == MD_DELIVER ||
2154	    OpMode == MD_ARPAFTP)
2155	{
2156		/* check whether STARTTLS is turned off for the client */
2157		if (chkclientmodifiers(D_NOTLS))
2158			tls_ok = false;
2159	}
2160	else if (OpMode == MD_DAEMON || OpMode == MD_FGDAEMON ||
2161		 OpMode == MD_SMTP)
2162	{
2163		/* check whether STARTTLS is turned off */
2164		if (chkdaemonmodifiers(D_NOTLS) && chkclientmodifiers(D_NOTLS))
2165			tls_ok = false;
2166	}
2167	else	/* other modes don't need STARTTLS */
2168		tls_ok = false;
2169
2170	if (tls_ok)
2171	{
2172		/* basic TLS initialization */
2173		j = init_tls_library(FipsMode);
2174		if (j < 0)
2175		{
2176			(void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
2177				     "ERROR: TLS failed to initialize\n");
2178			exit(EX_USAGE);
2179		}
2180		if (j > 0)
2181			tls_ok = false;
2182	}
2183
2184	if (!tls_ok && (OpMode == MD_QUEUERUN || OpMode == MD_DELIVER))
2185	{
2186		/* disable TLS for client */
2187		setclttls(false);
2188	}
2189#endif /* STARTTLS */
2190
2191	/*
2192	**  If collecting stuff from the queue, go start doing that.
2193	*/
2194
2195	if (OpMode == MD_QUEUERUN && QueueIntvl == 0)
2196	{
2197		pid_t pid = -1;
2198
2199#if STARTTLS
2200		/* init TLS for client, ignore result for now */
2201		(void) initclttls(tls_ok);
2202#endif
2203
2204		/*
2205		**  The parent process of the caller of runqueue() needs
2206		**  to stay around for a possible SIGTERM. The SIGTERM will
2207		**  tell this process that all of the queue runners children
2208		**  need to be sent SIGTERM as well. At the same time, we
2209		**  want to return control to the command line. So we do an
2210		**  extra fork().
2211		*/
2212
2213		if (Verbose || foregroundqueue || (pid = fork()) <= 0)
2214		{
2215			/*
2216			**  If the fork() failed we should still try to do
2217			**  the queue run. If it succeeded then the child
2218			**  is going to start the run and wait for all
2219			**  of the children to finish.
2220			*/
2221
2222			if (pid == 0)
2223			{
2224				/* Reset global flags */
2225				RestartRequest = NULL;
2226				ShutdownRequest = NULL;
2227				PendingSignal = 0;
2228
2229				/* disconnect from terminal */
2230				disconnect(2, CurEnv);
2231			}
2232
2233			CurrentPid = getpid();
2234			if (qgrp != NOQGRP)
2235			{
2236				int rwgflags = RWG_NONE;
2237
2238				/*
2239				**  To run a specific queue group mark it to
2240				**  be run, select the work group it's in and
2241				**  increment the work counter.
2242				*/
2243
2244				for (i = 0; i < NumQueue && Queue[i] != NULL;
2245				     i++)
2246					Queue[i]->qg_nextrun = (time_t) -1;
2247				Queue[qgrp]->qg_nextrun = 0;
2248				if (Verbose)
2249					rwgflags |= RWG_VERBOSE;
2250				if (queuepersistent)
2251					rwgflags |= RWG_PERSISTENT;
2252				rwgflags |= RWG_FORCE;
2253				(void) run_work_group(Queue[qgrp]->qg_wgrp,
2254						      rwgflags);
2255			}
2256			else
2257				(void) runqueue(false, Verbose,
2258						queuepersistent, true);
2259
2260			/* set the title to make it easier to find */
2261			sm_setproctitle(true, CurEnv, "Queue control");
2262			(void) sm_signal(SIGCHLD, SIG_DFL);
2263			while (CurChildren > 0)
2264			{
2265				int status;
2266				pid_t ret;
2267
2268				errno = 0;
2269				while ((ret = sm_wait(&status)) <= 0)
2270				{
2271					if (errno == ECHILD)
2272					{
2273						/*
2274						**  Oops... something got messed
2275						**  up really bad. Waiting for
2276						**  non-existent children
2277						**  shouldn't happen. Let's get
2278						**  out of here.
2279						*/
2280
2281						CurChildren = 0;
2282						break;
2283					}
2284					continue;
2285				}
2286
2287				/* something is really really wrong */
2288				if (errno == ECHILD)
2289				{
2290					sm_syslog(LOG_ERR, NOQID,
2291						  "queue control process: lost all children: wait returned ECHILD");
2292					break;
2293				}
2294
2295				/* Only drop when a child gives status */
2296				if (WIFSTOPPED(status))
2297					continue;
2298
2299				proc_list_drop(ret, status, NULL);
2300			}
2301		}
2302		finis(true, true, ExitStat);
2303		/* NOTREACHED */
2304	}
2305
2306#if SASL
2307	if (OpMode == MD_SMTP || OpMode == MD_DAEMON)
2308	{
2309		/* check whether AUTH is turned off for the server */
2310		if (!chkdaemonmodifiers(D_NOAUTH) &&
2311		    (i = sasl_server_init(srvcallbacks, "Sendmail")) != SASL_OK)
2312			syserr("!sasl_server_init failed! [%s]",
2313				sasl_errstring(i, NULL, NULL));
2314	}
2315#endif /* SASL */
2316
2317	if (OpMode == MD_SMTP)
2318	{
2319		proc_list_add(CurrentPid, "Sendmail SMTP Agent",
2320			      PROC_DAEMON, 0, -1, NULL);
2321
2322		/* clean up background delivery children */
2323		(void) sm_signal(SIGCHLD, reapchild);
2324	}
2325
2326	/*
2327	**  If a daemon, wait for a request.
2328	**	getrequests will always return in a child.
2329	**	If we should also be processing the queue, start
2330	**		doing it in background.
2331	**	We check for any errors that might have happened
2332	**		during startup.
2333	*/
2334
2335	if (OpMode == MD_DAEMON || QueueIntvl > 0)
2336	{
2337		char dtype[200];
2338
2339		/* avoid cleanup in finis(), DaemonPid will be set below */
2340		DaemonPid = 0;
2341		if (!run_in_foreground && !tTd(99, 100))
2342		{
2343			/* put us in background */
2344			i = fork();
2345			if (i < 0)
2346				syserr("daemon: cannot fork");
2347			if (i != 0)
2348			{
2349				finis(false, true, EX_OK);
2350				/* NOTREACHED */
2351			}
2352
2353			/*
2354			**  Initialize exception stack and default exception
2355			**  handler for child process.
2356			*/
2357
2358			/* Reset global flags */
2359			RestartRequest = NULL;
2360			RestartWorkGroup = false;
2361			ShutdownRequest = NULL;
2362			PendingSignal = 0;
2363			CurrentPid = getpid();
2364
2365			sm_exc_newthread(fatal_error);
2366
2367			/* disconnect from our controlling tty */
2368			disconnect(2, &MainEnvelope);
2369		}
2370
2371		dtype[0] = '\0';
2372		if (OpMode == MD_DAEMON)
2373		{
2374			(void) sm_strlcat(dtype, "+SMTP", sizeof(dtype));
2375			DaemonPid = CurrentPid;
2376		}
2377		if (QueueIntvl > 0)
2378		{
2379			(void) sm_strlcat2(dtype,
2380					   queuepersistent
2381					   ? "+persistent-queueing@"
2382					   : "+queueing@",
2383					   pintvl(QueueIntvl, true),
2384					   sizeof(dtype));
2385		}
2386		if (tTd(0, 1))
2387			(void) sm_strlcat(dtype, "+debugging", sizeof(dtype));
2388
2389		sm_syslog(LOG_INFO, NOQID,
2390			  "starting daemon (%s): %s", Version, dtype + 1);
2391#if XLA
2392		xla_create_file();
2393#endif
2394
2395		/* save daemon type in a macro for possible PidFile use */
2396		macdefine(&BlankEnvelope.e_macro, A_TEMP,
2397			macid("{daemon_info}"), dtype + 1);
2398
2399		/* save queue interval in a macro for possible PidFile use */
2400		macdefine(&MainEnvelope.e_macro, A_TEMP,
2401			macid("{queue_interval}"), pintvl(QueueIntvl, true));
2402
2403		/* workaround: can't seem to release the signal in the parent */
2404		(void) sm_signal(SIGHUP, sighup);
2405		(void) sm_releasesignal(SIGHUP);
2406		(void) sm_signal(SIGTERM, sigterm);
2407
2408		if (QueueIntvl > 0)
2409		{
2410#if _FFR_RUNPQG
2411			if (qgrp != NOQGRP)
2412			{
2413				int rwgflags = RWG_NONE;
2414
2415				/*
2416				**  To run a specific queue group mark it to
2417				**  be run, select the work group it's in and
2418				**  increment the work counter.
2419				*/
2420
2421				for (i = 0; i < NumQueue && Queue[i] != NULL;
2422				     i++)
2423					Queue[i]->qg_nextrun = (time_t) -1;
2424				Queue[qgrp]->qg_nextrun = 0;
2425				if (Verbose)
2426					rwgflags |= RWG_VERBOSE;
2427				if (queuepersistent)
2428					rwgflags |= RWG_PERSISTENT;
2429				rwgflags |= RWG_FORCE;
2430				(void) run_work_group(Queue[qgrp]->qg_wgrp,
2431						      rwgflags);
2432			}
2433			else
2434#endif /* _FFR_RUNPQG */
2435				(void) runqueue(true, false, queuepersistent,
2436						true);
2437
2438			/*
2439			**  If queuepersistent but not in daemon mode then
2440			**  we're going to do the queue runner monitoring here.
2441			**  If in daemon mode then the monitoring will happen
2442			**  elsewhere.
2443			*/
2444
2445			if (OpMode != MD_DAEMON && queuepersistent)
2446			{
2447				/*
2448				**  Write the pid to file
2449				**  XXX Overwrites sendmail.pid
2450				*/
2451
2452				log_sendmail_pid(&MainEnvelope);
2453
2454				/* set the title to make it easier to find */
2455				sm_setproctitle(true, CurEnv, "Queue control");
2456				(void) sm_signal(SIGCHLD, SIG_DFL);
2457				while (CurChildren > 0)
2458				{
2459					int status;
2460					pid_t ret;
2461					int group;
2462
2463					CHECK_RESTART;
2464					errno = 0;
2465					while ((ret = sm_wait(&status)) <= 0)
2466					{
2467						/*
2468						**  Waiting for non-existent
2469						**  children shouldn't happen.
2470						**  Let's get out of here if
2471						**  it occurs.
2472						*/
2473
2474						if (errno == ECHILD)
2475						{
2476							CurChildren = 0;
2477							break;
2478						}
2479						continue;
2480					}
2481
2482					/* something is really really wrong */
2483					if (errno == ECHILD)
2484					{
2485						sm_syslog(LOG_ERR, NOQID,
2486							  "persistent queue runner control process: lost all children: wait returned ECHILD");
2487						break;
2488					}
2489
2490					if (WIFSTOPPED(status))
2491						continue;
2492
2493					/* Probe only on a child status */
2494					proc_list_drop(ret, status, &group);
2495
2496					if (WIFSIGNALED(status))
2497					{
2498						if (WCOREDUMP(status))
2499						{
2500							sm_syslog(LOG_ERR, NOQID,
2501								  "persistent queue runner=%d core dumped, signal=%d",
2502								  group, WTERMSIG(status));
2503
2504							/* don't restart this */
2505							mark_work_group_restart(
2506								group, -1);
2507							continue;
2508						}
2509
2510						sm_syslog(LOG_ERR, NOQID,
2511							  "persistent queue runner=%d died, pid=%ld, signal=%d",
2512							  group, (long) ret,
2513							  WTERMSIG(status));
2514					}
2515
2516					/*
2517					**  When debugging active, don't
2518					**  restart the persistent queues.
2519					**  But do log this as info.
2520					*/
2521
2522					if (sm_debug_active(&DebugNoPRestart,
2523							    1))
2524					{
2525						sm_syslog(LOG_DEBUG, NOQID,
2526							  "persistent queue runner=%d, exited",
2527							  group);
2528						mark_work_group_restart(group,
2529									-1);
2530					}
2531					CHECK_RESTART;
2532				}
2533				finis(true, true, ExitStat);
2534				/* NOTREACHED */
2535			}
2536
2537			if (OpMode != MD_DAEMON)
2538			{
2539				char qtype[200];
2540
2541				/*
2542				**  Write the pid to file
2543				**  XXX Overwrites sendmail.pid
2544				*/
2545
2546				log_sendmail_pid(&MainEnvelope);
2547
2548				/* set the title to make it easier to find */
2549				qtype[0] = '\0';
2550				(void) sm_strlcpyn(qtype, sizeof(qtype), 4,
2551						   "Queue runner@",
2552						   pintvl(QueueIntvl, true),
2553						   " for ",
2554						   QueueDir);
2555				sm_setproctitle(true, CurEnv, qtype);
2556				for (;;)
2557				{
2558					(void) pause();
2559
2560					CHECK_RESTART;
2561
2562					if (doqueuerun())
2563						(void) runqueue(true, false,
2564								false, false);
2565				}
2566			}
2567		}
2568		(void) dropenvelope(&MainEnvelope, true, false);
2569
2570#if STARTTLS
2571		/* init TLS for server, ignore result for now */
2572		(void) initsrvtls(tls_ok);
2573#endif
2574
2575	nextreq:
2576		p_flags = getrequests(&MainEnvelope);
2577
2578		/* drop privileges */
2579		(void) drop_privileges(false);
2580
2581		/*
2582		**  Get authentication data
2583		**  Set _ macro in BlankEnvelope before calling newenvelope().
2584		*/
2585
2586#if _FFR_XCNCT
2587		if (bitnset(D_XCNCT, *p_flags) || bitnset(D_XCNCT_M, *p_flags))
2588		{
2589			/* copied from getauthinfo() */
2590			if (RealHostName == NULL)
2591			{
2592				RealHostName = newstr(hostnamebyanyaddr(&RealHostAddr));
2593				if (strlen(RealHostName) > MAXNAME)
2594					RealHostName[MAXNAME] = '\0'; /* XXX - 1 ? */
2595			}
2596			snprintf(buf, sizeof(buf), "%s [%s]",
2597				RealHostName, anynet_ntoa(&RealHostAddr));
2598
2599			forged = bitnset(D_XCNCT_M, *p_flags);
2600			if (forged)
2601			{
2602				(void) sm_strlcat(buf, " (may be forged)",
2603						sizeof(buf));
2604				macdefine(&BlankEnvelope.e_macro, A_PERM,
2605					  macid("{client_resolve}"), "FORGED");
2606			}
2607
2608			/* HACK! variable used only two times right below */
2609			authinfo = buf;
2610			if (tTd(75, 9))
2611				sm_syslog(LOG_INFO, NOQID,
2612					"main: where=not_calling_getauthinfo, RealHostAddr=%s",
2613					anynet_ntoa(&RealHostAddr));
2614		}
2615		else
2616		/* WARNING: "non-braced" else */
2617#endif /* _FFR_XCNCT */
2618		authinfo = getauthinfo(sm_io_getinfo(InChannel, SM_IO_WHAT_FD,
2619						     NULL), &forged);
2620		macdefine(&BlankEnvelope.e_macro, A_TEMP, '_', authinfo);
2621		if (tTd(75, 9))
2622			sm_syslog(LOG_INFO, NOQID,
2623				"main: where=after_getauthinfo, RealHostAddr=%s",
2624				anynet_ntoa(&RealHostAddr));
2625
2626		/* at this point we are in a child: reset state */
2627		sm_rpool_free(MainEnvelope.e_rpool);
2628		(void) newenvelope(&MainEnvelope, &MainEnvelope,
2629				   sm_rpool_new_x(NULL));
2630	}
2631
2632	if (LogLevel > 9)
2633	{
2634		p = authinfo;
2635		if (NULL == p)
2636		{
2637			if (NULL != RealHostName)
2638				p = RealHostName;
2639			else
2640				p = anynet_ntoa(&RealHostAddr);
2641			if (NULL == p)
2642				p = "unknown";
2643		}
2644
2645		/* log connection information */
2646		sm_syslog(LOG_INFO, NULL, "connect from %s", p);
2647	}
2648
2649	/*
2650	**  If running SMTP protocol, start collecting and executing
2651	**  commands.  This will never return.
2652	*/
2653
2654	if (OpMode == MD_SMTP || OpMode == MD_DAEMON)
2655	{
2656		char pbuf[20];
2657
2658		/*
2659		**  Save some macros for check_* rulesets.
2660		*/
2661
2662		if (forged)
2663		{
2664			char ipbuf[103];
2665
2666			(void) sm_snprintf(ipbuf, sizeof(ipbuf), "[%.100s]",
2667					   anynet_ntoa(&RealHostAddr));
2668			macdefine(&BlankEnvelope.e_macro, A_TEMP,
2669				  macid("{client_name}"), ipbuf);
2670		}
2671		else
2672			macdefine(&BlankEnvelope.e_macro, A_PERM,
2673				  macid("{client_name}"), RealHostName);
2674		macdefine(&BlankEnvelope.e_macro, A_PERM,
2675			  macid("{client_ptr}"), RealHostName);
2676		macdefine(&BlankEnvelope.e_macro, A_TEMP,
2677			  macid("{client_addr}"), anynet_ntoa(&RealHostAddr));
2678		sm_getla();
2679
2680		switch (RealHostAddr.sa.sa_family)
2681		{
2682#if NETINET
2683		  case AF_INET:
2684			(void) sm_snprintf(pbuf, sizeof(pbuf), "%d",
2685					   ntohs(RealHostAddr.sin.sin_port));
2686			break;
2687#endif /* NETINET */
2688#if NETINET6
2689		  case AF_INET6:
2690			(void) sm_snprintf(pbuf, sizeof(pbuf), "%d",
2691					   ntohs(RealHostAddr.sin6.sin6_port));
2692			break;
2693#endif /* NETINET6 */
2694		  default:
2695			(void) sm_snprintf(pbuf, sizeof(pbuf), "0");
2696			break;
2697		}
2698		macdefine(&BlankEnvelope.e_macro, A_TEMP,
2699			macid("{client_port}"), pbuf);
2700
2701		if (OpMode == MD_DAEMON)
2702		{
2703			ENVELOPE *saved_env;
2704
2705			/* validate the connection */
2706			HoldErrs = true;
2707			saved_env = CurEnv;
2708			CurEnv = &BlankEnvelope;
2709			nullserver = validate_connection(&RealHostAddr,
2710						macvalue(macid("{client_name}"),
2711							&BlankEnvelope),
2712						&BlankEnvelope);
2713			if (bitset(EF_DISCARD, BlankEnvelope.e_flags))
2714				MainEnvelope.e_flags |= EF_DISCARD;
2715			CurEnv = saved_env;
2716			HoldErrs = false;
2717		}
2718		else if (p_flags == NULL)
2719		{
2720			p_flags = (BITMAP256 *) xalloc(sizeof(*p_flags));
2721			clrbitmap(p_flags);
2722		}
2723#if STARTTLS
2724		if (OpMode == MD_SMTP)
2725			(void) initsrvtls(tls_ok);
2726#endif
2727
2728		/* turn off profiling */
2729		SM_PROF(1);
2730		smtp(nullserver, *p_flags, &MainEnvelope);
2731
2732		if (tTd(93, 100))
2733		{
2734			/* turn off profiling */
2735			SM_PROF(0);
2736			if (OpMode == MD_DAEMON)
2737				goto nextreq;
2738		}
2739	}
2740
2741	sm_rpool_free(MainEnvelope.e_rpool);
2742	clearenvelope(&MainEnvelope, false, sm_rpool_new_x(NULL));
2743	if (OpMode == MD_VERIFY)
2744	{
2745		set_delivery_mode(SM_VERIFY, &MainEnvelope);
2746		PostMasterCopy = NULL;
2747	}
2748	else
2749	{
2750		/* interactive -- all errors are global */
2751		MainEnvelope.e_flags |= EF_GLOBALERRS|EF_LOGSENDER;
2752	}
2753
2754	/*
2755	**  Do basic system initialization and set the sender
2756	*/
2757
2758	initsys(&MainEnvelope);
2759	macdefine(&MainEnvelope.e_macro, A_PERM, macid("{ntries}"), "0");
2760	macdefine(&MainEnvelope.e_macro, A_PERM, macid("{nrcpts}"), "0");
2761	setsender(from, &MainEnvelope, NULL, '\0', false);
2762	if (warn_f_flag != '\0' && !wordinclass(RealUserName, 't') &&
2763	    (!bitnset(M_LOCALMAILER, MainEnvelope.e_from.q_mailer->m_flags) ||
2764	     strcmp(MainEnvelope.e_from.q_user, RealUserName) != 0))
2765	{
2766		auth_warning(&MainEnvelope, "%s set sender to %s using -%c",
2767			     RealUserName, from, warn_f_flag);
2768#if SASL
2769		auth = false;
2770#endif
2771	}
2772	if (auth)
2773	{
2774		char *fv;
2775
2776		/* set the initial sender for AUTH= to $f@$j */
2777		fv = macvalue('f', &MainEnvelope);
2778		if (fv == NULL || *fv == '\0')
2779			MainEnvelope.e_auth_param = NULL;
2780		else
2781		{
2782			if (strchr(fv, '@') == NULL)
2783			{
2784				i = strlen(fv) + strlen(macvalue('j',
2785							&MainEnvelope)) + 2;
2786				p = sm_malloc_x(i);
2787				(void) sm_strlcpyn(p, i, 3, fv, "@",
2788						   macvalue('j',
2789							    &MainEnvelope));
2790			}
2791			else
2792				p = sm_strdup_x(fv);
2793			MainEnvelope.e_auth_param = sm_rpool_strdup_x(MainEnvelope.e_rpool,
2794								      xtextify(p, "="));
2795			sm_free(p);  /* XXX */
2796		}
2797	}
2798	if (macvalue('s', &MainEnvelope) == NULL)
2799		macdefine(&MainEnvelope.e_macro, A_PERM, 's', RealHostName);
2800
2801	av = argv + optind;
2802	if (*av == NULL && !GrabTo)
2803	{
2804		MainEnvelope.e_to = NULL;
2805		MainEnvelope.e_flags |= EF_GLOBALERRS;
2806		HoldErrs = false;
2807		SuperSafe = SAFE_NO;
2808		usrerr("Recipient names must be specified");
2809
2810		/* collect body for UUCP return */
2811		if (OpMode != MD_VERIFY)
2812			collect(InChannel, false, NULL, &MainEnvelope, true);
2813		finis(true, true, EX_USAGE);
2814		/* NOTREACHED */
2815	}
2816
2817	/*
2818	**  Scan argv and deliver the message to everyone.
2819	*/
2820
2821	save_val = LogUsrErrs;
2822	LogUsrErrs = true;
2823	sendtoargv(av, &MainEnvelope);
2824	LogUsrErrs = save_val;
2825
2826	/* if we have had errors sofar, arrange a meaningful exit stat */
2827	if (Errors > 0 && ExitStat == EX_OK)
2828		ExitStat = EX_USAGE;
2829
2830#if _FFR_FIX_DASHT
2831	/*
2832	**  If using -t, force not sending to argv recipients, even
2833	**  if they are mentioned in the headers.
2834	*/
2835
2836	if (GrabTo)
2837	{
2838		ADDRESS *q;
2839
2840		for (q = MainEnvelope.e_sendqueue; q != NULL; q = q->q_next)
2841			q->q_state = QS_REMOVED;
2842	}
2843#endif /* _FFR_FIX_DASHT */
2844
2845	/*
2846	**  Read the input mail.
2847	*/
2848
2849	MainEnvelope.e_to = NULL;
2850	if (OpMode != MD_VERIFY || GrabTo)
2851	{
2852		int savederrors;
2853		unsigned long savedflags;
2854
2855		/*
2856		**  workaround for compiler warning on Irix:
2857		**  do not initialize variable in the definition, but
2858		**  later on:
2859		**  warning(1548): transfer of control bypasses
2860		**  initialization of:
2861		**  variable "savederrors" (declared at line 2570)
2862		**  variable "savedflags" (declared at line 2571)
2863		**  goto giveup;
2864		*/
2865
2866		savederrors = Errors;
2867		savedflags = MainEnvelope.e_flags & EF_FATALERRS;
2868		MainEnvelope.e_flags |= EF_GLOBALERRS;
2869		MainEnvelope.e_flags &= ~EF_FATALERRS;
2870		Errors = 0;
2871		buffer_errors();
2872		collect(InChannel, false, NULL, &MainEnvelope, true);
2873
2874		/* header checks failed */
2875		if (Errors > 0)
2876		{
2877  giveup:
2878			if (!GrabTo)
2879			{
2880				/* Log who the mail would have gone to */
2881				logundelrcpts(&MainEnvelope,
2882					      MainEnvelope.e_message,
2883					      8, false);
2884			}
2885			flush_errors(true);
2886			finis(true, true, ExitStat);
2887			/* NOTREACHED */
2888			return -1;
2889		}
2890
2891		/* bail out if message too large */
2892		if (bitset(EF_CLRQUEUE, MainEnvelope.e_flags))
2893		{
2894			finis(true, true, ExitStat != EX_OK ? ExitStat
2895							    : EX_DATAERR);
2896			/* NOTREACHED */
2897			return -1;
2898		}
2899
2900		/* set message size */
2901		(void) sm_snprintf(buf, sizeof(buf), "%ld",
2902				   PRT_NONNEGL(MainEnvelope.e_msgsize));
2903		macdefine(&MainEnvelope.e_macro, A_TEMP,
2904			  macid("{msg_size}"), buf);
2905
2906		Errors = savederrors;
2907		MainEnvelope.e_flags |= savedflags;
2908	}
2909	errno = 0;
2910
2911	if (tTd(1, 1))
2912		sm_dprintf("From person = \"%s\"\n",
2913			   MainEnvelope.e_from.q_paddr);
2914
2915	/* Check if quarantining stats should be updated */
2916	if (MainEnvelope.e_quarmsg != NULL)
2917		markstats(&MainEnvelope, NULL, STATS_QUARANTINE);
2918
2919	/*
2920	**  Actually send everything.
2921	**	If verifying, just ack.
2922	*/
2923
2924	if (Errors == 0)
2925	{
2926		if (!split_by_recipient(&MainEnvelope) &&
2927		    bitset(EF_FATALERRS, MainEnvelope.e_flags))
2928			goto giveup;
2929	}
2930
2931	/* make sure we deliver at least the first envelope */
2932	i = FastSplit > 0 ? 0 : -1;
2933	for (e = &MainEnvelope; e != NULL; e = e->e_sibling, i++)
2934	{
2935		ENVELOPE *next;
2936
2937		e->e_from.q_state = QS_SENDER;
2938		if (tTd(1, 5))
2939		{
2940			sm_dprintf("main[%d]: QS_SENDER ", i);
2941			printaddr(sm_debug_file(), &e->e_from, false);
2942		}
2943		e->e_to = NULL;
2944		sm_getla();
2945		GrabTo = false;
2946#if NAMED_BIND
2947		_res.retry = TimeOuts.res_retry[RES_TO_FIRST];
2948		_res.retrans = TimeOuts.res_retrans[RES_TO_FIRST];
2949#endif
2950		next = e->e_sibling;
2951		e->e_sibling = NULL;
2952
2953		/* after FastSplit envelopes: queue up */
2954		sendall(e, i >= FastSplit ? SM_QUEUE : SM_DEFAULT);
2955		e->e_sibling = next;
2956	}
2957
2958	/*
2959	**  All done.
2960	**	Don't send return error message if in VERIFY mode.
2961	*/
2962
2963	finis(true, true, ExitStat);
2964	/* NOTREACHED */
2965	return ExitStat;
2966}
2967/*
2968**  STOP_SENDMAIL -- Stop the running program
2969**
2970**	Parameters:
2971**		none.
2972**
2973**	Returns:
2974**		none.
2975**
2976**	Side Effects:
2977**		exits.
2978*/
2979
2980void
2981stop_sendmail()
2982{
2983	/* reset uid for process accounting */
2984	endpwent();
2985	(void) setuid(RealUid);
2986	exit(EX_OK);
2987}
2988/*
2989**  FINIS -- Clean up and exit.
2990**
2991**	Parameters:
2992**		drop -- whether or not to drop CurEnv envelope
2993**		cleanup -- call exit() or _exit()?
2994**		exitstat -- exit status to use for exit() call
2995**
2996**	Returns:
2997**		never
2998**
2999**	Side Effects:
3000**		exits sendmail
3001*/
3002
3003void
3004finis(drop, cleanup, exitstat)
3005	bool drop;
3006	bool cleanup;
3007	volatile int exitstat;
3008{
3009	char pidpath[MAXPATHLEN];
3010	pid_t pid;
3011
3012	/* Still want to process new timeouts added below */
3013	sm_clear_events();
3014	(void) sm_releasesignal(SIGALRM);
3015
3016#if RATECTL_DEBUG || _FFR_OCC
3017	/* do this only in "main" process */
3018	if (DaemonPid == getpid())
3019	{
3020		SM_FILE_T *fp;
3021
3022		fp = sm_debug_file();
3023		if (fp != NULL)
3024			dump_ch(fp);
3025	}
3026#endif
3027	if (tTd(2, 1))
3028	{
3029		sm_dprintf("\n====finis: stat %d e_id=%s e_flags=",
3030			   exitstat,
3031			   CurEnv->e_id == NULL ? "NOQUEUE" : CurEnv->e_id);
3032		printenvflags(CurEnv);
3033	}
3034	if (tTd(2, 9))
3035		printopenfds(false);
3036
3037	SM_TRY
3038		/*
3039		**  Clean up.  This might raise E:mta.quickabort
3040		*/
3041
3042		/* clean up temp files */
3043		CurEnv->e_to = NULL;
3044		if (drop)
3045		{
3046			if (CurEnv->e_id != NULL)
3047			{
3048				int r;
3049
3050				r = dropenvelope(CurEnv, true, false);
3051				if (exitstat == EX_OK)
3052					exitstat = r;
3053				sm_rpool_free(CurEnv->e_rpool);
3054				CurEnv->e_rpool = NULL;
3055
3056				/* these may have pointed to the rpool */
3057				CurEnv->e_to = NULL;
3058				CurEnv->e_message = NULL;
3059				CurEnv->e_statmsg = NULL;
3060				CurEnv->e_quarmsg = NULL;
3061				CurEnv->e_bodytype = NULL;
3062				CurEnv->e_id = NULL;
3063				CurEnv->e_envid = NULL;
3064				CurEnv->e_auth_param = NULL;
3065			}
3066			else
3067				poststats(StatFile);
3068		}
3069
3070		/* flush any cached connections */
3071		mci_flush(true, NULL);
3072
3073		/* close maps belonging to this pid */
3074		closemaps(false);
3075
3076#if USERDB
3077		/* close UserDatabase */
3078		_udbx_close();
3079#endif
3080
3081#if SASL
3082		stop_sasl_client();
3083#endif
3084
3085#if XLA
3086		/* clean up extended load average stuff */
3087		xla_all_end();
3088#endif
3089
3090	SM_FINALLY
3091		/*
3092		**  And exit.
3093		*/
3094
3095		if (LogLevel > 78)
3096			sm_syslog(LOG_DEBUG, CurEnv->e_id, "finis, pid=%d",
3097				  (int) CurrentPid);
3098		if (exitstat == EX_TEMPFAIL ||
3099		    CurEnv->e_errormode == EM_BERKNET)
3100			exitstat = EX_OK;
3101
3102		/* XXX clean up queues and related data structures */
3103		cleanup_queues();
3104		pid = getpid();
3105#if SM_CONF_SHM
3106		cleanup_shm(DaemonPid == pid);
3107#endif
3108
3109		/* close locked pid file */
3110		close_sendmail_pid();
3111
3112		if (DaemonPid == pid || PidFilePid == pid)
3113		{
3114			/* blow away the pid file */
3115			expand(PidFile, pidpath, sizeof(pidpath), CurEnv);
3116			(void) unlink(pidpath);
3117		}
3118
3119		/* reset uid for process accounting */
3120		endpwent();
3121		sm_mbdb_terminate();
3122#if _FFR_MEMSTAT
3123		(void) sm_memstat_close();
3124#endif
3125		(void) setuid(RealUid);
3126#if SM_HEAP_CHECK
3127		/* dump the heap, if we are checking for memory leaks */
3128		if (sm_debug_active(&SmHeapCheck, 2))
3129			sm_heap_report(smioout,
3130				       sm_debug_level(&SmHeapCheck) - 1);
3131#endif
3132		if (sm_debug_active(&SmXtrapReport, 1))
3133			sm_dprintf("xtrap count = %d\n", SmXtrapCount);
3134		if (cleanup)
3135			exit(exitstat);
3136		else
3137			_exit(exitstat);
3138	SM_END_TRY
3139}
3140/*
3141**  INTINDEBUG -- signal handler for SIGINT in -bt mode
3142**
3143**	Parameters:
3144**		sig -- incoming signal.
3145**
3146**	Returns:
3147**		none.
3148**
3149**	Side Effects:
3150**		longjmps back to test mode loop.
3151**
3152**	NOTE:	THIS CAN BE CALLED FROM A SIGNAL HANDLER.  DO NOT ADD
3153**		ANYTHING TO THIS ROUTINE UNLESS YOU KNOW WHAT YOU ARE
3154**		DOING.
3155*/
3156
3157/* Type of an exception generated on SIGINT during address test mode.  */
3158static const SM_EXC_TYPE_T EtypeInterrupt =
3159{
3160	SmExcTypeMagic,
3161	"S:mta.interrupt",
3162	"",
3163	sm_etype_printf,
3164	"interrupt",
3165};
3166
3167/* ARGSUSED */
3168static SIGFUNC_DECL
3169intindebug(sig)
3170	int sig;
3171{
3172	int save_errno = errno;
3173
3174	FIX_SYSV_SIGNAL(sig, intindebug);
3175	errno = save_errno;
3176	CHECK_CRITICAL(sig);
3177	errno = save_errno;
3178	sm_exc_raisenew_x(&EtypeInterrupt);
3179	errno = save_errno;
3180	return SIGFUNC_RETURN;
3181}
3182/*
3183**  SIGTERM -- SIGTERM handler for the daemon
3184**
3185**	Parameters:
3186**		sig -- signal number.
3187**
3188**	Returns:
3189**		none.
3190**
3191**	Side Effects:
3192**		Sets ShutdownRequest which will hopefully trigger
3193**		the daemon to exit.
3194**
3195**	NOTE:	THIS CAN BE CALLED FROM A SIGNAL HANDLER.  DO NOT ADD
3196**		ANYTHING TO THIS ROUTINE UNLESS YOU KNOW WHAT YOU ARE
3197**		DOING.
3198*/
3199
3200/* ARGSUSED */
3201static SIGFUNC_DECL
3202sigterm(sig)
3203	int sig;
3204{
3205	int save_errno = errno;
3206
3207	FIX_SYSV_SIGNAL(sig, sigterm);
3208	ShutdownRequest = "signal";
3209	errno = save_errno;
3210	return SIGFUNC_RETURN;
3211}
3212/*
3213**  SIGHUP -- handle a SIGHUP signal
3214**
3215**	Parameters:
3216**		sig -- incoming signal.
3217**
3218**	Returns:
3219**		none.
3220**
3221**	Side Effects:
3222**		Sets RestartRequest which should cause the daemon
3223**		to restart.
3224**
3225**	NOTE:	THIS CAN BE CALLED FROM A SIGNAL HANDLER.  DO NOT ADD
3226**		ANYTHING TO THIS ROUTINE UNLESS YOU KNOW WHAT YOU ARE
3227**		DOING.
3228*/
3229
3230/* ARGSUSED */
3231static SIGFUNC_DECL
3232sighup(sig)
3233	int sig;
3234{
3235	int save_errno = errno;
3236
3237	FIX_SYSV_SIGNAL(sig, sighup);
3238	RestartRequest = "signal";
3239	errno = save_errno;
3240	return SIGFUNC_RETURN;
3241}
3242/*
3243**  SIGPIPE -- signal handler for SIGPIPE
3244**
3245**	Parameters:
3246**		sig -- incoming signal.
3247**
3248**	Returns:
3249**		none.
3250**
3251**	Side Effects:
3252**		Sets StopRequest which should cause the mailq/hoststatus
3253**		display to stop.
3254**
3255**	NOTE:	THIS CAN BE CALLED FROM A SIGNAL HANDLER.  DO NOT ADD
3256**		ANYTHING TO THIS ROUTINE UNLESS YOU KNOW WHAT YOU ARE
3257**		DOING.
3258*/
3259
3260/* ARGSUSED */
3261static SIGFUNC_DECL
3262sigpipe(sig)
3263	int sig;
3264{
3265	int save_errno = errno;
3266
3267	FIX_SYSV_SIGNAL(sig, sigpipe);
3268	StopRequest = true;
3269	errno = save_errno;
3270	return SIGFUNC_RETURN;
3271}
3272/*
3273**  INTSIG -- clean up on interrupt
3274**
3275**	This just arranges to exit.  It pessimizes in that it
3276**	may resend a message.
3277**
3278**	Parameters:
3279**		sig -- incoming signal.
3280**
3281**	Returns:
3282**		none.
3283**
3284**	Side Effects:
3285**		Unlocks the current job.
3286**
3287**	NOTE:	THIS CAN BE CALLED FROM A SIGNAL HANDLER.  DO NOT ADD
3288**		ANYTHING TO THIS ROUTINE UNLESS YOU KNOW WHAT YOU ARE
3289**		DOING.
3290*/
3291
3292/* ARGSUSED */
3293SIGFUNC_DECL
3294intsig(sig)
3295	int sig;
3296{
3297	bool drop = false;
3298	int save_errno = errno;
3299
3300	FIX_SYSV_SIGNAL(sig, intsig);
3301	errno = save_errno;
3302	CHECK_CRITICAL(sig);
3303	sm_allsignals(true);
3304	IntSig = true;
3305
3306	FileName = NULL;
3307
3308	/* Clean-up on aborted stdin message submission */
3309	if  (OpMode == MD_SMTP ||
3310	     OpMode == MD_DELIVER ||
3311	     OpMode == MD_ARPAFTP)
3312	{
3313		if (CurEnv->e_id != NULL)
3314		{
3315			char *fn;
3316
3317			fn = queuename(CurEnv, DATAFL_LETTER);
3318			if (fn != NULL)
3319				(void) unlink(fn);
3320			fn = queuename(CurEnv, ANYQFL_LETTER);
3321			if (fn != NULL)
3322				(void) unlink(fn);
3323		}
3324		_exit(EX_OK);
3325		/* NOTREACHED */
3326	}
3327
3328	if (sig != 0 && LogLevel > 79)
3329		sm_syslog(LOG_DEBUG, CurEnv->e_id, "interrupt");
3330	if (OpMode != MD_TEST)
3331		unlockqueue(CurEnv);
3332
3333	finis(drop, false, EX_OK);
3334	/* NOTREACHED */
3335}
3336/*
3337**  DISCONNECT -- remove our connection with any foreground process
3338**
3339**	Parameters:
3340**		droplev -- how "deeply" we should drop the line.
3341**			0 -- ignore signals, mail back errors, make sure
3342**			     output goes to stdout.
3343**			1 -- also, make stdout go to /dev/null.
3344**			2 -- also, disconnect from controlling terminal
3345**			     (only for daemon mode).
3346**		e -- the current envelope.
3347**
3348**	Returns:
3349**		none
3350**
3351**	Side Effects:
3352**		Trys to insure that we are immune to vagaries of
3353**		the controlling tty.
3354*/
3355
3356void
3357disconnect(droplev, e)
3358	int droplev;
3359	register ENVELOPE *e;
3360{
3361	int fd;
3362
3363	if (tTd(52, 1))
3364		sm_dprintf("disconnect: In %d Out %d, e=%p\n",
3365			   sm_io_getinfo(InChannel, SM_IO_WHAT_FD, NULL),
3366			   sm_io_getinfo(OutChannel, SM_IO_WHAT_FD, NULL),
3367			   (void *)e);
3368	if (tTd(52, 100))
3369	{
3370		sm_dprintf("don't\n");
3371		return;
3372	}
3373	if (LogLevel > 93)
3374		sm_syslog(LOG_DEBUG, e->e_id,
3375			  "disconnect level %d",
3376			  droplev);
3377
3378	/* be sure we don't get nasty signals */
3379	(void) sm_signal(SIGINT, SIG_IGN);
3380	(void) sm_signal(SIGQUIT, SIG_IGN);
3381
3382	/* we can't communicate with our caller, so.... */
3383	HoldErrs = true;
3384	CurEnv->e_errormode = EM_MAIL;
3385	Verbose = 0;
3386	DisConnected = true;
3387
3388	/* all input from /dev/null */
3389	if (InChannel != smioin)
3390	{
3391		(void) sm_io_close(InChannel, SM_TIME_DEFAULT);
3392		InChannel = smioin;
3393	}
3394	if (sm_io_reopen(SmFtStdio, SM_TIME_DEFAULT, SM_PATH_DEVNULL,
3395			 SM_IO_RDONLY, NULL, smioin) == NULL)
3396		sm_syslog(LOG_ERR, e->e_id,
3397			  "disconnect: sm_io_reopen(\"%s\") failed: %s",
3398			  SM_PATH_DEVNULL, sm_errstring(errno));
3399
3400	/*
3401	**  output to the transcript
3402	**	We also compare the fd numbers here since OutChannel
3403	**	might be a layer on top of smioout due to encryption
3404	**	(see sfsasl.c).
3405	*/
3406
3407	if (OutChannel != smioout &&
3408	    sm_io_getinfo(OutChannel, SM_IO_WHAT_FD, NULL) !=
3409	    sm_io_getinfo(smioout, SM_IO_WHAT_FD, NULL))
3410	{
3411		(void) sm_io_close(OutChannel, SM_TIME_DEFAULT);
3412		OutChannel = smioout;
3413
3414#if 0
3415		/*
3416		**  Has smioout been closed? Reopen it.
3417		**	This shouldn't happen anymore, the code is here
3418		**	just as a reminder.
3419		*/
3420
3421		if (smioout->sm_magic == NULL &&
3422		    sm_io_reopen(SmFtStdio, SM_TIME_DEFAULT, SM_PATH_DEVNULL,
3423				 SM_IO_WRONLY, NULL, smioout) == NULL)
3424			sm_syslog(LOG_ERR, e->e_id,
3425				  "disconnect: sm_io_reopen(\"%s\") failed: %s",
3426				  SM_PATH_DEVNULL, sm_errstring(errno));
3427#endif /* 0 */
3428	}
3429	if (droplev > 0)
3430	{
3431		fd = open(SM_PATH_DEVNULL, O_WRONLY, 0666);
3432		if (fd == -1)
3433		{
3434			sm_syslog(LOG_ERR, e->e_id,
3435				  "disconnect: open(\"%s\") failed: %s",
3436				  SM_PATH_DEVNULL, sm_errstring(errno));
3437		}
3438		(void) sm_io_flush(smioout, SM_TIME_DEFAULT);
3439		if (fd >= 0)
3440		{
3441			(void) dup2(fd, STDOUT_FILENO);
3442			(void) dup2(fd, STDERR_FILENO);
3443			(void) close(fd);
3444		}
3445	}
3446
3447	/* drop our controlling TTY completely if possible */
3448	if (droplev > 1)
3449	{
3450		(void) setsid();
3451		errno = 0;
3452	}
3453
3454#if XDEBUG
3455	checkfd012("disconnect");
3456#endif
3457
3458	if (LogLevel > 71)
3459		sm_syslog(LOG_DEBUG, e->e_id, "in background, pid=%d",
3460			  (int) CurrentPid);
3461
3462	errno = 0;
3463}
3464
3465static void
3466obsolete(argv)
3467	char *argv[];
3468{
3469	register char *ap;
3470	register char *op;
3471
3472	while ((ap = *++argv) != NULL)
3473	{
3474		/* Return if "--" or not an option of any form. */
3475		if (ap[0] != '-' || ap[1] == '-')
3476			return;
3477
3478		/* Don't allow users to use "-Q." or "-Q ." */
3479		if ((ap[1] == 'Q' && ap[2] == '.') ||
3480		    (ap[1] == 'Q' && argv[1] != NULL &&
3481		     argv[1][0] == '.' && argv[1][1] == '\0'))
3482		{
3483			(void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
3484					     "Can not use -Q.\n");
3485			exit(EX_USAGE);
3486		}
3487
3488		/* skip over options that do have a value */
3489		op = strchr(OPTIONS, ap[1]);
3490		if (op != NULL && *++op == ':' && ap[2] == '\0' &&
3491		    ap[1] != 'd' &&
3492#if defined(sony_news)
3493		    ap[1] != 'E' && ap[1] != 'J' &&
3494#endif
3495		    argv[1] != NULL && argv[1][0] != '-')
3496		{
3497			argv++;
3498			continue;
3499		}
3500
3501		/* If -C doesn't have an argument, use sendmail.cf. */
3502#define __DEFPATH	"sendmail.cf"
3503		if (ap[1] == 'C' && ap[2] == '\0')
3504		{
3505			*argv = xalloc(sizeof(__DEFPATH) + 2);
3506			(void) sm_strlcpyn(argv[0], sizeof(__DEFPATH) + 2, 2,
3507					   "-C", __DEFPATH);
3508		}
3509
3510		/* If -q doesn't have an argument, run it once. */
3511		if (ap[1] == 'q' && ap[2] == '\0')
3512			*argv = "-q0";
3513
3514		/* If -Q doesn't have an argument, disable quarantining */
3515		if (ap[1] == 'Q' && ap[2] == '\0')
3516			*argv = "-Q.";
3517
3518		/* if -d doesn't have an argument, use 0-99.1 */
3519		if (ap[1] == 'd' && ap[2] == '\0')
3520			*argv = "-d0-99.1";
3521
3522#if defined(sony_news)
3523		/* if -E doesn't have an argument, use -EC */
3524		if (ap[1] == 'E' && ap[2] == '\0')
3525			*argv = "-EC";
3526
3527		/* if -J doesn't have an argument, use -JJ */
3528		if (ap[1] == 'J' && ap[2] == '\0')
3529			*argv = "-JJ";
3530#endif /* defined(sony_news) */
3531	}
3532}
3533/*
3534**  AUTH_WARNING -- specify authorization warning
3535**
3536**	Parameters:
3537**		e -- the current envelope.
3538**		msg -- the text of the message.
3539**		args -- arguments to the message.
3540**
3541**	Returns:
3542**		none.
3543*/
3544
3545void
3546#ifdef __STDC__
3547auth_warning(register ENVELOPE *e, const char *msg, ...)
3548#else /* __STDC__ */
3549auth_warning(e, msg, va_alist)
3550	register ENVELOPE *e;
3551	const char *msg;
3552	va_dcl
3553#endif /* __STDC__ */
3554{
3555	char buf[MAXLINE];
3556	SM_VA_LOCAL_DECL
3557
3558	if (bitset(PRIV_AUTHWARNINGS, PrivacyFlags))
3559	{
3560		register char *p;
3561		static char hostbuf[48];
3562
3563		if (hostbuf[0] == '\0')
3564		{
3565			struct hostent *hp;
3566
3567			hp = myhostname(hostbuf, sizeof(hostbuf));
3568#if NETINET6
3569			if (hp != NULL)
3570			{
3571				freehostent(hp);
3572				hp = NULL;
3573			}
3574#endif /* NETINET6 */
3575		}
3576
3577		(void) sm_strlcpyn(buf, sizeof(buf), 2, hostbuf, ": ");
3578		p = &buf[strlen(buf)];
3579		SM_VA_START(ap, msg);
3580		(void) sm_vsnprintf(p, SPACELEFT(buf, p), msg, ap);
3581		SM_VA_END(ap);
3582		addheader("X-Authentication-Warning", buf, 0, e, true);
3583		if (LogLevel > 3)
3584			sm_syslog(LOG_INFO, e->e_id,
3585				  "Authentication-Warning: %.400s",
3586				  buf);
3587	}
3588}
3589/*
3590**  GETEXTENV -- get from external environment
3591**
3592**	Parameters:
3593**		envar -- the name of the variable to retrieve
3594**
3595**	Returns:
3596**		The value, if any.
3597*/
3598
3599static char *
3600getextenv(envar)
3601	const char *envar;
3602{
3603	char **envp;
3604	int l;
3605
3606	l = strlen(envar);
3607	for (envp = ExternalEnviron; envp != NULL && *envp != NULL; envp++)
3608	{
3609		if (strncmp(*envp, envar, l) == 0 && (*envp)[l] == '=')
3610			return &(*envp)[l + 1];
3611	}
3612	return NULL;
3613}
3614/*
3615**  SM_SETUSERENV -- set an environment variable in the propagated environment
3616**
3617**	Parameters:
3618**		envar -- the name of the environment variable.
3619**		value -- the value to which it should be set.  If
3620**			null, this is extracted from the incoming
3621**			environment.  If that is not set, the call
3622**			to sm_setuserenv is ignored.
3623**
3624**	Returns:
3625**		none.
3626*/
3627
3628void
3629sm_setuserenv(envar, value)
3630	const char *envar;
3631	const char *value;
3632{
3633	int i, l;
3634	char **evp = UserEnviron;
3635	char *p;
3636
3637	if (value == NULL)
3638	{
3639		value = getextenv(envar);
3640		if (value == NULL)
3641			return;
3642	}
3643
3644	/* XXX enforce reasonable size? */
3645	i = strlen(envar) + 1;
3646	l = strlen(value) + i + 1;
3647	p = (char *) xalloc(l);
3648	(void) sm_strlcpyn(p, l, 3, envar, "=", value);
3649
3650	while (*evp != NULL && strncmp(*evp, p, i) != 0)
3651		evp++;
3652	if (*evp != NULL)
3653	{
3654		*evp++ = p;
3655	}
3656	else if (evp < &UserEnviron[MAXUSERENVIRON])
3657	{
3658		*evp++ = p;
3659		*evp = NULL;
3660	}
3661
3662	/* make sure it is in our environment as well */
3663	if (putenv(p) < 0)
3664		syserr("sm_setuserenv: putenv(%s) failed", p);
3665}
3666/*
3667**  DUMPSTATE -- dump state
3668**
3669**	For debugging.
3670*/
3671
3672void
3673dumpstate(when)
3674	char *when;
3675{
3676	register char *j = macvalue('j', CurEnv);
3677	int rs;
3678	extern int NextMacroId;
3679
3680	sm_syslog(LOG_DEBUG, CurEnv->e_id,
3681		  "--- dumping state on %s: $j = %s ---",
3682		  when,
3683		  j == NULL ? "<NULL>" : j);
3684	if (j != NULL)
3685	{
3686		if (!wordinclass(j, 'w'))
3687			sm_syslog(LOG_DEBUG, CurEnv->e_id,
3688				  "*** $j not in $=w ***");
3689	}
3690	sm_syslog(LOG_DEBUG, CurEnv->e_id, "CurChildren = %d", CurChildren);
3691	sm_syslog(LOG_DEBUG, CurEnv->e_id, "NextMacroId = %d (Max %d)",
3692		  NextMacroId, MAXMACROID);
3693	sm_syslog(LOG_DEBUG, CurEnv->e_id, "--- open file descriptors: ---");
3694	printopenfds(true);
3695	sm_syslog(LOG_DEBUG, CurEnv->e_id, "--- connection cache: ---");
3696	mci_dump_all(smioout, true);
3697	rs = strtorwset("debug_dumpstate", NULL, ST_FIND);
3698	if (rs > 0)
3699	{
3700		int status;
3701		register char **pvp;
3702		char *pv[MAXATOM + 1];
3703
3704		pv[0] = NULL;
3705		status = REWRITE(pv, rs, CurEnv);
3706		sm_syslog(LOG_DEBUG, CurEnv->e_id,
3707			  "--- ruleset debug_dumpstate returns stat %d, pv: ---",
3708			  status);
3709		for (pvp = pv; *pvp != NULL; pvp++)
3710			sm_syslog(LOG_DEBUG, CurEnv->e_id, "%s", *pvp);
3711	}
3712	sm_syslog(LOG_DEBUG, CurEnv->e_id, "--- end of state dump ---");
3713}
3714
3715#ifdef SIGUSR1
3716/*
3717**  SIGUSR1 -- Signal a request to dump state.
3718**
3719**	Parameters:
3720**		sig -- calling signal.
3721**
3722**	Returns:
3723**		none.
3724**
3725**	NOTE:	THIS CAN BE CALLED FROM A SIGNAL HANDLER.  DO NOT ADD
3726**		ANYTHING TO THIS ROUTINE UNLESS YOU KNOW WHAT YOU ARE
3727**		DOING.
3728**
3729**		XXX: More work is needed for this signal handler.
3730*/
3731
3732/* ARGSUSED */
3733static SIGFUNC_DECL
3734sigusr1(sig)
3735	int sig;
3736{
3737	int save_errno = errno;
3738
3739	FIX_SYSV_SIGNAL(sig, sigusr1);
3740	errno = save_errno;
3741	CHECK_CRITICAL(sig);
3742	dumpstate("user signal");
3743# if SM_HEAP_CHECK
3744	dumpstab();
3745# endif
3746	errno = save_errno;
3747	return SIGFUNC_RETURN;
3748}
3749#endif /* SIGUSR1 */
3750
3751/*
3752**  DROP_PRIVILEGES -- reduce privileges to those of the RunAsUser option
3753**
3754**	Parameters:
3755**		to_real_uid -- if set, drop to the real uid instead
3756**			of the RunAsUser.
3757**
3758**	Returns:
3759**		EX_OSERR if the setuid failed.
3760**		EX_OK otherwise.
3761*/
3762
3763int
3764drop_privileges(to_real_uid)
3765	bool to_real_uid;
3766{
3767	int rval = EX_OK;
3768	GIDSET_T emptygidset[1];
3769
3770	if (tTd(47, 1))
3771		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",
3772			   (int) to_real_uid,
3773			   (long) RealUid, (long) RealGid,
3774			   (long) getuid(), (long) getgid(),
3775			   (long) geteuid(), (long) getegid(),
3776			   (long) RunAsUid, (long) RunAsGid);
3777
3778	if (to_real_uid)
3779	{
3780		RunAsUserName = RealUserName;
3781		RunAsUid = RealUid;
3782		RunAsGid = RealGid;
3783		EffGid = RunAsGid;
3784	}
3785
3786	/* make sure no one can grab open descriptors for secret files */
3787	endpwent();
3788	sm_mbdb_terminate();
3789
3790	/* reset group permissions; these can be set later */
3791	emptygidset[0] = (to_real_uid || RunAsGid != 0) ? RunAsGid : getegid();
3792
3793	/*
3794	**  Notice:  on some OS (Linux...) the setgroups() call causes
3795	**	a logfile entry if sendmail is not run by root.
3796	**	However, it is unclear (no POSIX standard) whether
3797	**	setgroups() can only succeed if executed by root.
3798	**	So for now we keep it as it is; if you want to change it, use
3799	**  if (geteuid() == 0 && setgroups(1, emptygidset) == -1)
3800	*/
3801
3802	if (setgroups(1, emptygidset) == -1 && geteuid() == 0)
3803	{
3804		syserr("drop_privileges: setgroups(1, %d) failed",
3805		       (int) emptygidset[0]);
3806		rval = EX_OSERR;
3807	}
3808
3809	/* reset primary group id */
3810	if (to_real_uid)
3811	{
3812		/*
3813		**  Drop gid to real gid.
3814		**  On some OS we must reset the effective[/real[/saved]] gid,
3815		**  and then use setgid() to finally drop all group privileges.
3816		**  Later on we check whether we can get back the
3817		**  effective gid.
3818		*/
3819
3820#if HASSETEGID
3821		if (setegid(RunAsGid) < 0)
3822		{
3823			syserr("drop_privileges: setegid(%d) failed",
3824			       (int) RunAsGid);
3825			rval = EX_OSERR;
3826		}
3827#else /* HASSETEGID */
3828# if HASSETREGID
3829		if (setregid(RunAsGid, RunAsGid) < 0)
3830		{
3831			syserr("drop_privileges: setregid(%d, %d) failed",
3832			       (int) RunAsGid, (int) RunAsGid);
3833			rval = EX_OSERR;
3834		}
3835# else /* HASSETREGID */
3836#  if HASSETRESGID
3837		if (setresgid(RunAsGid, RunAsGid, RunAsGid) < 0)
3838		{
3839			syserr("drop_privileges: setresgid(%d, %d, %d) failed",
3840			       (int) RunAsGid, (int) RunAsGid, (int) RunAsGid);
3841			rval = EX_OSERR;
3842		}
3843#  endif /* HASSETRESGID */
3844# endif /* HASSETREGID */
3845#endif /* HASSETEGID */
3846	}
3847	if (rval == EX_OK && (to_real_uid || RunAsGid != 0))
3848	{
3849		if (setgid(RunAsGid) < 0 && (!UseMSP || getegid() != RunAsGid))
3850		{
3851			syserr("drop_privileges: setgid(%ld) failed",
3852			       (long) RunAsGid);
3853			rval = EX_OSERR;
3854		}
3855		errno = 0;
3856		if (rval == EX_OK && getegid() != RunAsGid)
3857		{
3858			syserr("drop_privileges: Unable to set effective gid=%ld to RunAsGid=%ld",
3859			       (long) getegid(), (long) RunAsGid);
3860			rval = EX_OSERR;
3861		}
3862	}
3863
3864	/* fiddle with uid */
3865	if (to_real_uid || RunAsUid != 0)
3866	{
3867		uid_t euid;
3868
3869		/*
3870		**  Try to setuid(RunAsUid).
3871		**  euid must be RunAsUid,
3872		**  ruid must be RunAsUid unless (e|r)uid wasn't 0
3873		**	and we didn't have to drop privileges to the real uid.
3874		*/
3875
3876		if (setuid(RunAsUid) < 0 ||
3877		    geteuid() != RunAsUid ||
3878		    (getuid() != RunAsUid &&
3879		     (to_real_uid || geteuid() == 0 || getuid() == 0)))
3880		{
3881#if HASSETREUID
3882			/*
3883			**  if ruid != RunAsUid, euid == RunAsUid, then
3884			**  try resetting just the real uid, then using
3885			**  setuid() to drop the saved-uid as well.
3886			*/
3887
3888			if (geteuid() == RunAsUid)
3889			{
3890				if (setreuid(RunAsUid, -1) < 0)
3891				{
3892					syserr("drop_privileges: setreuid(%d, -1) failed",
3893					       (int) RunAsUid);
3894					rval = EX_OSERR;
3895				}
3896				if (setuid(RunAsUid) < 0)
3897				{
3898					syserr("drop_privileges: second setuid(%d) attempt failed",
3899					       (int) RunAsUid);
3900					rval = EX_OSERR;
3901				}
3902			}
3903			else
3904#endif /* HASSETREUID */
3905			{
3906				syserr("drop_privileges: setuid(%d) failed",
3907				       (int) RunAsUid);
3908				rval = EX_OSERR;
3909			}
3910		}
3911		euid = geteuid();
3912		if (RunAsUid != 0 && setuid(0) == 0)
3913		{
3914			/*
3915			**  Believe it or not, the Linux capability model
3916			**  allows a non-root process to override setuid()
3917			**  on a process running as root and prevent that
3918			**  process from dropping privileges.
3919			*/
3920
3921			syserr("drop_privileges: setuid(0) succeeded (when it should not)");
3922			rval = EX_OSERR;
3923		}
3924		else if (RunAsUid != euid && setuid(euid) == 0)
3925		{
3926			/*
3927			**  Some operating systems will keep the saved-uid
3928			**  if a non-root effective-uid calls setuid(real-uid)
3929			**  making it possible to set it back again later.
3930			*/
3931
3932			syserr("drop_privileges: Unable to drop non-root set-user-ID privileges");
3933			rval = EX_OSERR;
3934		}
3935	}
3936
3937	if ((to_real_uid || RunAsGid != 0) &&
3938	    rval == EX_OK && RunAsGid != EffGid &&
3939	    getuid() != 0 && geteuid() != 0)
3940	{
3941		errno = 0;
3942		if (setgid(EffGid) == 0)
3943		{
3944			syserr("drop_privileges: setgid(%d) succeeded (when it should not)",
3945			       (int) EffGid);
3946			rval = EX_OSERR;
3947		}
3948	}
3949
3950	if (tTd(47, 5))
3951	{
3952		sm_dprintf("drop_privileges: e/ruid = %d/%d e/rgid = %d/%d\n",
3953			   (int) geteuid(), (int) getuid(),
3954			   (int) getegid(), (int) getgid());
3955		sm_dprintf("drop_privileges: RunAsUser = %d:%d\n",
3956			   (int) RunAsUid, (int) RunAsGid);
3957		if (tTd(47, 10))
3958			sm_dprintf("drop_privileges: rval = %d\n", rval);
3959	}
3960	return rval;
3961}
3962/*
3963**  FILL_FD -- make sure a file descriptor has been properly allocated
3964**
3965**	Used to make sure that stdin/out/err are allocated on startup
3966**
3967**	Parameters:
3968**		fd -- the file descriptor to be filled.
3969**		where -- a string used for logging.  If NULL, this is
3970**			being called on startup, and logging should
3971**			not be done.
3972**
3973**	Returns:
3974**		none
3975**
3976**	Side Effects:
3977**		possibly changes MissingFds
3978*/
3979
3980void
3981fill_fd(fd, where)
3982	int fd;
3983	char *where;
3984{
3985	int i;
3986	struct stat stbuf;
3987
3988	if (fstat(fd, &stbuf) >= 0 || errno != EBADF)
3989		return;
3990
3991	if (where != NULL)
3992		syserr("fill_fd: %s: fd %d not open", where, fd);
3993	else
3994		MissingFds |= 1 << fd;
3995	i = open(SM_PATH_DEVNULL, fd == 0 ? O_RDONLY : O_WRONLY, 0666);
3996	if (i < 0)
3997	{
3998		syserr("!fill_fd: %s: cannot open %s",
3999		       where == NULL ? "startup" : where, SM_PATH_DEVNULL);
4000	}
4001	if (fd != i)
4002	{
4003		(void) dup2(i, fd);
4004		(void) close(i);
4005	}
4006}
4007/*
4008**  SM_PRINTOPTIONS -- print options
4009**
4010**	Parameters:
4011**		options -- array of options.
4012**
4013**	Returns:
4014**		none.
4015*/
4016
4017static void
4018sm_printoptions(options)
4019	char **options;
4020{
4021	int ll;
4022	char **av;
4023
4024	av = options;
4025	ll = 7;
4026	while (*av != NULL)
4027	{
4028		if (ll + strlen(*av) > 63)
4029		{
4030			sm_dprintf("\n");
4031			ll = 0;
4032		}
4033		if (ll == 0)
4034			sm_dprintf("\t\t");
4035		else
4036			sm_dprintf(" ");
4037		sm_dprintf("%s", *av);
4038		ll += strlen(*av++) + 1;
4039	}
4040	sm_dprintf("\n");
4041}
4042
4043/*
4044**  TO8BIT -- convert \octal sequences in a test mode input line
4045**
4046**	Parameters:
4047**		str -- the input line.
4048**
4049**	Returns:
4050**		none.
4051**
4052**	Side Effects:
4053**		replaces \0octal in str with octal value.
4054*/
4055
4056static bool to8bit __P((char *));
4057
4058static bool
4059to8bit(str)
4060	char *str;
4061{
4062	int c, len;
4063	char *out, *in;
4064	bool changed;
4065
4066	if (str == NULL)
4067		return false;
4068	in = out = str;
4069	changed = false;
4070	len = 0;
4071	while ((c = (*str++ & 0377)) != '\0')
4072	{
4073		int oct, nxtc;
4074
4075		++len;
4076		if (c == '\\' &&
4077		    (nxtc = (*str & 0377)) == '0')
4078		{
4079			oct = 0;
4080			while ((nxtc = (*str & 0377)) != '\0' &&
4081				isascii(nxtc) && isdigit(nxtc))
4082			{
4083				oct <<= 3;
4084				oct += nxtc - '0';
4085				++str;
4086				++len;
4087			}
4088			changed = true;
4089			c = oct;
4090		}
4091		*out++ = c;
4092	}
4093	*out++ = c;
4094	if (changed)
4095	{
4096		char *q;
4097
4098		q = quote_internal_chars(in, in, &len);
4099		if (q != in)
4100			sm_strlcpy(in, q, len);
4101	}
4102	return changed;
4103}
4104
4105/*
4106**  TESTMODELINE -- process a test mode input line
4107**
4108**	Parameters:
4109**		line -- the input line.
4110**		e -- the current environment.
4111**	Syntax:
4112**		#  a comment
4113**		.X process X as a configuration line
4114**		=X dump a configuration item (such as mailers)
4115**		$X dump a macro or class
4116**		/X try an activity
4117**		X  normal process through rule set X
4118*/
4119
4120static void
4121testmodeline(line, e)
4122	char *line;
4123	ENVELOPE *e;
4124{
4125	register char *p;
4126	char *q;
4127	auto char *delimptr;
4128	int mid;
4129	int i, rs;
4130	STAB *map;
4131	char **s;
4132	struct rewrite *rw;
4133	ADDRESS a;
4134	char *lbp;
4135	auto int lbs;
4136	static int tryflags = RF_COPYNONE;
4137	char exbuf[MAXLINE];
4138	char lbuf[MAXLINE];
4139	extern unsigned char TokTypeNoC[];
4140	bool eightbit;
4141
4142	/* skip leading spaces */
4143	while (*line == ' ')
4144		line++;
4145
4146	lbp = NULL;
4147	eightbit = false;
4148	switch (line[0])
4149	{
4150	  case '#':
4151	  case '\0':
4152		return;
4153
4154	  case '?':
4155		help("-bt", e);
4156		return;
4157
4158	  case '.':		/* config-style settings */
4159		switch (line[1])
4160		{
4161		  case 'D':
4162			mid = macid_parse(&line[2], &delimptr);
4163			if (mid == 0)
4164				return;
4165			lbs = sizeof(lbuf);
4166			lbp = translate_dollars(delimptr, lbuf, &lbs);
4167			macdefine(&e->e_macro, A_TEMP, mid, lbp);
4168			if (lbp != lbuf)
4169				SM_FREE(lbp);
4170			break;
4171
4172		  case 'C':
4173			if (line[2] == '\0')	/* not to call syserr() */
4174				return;
4175
4176			mid = macid_parse(&line[2], &delimptr);
4177			if (mid == 0)
4178				return;
4179			lbs = sizeof(lbuf);
4180			lbp = translate_dollars(delimptr, lbuf, &lbs);
4181			expand(lbp, exbuf, sizeof(exbuf), e);
4182			if (lbp != lbuf)
4183				SM_FREE(lbp);
4184			p = exbuf;
4185			while (*p != '\0')
4186			{
4187				register char *wd;
4188				char delim;
4189
4190				while (*p != '\0' && SM_ISSPACE(*p))
4191					p++;
4192				wd = p;
4193				while (*p != '\0' && !(SM_ISSPACE(*p)))
4194					p++;
4195				delim = *p;
4196				*p = '\0';
4197				if (wd[0] != '\0')
4198					setclass(mid, wd);
4199				*p = delim;
4200			}
4201			break;
4202
4203		  case '\0':
4204			(void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
4205					     "Usage: .[DC]macro value(s)\n");
4206			break;
4207
4208		  default:
4209			(void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
4210					     "Unknown \".\" command %s\n", line);
4211			break;
4212		}
4213		return;
4214
4215	  case '=':		/* config-style settings */
4216		switch (line[1])
4217		{
4218		  case 'S':		/* dump rule set */
4219			rs = strtorwset(&line[2], NULL, ST_FIND);
4220			if (rs < 0)
4221			{
4222				(void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
4223						     "Undefined ruleset %s\n", &line[2]);
4224				return;
4225			}
4226			rw = RewriteRules[rs];
4227			if (rw == NULL)
4228				return;
4229			do
4230			{
4231				(void) sm_io_putc(smioout, SM_TIME_DEFAULT,
4232						  'R');
4233				s = rw->r_lhs;
4234				while (*s != NULL)
4235				{
4236					xputs(smioout, *s++);
4237					(void) sm_io_putc(smioout,
4238							  SM_TIME_DEFAULT, ' ');
4239				}
4240				(void) sm_io_putc(smioout, SM_TIME_DEFAULT,
4241						  '\t');
4242				(void) sm_io_putc(smioout, SM_TIME_DEFAULT,
4243						  '\t');
4244				s = rw->r_rhs;
4245				while (*s != NULL)
4246				{
4247					xputs(smioout, *s++);
4248					(void) sm_io_putc(smioout,
4249							  SM_TIME_DEFAULT, ' ');
4250				}
4251				(void) sm_io_putc(smioout, SM_TIME_DEFAULT,
4252						  '\n');
4253			} while ((rw = rw->r_next) != NULL);
4254			break;
4255
4256		  case 'M':
4257			for (i = 0; i < MAXMAILERS; i++)
4258			{
4259				if (Mailer[i] != NULL)
4260					printmailer(smioout, Mailer[i]);
4261			}
4262			break;
4263
4264		  case '\0':
4265			(void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
4266					     "Usage: =Sruleset or =M\n");
4267			break;
4268
4269		  default:
4270			(void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
4271					     "Unknown \"=\" command %s\n", line);
4272			break;
4273		}
4274		return;
4275
4276	  case '-':		/* set command-line-like opts */
4277		switch (line[1])
4278		{
4279		  case 'd':
4280			tTflag(&line[2]);
4281			break;
4282
4283		  case '\0':
4284			(void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
4285					     "Usage: -d{debug arguments}\n");
4286			break;
4287
4288		  default:
4289			(void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
4290					     "Unknown \"-\" command %s\n", line);
4291			break;
4292		}
4293		return;
4294
4295	  case '$':
4296		if (line[1] == '=')
4297		{
4298			mid = macid(&line[2]);
4299			if (mid != 0)
4300				stabapply(dump_class, mid);
4301			return;
4302		}
4303		mid = macid(&line[1]);
4304		if (mid == 0)
4305			return;
4306		p = macvalue(mid, e);
4307		if (p == NULL)
4308			(void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
4309					     "Undefined\n");
4310		else
4311		{
4312			xputs(smioout, p);
4313			(void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
4314					     "\n");
4315		}
4316		return;
4317
4318	  case '/':		/* miscellaneous commands */
4319		p = &line[strlen(line)];
4320		while (--p >= line && SM_ISSPACE(*p))
4321			*p = '\0';
4322		p = strpbrk(line, " \t");
4323		if (p != NULL)
4324		{
4325			while (SM_ISSPACE(*p))
4326				*p++ = '\0';
4327		}
4328		else
4329			p = "";
4330		if (line[1] == '\0')
4331		{
4332			(void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
4333					     "Usage: /[canon|map|mx|parse|try|tryflags]\n");
4334			return;
4335		}
4336		if (sm_strcasecmp(&line[1], "quit") == 0)
4337		{
4338			CurEnv->e_id = NULL;
4339			finis(true, true, ExitStat);
4340			/* NOTREACHED */
4341		}
4342		if (sm_strcasecmp(&line[1], "mx") == 0)
4343		{
4344#if NAMED_BIND
4345			/* look up MX records */
4346			int nmx;
4347			auto int rcode;
4348			char *mxhosts[MAXMXHOSTS + 1];
4349
4350			if (*p == '\0')
4351			{
4352				(void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
4353						     "Usage: /mx address\n");
4354				return;
4355			}
4356			nmx = getmxrr(p, mxhosts, NULL, TRYFALLBACK, &rcode,
4357				      NULL, -1);
4358			if (nmx == NULLMX)
4359				(void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
4360						     "getmxrr(%s) returns null MX (See RFC7505)\n",
4361						     p);
4362			else
4363				(void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
4364						     "getmxrr(%s) returns %d value(s):\n",
4365						     p, nmx);
4366			for (i = 0; i < nmx; i++)
4367				(void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
4368						     "\t%s\n", mxhosts[i]);
4369#else /* NAMED_BIND */
4370			(void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
4371					     "No MX code compiled in\n");
4372#endif /* NAMED_BIND */
4373		}
4374		else if (sm_strcasecmp(&line[1], "canon") == 0)
4375		{
4376			char host[MAXHOSTNAMELEN];
4377
4378			if (*p == '\0')
4379			{
4380				(void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
4381						     "Usage: /canon address\n");
4382				return;
4383			}
4384			else if (sm_strlcpy(host, p, sizeof(host)) >= sizeof(host))
4385			{
4386				(void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
4387						     "Name too long\n");
4388				return;
4389			}
4390			(void) getcanonname(host, sizeof(host), !HasWildcardMX,
4391					    NULL);
4392			(void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
4393					     "getcanonname(%s) returns %s\n",
4394					     p, host);
4395		}
4396		else if (sm_strcasecmp(&line[1], "map") == 0)
4397		{
4398			auto int rcode = EX_OK;
4399			char *av[2];
4400
4401			if (*p == '\0')
4402			{
4403				(void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
4404						     "Usage: /map mapname key\n");
4405				return;
4406			}
4407			for (q = p; *q != '\0' && !(SM_ISSPACE(*q)); q++)
4408				continue;
4409			if (*q == '\0')
4410			{
4411				(void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
4412						     "No key specified\n");
4413				return;
4414			}
4415			*q++ = '\0';
4416			map = stab(p, ST_MAP, ST_FIND);
4417			if (map == NULL)
4418			{
4419				(void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
4420						     "Map named \"%s\" not found\n", p);
4421				return;
4422			}
4423			if (!bitset(MF_OPEN, map->s_map.map_mflags) &&
4424			    !openmap(&(map->s_map)))
4425			{
4426				(void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
4427						     "Map named \"%s\" not open\n", p);
4428				return;
4429			}
4430			(void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
4431					     "map_lookup: %s (%s) ", p, q);
4432			av[0] = q;
4433			av[1] = NULL;
4434			p = (*map->s_map.map_class->map_lookup)
4435					(&map->s_map, q, av, &rcode);
4436			if (p == NULL)
4437				(void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
4438						     "no match (%d)\n",
4439						     rcode);
4440			else
4441				(void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
4442						     "returns %s (%d)\n", p,
4443						     rcode);
4444		}
4445		else if (sm_strcasecmp(&line[1], "try") == 0)
4446		{
4447			MAILER *m;
4448			STAB *st;
4449			auto int rcode = EX_OK;
4450
4451			q = strpbrk(p, " \t");
4452			if (q != NULL)
4453			{
4454				while (SM_ISSPACE(*q))
4455					*q++ = '\0';
4456			}
4457			if (q == NULL || *q == '\0')
4458			{
4459				(void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
4460						     "Usage: /try mailer address\n");
4461				return;
4462			}
4463			st = stab(p, ST_MAILER, ST_FIND);
4464			if (st == NULL)
4465			{
4466				(void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
4467						     "Unknown mailer %s\n", p);
4468				return;
4469			}
4470			m = st->s_mailer;
4471			(void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
4472					     "Trying %s %s address %s for mailer %s\n",
4473				     bitset(RF_HEADERADDR, tryflags) ? "header"
4474							: "envelope",
4475				     bitset(RF_SENDERADDR, tryflags) ? "sender"
4476							: "recipient", q, p);
4477			p = remotename(q, m, tryflags, &rcode, CurEnv);
4478			(void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
4479					     "Rcode = %d, addr = %s\n",
4480					     rcode, p == NULL ? "<NULL>" : p);
4481			e->e_to = NULL;
4482		}
4483		else if (sm_strcasecmp(&line[1], "tryflags") == 0)
4484		{
4485			if (*p == '\0')
4486			{
4487				(void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
4488						     "Usage: /tryflags [Hh|Ee][Ss|Rr]\n");
4489				return;
4490			}
4491			for (; *p != '\0'; p++)
4492			{
4493				switch (*p)
4494				{
4495				  case 'H':
4496				  case 'h':
4497					tryflags |= RF_HEADERADDR;
4498					break;
4499
4500				  case 'E':
4501				  case 'e':
4502					tryflags &= ~RF_HEADERADDR;
4503					break;
4504
4505				  case 'S':
4506				  case 's':
4507					tryflags |= RF_SENDERADDR;
4508					break;
4509
4510				  case 'R':
4511				  case 'r':
4512					tryflags &= ~RF_SENDERADDR;
4513					break;
4514				}
4515			}
4516			exbuf[0] = bitset(RF_HEADERADDR, tryflags) ? 'h' : 'e';
4517			exbuf[1] = ' ';
4518			exbuf[2] = bitset(RF_SENDERADDR, tryflags) ? 's' : 'r';
4519			exbuf[3] = '\0';
4520			macdefine(&e->e_macro, A_TEMP,
4521				macid("{addr_type}"), exbuf);
4522		}
4523		else if (sm_strcasecmp(&line[1], "parse") == 0)
4524		{
4525			if (*p == '\0')
4526			{
4527				(void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
4528						     "Usage: /parse address\n");
4529				return;
4530			}
4531			q = crackaddr(p, e);
4532			(void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
4533					     "Cracked address = ");
4534			xputs(smioout, q);
4535			(void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
4536					     "\nParsing %s %s address\n",
4537					     bitset(RF_HEADERADDR, tryflags) ?
4538							"header" : "envelope",
4539					     bitset(RF_SENDERADDR, tryflags) ?
4540							"sender" : "recipient");
4541			if (parseaddr(p, &a, tryflags, '\0', NULL, e, true)
4542			    == NULL)
4543				(void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
4544						     "Cannot parse\n");
4545			else if (a.q_host != NULL && a.q_host[0] != '\0')
4546				(void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
4547						     "mailer %s, host %s, user %s\n",
4548						     a.q_mailer->m_name,
4549						     a.q_host,
4550						     a.q_user);
4551			else
4552				(void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
4553						     "mailer %s, user %s\n",
4554						     a.q_mailer->m_name,
4555						     a.q_user);
4556			e->e_to = NULL;
4557		}
4558		else if (sm_strcasecmp(&line[1], "header") == 0)
4559		{
4560			unsigned long ul;
4561
4562			ul = chompheader(p, CHHDR_CHECK|CHHDR_USER, NULL, e);
4563			(void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
4564					     "ul = %lu\n", ul);
4565		}
4566#if NETINET || NETINET6
4567		else if (sm_strcasecmp(&line[1], "gethostbyname") == 0)
4568		{
4569			int family = AF_INET;
4570
4571			q = strpbrk(p, " \t");
4572			if (q != NULL)
4573			{
4574				while (SM_ISSPACE(*q))
4575					*q++ = '\0';
4576# if NETINET6
4577				if (*q != '\0' && (strcmp(q, "inet6") == 0 ||
4578						   strcmp(q, "AAAA") == 0))
4579					family = AF_INET6;
4580# endif /* NETINET6 */
4581			}
4582			(void) sm_gethostbyname(p, family);
4583		}
4584#endif /* NETINET || NETINET6 */
4585#if DANE
4586		else if (sm_strcasecmp(&line[1], "dnslookup") == 0)
4587		{
4588			DNS_REPLY_T *r;
4589			int rr_type, family;
4590			unsigned int flags;
4591
4592			rr_type = T_A;
4593			family = AF_INET;
4594			flags = RR_AS_TEXT;
4595			q = strpbrk(p, " \t");
4596			if (q != NULL)
4597			{
4598				char *pflags;
4599
4600				while (SM_ISSPACE(*q))
4601					*q++ = '\0';
4602				pflags = strpbrk(q, " \t");
4603				if (pflags != NULL)
4604				{
4605					while (SM_ISSPACE(*pflags))
4606						*pflags++ = '\0';
4607				}
4608				rr_type = dns_string_to_type(q);
4609				if (rr_type == T_A)
4610					family = AF_INET;
4611# if NETINET6
4612				if (rr_type == T_AAAA)
4613					family = AF_INET6;
4614# endif
4615				while (pflags != NULL && *pflags != '\0' &&
4616					!SM_ISSPACE(*pflags))
4617				{
4618					if (*pflags == 'c')
4619						flags |= RR_NO_CNAME;
4620					else if (*pflags == 'o')
4621						flags |= RR_ONLY_CNAME;
4622					else if (*pflags == 'T')
4623						flags &= ~RR_AS_TEXT;
4624					++pflags;
4625				}
4626			}
4627			r = dns_lookup_int(p, C_IN, rr_type,
4628					0, 0, 0, flags, NULL, NULL);
4629			if (r != NULL && family >= 0)
4630			{
4631				(void) dns2he(r, family);
4632				dns_free_data(r);
4633				r = NULL;
4634			}
4635		}
4636#endif /* DANE */
4637		else
4638		{
4639			(void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
4640					     "Unknown \"/\" command %s\n",
4641					     line);
4642		}
4643		(void) sm_io_flush(smioout, SM_TIME_DEFAULT);
4644		return;
4645	}
4646
4647	for (p = line; SM_ISSPACE(*p); p++)
4648		continue;
4649	q = p;
4650	while (*p != '\0' && !(SM_ISSPACE(*p)))
4651		p++;
4652	if (*p == '\0')
4653	{
4654		(void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
4655				     "No address!\n");
4656		return;
4657	}
4658	*p = '\0';
4659	if (tTd(23, 101))
4660		eightbit = to8bit(p + 1);
4661	if (invalidaddr(p + 1, NULL, true))
4662		return;
4663	do
4664	{
4665		register char **pvp;
4666		char pvpbuf[PSBUFSIZE];
4667
4668		pvp = prescan(++p, ',', pvpbuf, sizeof(pvpbuf), &delimptr,
4669			      ConfigLevel >= 9 ? TokTypeNoC : ExtTokenTab, false);
4670		if (pvp == NULL)
4671			continue;
4672		p = q;
4673		while (*p != '\0')
4674		{
4675			int status;
4676
4677			rs = strtorwset(p, NULL, ST_FIND);
4678			if (rs < 0)
4679			{
4680				(void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
4681						     "Undefined ruleset %s\n",
4682						     p);
4683				break;
4684			}
4685			status = REWRITE(pvp, rs, e);
4686			if (status != EX_OK)
4687				(void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
4688						     "== Ruleset %s (%d) status %d\n",
4689						     p, rs, status);
4690			else if (eightbit)
4691			{
4692				cataddr(pvp, NULL, exbuf, sizeof(exbuf), '\0',
4693					true);
4694				(void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
4695						     "cataddr: %s\n",
4696						     str2prt(exbuf));
4697			}
4698			while (*p != '\0' && *p++ != ',')
4699				continue;
4700		}
4701	} while (*(p = delimptr) != '\0');
4702	(void) sm_io_flush(smioout, SM_TIME_DEFAULT);
4703}
4704
4705static void
4706dump_class(s, id)
4707	register STAB *s;
4708	int id;
4709{
4710	if (s->s_symtype != ST_CLASS)
4711		return;
4712	if (bitnset(bitidx(id), s->s_class))
4713		(void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
4714				     "%s\n", s->s_name);
4715}
4716
4717/*
4718**  An exception type used to create QuickAbort exceptions.
4719**  This is my first cut at converting QuickAbort from longjmp to exceptions.
4720**  These exceptions have a single integer argument, which is the argument
4721**  to longjmp in the original code (either 1 or 2).  I don't know the
4722**  significance of 1 vs 2: the calls to setjmp don't care.
4723*/
4724
4725const SM_EXC_TYPE_T EtypeQuickAbort =
4726{
4727	SmExcTypeMagic,
4728	"E:mta.quickabort",
4729	"i",
4730	sm_etype_printf,
4731	"quick abort %0",
4732};
4733