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

📄 readcf.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 id[] = "@(#)$Id: readcf.c,v 8.382.4.27 2000/09/28 01:31:16 gshapiro Exp $";
#endif /* ! lint */

#include <sendmail.h>


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

#define SECONDS
#define MINUTES	* 60
#define HOUR	* 3600
#define HOURS	HOUR

static void	fileclass __P((int, char *, char *, bool, bool));
static char	**makeargv __P((char *));
static void	settimeout __P((char *, char *, bool));
static void	toomany __P((int, int));

/*
**  READCF -- read configuration file.
**
**	This routine reads the configuration file and builds the internal
**	form.
**
**	The file is formatted as a sequence of lines, each taken
**	atomically.  The first character of each line describes how
**	the line is to be interpreted.  The lines are:
**		Dxval		Define macro x to have value val.
**		Cxword		Put word into class x.
**		Fxfile [fmt]	Read file for lines to put into
**				class x.  Use scanf string 'fmt'
**				or "%s" if not present.  Fmt should
**				only produce one string-valued result.
**		Hname: value	Define header with field-name 'name'
**				and value as specified; this will be
**				macro expanded immediately before
**				use.
**		Sn		Use rewriting set n.
**		Rlhs rhs	Rewrite addresses that match lhs to
**				be rhs.
**		Mn arg=val...	Define mailer.  n is the internal name.
**				Args specify mailer parameters.
**		Oxvalue		Set option x to value.
**		Pname=value	Set precedence name to value.
**		Vversioncode[/vendorcode]
**				Version level/vendor name of
**				configuration syntax.
**		Kmapname mapclass arguments....
**				Define keyed lookup of a given class.
**				Arguments are class dependent.
**		Eenvar=value	Set the environment value to the given value.
**
**	Parameters:
**		cfname -- configuration file name.
**		safe -- TRUE if this is the system config file;
**			FALSE otherwise.
**		e -- the main envelope.
**
**	Returns:
**		none.
**
**	Side Effects:
**		Builds several internal tables.
*/

