main.c

来自「<B>Digital的Unix操作系统VAX 4.2源码</B>」· C语言 代码 · 共 1,090 行 · 第 1/2 页

C
1,090
字号
#ifndef lintstatic	char	*sccsid = "@(#)main.c	4.1	(ULTRIX)	7/2/90";#endif lint/************************************************************************ *									* *			Copyright (c) 1987 by				* *		Digital Equipment Corporation, Maynard, MA		* *			All rights reserved.				* *									* *   This software is furnished under a license and may be used and	* *   copied  only  in accordance with the terms of such license and	* *   with the  inclusion  of  the  above  copyright  notice.   This	* *   software  or  any  other copies thereof may not be provided or	* *   otherwise made available to any other person.  No title to and	* *   ownership of the software is hereby transferred.			* *									* *   This software is  derived  from  software  received  from  the	* *   University    of   California,   Berkeley,   and   from   Bell	* *   Laboratories.  Use, duplication, or disclosure is  subject  to	* *   restrictions  under  license  agreements  with  University  of	* *   California and with AT&T.						* *									* *   The information in this software is subject to change  without	* *   notice  and should not be construed as a commitment by Digital	* *   Equipment Corporation.						* *									* *   Digital assumes no responsibility for the use  or  reliability	* *   of its software on equipment which is not supplied by Digital.	* *									* ************************************************************************/# define  _DEFINE# include <signal.h># include <sgtty.h># include "sendmail.h"# ifdef lintchar	edata, end;# endif lint/***  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 tables read in from /usr/lib/sendmail.cf**	(read by readcf.c).  Some more static configuration info,**	including some code that you may want to tailor for your**	installation, is in conf.c.  You may also want to touch**	daemon.c (if you have some other IPC mechanism), acct.c**	(to change your accounting), names.c (to adjust the name**	server mechanism).****	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 (from 11/81)**		The support of the INGRES Project and Britton-Lee is**			gratefully acknowledged.  Britton-Lee in**			particular had absolutely nothing 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 */ENVELOPE	MainEnvelope;	/* the envelope around the basic letter */ADDRESS		NullAddress =	/* a null address */		{ "", "", "" };/***  Pointers for setproctitle.**	This allows "ps" listings to give more useful information.**	These must be kept out of BSS for frozen configuration files**		to work.*/# ifdef SETPROCTITLEchar		**Argv = NULL;		/* pointer to argument vector */char		*LastArgv = NULL;	/* end of argv */# endif SETPROCTITLE#ifdef DAEMON#ifndef SMTPERROR %%%%   Cannot have daemon mode without SMTP   %%%% ERROR#endif SMTP#endif DAEMONmain(argc, argv, envp)	int argc;	char **argv;	char **envp;{	register char *p;	char **av;	extern int finis();	extern char Version[];	char *from;	typedef int (*fnptr)();	STAB *st;	register int i;	bool readconfig = TRUE;	bool queuemode = FALSE;		/* process queue requests */	bool nothaw;	static bool reenter = FALSE;	char jbuf[30];			/* holds MyHostName */	extern bool safefile();	extern time_t convtime();	extern putheader(), putbody();	extern ENVELOPE *newenvelope();	extern intsig();	extern char **myhostname();	extern char *arpadate();	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;	/*	**  Be sure we have enough file descriptors.	*/	for (i = 3; i < 50; i++)		(void) close(i);	errno = 0;	/*	**  Set default values for variables.	**	These cannot be in initialized data space.	*/	setdefaults();	/* 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);	/*	**  Do a quick prescan of the argument list.	**	We do this to find out if we can potentially thaw the	**	configuration file.  If not, we do the thaw now so that	**	the argument processing applies to this run rather than	**	to the run that froze the configuration.	*/	argv[argc] = NULL;	av = argv;	nothaw = FALSE;	while ((p = *++av) != NULL)	{		if (strncmp(p, "-C", 2) == 0)		{			ConfFile = &p[2];			if (ConfFile[0] == '\0')				ConfFile = "sendmail.cf";			(void) setgid(getrgid());			(void) setuid(getruid());			nothaw = TRUE;		}		else if (strncmp(p, "-bz", 3) == 0)			nothaw = TRUE;# ifdef DEBUG		else if (strncmp(p, "-d", 2) == 0)		{			tTsetup(tTdvect, sizeof tTdvect, "0-99.1");			tTflag(&p[2]);			setbuf(stdout, (char *) NULL);			printf("Version %s\n", Version);		}# endif DEBUG	}	if (!nothaw)		readconfig = !thaw(FreezeFile);	/* reset the environment after the thaw */	for (i = 0; i < MAXUSERENVIRON && envp[i] != NULL; i++)		UserEnviron[i] = newstr(envp[i]);	UserEnviron[i] = NULL;	environ = UserEnviron;# ifdef SETPROCTITLE	/*	**  Save start and extent of argv for setproctitle.	*/	Argv = argv;	if (i > 0)		LastArgv = envp[i - 1] + strlen(envp[i - 1]);	else		LastArgv = argv[argc - 1] + strlen(argv[argc - 1]);# endif SETPROCTITLE	/*	**  Now do basic initialization	*/	InChannel = stdin;	OutChannel = stdout;	if (signal(SIGINT, SIG_IGN) != SIG_IGN)		(void) signal(SIGINT, intsig);	if (signal(SIGHUP, SIG_IGN) != SIG_IGN)		(void) signal(SIGHUP, intsig);	(void) signal(SIGTERM, intsig);	(void) signal(SIGPIPE, SIG_IGN);	OldUmask = umask(0);	OpMode = MD_DELIVER;	MotherPid = getpid();# ifndef V6	FullName = getenv("NAME");# endif V6	/* Get Yellow Pages domain (if any)	 */	if (!getdomainname(default_domain,YPMAXDOMAIN) && 		   (strlen(default_domain) > 0)) 			YPdomain = default_domain;		else			/* If we can't get a domain name for YP,			 * assume YP not up and therefor, no YP maps.			 */			YPdomain = NULL;#ifdef LOG# ifndef BSD4_3	openlog("sendmail", LOG_PID|LOG_CONS|LOG_NDELAY, LOG_DAEMON);# else	BSD4_3	openlog("sendmail",LOG_PID|LOG_TIME);# endif BSD4_3#endif LOG	errno = 0;	from = NULL;	if (readconfig)	{		/* initialize some macros, etc. */		initmacros();		/* hostname */		av = myhostname(jbuf, sizeof jbuf);		if (jbuf[0] != '\0')		{		int i=0;			/* Strip trailing domain spec so that $w macro			 * is unqualified host name for config file			 * rules parsing.			 */                        while (jbuf[i] != '\0' && jbuf[i] != '.')                        {                                i++;                        }                        jbuf[i] = '\0';#ifdef DEBUG			if (tTd(0, 4))				printf("canonical name: %s\n", jbuf);#endif DEBUG			p = newstr(jbuf);			define('w', p, CurEnv);			setclass('w', p);		}		while (av != NULL && *av != NULL)		{#ifdef DEBUG			if (tTd(0, 4))				printf("\ta.k.a.: %s\n", *av);#endif DEBUG			setclass('w', *av++);		}		/* version */		define('v', Version, CurEnv);	}	/* current time */	define('b', arpadate((char *) NULL), CurEnv);	/*	** Crack argv.	*/	av = argv;	p = rindex(*av, '/');	if (p++ == NULL)		p = *av;	if (strcmp(p, "newaliases") == 0)		OpMode = MD_INITALIAS;	else if (strcmp(p, "mailq") == 0)		OpMode = MD_PRINT;	else if (strcmp(p, "smtpd") == 0)		OpMode = MD_DAEMON;	while ((p = *++av) != NULL && p[0] == '-')	{		switch (p[1])		{		  case 'b':	/* operations mode */			switch (p[2])			{			  case MD_DAEMON:# ifndef DAEMON				syserr("Daemon mode not implemented");				break;# endif DAEMON			  case MD_SMTP:# ifndef SMTP				syserr("I don't speak SMTP");				break;# endif SMTP			  case MD_ARPAFTP:			  case MD_DELIVER:			  case MD_VERIFY:			  case MD_TEST:			  case MD_INITALIAS:			  case MD_PRINT:			  case MD_FREEZE:				OpMode = p[2];				break;			  default:				syserr("Invalid operation mode %c", p[2]);				break;			}			break;		  case 'C':	/* select configuration file (already done) */			break;# ifdef DEBUG		  case 'd':	/* debugging -- redo in case frozen */			tTsetup(tTdvect, sizeof tTdvect, "0-99.1");			tTflag(&p[2]);			setbuf(stdout, (char *) NULL);			break;# endif DEBUG		  case 'f':	/* from address */		  case 'r':	/* obsolete -f flag */			p += 2;			if (*p == '\0' && ((p = *++av) == NULL || *p == '-'))			{				p = *++av;				if (p == NULL || *p == '-')				{					syserr("No \"from\" person");					av--;					break;				}			}			if (from != NULL)			{				syserr("More than one \"from\" person");				break;			}			from = newstr(p);			break;		  case 'F':	/* set full name */			p += 2;			if (*p == '\0' && ((p = *++av) == NULL || *p == '-'))			{				syserr("Bad -F flag");				av--;				break;			}			FullName = newstr(p);			break;		  case 'h':	/* hop count */			p += 2;			if (*p == '\0' && ((p = *++av) == NULL || !isdigit(*p)))			{				syserr("Bad hop count (%s)", p);				av--;				break;			}			CurEnv->e_hopcount = atoi(p);			break;				  case 'n':	/* don't alias */			NoAlias = TRUE;			break;		  case 'o':	/* set option */			setoption(p[2], &p[3], FALSE, TRUE);			break;		  case 'q':	/* run queue files at intervals */# ifdef QUEUE			queuemode = TRUE;			QueueIntvl = convtime(&p[2]);# else QUEUE			syserr("I don't know about queues");# endif QUEUE			break;		  case 't':	/* read recipients from message */			GrabTo = TRUE;			break;			/* compatibility flags */		  case 'c':	/* connect to non-local mailers */		  case 'e':	/* error message disposition */		  case 'i':	/* don't let dot stop me */		  case 'm':	/* send to me too */		  case 'T':	/* set timeout interval */		  case 'v':	/* give blow-by-blow description */			setoption(p[1], &p[2], FALSE, TRUE);			break;		  case 's':	/* save From lines in headers */			setoption('f', &p[2], FALSE, TRUE);			break;# ifdef DBM		  case 'I':	/* initialize alias DBM file */			OpMode = MD_INITALIAS;			break;# endif DBM		}	}	/*	**  Do basic initialization.	**	Read system control file.	**	Extract special fields for local use.	*/	if (OpMode == MD_FREEZE || readconfig)		readcf(ConfFile);	switch (OpMode)	{	  case MD_FREEZE:		/* this is critical to avoid forgeries of the frozen config */		(void) setgid(getgid());		(void) setuid(getuid());		/* freeze the configuration */		freeze(FreezeFile);		exit(EX_OK);	  case MD_INITALIAS:		Verbose = TRUE;		break;	}	/* do heuristic mode adjustment */	if (Verbose)	{		/* turn off noconnect option */		setoption('c', "F", TRUE, FALSE);		/* turn on interactive delivery */		setoption('d', "", TRUE, FALSE);	}	/* our name for SMTP codes */	expand("\001j", jbuf, &jbuf[sizeof jbuf - 1], CurEnv);	MyHostName = jbuf;	/* the indices of local and program mailers */	st = stab("local", ST_MAILER, ST_FIND);	if (st == NULL)		syserr("No local mailer defined");	else		LocalMailer = st->s_mailer;	st = stab("prog", ST_MAILER, ST_FIND);	if (st == NULL)		syserr("No prog mailer defined");	else		ProgMailer = st->s_mailer;	/* operate in queue directory */	if (chdir(QueueDir) < 0)	{		syserr("cannot chdir(%s)", QueueDir);		exit(EX_SOFTWARE);	}	/*	**  Do operation-mode-dependent initialization.	*/	switch (OpMode)	{	  case MD_PRINT:		/* print the queue */#ifdef QUEUE		dropenvelope(CurEnv);		printqueue();		exit(EX_OK);#else QUEUE		usrerr("No queue to print");		finis();#endif QUEUE	  case MD_INITALIAS:		/* initialize alias database */		initaliases(AliasFile, TRUE);		exit(EX_OK);	  case MD_DAEMON:		/* don't open alias database -- done in srvrsmtp */		break;	  default:		/* open the alias database */		initaliases(AliasFile, FALSE);		break;	}# ifdef DEBUG	if (tTd(0, 15))	{		/* print configuration table (or at least part of it) */		printrules();

⌨️ 快捷键说明

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