xref: /illumos-gate/usr/src/cmd/sendmail/src/main.c (revision e9af4bc0)
17c478bd9Sstevel@tonic-gate /*
2*e9af4bc0SJohn Beck  * Copyright (c) 1998-2006, 2008, 2009 Sendmail, Inc. and its suppliers.
37c478bd9Sstevel@tonic-gate  *	All rights reserved.
47c478bd9Sstevel@tonic-gate  * Copyright (c) 1983, 1995-1997 Eric P. Allman.  All rights reserved.
57c478bd9Sstevel@tonic-gate  * Copyright (c) 1988, 1993
67c478bd9Sstevel@tonic-gate  *	The Regents of the University of California.  All rights reserved.
77c478bd9Sstevel@tonic-gate  *
87c478bd9Sstevel@tonic-gate  * By using this file, you agree to the terms and conditions set
97c478bd9Sstevel@tonic-gate  * forth in the LICENSE file which can be found at the top level of
107c478bd9Sstevel@tonic-gate  * the sendmail distribution.
117c478bd9Sstevel@tonic-gate  *
127c478bd9Sstevel@tonic-gate  */
137c478bd9Sstevel@tonic-gate 
147c478bd9Sstevel@tonic-gate /*
15445f2479Sjbeck  * Copyright 1996-2006 Sun Microsystems, Inc.  All rights reserved.
167c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
177c478bd9Sstevel@tonic-gate  */
187c478bd9Sstevel@tonic-gate 
197c478bd9Sstevel@tonic-gate #define _DEFINE
207c478bd9Sstevel@tonic-gate #include <sendmail.h>
21058561cbSjbeck #include <sm/sendmail.h>
227c478bd9Sstevel@tonic-gate #include <sm/xtrap.h>
237c478bd9Sstevel@tonic-gate #include <sm/signal.h>
247c478bd9Sstevel@tonic-gate 
257c478bd9Sstevel@tonic-gate #ifndef lint
267c478bd9Sstevel@tonic-gate SM_UNUSED(static char copyright[]) =
277c478bd9Sstevel@tonic-gate "@(#) Copyright (c) 1998-2003 Sendmail, Inc. and its suppliers.\n\
287c478bd9Sstevel@tonic-gate @(#)	All rights reserved.\n\
297c478bd9Sstevel@tonic-gate @(#) Copyright (c) 1983, 1995-1997 Eric P. Allman.  All rights reserved.\n\
307c478bd9Sstevel@tonic-gate @(#) Copyright (c) 1988, 1993\n\
317c478bd9Sstevel@tonic-gate @(#)	The Regents of the University of California.  All rights reserved.\n\
32445f2479Sjbeck @(#) Copyright 1996-2006 Sun Microsystems, Inc.  All rights reserved.\n\
337c478bd9Sstevel@tonic-gate @(#) Use is subject to license terms.\n";
347c478bd9Sstevel@tonic-gate #endif /* ! lint */
357c478bd9Sstevel@tonic-gate 
36*e9af4bc0SJohn Beck SM_RCSID("@(#)$Id: main.c,v 8.971 2009/12/18 17:08:01 ca Exp $")
377c478bd9Sstevel@tonic-gate 
387c478bd9Sstevel@tonic-gate #if NETINET || NETINET6
397c478bd9Sstevel@tonic-gate # include <arpa/inet.h>
407c478bd9Sstevel@tonic-gate #endif /* NETINET || NETINET6 */
417c478bd9Sstevel@tonic-gate 
427c478bd9Sstevel@tonic-gate /* for getcfname() */
437c478bd9Sstevel@tonic-gate #include <sendmail/pathnames.h>
447c478bd9Sstevel@tonic-gate 
457c478bd9Sstevel@tonic-gate static SM_DEBUG_T
467c478bd9Sstevel@tonic-gate DebugNoPRestart = SM_DEBUG_INITIALIZER("no_persistent_restart",
477c478bd9Sstevel@tonic-gate 	"@(#)$Debug: no_persistent_restart - don't restart, log only $");
487c478bd9Sstevel@tonic-gate 
497c478bd9Sstevel@tonic-gate static void	dump_class __P((STAB *, int));
507c478bd9Sstevel@tonic-gate static void	obsolete __P((char **));
517c478bd9Sstevel@tonic-gate static void	testmodeline __P((char *, ENVELOPE *));
527c478bd9Sstevel@tonic-gate static char	*getextenv __P((const char *));
537c478bd9Sstevel@tonic-gate static void	sm_printoptions __P((char **));
547c478bd9Sstevel@tonic-gate static SIGFUNC_DECL	intindebug __P((int));
557c478bd9Sstevel@tonic-gate static SIGFUNC_DECL	sighup __P((int));
567c478bd9Sstevel@tonic-gate static SIGFUNC_DECL	sigpipe __P((int));
577c478bd9Sstevel@tonic-gate static SIGFUNC_DECL	sigterm __P((int));
587c478bd9Sstevel@tonic-gate #ifdef SIGUSR1
597c478bd9Sstevel@tonic-gate static SIGFUNC_DECL	sigusr1 __P((int));
607c478bd9Sstevel@tonic-gate #endif /* SIGUSR1 */
617c478bd9Sstevel@tonic-gate 
627c478bd9Sstevel@tonic-gate /*
637c478bd9Sstevel@tonic-gate **  SENDMAIL -- Post mail to a set of destinations.
647c478bd9Sstevel@tonic-gate **
657c478bd9Sstevel@tonic-gate **	This is the basic mail router.  All user mail programs should
667c478bd9Sstevel@tonic-gate **	call this routine to actually deliver mail.  Sendmail in
677c478bd9Sstevel@tonic-gate **	turn calls a bunch of mail servers that do the real work of
687c478bd9Sstevel@tonic-gate **	delivering the mail.
697c478bd9Sstevel@tonic-gate **
707c478bd9Sstevel@tonic-gate **	Sendmail is driven by settings read in from /etc/mail/sendmail.cf
717c478bd9Sstevel@tonic-gate **	(read by readcf.c).
727c478bd9Sstevel@tonic-gate **
737c478bd9Sstevel@tonic-gate **	Usage:
747c478bd9Sstevel@tonic-gate **		/usr/lib/sendmail [flags] addr ...
757c478bd9Sstevel@tonic-gate **
767c478bd9Sstevel@tonic-gate **		See the associated documentation for details.
777c478bd9Sstevel@tonic-gate **
787c478bd9Sstevel@tonic-gate **	Authors:
797c478bd9Sstevel@tonic-gate **		Eric Allman, UCB/INGRES (until 10/81).
807c478bd9Sstevel@tonic-gate **			     Britton-Lee, Inc., purveyors of fine
817c478bd9Sstevel@tonic-gate **				database computers (11/81 - 10/88).
827c478bd9Sstevel@tonic-gate **			     International Computer Science Institute
837c478bd9Sstevel@tonic-gate **				(11/88 - 9/89).
847c478bd9Sstevel@tonic-gate **			     UCB/Mammoth Project (10/89 - 7/95).
857c478bd9Sstevel@tonic-gate **			     InReference, Inc. (8/95 - 1/97).
867c478bd9Sstevel@tonic-gate **			     Sendmail, Inc. (1/98 - present).
877c478bd9Sstevel@tonic-gate **		The support of my employers is gratefully acknowledged.
887c478bd9Sstevel@tonic-gate **			Few of them (Britton-Lee in particular) have had
897c478bd9Sstevel@tonic-gate **			anything to gain from my involvement in this project.
907c478bd9Sstevel@tonic-gate **
917c478bd9Sstevel@tonic-gate **		Gregory Neil Shapiro,
927c478bd9Sstevel@tonic-gate **			Worcester Polytechnic Institute	(until 3/98).
937c478bd9Sstevel@tonic-gate **			Sendmail, Inc. (3/98 - present).
947c478bd9Sstevel@tonic-gate **
957c478bd9Sstevel@tonic-gate **		Claus Assmann,
967c478bd9Sstevel@tonic-gate **			Sendmail, Inc. (12/98 - present).
977c478bd9Sstevel@tonic-gate */
987c478bd9Sstevel@tonic-gate 
997c478bd9Sstevel@tonic-gate char		*FullName;	/* sender's full name */
1007c478bd9Sstevel@tonic-gate ENVELOPE	BlankEnvelope;	/* a "blank" envelope */
1017c478bd9Sstevel@tonic-gate static ENVELOPE	MainEnvelope;	/* the envelope around the basic letter */
1027c478bd9Sstevel@tonic-gate ADDRESS		NullAddress =	/* a null address */
1037c478bd9Sstevel@tonic-gate 		{ "", "", NULL, "" };
1047c478bd9Sstevel@tonic-gate char		*CommandLineArgs;	/* command line args for pid file */
1057c478bd9Sstevel@tonic-gate bool		Warn_Q_option = false;	/* warn about Q option use */
1067c478bd9Sstevel@tonic-gate static int	MissingFds = 0;	/* bit map of fds missing on startup */
1077c478bd9Sstevel@tonic-gate char		*Mbdb = "pw";	/* mailbox database defaults to /etc/passwd */
1087c478bd9Sstevel@tonic-gate 
1097c478bd9Sstevel@tonic-gate #ifdef NGROUPS_MAX
1107c478bd9Sstevel@tonic-gate GIDSET_T	InitialGidSet[NGROUPS_MAX];
1117c478bd9Sstevel@tonic-gate #endif /* NGROUPS_MAX */
1127c478bd9Sstevel@tonic-gate 
1137c478bd9Sstevel@tonic-gate #define MAXCONFIGLEVEL	10	/* highest config version level known */
1147c478bd9Sstevel@tonic-gate 
1157c478bd9Sstevel@tonic-gate #if SASL
1167c478bd9Sstevel@tonic-gate static sasl_callback_t srvcallbacks[] =
1177c478bd9Sstevel@tonic-gate {
1187c478bd9Sstevel@tonic-gate 	{	SASL_CB_VERIFYFILE,	&safesaslfile,	NULL	},
1197c478bd9Sstevel@tonic-gate 	{	SASL_CB_PROXY_POLICY,	&proxy_policy,	NULL	},
1207c478bd9Sstevel@tonic-gate 	{	SASL_CB_LIST_END,	NULL,		NULL	}
1217c478bd9Sstevel@tonic-gate };
1227c478bd9Sstevel@tonic-gate #endif /* SASL */
1237c478bd9Sstevel@tonic-gate 
1247c478bd9Sstevel@tonic-gate unsigned int	SubmitMode;
1257c478bd9Sstevel@tonic-gate int		SyslogPrefixLen; /* estimated length of syslog prefix */
1267c478bd9Sstevel@tonic-gate #define PIDLEN		6	/* pid length for computing SyslogPrefixLen */
1277c478bd9Sstevel@tonic-gate #ifndef SL_FUDGE
1287c478bd9Sstevel@tonic-gate # define SL_FUDGE	10	/* fudge offset for SyslogPrefixLen */
1297c478bd9Sstevel@tonic-gate #endif /* ! SL_FUDGE */
1307c478bd9Sstevel@tonic-gate #define SLDLL		8	/* est. length of default syslog label */
1317c478bd9Sstevel@tonic-gate 
1327c478bd9Sstevel@tonic-gate 
1337c478bd9Sstevel@tonic-gate /* Some options are dangerous to allow users to use in non-submit mode */
1347c478bd9Sstevel@tonic-gate #define CHECK_AGAINST_OPMODE(cmd)					\
1357c478bd9Sstevel@tonic-gate {									\
1367c478bd9Sstevel@tonic-gate 	if (extraprivs &&						\
1377c478bd9Sstevel@tonic-gate 	    OpMode != MD_DELIVER && OpMode != MD_SMTP &&		\
138*e9af4bc0SJohn Beck 	    OpMode != MD_ARPAFTP && OpMode != MD_CHECKCONFIG &&		\
1397c478bd9Sstevel@tonic-gate 	    OpMode != MD_VERIFY && OpMode != MD_TEST)			\
1407c478bd9Sstevel@tonic-gate 	{								\
1417c478bd9Sstevel@tonic-gate 		(void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,		\
1427c478bd9Sstevel@tonic-gate 				     "WARNING: Ignoring submission mode -%c option (not in submission mode)\n", \
1437c478bd9Sstevel@tonic-gate 		       (cmd));						\
1447c478bd9Sstevel@tonic-gate 		break;							\
1457c478bd9Sstevel@tonic-gate 	}								\
1467c478bd9Sstevel@tonic-gate 	if (extraprivs && queuerun)					\
1477c478bd9Sstevel@tonic-gate 	{								\
1487c478bd9Sstevel@tonic-gate 		(void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,		\
1497c478bd9Sstevel@tonic-gate 				     "WARNING: Ignoring submission mode -%c option with -q\n", \
1507c478bd9Sstevel@tonic-gate 		       (cmd));						\
1517c478bd9Sstevel@tonic-gate 		break;							\
1527c478bd9Sstevel@tonic-gate 	}								\
1537c478bd9Sstevel@tonic-gate }
1547c478bd9Sstevel@tonic-gate 
1557c478bd9Sstevel@tonic-gate int
main(argc,argv,envp)1567c478bd9Sstevel@tonic-gate main(argc, argv, envp)
1577c478bd9Sstevel@tonic-gate 	int argc;
1587c478bd9Sstevel@tonic-gate 	char **argv;
1597c478bd9Sstevel@tonic-gate 	char **envp;
1607c478bd9Sstevel@tonic-gate {
1617c478bd9Sstevel@tonic-gate 	register char *p;
1627c478bd9Sstevel@tonic-gate 	char **av;
1637c478bd9Sstevel@tonic-gate 	extern char Version[];
1647c478bd9Sstevel@tonic-gate 	char *ep, *from;
1657c478bd9Sstevel@tonic-gate 	STAB *st;
1667c478bd9Sstevel@tonic-gate 	register int i;
1677c478bd9Sstevel@tonic-gate 	int j;
1687c478bd9Sstevel@tonic-gate 	int dp;
1697c478bd9Sstevel@tonic-gate 	int fill_errno;
1707c478bd9Sstevel@tonic-gate 	int qgrp = NOQGRP;		/* queue group to process */
1717c478bd9Sstevel@tonic-gate 	bool safecf = true;
1727c478bd9Sstevel@tonic-gate 	BITMAP256 *p_flags = NULL;	/* daemon flags */
1737c478bd9Sstevel@tonic-gate 	bool warn_C_flag = false;
1747c478bd9Sstevel@tonic-gate 	bool auth = true;		/* whether to set e_auth_param */
1757c478bd9Sstevel@tonic-gate 	char warn_f_flag = '\0';
1767c478bd9Sstevel@tonic-gate 	bool run_in_foreground = false;	/* -bD mode */
1777c478bd9Sstevel@tonic-gate 	bool queuerun = false, debug = false;
1787c478bd9Sstevel@tonic-gate 	struct passwd *pw;
1797c478bd9Sstevel@tonic-gate 	struct hostent *hp;
1807c478bd9Sstevel@tonic-gate 	char *nullserver = NULL;
1817c478bd9Sstevel@tonic-gate 	char *authinfo = NULL;
1827c478bd9Sstevel@tonic-gate 	char *sysloglabel = NULL;	/* label for syslog */
1837c478bd9Sstevel@tonic-gate 	char *conffile = NULL;		/* name of .cf file */
1847c478bd9Sstevel@tonic-gate 	char *queuegroup = NULL;	/* queue group to process */
1857c478bd9Sstevel@tonic-gate 	char *quarantining = NULL;	/* quarantine queue items? */
1867c478bd9Sstevel@tonic-gate 	bool extraprivs;
1877c478bd9Sstevel@tonic-gate 	bool forged, negate;
1887c478bd9Sstevel@tonic-gate 	bool queuepersistent = false;	/* queue runner process runs forever */
1897c478bd9Sstevel@tonic-gate 	bool foregroundqueue = false;	/* queue run in foreground */
1907c478bd9Sstevel@tonic-gate 	bool save_val;			/* to save some bool var. */
1917c478bd9Sstevel@tonic-gate 	int cftype;			/* which cf file to use? */
1927c478bd9Sstevel@tonic-gate 	SM_FILE_T *smdebug;
1937c478bd9Sstevel@tonic-gate 	static time_t starttime = 0;	/* when was process started */
1947c478bd9Sstevel@tonic-gate 	struct stat traf_st;		/* for TrafficLog FIFO check */
1957c478bd9Sstevel@tonic-gate 	char buf[MAXLINE];
1967c478bd9Sstevel@tonic-gate 	char jbuf[MAXHOSTNAMELEN];	/* holds MyHostName */
1977c478bd9Sstevel@tonic-gate 	static char rnamebuf[MAXNAME];	/* holds RealUserName */
1987c478bd9Sstevel@tonic-gate 	char *emptyenviron[1];
1997c478bd9Sstevel@tonic-gate #if STARTTLS
2007c478bd9Sstevel@tonic-gate 	bool tls_ok;
2017c478bd9Sstevel@tonic-gate #endif /* STARTTLS */
2027c478bd9Sstevel@tonic-gate 	QUEUE_CHAR *new;
2037c478bd9Sstevel@tonic-gate 	ENVELOPE *e;
2047c478bd9Sstevel@tonic-gate 	extern int DtableSize;
2057c478bd9Sstevel@tonic-gate 	extern int optind;
2067c478bd9Sstevel@tonic-gate 	extern int opterr;
2077c478bd9Sstevel@tonic-gate 	extern char *optarg;
2087c478bd9Sstevel@tonic-gate 	extern char **environ;
2097c478bd9Sstevel@tonic-gate #if SASL
2107c478bd9Sstevel@tonic-gate 	extern void sm_sasl_init __P((void));
2117c478bd9Sstevel@tonic-gate #endif /* SASL */
2127c478bd9Sstevel@tonic-gate 
2137c478bd9Sstevel@tonic-gate #if USE_ENVIRON
2147c478bd9Sstevel@tonic-gate 	envp = environ;
2157c478bd9Sstevel@tonic-gate #endif /* USE_ENVIRON */
2167c478bd9Sstevel@tonic-gate 
2177c478bd9Sstevel@tonic-gate 	/* turn off profiling */
2187c478bd9Sstevel@tonic-gate 	SM_PROF(0);
2197c478bd9Sstevel@tonic-gate 
2207c478bd9Sstevel@tonic-gate 	/* install default exception handler */
2217c478bd9Sstevel@tonic-gate 	sm_exc_newthread(fatal_error);
2227c478bd9Sstevel@tonic-gate 
2237c478bd9Sstevel@tonic-gate 	/* set the default in/out channel so errors reported to screen */
2247c478bd9Sstevel@tonic-gate 	InChannel = smioin;
2257c478bd9Sstevel@tonic-gate 	OutChannel = smioout;
2267c478bd9Sstevel@tonic-gate 
2277c478bd9Sstevel@tonic-gate 	/*
2287c478bd9Sstevel@tonic-gate 	**  Check to see if we reentered.
2297c478bd9Sstevel@tonic-gate 	**	This would normally happen if e_putheader or e_putbody
2307c478bd9Sstevel@tonic-gate 	**	were NULL when invoked.
2317c478bd9Sstevel@tonic-gate 	*/
2327c478bd9Sstevel@tonic-gate 
2337c478bd9Sstevel@tonic-gate 	if (starttime != 0)
2347c478bd9Sstevel@tonic-gate 	{
2357c478bd9Sstevel@tonic-gate 		syserr("main: reentered!");
2367c478bd9Sstevel@tonic-gate 		abort();
2377c478bd9Sstevel@tonic-gate 	}
2387c478bd9Sstevel@tonic-gate 	starttime = curtime();
2397c478bd9Sstevel@tonic-gate 
2407c478bd9Sstevel@tonic-gate 	/* avoid null pointer dereferences */
241058561cbSjbeck 	TermEscape.te_rv_on = TermEscape.te_under_on = TermEscape.te_normal = "";
2427c478bd9Sstevel@tonic-gate 
2437c478bd9Sstevel@tonic-gate 	RealUid = getuid();
2447c478bd9Sstevel@tonic-gate 	RealGid = getgid();
2457c478bd9Sstevel@tonic-gate 
2467c478bd9Sstevel@tonic-gate 	/* Check if sendmail is running with extra privs */
2477c478bd9Sstevel@tonic-gate 	extraprivs = (RealUid != 0 &&
2487c478bd9Sstevel@tonic-gate 		      (geteuid() != getuid() || getegid() != getgid()));
2497c478bd9Sstevel@tonic-gate 
2507c478bd9Sstevel@tonic-gate 	CurrentPid = getpid();
2517c478bd9Sstevel@tonic-gate 
2527c478bd9Sstevel@tonic-gate 	/* get whatever .cf file is right for the opmode */
2537c478bd9Sstevel@tonic-gate 	cftype = SM_GET_RIGHT_CF;
2547c478bd9Sstevel@tonic-gate 
2557c478bd9Sstevel@tonic-gate 	/* in 4.4BSD, the table can be huge; impose a reasonable limit */
2567c478bd9Sstevel@tonic-gate 	DtableSize = getdtsize();
2577c478bd9Sstevel@tonic-gate 	if (DtableSize > 256)
2587c478bd9Sstevel@tonic-gate 		DtableSize = 256;
2597c478bd9Sstevel@tonic-gate 
2607c478bd9Sstevel@tonic-gate 	/*
2617c478bd9Sstevel@tonic-gate 	**  Be sure we have enough file descriptors.
2627c478bd9Sstevel@tonic-gate 	**	But also be sure that 0, 1, & 2 are open.
2637c478bd9Sstevel@tonic-gate 	*/
2647c478bd9Sstevel@tonic-gate 
2657c478bd9Sstevel@tonic-gate 	/* reset errno and fill_errno; the latter is used way down below */
2667c478bd9Sstevel@tonic-gate 	errno = fill_errno = 0;
2677c478bd9Sstevel@tonic-gate 	fill_fd(STDIN_FILENO, NULL);
2687c478bd9Sstevel@tonic-gate 	if (errno != 0)
2697c478bd9Sstevel@tonic-gate 		fill_errno = errno;
2707c478bd9Sstevel@tonic-gate 	fill_fd(STDOUT_FILENO, NULL);
2717c478bd9Sstevel@tonic-gate 	if (errno != 0)
2727c478bd9Sstevel@tonic-gate 		fill_errno = errno;
2737c478bd9Sstevel@tonic-gate 	fill_fd(STDERR_FILENO, NULL);
2747c478bd9Sstevel@tonic-gate 	if (errno != 0)
2757c478bd9Sstevel@tonic-gate 		fill_errno = errno;
2767c478bd9Sstevel@tonic-gate 
2777c478bd9Sstevel@tonic-gate 	sm_closefrom(STDERR_FILENO + 1, DtableSize);
2787c478bd9Sstevel@tonic-gate 	errno = 0;
2797c478bd9Sstevel@tonic-gate 	smdebug = NULL;
2807c478bd9Sstevel@tonic-gate 
2817c478bd9Sstevel@tonic-gate #if LOG
2827c478bd9Sstevel@tonic-gate # ifndef SM_LOG_STR
2837c478bd9Sstevel@tonic-gate #  define SM_LOG_STR	"sendmail"
2847c478bd9Sstevel@tonic-gate # endif /* ! SM_LOG_STR */
2857c478bd9Sstevel@tonic-gate #  ifdef LOG_MAIL
2867c478bd9Sstevel@tonic-gate 	openlog(SM_LOG_STR, LOG_PID, LOG_MAIL);
2877c478bd9Sstevel@tonic-gate #  else /* LOG_MAIL */
2887c478bd9Sstevel@tonic-gate 	openlog(SM_LOG_STR, LOG_PID);
2897c478bd9Sstevel@tonic-gate #  endif /* LOG_MAIL */
2907c478bd9Sstevel@tonic-gate #endif /* LOG */
2917c478bd9Sstevel@tonic-gate 
2927c478bd9Sstevel@tonic-gate 	/*
2937c478bd9Sstevel@tonic-gate 	**  Seed the random number generator.
2947c478bd9Sstevel@tonic-gate 	**  Used for queue file names, picking a queue directory, and
2957c478bd9Sstevel@tonic-gate 	**  MX randomization.
2967c478bd9Sstevel@tonic-gate 	*/
2977c478bd9Sstevel@tonic-gate 
2987c478bd9Sstevel@tonic-gate 	seed_random();
2997c478bd9Sstevel@tonic-gate 
3007c478bd9Sstevel@tonic-gate 	/* do machine-dependent initializations */
3017c478bd9Sstevel@tonic-gate 	init_md(argc, argv);
3027c478bd9Sstevel@tonic-gate 
3037c478bd9Sstevel@tonic-gate 
3047c478bd9Sstevel@tonic-gate 	SyslogPrefixLen = PIDLEN + (MAXQFNAME - 3) + SL_FUDGE + SLDLL;
3057c478bd9Sstevel@tonic-gate 
3067c478bd9Sstevel@tonic-gate 	/* reset status from syserr() calls for missing file descriptors */
3077c478bd9Sstevel@tonic-gate 	Errors = 0;
3087c478bd9Sstevel@tonic-gate 	ExitStat = EX_OK;
3097c478bd9Sstevel@tonic-gate 
3107c478bd9Sstevel@tonic-gate 	SubmitMode = SUBMIT_UNKNOWN;
311d4660949Sjbeck #if _FFR_LOCAL_DAEMON
312d4660949Sjbeck 	LocalDaemon = false;
313d4660949Sjbeck #endif /* _FFR_LOCAL_DAEMON */
3147c478bd9Sstevel@tonic-gate #if XDEBUG
3157c478bd9Sstevel@tonic-gate 	checkfd012("after openlog");
3167c478bd9Sstevel@tonic-gate #endif /* XDEBUG */
3177c478bd9Sstevel@tonic-gate 
318058561cbSjbeck 	tTsetup(tTdvect, sizeof(tTdvect), "0-99.1,*_trace_*.1");
3197c478bd9Sstevel@tonic-gate 
3207c478bd9Sstevel@tonic-gate #ifdef NGROUPS_MAX
3217c478bd9Sstevel@tonic-gate 	/* save initial group set for future checks */
3227c478bd9Sstevel@tonic-gate 	i = getgroups(NGROUPS_MAX, InitialGidSet);
3237c478bd9Sstevel@tonic-gate 	if (i <= 0)
3247c478bd9Sstevel@tonic-gate 	{
3257c478bd9Sstevel@tonic-gate 		InitialGidSet[0] = (GID_T) -1;
3267c478bd9Sstevel@tonic-gate 		i = 0;
3277c478bd9Sstevel@tonic-gate 	}
3287c478bd9Sstevel@tonic-gate 	while (i < NGROUPS_MAX)
3297c478bd9Sstevel@tonic-gate 		InitialGidSet[i++] = InitialGidSet[0];
3307c478bd9Sstevel@tonic-gate #endif /* NGROUPS_MAX */
3317c478bd9Sstevel@tonic-gate 
3327c478bd9Sstevel@tonic-gate 	/* drop group id privileges (RunAsUser not yet set) */
3337c478bd9Sstevel@tonic-gate 	dp = drop_privileges(false);
3347c478bd9Sstevel@tonic-gate 	setstat(dp);
3357c478bd9Sstevel@tonic-gate 
3367c478bd9Sstevel@tonic-gate #ifdef SIGUSR1
3377c478bd9Sstevel@tonic-gate 	/* Only allow root (or non-set-*-ID binaries) to use SIGUSR1 */
3387c478bd9Sstevel@tonic-gate 	if (!extraprivs)
3397c478bd9Sstevel@tonic-gate 	{
3407c478bd9Sstevel@tonic-gate 		/* arrange to dump state on user-1 signal */
3417c478bd9Sstevel@tonic-gate 		(void) sm_signal(SIGUSR1, sigusr1);
3427c478bd9Sstevel@tonic-gate 	}
3437c478bd9Sstevel@tonic-gate 	else
3447c478bd9Sstevel@tonic-gate 	{
3457c478bd9Sstevel@tonic-gate 		/* ignore user-1 signal */
3467c478bd9Sstevel@tonic-gate 		(void) sm_signal(SIGUSR1, SIG_IGN);
3477c478bd9Sstevel@tonic-gate 	}
3487c478bd9Sstevel@tonic-gate #endif /* SIGUSR1 */
3497c478bd9Sstevel@tonic-gate 
3507c478bd9Sstevel@tonic-gate 	/* initialize for setproctitle */
3517c478bd9Sstevel@tonic-gate 	initsetproctitle(argc, argv, envp);
3527c478bd9Sstevel@tonic-gate 
3537c478bd9Sstevel@tonic-gate 	/* Handle any non-getoptable constructions. */
3547c478bd9Sstevel@tonic-gate 	obsolete(argv);
3557c478bd9Sstevel@tonic-gate 
3567c478bd9Sstevel@tonic-gate 	/*
3577c478bd9Sstevel@tonic-gate 	**  Do a quick prescan of the argument list.
3587c478bd9Sstevel@tonic-gate 	*/
3597c478bd9Sstevel@tonic-gate 
3607c478bd9Sstevel@tonic-gate 
3617c478bd9Sstevel@tonic-gate 	/* find initial opMode */
3627c478bd9Sstevel@tonic-gate 	OpMode = MD_DELIVER;
3637c478bd9Sstevel@tonic-gate 	av = argv;
3647c478bd9Sstevel@tonic-gate 	p = strrchr(*av, '/');
3657c478bd9Sstevel@tonic-gate 	if (p++ == NULL)
3667c478bd9Sstevel@tonic-gate 		p = *av;
3677c478bd9Sstevel@tonic-gate 	if (strcmp(p, "newaliases") == 0)
3687c478bd9Sstevel@tonic-gate 		OpMode = MD_INITALIAS;
3697c478bd9Sstevel@tonic-gate 	else if (strcmp(p, "mailq") == 0)
3707c478bd9Sstevel@tonic-gate 		OpMode = MD_PRINT;
3717c478bd9Sstevel@tonic-gate 	else if (strcmp(p, "smtpd") == 0)
3727c478bd9Sstevel@tonic-gate 		OpMode = MD_DAEMON;
3737c478bd9Sstevel@tonic-gate 	else if (strcmp(p, "hoststat") == 0)
3747c478bd9Sstevel@tonic-gate 		OpMode = MD_HOSTSTAT;
3757c478bd9Sstevel@tonic-gate 	else if (strcmp(p, "purgestat") == 0)
3767c478bd9Sstevel@tonic-gate 		OpMode = MD_PURGESTAT;
3777c478bd9Sstevel@tonic-gate 
3787c478bd9Sstevel@tonic-gate #if defined(__osf__) || defined(_AIX3)
3797c478bd9Sstevel@tonic-gate # 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"
3807c478bd9Sstevel@tonic-gate #endif /* defined(__osf__) || defined(_AIX3) */
3817c478bd9Sstevel@tonic-gate #if defined(sony_news)
3827c478bd9Sstevel@tonic-gate # 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:"
3837c478bd9Sstevel@tonic-gate #endif /* defined(sony_news) */
3847c478bd9Sstevel@tonic-gate #ifndef OPTIONS
3857c478bd9Sstevel@tonic-gate # define OPTIONS	"A:B:b:C:cD:d:e:F:f:Gh:IiL:M:mN:nO:o:p:Q:q:R:r:sTtV:vX:"
3867c478bd9Sstevel@tonic-gate #endif /* ! OPTIONS */
3877c478bd9Sstevel@tonic-gate 
3887c478bd9Sstevel@tonic-gate 	/* Set to 0 to allow -b; need to check optarg before using it! */
3897c478bd9Sstevel@tonic-gate 	opterr = 0;
3907c478bd9Sstevel@tonic-gate 	while ((j = getopt(argc, argv, OPTIONS)) != -1)
3917c478bd9Sstevel@tonic-gate 	{
3927c478bd9Sstevel@tonic-gate 		switch (j)
3937c478bd9Sstevel@tonic-gate 		{
3947c478bd9Sstevel@tonic-gate 		  case 'b':	/* operations mode */
3957c478bd9Sstevel@tonic-gate 			j = (optarg == NULL) ? ' ' : *optarg;
3967c478bd9Sstevel@tonic-gate 			switch (j)
3977c478bd9Sstevel@tonic-gate 			{
3987c478bd9Sstevel@tonic-gate 			  case MD_DAEMON:
3997c478bd9Sstevel@tonic-gate 			  case MD_FGDAEMON:
4007c478bd9Sstevel@tonic-gate 			  case MD_SMTP:
4017c478bd9Sstevel@tonic-gate 			  case MD_INITALIAS:
4027c478bd9Sstevel@tonic-gate 			  case MD_DELIVER:
4037c478bd9Sstevel@tonic-gate 			  case MD_VERIFY:
4047c478bd9Sstevel@tonic-gate 			  case MD_TEST:
4057c478bd9Sstevel@tonic-gate 			  case MD_PRINT:
4067c478bd9Sstevel@tonic-gate 			  case MD_PRINTNQE:
4077c478bd9Sstevel@tonic-gate 			  case MD_HOSTSTAT:
4087c478bd9Sstevel@tonic-gate 			  case MD_PURGESTAT:
4097c478bd9Sstevel@tonic-gate 			  case MD_ARPAFTP:
410*e9af4bc0SJohn Beck #if _FFR_CHECKCONFIG
411*e9af4bc0SJohn Beck 			  case MD_CHECKCONFIG:
412*e9af4bc0SJohn Beck #endif /* _FFR_CHECKCONFIG */
4137c478bd9Sstevel@tonic-gate 				OpMode = j;
4147c478bd9Sstevel@tonic-gate 				break;
4157c478bd9Sstevel@tonic-gate 
416d4660949Sjbeck #if _FFR_LOCAL_DAEMON
417d4660949Sjbeck 			  case MD_LOCAL:
418d4660949Sjbeck 				OpMode = MD_DAEMON;
419d4660949Sjbeck 				LocalDaemon = true;
420d4660949Sjbeck 				break;
421d4660949Sjbeck #endif /* _FFR_LOCAL_DAEMON */
422d4660949Sjbeck 
4237c478bd9Sstevel@tonic-gate 			  case MD_FREEZE:
4247c478bd9Sstevel@tonic-gate 				(void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
4257c478bd9Sstevel@tonic-gate 						     "Frozen configurations unsupported\n");
4267c478bd9Sstevel@tonic-gate 				return EX_USAGE;
4277c478bd9Sstevel@tonic-gate 
4287c478bd9Sstevel@tonic-gate 			  default:
4297c478bd9Sstevel@tonic-gate 				(void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
4307c478bd9Sstevel@tonic-gate 						     "Invalid operation mode %c\n",
4317c478bd9Sstevel@tonic-gate 						     j);
4327c478bd9Sstevel@tonic-gate 				return EX_USAGE;
4337c478bd9Sstevel@tonic-gate 			}
4347c478bd9Sstevel@tonic-gate 			break;
4357c478bd9Sstevel@tonic-gate 
4367c478bd9Sstevel@tonic-gate 		  case 'D':
4377c478bd9Sstevel@tonic-gate 			if (debug)
4387c478bd9Sstevel@tonic-gate 			{
4397c478bd9Sstevel@tonic-gate 				errno = 0;
4407c478bd9Sstevel@tonic-gate 				syserr("-D file must be before -d");
4417c478bd9Sstevel@tonic-gate 				ExitStat = EX_USAGE;
4427c478bd9Sstevel@tonic-gate 				break;
4437c478bd9Sstevel@tonic-gate 			}
4447c478bd9Sstevel@tonic-gate 			dp = drop_privileges(true);
4457c478bd9Sstevel@tonic-gate 			setstat(dp);
4467c478bd9Sstevel@tonic-gate 			smdebug = sm_io_open(SmFtStdio, SM_TIME_DEFAULT,
4477c478bd9Sstevel@tonic-gate 					    optarg, SM_IO_APPEND, NULL);
4487c478bd9Sstevel@tonic-gate 			if (smdebug == NULL)
4497c478bd9Sstevel@tonic-gate 			{
4507c478bd9Sstevel@tonic-gate 				syserr("cannot open %s", optarg);
4517c478bd9Sstevel@tonic-gate 				ExitStat = EX_CANTCREAT;
4527c478bd9Sstevel@tonic-gate 				break;
4537c478bd9Sstevel@tonic-gate 			}
4547c478bd9Sstevel@tonic-gate 			sm_debug_setfile(smdebug);
4557c478bd9Sstevel@tonic-gate 			break;
4567c478bd9Sstevel@tonic-gate 
4577c478bd9Sstevel@tonic-gate 		  case 'd':
4587c478bd9Sstevel@tonic-gate 			debug = true;
4597c478bd9Sstevel@tonic-gate 			tTflag(optarg);
4607c478bd9Sstevel@tonic-gate 			(void) sm_io_setvbuf(sm_debug_file(), SM_TIME_DEFAULT,
4617c478bd9Sstevel@tonic-gate 					     (char *) NULL, SM_IO_NBF,
4627c478bd9Sstevel@tonic-gate 					     SM_IO_BUFSIZ);
4637c478bd9Sstevel@tonic-gate 			break;
4647c478bd9Sstevel@tonic-gate 
4657c478bd9Sstevel@tonic-gate 		  case 'G':	/* relay (gateway) submission */
4667c478bd9Sstevel@tonic-gate 			SubmitMode = SUBMIT_MTA;
4677c478bd9Sstevel@tonic-gate 			break;
4687c478bd9Sstevel@tonic-gate 
4697c478bd9Sstevel@tonic-gate 		  case 'L':
4707c478bd9Sstevel@tonic-gate 			if (optarg == NULL)
4717c478bd9Sstevel@tonic-gate 			{
4727c478bd9Sstevel@tonic-gate 				(void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
4737c478bd9Sstevel@tonic-gate 						     "option requires an argument -- '%c'",
4747c478bd9Sstevel@tonic-gate 						     (char) j);
4757c478bd9Sstevel@tonic-gate 				return EX_USAGE;
4767c478bd9Sstevel@tonic-gate 			}
4777c478bd9Sstevel@tonic-gate 			j = SM_MIN(strlen(optarg), 32) + 1;
4787c478bd9Sstevel@tonic-gate 			sysloglabel = xalloc(j);
4797c478bd9Sstevel@tonic-gate 			(void) sm_strlcpy(sysloglabel, optarg, j);
4807c478bd9Sstevel@tonic-gate 			SyslogPrefixLen = PIDLEN + (MAXQFNAME - 3) +
4817c478bd9Sstevel@tonic-gate 					  SL_FUDGE + j;
4827c478bd9Sstevel@tonic-gate 			break;
4837c478bd9Sstevel@tonic-gate 
4847c478bd9Sstevel@tonic-gate 		  case 'Q':
4857c478bd9Sstevel@tonic-gate 		  case 'q':
4867c478bd9Sstevel@tonic-gate 			/* just check if it is there */
4877c478bd9Sstevel@tonic-gate 			queuerun = true;
4887c478bd9Sstevel@tonic-gate 			break;
4897c478bd9Sstevel@tonic-gate 		}
4907c478bd9Sstevel@tonic-gate 	}
4917c478bd9Sstevel@tonic-gate 	opterr = 1;
4927c478bd9Sstevel@tonic-gate 
4937c478bd9Sstevel@tonic-gate 	/* Don't leak queue information via debug flags */
4947c478bd9Sstevel@tonic-gate 	if (extraprivs && queuerun && debug)
4957c478bd9Sstevel@tonic-gate 	{
4967c478bd9Sstevel@tonic-gate 		(void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
4977c478bd9Sstevel@tonic-gate 				     "WARNING: Can not use -d with -q.  Disabling debugging.\n");
4987c478bd9Sstevel@tonic-gate 		sm_debug_close();
4997c478bd9Sstevel@tonic-gate 		sm_debug_setfile(NULL);
500058561cbSjbeck 		(void) memset(tTdvect, '\0', sizeof(tTdvect));
5017c478bd9Sstevel@tonic-gate 	}
5027c478bd9Sstevel@tonic-gate 
5037c478bd9Sstevel@tonic-gate #if LOG
5047c478bd9Sstevel@tonic-gate 	if (sysloglabel != NULL)
5057c478bd9Sstevel@tonic-gate 	{
5067c478bd9Sstevel@tonic-gate 		/* Sanitize the string */
5077c478bd9Sstevel@tonic-gate 		for (p = sysloglabel; *p != '\0'; p++)
5087c478bd9Sstevel@tonic-gate 		{
5097c478bd9Sstevel@tonic-gate 			if (!isascii(*p) || !isprint(*p) || *p == '%')
5107c478bd9Sstevel@tonic-gate 				*p = '*';
5117c478bd9Sstevel@tonic-gate 		}
5127c478bd9Sstevel@tonic-gate 		closelog();
5137c478bd9Sstevel@tonic-gate #  ifdef LOG_MAIL
5147c478bd9Sstevel@tonic-gate 		openlog(sysloglabel, LOG_PID, LOG_MAIL);
5157c478bd9Sstevel@tonic-gate #  else /* LOG_MAIL */
5167c478bd9Sstevel@tonic-gate 		openlog(sysloglabel, LOG_PID);
5177c478bd9Sstevel@tonic-gate #  endif /* LOG_MAIL */
5187c478bd9Sstevel@tonic-gate 	}
5197c478bd9Sstevel@tonic-gate #endif /* LOG */
5207c478bd9Sstevel@tonic-gate 
5217c478bd9Sstevel@tonic-gate 	/* set up the blank envelope */
5227c478bd9Sstevel@tonic-gate 	BlankEnvelope.e_puthdr = putheader;
5237c478bd9Sstevel@tonic-gate 	BlankEnvelope.e_putbody = putbody;
5247c478bd9Sstevel@tonic-gate 	BlankEnvelope.e_xfp = NULL;
5257c478bd9Sstevel@tonic-gate 	STRUCTCOPY(NullAddress, BlankEnvelope.e_from);
5267c478bd9Sstevel@tonic-gate 	CurEnv = &BlankEnvelope;
5277c478bd9Sstevel@tonic-gate 	STRUCTCOPY(NullAddress, MainEnvelope.e_from);
5287c478bd9Sstevel@tonic-gate 
5297c478bd9Sstevel@tonic-gate 	/*
5307c478bd9Sstevel@tonic-gate 	**  Set default values for variables.
5317c478bd9Sstevel@tonic-gate 	**	These cannot be in initialized data space.
5327c478bd9Sstevel@tonic-gate 	*/
5337c478bd9Sstevel@tonic-gate 
5347c478bd9Sstevel@tonic-gate 	setdefaults(&BlankEnvelope);
5357c478bd9Sstevel@tonic-gate 	initmacros(&BlankEnvelope);
5367c478bd9Sstevel@tonic-gate 
5377c478bd9Sstevel@tonic-gate 	/* reset macro */
5387c478bd9Sstevel@tonic-gate 	set_op_mode(OpMode);
5393ee0e492Sjbeck 	if (OpMode == MD_DAEMON)
5403ee0e492Sjbeck 		DaemonPid = CurrentPid;	/* needed for finis() to work */
5417c478bd9Sstevel@tonic-gate 
5427c478bd9Sstevel@tonic-gate 	pw = sm_getpwuid(RealUid);
5437c478bd9Sstevel@tonic-gate 	if (pw != NULL)
544058561cbSjbeck 		(void) sm_strlcpy(rnamebuf, pw->pw_name, sizeof(rnamebuf));
5457c478bd9Sstevel@tonic-gate 	else
546058561cbSjbeck 		(void) sm_snprintf(rnamebuf, sizeof(rnamebuf), "Unknown UID %d",
5477c478bd9Sstevel@tonic-gate 				   (int) RealUid);
5487c478bd9Sstevel@tonic-gate 
5497c478bd9Sstevel@tonic-gate 	RealUserName = rnamebuf;
5507c478bd9Sstevel@tonic-gate 
5517c478bd9Sstevel@tonic-gate 	if (tTd(0, 101))
5527c478bd9Sstevel@tonic-gate 	{
5537c478bd9Sstevel@tonic-gate 		sm_dprintf("Version %s\n", Version);
5547c478bd9Sstevel@tonic-gate 		finis(false, true, EX_OK);
5557c478bd9Sstevel@tonic-gate 		/* NOTREACHED */
5567c478bd9Sstevel@tonic-gate 	}
5577c478bd9Sstevel@tonic-gate 
5587c478bd9Sstevel@tonic-gate 	/*
5597c478bd9Sstevel@tonic-gate 	**  if running non-set-user-ID binary as non-root, pretend
5607c478bd9Sstevel@tonic-gate 	**  we are the RunAsUid
5617c478bd9Sstevel@tonic-gate 	*/
5627c478bd9Sstevel@tonic-gate 
5637c478bd9Sstevel@tonic-gate 	if (RealUid != 0 && geteuid() == RealUid)
5647c478bd9Sstevel@tonic-gate 	{
5657c478bd9Sstevel@tonic-gate 		if (tTd(47, 1))
5667c478bd9Sstevel@tonic-gate 			sm_dprintf("Non-set-user-ID binary: RunAsUid = RealUid = %d\n",
5677c478bd9Sstevel@tonic-gate 				   (int) RealUid);
5687c478bd9Sstevel@tonic-gate 		RunAsUid = RealUid;
5697c478bd9Sstevel@tonic-gate 	}
5707c478bd9Sstevel@tonic-gate 	else if (geteuid() != 0)
5717c478bd9Sstevel@tonic-gate 		RunAsUid = geteuid();
5727c478bd9Sstevel@tonic-gate 
5737c478bd9Sstevel@tonic-gate 	EffGid = getegid();
5747c478bd9Sstevel@tonic-gate 	if (RealUid != 0 && EffGid == RealGid)
5757c478bd9Sstevel@tonic-gate 		RunAsGid = RealGid;
5767c478bd9Sstevel@tonic-gate 
5777c478bd9Sstevel@tonic-gate 	if (tTd(47, 5))
5787c478bd9Sstevel@tonic-gate 	{
5797c478bd9Sstevel@tonic-gate 		sm_dprintf("main: e/ruid = %d/%d e/rgid = %d/%d\n",
5807c478bd9Sstevel@tonic-gate 			   (int) geteuid(), (int) getuid(),
5817c478bd9Sstevel@tonic-gate 			   (int) getegid(), (int) getgid());
5827c478bd9Sstevel@tonic-gate 		sm_dprintf("main: RunAsUser = %d:%d\n",
5837c478bd9Sstevel@tonic-gate 			   (int) RunAsUid, (int) RunAsGid);
5847c478bd9Sstevel@tonic-gate 	}
5857c478bd9Sstevel@tonic-gate 
5867c478bd9Sstevel@tonic-gate 	/* save command line arguments */
5877c478bd9Sstevel@tonic-gate 	j = 0;
5887c478bd9Sstevel@tonic-gate 	for (av = argv; *av != NULL; )
5897c478bd9Sstevel@tonic-gate 		j += strlen(*av++) + 1;
590058561cbSjbeck 	SaveArgv = (char **) xalloc(sizeof(char *) * (argc + 1));
5917c478bd9Sstevel@tonic-gate 	CommandLineArgs = xalloc(j);
5927c478bd9Sstevel@tonic-gate 	p = CommandLineArgs;
5937c478bd9Sstevel@tonic-gate 	for (av = argv, i = 0; *av != NULL; )
5947c478bd9Sstevel@tonic-gate 	{
5957c478bd9Sstevel@tonic-gate 		int h;
5967c478bd9Sstevel@tonic-gate 
5977c478bd9Sstevel@tonic-gate 		SaveArgv[i++] = newstr(*av);
5987c478bd9Sstevel@tonic-gate 		if (av != argv)
5997c478bd9Sstevel@tonic-gate 			*p++ = ' ';
6007c478bd9Sstevel@tonic-gate 		(void) sm_strlcpy(p, *av++, j);
6017c478bd9Sstevel@tonic-gate 		h = strlen(p);
6027c478bd9Sstevel@tonic-gate 		p += h;
6037c478bd9Sstevel@tonic-gate 		j -= h + 1;
6047c478bd9Sstevel@tonic-gate 	}
6057c478bd9Sstevel@tonic-gate 	SaveArgv[i] = NULL;
6067c478bd9Sstevel@tonic-gate 
6077c478bd9Sstevel@tonic-gate 	if (tTd(0, 1))
6087c478bd9Sstevel@tonic-gate 	{
6097c478bd9Sstevel@tonic-gate 		extern char *CompileOptions[];
6107c478bd9Sstevel@tonic-gate 
6117c478bd9Sstevel@tonic-gate 		sm_dprintf("Version %s\n Compiled with:", Version);
6127c478bd9Sstevel@tonic-gate 		sm_printoptions(CompileOptions);
6137c478bd9Sstevel@tonic-gate 	}
6147c478bd9Sstevel@tonic-gate 	if (tTd(0, 10))
6157c478bd9Sstevel@tonic-gate 	{
6167c478bd9Sstevel@tonic-gate 		extern char *OsCompileOptions[];
6177c478bd9Sstevel@tonic-gate 
6187c478bd9Sstevel@tonic-gate 		sm_dprintf("    OS Defines:");
6197c478bd9Sstevel@tonic-gate 		sm_printoptions(OsCompileOptions);
6207c478bd9Sstevel@tonic-gate #ifdef _PATH_UNIX
6217c478bd9Sstevel@tonic-gate 		sm_dprintf("Kernel symbols:\t%s\n", _PATH_UNIX);
6227c478bd9Sstevel@tonic-gate #endif /* _PATH_UNIX */
6237c478bd9Sstevel@tonic-gate 
6247c478bd9Sstevel@tonic-gate 		sm_dprintf("     Conf file:\t%s (default for MSP)\n",
6257c478bd9Sstevel@tonic-gate 			   getcfname(OpMode, SubmitMode, SM_GET_SUBMIT_CF,
6267c478bd9Sstevel@tonic-gate 				     conffile));
6277c478bd9Sstevel@tonic-gate 		sm_dprintf("     Conf file:\t%s (default for MTA)\n",
6287c478bd9Sstevel@tonic-gate 			   getcfname(OpMode, SubmitMode, SM_GET_SENDMAIL_CF,
6297c478bd9Sstevel@tonic-gate 				     conffile));
6307c478bd9Sstevel@tonic-gate 		sm_dprintf("      Pid file:\t%s (default)\n", PidFile);
6317c478bd9Sstevel@tonic-gate 	}
6327c478bd9Sstevel@tonic-gate 
6337c478bd9Sstevel@tonic-gate 	if (tTd(0, 12))
6347c478bd9Sstevel@tonic-gate 	{
6357c478bd9Sstevel@tonic-gate 		extern char *SmCompileOptions[];
6367c478bd9Sstevel@tonic-gate 
6377c478bd9Sstevel@tonic-gate 		sm_dprintf(" libsm Defines:");
6387c478bd9Sstevel@tonic-gate 		sm_printoptions(SmCompileOptions);
6397c478bd9Sstevel@tonic-gate 	}
6407c478bd9Sstevel@tonic-gate 
6417c478bd9Sstevel@tonic-gate 	if (tTd(0, 13))
6427c478bd9Sstevel@tonic-gate 	{
6437c478bd9Sstevel@tonic-gate 		extern char *FFRCompileOptions[];
6447c478bd9Sstevel@tonic-gate 
6457c478bd9Sstevel@tonic-gate 		sm_dprintf("   FFR Defines:");
6467c478bd9Sstevel@tonic-gate 		sm_printoptions(FFRCompileOptions);
6477c478bd9Sstevel@tonic-gate 	}
6487c478bd9Sstevel@tonic-gate 
6497c478bd9Sstevel@tonic-gate 	/* clear sendmail's environment */
6507c478bd9Sstevel@tonic-gate 	ExternalEnviron = environ;
6517c478bd9Sstevel@tonic-gate 	emptyenviron[0] = NULL;
6527c478bd9Sstevel@tonic-gate 	environ = emptyenviron;
6537c478bd9Sstevel@tonic-gate 
6547c478bd9Sstevel@tonic-gate 	/*
6557c478bd9Sstevel@tonic-gate 	**  restore any original TZ setting until TimeZoneSpec has been
6567c478bd9Sstevel@tonic-gate 	**  determined - or early log messages may get bogus time stamps
6577c478bd9Sstevel@tonic-gate 	*/
6587c478bd9Sstevel@tonic-gate 
6597c478bd9Sstevel@tonic-gate 	if ((p = getextenv("TZ")) != NULL)
6607c478bd9Sstevel@tonic-gate 	{
6617c478bd9Sstevel@tonic-gate 		char *tz;
6627c478bd9Sstevel@tonic-gate 		int tzlen;
6637c478bd9Sstevel@tonic-gate 
6647c478bd9Sstevel@tonic-gate 		/* XXX check for reasonable length? */
6657c478bd9Sstevel@tonic-gate 		tzlen = strlen(p) + 4;
6667c478bd9Sstevel@tonic-gate 		tz = xalloc(tzlen);
6677c478bd9Sstevel@tonic-gate 		(void) sm_strlcpyn(tz, tzlen, 2, "TZ=", p);
6687c478bd9Sstevel@tonic-gate 
6697c478bd9Sstevel@tonic-gate 		/* XXX check return code? */
6707c478bd9Sstevel@tonic-gate 		(void) putenv(tz);
6717c478bd9Sstevel@tonic-gate 	}
6727c478bd9Sstevel@tonic-gate 
6737c478bd9Sstevel@tonic-gate 	/* prime the child environment */
674445f2479Sjbeck 	sm_setuserenv("AGENT", "sendmail");
6757c478bd9Sstevel@tonic-gate 
6767c478bd9Sstevel@tonic-gate 	(void) sm_signal(SIGPIPE, SIG_IGN);
6777c478bd9Sstevel@tonic-gate 	OldUmask = umask(022);
6787c478bd9Sstevel@tonic-gate 	FullName = getextenv("NAME");
6797c478bd9Sstevel@tonic-gate 	if (FullName != NULL)
6807c478bd9Sstevel@tonic-gate 		FullName = newstr(FullName);
6817c478bd9Sstevel@tonic-gate 
6827c478bd9Sstevel@tonic-gate 	/*
6837c478bd9Sstevel@tonic-gate 	**  Initialize name server if it is going to be used.
6847c478bd9Sstevel@tonic-gate 	*/
6857c478bd9Sstevel@tonic-gate 
6867c478bd9Sstevel@tonic-gate #if NAMED_BIND
6877c478bd9Sstevel@tonic-gate 	if (!bitset(RES_INIT, _res.options))
6887c478bd9Sstevel@tonic-gate 		(void) res_init();
6897c478bd9Sstevel@tonic-gate 	if (tTd(8, 8))
6907c478bd9Sstevel@tonic-gate 		_res.options |= RES_DEBUG;
6917c478bd9Sstevel@tonic-gate 	else
6927c478bd9Sstevel@tonic-gate 		_res.options &= ~RES_DEBUG;
6937c478bd9Sstevel@tonic-gate # ifdef RES_NOALIASES
6947c478bd9Sstevel@tonic-gate 	_res.options |= RES_NOALIASES;
6957c478bd9Sstevel@tonic-gate # endif /* RES_NOALIASES */
6967c478bd9Sstevel@tonic-gate 	TimeOuts.res_retry[RES_TO_DEFAULT] = _res.retry;
6977c478bd9Sstevel@tonic-gate 	TimeOuts.res_retry[RES_TO_FIRST] = _res.retry;
6987c478bd9Sstevel@tonic-gate 	TimeOuts.res_retry[RES_TO_NORMAL] = _res.retry;
6997c478bd9Sstevel@tonic-gate 	TimeOuts.res_retrans[RES_TO_DEFAULT] = _res.retrans;
7007c478bd9Sstevel@tonic-gate 	TimeOuts.res_retrans[RES_TO_FIRST] = _res.retrans;
7017c478bd9Sstevel@tonic-gate 	TimeOuts.res_retrans[RES_TO_NORMAL] = _res.retrans;
7027c478bd9Sstevel@tonic-gate #endif /* NAMED_BIND */
7037c478bd9Sstevel@tonic-gate 
7047c478bd9Sstevel@tonic-gate 	errno = 0;
7057c478bd9Sstevel@tonic-gate 	from = NULL;
7067c478bd9Sstevel@tonic-gate 
7077c478bd9Sstevel@tonic-gate 	/* initialize some macros, etc. */
7087c478bd9Sstevel@tonic-gate 	init_vendor_macros(&BlankEnvelope);
7097c478bd9Sstevel@tonic-gate 
7107c478bd9Sstevel@tonic-gate 	/* version */
7117c478bd9Sstevel@tonic-gate 	macdefine(&BlankEnvelope.e_macro, A_PERM, 'v', Version);
7127c478bd9Sstevel@tonic-gate 
7137c478bd9Sstevel@tonic-gate 	/* hostname */
714058561cbSjbeck 	hp = myhostname(jbuf, sizeof(jbuf));
7157c478bd9Sstevel@tonic-gate 	if (jbuf[0] != '\0')
7167c478bd9Sstevel@tonic-gate 	{
7177c478bd9Sstevel@tonic-gate 		struct utsname utsname;
7187c478bd9Sstevel@tonic-gate 
7197c478bd9Sstevel@tonic-gate 		if (tTd(0, 4))
7207c478bd9Sstevel@tonic-gate 			sm_dprintf("Canonical name: %s\n", jbuf);
7217c478bd9Sstevel@tonic-gate 		macdefine(&BlankEnvelope.e_macro, A_TEMP, 'w', jbuf);
7227c478bd9Sstevel@tonic-gate 		macdefine(&BlankEnvelope.e_macro, A_TEMP, 'j', jbuf);
7237c478bd9Sstevel@tonic-gate 		setclass('w', jbuf);
7247c478bd9Sstevel@tonic-gate 
7257c478bd9Sstevel@tonic-gate 		p = strchr(jbuf, '.');
7267c478bd9Sstevel@tonic-gate 		if (p != NULL && p[1] != '\0')
7277c478bd9Sstevel@tonic-gate 			macdefine(&BlankEnvelope.e_macro, A_TEMP, 'm', &p[1]);
7287c478bd9Sstevel@tonic-gate 
7297c478bd9Sstevel@tonic-gate 		if (uname(&utsname) >= 0)
7307c478bd9Sstevel@tonic-gate 			p = utsname.nodename;
7317c478bd9Sstevel@tonic-gate 		else
7327c478bd9Sstevel@tonic-gate 		{
7337c478bd9Sstevel@tonic-gate 			if (tTd(0, 22))
7347c478bd9Sstevel@tonic-gate 				sm_dprintf("uname failed (%s)\n",
7357c478bd9Sstevel@tonic-gate 					   sm_errstring(errno));
7367c478bd9Sstevel@tonic-gate 			makelower(jbuf);
7377c478bd9Sstevel@tonic-gate 			p = jbuf;
7387c478bd9Sstevel@tonic-gate 		}
7397c478bd9Sstevel@tonic-gate 		if (tTd(0, 4))
7407c478bd9Sstevel@tonic-gate 			sm_dprintf(" UUCP nodename: %s\n", p);
7417c478bd9Sstevel@tonic-gate 		macdefine(&BlankEnvelope.e_macro, A_TEMP, 'k', p);
7427c478bd9Sstevel@tonic-gate 		setclass('k', p);
7437c478bd9Sstevel@tonic-gate 		setclass('w', p);
7447c478bd9Sstevel@tonic-gate 	}
7457c478bd9Sstevel@tonic-gate 	if (hp != NULL)
7467c478bd9Sstevel@tonic-gate 	{
7477c478bd9Sstevel@tonic-gate 		for (av = hp->h_aliases; av != NULL && *av != NULL; av++)
7487c478bd9Sstevel@tonic-gate 		{
7497c478bd9Sstevel@tonic-gate 			if (tTd(0, 4))
7507c478bd9Sstevel@tonic-gate 				sm_dprintf("\ta.k.a.: %s\n", *av);
7517c478bd9Sstevel@tonic-gate 			setclass('w', *av);
7527c478bd9Sstevel@tonic-gate 		}
7537c478bd9Sstevel@tonic-gate #if NETINET || NETINET6
7547c478bd9Sstevel@tonic-gate 		for (i = 0; i >= 0 && hp->h_addr_list[i] != NULL; i++)
7557c478bd9Sstevel@tonic-gate 		{
7567c478bd9Sstevel@tonic-gate # if NETINET6
7577c478bd9Sstevel@tonic-gate 			char *addr;
7587c478bd9Sstevel@tonic-gate 			char buf6[INET6_ADDRSTRLEN];
7597c478bd9Sstevel@tonic-gate 			struct in6_addr ia6;
7607c478bd9Sstevel@tonic-gate # endif /* NETINET6 */
7617c478bd9Sstevel@tonic-gate # if NETINET
7627c478bd9Sstevel@tonic-gate 			struct in_addr ia;
7637c478bd9Sstevel@tonic-gate # endif /* NETINET */
7647c478bd9Sstevel@tonic-gate 			char ipbuf[103];
7657c478bd9Sstevel@tonic-gate 
7667c478bd9Sstevel@tonic-gate 			ipbuf[0] = '\0';
7677c478bd9Sstevel@tonic-gate 			switch (hp->h_addrtype)
7687c478bd9Sstevel@tonic-gate 			{
7697c478bd9Sstevel@tonic-gate # if NETINET
7707c478bd9Sstevel@tonic-gate 			  case AF_INET:
7717c478bd9Sstevel@tonic-gate 				if (hp->h_length != INADDRSZ)
7727c478bd9Sstevel@tonic-gate 					break;
7737c478bd9Sstevel@tonic-gate 
7747c478bd9Sstevel@tonic-gate 				memmove(&ia, hp->h_addr_list[i], INADDRSZ);
775058561cbSjbeck 				(void) sm_snprintf(ipbuf, sizeof(ipbuf),
7767c478bd9Sstevel@tonic-gate 						   "[%.100s]", inet_ntoa(ia));
7777c478bd9Sstevel@tonic-gate 				break;
7787c478bd9Sstevel@tonic-gate # endif /* NETINET */
7797c478bd9Sstevel@tonic-gate 
7807c478bd9Sstevel@tonic-gate # if NETINET6
7817c478bd9Sstevel@tonic-gate 			  case AF_INET6:
7827c478bd9Sstevel@tonic-gate 				if (hp->h_length != IN6ADDRSZ)
7837c478bd9Sstevel@tonic-gate 					break;
7847c478bd9Sstevel@tonic-gate 
7857c478bd9Sstevel@tonic-gate 				memmove(&ia6, hp->h_addr_list[i], IN6ADDRSZ);
786058561cbSjbeck 				addr = anynet_ntop(&ia6, buf6, sizeof(buf6));
7877c478bd9Sstevel@tonic-gate 				if (addr != NULL)
788058561cbSjbeck 					(void) sm_snprintf(ipbuf, sizeof(ipbuf),
7897c478bd9Sstevel@tonic-gate 							   "[%.100s]", addr);
7907c478bd9Sstevel@tonic-gate 				break;
7917c478bd9Sstevel@tonic-gate # endif /* NETINET6 */
7927c478bd9Sstevel@tonic-gate 			}
7937c478bd9Sstevel@tonic-gate 			if (ipbuf[0] == '\0')
7947c478bd9Sstevel@tonic-gate 				break;
7957c478bd9Sstevel@tonic-gate 
7967c478bd9Sstevel@tonic-gate 			if (tTd(0, 4))
7977c478bd9Sstevel@tonic-gate 				sm_dprintf("\ta.k.a.: %s\n", ipbuf);
7987c478bd9Sstevel@tonic-gate 			setclass('w', ipbuf);
7997c478bd9Sstevel@tonic-gate 		}
8007c478bd9Sstevel@tonic-gate #endif /* NETINET || NETINET6 */
8017c478bd9Sstevel@tonic-gate #if NETINET6
8027c478bd9Sstevel@tonic-gate 		freehostent(hp);
8037c478bd9Sstevel@tonic-gate 		hp = NULL;
8047c478bd9Sstevel@tonic-gate #endif /* NETINET6 */
8057c478bd9Sstevel@tonic-gate 	}
8067c478bd9Sstevel@tonic-gate 
8077c478bd9Sstevel@tonic-gate 	/* current time */
8087c478bd9Sstevel@tonic-gate 	macdefine(&BlankEnvelope.e_macro, A_TEMP, 'b', arpadate((char *) NULL));
8097c478bd9Sstevel@tonic-gate 
8107c478bd9Sstevel@tonic-gate 	/* current load average */
8117c478bd9Sstevel@tonic-gate 	sm_getla();
8127c478bd9Sstevel@tonic-gate 
8137c478bd9Sstevel@tonic-gate 	QueueLimitRecipient = (QUEUE_CHAR *) NULL;
8147c478bd9Sstevel@tonic-gate 	QueueLimitSender = (QUEUE_CHAR *) NULL;
8157c478bd9Sstevel@tonic-gate 	QueueLimitId = (QUEUE_CHAR *) NULL;
8167c478bd9Sstevel@tonic-gate 	QueueLimitQuarantine = (QUEUE_CHAR *) NULL;
8177c478bd9Sstevel@tonic-gate 
8187c478bd9Sstevel@tonic-gate 	/*
8197c478bd9Sstevel@tonic-gate 	**  Crack argv.
8207c478bd9Sstevel@tonic-gate 	*/
8217c478bd9Sstevel@tonic-gate 
8227c478bd9Sstevel@tonic-gate 	optind = 1;
8237c478bd9Sstevel@tonic-gate 	while ((j = getopt(argc, argv, OPTIONS)) != -1)
8247c478bd9Sstevel@tonic-gate 	{
8257c478bd9Sstevel@tonic-gate 		switch (j)
8267c478bd9Sstevel@tonic-gate 		{
8277c478bd9Sstevel@tonic-gate 		  case 'b':	/* operations mode */
8287c478bd9Sstevel@tonic-gate 			/* already done */
8297c478bd9Sstevel@tonic-gate 			break;
8307c478bd9Sstevel@tonic-gate 
8317c478bd9Sstevel@tonic-gate 		  case 'A':	/* use Alternate sendmail/submit.cf */
8327c478bd9Sstevel@tonic-gate 			cftype = optarg[0] == 'c' ? SM_GET_SUBMIT_CF
8337c478bd9Sstevel@tonic-gate 						  : SM_GET_SENDMAIL_CF;
8347c478bd9Sstevel@tonic-gate 			break;
8357c478bd9Sstevel@tonic-gate 
8367c478bd9Sstevel@tonic-gate 		  case 'B':	/* body type */
8377c478bd9Sstevel@tonic-gate 			CHECK_AGAINST_OPMODE(j);
8387c478bd9Sstevel@tonic-gate 			BlankEnvelope.e_bodytype = newstr(optarg);
8397c478bd9Sstevel@tonic-gate 			break;
8407c478bd9Sstevel@tonic-gate 
8417c478bd9Sstevel@tonic-gate 		  case 'C':	/* select configuration file (already done) */
8427c478bd9Sstevel@tonic-gate 			if (RealUid != 0)
8437c478bd9Sstevel@tonic-gate 				warn_C_flag = true;
8447c478bd9Sstevel@tonic-gate 			conffile = newstr(optarg);
8457c478bd9Sstevel@tonic-gate 			dp = drop_privileges(true);
8467c478bd9Sstevel@tonic-gate 			setstat(dp);
8477c478bd9Sstevel@tonic-gate 			safecf = false;
8487c478bd9Sstevel@tonic-gate 			break;
8497c478bd9Sstevel@tonic-gate 
8507c478bd9Sstevel@tonic-gate 		  case 'D':
8517c478bd9Sstevel@tonic-gate 		  case 'd':	/* debugging */
8527c478bd9Sstevel@tonic-gate 			/* already done */
8537c478bd9Sstevel@tonic-gate 			break;
8547c478bd9Sstevel@tonic-gate 
8557c478bd9Sstevel@tonic-gate 		  case 'f':	/* from address */
8567c478bd9Sstevel@tonic-gate 		  case 'r':	/* obsolete -f flag */
8577c478bd9Sstevel@tonic-gate 			CHECK_AGAINST_OPMODE(j);
8587c478bd9Sstevel@tonic-gate 			if (from != NULL)
8597c478bd9Sstevel@tonic-gate 			{
8607c478bd9Sstevel@tonic-gate 				usrerr("More than one \"from\" person");
8617c478bd9Sstevel@tonic-gate 				ExitStat = EX_USAGE;
8627c478bd9Sstevel@tonic-gate 				break;
8637c478bd9Sstevel@tonic-gate 			}
8647c478bd9Sstevel@tonic-gate 			if (optarg[0] == '\0')
8657c478bd9Sstevel@tonic-gate 				from = newstr("<>");
8667c478bd9Sstevel@tonic-gate 			else
8677c478bd9Sstevel@tonic-gate 				from = newstr(denlstring(optarg, true, true));
8687c478bd9Sstevel@tonic-gate 			if (strcmp(RealUserName, from) != 0)
8697c478bd9Sstevel@tonic-gate 				warn_f_flag = j;
8707c478bd9Sstevel@tonic-gate 			break;
8717c478bd9Sstevel@tonic-gate 
8727c478bd9Sstevel@tonic-gate 		  case 'F':	/* set full name */
8737c478bd9Sstevel@tonic-gate 			CHECK_AGAINST_OPMODE(j);
8747c478bd9Sstevel@tonic-gate 			FullName = newstr(optarg);
8757c478bd9Sstevel@tonic-gate 			break;
8767c478bd9Sstevel@tonic-gate 
8777c478bd9Sstevel@tonic-gate 		  case 'G':	/* relay (gateway) submission */
8787c478bd9Sstevel@tonic-gate 			/* already set */
8797c478bd9Sstevel@tonic-gate 			CHECK_AGAINST_OPMODE(j);
8807c478bd9Sstevel@tonic-gate 			break;
8817c478bd9Sstevel@tonic-gate 
8827c478bd9Sstevel@tonic-gate 		  case 'h':	/* hop count */
8837c478bd9Sstevel@tonic-gate 			CHECK_AGAINST_OPMODE(j);
8847c478bd9Sstevel@tonic-gate 			BlankEnvelope.e_hopcount = (short) strtol(optarg, &ep,
8857c478bd9Sstevel@tonic-gate 								  10);
886058561cbSjbeck 			(void) sm_snprintf(buf, sizeof(buf), "%d",
8877c478bd9Sstevel@tonic-gate 					   BlankEnvelope.e_hopcount);
8887c478bd9Sstevel@tonic-gate 			macdefine(&BlankEnvelope.e_macro, A_TEMP, 'c', buf);
8897c478bd9Sstevel@tonic-gate 
8907c478bd9Sstevel@tonic-gate 			if (*ep)
8917c478bd9Sstevel@tonic-gate 			{
8927c478bd9Sstevel@tonic-gate 				usrerr("Bad hop count (%s)", optarg);
8937c478bd9Sstevel@tonic-gate 				ExitStat = EX_USAGE;
8947c478bd9Sstevel@tonic-gate 			}
8957c478bd9Sstevel@tonic-gate 			break;
8967c478bd9Sstevel@tonic-gate 
8977c478bd9Sstevel@tonic-gate 		  case 'L':	/* program label */
8987c478bd9Sstevel@tonic-gate 			/* already set */
8997c478bd9Sstevel@tonic-gate 			break;
9007c478bd9Sstevel@tonic-gate 
9017c478bd9Sstevel@tonic-gate 		  case 'n':	/* don't alias */
9027c478bd9Sstevel@tonic-gate 			CHECK_AGAINST_OPMODE(j);
9037c478bd9Sstevel@tonic-gate 			NoAlias = true;
9047c478bd9Sstevel@tonic-gate 			break;
9057c478bd9Sstevel@tonic-gate 
9067c478bd9Sstevel@tonic-gate 		  case 'N':	/* delivery status notifications */
9077c478bd9Sstevel@tonic-gate 			CHECK_AGAINST_OPMODE(j);
9087c478bd9Sstevel@tonic-gate 			DefaultNotify |= QHASNOTIFY;
9097c478bd9Sstevel@tonic-gate 			macdefine(&BlankEnvelope.e_macro, A_TEMP,
9107c478bd9Sstevel@tonic-gate 				macid("{dsn_notify}"), optarg);
9117c478bd9Sstevel@tonic-gate 			if (sm_strcasecmp(optarg, "never") == 0)
9127c478bd9Sstevel@tonic-gate 				break;
9137c478bd9Sstevel@tonic-gate 			for (p = optarg; p != NULL; optarg = p)
9147c478bd9Sstevel@tonic-gate 			{
9157c478bd9Sstevel@tonic-gate 				p = strchr(p, ',');
9167c478bd9Sstevel@tonic-gate 				if (p != NULL)
9177c478bd9Sstevel@tonic-gate 					*p++ = '\0';
9187c478bd9Sstevel@tonic-gate 				if (sm_strcasecmp(optarg, "success") == 0)
9197c478bd9Sstevel@tonic-gate 					DefaultNotify |= QPINGONSUCCESS;
9207c478bd9Sstevel@tonic-gate 				else if (sm_strcasecmp(optarg, "failure") == 0)
9217c478bd9Sstevel@tonic-gate 					DefaultNotify |= QPINGONFAILURE;
9227c478bd9Sstevel@tonic-gate 				else if (sm_strcasecmp(optarg, "delay") == 0)
9237c478bd9Sstevel@tonic-gate 					DefaultNotify |= QPINGONDELAY;
9247c478bd9Sstevel@tonic-gate 				else
9257c478bd9Sstevel@tonic-gate 				{
9267c478bd9Sstevel@tonic-gate 					usrerr("Invalid -N argument");
9277c478bd9Sstevel@tonic-gate 					ExitStat = EX_USAGE;
9287c478bd9Sstevel@tonic-gate 				}
9297c478bd9Sstevel@tonic-gate 			}
9307c478bd9Sstevel@tonic-gate 			break;
9317c478bd9Sstevel@tonic-gate 
9327c478bd9Sstevel@tonic-gate 		  case 'o':	/* set option */
9337c478bd9Sstevel@tonic-gate 			setoption(*optarg, optarg + 1, false, true,
9347c478bd9Sstevel@tonic-gate 				  &BlankEnvelope);
9357c478bd9Sstevel@tonic-gate 			break;
9367c478bd9Sstevel@tonic-gate 
9377c478bd9Sstevel@tonic-gate 		  case 'O':	/* set option (long form) */
9387c478bd9Sstevel@tonic-gate 			setoption(' ', optarg, false, true, &BlankEnvelope);
9397c478bd9Sstevel@tonic-gate 			break;
9407c478bd9Sstevel@tonic-gate 
9417c478bd9Sstevel@tonic-gate 		  case 'p':	/* set protocol */
9427c478bd9Sstevel@tonic-gate 			CHECK_AGAINST_OPMODE(j);
9437c478bd9Sstevel@tonic-gate 			p = strchr(optarg, ':');
9447c478bd9Sstevel@tonic-gate 			if (p != NULL)
9457c478bd9Sstevel@tonic-gate 			{
9467c478bd9Sstevel@tonic-gate 				*p++ = '\0';
9477c478bd9Sstevel@tonic-gate 				if (*p != '\0')
9487c478bd9Sstevel@tonic-gate 				{
9497c478bd9Sstevel@tonic-gate 					i = strlen(p) + 1;
9507c478bd9Sstevel@tonic-gate 					ep = sm_malloc_x(i);
9517c478bd9Sstevel@tonic-gate 					cleanstrcpy(ep, p, i);
9527c478bd9Sstevel@tonic-gate 					macdefine(&BlankEnvelope.e_macro,
9537c478bd9Sstevel@tonic-gate 						  A_HEAP, 's', ep);
9547c478bd9Sstevel@tonic-gate 				}
9557c478bd9Sstevel@tonic-gate 			}
9567c478bd9Sstevel@tonic-gate 			if (*optarg != '\0')
9577c478bd9Sstevel@tonic-gate 			{
9587c478bd9Sstevel@tonic-gate 				i = strlen(optarg) + 1;
9597c478bd9Sstevel@tonic-gate 				ep = sm_malloc_x(i);
9607c478bd9Sstevel@tonic-gate 				cleanstrcpy(ep, optarg, i);
9617c478bd9Sstevel@tonic-gate 				macdefine(&BlankEnvelope.e_macro, A_HEAP,
9627c478bd9Sstevel@tonic-gate 					  'r', ep);
9637c478bd9Sstevel@tonic-gate 			}
9647c478bd9Sstevel@tonic-gate 			break;
9657c478bd9Sstevel@tonic-gate 
9667c478bd9Sstevel@tonic-gate 		  case 'Q':	/* change quarantining on queued items */
9677c478bd9Sstevel@tonic-gate 			/* sanity check */
9687c478bd9Sstevel@tonic-gate 			if (OpMode != MD_DELIVER &&
9697c478bd9Sstevel@tonic-gate 			    OpMode != MD_QUEUERUN)
9707c478bd9Sstevel@tonic-gate 			{
9717c478bd9Sstevel@tonic-gate 				usrerr("Can not use -Q with -b%c", OpMode);
9727c478bd9Sstevel@tonic-gate 				ExitStat = EX_USAGE;
9737c478bd9Sstevel@tonic-gate 				break;
9747c478bd9Sstevel@tonic-gate 			}
9757c478bd9Sstevel@tonic-gate 
9767c478bd9Sstevel@tonic-gate 			if (OpMode == MD_DELIVER)
9777c478bd9Sstevel@tonic-gate 				set_op_mode(MD_QUEUERUN);
9787c478bd9Sstevel@tonic-gate 
9797c478bd9Sstevel@tonic-gate 			FullName = NULL;
9807c478bd9Sstevel@tonic-gate 
9817c478bd9Sstevel@tonic-gate 			quarantining = newstr(optarg);
9827c478bd9Sstevel@tonic-gate 			break;
9837c478bd9Sstevel@tonic-gate 
9847c478bd9Sstevel@tonic-gate 		  case 'q':	/* run queue files at intervals */
9857c478bd9Sstevel@tonic-gate 			/* sanity check */
9867c478bd9Sstevel@tonic-gate 			if (OpMode != MD_DELIVER &&
9877c478bd9Sstevel@tonic-gate 			    OpMode != MD_DAEMON &&
9887c478bd9Sstevel@tonic-gate 			    OpMode != MD_FGDAEMON &&
9897c478bd9Sstevel@tonic-gate 			    OpMode != MD_PRINT &&
9907c478bd9Sstevel@tonic-gate 			    OpMode != MD_PRINTNQE &&
9917c478bd9Sstevel@tonic-gate 			    OpMode != MD_QUEUERUN)
9927c478bd9Sstevel@tonic-gate 			{
9937c478bd9Sstevel@tonic-gate 				usrerr("Can not use -q with -b%c", OpMode);
9947c478bd9Sstevel@tonic-gate 				ExitStat = EX_USAGE;
9957c478bd9Sstevel@tonic-gate 				break;
9967c478bd9Sstevel@tonic-gate 			}
9977c478bd9Sstevel@tonic-gate 
9987c478bd9Sstevel@tonic-gate 			/* don't override -bd, -bD or -bp */
9997c478bd9Sstevel@tonic-gate 			if (OpMode == MD_DELIVER)
10007c478bd9Sstevel@tonic-gate 				set_op_mode(MD_QUEUERUN);
10017c478bd9Sstevel@tonic-gate 
10027c478bd9Sstevel@tonic-gate 			FullName = NULL;
10037c478bd9Sstevel@tonic-gate 			negate = optarg[0] == '!';
10047c478bd9Sstevel@tonic-gate 			if (negate)
10057c478bd9Sstevel@tonic-gate 			{
10067c478bd9Sstevel@tonic-gate 				/* negate meaning of pattern match */
10077c478bd9Sstevel@tonic-gate 				optarg++; /* skip '!' for next switch */
10087c478bd9Sstevel@tonic-gate 			}
10097c478bd9Sstevel@tonic-gate 
10107c478bd9Sstevel@tonic-gate 			switch (optarg[0])
10117c478bd9Sstevel@tonic-gate 			{
10127c478bd9Sstevel@tonic-gate 			  case 'G': /* Limit by queue group name */
10137c478bd9Sstevel@tonic-gate 				if (negate)
10147c478bd9Sstevel@tonic-gate 				{
10157c478bd9Sstevel@tonic-gate 					usrerr("Can not use -q!G");
10167c478bd9Sstevel@tonic-gate 					ExitStat = EX_USAGE;
10177c478bd9Sstevel@tonic-gate 					break;
10187c478bd9Sstevel@tonic-gate 				}
10197c478bd9Sstevel@tonic-gate 				if (queuegroup != NULL)
10207c478bd9Sstevel@tonic-gate 				{
10217c478bd9Sstevel@tonic-gate 					usrerr("Can not use multiple -qG options");
10227c478bd9Sstevel@tonic-gate 					ExitStat = EX_USAGE;
10237c478bd9Sstevel@tonic-gate 					break;
10247c478bd9Sstevel@tonic-gate 				}
10257c478bd9Sstevel@tonic-gate 				queuegroup = newstr(&optarg[1]);
10267c478bd9Sstevel@tonic-gate 				break;
10277c478bd9Sstevel@tonic-gate 
10287c478bd9Sstevel@tonic-gate 			  case 'I': /* Limit by ID */
1029058561cbSjbeck 				new = (QUEUE_CHAR *) xalloc(sizeof(*new));
10307c478bd9Sstevel@tonic-gate 				new->queue_match = newstr(&optarg[1]);
10317c478bd9Sstevel@tonic-gate 				new->queue_negate = negate;
10327c478bd9Sstevel@tonic-gate 				new->queue_next = QueueLimitId;
10337c478bd9Sstevel@tonic-gate 				QueueLimitId = new;
10347c478bd9Sstevel@tonic-gate 				break;
10357c478bd9Sstevel@tonic-gate 
10367c478bd9Sstevel@tonic-gate 			  case 'R': /* Limit by recipient */
1037058561cbSjbeck 				new = (QUEUE_CHAR *) xalloc(sizeof(*new));
10387c478bd9Sstevel@tonic-gate 				new->queue_match = newstr(&optarg[1]);
10397c478bd9Sstevel@tonic-gate 				new->queue_negate = negate;
10407c478bd9Sstevel@tonic-gate 				new->queue_next = QueueLimitRecipient;
10417c478bd9Sstevel@tonic-gate 				QueueLimitRecipient = new;
10427c478bd9Sstevel@tonic-gate 				break;
10437c478bd9Sstevel@tonic-gate 
10447c478bd9Sstevel@tonic-gate 			  case 'S': /* Limit by sender */
1045058561cbSjbeck 				new = (QUEUE_CHAR *) xalloc(sizeof(*new));
10467c478bd9Sstevel@tonic-gate 				new->queue_match = newstr(&optarg[1]);
10477c478bd9Sstevel@tonic-gate 				new->queue_negate = negate;
10487c478bd9Sstevel@tonic-gate 				new->queue_next = QueueLimitSender;
10497c478bd9Sstevel@tonic-gate 				QueueLimitSender = new;
10507c478bd9Sstevel@tonic-gate 				break;
10517c478bd9Sstevel@tonic-gate 
10527c478bd9Sstevel@tonic-gate 			  case 'f': /* foreground queue run */
10537c478bd9Sstevel@tonic-gate 				foregroundqueue  = true;
10547c478bd9Sstevel@tonic-gate 				break;
10557c478bd9Sstevel@tonic-gate 
10567c478bd9Sstevel@tonic-gate 			  case 'Q': /* Limit by quarantine message */
10577c478bd9Sstevel@tonic-gate 				if (optarg[1] != '\0')
10587c478bd9Sstevel@tonic-gate 				{
1059058561cbSjbeck 					new = (QUEUE_CHAR *) xalloc(sizeof(*new));
10607c478bd9Sstevel@tonic-gate 					new->queue_match = newstr(&optarg[1]);
10617c478bd9Sstevel@tonic-gate 					new->queue_negate = negate;
10627c478bd9Sstevel@tonic-gate 					new->queue_next = QueueLimitQuarantine;
10637c478bd9Sstevel@tonic-gate 					QueueLimitQuarantine = new;
10647c478bd9Sstevel@tonic-gate 				}
10657c478bd9Sstevel@tonic-gate 				QueueMode = QM_QUARANTINE;
10667c478bd9Sstevel@tonic-gate 				break;
10677c478bd9Sstevel@tonic-gate 
10687c478bd9Sstevel@tonic-gate 			  case 'L': /* act on lost items */
10697c478bd9Sstevel@tonic-gate 				QueueMode = QM_LOST;
10707c478bd9Sstevel@tonic-gate 				break;
10717c478bd9Sstevel@tonic-gate 
10727c478bd9Sstevel@tonic-gate 			  case 'p': /* Persistent queue */
10737c478bd9Sstevel@tonic-gate 				queuepersistent = true;
10747c478bd9Sstevel@tonic-gate 				if (QueueIntvl == 0)
10757c478bd9Sstevel@tonic-gate 					QueueIntvl = 1;
10767c478bd9Sstevel@tonic-gate 				if (optarg[1] == '\0')
10777c478bd9Sstevel@tonic-gate 					break;
10787c478bd9Sstevel@tonic-gate 				++optarg;
10797c478bd9Sstevel@tonic-gate 				/* FALLTHROUGH */
10807c478bd9Sstevel@tonic-gate 
10817c478bd9Sstevel@tonic-gate 			  default:
10827c478bd9Sstevel@tonic-gate 				i = Errors;
10837c478bd9Sstevel@tonic-gate 				QueueIntvl = convtime(optarg, 'm');
10847c478bd9Sstevel@tonic-gate 				if (QueueIntvl < 0)
10857c478bd9Sstevel@tonic-gate 				{
10867c478bd9Sstevel@tonic-gate 					usrerr("Invalid -q value");
10877c478bd9Sstevel@tonic-gate 					ExitStat = EX_USAGE;
10887c478bd9Sstevel@tonic-gate 				}
10897c478bd9Sstevel@tonic-gate 
10907c478bd9Sstevel@tonic-gate 				/* check for bad conversion */
10917c478bd9Sstevel@tonic-gate 				if (i < Errors)
10927c478bd9Sstevel@tonic-gate 					ExitStat = EX_USAGE;
10937c478bd9Sstevel@tonic-gate 				break;
10947c478bd9Sstevel@tonic-gate 			}
10957c478bd9Sstevel@tonic-gate 			break;
10967c478bd9Sstevel@tonic-gate 
10977c478bd9Sstevel@tonic-gate 		  case 'R':	/* DSN RET: what to return */
10987c478bd9Sstevel@tonic-gate 			CHECK_AGAINST_OPMODE(j);
10997c478bd9Sstevel@tonic-gate 			if (bitset(EF_RET_PARAM, BlankEnvelope.e_flags))
11007c478bd9Sstevel@tonic-gate 			{
11017c478bd9Sstevel@tonic-gate 				usrerr("Duplicate -R flag");
11027c478bd9Sstevel@tonic-gate 				ExitStat = EX_USAGE;
11037c478bd9Sstevel@tonic-gate 				break;
11047c478bd9Sstevel@tonic-gate 			}
11057c478bd9Sstevel@tonic-gate 			BlankEnvelope.e_flags |= EF_RET_PARAM;
11067c478bd9Sstevel@tonic-gate 			if (sm_strcasecmp(optarg, "hdrs") == 0)
11077c478bd9Sstevel@tonic-gate 				BlankEnvelope.e_flags |= EF_NO_BODY_RETN;
11087c478bd9Sstevel@tonic-gate 			else if (sm_strcasecmp(optarg, "full") != 0)
11097c478bd9Sstevel@tonic-gate 			{
11107c478bd9Sstevel@tonic-gate 				usrerr("Invalid -R value");
11117c478bd9Sstevel@tonic-gate 				ExitStat = EX_USAGE;
11127c478bd9Sstevel@tonic-gate 			}
11137c478bd9Sstevel@tonic-gate 			macdefine(&BlankEnvelope.e_macro, A_TEMP,
11147c478bd9Sstevel@tonic-gate 				  macid("{dsn_ret}"), optarg);
11157c478bd9Sstevel@tonic-gate 			break;
11167c478bd9Sstevel@tonic-gate 
11177c478bd9Sstevel@tonic-gate 		  case 't':	/* read recipients from message */
11187c478bd9Sstevel@tonic-gate 			CHECK_AGAINST_OPMODE(j);
11197c478bd9Sstevel@tonic-gate 			GrabTo = true;
11207c478bd9Sstevel@tonic-gate 			break;
11217c478bd9Sstevel@tonic-gate 
11227c478bd9Sstevel@tonic-gate 		  case 'V':	/* DSN ENVID: set "original" envelope id */
11237c478bd9Sstevel@tonic-gate 			CHECK_AGAINST_OPMODE(j);
11247c478bd9Sstevel@tonic-gate 			if (!xtextok(optarg))
11257c478bd9Sstevel@tonic-gate 			{
11267c478bd9Sstevel@tonic-gate 				usrerr("Invalid syntax in -V flag");
11277c478bd9Sstevel@tonic-gate 				ExitStat = EX_USAGE;
11287c478bd9Sstevel@tonic-gate 			}
11297c478bd9Sstevel@tonic-gate 			else
11307c478bd9Sstevel@tonic-gate 			{
11317c478bd9Sstevel@tonic-gate 				BlankEnvelope.e_envid = newstr(optarg);
11327c478bd9Sstevel@tonic-gate 				macdefine(&BlankEnvelope.e_macro, A_TEMP,
11337c478bd9Sstevel@tonic-gate 					  macid("{dsn_envid}"), optarg);
11347c478bd9Sstevel@tonic-gate 			}
11357c478bd9Sstevel@tonic-gate 			break;
11367c478bd9Sstevel@tonic-gate 
11377c478bd9Sstevel@tonic-gate 		  case 'X':	/* traffic log file */
11387c478bd9Sstevel@tonic-gate 			dp = drop_privileges(true);
11397c478bd9Sstevel@tonic-gate 			setstat(dp);
11407c478bd9Sstevel@tonic-gate 			if (stat(optarg, &traf_st) == 0 &&
11417c478bd9Sstevel@tonic-gate 			    S_ISFIFO(traf_st.st_mode))
11427c478bd9Sstevel@tonic-gate 				TrafficLogFile = sm_io_open(SmFtStdio,
11437c478bd9Sstevel@tonic-gate 							    SM_TIME_DEFAULT,
11447c478bd9Sstevel@tonic-gate 							    optarg,
11457c478bd9Sstevel@tonic-gate 							    SM_IO_WRONLY, NULL);
11467c478bd9Sstevel@tonic-gate 			else
11477c478bd9Sstevel@tonic-gate 				TrafficLogFile = sm_io_open(SmFtStdio,
11487c478bd9Sstevel@tonic-gate 							    SM_TIME_DEFAULT,
11497c478bd9Sstevel@tonic-gate 							    optarg,
11507c478bd9Sstevel@tonic-gate 							    SM_IO_APPEND, NULL);
11517c478bd9Sstevel@tonic-gate 			if (TrafficLogFile == NULL)
11527c478bd9Sstevel@tonic-gate 			{
11537c478bd9Sstevel@tonic-gate 				syserr("cannot open %s", optarg);
11547c478bd9Sstevel@tonic-gate 				ExitStat = EX_CANTCREAT;
11557c478bd9Sstevel@tonic-gate 				break;
11567c478bd9Sstevel@tonic-gate 			}
11577c478bd9Sstevel@tonic-gate 			(void) sm_io_setvbuf(TrafficLogFile, SM_TIME_DEFAULT,
11587c478bd9Sstevel@tonic-gate 					     NULL, SM_IO_LBF, 0);
11597c478bd9Sstevel@tonic-gate 			break;
11607c478bd9Sstevel@tonic-gate 
11617c478bd9Sstevel@tonic-gate 			/* compatibility flags */
11627c478bd9Sstevel@tonic-gate 		  case 'c':	/* connect to non-local mailers */
11637c478bd9Sstevel@tonic-gate 		  case 'i':	/* don't let dot stop me */
11647c478bd9Sstevel@tonic-gate 		  case 'm':	/* send to me too */
11657c478bd9Sstevel@tonic-gate 		  case 'T':	/* set timeout interval */
11667c478bd9Sstevel@tonic-gate 		  case 'v':	/* give blow-by-blow description */
11677c478bd9Sstevel@tonic-gate 			setoption(j, "T", false, true, &BlankEnvelope);
11687c478bd9Sstevel@tonic-gate 			break;
11697c478bd9Sstevel@tonic-gate 
11707c478bd9Sstevel@tonic-gate 		  case 'e':	/* error message disposition */
11717c478bd9Sstevel@tonic-gate 		  case 'M':	/* define macro */
11727c478bd9Sstevel@tonic-gate 			setoption(j, optarg, false, true, &BlankEnvelope);
11737c478bd9Sstevel@tonic-gate 			break;
11747c478bd9Sstevel@tonic-gate 
11757c478bd9Sstevel@tonic-gate 		  case 's':	/* save From lines in headers */
11767c478bd9Sstevel@tonic-gate 			setoption('f', "T", false, true, &BlankEnvelope);
11777c478bd9Sstevel@tonic-gate 			break;
11787c478bd9Sstevel@tonic-gate 
11797c478bd9Sstevel@tonic-gate #ifdef DBM
11807c478bd9Sstevel@tonic-gate 		  case 'I':	/* initialize alias DBM file */
11817c478bd9Sstevel@tonic-gate 			set_op_mode(MD_INITALIAS);
11827c478bd9Sstevel@tonic-gate 			break;
11837c478bd9Sstevel@tonic-gate #endif /* DBM */
11847c478bd9Sstevel@tonic-gate 
11857c478bd9Sstevel@tonic-gate #if defined(__osf__) || defined(_AIX3)
11867c478bd9Sstevel@tonic-gate 		  case 'x':	/* random flag that OSF/1 & AIX mailx passes */
11877c478bd9Sstevel@tonic-gate 			break;
11887c478bd9Sstevel@tonic-gate #endif /* defined(__osf__) || defined(_AIX3) */
11897c478bd9Sstevel@tonic-gate #if defined(sony_news)
11907c478bd9Sstevel@tonic-gate 		  case 'E':
11917c478bd9Sstevel@tonic-gate 		  case 'J':	/* ignore flags for Japanese code conversion
11927c478bd9Sstevel@tonic-gate 				   implemented on Sony NEWS */
11937c478bd9Sstevel@tonic-gate 			break;
11947c478bd9Sstevel@tonic-gate #endif /* defined(sony_news) */
11957c478bd9Sstevel@tonic-gate 
11967c478bd9Sstevel@tonic-gate 		  default:
11977c478bd9Sstevel@tonic-gate 			finis(true, true, EX_USAGE);
11987c478bd9Sstevel@tonic-gate 			/* NOTREACHED */
11997c478bd9Sstevel@tonic-gate 			break;
12007c478bd9Sstevel@tonic-gate 		}
12017c478bd9Sstevel@tonic-gate 	}
12027c478bd9Sstevel@tonic-gate 
12037c478bd9Sstevel@tonic-gate 	/* if we've had errors so far, exit now */
1204*e9af4bc0SJohn Beck 	if ((ExitStat != EX_OK && OpMode != MD_TEST && OpMode != MD_CHECKCONFIG) ||
12057c478bd9Sstevel@tonic-gate 	    ExitStat == EX_OSERR)
12067c478bd9Sstevel@tonic-gate 	{
12077c478bd9Sstevel@tonic-gate 		finis(false, true, ExitStat);
12087c478bd9Sstevel@tonic-gate 		/* NOTREACHED */
12097c478bd9Sstevel@tonic-gate 	}
12107c478bd9Sstevel@tonic-gate 
12117c478bd9Sstevel@tonic-gate 	if (bitset(SUBMIT_MTA, SubmitMode))
12127c478bd9Sstevel@tonic-gate 	{
12137c478bd9Sstevel@tonic-gate 		/* If set daemon_flags on command line, don't reset it */
1214