void
readcf(cfname, safe, e)
	char *cfname;
	bool safe;
	register ENVELOPE *e;
{
	FILE *cf;
	int ruleset = -1;
	char *q;
	struct rewrite *rwp = NULL;
	char *bp;
	auto char *ep;
	int nfuzzy;
	char *file;
	bool optional;
	int mid;
	register char *p;
	long sff = SFF_OPENASROOT;
	struct stat statb;
	char buf[MAXLINE];
	char exbuf[MAXLINE];
	char pvpbuf[MAXLINE + MAXATOM];
	static char *null_list[1] = { NULL };
	extern u_char TokTypeNoC[];

	FileName = cfname;
	LineNumber = 0;

	if (DontLockReadFiles)
		sff |= SFF_NOLOCK;
	cf = safefopen(cfname, O_RDONLY, 0444, sff);
	if (cf == NULL)
	{
		syserr("cannot open");
		finis(FALSE, EX_OSFILE);
	}

	if (fstat(fileno(cf), &statb) < 0)
	{
		syserr("cannot fstat");
		finis(FALSE, EX_OSFILE);
	}

	if (!S_ISREG(statb.st_mode))
	{
		syserr("not a plain file");
		finis(FALSE, EX_OSFILE);
	}

	if (OpMode != MD_TEST && bitset(S_IWGRP|S_IWOTH, statb.st_mode))
	{
		if (OpMode == MD_DAEMON || OpMode == MD_INITALIAS)
			fprintf(stderr, "%s: WARNING: dangerous write permissions\n",
				FileName);
		if (LogLevel > 0)
			sm_syslog(LOG_CRIT, NOQID,
				  "%s: WARNING: dangerous write permissions",
				  FileName);
	}

#ifdef XLA
	xla_zero();
#endif /* XLA */

	while ((bp = fgetfolded(buf, sizeof buf, cf)) != NULL)
	{
		if (bp[0] == '#')
		{
			if (bp != buf)
				free(bp);
			continue;
		}

		/* do macro expansion mappings */
		translate_dollars(bp);

		/* interpret this line */
		errno = 0;
		switch (bp[0])
		{
		  case '\0':
		  case '#':		/* comment */
			break;

		  case 'R':		/* rewriting rule */
			if (ruleset < 0)
			{
				syserr("missing valid ruleset for \"%s\"", bp);
				break;
			}
			for (p = &bp[1]; *p != '\0' && *p != '\t'; p++)
				continue;

			if (*p == '\0')
			{
				syserr("invalid rewrite line \"%s\" (tab expected)", bp);
				break;
			}

			/* allocate space for the rule header */
			if (rwp == NULL)
			{
				RewriteRules[ruleset] = rwp =
					(struct rewrite *) xalloc(sizeof *rwp);
			}
			else
			{
				rwp->r_next = (struct rewrite *) xalloc(sizeof *rwp);
				rwp = rwp->r_next;
			}
			rwp->r_next = NULL;

			/* expand and save the LHS */
			*p = '\0';
			expand(&bp[1], exbuf, sizeof exbuf, e);
			rwp->r_lhs = prescan(exbuf, '\t', pvpbuf,
					     sizeof pvpbuf, NULL,
					     ConfigLevel >= 9 ? TokTypeNoC : NULL);
			nfuzzy = 0;
			if (rwp->r_lhs != NULL)
			{
				register char **ap;

				rwp->r_lhs = copyplist(rwp->r_lhs, TRUE);

				/* count the number of fuzzy matches in LHS */
				for (ap = rwp->r_lhs; *ap != NULL; ap++)
				{
					char *botch;

					botch = NULL;
					switch (**ap & 0377)
					{
					  case MATCHZANY:
					  case MATCHANY:
					  case MATCHONE:
					  case MATCHCLASS:
					  case MATCHNCLASS:
						nfuzzy++;
						break;

					  case MATCHREPL:
						botch = "$0-$9";
						break;

					  case CANONUSER:
						botch = "$:";
						break;

					  case CALLSUBR:
						botch = "$>";
						break;

					  case CONDIF:
						botch = "$?";
						break;

					  case CONDFI:
						botch = "$.";
						break;

					  case HOSTBEGIN:
						botch = "$[";
						break;

					  case HOSTEND:
						botch = "$]";
						break;

					  case LOOKUPBEGIN:
						botch = "$(";
						break;

					  case LOOKUPEND:
						botch = "$)";
						break;
					}
					if (botch != NULL)
						syserr("Inappropriate use of %s on LHS",
							botch);
				}
				rwp->r_line = LineNumber;
			}
			else
			{
				syserr("R line: null LHS");
				rwp->r_lhs = null_list;
			}

			/* expand and save the RHS */
			while (*++p == '\t')
				continue;
			q = p;
			while (*p != '\0' && *p != '\t')
				p++;
			*p = '\0';
			expand(q, exbuf, sizeof exbuf, e);
			rwp->r_rhs = prescan(exbuf, '\t', pvpbuf,
					     sizeof pvpbuf, NULL,
					     ConfigLevel >= 9 ? TokTypeNoC : NULL);
			if (rwp->r_rhs != NULL)
			{
				register char **ap;

				rwp->r_rhs = copyplist(rwp->r_rhs, TRUE);

				/* check no out-of-bounds replacements */
				nfuzzy += '0';
				for (ap = rwp->r_rhs; *ap != NULL; ap++)
				{
					char *botch;

					botch = NULL;
					switch (**ap & 0377)
					{
					  case MATCHREPL:
						if ((*ap)[1] <= '0' || (*ap)[1] > nfuzzy)
						{
							syserr("replacement $%c out of bounds",
								(*ap)[1]);
						}
						break;

					  case MATCHZANY:
						botch = "$*";
						break;

					  case MATCHANY:
						botch = "$+";
						break;

					  case MATCHONE:
						botch = "$-";
						break;

					  case MATCHCLASS:
						botch = "$=";
						break;

					  case MATCHNCLASS:
						botch = "$~";
						break;
					}
					if (botch != NULL)
						syserr("Inappropriate use of %s on RHS",
							botch);
				}
			}
			else
			{
				syserr("R line: null RHS");
				rwp->r_rhs = null_list;
			}
			break;

		  case 'S':		/* select rewriting set */
			expand(&bp[1], exbuf, sizeof exbuf, e);
			ruleset = strtorwset(exbuf, NULL, ST_ENTER);
			if (ruleset < 0)
				break;

			rwp = RewriteRules[ruleset];
			if (rwp != NULL)
			{
				if (OpMode == MD_TEST)
					printf("WARNING: Ruleset %s has multiple definitions\n",
					       &bp[1]);
				if (tTd(37, 1))
					dprintf("WARNING: Ruleset %s has multiple definitions\n",
						&bp[1]);
				while (rwp->r_next != NULL)
					rwp = rwp->r_next;
			}
			break;

		  case 'D':		/* macro definition */
			mid = macid(&bp[1], &ep);
			p = munchstring(ep, NULL, '\0');
			define(mid, newstr(p), e);
			break;

		  case 'H':		/* required header line */
			(void) chompheader(&bp[1], CHHDR_DEF, NULL, e);
			break;

		  case 'C':		/* word class */
		  case 'T':		/* trusted user (set class `t') */
			if (bp[0] == 'C')
			{
				mid = macid(&bp[1], &ep);
				expand(ep, exbuf, sizeof exbuf, e);
				p = exbuf;
			}
			else
			{
				mid = 't';
				p = &bp[1];
			}
			while (*p != '\0')
			{
				register char *wd;
				char delim;

				while (*p != '\0' && isascii(*p) && isspace(*p))
					p++;
				wd = p;
				while (*p != '\0' && !(isascii(*p) && isspace(*p)))
					p++;
				delim = *p;
				*p = '\0';
				if (wd[0] != '\0')
					setclass(mid, wd);
				*p = delim;
			}
			break;

		  case 'F':		/* word class from file */
			mid = macid(&bp[1], &ep);
			for (p = ep; isascii(*p) && isspace(*p); )
				p++;
			if (p[0] == '-' && p[1] == 'o')
			{
				optional = TRUE;
				while (*p != '\0' && !(isascii(*p) && isspace(*p)))
					p++;
				while (isascii(*p) && isspace(*p))
					p++;
			}
			else
				optional = FALSE;

			file = p;
			q = p;
			while (*q != '\0' && !(isascii(*q) && isspace(*q)))
				q++;
			if (*file == '|')
				p = "%s";
			else
			{
				p = q;
				if (*p == '\0')
					p = "%s";
				else
				{
					*p = '\0';
					while (isascii(*++p) && isspace(*p))
						continue;
				}
			}
			fileclass(mid, file, p, safe, optional);
			break;

#ifdef XLA
		  case 'L':		/* extended load average description */
			xla_init(&bp[1]);
			break;
#endif /* XLA */

#if defined(SUN_EXTENSIONS) && defined(SUN_LOOKUP_MACRO)
		  case 'L':		/* lookup macro */
		  case 'G':		/* lookup class */
			/* reserved for Sun -- NIS+ database lookup */
			if (VendorCode != VENDOR_SUN)
				goto badline;
			sun_lg_config_line(bp, e);
			break;
#endif /* defined(SUN_EXTENSIONS) && defined(SUN_LOOKUP_MACRO) */

		  case 'M':		/* define mailer */
			makemailer(&bp[1]);
			break;

		  case 'O':		/* set option */
			setoption(bp[1], &bp[2], safe, FALSE, e);
			break;

		  case 'P':		/* set precedence */
			if (NumPriorities >= MAXPRIORITIES)
			{
				toomany('P', MAXPRIORITIES);
				break;
			}
			for (p = &bp[1]; *p != '\0' && *p != '='; p++)
				continue;
			if (*p == '\0')
				goto badline;
			*p = '\0';
			Priorities[NumPriorities].pri_name = newstr(&bp[1]);
			Priorities[NumPriorities].pri_val = atoi(++p);
			NumPriorities++;
			break;

		  case 'V':		/* configuration syntax version */
			for (p = &bp[1]; isascii(*p) && isspace(*p); p++)
				continue;
			if (!isascii(*p) || !isdigit(*p))
			{
				syserr("invalid argument to V line: \"%.20s\"",
					&bp[1]);
				break;
			}
			ConfigLevel = strtol(p, &ep, 10);

			/*
			**  Do heuristic tweaking for back compatibility.
			*/

			if (ConfigLevel >= 5)
			{
				/* level 5 configs have short name in $w */
				p = macvalue('w', e);
				if (p != NULL && (p = strchr(p, '.')) != NULL)
					*p = '\0';
				define('w', macvalue('w', e), e);
			}
			if (ConfigLevel >= 6)
			{
				ColonOkInAddr = FALSE;
			}

			/*
			**  Look for vendor code.
			*/

			if (*ep++ == '/')
			{
				/* extract vendor code */
				for (p = ep; isascii(*p) && isalpha(*p); )
					p++;
				*p = '\0';

				if (!setvendor(ep))
					syserr("invalid V line vendor code: \"%s\"",
						ep);
			}
			break;

		  case 'K':
			expand(&bp[1], exbuf, sizeof exbuf, e);
			(void) makemapentry(exbuf);
			break;

		  case 'E':
			p = strchr(bp, '=');
			if (p != NULL)
				*p++ = '\0';
			setuserenv(&bp[1], p);
			break;

#if _FFR_MILTER
		  case 'X':		/* mail filter */
			milter_setup(&bp[1]);
			break;
#endif /* _FFR_MILTER */

		  default:
		  badline:
			syserr("unknown configuration line \"%s\"", bp);
		}
		if (bp != buf)
			free(bp);
	}
	if (ferror(cf))
	{
		syserr("I/O read error");
		finis(FALSE, EX_OSFILE);
	}
	(void) fclose(cf);
	FileName = NULL;

	/* initialize host maps from local service tables */
	inithostmaps();

	/* initialize daemon (if not defined yet) */
	initdaemon();

	/* determine if we need to do special name-server frotz */
	{
		int nmaps;
		char *maptype[MAXMAPSTACK];
		short mapreturn[MAXMAPACTIONS];

		nmaps = switch_map_find("hosts", maptype, mapreturn);
		UseNameServer = FALSE;

⌨️ 快捷键说明

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