⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 main.c

📁 < linux网络编程工具>>配套源码
💻 C
📖 第 1 页 / 共 5 页
字号:
/*
 * Copyright (c) 1998-2000 Sendmail, Inc. and its suppliers.
 *	All rights reserved.
 * Copyright (c) 1983, 1995-1997 Eric P. Allman.  All rights reserved.
 * Copyright (c) 1988, 1993
 *	The Regents of the University of California.  All rights reserved.
 *
 * By using this file, you agree to the terms and conditions set
 * forth in the LICENSE file which can be found at the top level of
 * the sendmail distribution.
 *
 */

#ifndef lint
static char copyright[] =
"@(#) Copyright (c) 1998-2000 Sendmail, Inc. and its suppliers.\n\
	All rights reserved.\n\
     Copyright (c) 1983, 1995-1997 Eric P. Allman.  All rights reserved.\n\
     Copyright (c) 1988, 1993\n\
	The Regents of the University of California.  All rights reserved.\n";
#endif /* ! lint */

#ifndef lint
static char id[] = "@(#)$Id: main.c,v 8.485.4.27 2000/09/26 01:30:38 gshapiro Exp $";
#endif /* ! lint */

#define	_DEFINE

#include <sendmail.h>


#if NETINET || NETINET6
# include <arpa/inet.h>
#endif /* NETINET || NETINET6 */

static void	dump_class __P((STAB *, int));
static void	obsolete __P((char **));
static void	testmodeline __P((char *, ENVELOPE *));

/*
**  SENDMAIL -- Post mail to a set of destinations.
**
**	This is the basic mail router.  All user mail programs should
**	call this routine to actually deliver mail.  Sendmail in
**	turn calls a bunch of mail servers that do the real work of
**	delivering the mail.
**
**	Sendmail is driven by settings read in from /etc/mail/sendmail.cf
**	(read by readcf.c).
**
**	Usage:
**		/usr/lib/sendmail [flags] addr ...
**
**		See the associated documentation for details.
**
**	Author:
**		Eric Allman, UCB/INGRES (until 10/81).
**			     Britton-Lee, Inc., purveyors of fine
**				database computers (11/81 - 10/88).
**			     International Computer Science Institute
**				(11/88 - 9/89).
**			     UCB/Mammoth Project (10/89 - 7/95).
**			     InReference, Inc. (8/95 - 1/97).
**			     Sendmail, Inc. (1/98 - present).
**		The support of the my employers is gratefully acknowledged.
**			Few of them (Britton-Lee in particular) have had
**			anything to gain from my involvement in this project.
*/


int		NextMailer;	/* "free" index into Mailer struct */
char		*FullName;	/* sender's full name */
ENVELOPE	BlankEnvelope;	/* a "blank" envelope */
static ENVELOPE	MainEnvelope;	/* the envelope around the basic letter */
ADDRESS		NullAddress =	/* a null address */
		{ "", "", NULL, "" };
char		*CommandLineArgs;	/* command line args for pid file */
bool		Warn_Q_option = FALSE;	/* warn about Q option use */
char		**SaveArgv;	/* argument vector for re-execing */
static int	MissingFds = 0;	/* bit map of fds missing on startup */

#ifdef NGROUPS_MAX
GIDSET_T	InitialGidSet[NGROUPS_MAX];
#endif /* NGROUPS_MAX */

#if DAEMON && !SMTP
ERROR %%%%   Cannot have DAEMON mode without SMTP   %%%% ERROR
#endif /* DAEMON && !SMTP */
#if SMTP && !QUEUE
ERROR %%%%   Cannot have SMTP mode without QUEUE   %%%% ERROR
#endif /* SMTP && !QUEUE */

#define MAXCONFIGLEVEL	9	/* highest config version level known */

#if SASL
static sasl_callback_t srvcallbacks[] =
{
	{	SASL_CB_VERIFYFILE,	&safesaslfile,	NULL	},
	{	SASL_CB_PROXY_POLICY,	&proxy_policy,	NULL	},
	{	SASL_CB_LIST_END,	NULL,		NULL	}
};

#endif /* SASL */

int SubmitMode;

