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

📄 readcf.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * Copyright (c) 1983 Eric P. Allman * Copyright (c) 1988, 1993 *	The Regents of the University of California.  All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright *    notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright *    notice, this list of conditions and the following disclaimer in the *    documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software *    must display the following acknowledgement: *	This product includes software developed by the University of *	California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors *    may be used to endorse or promote products derived from this software *    without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */#ifndef lintstatic char sccsid[] = "@(#)readcf.c	8.23 (Berkeley) 3/18/94";#endif /* not lint */# include "sendmail.h"# include <pwd.h># include <grp.h>#if NAMED_BIND# include <arpa/nameser.h># include <resolv.h>#endif/***  READCF -- read control file.****	This routine reads the control 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.****	Parameters:**		cfname -- control 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.*/readcf(cfname, safe, e)	char *cfname;	bool safe;	register ENVELOPE *e;{	FILE *cf;	int ruleset = 0;	char *q;	struct rewrite *rwp = NULL;	char *bp;	auto char *ep;	int nfuzzy;	char *file;	bool optional;	char buf[MAXLINE];	register char *p;	extern char **copyplist();	struct stat statb;	char exbuf[MAXLINE];	char pvpbuf[MAXLINE + MAXATOM];	extern char *munchstring();	extern void makemapentry();	FileName = cfname;	LineNumber = 0;	cf = fopen(cfname, "r");	if (cf == NULL)	{		syserr("cannot open");		exit(EX_OSFILE);	}	if (fstat(fileno(cf), &statb) < 0)	{		syserr("cannot fstat");		exit(EX_OSFILE);	}	if (!S_ISREG(statb.st_mode))	{		syserr("not a plain file");		exit(EX_OSFILE);	}	if (OpMode != MD_TEST && bitset(S_IWGRP|S_IWOTH, statb.st_mode))	{		if (OpMode == MD_DAEMON || OpMode == MD_FREEZE)			fprintf(stderr, "%s: WARNING: dangerous write permissions\n",				FileName);#ifdef LOG		if (LogLevel > 0)			syslog(LOG_CRIT, "%s: WARNING: dangerous write permissions",				FileName);#endif	}#ifdef XLA	xla_zero();#endif	while ((bp = fgetfolded(buf, sizeof buf, cf)) != NULL)	{		if (bp[0] == '#')		{			if (bp != buf)				free(bp);			continue;		}		/* map $ into \201 for macro expansion */		for (p = bp; *p != '\0'; p++)		{			if (*p == '#' && p > bp && ConfigLevel >= 3)			{				/* this is an on-line comment */				register char *e;				switch (*--p & 0377)				{				  case MACROEXPAND:					/* it's from $# -- let it go through */					p++;					break;				  case '\\':					/* it's backslash escaped */					(void) strcpy(p, p + 1);					break;				  default:					/* delete preceeding white space */					while (isascii(*p) && isspace(*p) && p > bp)						p--;					if ((e = strchr(++p, '\n')) != NULL)						(void) strcpy(p, e);					else						p[0] = p[1] = '\0';					break;				}				continue;			}			if (*p != '$')				continue;			if (p[1] == '$')			{				/* actual dollar sign.... */				(void) strcpy(p, p + 1);				continue;			}			/* convert to macro expansion character */			*p = MACROEXPAND;		}		/* interpret this line */		errno = 0;		switch (bp[0])		{		  case '\0':		  case '#':		/* comment */			break;		  case 'R':		/* rewriting rule */			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, &exbuf[sizeof exbuf], e);			rwp->r_lhs = prescan(exbuf, '\t', pvpbuf,					     sizeof pvpbuf, 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 CANONNET:						botch = "$#";						break;					  case CANONUSER:						botch = "$:";						break;					  case CALLSUBR:						botch = "$>";						break;					  case CONDIF:						botch = "$?";						break;					  case CONDELSE:						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);				}			}			else				syserr("R line: null LHS");			/* expand and save the RHS */			while (*++p == '\t')				continue;			q = p;			while (*p != '\0' && *p != '\t')				p++;			*p = '\0';			expand(q, exbuf, &exbuf[sizeof exbuf], e);			rwp->r_rhs = prescan(exbuf, '\t', pvpbuf,					     sizeof pvpbuf, 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");			break;		  case 'S':		/* select rewriting set */			for (p = &bp[1]; isascii(*p) && isspace(*p); p++)				continue;			if (!isascii(*p) || !isdigit(*p))			{				syserr("invalid argument to S line: \"%.20s\"", 					&bp[1]);				break;			}			ruleset = atoi(p);			if (ruleset >= MAXRWSETS || ruleset < 0)			{				syserr("bad ruleset %d (%d max)", ruleset, MAXRWSETS);				ruleset = 0;			}			rwp = NULL;			break;		  case 'D':		/* macro definition */			p = munchstring(&bp[2], NULL);			define(bp[1], newstr(p), e);			break;		  case 'H':		/* required header line */			(void) chompheader(&bp[1], TRUE, e);			break;		  case 'C':		/* word class */			/* scan the list of words and set class for all */			expand(&bp[2], exbuf, &exbuf[sizeof exbuf], e);			for (p = exbuf; *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(bp[1], wd);				*p = delim;			}			break;		  case 'F':		/* word class from file */			for (p = &bp[2]; 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;			while (*p != '\0' && !(isascii(*p) && isspace(*p)))				p++;			if (*p == '\0')				p = "%s";			else			{				*p = '\0';				while (isascii(*++p) && isspace(*p))					continue;			}			fileclass(bp[1], file, p, safe, optional);			break;#ifdef XLA		  case 'L':		/* extended load average description */			xla_init(&bp[1]);			break;#endif		  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 != '\t'; 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 'T':		/* trusted user(s) */			/* this option is obsolete, but will be ignored */			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);			if (ConfigLevel >= 5)			{				/* level 5 configs have short name in $w */				p = macvalue('w', e);				if (p != NULL && (p = strchr(p, '.')) != NULL)					*p = '\0';			}			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':			makemapentry(&bp[1]);			break;		  default:		  badline:			syserr("unknown control line \"%s\"", bp);		}		if (bp != buf)			free(bp);	}	if (ferror(cf))	{		syserr("I/O read error", cfname);		exit(EX_OSFILE);	}	fclose(cf);	FileName = NULL;	if (stab("host", ST_MAP, ST_FIND) == NULL)	{		/* user didn't initialize: set up host map */		strcpy(buf, "host host");#if NAMED_BIND		if (ConfigLevel >= 2)			strcat(buf, " -a.");#endif		makemapentry(buf);	}}/***  TOOMANY -- signal too many of some option****	Parameters:**		id -- the id of the error line**		maxcnt -- the maximum possible values****	Returns:**		none.**

⌨️ 快捷键说明

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