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

📄 main.c

📁 < linux网络编程工具>>配套源码
💻 C
📖 第 1 页 / 共 5 页
字号:
		usrerr("Illegal body type %s", CurEnv->e_bodytype);
		CurEnv->e_bodytype = NULL;
	}

	/* tweak default DSN notifications */
	if (DefaultNotify == 0)
		DefaultNotify = QPINGONFAILURE|QPINGONDELAY;

	/* be sure we don't pick up bogus HOSTALIASES environment variable */
	if (OpMode == MD_QUEUERUN && RealUid != 0)
		(void) unsetenv("HOSTALIASES");

	/* check for sane configuration level */
	if (ConfigLevel > MAXCONFIGLEVEL)
	{
		syserr("Warning: .cf version level (%d) exceeds sendmail version %s functionality (%d)",
			ConfigLevel, Version, MAXCONFIGLEVEL);
	}

	/* need MCI cache to have persistence */
	if (HostStatDir != NULL && MaxMciCache == 0)
	{
		HostStatDir = NULL;
		printf("Warning: HostStatusDirectory disabled with ConnectionCacheSize = 0\n");
	}

	/* need HostStatusDir in order to have SingleThreadDelivery */
	if (SingleThreadDelivery && HostStatDir == NULL)
	{
		SingleThreadDelivery = FALSE;
		printf("Warning: HostStatusDirectory required for SingleThreadDelivery\n");
	}

	/* check for permissions */
	if ((OpMode == MD_DAEMON ||
	     OpMode == MD_FGDAEMON ||
	     OpMode == MD_PURGESTAT) &&
	    RealUid != 0 &&
	    RealUid != TrustedUid)
	{
		if (LogLevel > 1)
			sm_syslog(LOG_ALERT, NOQID,
				  "user %d attempted to %s",
				  RealUid,
				  OpMode != MD_PURGESTAT ? "run daemon"
							 : "purge host status");
		usrerr("Permission denied");
		finis(FALSE, EX_USAGE);
	}
	if (OpMode == MD_INITALIAS &&
	    RealUid != 0 &&
	    RealUid != TrustedUid &&
	    !wordinclass(RealUserName, 't'))
	{
		if (LogLevel > 1)
			sm_syslog(LOG_ALERT, NOQID,
				  "user %d attempted to rebuild the alias map",
				  RealUid);
		usrerr("Permission denied");
		finis(FALSE, EX_USAGE);
	}

	if (MeToo)
		BlankEnvelope.e_flags |= EF_METOO;

	switch (OpMode)
	{
	  case MD_TEST:
		/* don't have persistent host status in test mode */
		HostStatDir = NULL;
		if (Verbose == 0)
			Verbose = 2;
		CurEnv->e_errormode = EM_PRINT;
		HoldErrs = FALSE;
		break;

	  case MD_VERIFY:
		CurEnv->e_errormode = EM_PRINT;
		HoldErrs = FALSE;
		/* arrange to exit cleanly on hangup signal */
		if (setsignal(SIGHUP, SIG_IGN) == (sigfunc_t) SIG_DFL)
			(void) setsignal(SIGHUP, intsig);
		break;

	  case MD_FGDAEMON:
		run_in_foreground = TRUE;
		OpMode = MD_DAEMON;
		/* FALLTHROUGH */

	  case MD_DAEMON:
		vendor_daemon_setup(CurEnv);

		/* remove things that don't make sense in daemon mode */
		FullName = NULL;
		GrabTo = FALSE;

		/* arrange to restart on hangup signal */
		if (SaveArgv[0] == NULL || SaveArgv[0][0] != '/')
			sm_syslog(LOG_WARNING, NOQID,
				  "daemon invoked without full pathname; kill -1 won't work");
		(void) setsignal(SIGHUP, sighup);

		/* workaround: can't seem to release the signal in the parent */
		(void) releasesignal(SIGHUP);
		break;

	  case MD_INITALIAS:
		Verbose = 2;
		CurEnv->e_errormode = EM_PRINT;
		HoldErrs = FALSE;
		/* FALLTHROUGH */

	  default:
		/* arrange to exit cleanly on hangup signal */
		if (setsignal(SIGHUP, SIG_IGN) == (sigfunc_t) SIG_DFL)
			(void) setsignal(SIGHUP, intsig);
		break;
	}

	/* special considerations for FullName */
	if (FullName != NULL)
	{
		char *full = NULL;

		/* full names can't have newlines */
		if (strchr(FullName, '\n') != NULL)
		{
			FullName = full = newstr(denlstring(FullName, TRUE, TRUE));
		}
		/* check for characters that may have to be quoted */
		if (!rfc822_string(FullName))
		{
			/*
			**  Quote a full name with special characters
			**  as a comment so crackaddr() doesn't destroy
			**  the name portion of the address.
			*/
			FullName = addquotes(FullName);
			if (full != NULL)
				free(full);
		}
	}

	/* do heuristic mode adjustment */
	if (Verbose)
	{
		/* turn off noconnect option */
		setoption('c', "F", TRUE, FALSE, CurEnv);

		/* turn on interactive delivery */
		setoption('d', "", TRUE, FALSE, CurEnv);
	}