int
main(argc, argv, envp)
	int argc;
	char **argv;
	char **envp;
{
	register char *p;
	char **av;
	extern char Version[];
	char *ep, *from;
	STAB *st;
	register int i;
	int j;
	int dp;
	bool safecf = TRUE;
	BITMAP256 *p_flags = NULL;	/* daemon flags */
	bool warn_C_flag = FALSE;
	bool auth = TRUE;		/* whether to set e_auth_param */
	char warn_f_flag = '\0';
	bool run_in_foreground = FALSE;	/* -bD mode */
	static bool reenter = FALSE;
	struct passwd *pw;
	struct hostent *hp;
	char *nullserver = NULL;
	char *authinfo = NULL;
	char *sysloglabel = NULL;	/* label for syslog */
	bool forged;
	struct stat traf_st;		/* for TrafficLog FIFO check */
	char jbuf[MAXHOSTNAMELEN];	/* holds MyHostName */
	static char rnamebuf[MAXNAME];	/* holds RealUserName */
	char *emptyenviron[1];
# if STARTTLS
	bool tls_ok;
# endif /* STARTTLS */
	QUEUE_CHAR *new;
	extern int DtableSize;
	extern int optind;
	extern int opterr;
	extern char *optarg;
	extern char **environ;

	/*
	**  Check to see if we reentered.
	**	This would normally happen if e_putheader or e_putbody
	**	were NULL when invoked.
	*/

	if (reenter)
	{
		syserr("main: reentered!");
		abort();
	}
	reenter = TRUE;

	/* avoid null pointer dereferences */
	TermEscape.te_rv_on = TermEscape.te_rv_off = "";

	/* do machine-dependent initializations */
	init_md(argc, argv);


	/* in 4.4BSD, the table can be huge; impose a reasonable limit */
	DtableSize = getdtsize();
	if (DtableSize > 256)
		DtableSize = 256;

	/*
	**  Be sure we have enough file descriptors.
	**	But also be sure that 0, 1, & 2 are open.
	*/

	fill_fd(STDIN_FILENO, NULL);
	fill_fd(STDOUT_FILENO, NULL);
	fill_fd(STDERR_FILENO, NULL);

	i = DtableSize;
	while (--i > 0)
	{
		if (i != STDIN_FILENO && i != STDOUT_FILENO && i != STDERR_FILENO)
			(void) close(i);
	}
	errno = 0;

#if LOG
#  ifdef LOG_MAIL
	openlog("sendmail", LOG_PID, LOG_MAIL);
#  else /* LOG_MAIL */
	openlog("sendmail", LOG_PID);
#  endif /* LOG_MAIL */
#endif /* LOG */

	if (MissingFds != 0)
	{
		char mbuf[MAXLINE];

		mbuf[0] = '\0';
		if (bitset(1 << STDIN_FILENO, MissingFds))
			(void) strlcat(mbuf, ", stdin", sizeof mbuf);
		if (bitset(1 << STDOUT_FILENO, MissingFds))
			(void) strlcat(mbuf, ", stdout", sizeof mbuf);
		if (bitset(1 << STDERR_FILENO, MissingFds))
			(void) strlcat(mbuf, ", stderr", sizeof mbuf);
		syserr("File descriptors missing on startup: %s", &mbuf[2]);
	}

	/* reset status from syserr() calls for missing file descriptors */
	Errors = 0;
	ExitStat = EX_OK;

	SubmitMode = SUBMIT_UNKNOWN;
#if XDEBUG
	checkfd012("after openlog");
#endif /* XDEBUG */

	/*
	**  Seed the random number generator.
	**  Used for queue file names, picking a queue directory, and
	**  MX randomization.
	*/

	seed_random();

	tTsetup(tTdvect, sizeof tTdvect, "0-99.1");

#ifdef NGROUPS_MAX
	/* save initial group set for future checks */
	i = getgroups(NGROUPS_MAX, InitialGidSet);
	if (i == 0)
		InitialGidSet[0] = (GID_T) -1;
	while (i < NGROUPS_MAX)
		InitialGidSet[i++] = InitialGidSet[0];
#endif /* NGROUPS_MAX */

	/* drop group id privileges (RunAsUser not yet set) */
	dp = drop_privileges(FALSE);
	setstat(dp);

# ifdef SIGUSR1
	/* arrange to dump state on user-1 signal */
	(void) setsignal(SIGUSR1, sigusr1);
# endif /* SIGUSR1 */

	/* initialize for setproctitle */
	initsetproctitle(argc, argv, envp);

	/* Handle any non-getoptable constructions. */
	obsolete(argv);

	/*
	**  Do a quick prescan of the argument list.
	*/


#if defined(__osf__) || defined(_AIX3)
# define OPTIONS	"B:b:C:cd:e:F:f:Gh:IiL:M:mN:nO:o:p:q:R:r:sTtUV:vX:x"
#endif /* defined(__osf__) || defined(_AIX3) */
#if defined(sony_news)
# define OPTIONS	"B:b:C:cd:E:e:F:f:Gh:IiJ:L:M:mN:nO:o:p:q:R:r:sTtUV:vX:"
#endif /* defined(sony_news) */
#ifndef OPTIONS
# define OPTIONS	"B:b:C:cd:e:F:f:Gh:IiL:M:mN:nO:o:p:q:R:r:sTtUV:vX:"
#endif /* ! OPTIONS */
	opterr = 0;
	while ((j = getopt(argc, argv, OPTIONS)) != -1)
	{
		switch (j)
		{
		  case 'd':
			/* hack attack -- see if should use ANSI mode */
			if (strcmp(optarg, "ANSI") == 0)
			{
				TermEscape.te_rv_on = "\033[7m";
				TermEscape.te_rv_off = "\033[0m";
				break;
			}
			tTflag(optarg);
			setbuf(stdout, (char *) NULL);
			break;

		  case 'G':	/* relay (gateway) submission */
			SubmitMode |= SUBMIT_MTA;
			break;

		  case 'L':
			j = min(strlen(optarg), 24) + 1;
			sysloglabel = xalloc(j);
			(void) strlcpy(sysloglabel, optarg, j);
			break;

		  case 'U':	/* initial (user) submission */
			SubmitMode |= SUBMIT_MSA;
			break;
		}
	}
	opterr = 1;

	if (sysloglabel != NULL)
	{
#if LOG
		closelog();
#  ifdef LOG_MAIL
		openlog(sysloglabel, LOG_PID, LOG_MAIL);
#  else /* LOG_MAIL */
		openlog(sysloglabel, LOG_PID);
#  endif /* LOG_MAIL */
#endif /* LOG */
	}

	/* set up the blank envelope */
	BlankEnvelope.e_puthdr = putheader;
	BlankEnvelope.e_putbody = putbody;
	BlankEnvelope.e_xfp = NULL;
	STRUCTCOPY(NullAddress, BlankEnvelope.e_from);
	CurEnv = &BlankEnvelope;
	STRUCTCOPY(NullAddress, MainEnvelope.e_from);

	/*
	**  Set default values for variables.
	**	These cannot be in initialized data space.
	*/

	setdefaults(&BlankEnvelope);

	RealUid = getuid();
	RealGid = getgid();

	pw = sm_getpwuid(RealUid);
	if (pw != NULL)
		(void) snprintf(rnamebuf, sizeof rnamebuf, "%s", pw->pw_name);
	else
		(void) snprintf(rnamebuf, sizeof rnamebuf, "Unknown UID %d",
				(int) RealUid);

	RealUserName = rnamebuf;

	if (tTd(0, 101))
	{
		dprintf("Version %s\n", Version);
		finis(FALSE, EX_OK);
	}

	/*
	**  if running non-setuid binary as non-root, pretend
	**  we are the RunAsUid
	*/
	if (RealUid != 0 && geteuid() == RealUid)
	{
		if (tTd(47, 1))
			dprintf("Non-setuid binary: RunAsUid = RealUid = %d\n",
				(int)RealUid);
		RunAsUid = RealUid;
	}
	else if (geteuid() != 0)
		RunAsUid = geteuid();

	if (RealUid != 0 && getegid() == RealGid)
		RunAsGid = RealGid;

	if (tTd(47, 5))
	{
		dprintf("main: e/ruid = %d/%d e/rgid = %d/%d\n",
			(int)geteuid(), (int)getuid(),
			(int)getegid(), (int)getgid());
		dprintf("main: RunAsUser = %d:%d\n",
			(int)RunAsUid, (int)RunAsGid);
	}

	/* save command line arguments */
	j = 0;
	for (av = argv; *av != NULL; )
		j += strlen(*av++) + 1;
	SaveArgv = (char **) xalloc(sizeof (char *) * (argc + 1));
	CommandLineArgs = xalloc(j);
	p = CommandLineArgs;
	for (av = argv, i = 0; *av != NULL; )
	{
		int h;

		SaveArgv[i++] = newstr(*av);
		if (av != argv)
			*p++ = ' ';
		(void) strlcpy(p, *av++, j);
		h = strlen(p);
		p += h;
		j -= h + 1;
	}
	SaveArgv[i] = NULL;

	if (tTd(0, 1))
	{
		int ll;
		extern char *CompileOptions[];

		dprintf("Version %s\n Compiled with:", Version);
		av = CompileOptions;
		ll = 7;
		while (*av != NULL)
		{
			if (ll + strlen(*av) > 63)
			{
				dprintf("\n");
				ll = 0;
			}
			if (ll == 0)
				dprintf("\t\t");
			else
				dprintf(" ");
			dprintf("%s", *av);
			ll += strlen(*av++) + 1;
		}
		dprintf("\n");
	}
	if (tTd(0, 10))
	{
		int ll;
		extern char *OsCompileOptions[];

		dprintf("    OS Defines:");
		av = OsCompileOptions;
		ll = 7;
		while (*av != NULL)
		{
			if (ll + strlen(*av) > 63)
			{
				dprintf("\n");
				ll = 0;
			}
			if (ll == 0)
				dprintf("\t\t");
			else
				dprintf(" ");
			dprintf("%s", *av);
			ll += strlen(*av++) + 1;
		}
		dprintf("\n");
#ifdef _PATH_UNIX
		dprintf("Kernel symbols:\t%s\n", _PATH_UNIX);
#endif /* _PATH_UNIX */
		dprintf(" Def Conf file:\t%s\n", getcfname());
		dprintf("  Def Pid file:\t%s\n", PidFile);
	}

	InChannel = stdin;
	OutChannel = stdout;

	/* clear sendmail's environment */
	ExternalEnviron = environ;
	emptyenviron[0] = NULL;
	environ = emptyenviron;

	/*
	**  restore any original TZ setting until TimeZoneSpec has been
	**  determined - or early log messages may get bogus time stamps
	*/
	if ((p = getextenv("TZ")) != NULL)
	{
		char *tz;
		int tzlen;

		tzlen = strlen(p) + 4;
		tz = xalloc(tzlen);
		(void) snprintf(tz, tzlen, "TZ=%s", p);
		(void) putenv(tz);
	}

	/* prime the child environment */
	setuserenv("AGENT", "sendmail");

	if (setsignal(SIGINT, SIG_IGN) != SIG_IGN)
		(void) setsignal(SIGINT, intsig);
	(void) setsignal(SIGTERM, intsig);
	(void) setsignal(SIGPIPE, SIG_IGN);
	OldUmask = umask(022);
	OpMode = MD_DELIVER;
	FullName = getextenv("NAME");

	/*
	**  Initialize name server if it is going to be used.
	*/

#if NAMED_BIND
	if (!bitset(RES_INIT, _res.options))
		(void) res_init();

	/*
	**  hack to avoid crashes when debugging for the resolver is
	**  turned on and sfio is used
	*/
	if (tTd(8, 8))
# if !SFIO || SFIO_STDIO_COMPAT
		_res.options |= RES_DEBUG;
# else /* !SFIO || SFIO_STDIO_COMPAT */
		dprintf("RES_DEBUG not available due to SFIO\n");
# endif /* !SFIO || SFIO_STDIO_COMPAT */
	else
		_res.options &= ~RES_DEBUG;
# ifdef RES_NOALIASES
	_res.options |= RES_NOALIASES;
# endif /* RES_NOALIASES */
	TimeOuts.res_retry[RES_TO_DEFAULT] = _res.retry;
	TimeOuts.res_retry[RES_TO_FIRST] = _res.retry;
	TimeOuts.res_retry[RES_TO_NORMAL] = _res.retry;
	TimeOuts.res_retrans[RES_TO_DEFAULT] = _res.retrans;
	TimeOuts.res_retrans[RES_TO_FIRST] = _res.retrans;
	TimeOuts.res_retrans[RES_TO_NORMAL] = _res.retrans;
#endif /* NAMED_BIND */

	errno = 0;
	from = NULL;

	/* initialize some macros, etc. */
	initmacros(CurEnv);
	init_vendor_macros(CurEnv);

	/* version */
	define('v', Version, CurEnv);

	/* hostname */
	hp = myhostname(jbuf, sizeof jbuf);
	if (jbuf[0] != '\0')
	{
		struct	utsname	utsname;

		if (tTd(0, 4))
			dprintf("canonical name: %s\n", jbuf);
		define('w', newstr(jbuf), CurEnv);	/* must be new string */
		define('j', newstr(jbuf), CurEnv);
		setclass('w', jbuf);

		p = strchr(jbuf, '.');
		if (p != NULL)
		{
			if (p[1] != '\0')
			{
				define('m', newstr(&p[1]), CurEnv);
			}
			while (p != NULL && strchr(&p[1], '.') != NULL)
			{
				*p = '\0';
				if (tTd(0, 4))
					dprintf("\ta.k.a.: %s\n", jbuf);
				setclass('w', jbuf);
				*p++ = '.';
				p = strchr(p, '.');
			}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -