readcf.c

来自「< linux网络编程工具>>配套源码」· C语言 代码 · 共 2,821 行 · 第 1/5 页

C
2,821
字号
	{ "Milter",			O_MILTER,	OI_SUBOPT	},
#endif /* _FFR_MILTER */
#define O_SASLOPTS	0xbd
	{ "AuthOptions",		O_SASLOPTS,	OI_NONE	},
#if _FFR_QUEUE_FILE_MODE
#define O_QUEUE_FILE_MODE	0xbe
	{ "QueueFileMode",		O_QUEUE_FILE_MODE, OI_NONE	},
#endif /* _FFR_QUEUE_FILE_MODE */
# if _FFR_TLS_1
# define O_DHPARAMS5	0xbf
	{ "DHParameters512",		O_DHPARAMS5,	OI_NONE	},
# define O_CIPHERLIST	0xc0
	{ "CipherList",			O_CIPHERLIST,	OI_NONE	},
# endif /* _FFR_TLS_1 */
# define O_RANDFILE	0xc1
	{ "RandFile",			O_RANDFILE,	OI_NONE	},
	{ NULL,				'\0',		OI_NONE	}
};

void
setoption(opt, val, safe, sticky, e)
	int opt;
	char *val;
	bool safe;
	bool sticky;
	register ENVELOPE *e;
{
	register char *p;
	register struct optioninfo *o;
	char *subopt;
	int mid;
	bool can_setuid = RunAsUid == 0;
	auto char *ep;
	char buf[50];
	extern bool Warn_Q_option;
#if _FFR_ALLOW_SASLINFO
	extern int SubmitMode;
#endif /* _FFR_ALLOW_SASLINFO */

	errno = 0;
	if (opt == ' ')
	{
		/* full word options */
		struct optioninfo *sel;

		p = strchr(val, '=');
		if (p == NULL)
			p = &val[strlen(val)];
		while (*--p == ' ')
			continue;
		while (*++p == ' ')
			*p = '\0';
		if (p == val)
		{
			syserr("readcf: null option name");
			return;
		}
		if (*p == '=')
			*p++ = '\0';
		while (*p == ' ')
			p++;
		subopt = strchr(val, '.');
		if (subopt != NULL)
			*subopt++ = '\0';
		sel = NULL;
		for (o = OptionTab; o->o_name != NULL; o++)
		{
			if (strncasecmp(o->o_name, val, strlen(val)) != 0)
				continue;
			if (strlen(o->o_name) == strlen(val))
			{
				/* completely specified -- this must be it */
				sel = NULL;
				break;
			}
			if (sel != NULL)
				break;
			sel = o;
		}
		if (sel != NULL && o->o_name == NULL)
			o = sel;
		else if (o->o_name == NULL)
		{
			syserr("readcf: unknown option name %s", val);
			return;
		}
		else if (sel != NULL)
		{
			syserr("readcf: ambiguous option name %s (matches %s and %s)",
				val, sel->o_name, o->o_name);
			return;
		}
		if (strlen(val) != strlen(o->o_name))
		{
			int oldVerbose = Verbose;

			Verbose = 1;
			message("Option %s used as abbreviation for %s",
				val, o->o_name);
			Verbose = oldVerbose;
		}
		opt = o->o_code;
		val = p;
	}
	else
	{
		for (o = OptionTab; o->o_name != NULL; o++)
		{
			if (o->o_code == opt)
				break;
		}
		subopt = NULL;
	}

	if (subopt != NULL && !bitset(OI_SUBOPT, o->o_flags))
	{
		if (tTd(37, 1))
			dprintf("setoption: %s does not support suboptions, ignoring .%s\n",
				o->o_name == NULL ? "<unknown>" : o->o_name,
				subopt);
		subopt = NULL;
	}

	if (tTd(37, 1))
	{
		dprintf(isascii(opt) && isprint(opt) ?
			"setoption %s (%c)%s%s=" :
			"setoption %s (0x%x)%s%s=",
			o->o_name == NULL ? "<unknown>" : o->o_name,
			opt,
			subopt == NULL ? "" : ".",
			subopt == NULL ? "" : subopt);
		xputs(val);
	}

	/*
	**  See if this option is preset for us.
	*/

	if (!sticky && bitnset(opt, StickyOpt))
	{
		if (tTd(37, 1))
			dprintf(" (ignored)\n");
		return;
	}

	/*
	**  Check to see if this option can be specified by this user.
	*/

	if (!safe && RealUid == 0)
		safe = TRUE;
	if (!safe && !bitset(OI_SAFE, o->o_flags))
	{
		if (opt != 'M' || (val[0] != 'r' && val[0] != 's'))
		{
			int dp;

			if (tTd(37, 1))
				dprintf(" (unsafe)");
			dp = drop_privileges(TRUE);
			setstat(dp);
		}
	}
	if (tTd(37, 1))
		dprintf("\n");

	switch (opt & 0xff)
	{
	  case '7':		/* force seven-bit input */
		SevenBitInput = atobool(val);
		break;

#if MIME8TO7
	  case '8':		/* handling of 8-bit input */
		switch (*val)
		{
		  case 'm':		/* convert 8-bit, convert MIME */
			MimeMode = MM_CVTMIME|MM_MIME8BIT;
			break;

		  case 'p':		/* pass 8 bit, convert MIME */
			MimeMode = MM_CVTMIME|MM_PASS8BIT;
			break;

		  case 's':		/* strict adherence */
			MimeMode = MM_CVTMIME;
			break;

# if 0
		  case 'r':		/* reject 8-bit, don't convert MIME */
			MimeMode = 0;
			break;

		  case 'j':		/* "just send 8" */
			MimeMode = MM_PASS8BIT;
			break;

		  case 'a':		/* encode 8 bit if available */
			MimeMode = MM_MIME8BIT|MM_PASS8BIT|MM_CVTMIME;
			break;

		  case 'c':		/* convert 8 bit to MIME, never 7 bit */
			MimeMode = MM_MIME8BIT;
			break;
# endif /* 0 */

		  default:
			syserr("Unknown 8-bit mode %c", *val);
			finis(FALSE, EX_USAGE);
		}
		break;
#endif /* MIME8TO7 */

	  case 'A':		/* set default alias file */
		if (val[0] == '\0')
			setalias("aliases");
		else
			setalias(val);
		break;

	  case 'a':		/* look N minutes for "@:@" in alias file */
		if (val[0] == '\0')
			SafeAlias = 5 * 60;		/* five minutes */
		else
			SafeAlias = convtime(val, 'm');
		break;

	  case 'B':		/* substitution for blank character */
		SpaceSub = val[0];
		if (SpaceSub == '\0')
			SpaceSub = ' ';
		break;

	  case 'b':		/* min blocks free on queue fs/max msg size */
		p = strchr(val, '/');
		if (p != NULL)
		{
			*p++ = '\0';
			MaxMessageSize = atol(p);
		}
		MinBlocksFree = atol(val);
		break;

	  case 'c':		/* don't connect to "expensive" mailers */
		NoConnect = atobool(val);
		break;

	  case 'C':		/* checkpoint every N addresses */
		CheckpointInterval = atoi(val);
		break;

	  case 'd':		/* delivery mode */
		switch (*val)
		{
		  case '\0':
			set_delivery_mode(SM_DELIVER, e);
			break;

		  case SM_QUEUE:	/* queue only */
		  case SM_DEFER:	/* queue only and defer map lookups */
#if !QUEUE
			syserr("need QUEUE to set -odqueue or -oddefer");
#endif /* !QUEUE */
			/* FALLTHROUGH */

		  case SM_DELIVER:	/* do everything */
		  case SM_FORK:		/* fork after verification */
			set_delivery_mode(*val, e);
			break;

		  default:
			syserr("Unknown delivery mode %c", *val);
			finis(FALSE, EX_USAGE);
		}
		break;

#if !_FFR_REMOVE_AUTOREBUILD
	  case 'D':		/* rebuild alias database as needed */
		AutoRebuild = atobool(val);
		break;
#endif /* !_FFR_REMOVE_AUTOREBUILD */

	  case 'E':		/* error message header/header file */
		if (*val != '\0')
			ErrMsgFile = newstr(val);
		break;

	  case 'e':		/* set error processing mode */
		switch (*val)
		{
		  case EM_QUIET:	/* be silent about it */
		  case EM_MAIL:		/* mail back */
		  case EM_BERKNET:	/* do berknet error processing */
		  case EM_WRITE:	/* write back (or mail) */
		  case EM_PRINT:	/* print errors normally (default) */
			e->e_errormode = *val;
			break;
		}
		break;

	  case 'F':		/* file mode */
		FileMode = atooct(val) & 0777;
		break;

	  case 'f':		/* save Unix-style From lines on front */
		SaveFrom = atobool(val);
		break;

	  case 'G':		/* match recipients against GECOS field */
		MatchGecos = atobool(val);
		break;

	  case 'g':		/* default gid */
  g_opt:
		if (isascii(*val) && isdigit(*val))
			DefGid = atoi(val);
		else
		{
			register struct group *gr;

			DefGid = -1;
			gr = getgrnam(val);
			if (gr == NULL)
				syserr("readcf: option %c: unknown group %s",
					opt, val);
			else
				DefGid = gr->gr_gid;
		}
		break;

	  case 'H':		/* help file */
		if (val[0] == '\0')
			HelpFile = "helpfile";
		else
			HelpFile = newstr(val);
		break;

	  case 'h':		/* maximum hop count */
		MaxHopCount = atoi(val);
		break;

	  case 'I':		/* use internet domain name server */
#if NAMED_BIND
		for (p = val; *p != 0; )
		{
			bool clearmode;
			char *q;
			struct resolverflags *rfp;

			while (*p == ' ')
				p++;
			if (*p == '\0')
				break;
			clearmode = FALSE;
			if (*p == '-')
				clearmode = TRUE;
			else if (*p != '+')
				p--;
			p++;
			q = p;
			while (*p != '\0' && !(isascii(*p) && isspace(*p)))
				p++;
			if (*p != '\0')
				*p++ = '\0';
			if (strcasecmp(q, "HasWildcardMX") == 0)
			{
				HasWildcardMX = !clearmode;
				continue;
			}
			for (rfp = ResolverFlags; rfp->rf_name != NULL; rfp++)
			{
				if (strcasecmp(q, rfp->rf_name) == 0)
					break;
			}
			if (rfp->rf_name == NULL)
				syserr("readcf: I option value %s unrecognized", q);
			else if (clearmode)
				_res.options &= ~rfp->rf_bits;
			else
				_res.options |= rfp->rf_bits;
		}
		if (tTd(8, 2))
			dprintf("_res.options = %x, HasWildcardMX = %d\n",
				(u_int) _res.options, HasWildcardMX);
#else /* NAMED_BIND */
		usrerr("name server (I option) specified but BIND not compiled in");
#endif /* NAMED_BIND */
		break;

	  case 'i':		/* ignore dot lines in message */
		IgnrDot = atobool(val);
		break;

	  case 'j':		/* send errors in MIME (RFC 1341) format */
		SendMIMEErrors = atobool(val);
		break;

	  case 'J':		/* .forward search path */
		ForwardPath = newstr(val);
		break;

	  case 'k':		/* connection cache size */
		MaxMciCache = atoi(val);
		if (MaxMciCache < 0)
			MaxMciCache = 0;
		break;

	  case 'K':		/* connection cache timeout */
		MciCacheTimeout = convtime(val, 'm');
		break;

	  case 'l':		/* use Errors-To: header */
		UseErrorsTo = atobool(val);
		break;

	  case 'L':		/* log level */
		if (safe || LogLevel < atoi(val))
			LogLevel = atoi(val);
		break;

	  case 'M':		/* define macro */
		mid = macid(val, &ep);
		p = newstr(ep);
		if (!safe)
			cleanstrcpy(p, p, MAXNAME);
		define(mid, p, CurEnv);
		sticky = FALSE;
		break;

	  case 'm':		/* send to me too */
		MeToo = atobool(val);
		break;

	  case 'n':		/* validate RHS in newaliases */
		CheckAliases = atobool(val);
		break;

	    /* 'N' available -- was "net name" */

	  case 'O':		/* daemon options */
#if DAEMON
		if (!setdaemonoptions(val))
		{
			syserr("too many daemons defined (%d max)", MAXDAEMONS);
		}
#else /* DAEMON */
		syserr("DaemonPortOptions (O option) set but DAEMON not compiled in");
#endif /* DAEMON */
		break;

	  case 'o':		/* assume old style headers */
		if (atobool(val))
			CurEnv->e_flags |= EF_OLDSTYLE;
		else
			CurEnv->e_flags &= ~EF_OLDSTYLE;
		break;

	  case 'p':		/* select privacy level */
		p = val;
		for (;;)
		{
			register struct prival *pv;
			extern struct prival PrivacyValues[];

			while (isascii(*p) && (isspace(*p) || ispunct(*p)))
				p++;
			if (*p == '\0')
				break;
			val = p;
			while (isascii(*p) && isalnum(*p))
				p++;
			if (*p != '\0')
				*p++ = '\0';

			for (pv = PrivacyValues; pv->pv_name != NULL; pv++)
			{
				if (strcasecmp(val, pv->pv_name) == 0)
					break;
			}
			if (pv->pv_name == NULL)
				syserr("readcf: Op line: %s unrecognized", val);
			PrivacyFlags |= pv->pv_flag;
		}
		sticky = FALSE;
		break;

	  case 'P':		/* postmaster copy address for returned mail */
		PostMasterCopy = newstr(val);
		break;

	  case 'q':		/* slope of queue only function */
		QueueFactor = atoi(val);
		break;

	  case 'Q':		/* queue directory */
		if (val[0] == '\0')
		{
			QueueDir = "mqueue";
		}
		else
		{
			QueueDir = newstr(val);
		}
		if (RealUid != 0 && !safe)
			Warn_Q_option = TRUE;
		break;

	  case 'R':		/* don't prune routes */
		DontPruneRoutes = atobool(val);
		break;

	  case 'r':		/* read timeout */
		if (subopt == NULL)
			inittimeouts(val, sticky);
		else
			settimeout(subopt, val, sticky);
		break;

	  case 'S':		/* status file */
		if (val[0] == '\0')
			StatFile = "statistics";
		else
			StatFile = newstr(val);
		break;

	  case 's':		/* be super safe, even if expensive */
		SuperSafe = atobool(val);
		break;

	  case 'T':		/* queue timeout */
		p = strchr(val, '/');
		if (p != NULL)
		{
			*p++ = '\0';
			settimeout("queuewarn", p, sticky);
		}
		settimeout("queuereturn", val, sticky);
		break;

	  case 't':		/* time zone name */
		TimeZoneSpec = newstr(val);
		break;

	  case 'U':		/* location of user database */
		UdbSpec = newstr(val);
		break;

	  case 'u':		/* set default uid */
		for (p = val; *p != '\0'; p++)
		{
			if (*p == '.' || *p == '/' || *p == ':')
			{
				*p++ = '\0';
				break;
			}
		}
		if (isascii(*val) && isdigit(*val))
		{
			DefUid = atoi(val);
			setdefuser();
		}
		else
		{
			register struct passwd *pw;

⌨️ 快捷键说明

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