#ifdef VENDOR_CODE
	/* check for vendor mismatch */
	if (VendorCode != VENDOR_CODE)
	{
		message("Warning: .cf file vendor code mismatch: sendmail expects vendor %s, .cf file vendor is %s",
			getvendor(VENDOR_CODE), getvendor(VendorCode));
	}
#endif /* VENDOR_CODE */

	/* check for out of date configuration level */
	if (ConfigLevel < MAXCONFIGLEVEL)
	{
		message("Warning: .cf file is out of date: sendmail %s supports version %d, .cf file is version %d",
			Version, MAXCONFIGLEVEL, ConfigLevel);
	}

	if (ConfigLevel < 3)
		UseErrorsTo = TRUE;

	/* set options that were previous macros */
	if (SmtpGreeting == NULL)
	{
		if (ConfigLevel < 7 && (p = macvalue('e', CurEnv)) != NULL)
			SmtpGreeting = newstr(p);
		else
			SmtpGreeting = "\201j Sendmail \201v ready at \201b";
	}
	if (UnixFromLine == NULL)
	{
		if (ConfigLevel < 7 && (p = macvalue('l', CurEnv)) != NULL)
			UnixFromLine = newstr(p);
		else
			UnixFromLine = "From \201g  \201d";
	}
	SmtpError[0] = '\0';

	/* our name for SMTP codes */
	expand("\201j", jbuf, sizeof jbuf, CurEnv);
	MyHostName = jbuf;
	if (strchr(jbuf, '.') == NULL)
		message("WARNING: local host name (%s) is not qualified; fix $j in config file",
			jbuf);

	/* make certain that this name is part of the $=w class */
	setclass('w', MyHostName);

	/* the indices of built-in mailers */
	st = stab("local", ST_MAILER, ST_FIND);
	if (st != NULL)
		LocalMailer = st->s_mailer;
	else if (OpMode != MD_TEST || !warn_C_flag)
		syserr("No local mailer defined");

	st = stab("prog", ST_MAILER, ST_FIND);
	if (st == NULL)
		syserr("No prog mailer defined");
	else
	{
		ProgMailer = st->s_mailer;
		clrbitn(M_MUSER, ProgMailer->m_flags);
	}

	st = stab("*file*", ST_MAILER, ST_FIND);
	if (st == NULL)
		syserr("No *file* mailer defined");
	else
	{
		FileMailer = st->s_mailer;
		clrbitn(M_MUSER, FileMailer->m_flags);
	}

	st = stab("*include*", ST_MAILER, ST_FIND);
	if (st == NULL)
		syserr("No *include* mailer defined");
	else
		InclMailer = st->s_mailer;

	if (ConfigLevel < 6)
	{
		/* heuristic tweaking of local mailer for back compat */
		if (LocalMailer != NULL)
		{
			setbitn(M_ALIASABLE, LocalMailer->m_flags);
			setbitn(M_HASPWENT, LocalMailer->m_flags);
			setbitn(M_TRYRULESET5, LocalMailer->m_flags);
			setbitn(M_CHECKINCLUDE, LocalMailer->m_flags);
			setbitn(M_CHECKPROG, LocalMailer->m_flags);
			setbitn(M_CHECKFILE, LocalMailer->m_flags);
			setbitn(M_CHECKUDB, LocalMailer->m_flags);
		}
		if (ProgMailer != NULL)
			setbitn(M_RUNASRCPT, ProgMailer->m_flags);
		if (FileMailer != NULL)
			setbitn(M_RUNASRCPT, FileMailer->m_flags);
	}
	if (ConfigLevel < 7)
	{
		if (LocalMailer != NULL)
			setbitn(M_VRFY250, LocalMailer->m_flags);
		if (ProgMailer != NULL)
			setbitn(M_VRFY250, ProgMailer->m_flags);
		if (FileMailer != NULL)
			setbitn(M_VRFY250, FileMailer->m_flags);
	}

	/* MIME Content-Types that cannot be transfer encoded */
	setclass('n', "multipart/signed");

	/* MIME message/xxx subtypes that can be treated as messages */
	setclass('s', "rfc822");

	/* MIME Content-Transfer-Encodings that can be encoded */
	setclass('e', "7bit");
	setclass('e', "8bit");
	setclass('e', "binary");

