xref: /freebsd/contrib/sendmail/src/main.c (revision 1b6c76a2fe091c74f08427e6c870851025a9cf67)
1 /*
2  * Copyright (c) 1998-2001 Sendmail, 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 #ifndef lint
15 static char copyright[] =
16 "@(#) Copyright (c) 1998-2001 Sendmail, Inc. and its suppliers.\n\
17 	All rights reserved.\n\
18      Copyright (c) 1983, 1995-1997 Eric P. Allman.  All rights reserved.\n\
19      Copyright (c) 1988, 1993\n\
20 	The Regents of the University of California.  All rights reserved.\n";
21 #endif /* ! lint */
22 
23 #ifndef lint
24 static char id[] = "@(#)$Id: main.c,v 8.485.4.60 2001/05/27 22:00:26 gshapiro Exp $";
25 #endif /* ! lint */
26 
27 #define	_DEFINE
28 
29 #include <sendmail.h>
30 
31 
32 #if NETINET || NETINET6
33 # include <arpa/inet.h>
34 #endif /* NETINET || NETINET6 */
35 
36 static SIGFUNC_DECL	intindebug __P((int));
37 static SIGFUNC_DECL	quiesce __P((int));
38 static SIGFUNC_DECL	sigusr1 __P((int));
39 static SIGFUNC_DECL	term_daemon __P((int));
40 static void	dump_class __P((STAB *, int));
41 static void	obsolete __P((char **));
42 static void	testmodeline __P((char *, ENVELOPE *));
43 
44 /*
45 **  SENDMAIL -- Post mail to a set of destinations.
46 **
47 **	This is the basic mail router.  All user mail programs should
48 **	call this routine to actually deliver mail.  Sendmail in
49 **	turn calls a bunch of mail servers that do the real work of
50 **	delivering the mail.
51 **
52 **	Sendmail is driven by settings read in from /etc/mail/sendmail.cf
53 **	(read by readcf.c).
54 **
55 **	Usage:
56 **		/usr/lib/sendmail [flags] addr ...
57 **
58 **		See the associated documentation for details.
59 **
60 **	Author:
61 **		Eric Allman, UCB/INGRES (until 10/81).
62 **			     Britton-Lee, Inc., purveyors of fine
63 **				database computers (11/81 - 10/88).
64 **			     International Computer Science Institute
65 **				(11/88 - 9/89).
66 **			     UCB/Mammoth Project (10/89 - 7/95).
67 **			     InReference, Inc. (8/95 - 1/97).
68 **			     Sendmail, Inc. (1/98 - present).
69 **		The support of the my employers is gratefully acknowledged.
70 **			Few of them (Britton-Lee in particular) have had
71 **			anything to gain from my involvement in this project.
72 */
73 
74 
75 int		NextMailer;	/* "free" index into Mailer struct */
76 char		*FullName;	/* sender's full name */
77 ENVELOPE	BlankEnvelope;	/* a "blank" envelope */
78 static ENVELOPE	MainEnvelope;	/* the envelope around the basic letter */
79 ADDRESS		NullAddress =	/* a null address */
80 		{ "", "", NULL, "" };
81 char		*CommandLineArgs;	/* command line args for pid file */
82 bool		Warn_Q_option = FALSE;	/* warn about Q option use */
83 static int	MissingFds = 0;	/* bit map of fds missing on startup */
84 
85 #ifdef NGROUPS_MAX
86 GIDSET_T	InitialGidSet[NGROUPS_MAX];
87 #endif /* NGROUPS_MAX */
88 
89 #if DAEMON && !SMTP
90 ERROR %%%%   Cannot have DAEMON mode without SMTP   %%%% ERROR
91 #endif /* DAEMON && !SMTP */
92 #if SMTP && !QUEUE
93 ERROR %%%%   Cannot have SMTP mode without QUEUE   %%%% ERROR
94 #endif /* SMTP && !QUEUE */
95 
96 #define MAXCONFIGLEVEL	9	/* highest config version level known */
97 
98 #if SASL
99 static sasl_callback_t srvcallbacks[] =
100 {
101 	{	SASL_CB_VERIFYFILE,	&safesaslfile,	NULL	},
102 	{	SASL_CB_PROXY_POLICY,	&proxy_policy,	NULL	},
103 	{	SASL_CB_LIST_END,	NULL,		NULL	}
104 };
105 
106 #endif /* SASL */
107 
108 int SubmitMode;
109 
110 int
111 main(argc, argv, envp)
112 	int argc;
113 	char **argv;
114 	char **envp;
115 {
116 	register char *p;
117 	char **av;
118 	extern char Version[];
119 	char *ep, *from;
120 	STAB *st;
121 	register int i;
122 	int j;
123 	int dp;
124 	bool safecf = TRUE;
125 	BITMAP256 *p_flags = NULL;	/* daemon flags */
126 	bool warn_C_flag = FALSE;
127 	bool auth = TRUE;		/* whether to set e_auth_param */
128 	char warn_f_flag = '\0';
129 	bool run_in_foreground = FALSE;	/* -bD mode */
130 	static bool reenter = FALSE;
131 	struct passwd *pw;
132 	struct hostent *hp;
133 	char *nullserver = NULL;
134 	char *authinfo = NULL;
135 	char *sysloglabel = NULL;	/* label for syslog */
136 	bool forged;
137 	struct stat traf_st;		/* for TrafficLog FIFO check */
138 	char jbuf[MAXHOSTNAMELEN];	/* holds MyHostName */
139 	static char rnamebuf[MAXNAME];	/* holds RealUserName */
140 	char *emptyenviron[1];
141 # if STARTTLS
142 	bool tls_ok;
143 # endif /* STARTTLS */
144 	QUEUE_CHAR *new;
145 	extern int DtableSize;
146 	extern int optind;
147 	extern int opterr;
148 	extern char *optarg;
149 	extern char **environ;
150 
151 	/*
152 	**  Check to see if we reentered.
153 	**	This would normally happen if e_putheader or e_putbody
154 	**	were NULL when invoked.
155 	*/
156 
157 	if (reenter)
158 	{
159 		syserr("main: reentered!");
160 		abort();
161 	}
162 	reenter = TRUE;
163 
164 	/* avoid null pointer dereferences */
165 	TermEscape.te_rv_on = TermEscape.te_rv_off = "";
166 
167 	/*
168 	**  Seed the random number generator.
169 	**  Used for queue file names, picking a queue directory, and
170 	**  MX randomization.
171 	*/
172 
173 	seed_random();
174 
175 	/* do machine-dependent initializations */
176 	init_md(argc, argv);
177 
178 
179 	/* in 4.4BSD, the table can be huge; impose a reasonable limit */
180 	DtableSize = getdtsize();
181 	if (DtableSize > 256)
182 		DtableSize = 256;
183 
184 	/*
185 	**  Be sure we have enough file descriptors.
186 	**	But also be sure that 0, 1, & 2 are open.
187 	*/
188 
189 	fill_fd(STDIN_FILENO, NULL);
190 	fill_fd(STDOUT_FILENO, NULL);
191 	fill_fd(STDERR_FILENO, NULL);
192 
193 	i = DtableSize;
194 	while (--i > 0)
195 	{
196 		if (i != STDIN_FILENO && i != STDOUT_FILENO && i != STDERR_FILENO)
197 			(void) close(i);
198 	}
199 	errno = 0;
200 
201 #if LOG
202 #  ifdef LOG_MAIL
203 	openlog("sendmail", LOG_PID, LOG_MAIL);
204 #  else /* LOG_MAIL */
205 	openlog("sendmail", LOG_PID);
206 #  endif /* LOG_MAIL */
207 #endif /* LOG */
208 
209 	if (MissingFds != 0)
210 	{
211 		char mbuf[MAXLINE];
212 
213 		mbuf[0] = '\0';
214 		if (bitset(1 << STDIN_FILENO, MissingFds))
215 			(void) strlcat(mbuf, ", stdin", sizeof mbuf);
216 		if (bitset(1 << STDOUT_FILENO, MissingFds))
217 			(void) strlcat(mbuf, ", stdout", sizeof mbuf);
218 		if (bitset(1 << STDERR_FILENO, MissingFds))
219 			(void) strlcat(mbuf, ", stderr", sizeof mbuf);
220 		syserr("File descriptors missing on startup: %s", &mbuf[2]);
221 	}
222 
223 	/* reset status from syserr() calls for missing file descriptors */
224 	Errors = 0;
225 	ExitStat = EX_OK;
226 
227 	SubmitMode = SUBMIT_UNKNOWN;
228 #if XDEBUG
229 	checkfd012("after openlog");
230 #endif /* XDEBUG */
231 
232 	tTsetup(tTdvect, sizeof tTdvect, "0-99.1");
233 
234 #ifdef NGROUPS_MAX
235 	/* save initial group set for future checks */
236 	i = getgroups(NGROUPS_MAX, InitialGidSet);
237 	if (i == 0)
238 		InitialGidSet[0] = (GID_T) -1;
239 	while (i < NGROUPS_MAX)
240 		InitialGidSet[i++] = InitialGidSet[0];
241 #endif /* NGROUPS_MAX */
242 
243 	/* drop group id privileges (RunAsUser not yet set) */
244 	dp = drop_privileges(FALSE);
245 	setstat(dp);
246 
247 # ifdef SIGUSR1
248 	/* Only allow root (or non-set-*-ID binaries) to use SIGUSR1 */
249 	if (getuid() == 0 ||
250 	    (getuid() == geteuid() && getgid() == getegid()))
251 	{
252 		/* arrange to dump state on user-1 signal */
253 		(void) setsignal(SIGUSR1, sigusr1);
254 	}
255 # endif /* SIGUSR1 */
256 
257 	/* initialize for setproctitle */
258 	initsetproctitle(argc, argv, envp);
259 
260 	/* Handle any non-getoptable constructions. */
261 	obsolete(argv);
262 
263 	/*
264 	**  Do a quick prescan of the argument list.
265 	*/
266 
267 
268 #if defined(__osf__) || defined(_AIX3)
269 # define OPTIONS	"B:b:C:cd:e:F:f:Gh:IiL:M:mN:nO:o:p:q:R:r:sTtUV:vX:x"
270 #endif /* defined(__osf__) || defined(_AIX3) */
271 #if defined(sony_news)
272 # define OPTIONS	"B:b:C:cd:E:e:F:f:Gh:IiJ:L:M:mN:nO:o:p:q:R:r:sTtUV:vX:"
273 #endif /* defined(sony_news) */
274 #ifndef OPTIONS
275 # define OPTIONS	"B:b:C:cd:e:F:f:Gh:IiL:M:mN:nO:o:p:q:R:r:sTtUV:vX:"
276 #endif /* ! OPTIONS */
277 	opterr = 0;
278 	while ((j = getopt(argc, argv, OPTIONS)) != -1)
279 	{
280 		switch (j)
281 		{
282 		  case 'd':
283 			/* hack attack -- see if should use ANSI mode */
284 			if (strcmp(optarg, "ANSI") == 0)
285 			{
286 				TermEscape.te_rv_on = "\033[7m";
287 				TermEscape.te_rv_off = "\033[0m";
288 				break;
289 			}
290 			tTflag(optarg);
291 			setbuf(stdout, (char *) NULL);
292 			break;
293 
294 		  case 'G':	/* relay (gateway) submission */
295 			SubmitMode |= SUBMIT_MTA;
296 			break;
297 
298 		  case 'L':
299 			j = min(strlen(optarg), 24) + 1;
300 			sysloglabel = xalloc(j);
301 			(void) strlcpy(sysloglabel, optarg, j);
302 			break;
303 
304 		  case 'U':	/* initial (user) submission */
305 			SubmitMode |= SUBMIT_MSA;
306 			break;
307 		}
308 	}
309 	opterr = 1;
310 
311 #if LOG
312 	if (sysloglabel != NULL)
313 	{
314 		/* Sanitize the string */
315 		for (p = sysloglabel; *p != '\0'; p++)
316 		{
317 			if (!isascii(*p) || !isprint(*p) || *p == '%')
318 				*p = '*';
319 		}
320 		closelog();
321 #  ifdef LOG_MAIL
322 		openlog(sysloglabel, LOG_PID, LOG_MAIL);
323 #  else /* LOG_MAIL */
324 		openlog(sysloglabel, LOG_PID);
325 #  endif /* LOG_MAIL */
326 	}
327 #endif /* LOG */
328 
329 	/* set up the blank envelope */
330 	BlankEnvelope.e_puthdr = putheader;
331 	BlankEnvelope.e_putbody = putbody;
332 	BlankEnvelope.e_xfp = NULL;
333 	STRUCTCOPY(NullAddress, BlankEnvelope.e_from);
334 	CurEnv = &BlankEnvelope;
335 	STRUCTCOPY(NullAddress, MainEnvelope.e_from);
336 
337 	/*
338 	**  Set default values for variables.
339 	**	These cannot be in initialized data space.
340 	*/
341 
342 	setdefaults(&BlankEnvelope);
343 
344 	RealUid = getuid();
345 	RealGid = getgid();
346 
347 	pw = sm_getpwuid(RealUid);
348 	if (pw != NULL)
349 		(void) snprintf(rnamebuf, sizeof rnamebuf, "%s", pw->pw_name);
350 	else
351 		(void) snprintf(rnamebuf, sizeof rnamebuf, "Unknown UID %d",
352 				(int) RealUid);
353 
354 	RealUserName = rnamebuf;
355 
356 	if (tTd(0, 101))
357 	{
358 		dprintf("Version %s\n", Version);
359 		finis(FALSE, EX_OK);
360 	}
361 
362 	/*
363 	**  if running non-setuid binary as non-root, pretend
364 	**  we are the RunAsUid
365 	*/
366 
367 	if (RealUid != 0 && geteuid() == RealUid)
368 	{
369 		if (tTd(47, 1))
370 			dprintf("Non-setuid binary: RunAsUid = RealUid = %d\n",
371 				(int)RealUid);
372 		RunAsUid = RealUid;
373 	}
374 	else if (geteuid() != 0)
375 		RunAsUid = geteuid();
376 
377 	if (RealUid != 0 && getegid() == RealGid)
378 		RunAsGid = RealGid;
379 
380 	if (tTd(47, 5))
381 	{
382 		dprintf("main: e/ruid = %d/%d e/rgid = %d/%d\n",
383 			(int)geteuid(), (int)getuid(),
384 			(int)getegid(), (int)getgid());
385 		dprintf("main: RunAsUser = %d:%d\n",
386 			(int)RunAsUid, (int)RunAsGid);
387 	}
388 
389 	/* save command line arguments */
390 	j = 0;
391 	for (av = argv; *av != NULL; )
392 		j += strlen(*av++) + 1;
393 	SaveArgv = (char **) xalloc(sizeof (char *) * (argc + 1));
394 	CommandLineArgs = xalloc(j);
395 	p = CommandLineArgs;
396 	for (av = argv, i = 0; *av != NULL; )
397 	{
398 		int h;
399 
400 		SaveArgv[i++] = newstr(*av);
401 		if (av != argv)
402 			*p++ = ' ';
403 		(void) strlcpy(p, *av++, j);
404 		h = strlen(p);
405 		p += h;
406 		j -= h + 1;
407 	}
408 	SaveArgv[i] = NULL;
409 
410 	if (tTd(0, 1))
411 	{
412 		int ll;
413 		extern char *CompileOptions[];
414 
415 		dprintf("Version %s\n Compiled with:", Version);
416 		av = CompileOptions;
417 		ll = 7;
418 		while (*av != NULL)
419 		{
420 			if (ll + strlen(*av) > 63)
421 			{
422 				dprintf("\n");
423 				ll = 0;
424 			}
425 			if (ll == 0)
426 				dprintf("\t\t");
427 			else
428 				dprintf(" ");
429 			dprintf("%s", *av);
430 			ll += strlen(*av++) + 1;
431 		}
432 		dprintf("\n");
433 	}
434 	if (tTd(0, 10))
435 	{
436 		int ll;
437 		extern char *OsCompileOptions[];
438 
439 		dprintf("    OS Defines:");
440 		av = OsCompileOptions;
441 		ll = 7;
442 		while (*av != NULL)
443 		{
444 			if (ll + strlen(*av) > 63)
445 			{
446 				dprintf("\n");
447 				ll = 0;
448 			}
449 			if (ll == 0)
450 				dprintf("\t\t");
451 			else
452 				dprintf(" ");
453 			dprintf("%s", *av);
454 			ll += strlen(*av++) + 1;
455 		}
456 		dprintf("\n");
457 #ifdef _PATH_UNIX
458 		dprintf("Kernel symbols:\t%s\n", _PATH_UNIX);
459 #endif /* _PATH_UNIX */
460 		dprintf(" Def Conf file:\t%s\n", getcfname());
461 		dprintf("  Def Pid file:\t%s\n", PidFile);
462 	}
463 
464 	InChannel = stdin;
465 	OutChannel = stdout;
466 
467 	/* clear sendmail's environment */
468 	ExternalEnviron = environ;
469 	emptyenviron[0] = NULL;
470 	environ = emptyenviron;
471 
472 	/*
473 	**  restore any original TZ setting until TimeZoneSpec has been
474 	**  determined - or early log messages may get bogus time stamps
475 	*/
476 	if ((p = getextenv("TZ")) != NULL)
477 	{
478 		char *tz;
479 		int tzlen;
480 
481 		tzlen = strlen(p) + 4;
482 		tz = xalloc(tzlen);
483 		(void) snprintf(tz, tzlen, "TZ=%s", p);
484 		(void) putenv(tz);
485 	}
486 
487 	/* prime the child environment */
488 	setuserenv("AGENT", "sendmail");
489 	(void) setsignal(SIGPIPE, SIG_IGN);
490 
491 	OldUmask = umask(022);
492 	OpMode = MD_DELIVER;
493 	FullName = getextenv("NAME");
494 
495 	/*
496 	**  Initialize name server if it is going to be used.
497 	*/
498 
499 #if NAMED_BIND
500 	if (!bitset(RES_INIT, _res.options))
501 		(void) res_init();
502 
503 	/*
504 	**  hack to avoid crashes when debugging for the resolver is
505 	**  turned on and sfio is used
506 	*/
507 	if (tTd(8, 8))
508 # if !SFIO || SFIO_STDIO_COMPAT
509 		_res.options |= RES_DEBUG;
510 # else /* !SFIO || SFIO_STDIO_COMPAT */
511 		dprintf("RES_DEBUG not available due to SFIO\n");
512 # endif /* !SFIO || SFIO_STDIO_COMPAT */
513 	else
514 		_res.options &= ~RES_DEBUG;
515 # ifdef RES_NOALIASES
516 	_res.options |= RES_NOALIASES;
517 # endif /* RES_NOALIASES */
518 	TimeOuts.res_retry[RES_TO_DEFAULT] = _res.retry;
519 	TimeOuts.res_retry[RES_TO_FIRST] = _res.retry;
520 	TimeOuts.res_retry[RES_TO_NORMAL] = _res.retry;
521 	TimeOuts.res_retrans[RES_TO_DEFAULT] = _res.retrans;
522 	TimeOuts.res_retrans[RES_TO_FIRST] = _res.retrans;
523 	TimeOuts.res_retrans[RES_TO_NORMAL] = _res.retrans;
524 #endif /* NAMED_BIND */
525 
526 	errno = 0;
527 	from = NULL;
528 
529 	/* initialize some macros, etc. */
530 	initmacros(CurEnv);
531 	init_vendor_macros(CurEnv);
532 
533 	/* version */
534 	define('v', Version, CurEnv);
535 
536 	/* hostname */
537 	hp = myhostname(jbuf, sizeof jbuf);
538 	if (jbuf[0] != '\0')
539 	{
540 		struct	utsname	utsname;
541 
542 		if (tTd(0, 4))
543 			dprintf("canonical name: %s\n", jbuf);
544 		define('w', newstr(jbuf), CurEnv);	/* must be new string */
545 		define('j', newstr(jbuf), CurEnv);
546 		setclass('w', jbuf);
547 
548 		p = strchr(jbuf, '.');
549 		if (p != NULL)
550 		{
551 			if (p[1] != '\0')
552 			{
553 				define('m', newstr(&p[1]), CurEnv);
554 			}
555 			while (p != NULL && strchr(&p[1], '.') != NULL)
556 			{
557 				*p = '\0';
558 				if (tTd(0, 4))
559 					dprintf("\ta.k.a.: %s\n", jbuf);
560 				setclass('w', jbuf);
561 				*p++ = '.';
562 				p = strchr(p, '.');
563 			}
564 		}
565 
566 		if (uname(&utsname) >= 0)
567 			p = utsname.nodename;
568 		else
569 		{
570 			if (tTd(0, 22))
571 				dprintf("uname failed (%s)\n",
572 					errstring(errno));
573 			makelower(jbuf);
574 			p = jbuf;
575 		}
576 		if (tTd(0, 4))
577 			dprintf(" UUCP nodename: %s\n", p);
578 		p = newstr(p);
579 		define('k', p, CurEnv);
580 		setclass('k', p);
581 		setclass('w', p);
582 	}
583 	if (hp != NULL)
584 	{
585 		for (av = hp->h_aliases; av != NULL && *av != NULL; av++)
586 		{
587 			if (tTd(0, 4))
588 				dprintf("\ta.k.a.: %s\n", *av);
589 			setclass('w', *av);
590 		}
591 #if NETINET || NETINET6
592 		for (i = 0; hp->h_addr_list[i] != NULL; i++)
593 		{
594 # if NETINET6
595 			char *addr;
596 			char buf6[INET6_ADDRSTRLEN];
597 			struct in6_addr ia6;
598 # endif /* NETINET6 */
599 # if NETINET
600 			struct in_addr ia;
601 # endif /* NETINET */
602 			char ipbuf[103];
603 
604 			ipbuf[0] = '\0';
605 			switch (hp->h_addrtype)
606 			{
607 # if NETINET
608 			  case AF_INET:
609 				if (hp->h_length != INADDRSZ)
610 					break;
611 
612 				memmove(&ia, hp->h_addr_list[i], INADDRSZ);
613 				(void) snprintf(ipbuf,	 sizeof ipbuf,
614 						"[%.100s]", inet_ntoa(ia));
615 				break;
616 # endif /* NETINET */
617 
618 # if NETINET6
619 			  case AF_INET6:
620 				if (hp->h_length != IN6ADDRSZ)
621 					break;
622 
623 				memmove(&ia6, hp->h_addr_list[i], IN6ADDRSZ);
624 				addr = anynet_ntop(&ia6, buf6, sizeof buf6);
625 				if (addr != NULL)
626 					(void) snprintf(ipbuf, sizeof ipbuf,
627 							"[%.100s]", addr);
628 				break;
629 # endif /* NETINET6 */
630 			}
631 			if (ipbuf[0] == '\0')
632 				break;
633 
634 			if (tTd(0, 4))
635 				dprintf("\ta.k.a.: %s\n", ipbuf);
636 			setclass('w', ipbuf);
637 		}
638 #endif /* NETINET || NETINET6 */
639 #if _FFR_FREEHOSTENT && NETINET6
640 		freehostent(hp);
641 		hp = NULL;
642 #endif /* _FFR_FREEHOSTENT && NETINET6 */
643 	}
644 
645 	/* current time */
646 	define('b', arpadate((char *) NULL), CurEnv);
647 	/* current load average */
648 	CurrentLA = sm_getla(CurEnv);
649 
650 	QueueLimitRecipient = (QUEUE_CHAR *) NULL;
651 	QueueLimitSender = (QUEUE_CHAR *) NULL;
652 	QueueLimitId = (QUEUE_CHAR *) NULL;
653 
654 	/*
655 	**  Crack argv.
656 	*/
657 
658 	av = argv;
659 	p = strrchr(*av, '/');
660 	if (p++ == NULL)
661 		p = *av;
662 	if (strcmp(p, "newaliases") == 0)
663 		OpMode = MD_INITALIAS;
664 	else if (strcmp(p, "mailq") == 0)
665 		OpMode = MD_PRINT;
666 	else if (strcmp(p, "smtpd") == 0)
667 		OpMode = MD_DAEMON;
668 	else if (strcmp(p, "hoststat") == 0)
669 		OpMode = MD_HOSTSTAT;
670 	else if (strcmp(p, "purgestat") == 0)
671 		OpMode = MD_PURGESTAT;
672 
673 	optind = 1;
674 	while ((j = getopt(argc, argv, OPTIONS)) != -1)
675 	{
676 		switch (j)
677 		{
678 		  case 'b':	/* operations mode */
679 			switch (j = *optarg)
680 			{
681 			  case MD_DAEMON:
682 			  case MD_FGDAEMON:
683 #if !DAEMON
684 				usrerr("Daemon mode not implemented");
685 				ExitStat = EX_USAGE;
686 				break;
687 #endif /* !DAEMON */
688 			  case MD_SMTP:
689 #if !SMTP
690 				usrerr("I don't speak SMTP");
691 				ExitStat = EX_USAGE;
692 				break;
693 #endif /* !SMTP */
694 
695 			  case MD_INITALIAS:
696 			  case MD_DELIVER:
697 			  case MD_VERIFY:
698 			  case MD_TEST:
699 			  case MD_PRINT:
700 			  case MD_HOSTSTAT:
701 			  case MD_PURGESTAT:
702 			  case MD_ARPAFTP:
703 				OpMode = j;
704 				break;
705 
706 			  case MD_FREEZE:
707 				usrerr("Frozen configurations unsupported");
708 				ExitStat = EX_USAGE;
709 				break;
710 
711 			  default:
712 				usrerr("Invalid operation mode %c", j);
713 				ExitStat = EX_USAGE;
714 				break;
715 			}
716 			break;
717 
718 		  case 'B':	/* body type */
719 			CurEnv->e_bodytype = newstr(optarg);
720 			break;
721 
722 		  case 'C':	/* select configuration file (already done) */
723 			if (RealUid != 0)
724 				warn_C_flag = TRUE;
725 			ConfFile = newstr(optarg);
726 			dp = drop_privileges(TRUE);
727 			setstat(dp);
728 			safecf = FALSE;
729 			break;
730 
731 		  case 'd':	/* debugging -- already done */
732 			break;
733 
734 		  case 'f':	/* from address */
735 		  case 'r':	/* obsolete -f flag */
736 			if (from != NULL)
737 			{
738 				usrerr("More than one \"from\" person");
739 				ExitStat = EX_USAGE;
740 				break;
741 			}
742 			from = newstr(denlstring(optarg, TRUE, TRUE));
743 			if (strcmp(RealUserName, from) != 0)
744 				warn_f_flag = j;
745 			break;
746 
747 		  case 'F':	/* set full name */
748 			FullName = newstr(optarg);
749 			break;
750 
751 		  case 'G':	/* relay (gateway) submission */
752 			/* already set */
753 			break;
754 
755 		  case 'h':	/* hop count */
756 			CurEnv->e_hopcount = (short) strtol(optarg, &ep, 10);
757 			if (*ep)
758 			{
759 				usrerr("Bad hop count (%s)", optarg);
760 				ExitStat = EX_USAGE;
761 			}
762 			break;
763 
764 		  case 'L':	/* program label */
765 			/* already set */
766 			break;
767 
768 		  case 'n':	/* don't alias */
769 			NoAlias = TRUE;
770 			break;
771 
772 		  case 'N':	/* delivery status notifications */
773 			DefaultNotify |= QHASNOTIFY;
774 			define(macid("{dsn_notify}", NULL),
775 			       newstr(optarg), CurEnv);
776 			if (strcasecmp(optarg, "never") == 0)
777 				break;
778 			for (p = optarg; p != NULL; optarg = p)
779 			{
780 				p = strchr(p, ',');
781 				if (p != NULL)
782 					*p++ = '\0';
783 				if (strcasecmp(optarg, "success") == 0)
784 					DefaultNotify |= QPINGONSUCCESS;
785 				else if (strcasecmp(optarg, "failure") == 0)
786 					DefaultNotify |= QPINGONFAILURE;
787 				else if (strcasecmp(optarg, "delay") == 0)
788 					DefaultNotify |= QPINGONDELAY;
789 				else
790 				{
791 					usrerr("Invalid -N argument");
792 					ExitStat = EX_USAGE;
793 				}
794 			}
795 			break;
796 
797 		  case 'o':	/* set option */
798 			setoption(*optarg, optarg + 1, FALSE, TRUE, CurEnv);
799 			break;
800 
801 		  case 'O':	/* set option (long form) */
802 			setoption(' ', optarg, FALSE, TRUE, CurEnv);
803 			break;
804 
805 		  case 'p':	/* set protocol */
806 			p = strchr(optarg, ':');
807 			if (p != NULL)
808 			{
809 				*p++ = '\0';
810 				if (*p != '\0')
811 				{
812 					ep = xalloc(strlen(p) + 1);
813 					cleanstrcpy(ep, p, MAXNAME);
814 					define('s', ep, CurEnv);
815 				}
816 			}
817 			if (*optarg != '\0')
818 			{
819 				ep = xalloc(strlen(optarg) + 1);
820 				cleanstrcpy(ep, optarg, MAXNAME);
821 				define('r', ep, CurEnv);
822 			}
823 			break;
824 
825 		  case 'q':	/* run queue files at intervals */
826 #if QUEUE
827 			/* sanity check */
828 			if (OpMode != MD_DELIVER &&
829 			    OpMode != MD_DAEMON &&
830 			    OpMode != MD_FGDAEMON &&
831 			    OpMode != MD_PRINT &&
832 			    OpMode != MD_QUEUERUN)
833 			{
834 				usrerr("Can not use -q with -b%c", OpMode);
835 				ExitStat = EX_USAGE;
836 				break;
837 			}
838 
839 			/* don't override -bd, -bD or -bp */
840 			if (OpMode == MD_DELIVER)
841 				OpMode = MD_QUEUERUN;
842 
843 			FullName = NULL;
844 
845 			switch (optarg[0])
846 			{
847 			  case 'I':
848 				new = (QUEUE_CHAR *) xalloc(sizeof *new);
849 				new->queue_match = newstr(&optarg[1]);
850 				new->queue_next = QueueLimitId;
851 				QueueLimitId = new;
852 				break;
853 
854 			  case 'R':
855 				new = (QUEUE_CHAR *) xalloc(sizeof *new);
856 				new->queue_match = newstr(&optarg[1]);
857 				new->queue_next = QueueLimitRecipient;
858 				QueueLimitRecipient = new;
859 				break;
860 
861 			  case 'S':
862 				new = (QUEUE_CHAR *) xalloc(sizeof *new);
863 				new->queue_match = newstr(&optarg[1]);
864 				new->queue_next = QueueLimitSender;
865 				QueueLimitSender = new;
866 				break;
867 
868 			  default:
869 				i = Errors;
870 				QueueIntvl = convtime(optarg, 'm');
871 
872 				/* check for bad conversion */
873 				if (i < Errors)
874 					ExitStat = EX_USAGE;
875 				break;
876 			}
877 #else /* QUEUE */
878 			usrerr("I don't know about queues");
879 			ExitStat = EX_USAGE;
880 #endif /* QUEUE */
881 			break;
882 
883 		  case 'R':	/* DSN RET: what to return */
884 			if (bitset(EF_RET_PARAM, CurEnv->e_flags))
885 			{
886 				usrerr("Duplicate -R flag");
887 				ExitStat = EX_USAGE;
888 				break;
889 			}
890 			CurEnv->e_flags |= EF_RET_PARAM;
891 			if (strcasecmp(optarg, "hdrs") == 0)
892 				CurEnv->e_flags |= EF_NO_BODY_RETN;
893 			else if (strcasecmp(optarg, "full") != 0)
894 			{
895 				usrerr("Invalid -R value");
896 				ExitStat = EX_USAGE;
897 			}
898 			define(macid("{dsn_ret}", NULL),
899 			       newstr(optarg), CurEnv);
900 			break;
901 
902 		  case 't':	/* read recipients from message */
903 			GrabTo = TRUE;
904 			break;
905 
906 		  case 'U':	/* initial (user) submission */
907 			/* already set */
908 			break;
909 
910 		  case 'V':	/* DSN ENVID: set "original" envelope id */
911 			if (!xtextok(optarg))
912 			{
913 				usrerr("Invalid syntax in -V flag");
914 				ExitStat = EX_USAGE;
915 			}
916 			else
917 			{
918 				CurEnv->e_envid = newstr(optarg);
919 				define(macid("{dsn_envid}", NULL),
920 				       newstr(optarg), CurEnv);
921 			}
922 			break;
923 
924 		  case 'X':	/* traffic log file */
925 			dp = drop_privileges(TRUE);
926 			setstat(dp);
927 			if (stat(optarg, &traf_st) == 0 &&
928 			    S_ISFIFO(traf_st.st_mode))
929 				TrafficLogFile = fopen(optarg, "w");
930 			else
931 				TrafficLogFile = fopen(optarg, "a");
932 			if (TrafficLogFile == NULL)
933 			{
934 				syserr("cannot open %s", optarg);
935 				ExitStat = EX_CANTCREAT;
936 				break;
937 			}
938 #if HASSETVBUF
939 			(void) setvbuf(TrafficLogFile, NULL, _IOLBF, 0);
940 #else /* HASSETVBUF */
941 			(void) setlinebuf(TrafficLogFile);
942 #endif /* HASSETVBUF */
943 			break;
944 
945 			/* compatibility flags */
946 		  case 'c':	/* connect to non-local mailers */
947 		  case 'i':	/* don't let dot stop me */
948 		  case 'm':	/* send to me too */
949 		  case 'T':	/* set timeout interval */
950 		  case 'v':	/* give blow-by-blow description */
951 			setoption(j, "T", FALSE, TRUE, CurEnv);
952 			break;
953 
954 		  case 'e':	/* error message disposition */
955 		  case 'M':	/* define macro */
956 			setoption(j, optarg, FALSE, TRUE, CurEnv);
957 			break;
958 
959 		  case 's':	/* save From lines in headers */
960 			setoption('f', "T", FALSE, TRUE, CurEnv);
961 			break;
962 
963 #ifdef DBM
964 		  case 'I':	/* initialize alias DBM file */
965 			OpMode = MD_INITALIAS;
966 			break;
967 #endif /* DBM */
968 
969 #if defined(__osf__) || defined(_AIX3)
970 		  case 'x':	/* random flag that OSF/1 & AIX mailx passes */
971 			break;
972 #endif /* defined(__osf__) || defined(_AIX3) */
973 #if defined(sony_news)
974 		  case 'E':
975 		  case 'J':	/* ignore flags for Japanese code conversion
976 				   implemented on Sony NEWS */
977 			break;
978 #endif /* defined(sony_news) */
979 
980 		  default:
981 			finis(TRUE, EX_USAGE);
982 			break;
983 		}
984 	}
985 	av += optind;
986 
987 	if (bitset(SUBMIT_MTA, SubmitMode) &&
988 	    bitset(SUBMIT_MSA, SubmitMode))
989 	{
990 		/* sanity check */
991 		errno = 0;	/* reset to avoid bogus error messages */
992 		syserr("Cannot use both -G and -U together");
993 	}
994 	else if (bitset(SUBMIT_MTA, SubmitMode))
995 		define(macid("{daemon_flags}", NULL), "CC f", CurEnv);
996 	else if (bitset(SUBMIT_MSA, SubmitMode))
997 	{
998 		define(macid("{daemon_flags}", NULL), "c u", CurEnv);
999 
1000 		/* check for wrong OpMode */
1001 		if (OpMode != MD_DELIVER && OpMode != MD_SMTP)
1002 		{
1003 			errno = 0;	/* reset to avoid bogus error msgs */
1004 			syserr("Cannot use -U and -b%c", OpMode);
1005 		}
1006 	}
1007 	else
1008 	{
1009 #if _FFR_DEFAULT_SUBMIT_TO_MSA
1010 		define(macid("{daemon_flags}", NULL), "c u", CurEnv);
1011 #else /* _FFR_DEFAULT_SUBMIT_TO_MSA */
1012 		/* EMPTY */
1013 #endif /* _FFR_DEFAULT_SUBMIT_TO_MSA */
1014 	}
1015 
1016 	/*
1017 	**  Do basic initialization.
1018 	**	Read system control file.
1019 	**	Extract special fields for local use.
1020 	*/
1021 
1022 	/* set up ${opMode} for use in config file */
1023 	{
1024 		char mbuf[2];
1025 
1026 		mbuf[0] = OpMode;
1027 		mbuf[1] = '\0';
1028 		define(MID_OPMODE, newstr(mbuf), CurEnv);
1029 	}
1030 
1031 #if XDEBUG
1032 	checkfd012("before readcf");
1033 #endif /* XDEBUG */
1034 	vendor_pre_defaults(CurEnv);
1035 
1036 	readcf(getcfname(), safecf, CurEnv);
1037 	ConfigFileRead = TRUE;
1038 	vendor_post_defaults(CurEnv);
1039 
1040 	/* Remove the ability for a normal user to send signals */
1041 	if (RealUid != 0 &&
1042 	    RealUid != geteuid())
1043 	{
1044 		uid_t new_uid = geteuid();
1045 
1046 #if HASSETREUID
1047 		/*
1048 		**  Since we can differentiate between uid and euid,
1049 		**  make the uid a different user so the real user
1050 		**  can't send signals.  However, it doesn't need to be
1051 		**  root (euid has root).
1052 		*/
1053 
1054 		if (new_uid == 0)
1055 			new_uid = DefUid;
1056 		if (tTd(47, 5))
1057 			dprintf("Changing real uid to %d\n", (int) new_uid);
1058 		if (setreuid(new_uid, geteuid()) < 0)
1059 		{
1060 			syserr("main: setreuid(%d, %d) failed",
1061 			       (int) new_uid, (int) geteuid());
1062 			finis(FALSE, EX_OSERR);
1063 			/* NOTREACHED */
1064 		}
1065 		if (tTd(47, 10))
1066 			dprintf("Now running as e/ruid %d:%d\n",
1067 				(int) geteuid(), (int) getuid());
1068 #else /* HASSETREUID */
1069 		/*
1070 		**  Have to change both effective and real so need to
1071 		**  change them both to effective to keep privs.
1072 		*/
1073 
1074 		if (tTd(47, 5))
1075 			dprintf("Changing uid to %d\n", (int) new_uid);
1076 		if (setuid(new_uid) < 0)
1077 		{
1078 			syserr("main: setuid(%d) failed", (int) new_uid);
1079 			finis(FALSE, EX_OSERR);
1080 			/* NOTREACHED */
1081 		}
1082 		if (tTd(47, 10))
1083 			dprintf("Now running as e/ruid %d:%d\n",
1084 				(int) geteuid(), (int) getuid());
1085 #endif /* HASSETREUID */
1086 	}
1087 
1088 	/* set up the basic signal handlers */
1089 	if (setsignal(SIGINT, SIG_IGN) != SIG_IGN)
1090 		(void) setsignal(SIGINT, intsig);
1091 	(void) setsignal(SIGTERM, intsig);
1092 
1093 	/* Enforce use of local time (null string overrides this) */
1094 	if (TimeZoneSpec == NULL)
1095 		unsetenv("TZ");
1096 	else if (TimeZoneSpec[0] != '\0')
1097 		setuserenv("TZ", TimeZoneSpec);
1098 	else
1099 		setuserenv("TZ", NULL);
1100 	tzset();
1101 
1102 	/* avoid denial-of-service attacks */
1103 	resetlimits();
1104 
1105 	if (OpMode != MD_DAEMON && OpMode != MD_FGDAEMON)
1106 	{
1107 		/* drop privileges -- daemon mode done after socket/bind */
1108 		dp = drop_privileges(FALSE);
1109 		setstat(dp);
1110 	}
1111 
1112 #if NAMED_BIND
1113 	_res.retry = TimeOuts.res_retry[RES_TO_DEFAULT];
1114 	_res.retrans = TimeOuts.res_retrans[RES_TO_DEFAULT];
1115 #endif /* NAMED_BIND */
1116 
1117 	/*
1118 	**  Find our real host name for future logging.
1119 	*/
1120 
1121 	authinfo = getauthinfo(STDIN_FILENO, &forged);
1122 	define('_', authinfo, CurEnv);
1123 
1124 	/* suppress error printing if errors mailed back or whatever */
1125 	if (CurEnv->e_errormode != EM_PRINT)
1126 		HoldErrs = TRUE;
1127 
1128 	/* set up the $=m class now, after .cf has a chance to redefine $m */
1129 	expand("\201m", jbuf, sizeof jbuf, CurEnv);
1130 	if (jbuf[0] != '\0')
1131 		setclass('m', jbuf);
1132 
1133 	/* probe interfaces and locate any additional names */
1134 	if (!DontProbeInterfaces)
1135 		load_if_names();
1136 
1137 	if (tTd(0, 1))
1138 	{
1139 		dprintf("\n============ SYSTEM IDENTITY (after readcf) ============");
1140 		dprintf("\n      (short domain name) $w = ");
1141 		xputs(macvalue('w', CurEnv));
1142 		dprintf("\n  (canonical domain name) $j = ");
1143 		xputs(macvalue('j', CurEnv));
1144 		dprintf("\n         (subdomain name) $m = ");
1145 		xputs(macvalue('m', CurEnv));
1146 		dprintf("\n              (node name) $k = ");
1147 		xputs(macvalue('k', CurEnv));
1148 		dprintf("\n========================================================\n\n");
1149 	}
1150 
1151 	/*
1152 	**  Do more command line checking -- these are things that
1153 	**  have to modify the results of reading the config file.
1154 	*/
1155 
1156 	/* process authorization warnings from command line */
1157 	if (warn_C_flag)
1158 		auth_warning(CurEnv, "Processed by %s with -C %s",
1159 			RealUserName, ConfFile);
1160 	if (Warn_Q_option && !wordinclass(RealUserName, 't'))
1161 		auth_warning(CurEnv, "Processed from queue %s", QueueDir);
1162 
1163 	/* check body type for legality */
1164 	if (CurEnv->e_bodytype == NULL)
1165 		/* EMPTY */
1166 		/* nothing */ ;
1167 	else if (strcasecmp(CurEnv->e_bodytype, "7BIT") == 0)
1168 		SevenBitInput = TRUE;
1169 	else if (strcasecmp(CurEnv->e_bodytype, "8BITMIME") == 0)
1170 		SevenBitInput = FALSE;
1171 	else
1172 	{
1173 		usrerr("Illegal body type %s", CurEnv->e_bodytype);
1174 		CurEnv->e_bodytype = NULL;
1175 	}
1176 
1177 	/* tweak default DSN notifications */
1178 	if (DefaultNotify == 0)
1179 		DefaultNotify = QPINGONFAILURE|QPINGONDELAY;
1180 
1181 	/* be sure we don't pick up bogus HOSTALIASES environment variable */
1182 	if (OpMode == MD_QUEUERUN && RealUid != 0)
1183 		(void) unsetenv("HOSTALIASES");
1184 
1185 	/* check for sane configuration level */
1186 	if (ConfigLevel > MAXCONFIGLEVEL)
1187 	{
1188 		syserr("Warning: .cf version level (%d) exceeds sendmail version %s functionality (%d)",
1189 			ConfigLevel, Version, MAXCONFIGLEVEL);
1190 	}
1191 
1192 	/* need MCI cache to have persistence */
1193 	if (HostStatDir != NULL && MaxMciCache == 0)
1194 	{
1195 		HostStatDir = NULL;
1196 		printf("Warning: HostStatusDirectory disabled with ConnectionCacheSize = 0\n");
1197 	}
1198 
1199 	/* need HostStatusDir in order to have SingleThreadDelivery */
1200 	if (SingleThreadDelivery && HostStatDir == NULL)
1201 	{
1202 		SingleThreadDelivery = FALSE;
1203 		printf("Warning: HostStatusDirectory required for SingleThreadDelivery\n");
1204 	}
1205 
1206 	/* check for permissions */
1207 	if ((OpMode == MD_DAEMON ||
1208 	     OpMode == MD_FGDAEMON ||
1209 	     OpMode == MD_PURGESTAT) &&
1210 	    RealUid != 0 &&
1211 	    RealUid != TrustedUid)
1212 	{
1213 		if (LogLevel > 1)
1214 			sm_syslog(LOG_ALERT, NOQID,
1215 				  "user %d attempted to %s",
1216 				  RealUid,
1217 				  OpMode != MD_PURGESTAT ? "run daemon"
1218 							 : "purge host status");
1219 		usrerr("Permission denied");
1220 		finis(FALSE, EX_USAGE);
1221 	}
1222 	if (OpMode == MD_INITALIAS &&
1223 	    RealUid != 0 &&
1224 	    RealUid != TrustedUid &&
1225 	    !wordinclass(RealUserName, 't'))
1226 	{
1227 		if (LogLevel > 1)
1228 			sm_syslog(LOG_ALERT, NOQID,
1229 				  "user %d attempted to rebuild the alias map",
1230 				  RealUid);
1231 		usrerr("Permission denied");
1232 		finis(FALSE, EX_USAGE);
1233 	}
1234 
1235 	if (MeToo)
1236 		BlankEnvelope.e_flags |= EF_METOO;
1237 
1238 	switch (OpMode)
1239 	{
1240 	  case MD_TEST:
1241 		/* don't have persistent host status in test mode */
1242 		HostStatDir = NULL;
1243 		if (Verbose == 0)
1244 			Verbose = 2;
1245 		CurEnv->e_errormode = EM_PRINT;
1246 		HoldErrs = FALSE;
1247 		break;
1248 
1249 	  case MD_VERIFY:
1250 		CurEnv->e_errormode = EM_PRINT;
1251 		HoldErrs = FALSE;
1252 
1253 		/* arrange to exit cleanly on hangup signal */
1254 		if (setsignal(SIGHUP, SIG_IGN) == (sigfunc_t) SIG_DFL)
1255 			(void) setsignal(SIGHUP, intsig);
1256 		break;
1257 
1258 	  case MD_FGDAEMON:
1259 		run_in_foreground = TRUE;
1260 		OpMode = MD_DAEMON;
1261 		/* FALLTHROUGH */
1262 
1263 	  case MD_DAEMON:
1264 		vendor_daemon_setup(CurEnv);
1265 
1266 		/* remove things that don't make sense in daemon mode */
1267 		FullName = NULL;
1268 		GrabTo = FALSE;
1269 
1270 		/* arrange to restart on hangup signal */
1271 		if (SaveArgv[0] == NULL || SaveArgv[0][0] != '/')
1272 			sm_syslog(LOG_WARNING, NOQID,
1273 				  "daemon invoked without full pathname; kill -1 won't work");
1274 		(void) setsignal(SIGTERM, term_daemon);
1275 		break;
1276 
1277 	  case MD_INITALIAS:
1278 		Verbose = 2;
1279 		CurEnv->e_errormode = EM_PRINT;
1280 		HoldErrs = FALSE;
1281 		/* FALLTHROUGH */
1282 
1283 	  default:
1284 		/* arrange to exit cleanly on hangup signal */
1285 		if (setsignal(SIGHUP, SIG_IGN) == (sigfunc_t) SIG_DFL)
1286 			(void) setsignal(SIGHUP, intsig);
1287 		break;
1288 	}
1289 
1290 	/* special considerations for FullName */
1291 	if (FullName != NULL)
1292 	{
1293 		char *full = NULL;
1294 
1295 		/* full names can't have newlines */
1296 		if (strchr(FullName, '\n') != NULL)
1297 		{
1298 			full = newstr(denlstring(FullName, TRUE, TRUE));
1299 			FullName = full;
1300 		}
1301 
1302 		/* check for characters that may have to be quoted */
1303 		if (!rfc822_string(FullName))
1304 		{
1305 			/*
1306 			**  Quote a full name with special characters
1307 			**  as a comment so crackaddr() doesn't destroy
1308 			**  the name portion of the address.
1309 			*/
1310 
1311 			FullName = addquotes(FullName);
1312 			if (full != NULL)
1313 				sm_free(full);
1314 		}
1315 	}
1316 
1317 	/* do heuristic mode adjustment */
1318 	if (Verbose)
1319 	{
1320 		/* turn off noconnect option */
1321 		setoption('c', "F", TRUE, FALSE, CurEnv);
1322 
1323 		/* turn on interactive delivery */
1324 		setoption('d', "", TRUE, FALSE, CurEnv);
1325 	}
1326 
1327 #ifdef VENDOR_CODE
1328 	/* check for vendor mismatch */
1329 	if (VendorCode != VENDOR_CODE)
1330 	{
1331 		message("Warning: .cf file vendor code mismatch: sendmail expects vendor %s, .cf file vendor is %s",
1332 			getvendor(VENDOR_CODE), getvendor(VendorCode));
1333 	}
1334 #endif /* VENDOR_CODE */
1335 
1336 	/* check for out of date configuration level */
1337 	if (ConfigLevel < MAXCONFIGLEVEL)
1338 	{
1339 		message("Warning: .cf file is out of date: sendmail %s supports version %d, .cf file is version %d",
1340 			Version, MAXCONFIGLEVEL, ConfigLevel);
1341 	}
1342 
1343 	if (ConfigLevel < 3)
1344 		UseErrorsTo = TRUE;
1345 
1346 	/* set options that were previous macros */
1347 	if (SmtpGreeting == NULL)
1348 	{
1349 		if (ConfigLevel < 7 && (p = macvalue('e', CurEnv)) != NULL)
1350 			SmtpGreeting = newstr(p);
1351 		else
1352 			SmtpGreeting = "\201j Sendmail \201v ready at \201b";
1353 	}
1354 	if (UnixFromLine == NULL)
1355 	{
1356 		if (ConfigLevel < 7 && (p = macvalue('l', CurEnv)) != NULL)
1357 			UnixFromLine = newstr(p);
1358 		else
1359 			UnixFromLine = "From \201g  \201d";
1360 	}
1361 	SmtpError[0] = '\0';
1362 
1363 	/* our name for SMTP codes */
1364 	expand("\201j", jbuf, sizeof jbuf, CurEnv);
1365 	if (jbuf[0] == '\0')
1366 		MyHostName = newstr("localhost");
1367 	else
1368 		MyHostName = jbuf;
1369 	if (strchr(MyHostName, '.') == NULL)
1370 		message("WARNING: local host name (%s) is not qualified; fix $j in config file",
1371 			MyHostName);
1372 
1373 	/* make certain that this name is part of the $=w class */
1374 	setclass('w', MyHostName);
1375 
1376 	/* the indices of built-in mailers */
1377 	st = stab("local", ST_MAILER, ST_FIND);
1378 	if (st != NULL)
1379 		LocalMailer = st->s_mailer;
1380 	else if (OpMode != MD_TEST || !warn_C_flag)
1381 		syserr("No local mailer defined");
1382 
1383 	st = stab("prog", ST_MAILER, ST_FIND);
1384 	if (st == NULL)
1385 		syserr("No prog mailer defined");
1386 	else
1387 	{
1388 		ProgMailer = st->s_mailer;
1389 		clrbitn(M_MUSER, ProgMailer->m_flags);
1390 	}
1391 
1392 	st = stab("*file*", ST_MAILER, ST_FIND);
1393 	if (st == NULL)
1394 		syserr("No *file* mailer defined");
1395 	else
1396 	{
1397 		FileMailer = st->s_mailer;
1398 		clrbitn(M_MUSER, FileMailer->m_flags);
1399 	}
1400 
1401 	st = stab("*include*", ST_MAILER, ST_FIND);
1402 	if (st == NULL)
1403 		syserr("No *include* mailer defined");
1404 	else
1405 		InclMailer = st->s_mailer;
1406 
1407 	if (ConfigLevel < 6)
1408 	{
1409 		/* heuristic tweaking of local mailer for back compat */
1410 		if (LocalMailer != NULL)
1411 		{
1412 			setbitn(M_ALIASABLE, LocalMailer->m_flags);
1413 			setbitn(M_HASPWENT, LocalMailer->m_flags);
1414 			setbitn(M_TRYRULESET5, LocalMailer->m_flags);
1415 			setbitn(M_CHECKINCLUDE, LocalMailer->m_flags);
1416 			setbitn(M_CHECKPROG, LocalMailer->m_flags);
1417 			setbitn(M_CHECKFILE, LocalMailer->m_flags);
1418 			setbitn(M_CHECKUDB, LocalMailer->m_flags);
1419 		}
1420 		if (ProgMailer != NULL)
1421 			setbitn(M_RUNASRCPT, ProgMailer->m_flags);
1422 		if (FileMailer != NULL)
1423 			setbitn(M_RUNASRCPT, FileMailer->m_flags);
1424 	}
1425 	if (ConfigLevel < 7)
1426 	{
1427 		if (LocalMailer != NULL)
1428 			setbitn(M_VRFY250, LocalMailer->m_flags);
1429 		if (ProgMailer != NULL)
1430 			setbitn(M_VRFY250, ProgMailer->m_flags);
1431 		if (FileMailer != NULL)
1432 			setbitn(M_VRFY250, FileMailer->m_flags);
1433 	}
1434 
1435 	/* MIME Content-Types that cannot be transfer encoded */
1436 	setclass('n', "multipart/signed");
1437 
1438 	/* MIME message/xxx subtypes that can be treated as messages */
1439 	setclass('s', "rfc822");
1440 
1441 	/* MIME Content-Transfer-Encodings that can be encoded */
1442 	setclass('e', "7bit");
1443 	setclass('e', "8bit");
1444 	setclass('e', "binary");
1445 
1446 #ifdef USE_B_CLASS
1447 	/* MIME Content-Types that should be treated as binary */
1448 	setclass('b', "image");
1449 	setclass('b', "audio");
1450 	setclass('b', "video");
1451 	setclass('b', "application/octet-stream");
1452 #endif /* USE_B_CLASS */
1453 
1454 	/* MIME headers which have fields to check for overflow */
1455 	setclass(macid("{checkMIMEFieldHeaders}", NULL), "content-disposition");
1456 	setclass(macid("{checkMIMEFieldHeaders}", NULL), "content-type");
1457 
1458 	/* MIME headers to check for length overflow */
1459 	setclass(macid("{checkMIMETextHeaders}", NULL), "content-description");
1460 
1461 	/* MIME headers to check for overflow and rebalance */
1462 	setclass(macid("{checkMIMEHeaders}", NULL), "content-disposition");
1463 	setclass(macid("{checkMIMEHeaders}", NULL), "content-id");
1464 	setclass(macid("{checkMIMEHeaders}", NULL), "content-transfer-encoding");
1465 	setclass(macid("{checkMIMEHeaders}", NULL), "content-type");
1466 	setclass(macid("{checkMIMEHeaders}", NULL), "mime-version");
1467 
1468 	/* Macros to save in the qf file -- don't remove any */
1469 	setclass(macid("{persistentMacros}", NULL), "r");
1470 	setclass(macid("{persistentMacros}", NULL), "s");
1471 	setclass(macid("{persistentMacros}", NULL), "_");
1472 	setclass(macid("{persistentMacros}", NULL), "{if_addr}");
1473 	setclass(macid("{persistentMacros}", NULL), "{daemon_flags}");
1474 	setclass(macid("{persistentMacros}", NULL), "{client_flags}");
1475 
1476 	/* operate in queue directory */
1477 	if (QueueDir == NULL)
1478 	{
1479 		if (OpMode != MD_TEST)
1480 		{
1481 			syserr("QueueDirectory (Q) option must be set");
1482 			ExitStat = EX_CONFIG;
1483 		}
1484 	}
1485 	else
1486 	{
1487 		/*
1488 		**  If multiple queues wildcarded, use one for
1489 		**  the daemon's home. Note that this preconditions
1490 		**  a wildcarded QueueDir to a real pathname.
1491 		*/
1492 
1493 		if (OpMode != MD_TEST)
1494 			multiqueue_cache();
1495 	}
1496 
1497 	/* check host status directory for validity */
1498 	if (HostStatDir != NULL && !path_is_dir(HostStatDir, FALSE))
1499 	{
1500 		/* cannot use this value */
1501 		if (tTd(0, 2))
1502 			dprintf("Cannot use HostStatusDirectory = %s: %s\n",
1503 				HostStatDir, errstring(errno));
1504 		HostStatDir = NULL;
1505 	}
1506 
1507 #if QUEUE
1508 	if (OpMode == MD_QUEUERUN && RealUid != 0 &&
1509 	    bitset(PRIV_RESTRICTQRUN, PrivacyFlags))
1510 	{
1511 		struct stat stbuf;
1512 
1513 		/* check to see if we own the queue directory */
1514 		if (stat(".", &stbuf) < 0)
1515 			syserr("main: cannot stat %s", QueueDir);
1516 		if (stbuf.st_uid != RealUid)
1517 		{
1518 			/* nope, really a botch */
1519 			usrerr("You do not have permission to process the queue");
1520 			finis(FALSE, EX_NOPERM);
1521 		}
1522 	}
1523 #endif /* QUEUE */
1524 
1525 #if _FFR_MILTER
1526 	/* sanity checks on milter filters */
1527 	if (OpMode == MD_DAEMON || OpMode == MD_SMTP)
1528 		milter_parse_list(InputFilterList, InputFilters, MAXFILTERS);
1529 #endif /* _FFR_MILTER */
1530 
1531 
1532 	/* if we've had errors so far, exit now */
1533 	if (ExitStat != EX_OK && OpMode != MD_TEST)
1534 		finis(FALSE, ExitStat);
1535 
1536 #if XDEBUG
1537 	checkfd012("before main() initmaps");
1538 #endif /* XDEBUG */
1539 
1540 	/*
1541 	**  Do operation-mode-dependent initialization.
1542 	*/
1543 
1544 	switch (OpMode)
1545 	{
1546 	  case MD_PRINT:
1547 		/* print the queue */
1548 #if QUEUE
1549 		dropenvelope(CurEnv, TRUE);
1550 		(void) setsignal(SIGPIPE, quiesce);
1551 		printqueue();
1552 		finis(FALSE, EX_OK);
1553 #else /* QUEUE */
1554 		usrerr("No queue to print");
1555 		finis(FALSE, EX_UNAVAILABLE);
1556 #endif /* QUEUE */
1557 		break;
1558 
1559 	  case MD_HOSTSTAT:
1560 		(void) setsignal(SIGPIPE, quiesce);
1561 		(void) mci_traverse_persistent(mci_print_persistent, NULL);
1562 		finis(FALSE, EX_OK);
1563 		break;
1564 
1565 	  case MD_PURGESTAT:
1566 		(void) mci_traverse_persistent(mci_purge_persistent, NULL);
1567 		finis(FALSE, EX_OK);
1568 		break;
1569 
1570 	  case MD_INITALIAS:
1571 		/* initialize maps */
1572 		initmaps();
1573 		finis(FALSE, ExitStat);
1574 		break;
1575 
1576 	  case MD_SMTP:
1577 	  case MD_DAEMON:
1578 		/* reset DSN parameters */
1579 		DefaultNotify = QPINGONFAILURE|QPINGONDELAY;
1580 		define(macid("{dsn_notify}", NULL), NULL, CurEnv);
1581 		CurEnv->e_envid = NULL;
1582 		define(macid("{dsn_envid}", NULL), NULL, CurEnv);
1583 		CurEnv->e_flags &= ~(EF_RET_PARAM|EF_NO_BODY_RETN);
1584 		define(macid("{dsn_ret}", NULL), NULL, CurEnv);
1585 
1586 		/* don't open maps for daemon -- done below in child */
1587 		break;
1588 	}
1589 
1590 	if (tTd(0, 15))
1591 	{
1592 		/* print configuration table (or at least part of it) */
1593 		if (tTd(0, 90))
1594 			printrules();
1595 		for (i = 0; i < MAXMAILERS; i++)
1596 		{
1597 			if (Mailer[i] != NULL)
1598 				printmailer(Mailer[i]);
1599 		}
1600 	}
1601 
1602 	/*
1603 	**  Switch to the main envelope.
1604 	*/
1605 
1606 	CurEnv = newenvelope(&MainEnvelope, CurEnv);
1607 	MainEnvelope.e_flags = BlankEnvelope.e_flags;
1608 
1609 	/*
1610 	**  If test mode, read addresses from stdin and process.
1611 	*/
1612 
1613 	if (OpMode == MD_TEST)
1614 	{
1615 		char buf[MAXLINE];
1616 
1617 #if _FFR_TESTMODE_DROP_PRIVS
1618 		dp = drop_privileges(TRUE);
1619 		if (dp != EX_OK)
1620 		{
1621 			CurEnv->e_id = NULL;
1622 			finis(TRUE, dp);
1623 		}
1624 #endif /* _FFR_TESTMODE_DROP_PRIVS */
1625 
1626 		if (isatty(fileno(stdin)))
1627 			Verbose = 2;
1628 
1629 		if (Verbose)
1630 		{
1631 			printf("ADDRESS TEST MODE (ruleset 3 NOT automatically invoked)\n");
1632 			printf("Enter <ruleset> <address>\n");
1633 		}
1634 		if (setjmp(TopFrame) > 0)
1635 			printf("\n");
1636 		(void) setsignal(SIGINT, intindebug);
1637 		for (;;)
1638 		{
1639 			if (Verbose == 2)
1640 				printf("> ");
1641 			(void) fflush(stdout);
1642 			if (fgets(buf, sizeof buf, stdin) == NULL)
1643 				testmodeline("/quit", CurEnv);
1644 			p = strchr(buf, '\n');
1645 			if (p != NULL)
1646 				*p = '\0';
1647 			if (Verbose < 2)
1648 				printf("> %s\n", buf);
1649 			testmodeline(buf, CurEnv);
1650 		}
1651 	}
1652 
1653 #if SMTP
1654 # if STARTTLS
1655 	tls_ok = init_tls_library();
1656 # endif /* STARTTLS */
1657 #endif /* SMTP */
1658 
1659 #if QUEUE
1660 	/*
1661 	**  If collecting stuff from the queue, go start doing that.
1662 	*/
1663 
1664 	if (OpMode == MD_QUEUERUN && QueueIntvl == 0)
1665 	{
1666 # if SMTP
1667 #  if STARTTLS
1668 		if (tls_ok
1669 		   )
1670 		{
1671 			/* init TLS for client, ignore result for now */
1672 			(void) initclttls();
1673 		}
1674 #  endif /* STARTTLS */
1675 # endif /* SMTP */
1676 		(void) runqueue(FALSE, Verbose);
1677 		finis(TRUE, ExitStat);
1678 	}
1679 #endif /* QUEUE */
1680 
1681 # if SASL
1682 	if (OpMode == MD_SMTP || OpMode == MD_DAEMON)
1683 	{
1684 		/* give a syserr or just disable AUTH ? */
1685 		if ((i = sasl_server_init(srvcallbacks, "Sendmail")) != SASL_OK)
1686 			syserr("!sasl_server_init failed! [%s]",
1687 			       sasl_errstring(i, NULL, NULL));
1688 	}
1689 # endif /* SASL */
1690 
1691 	/*
1692 	**  If a daemon, wait for a request.
1693 	**	getrequests will always return in a child.
1694 	**	If we should also be processing the queue, start
1695 	**		doing it in background.
1696 	**	We check for any errors that might have happened
1697 	**		during startup.
1698 	*/
1699 
1700 	if (OpMode == MD_DAEMON || QueueIntvl != 0)
1701 	{
1702 		char dtype[200];
1703 
1704 		if (!run_in_foreground && !tTd(99, 100))
1705 		{
1706 			/* put us in background */
1707 			i = fork();
1708 			if (i < 0)
1709 				syserr("daemon: cannot fork");
1710 			if (i != 0)
1711 				finis(FALSE, EX_OK);
1712 
1713 			/* disconnect from our controlling tty */
1714 			disconnect(2, CurEnv);
1715 		}
1716 
1717 		dtype[0] = '\0';
1718 		if (OpMode == MD_DAEMON)
1719 			(void) strlcat(dtype, "+SMTP", sizeof dtype);
1720 		if (QueueIntvl != 0)
1721 		{
1722 			(void) strlcat(dtype, "+queueing@", sizeof dtype);
1723 			(void) strlcat(dtype, pintvl(QueueIntvl, TRUE),
1724 				       sizeof dtype);
1725 		}
1726 		if (tTd(0, 1))
1727 			(void) strlcat(dtype, "+debugging", sizeof dtype);
1728 
1729 		sm_syslog(LOG_INFO, NOQID,
1730 			  "starting daemon (%s): %s", Version, dtype + 1);
1731 #ifdef XLA
1732 		xla_create_file();
1733 #endif /* XLA */
1734 
1735 		/* save daemon type in a macro for possible PidFile use */
1736 		define(macid("{daemon_info}", NULL),
1737 		       newstr(dtype + 1), &BlankEnvelope);
1738 
1739 		/* save queue interval in a macro for possible PidFile use */
1740 		define(macid("{queue_interval}", NULL),
1741 		       newstr(pintvl(QueueIntvl, TRUE)), CurEnv);
1742 
1743 #if QUEUE
1744 		if (QueueIntvl != 0)
1745 		{
1746 			(void) runqueue(TRUE, FALSE);
1747 			if (OpMode != MD_DAEMON)
1748 			{
1749 				/* write the pid to file */
1750 				log_sendmail_pid(CurEnv);
1751 				(void) setsignal(SIGTERM, term_daemon);
1752 				for (;;)
1753 				{
1754 					(void) pause();
1755 					if (ShutdownRequest != NULL)
1756 						shutdown_daemon();
1757 					else if (DoQueueRun)
1758 						(void) runqueue(TRUE, FALSE);
1759 				}
1760 			}
1761 		}
1762 #endif /* QUEUE */
1763 		dropenvelope(CurEnv, TRUE);
1764 
1765 #if DAEMON
1766 # if STARTTLS
1767 		/* init TLS for server, ignore result for now */
1768 		(void) initsrvtls();
1769 # endif /* STARTTLS */
1770 		p_flags = getrequests(CurEnv);
1771 
1772 		/* drop privileges */
1773 		(void) drop_privileges(FALSE);
1774 
1775 		/* at this point we are in a child: reset state */
1776 		(void) newenvelope(CurEnv, CurEnv);
1777 
1778 		/*
1779 		**  Get authentication data
1780 		*/
1781 
1782 		authinfo = getauthinfo(fileno(InChannel), &forged);
1783 		define('_', authinfo, &BlankEnvelope);
1784 #endif /* DAEMON */
1785 	}
1786 
1787 	if (LogLevel > 9)
1788 	{
1789 		/* log connection information */
1790 		sm_syslog(LOG_INFO, NULL, "connect from %.100s", authinfo);
1791 	}
1792 
1793 #if SMTP
1794 	/*
1795 	**  If running SMTP protocol, start collecting and executing
1796 	**  commands.  This will never return.
1797 	*/
1798 
1799 	if (OpMode == MD_SMTP || OpMode == MD_DAEMON)
1800 	{
1801 		char pbuf[20];
1802 
1803 		/*
1804 		**  Save some macros for check_* rulesets.
1805 		*/
1806 
1807 		if (forged)
1808 		{
1809 			char ipbuf[103];
1810 
1811 			(void) snprintf(ipbuf, sizeof ipbuf, "[%.100s]",
1812 					anynet_ntoa(&RealHostAddr));
1813 			define(macid("{client_name}", NULL),
1814 			       newstr(ipbuf), &BlankEnvelope);
1815 			define(macid("{client_resolve}", NULL),
1816 			       "FORGED", &BlankEnvelope);
1817 		}
1818 		else
1819 			define(macid("{client_name}", NULL), RealHostName,
1820 			       &BlankEnvelope);
1821 		define(macid("{client_addr}", NULL),
1822 		       newstr(anynet_ntoa(&RealHostAddr)), &BlankEnvelope);
1823 		(void)sm_getla(&BlankEnvelope);
1824 
1825 		switch(RealHostAddr.sa.sa_family)
1826 		{
1827 # if NETINET
1828 		  case AF_INET:
1829 			(void) snprintf(pbuf, sizeof pbuf, "%d",
1830 					RealHostAddr.sin.sin_port);
1831 			break;
1832 # endif /* NETINET */
1833 # if NETINET6
1834 		  case AF_INET6:
1835 			(void) snprintf(pbuf, sizeof pbuf, "%d",
1836 					RealHostAddr.sin6.sin6_port);
1837 			break;
1838 # endif /* NETINET6 */
1839 		  default:
1840 			(void) snprintf(pbuf, sizeof pbuf, "0");
1841 			break;
1842 		}
1843 		define(macid("{client_port}", NULL),
1844 		       newstr(pbuf), &BlankEnvelope);
1845 
1846 		if (OpMode == MD_DAEMON)
1847 		{
1848 			/* validate the connection */
1849 			HoldErrs = TRUE;
1850 			nullserver = validate_connection(&RealHostAddr,
1851 							 RealHostName, CurEnv);
1852 			HoldErrs = FALSE;
1853 		}
1854 		else if (p_flags == NULL)
1855 		{
1856 			p_flags = (BITMAP256 *) xalloc(sizeof *p_flags);
1857 			clrbitmap(p_flags);
1858 		}
1859 # if STARTTLS
1860 		if (OpMode == MD_SMTP)
1861 			(void) initsrvtls();
1862 # endif /* STARTTLS */
1863 
1864 
1865 		smtp(nullserver, *p_flags, CurEnv);
1866 	}
1867 #endif /* SMTP */
1868 
1869 	clearenvelope(CurEnv, FALSE);
1870 	if (OpMode == MD_VERIFY)
1871 	{
1872 		set_delivery_mode(SM_VERIFY, CurEnv);
1873 		PostMasterCopy = NULL;
1874 	}
1875 	else
1876 	{
1877 		/* interactive -- all errors are global */
1878 		CurEnv->e_flags |= EF_GLOBALERRS|EF_LOGSENDER;
1879 	}
1880 
1881 	/*
1882 	**  Do basic system initialization and set the sender
1883 	*/
1884 
1885 	initsys(CurEnv);
1886 	define(macid("{ntries}", NULL), "0", CurEnv);
1887 	setsender(from, CurEnv, NULL, '\0', FALSE);
1888 	if (warn_f_flag != '\0' && !wordinclass(RealUserName, 't') &&
1889 	    (!bitnset(M_LOCALMAILER, CurEnv->e_from.q_mailer->m_flags) ||
1890 	     strcmp(CurEnv->e_from.q_user, RealUserName) != 0))
1891 	{
1892 		auth_warning(CurEnv, "%s set sender to %s using -%c",
1893 			RealUserName, from, warn_f_flag);
1894 #if SASL
1895 		auth = FALSE;
1896 #endif /* SASL */
1897 	}
1898 	if (auth)
1899 	{
1900 		char *fv;
1901 
1902 		/* set the initial sender for AUTH= to $f@$j */
1903 		fv = macvalue('f', CurEnv);
1904 		if (fv == NULL || *fv == '\0')
1905 			CurEnv->e_auth_param = NULL;
1906 		else
1907 		{
1908 			if (strchr(fv, '@') == NULL)
1909 			{
1910 				i = strlen(fv) + strlen(macvalue('j', CurEnv))
1911 				    + 2;
1912 				p = xalloc(i);
1913 				(void) snprintf(p, i, "%s@%s", fv,
1914 						macvalue('j', CurEnv));
1915 			}
1916 			else
1917 				p = newstr(fv);
1918 			CurEnv->e_auth_param = newstr(xtextify(p, "="));
1919 		}
1920 	}
1921 	if (macvalue('s', CurEnv) == NULL)
1922 		define('s', RealHostName, CurEnv);
1923 
1924 	if (*av == NULL && !GrabTo)
1925 	{
1926 		CurEnv->e_to = NULL;
1927 		CurEnv->e_flags |= EF_GLOBALERRS;
1928 		HoldErrs = FALSE;
1929 		SuperSafe = FALSE;
1930 		usrerr("Recipient names must be specified");
1931 
1932 		/* collect body for UUCP return */
1933 		if (OpMode != MD_VERIFY)
1934 			collect(InChannel, FALSE, NULL, CurEnv);
1935 		finis(TRUE, EX_USAGE);
1936 	}
1937 
1938 	/*
1939 	**  Scan argv and deliver the message to everyone.
1940 	*/
1941 
1942 	sendtoargv(av, CurEnv);
1943 
1944 	/* if we have had errors sofar, arrange a meaningful exit stat */
1945 	if (Errors > 0 && ExitStat == EX_OK)
1946 		ExitStat = EX_USAGE;
1947 
1948 #if _FFR_FIX_DASHT
1949 	/*
1950 	**  If using -t, force not sending to argv recipients, even
1951 	**  if they are mentioned in the headers.
1952 	*/
1953 
1954 	if (GrabTo)
1955 	{
1956 		ADDRESS *q;
1957 
1958 		for (q = CurEnv->e_sendqueue; q != NULL; q = q->q_next)
1959 			q->q_state = QS_REMOVED;
1960 	}
1961 #endif /* _FFR_FIX_DASHT */
1962 
1963 	/*
1964 	**  Read the input mail.
1965 	*/
1966 
1967 	CurEnv->e_to = NULL;
1968 	if (OpMode != MD_VERIFY || GrabTo)
1969 	{
1970 		int savederrors = Errors;
1971 		long savedflags = CurEnv->e_flags & EF_FATALERRS;
1972 
1973 		CurEnv->e_flags |= EF_GLOBALERRS;
1974 		CurEnv->e_flags &= ~EF_FATALERRS;
1975 		Errors = 0;
1976 		buffer_errors();
1977 		collect(InChannel, FALSE, NULL, CurEnv);
1978 
1979 		/* header checks failed */
1980 		if (Errors > 0)
1981 		{
1982 			/* Log who the mail would have gone to */
1983 			if (LogLevel > 8 && CurEnv->e_message != NULL &&
1984 			    !GrabTo)
1985 			{
1986 				ADDRESS *a;
1987 
1988 				for (a = CurEnv->e_sendqueue;
1989 				     a != NULL;
1990 				     a = a->q_next)
1991 				{
1992 					if (!QS_IS_UNDELIVERED(a->q_state))
1993 						continue;
1994 
1995 					CurEnv->e_to = a->q_paddr;
1996 					logdelivery(NULL, NULL, NULL,
1997 						    CurEnv->e_message,
1998 						    NULL, (time_t) 0, CurEnv);
1999 				}
2000 				CurEnv->e_to = NULL;
2001 			}
2002 			flush_errors(TRUE);
2003 			finis(TRUE, ExitStat);
2004 			/* NOTREACHED */
2005 			return -1;
2006 		}
2007 
2008 		/* bail out if message too large */
2009 		if (bitset(EF_CLRQUEUE, CurEnv->e_flags))
2010 		{
2011 			finis(TRUE, ExitStat != EX_OK ? ExitStat : EX_DATAERR);
2012 			/* NOTREACHED */
2013 			return -1;
2014 		}
2015 		Errors = savederrors;
2016 		CurEnv->e_flags |= savedflags;
2017 	}
2018 	errno = 0;
2019 
2020 	if (tTd(1, 1))
2021 		dprintf("From person = \"%s\"\n", CurEnv->e_from.q_paddr);
2022 
2023 	/*
2024 	**  Actually send everything.
2025 	**	If verifying, just ack.
2026 	*/
2027 
2028 	CurEnv->e_from.q_state = QS_SENDER;
2029 	if (tTd(1, 5))
2030 	{
2031 		dprintf("main: QS_SENDER ");
2032 		printaddr(&CurEnv->e_from, FALSE);
2033 	}
2034 	CurEnv->e_to = NULL;
2035 	CurrentLA = sm_getla(CurEnv);
2036 	GrabTo = FALSE;
2037 #if NAMED_BIND
2038 	_res.retry = TimeOuts.res_retry[RES_TO_FIRST];
2039 	_res.retrans = TimeOuts.res_retrans[RES_TO_FIRST];
2040 #endif /* NAMED_BIND */
2041 	sendall(CurEnv, SM_DEFAULT);
2042 
2043 	/*
2044 	**  All done.
2045 	**	Don't send return error message if in VERIFY mode.
2046 	*/
2047 
2048 	finis(TRUE, ExitStat);
2049 	/* NOTREACHED */
2050 	return ExitStat;
2051 }
2052 /*
2053 **  QUIESCE -- signal handler for SIGPIPE
2054 **
2055 **	Parameters:
2056 **		sig -- incoming signal.
2057 **
2058 **	Returns:
2059 **		none.
2060 **
2061 **	Side Effects:
2062 **		Sets StopRequest which should cause the mailq/hoststatus
2063 **		display to stop.
2064 **
2065 **	NOTE:	THIS CAN BE CALLED FROM A SIGNAL HANDLER.  DO NOT ADD
2066 **		ANYTHING TO THIS ROUTINE UNLESS YOU KNOW WHAT YOU ARE
2067 **		DOING.
2068 */
2069 
2070 /* ARGSUSED */
2071 static SIGFUNC_DECL
2072 quiesce(sig)
2073 	int sig;
2074 {
2075 	int save_errno = errno;
2076 
2077 	FIX_SYSV_SIGNAL(sig, quiesce);
2078 	StopRequest = TRUE;
2079 	errno = save_errno;
2080 	return SIGFUNC_RETURN;
2081 }
2082 /*
2083 **  STOP_SENDMAIL -- Stop the running program
2084 **
2085 **	Parameters:
2086 **		none.
2087 **
2088 **	Returns:
2089 **		none.
2090 **
2091 **	Side Effects:
2092 **		exits.
2093 */
2094 
2095 void
2096 stop_sendmail()
2097 {
2098 	/* reset uid for process accounting */
2099 	endpwent();
2100 	(void) setuid(RealUid);
2101 	exit(EX_OK);
2102 }
2103 
2104 /*
2105 **  INTINDEBUG -- signal handler for SIGINT in -bt mode
2106 **
2107 **	Parameters:
2108 **		sig -- incoming signal.
2109 **
2110 **	Returns:
2111 **		none.
2112 **
2113 **	Side Effects:
2114 **		longjmps back to test mode loop.
2115 **
2116 **	NOTE:	THIS CAN BE CALLED FROM A SIGNAL HANDLER.  DO NOT ADD
2117 **		ANYTHING TO THIS ROUTINE UNLESS YOU KNOW WHAT YOU ARE
2118 **		DOING.
2119 **
2120 **	XXX: More work is needed for this signal handler.
2121 */
2122 
2123 /* ARGSUSED */
2124 static SIGFUNC_DECL
2125 intindebug(sig)
2126 	int sig;
2127 {
2128 	int save_errno = errno;
2129 
2130 	FIX_SYSV_SIGNAL(sig, intindebug);
2131 	errno = save_errno;
2132 	CHECK_CRITICAL(sig);
2133 
2134 	errno = save_errno;
2135 	longjmp(TopFrame, 1);
2136 	return SIGFUNC_RETURN;
2137 }
2138 /*
2139 **  FINIS -- Clean up and exit.
2140 **
2141 **	Parameters:
2142 **		drop -- whether or not to drop CurEnv envelope
2143 **		exitstat -- exit status to use for exit() call
2144 **
2145 **	Returns:
2146 **		never
2147 **
2148 **	Side Effects:
2149 **		exits sendmail
2150 */
2151 
2152 void
2153 finis(drop, exitstat)
2154 	bool drop;
2155 	volatile int exitstat;
2156 {
2157 	/* Still want to process new timeouts added below */
2158 	clear_events();
2159 	releasesignal(SIGALRM);
2160 
2161 	if (tTd(2, 1))
2162 	{
2163 		dprintf("\n====finis: stat %d e_id=%s e_flags=",
2164 			exitstat,
2165 			CurEnv->e_id == NULL ? "NOQUEUE" : CurEnv->e_id);
2166 		printenvflags(CurEnv);
2167 	}
2168 	if (tTd(2, 9))
2169 		printopenfds(FALSE);
2170 
2171 	/* if we fail in finis(), just exit */
2172 	if (setjmp(TopFrame) != 0)
2173 	{
2174 		/* failed -- just give it up */
2175 		goto forceexit;
2176 	}
2177 
2178 	/* clean up temp files */
2179 	CurEnv->e_to = NULL;
2180 	if (drop)
2181 	{
2182 		if (CurEnv->e_id != NULL)
2183 			dropenvelope(CurEnv, TRUE);
2184 		else
2185 			poststats(StatFile);
2186 	}
2187 
2188 	/* flush any cached connections */
2189 	mci_flush(TRUE, NULL);
2190 
2191 	/* close maps belonging to this pid */
2192 	closemaps();
2193 
2194 #if USERDB
2195 	/* close UserDatabase */
2196 	_udbx_close();
2197 #endif /* USERDB */
2198 
2199 #ifdef XLA
2200 	/* clean up extended load average stuff */
2201 	xla_all_end();
2202 #endif /* XLA */
2203 
2204 	/* and exit */
2205   forceexit:
2206 	if (LogLevel > 78)
2207 		sm_syslog(LOG_DEBUG, CurEnv->e_id,
2208 			  "finis, pid=%d",
2209 			  (int) getpid());
2210 	if (exitstat == EX_TEMPFAIL || CurEnv->e_errormode == EM_BERKNET)
2211 		exitstat = EX_OK;
2212 
2213 	sync_queue_time();
2214 
2215 	/* reset uid for process accounting */
2216 	endpwent();
2217 	(void) setuid(RealUid);
2218 	exit(exitstat);
2219 }
2220 /*
2221 **  TERM_DEAMON -- SIGTERM handler for the daemon
2222 **
2223 **	Parameters:
2224 **		sig -- signal number.
2225 **
2226 **	Returns:
2227 **		none.
2228 **
2229 **	Side Effects:
2230 **		Sets ShutdownRequest which will hopefully trigger
2231 **		the daemon to exit.
2232 **
2233 **	NOTE:	THIS CAN BE CALLED FROM A SIGNAL HANDLER.  DO NOT ADD
2234 **		ANYTHING TO THIS ROUTINE UNLESS YOU KNOW WHAT YOU ARE
2235 **		DOING.
2236 */
2237 
2238 /* ARGSUSED */
2239 static SIGFUNC_DECL
2240 term_daemon(sig)
2241 	int sig;
2242 {
2243 	int save_errno = errno;
2244 
2245 	FIX_SYSV_SIGNAL(sig, term_daemon);
2246 	ShutdownRequest = "signal";
2247 	errno = save_errno;
2248 	return SIGFUNC_RETURN;
2249 }
2250 /*
2251 **  SHUTDOWN_DAEMON -- Performs a clean shutdown of the daemon
2252 **
2253 **	Parameters:
2254 **		none.
2255 **
2256 **	Returns:
2257 **		none.
2258 **
2259 **	Side Effects:
2260 **		closes control socket, exits.
2261 */
2262 
2263 void
2264 shutdown_daemon()
2265 {
2266 	char *reason;
2267 
2268 	allsignals(TRUE);
2269 
2270 	reason = ShutdownRequest;
2271 	ShutdownRequest = NULL;
2272 	PendingSignal = 0;
2273 
2274 	if (LogLevel > 79)
2275 		sm_syslog(LOG_DEBUG, CurEnv->e_id, "interrupt");
2276 
2277 	FileName = NULL;
2278 	closecontrolsocket(TRUE);
2279 #ifdef XLA
2280 	xla_all_end();
2281 #endif /* XLA */
2282 
2283 	finis(FALSE, EX_OK);
2284 }
2285 /*
2286 **  INTSIG -- clean up on interrupt
2287 **
2288 **	This just arranges to exit.  It pessimizes in that it
2289 **	may resend a message.
2290 **
2291 **	Parameters:
2292 **		none.
2293 **
2294 **	Returns:
2295 **		none.
2296 **
2297 **	Side Effects:
2298 **		Unlocks the current job.
2299 **
2300 **	NOTE:	THIS CAN BE CALLED FROM A SIGNAL HANDLER.  DO NOT ADD
2301 **		ANYTHING TO THIS ROUTINE UNLESS YOU KNOW WHAT YOU ARE
2302 **		DOING.
2303 **
2304 **		XXX: More work is needed for this signal handler.
2305 */
2306 
2307 /* ARGSUSED */
2308 SIGFUNC_DECL
2309 intsig(sig)
2310 	int sig;
2311 {
2312 	bool drop = FALSE;
2313 	int save_errno = errno;
2314 
2315 	FIX_SYSV_SIGNAL(sig, intsig);
2316 	errno = save_errno;
2317 	CHECK_CRITICAL(sig);
2318 	allsignals(TRUE);
2319 	if (sig != 0 && LogLevel > 79)
2320 		sm_syslog(LOG_DEBUG, CurEnv->e_id, "interrupt");
2321 	FileName = NULL;
2322 
2323 	/* Clean-up on aborted stdin message submission */
2324 	if (CurEnv->e_id != NULL &&
2325 	    (OpMode == MD_SMTP ||
2326 	     OpMode == MD_DELIVER ||
2327 	     OpMode == MD_ARPAFTP))
2328 	{
2329 		register ADDRESS *q;
2330 
2331 		/* don't return an error indication */
2332 		CurEnv->e_to = NULL;
2333 		CurEnv->e_flags &= ~EF_FATALERRS;
2334 		CurEnv->e_flags |= EF_CLRQUEUE;
2335 
2336 		/*
2337 		**  Spin through the addresses and
2338 		**  mark them dead to prevent bounces
2339 		*/
2340 
2341 		for (q = CurEnv->e_sendqueue; q != NULL; q = q->q_next)
2342 			q->q_state = QS_DONTSEND;
2343 
2344 		/* and don't try to deliver the partial message either */
2345 		if (InChild)
2346 			ExitStat = EX_QUIT;
2347 
2348 		drop = TRUE;
2349 	}
2350 	else
2351 		unlockqueue(CurEnv);
2352 
2353 	finis(drop, EX_OK);
2354 }
2355 /*
2356 **  INITMACROS -- initialize the macro system
2357 **
2358 **	This just involves defining some macros that are actually
2359 **	used internally as metasymbols to be themselves.
2360 **
2361 **	Parameters:
2362 **		none.
2363 **
2364 **	Returns:
2365 **		none.
2366 **
2367 **	Side Effects:
2368 **		initializes several macros to be themselves.
2369 */
2370 
2371 struct metamac	MetaMacros[] =
2372 {
2373 	/* LHS pattern matching characters */
2374 	{ '*', MATCHZANY },	{ '+', MATCHANY },	{ '-', MATCHONE },
2375 	{ '=', MATCHCLASS },	{ '~', MATCHNCLASS },
2376 
2377 	/* these are RHS metasymbols */
2378 	{ '#', CANONNET },	{ '@', CANONHOST },	{ ':', CANONUSER },
2379 	{ '>', CALLSUBR },
2380 
2381 	/* the conditional operations */
2382 	{ '?', CONDIF },	{ '|', CONDELSE },	{ '.', CONDFI },
2383 
2384 	/* the hostname lookup characters */
2385 	{ '[', HOSTBEGIN },	{ ']', HOSTEND },
2386 	{ '(', LOOKUPBEGIN },	{ ')', LOOKUPEND },
2387 
2388 	/* miscellaneous control characters */
2389 	{ '&', MACRODEXPAND },
2390 
2391 	{ '\0', '\0' }
2392 };
2393 
2394 #define MACBINDING(name, mid) \
2395 		stab(name, ST_MACRO, ST_ENTER)->s_macro = mid; \
2396 		MacroName[mid] = name;
2397 
2398 void
2399 initmacros(e)
2400 	register ENVELOPE *e;
2401 {
2402 	register struct metamac *m;
2403 	register int c;
2404 	char buf[5];
2405 	extern char *MacroName[MAXMACROID + 1];
2406 
2407 	for (m = MetaMacros; m->metaname != '\0'; m++)
2408 	{
2409 		buf[0] = m->metaval;
2410 		buf[1] = '\0';
2411 		define(m->metaname, newstr(buf), e);
2412 	}
2413 	buf[0] = MATCHREPL;
2414 	buf[2] = '\0';
2415 	for (c = '0'; c <= '9'; c++)
2416 	{
2417 		buf[1] = c;
2418 		define(c, newstr(buf), e);
2419 	}
2420 
2421 	/* set defaults for some macros sendmail will use later */
2422 	define('n', "MAILER-DAEMON", e);
2423 
2424 	/* set up external names for some internal macros */
2425 	MACBINDING("opMode", MID_OPMODE);
2426 	/*XXX should probably add equivalents for all short macros here XXX*/
2427 }
2428 /*
2429 **  DISCONNECT -- remove our connection with any foreground process
2430 **
2431 **	Parameters:
2432 **		droplev -- how "deeply" we should drop the line.
2433 **			0 -- ignore signals, mail back errors, make sure
2434 **			     output goes to stdout.
2435 **			1 -- also, make stdout go to /dev/null.
2436 **			2 -- also, disconnect from controlling terminal
2437 **			     (only for daemon mode).
2438 **		e -- the current envelope.
2439 **
2440 **	Returns:
2441 **		none
2442 **
2443 **	Side Effects:
2444 **		Trys to insure that we are immune to vagaries of
2445 **		the controlling tty.
2446 */
2447 
2448 void
2449 disconnect(droplev, e)
2450 	int droplev;
2451 	register ENVELOPE *e;
2452 {
2453 	int fd;
2454 
2455 	if (tTd(52, 1))
2456 		dprintf("disconnect: In %d Out %d, e=%lx\n",
2457 			fileno(InChannel), fileno(OutChannel), (u_long) e);
2458 	if (tTd(52, 100))
2459 	{
2460 		dprintf("don't\n");
2461 		return;
2462 	}
2463 	if (LogLevel > 93)
2464 		sm_syslog(LOG_DEBUG, e->e_id,
2465 			  "disconnect level %d",
2466 			  droplev);
2467 
2468 	/* be sure we don't get nasty signals */
2469 	(void) setsignal(SIGINT, SIG_IGN);
2470 	(void) setsignal(SIGQUIT, SIG_IGN);
2471 
2472 	/* we can't communicate with our caller, so.... */
2473 	HoldErrs = TRUE;
2474 	CurEnv->e_errormode = EM_MAIL;
2475 	Verbose = 0;
2476 	DisConnected = TRUE;
2477 
2478 	/* all input from /dev/null */
2479 	if (InChannel != stdin)
2480 	{
2481 		(void) fclose(InChannel);
2482 		InChannel = stdin;
2483 	}
2484 	if (freopen("/dev/null", "r", stdin) == NULL)
2485 		sm_syslog(LOG_ERR, e->e_id,
2486 			  "disconnect: freopen(\"/dev/null\") failed: %s",
2487 			  errstring(errno));
2488 
2489 	/* output to the transcript */
2490 	if (OutChannel != stdout)
2491 	{
2492 		(void) fclose(OutChannel);
2493 		OutChannel = stdout;
2494 	}
2495 	if (droplev > 0)
2496 	{
2497 		fd = open("/dev/null", O_WRONLY, 0666);
2498 		if (fd == -1)
2499 			sm_syslog(LOG_ERR, e->e_id,
2500 				  "disconnect: open(\"/dev/null\") failed: %s",
2501 				  errstring(errno));
2502 		(void) fflush(stdout);
2503 		(void) dup2(fd, STDOUT_FILENO);
2504 		(void) dup2(fd, STDERR_FILENO);
2505 		(void) close(fd);
2506 	}
2507 
2508 	/* drop our controlling TTY completely if possible */
2509 	if (droplev > 1)
2510 	{
2511 		(void) setsid();
2512 		errno = 0;
2513 	}
2514 
2515 #if XDEBUG
2516 	checkfd012("disconnect");
2517 #endif /* XDEBUG */
2518 
2519 	if (LogLevel > 71)
2520 		sm_syslog(LOG_DEBUG, e->e_id,
2521 			  "in background, pid=%d",
2522 			  (int) getpid());
2523 
2524 	errno = 0;
2525 }
2526 
2527 static void
2528 obsolete(argv)
2529 	char *argv[];
2530 {
2531 	register char *ap;
2532 	register char *op;
2533 
2534 	while ((ap = *++argv) != NULL)
2535 	{
2536 		/* Return if "--" or not an option of any form. */
2537 		if (ap[0] != '-' || ap[1] == '-')
2538 			return;
2539 
2540 		/* skip over options that do have a value */
2541 		op = strchr(OPTIONS, ap[1]);
2542 		if (op != NULL && *++op == ':' && ap[2] == '\0' &&
2543 		    ap[1] != 'd' &&
2544 #if defined(sony_news)
2545 		    ap[1] != 'E' && ap[1] != 'J' &&
2546 #endif /* defined(sony_news) */
2547 		    argv[1] != NULL && argv[1][0] != '-')
2548 		{
2549 			argv++;
2550 			continue;
2551 		}
2552 
2553 		/* If -C doesn't have an argument, use sendmail.cf. */
2554 #define	__DEFPATH	"sendmail.cf"
2555 		if (ap[1] == 'C' && ap[2] == '\0')
2556 		{
2557 			*argv = xalloc(sizeof(__DEFPATH) + 2);
2558 			(void) snprintf(argv[0], sizeof(__DEFPATH) + 2, "-C%s",
2559 					__DEFPATH);
2560 		}
2561 
2562 		/* If -q doesn't have an argument, run it once. */
2563 		if (ap[1] == 'q' && ap[2] == '\0')
2564 			*argv = "-q0";
2565 
2566 		/* if -d doesn't have an argument, use 0-99.1 */
2567 		if (ap[1] == 'd' && ap[2] == '\0')
2568 			*argv = "-d0-99.1";
2569 
2570 #if defined(sony_news)
2571 		/* if -E doesn't have an argument, use -EC */
2572 		if (ap[1] == 'E' && ap[2] == '\0')
2573 			*argv = "-EC";
2574 
2575 		/* if -J doesn't have an argument, use -JJ */
2576 		if (ap[1] == 'J' && ap[2] == '\0')
2577 			*argv = "-JJ";
2578 #endif /* defined(sony_news) */
2579 	}
2580 }
2581 /*
2582 **  AUTH_WARNING -- specify authorization warning
2583 **
2584 **	Parameters:
2585 **		e -- the current envelope.
2586 **		msg -- the text of the message.
2587 **		args -- arguments to the message.
2588 **
2589 **	Returns:
2590 **		none.
2591 */
2592 
2593 void
2594 #ifdef __STDC__
2595 auth_warning(register ENVELOPE *e, const char *msg, ...)
2596 #else /* __STDC__ */
2597 auth_warning(e, msg, va_alist)
2598 	register ENVELOPE *e;
2599 	const char *msg;
2600 	va_dcl
2601 #endif /* __STDC__ */
2602 {
2603 	char buf[MAXLINE];
2604 	VA_LOCAL_DECL
2605 
2606 	if (bitset(PRIV_AUTHWARNINGS, PrivacyFlags))
2607 	{
2608 		register char *p;
2609 		static char hostbuf[48];
2610 
2611 		if (hostbuf[0] == '\0')
2612 		{
2613 			struct hostent *hp;
2614 
2615 			hp = myhostname(hostbuf, sizeof hostbuf);
2616 #if _FFR_FREEHOSTENT && NETINET6
2617 			if (hp != NULL)
2618 			{
2619 				freehostent(hp);
2620 				hp = NULL;
2621 			}
2622 #endif /* _FFR_FREEHOSTENT && NETINET6 */
2623 		}
2624 
2625 		(void) snprintf(buf, sizeof buf, "%s: ", hostbuf);
2626 		p = &buf[strlen(buf)];
2627 		VA_START(msg);
2628 		vsnprintf(p, SPACELEFT(buf, p), msg, ap);
2629 		VA_END;
2630 		addheader("X-Authentication-Warning", buf, 0, &e->e_header);
2631 		if (LogLevel > 3)
2632 			sm_syslog(LOG_INFO, e->e_id,
2633 				  "Authentication-Warning: %.400s",
2634 				  buf);
2635 	}
2636 }
2637 /*
2638 **  GETEXTENV -- get from external environment
2639 **
2640 **	Parameters:
2641 **		envar -- the name of the variable to retrieve
2642 **
2643 **	Returns:
2644 **		The value, if any.
2645 */
2646 
2647 char *
2648 getextenv(envar)
2649 	const char *envar;
2650 {
2651 	char **envp;
2652 	int l;
2653 
2654 	l = strlen(envar);
2655 	for (envp = ExternalEnviron; *envp != NULL; envp++)
2656 	{
2657 		if (strncmp(*envp, envar, l) == 0 && (*envp)[l] == '=')
2658 			return &(*envp)[l + 1];
2659 	}
2660 	return NULL;
2661 }
2662 /*
2663 **  SETUSERENV -- set an environment in the propogated environment
2664 **
2665 **	Parameters:
2666 **		envar -- the name of the environment variable.
2667 **		value -- the value to which it should be set.  If
2668 **			null, this is extracted from the incoming
2669 **			environment.  If that is not set, the call
2670 **			to setuserenv is ignored.
2671 **
2672 **	Returns:
2673 **		none.
2674 */
2675 
2676 void
2677 setuserenv(envar, value)
2678 	const char *envar;
2679 	const char *value;
2680 {
2681 	int i, l;
2682 	char **evp = UserEnviron;
2683 	char *p;
2684 
2685 	if (value == NULL)
2686 	{
2687 		value = getextenv(envar);
2688 		if (value == NULL)
2689 			return;
2690 	}
2691 
2692 	i = strlen(envar) + 1;
2693 	l = strlen(value) + i + 1;
2694 	p = (char *) xalloc(l);
2695 	(void) snprintf(p, l, "%s=%s", envar, value);
2696 
2697 	while (*evp != NULL && strncmp(*evp, p, i) != 0)
2698 		evp++;
2699 	if (*evp != NULL)
2700 	{
2701 		*evp++ = p;
2702 	}
2703 	else if (evp < &UserEnviron[MAXUSERENVIRON])
2704 	{
2705 		*evp++ = p;
2706 		*evp = NULL;
2707 	}
2708 
2709 	/* make sure it is in our environment as well */
2710 	if (putenv(p) < 0)
2711 		syserr("setuserenv: putenv(%s) failed", p);
2712 }
2713 /*
2714 **  DUMPSTATE -- dump state
2715 **
2716 **	For debugging.
2717 */
2718 
2719 void
2720 dumpstate(when)
2721 	char *when;
2722 {
2723 	register char *j = macvalue('j', CurEnv);
2724 	int rs;
2725 	extern int NextMacroId;
2726 
2727 	sm_syslog(LOG_DEBUG, CurEnv->e_id,
2728 		  "--- dumping state on %s: $j = %s ---",
2729 		  when,
2730 		  j == NULL ? "<NULL>" : j);
2731 	if (j != NULL)
2732 	{
2733 		if (!wordinclass(j, 'w'))
2734 			sm_syslog(LOG_DEBUG, CurEnv->e_id,
2735 				  "*** $j not in $=w ***");
2736 	}
2737 	sm_syslog(LOG_DEBUG, CurEnv->e_id, "CurChildren = %d", CurChildren);
2738 	sm_syslog(LOG_DEBUG, CurEnv->e_id, "NextMacroId = %d (Max %d)\n",
2739 		  NextMacroId, MAXMACROID);
2740 	sm_syslog(LOG_DEBUG, CurEnv->e_id, "--- open file descriptors: ---");
2741 	printopenfds(TRUE);
2742 	sm_syslog(LOG_DEBUG, CurEnv->e_id, "--- connection cache: ---");
2743 	mci_dump_all(TRUE);
2744 	rs = strtorwset("debug_dumpstate", NULL, ST_FIND);
2745 	if (rs > 0)
2746 	{
2747 		int status;
2748 		register char **pvp;
2749 		char *pv[MAXATOM + 1];
2750 
2751 		pv[0] = NULL;
2752 		status = rewrite(pv, rs, 0, CurEnv);
2753 		sm_syslog(LOG_DEBUG, CurEnv->e_id,
2754 			  "--- ruleset debug_dumpstate returns stat %d, pv: ---",
2755 			  status);
2756 		for (pvp = pv; *pvp != NULL; pvp++)
2757 			sm_syslog(LOG_DEBUG, CurEnv->e_id, "%s", *pvp);
2758 	}
2759 	sm_syslog(LOG_DEBUG, CurEnv->e_id, "--- end of state dump ---");
2760 }
2761 /*
2762 **  SIGUSR1 -- Signal a request to dump state.
2763 **
2764 **	Parameters:
2765 **		sig -- calling signal.
2766 **
2767 **	Returns:
2768 **		none.
2769 **
2770 **	NOTE:	THIS CAN BE CALLED FROM A SIGNAL HANDLER.  DO NOT ADD
2771 **		ANYTHING TO THIS ROUTINE UNLESS YOU KNOW WHAT YOU ARE
2772 **		DOING.
2773 **
2774 **		XXX: More work is needed for this signal handler.
2775 */
2776 
2777 /* ARGSUSED */
2778 static SIGFUNC_DECL
2779 sigusr1(sig)
2780 	int sig;
2781 {
2782 	int save_errno = errno;
2783 
2784 	FIX_SYSV_SIGNAL(sig, sigusr1);
2785 	errno = save_errno;
2786 	CHECK_CRITICAL(sig);
2787 	dumpstate("user signal");
2788 	errno = save_errno;
2789 	return SIGFUNC_RETURN;
2790 }
2791 /*
2792 **  DROP_PRIVILEGES -- reduce privileges to those of the RunAsUser option
2793 **
2794 **	Parameters:
2795 **		to_real_uid -- if set, drop to the real uid instead
2796 **			of the RunAsUser.
2797 **
2798 **	Returns:
2799 **		EX_OSERR if the setuid failed.
2800 **		EX_OK otherwise.
2801 */
2802 
2803 int
2804 drop_privileges(to_real_uid)
2805 	bool to_real_uid;
2806 {
2807 	int rval = EX_OK;
2808 	GIDSET_T emptygidset[1];
2809 
2810 	if (tTd(47, 1))
2811 		dprintf("drop_privileges(%d): Real[UG]id=%d:%d, RunAs[UG]id=%d:%d\n",
2812 			(int)to_real_uid, (int)RealUid,
2813 			(int)RealGid, (int)RunAsUid, (int)RunAsGid);
2814 
2815 	if (to_real_uid)
2816 	{
2817 		RunAsUserName = RealUserName;
2818 		RunAsUid = RealUid;
2819 		RunAsGid = RealGid;
2820 	}
2821 
2822 	/* make sure no one can grab open descriptors for secret files */
2823 	endpwent();
2824 
2825 	/* reset group permissions; these can be set later */
2826 	emptygidset[0] = (to_real_uid || RunAsGid != 0) ? RunAsGid : getegid();
2827 	if (setgroups(1, emptygidset) == -1 && geteuid() == 0)
2828 	{
2829 		syserr("drop_privileges: setgroups(1, %d) failed",
2830 		       (int)emptygidset[0]);
2831 		rval = EX_OSERR;
2832 	}
2833 
2834 	/* reset primary group and user id */
2835 	if ((to_real_uid || RunAsGid != 0) && setgid(RunAsGid) < 0)
2836 	{
2837 		syserr("drop_privileges: setgid(%d) failed", (int)RunAsGid);
2838 		rval = EX_OSERR;
2839 	}
2840 	if (to_real_uid || RunAsUid != 0)
2841 	{
2842 		uid_t euid = geteuid();
2843 
2844 		if (setuid(RunAsUid) < 0)
2845 		{
2846 			syserr("drop_privileges: setuid(%d) failed",
2847 			       (int)RunAsUid);
2848 			rval = EX_OSERR;
2849 		}
2850 		else if (RunAsUid != 0 && setuid(0) == 0)
2851 		{
2852 			/*
2853 			**  Believe it or not, the Linux capability model
2854 			**  allows a non-root process to override setuid()
2855 			**  on a process running as root and prevent that
2856 			**  process from dropping privileges.
2857 			*/
2858 
2859 			syserr("drop_privileges: setuid(0) succeeded (when it should not)");
2860 			rval = EX_OSERR;
2861 		}
2862 		else if (RunAsUid != euid && setuid(euid) == 0)
2863 		{
2864 			/*
2865 			**  Some operating systems will keep the saved-uid
2866 			**  if a non-root effective-uid calls setuid(real-uid)
2867 			**  making it possible to set it back again later.
2868 			*/
2869 
2870 			syserr("drop_privileges: Unable to drop non-root set-user-id privileges");
2871 			rval = EX_OSERR;
2872 		}
2873 	}
2874 	if (tTd(47, 5))
2875 	{
2876 		dprintf("drop_privileges: e/ruid = %d/%d e/rgid = %d/%d\n",
2877 			(int)geteuid(), (int)getuid(),
2878 			(int)getegid(), (int)getgid());
2879 		dprintf("drop_privileges: RunAsUser = %d:%d\n",
2880 			(int)RunAsUid, (int)RunAsGid);
2881 		if (tTd(47, 10))
2882 			dprintf("drop_privileges: rval = %d\n", rval);
2883 	}
2884 	return rval;
2885 }
2886 /*
2887 **  FILL_FD -- make sure a file descriptor has been properly allocated
2888 **
2889 **	Used to make sure that stdin/out/err are allocated on startup
2890 **
2891 **	Parameters:
2892 **		fd -- the file descriptor to be filled.
2893 **		where -- a string used for logging.  If NULL, this is
2894 **			being called on startup, and logging should
2895 **			not be done.
2896 **
2897 **	Returns:
2898 **		none
2899 */
2900 
2901 void
2902 fill_fd(fd, where)
2903 	int fd;
2904 	char *where;
2905 {
2906 	int i;
2907 	struct stat stbuf;
2908 
2909 	if (fstat(fd, &stbuf) >= 0 || errno != EBADF)
2910 		return;
2911 
2912 	if (where != NULL)
2913 		syserr("fill_fd: %s: fd %d not open", where, fd);
2914 	else
2915 		MissingFds |= 1 << fd;
2916 	i = open("/dev/null", fd == 0 ? O_RDONLY : O_WRONLY, 0666);
2917 	if (i < 0)
2918 	{
2919 		syserr("!fill_fd: %s: cannot open /dev/null",
2920 			where == NULL ? "startup" : where);
2921 	}
2922 	if (fd != i)
2923 	{
2924 		(void) dup2(i, fd);
2925 		(void) close(i);
2926 	}
2927 }
2928 /*
2929 **  TESTMODELINE -- process a test mode input line
2930 **
2931 **	Parameters:
2932 **		line -- the input line.
2933 **		e -- the current environment.
2934 **	Syntax:
2935 **		#  a comment
2936 **		.X process X as a configuration line
2937 **		=X dump a configuration item (such as mailers)
2938 **		$X dump a macro or class
2939 **		/X try an activity
2940 **		X  normal process through rule set X
2941 */
2942 
2943 static void
2944 testmodeline(line, e)
2945 	char *line;
2946 	ENVELOPE *e;
2947 {
2948 	register char *p;
2949 	char *q;
2950 	auto char *delimptr;
2951 	int mid;
2952 	int i, rs;
2953 	STAB *map;
2954 	char **s;
2955 	struct rewrite *rw;
2956 	ADDRESS a;
2957 	static int tryflags = RF_COPYNONE;
2958 	char exbuf[MAXLINE];
2959 	extern u_char TokTypeNoC[];
2960 
2961 #if _FFR_ADDR_TYPE
2962 	define(macid("{addr_type}", NULL), "e r", e);
2963 #endif /* _FFR_ADDR_TYPE */
2964 
2965 	/* skip leading spaces */
2966 	while (*line == ' ')
2967 		line++;
2968 
2969 	switch (line[0])
2970 	{
2971 	  case '#':
2972 	  case '\0':
2973 		return;
2974 
2975 	  case '?':
2976 		help("-bt", e);
2977 		return;
2978 
2979 	  case '.':		/* config-style settings */
2980 		switch (line[1])
2981 		{
2982 		  case 'D':
2983 			mid = macid(&line[2], &delimptr);
2984 			if (mid == 0)
2985 				return;
2986 			translate_dollars(delimptr);
2987 			define(mid, newstr(delimptr), e);
2988 			break;
2989 
2990 		  case 'C':
2991 			if (line[2] == '\0')	/* not to call syserr() */
2992 				return;
2993 
2994 			mid = macid(&line[2], &delimptr);
2995 			if (mid == 0)
2996 				return;
2997 			translate_dollars(delimptr);
2998 			expand(delimptr, exbuf, sizeof exbuf, e);
2999 			p = exbuf;
3000 			while (*p != '\0')
3001 			{
3002 				register char *wd;
3003 				char delim;
3004 
3005 				while (*p != '\0' && isascii(*p) && isspace(*p))
3006 					p++;
3007 				wd = p;
3008 				while (*p != '\0' && !(isascii(*p) && isspace(*p)))
3009 					p++;
3010 				delim = *p;
3011 				*p = '\0';
3012 				if (wd[0] != '\0')
3013 					setclass(mid, wd);
3014 				*p = delim;
3015 			}
3016 			break;
3017 
3018 		  case '\0':
3019 			printf("Usage: .[DC]macro value(s)\n");
3020 			break;
3021 
3022 		  default:
3023 			printf("Unknown \".\" command %s\n", line);
3024 			break;
3025 		}
3026 		return;
3027 
3028 	  case '=':		/* config-style settings */
3029 		switch (line[1])
3030 		{
3031 		  case 'S':		/* dump rule set */
3032 			rs = strtorwset(&line[2], NULL, ST_FIND);
3033 			if (rs < 0)
3034 			{
3035 				printf("Undefined ruleset %s\n", &line[2]);
3036 				return;
3037 			}
3038 			rw = RewriteRules[rs];
3039 			if (rw == NULL)
3040 				return;
3041 			do
3042 			{
3043 				(void) putchar('R');
3044 				s = rw->r_lhs;
3045 				while (*s != NULL)
3046 				{
3047 					xputs(*s++);
3048 					(void) putchar(' ');
3049 				}
3050 				(void) putchar('\t');
3051 				(void) putchar('\t');
3052 				s = rw->r_rhs;
3053 				while (*s != NULL)
3054 				{
3055 					xputs(*s++);
3056 					(void) putchar(' ');
3057 				}
3058 				(void) putchar('\n');
3059 			} while ((rw = rw->r_next) != NULL);
3060 			break;
3061 
3062 		  case 'M':
3063 			for (i = 0; i < MAXMAILERS; i++)
3064 			{
3065 				if (Mailer[i] != NULL)
3066 					printmailer(Mailer[i]);
3067 			}
3068 			break;
3069 
3070 		  case '\0':
3071 			printf("Usage: =Sruleset or =M\n");
3072 			break;
3073 
3074 		  default:
3075 			printf("Unknown \"=\" command %s\n", line);
3076 			break;
3077 		}
3078 		return;
3079 
3080 	  case '-':		/* set command-line-like opts */
3081 		switch (line[1])
3082 		{
3083 		  case 'd':
3084 			tTflag(&line[2]);
3085 			break;
3086 
3087 		  case '\0':
3088 			printf("Usage: -d{debug arguments}\n");
3089 			break;
3090 
3091 		  default:
3092 			printf("Unknown \"-\" command %s\n", line);
3093 			break;
3094 		}
3095 		return;
3096 
3097 	  case '$':
3098 		if (line[1] == '=')
3099 		{
3100 			mid = macid(&line[2], NULL);
3101 			if (mid != 0)
3102 				stabapply(dump_class, mid);
3103 			return;
3104 		}
3105 		mid = macid(&line[1], NULL);
3106 		if (mid == 0)
3107 			return;
3108 		p = macvalue(mid, e);
3109 		if (p == NULL)
3110 			printf("Undefined\n");
3111 		else
3112 		{
3113 			xputs(p);
3114 			printf("\n");
3115 		}
3116 		return;
3117 
3118 	  case '/':		/* miscellaneous commands */
3119 		p = &line[strlen(line)];
3120 		while (--p >= line && isascii(*p) && isspace(*p))
3121 			*p = '\0';
3122 		p = strpbrk(line, " \t");
3123 		if (p != NULL)
3124 		{
3125 			while (isascii(*p) && isspace(*p))
3126 				*p++ = '\0';
3127 		}
3128 		else
3129 			p = "";
3130 		if (line[1] == '\0')
3131 		{
3132 			printf("Usage: /[canon|map|mx|parse|try|tryflags]\n");
3133 			return;
3134 		}
3135 		if (strcasecmp(&line[1], "quit") == 0)
3136 		{
3137 			CurEnv->e_id = NULL;
3138 			finis(TRUE, ExitStat);
3139 		}
3140 		if (strcasecmp(&line[1], "mx") == 0)
3141 		{
3142 #if NAMED_BIND
3143 			/* look up MX records */
3144 			int nmx;
3145 			auto int rcode;
3146 			char *mxhosts[MAXMXHOSTS + 1];
3147 
3148 			if (*p == '\0')
3149 			{
3150 				printf("Usage: /mx address\n");
3151 				return;
3152 			}
3153 			nmx = getmxrr(p, mxhosts, NULL, FALSE, &rcode);
3154 			printf("getmxrr(%s) returns %d value(s):\n", p, nmx);
3155 			for (i = 0; i < nmx; i++)
3156 				printf("\t%s\n", mxhosts[i]);
3157 #else /* NAMED_BIND */
3158 			printf("No MX code compiled in\n");
3159 #endif /* NAMED_BIND */
3160 		}
3161 		else if (strcasecmp(&line[1], "canon") == 0)
3162 		{
3163 			char host[MAXHOSTNAMELEN];
3164 
3165 			if (*p == '\0')
3166 			{
3167 				printf("Usage: /canon address\n");
3168 				return;
3169 			}
3170 			else if (strlcpy(host, p, sizeof host) >= sizeof host)
3171 			{
3172 				printf("Name too long\n");
3173 				return;
3174 			}
3175 			(void) getcanonname(host, sizeof host, HasWildcardMX);
3176 			printf("getcanonname(%s) returns %s\n", p, host);
3177 		}
3178 		else if (strcasecmp(&line[1], "map") == 0)
3179 		{
3180 			auto int rcode = EX_OK;
3181 			char *av[2];
3182 
3183 			if (*p == '\0')
3184 			{
3185 				printf("Usage: /map mapname key\n");
3186 				return;
3187 			}
3188 			for (q = p; *q != '\0' && !(isascii(*q) && isspace(*q)); q++)
3189 				continue;
3190 			if (*q == '\0')
3191 			{
3192 				printf("No key specified\n");
3193 				return;
3194 			}
3195 			*q++ = '\0';
3196 			map = stab(p, ST_MAP, ST_FIND);
3197 			if (map == NULL)
3198 			{
3199 				printf("Map named \"%s\" not found\n", p);
3200 				return;
3201 			}
3202 			if (!bitset(MF_OPEN, map->s_map.map_mflags) &&
3203 			    !openmap(&(map->s_map)))
3204 			{
3205 				printf("Map named \"%s\" not open\n", p);
3206 				return;
3207 			}
3208 			printf("map_lookup: %s (%s) ", p, q);
3209 			av[0] = q;
3210 			av[1] = NULL;
3211 			p = (*map->s_map.map_class->map_lookup)
3212 					(&map->s_map, q, av, &rcode);
3213 			if (p == NULL)
3214 				printf("no match (%d)\n", rcode);
3215 			else
3216 				printf("returns %s (%d)\n", p, rcode);
3217 		}
3218 		else if (strcasecmp(&line[1], "try") == 0)
3219 		{
3220 			MAILER *m;
3221 			STAB *st;
3222 			auto int rcode = EX_OK;
3223 
3224 			q = strpbrk(p, " \t");
3225 			if (q != NULL)
3226 			{
3227 				while (isascii(*q) && isspace(*q))
3228 					*q++ = '\0';
3229 			}
3230 			if (q == NULL || *q == '\0')
3231 			{
3232 				printf("Usage: /try mailer address\n");
3233 				return;
3234 			}
3235 			st = stab(p, ST_MAILER, ST_FIND);
3236 			if (st == NULL)
3237 			{
3238 				printf("Unknown mailer %s\n", p);
3239 				return;
3240 			}
3241 			m = st->s_mailer;
3242 			printf("Trying %s %s address %s for mailer %s\n",
3243 				bitset(RF_HEADERADDR, tryflags) ? "header" : "envelope",
3244 				bitset(RF_SENDERADDR, tryflags) ? "sender" : "recipient",
3245 				q, p);
3246 			p = remotename(q, m, tryflags, &rcode, CurEnv);
3247 			printf("Rcode = %d, addr = %s\n",
3248 				rcode, p == NULL ? "<NULL>" : p);
3249 			e->e_to = NULL;
3250 		}
3251 		else if (strcasecmp(&line[1], "tryflags") == 0)
3252 		{
3253 			if (*p == '\0')
3254 			{
3255 				printf("Usage: /tryflags [Hh|Ee][Ss|Rr]\n");
3256 				return;
3257 			}
3258 			for (; *p != '\0'; p++)
3259 			{
3260 				switch (*p)
3261 				{
3262 				  case 'H':
3263 				  case 'h':
3264 					tryflags |= RF_HEADERADDR;
3265 					break;
3266 
3267 				  case 'E':
3268 				  case 'e':
3269 					tryflags &= ~RF_HEADERADDR;
3270 					break;
3271 
3272 				  case 'S':
3273 				  case 's':
3274 					tryflags |= RF_SENDERADDR;
3275 					break;
3276 
3277 				  case 'R':
3278 				  case 'r':
3279 					tryflags &= ~RF_SENDERADDR;
3280 					break;
3281 				}
3282 			}
3283 #if _FFR_ADDR_TYPE
3284 			exbuf[0] = bitset(RF_HEADERADDR, tryflags) ? 'h' : 'e';
3285 			exbuf[1] = ' ';
3286 			exbuf[2] = bitset(RF_SENDERADDR, tryflags) ? 's' : 'r';
3287 			exbuf[3] = '\0';
3288 			define(macid("{addr_type}", NULL), newstr(exbuf), e);
3289 #endif /* _FFR_ADDR_TYPE */
3290 		}
3291 		else if (strcasecmp(&line[1], "parse") == 0)
3292 		{
3293 			if (*p == '\0')
3294 			{
3295 				printf("Usage: /parse address\n");
3296 				return;
3297 			}
3298 			q = crackaddr(p);
3299 			printf("Cracked address = ");
3300 			xputs(q);
3301 			printf("\nParsing %s %s address\n",
3302 				bitset(RF_HEADERADDR, tryflags) ? "header" : "envelope",
3303 				bitset(RF_SENDERADDR, tryflags) ? "sender" : "recipient");
3304 			if (parseaddr(p, &a, tryflags, '\0', NULL, e) == NULL)
3305 				printf("Cannot parse\n");
3306 			else if (a.q_host != NULL && a.q_host[0] != '\0')
3307 				printf("mailer %s, host %s, user %s\n",
3308 					a.q_mailer->m_name, a.q_host, a.q_user);
3309 			else
3310 				printf("mailer %s, user %s\n",
3311 					a.q_mailer->m_name, a.q_user);
3312 			e->e_to = NULL;
3313 		}
3314 		else
3315 		{
3316 			printf("Unknown \"/\" command %s\n", line);
3317 		}
3318 		return;
3319 	}
3320 
3321 	for (p = line; isascii(*p) && isspace(*p); p++)
3322 		continue;
3323 	q = p;
3324 	while (*p != '\0' && !(isascii(*p) && isspace(*p)))
3325 		p++;
3326 	if (*p == '\0')
3327 	{
3328 		printf("No address!\n");
3329 		return;
3330 	}
3331 	*p = '\0';
3332 	if (invalidaddr(p + 1, NULL))
3333 		return;
3334 	do
3335 	{
3336 		register char **pvp;
3337 		char pvpbuf[PSBUFSIZE];
3338 
3339 		pvp = prescan(++p, ',', pvpbuf, sizeof pvpbuf,
3340 			      &delimptr, ConfigLevel >= 9 ? TokTypeNoC : NULL);
3341 		if (pvp == NULL)
3342 			continue;
3343 		p = q;
3344 		while (*p != '\0')
3345 		{
3346 			int status;
3347 
3348 			rs = strtorwset(p, NULL, ST_FIND);
3349 			if (rs < 0)
3350 			{
3351 				printf("Undefined ruleset %s\n", p);
3352 				break;
3353 			}
3354 			status = rewrite(pvp, rs, 0, e);
3355 			if (status != EX_OK)
3356 				printf("== Ruleset %s (%d) status %d\n",
3357 					p, rs, status);
3358 			while (*p != '\0' && *p++ != ',')
3359 				continue;
3360 		}
3361 	} while (*(p = delimptr) != '\0');
3362 }
3363 
3364 static void
3365 dump_class(s, id)
3366 	register STAB *s;
3367 	int id;
3368 {
3369 	if (s->s_type != ST_CLASS)
3370 		return;
3371 	if (bitnset(bitidx(id), s->s_class))
3372 		printf("%s\n", s->s_name);
3373 }
3374