#ifdef USE_B_CLASS
	/* MIME Content-Types that should be treated as binary */
	setclass('b', "image");
	setclass('b', "audio");
	setclass('b', "video");
	setclass('b', "application/octet-stream");
#endif /* USE_B_CLASS */

	/* MIME headers which have fields to check for overflow */
	setclass(macid("{checkMIMEFieldHeaders}", NULL), "content-disposition");
	setclass(macid("{checkMIMEFieldHeaders}", NULL), "content-type");

	/* MIME headers to check for length overflow */
	setclass(macid("{checkMIMETextHeaders}", NULL), "content-description");

	/* MIME headers to check for overflow and rebalance */
	setclass(macid("{checkMIMEHeaders}", NULL), "content-disposition");
	setclass(macid("{checkMIMEHeaders}", NULL), "content-id");
	setclass(macid("{checkMIMEHeaders}", NULL), "content-transfer-encoding");
	setclass(macid("{checkMIMEHeaders}", NULL), "content-type");
	setclass(macid("{checkMIMEHeaders}", NULL), "mime-version");

	/* Macros to save in the qf file -- don't remove any */
	setclass(macid("{persistentMacros}", NULL), "r");
	setclass(macid("{persistentMacros}", NULL), "s");
	setclass(macid("{persistentMacros}", NULL), "_");
	setclass(macid("{persistentMacros}", NULL), "{if_addr}");
	setclass(macid("{persistentMacros}", NULL), "{daemon_flags}");
	setclass(macid("{persistentMacros}", NULL), "{client_flags}");

	/* operate in queue directory */
	if (QueueDir == NULL)
	{
		if (OpMode != MD_TEST)
		{
			syserr("QueueDirectory (Q) option must be set");
			ExitStat = EX_CONFIG;
		}
	}
	else
	{
		/*
		**  If multiple queues wildcarded, use one for
		**  the daemon's home. Note that this preconditions
		**  a wildcarded QueueDir to a real pathname.
		*/

		if (OpMode != MD_TEST)
			multiqueue_cache();
	}

	/* check host status directory for validity */
	if (HostStatDir != NULL && !path_is_dir(HostStatDir, FALSE))
	{
		/* cannot use this value */
		if (tTd(0, 2))
			dprintf("Cannot use HostStatusDirectory = %s: %s\n",
				HostStatDir, errstring(errno));
		HostStatDir = NULL;
	}

#if QUEUE
	if (OpMode == MD_QUEUERUN && RealUid != 0 &&
	    bitset(PRIV_RESTRICTQRUN, PrivacyFlags))
	{
		struct stat stbuf;

		/* check to see if we own the queue directory */
		if (stat(".", &stbuf) < 0)
			syserr("main: cannot stat %s", QueueDir);
		if (stbuf.st_uid != RealUid)
		{
			/* nope, really a botch */
			usrerr("You do not have permission to process the queue");
			finis(FALSE, EX_NOPERM);
		}
	}
#endif /* QUEUE */

#if _FFR_MILTER
	/* sanity checks on milter filters */
	if (OpMode == MD_DAEMON || OpMode == MD_SMTP)
		milter_parse_list(InputFilterList, InputFilters, MAXFILTERS);
#endif /* _FFR_MILTER */


	/* if we've had errors so far, exit now */
	if (ExitStat != EX_OK && OpMode != MD_TEST)
		finis(FALSE, ExitStat);

#if XDEBUG
	checkfd012("before main() initmaps");
#endif /* XDEBUG */

	/*
	**  Do operation-mode-dependent initialization.
	*/

	switch (OpMode)
	{
	  case MD_PRINT:
		/* print the queue */
#if QUEUE
		dropenvelope(CurEnv, TRUE);
		(void) setsignal(SIGPIPE, quiesce);
		printqueue();
		finis(FALSE, EX_OK);
#else /* QUEUE */
		usrerr("No queue to print");
		finis(FALSE, EX_UNAVAILABLE);
#endif /* QUEUE */
		break;

	  case MD_HOSTSTAT:
		(void) setsignal(SIGPIPE, quiesce);
		(void) mci_traverse_persistent(mci_print_persistent, NULL);
		finis(FALSE, EX_OK);
		break;

	  case MD_PURGESTAT:
		(void) mci_traverse_persistent(mci_purge_persistent, NULL);
		finis(FALSE, EX_OK);
		break;

	  case MD_INITALIAS:
		/* initialize maps */
		initmaps();
		finis(FALSE, ExitStat);
		break;

	  case MD_SMTP:
	  case MD_DAEMON:
		/* reset DSN parameters */
		DefaultNotify = QPINGONFAILURE|QPINGONDELAY;
		define(macid("{dsn_notify}", NULL), NULL, CurEnv);
		CurEnv->e_envid = NULL;
		define(macid("{dsn_envid}", NULL), NULL, CurEnv);
		CurEnv->e_flags &= ~(EF_RET_PARAM|EF_NO_BODY_RETN);
		define(macid("{dsn_ret}", NULL), NULL, CurEnv);

		/* don't open maps for daemon -- done below in child */
		break;
	}

	if (tTd(0, 15))
	{
		/* print configuration table (or at least part of it) */
		if (tTd(0, 90))
			printrules();
		for (i = 0; i < MAXMAILERS; i++)
		{
			if (Mailer[i] != NULL)
				printmailer(Mailer[i]);
		}
	}

	/*
	**  Switch to the main envelope.
	*/

	CurEnv = newenvelope(&MainEnvelope, CurEnv);
	MainEnvelope.e_flags = BlankEnvelope.e_flags;

	/*
	**  If test mode, read addresses from stdin and process.
	*/

	if (OpMode == MD_TEST)
	{
		char buf[MAXLINE];

		if (isatty(fileno(stdin)))
			Verbose = 2;

		if (Verbose)
		{
			printf("ADDRESS TEST MODE (ruleset 3 NOT automatically invoked)\n");
			printf("Enter <ruleset> <address>\n");
		}
		if (setjmp(TopFrame) > 0)
			printf("\n");
		(void) setsignal(SIGINT, intindebug);
		for (;;)
		{
			if (Verbose == 2)
				printf("> ");
			(void) fflush(stdout);
			if (fgets(buf, sizeof buf, stdin) == NULL)
				testmodeline("/quit", CurEnv);
			p = strchr(buf, '\n');
			if (p != NULL)
				*p = '\0';
			if (Verbose < 2)
				printf("> %s\n", buf);
			testmodeline(buf, CurEnv);
		}
	}

#if SMTP
# if STARTTLS
	/*
	**  basic TLS initialization
	**  ignore result for now
	*/
	SSL_library_init();
	SSL_load_error_strings();
#  if 0
	/* this is currently a macro for SSL_library_init */
	SSLeay_add_ssl_algorithms();
#  endif /* 0 */

	/* initialize PRNG */
	tls_ok = tls_rand_init(RandFile, 7);

# endif /* STARTTLS */
#endif /* SMTP */

#if QUEUE
	/*
	**  If collecting stuff from the queue, go start doing that.
	*/

	if (OpMode == MD_QUEUERUN && QueueIntvl == 0)
	{
# if SMTP
#  if STARTTLS
		if (tls_ok
		   )
		{
			/* init TLS for client, ignore result for now */
			(void) initclttls();
		}
#  endif /* STARTTLS */
# endif /* SMTP */
		(void) runqueue(FALSE, Verbose);
		finis(TRUE, ExitStat);
	}
#endif /* QUEUE */

	/*
	**  If a daemon, wait for a request.
	**	getrequests will always return in a child.
	**	If we should also be processing the queue, start
	**		doing it in background.
	**	We check for any errors that might have happened
	**		during startup.
	*/

	if (OpMode == MD_DAEMON || QueueIntvl != 0)
	{
		char dtype[200];

		if (!run_in_foreground && !tTd(99, 100))
		{
			/* put us in background */
			i = fork();
			if (i < 0)
				syserr("daemon: cannot fork");
			if (i != 0)
				finis(FALSE, EX_OK);

			/* disconnect from our controlling tty */
			disconnect(2, CurEnv);
		}

		dtype[0] = '\0';
		if (OpMode == MD_DAEMON)
			(void) strlcat(dtype, "+SMTP", sizeof dtype);
		if (QueueIntvl != 0)
		{
			(void) strlcat(dtype, "+queueing@", sizeof dtype);
			(void) strlcat(dtype, pintvl(QueueIntvl, TRUE),
				       sizeof dtype);
		}
		if (tTd(0, 1))
			(void) strlcat(dtype, "+debugging", sizeof dtype);

		sm_syslog(LOG_INFO, NOQID,
			  "starting daemon (%s): %s", Version, dtype + 1);
#ifdef XLA
		xla_create_file();
#endif /* XLA */

⌨️ 快捷键说明

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