}
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");			break;#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 */		sticky = FALSE;		mid = macid(val, &ep);		if (mid == 0)			break;		p = newstr(ep);		if (!safe)			cleanstrcpy(p, p, MAXNAME);		define(mid, p, CurEnv);		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);			else				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;			DefUid = -1;			pw = sm_getpwnam(val);			if (pw == NULL)			{				syserr("readcf: option u: unknown user %s", val);				break;			}			else			{				DefUid = pw->pw_uid;				DefGid = pw->pw_gid;				DefUser = newstr(pw->pw_name);			}		}#ifdef UID_MAX		if (DefUid > UID_MAX)		{			syserr("readcf: option u: uid value (%ld) > UID_MAX (%ld); ignored",				(long) DefUid, (long) UID_MAX);			break;		}#endif /* UID_MAX */		/* handle the group if it is there */		if (*p == '\0')			break;		val = p;		goto g_opt;	  case 'V':		/* fallback MX host */		if (val[0] != '\0')			FallBackMX = newstr(val);		break;	  case 'v':		/* run in verbose mode */		Verbose = atobool(val) ? 1 : 0;		break;	  case 'w':		/* if we are best MX, try host directly */		TryNullMXList = atobool(val);		break;	    /* 'W' available -- was wizard password */	  case 'x':		/* load avg at which to auto-queue msgs */		QueueLA = atoi(val);		break;	  case 'X':		/* load avg at which to auto-reject connections */		RefuseLA = atoi(val);		break;	  case 'y':		/* work recipient factor */		WkRecipFact = atoi(val);		break;	  case 'Y':		/* fork jobs during queue runs */		ForkQueueRuns = atobool(val);		break;	  case 'z':		/* work message class factor */		WkClassFact = atoi(val);		break;	  case 'Z':		/* work time factor */		WkTimeFact = atoi(val);		break;	  case O_QUEUESORTORD:	/* queue sorting order */		switch (*val)		{		  case 'h':	/* Host first */		  case 'H':			QueueSortOrder = QSO_BYHOST;			break;		  case 'p':	/* Priority order */		  case 'P':			QueueSortOrder = QSO_BYPRIORITY;			break;		  case 't':	/* Submission time */		  case 'T':			QueueSortOrder = QSO_BYTIME;			break;		  case 'f':	/* File Name */		  case 'F':			QueueSortOrder = QSO_BYFILENAME;			break;		  default:			syserr("Invalid queue sort order \"%s\"", val);		}		break;#if _FFR_QUEUEDELAY	  case O_QUEUEDELAY:	/* queue delay algorithm */		switch (*val)		{		  case 'e':	/* exponential */		  case 'E':			QueueAlg = QD_EXP;			QueueInitDelay = 10 MINUTES;			QueueMaxDelay = 2 HOURS;			p = strchr(val, '/');			if (p != NULL)			{				char *q;				*p++ = '\0';				q = strchr(p, '/');				if (q != NULL)					*q++ = '\0';				QueueInitDelay = convtime(p, 's');				if (q != NULL)				{					QueueMaxDelay = convtime(q, 's');				}			}			break;		  case 'l':	/* linear */		  case 'L':			QueueAlg = QD_LINEAR;			break;		  default:			syserr("Invalid queue delay algorithm \"%s\"", val);		}		break;#endif /* _FFR_QUEUEDELAY */	  case O_HOSTSFILE:	/* pathname of /etc/hosts file */		HostsFile = newstr(val);		break;	  case O_MQA:		/* minimum queue age between deliveries */		MinQueueAge = convtime(val, 'm');		break;	  case O_DEFCHARSET:	/* default character set for mimefying */		DefaultCharSet = newstr(denlstring(val, TRUE, TRUE));		break;	  case O_SSFILE:	/* service switch file */		ServiceSwitchFile = newstr(val);		break;	  case O_DIALDELAY:	/* delay for dial-on-demand operation */		DialDelay = convtime(val, 's');		break;	  case O_NORCPTACTION:	/* what to do if no recipient */		if (strcasecmp(val, "none") == 0)			NoRecipientAction = NRA_NO_ACTION;		else if (strcasecmp(val, "add-to") == 0)			NoRecipientAction = NRA_ADD_TO;		else if (strcasecmp(val, "add-apparently-to") == 0)			NoRecipientAction = NRA_ADD_APPARENTLY_TO;		else if (strcasecmp(val, "add-bcc") == 0)			NoRecipientAction = NRA_ADD_BCC;		else if (strcasecmp(val, "add-to-undisclosed") == 0)			NoRecipientAction = NRA_ADD_TO_UNDISCLOSED;		else			syserr("Invalid NoRecipientAction: %s", val);		break;	  case O_SAFEFILEENV:	/* chroot() environ for writing to files */		SafeFileEnv = newstr(val);		break;	  case O_MAXMSGSIZE:	/* maximum message size */		MaxMessageSize = atol(val);		break;	  case O_COLONOKINADDR:	/* old style handling of colon addresses */		ColonOkInAddr = atobool(val);		break;	  case O_MAXQUEUERUN:	/* max # of jobs in a single queue run */		MaxQueueRun = atol(val);		break;	  case O_MAXCHILDREN:	/* max # of children of daemon */		MaxChildren = atoi(val);		break;#if _FFR_MAX_FORWARD_ENTRIES	  case O_MAXFORWARD:	/* max # of forward entries */		MaxForwardEntries = atoi(val);		break;#endif /* _FFR_MAX_FORWARD_ENTRIES */	  case O_KEEPCNAMES:	/* don't expand CNAME records */		DontExpandCnames = atobool(val);		break;	  case O_MUSTQUOTE:	/* must quote these characters in phrases */		(void) strlcpy(buf, "@,;:\\()[]", sizeof buf);		if (strlen(val) < (SIZE_T) sizeof buf - 10)			(void) strlcat(buf, val, sizeof buf);		else			printf("Warning: MustQuoteChars too long, ignored.\n");		MustQuoteChars = newstr(buf);		break;	  case O_SMTPGREETING:	/* SMTP greeting message (old $e macro) */		SmtpGreeting = newstr(munchstring(val, NULL, '\0'));		break;	  case O_UNIXFROM:	/* UNIX From_ line (old $l macro) */		UnixFromLine = newstr(munchstring(val, NULL, '\0'));		break;	  case O_OPCHARS:	/* operator characters (old $o macro) */		if (OperatorChars != NULL)			printf("Warning: OperatorChars is being redefined.\n         It should only be set before ruleset definitions.\n");		OperatorChars = newstr(munchstring(val, NULL, '\0'));		break;	  case O_DONTINITGRPS:	/* don't call initgroups(3) */		DontInitGroups = atobool(val);		break;	  case O_SLFH:		/* make sure from fits on one line */		SingleLineFromHeader = atobool(val);		break;	  case O_ABH:		/* allow HELO commands with syntax errors */		AllowBogusHELO = atobool(val);		break;	  case O_CONNTHROT:	/* connection rate throttle */		ConnRateThrottle = atoi(val);		break;	  case O_UGW:		/* group writable files are unsafe */		if (!atobool(val))		{			setbitn(DBS_GROUPWRITABLEFORWARDFILESAFE,				DontBlameSendmail);			setbitn(DBS_GROUPWRITABLEINCLUDEFILESAFE,				DontBlameSendmail);		}		break;	  case O_DBLBOUNCE:	/* address to which to send double bounces */		if (val[0] != '\0')			DoubleBounceAddr = newstr(val);		else			syserr("readcf: option DoubleBounceAddress: value required");		break;	  case O_HSDIR:		/* persistent host status directory */		if (val[0] != '\0')			HostStatDir = newstr(val);		break;	  case O_SINGTHREAD:	/* single thread deliveries (requires hsdir) */		SingleThreadDelivery = atobool(val);		break;	  case O_RUNASUSER:	/* run bulk of code as this user */		for (p = val; *p != '\0'; p++)		{			if (*p == '.' || *p == '/' || *p == ':')			{				*p++ = '\0';				break;			}		}		if (isascii(*val) && isdigit(*val))		{			if (can_setuid)				RunAsUid = atoi(val);		}		else		{			register struct passwd *pw;			pw = sm_getpwnam(val);			if (pw == NULL)			{				syserr("readcf: option RunAsUser: unknown user %s", val);				break;			}			else if (can_setuid)			{				if (*p == '\0')					RunAsUserName = newstr(val);				RunAsUid = pw->pw_uid;				RunAsGid = pw->pw_gid;			}		}#ifdef UID_MAX		if (RunAsUid > UID_MAX)		{			syserr("readcf: option RunAsUser: uid value (%ld) > UID_MAX (%ld); ignored",				(long) RunAsUid, (long) UID_MAX);			break;		}#endif /* UID_MAX */		if (*p != '\0')		{			if (isascii(*p) && isdigit(*p))			{				if (can_setuid)					RunAsGid = atoi(p);			}			else			{				register struct group *gr;				gr = getgrnam(p);				if (gr == NULL)					syserr("readcf: option RunAsUser: unknown group %s",						p);				else if (can_setuid)					RunAsGid = gr->gr_gid;			}		}		if (tTd(47, 5))			dprintf("readcf: RunAsUser = %d:%d\n",				(int)RunAsUid, (int)RunAsGid);		break;	  case O_DSN_RRT:		RrtImpliesDsn = atobool(val);		break;	  case O_PIDFILE:		if (PidFile != NULL)			free(PidFile);		PidFile = newstr(val);		break;	case O_DONTBLAMESENDMAIL:		p = val;		for (;;)		{			register struct dbsval *dbs;			extern struct dbsval DontBlameSendmailValues[];			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 (dbs = DontBlameSendmailValues;			     dbs->dbs_name != NULL; dbs++)			{				if (strcasecmp(val, dbs->dbs_name) == 0)					break;			}			if (dbs->dbs_name == NULL)				syserr("readcf: DontBlameSendmail option: %s unrecognized", val);			else if (dbs->dbs_flag == DBS_SAFE)				clrbitmap(DontBlameSendmail);			else				setbitn(dbs->dbs_flag, DontBlameSendmail);		}		sticky = FALSE;		break;	  case O_DPI:		DontProbeInterfaces = atobool(val);		break;	  case O_MAXRCPT:		MaxRcptPerMsg = atoi(val);		break;	  case O_DEADLETTER:		if (DeadLetterDrop != NULL)			free(DeadLetterDrop);		DeadLetterDrop = newstr(val);		break;#if _FFR_DONTLOCKFILESFORREAD_OPTION	  case O_DONTLOCK:		DontLockReadFiles = atobool(val);		break;#endif /* _FFR_DONTLOCKFILESFORREAD_OPTION */	  case O_MAXALIASRCSN:		MaxAliasRecursion = atoi(val);		break;	  case O_CNCTONLYTO:		/* XXX should probably use gethostbyname */#if NETINET || NETINET6# if NETINET6		if (inet_addr(val) == INADDR_NONE)		{			ConnectOnlyTo.sa.sa_family = AF_INET6;			if (inet_pton(AF_INET6, val,				      &ConnectOnlyTo.sin6.sin6_addr) != 1)				syserr("readcf: option ConnectOnlyTo: invalid IP address %s",				       val);		}		else# endif /* NETINET6 */		{			ConnectOnlyTo.sa.sa_family = AF_INET;			ConnectOnlyTo.sin.sin_addr.s_addr = inet_addr(val);		}#endif /* NETINET || NETINET6 */		break;	  case O_TRUSTUSER:#if HASFCHOWN		if (isascii(*val) && isdigit(*val))			TrustedUid = atoi(val);		else		{			register struct passwd *pw;			TrustedUid = 0;			pw = sm_getpwnam(val);			if (pw == NULL)			{				syserr("readcf: option TrustedUser: unknown user %s", val);				break;			}			else				TrustedUid = pw->pw_uid;		}# ifdef UID_MAX		if (TrustedUid > UID_MAX)		{			syserr("readcf: option TrustedUser: uid value (%ld) > UID_MAX (%ld)",				(long) TrustedUid, (long) UID_MAX);			TrustedUid = 0;		}# endif /* UID_MAX */#else /* HASFCHOWN */		syserr("readcf: option TrustedUser: can not be used on systems which do not support fchown()");#endif /* HASFCHOWN */		break;	  case O_MAXMIMEHDRLEN:		p = strchr(val, '/');		if (p != NULL)			*p++ = '\0';		MaxMimeHeaderLength = atoi(val);		if (p != NULL && *p != '\0')			MaxMimeFieldLength = atoi(p);		else			MaxMimeFieldLength = MaxMimeHeaderLength / 2;		if (MaxMimeHeaderLength < 0)			MaxMimeHeaderLength = 0;		else if (MaxMimeHeaderLength < 128)			printf("Warning: MaxMimeHeaderLength: header length limit set lower than 128\n");		if (MaxMimeFieldLength < 0)			MaxMimeFieldLength = 0;		else if (MaxMimeFieldLength < 40)			printf("Warning: MaxMimeHeaderLength: field length limit set lower than 40\n");		break;	  case O_CONTROLSOCKET:		if (ControlSocketName != NULL)			free(ControlSocketName);		ControlSocketName = newstr(val);		break;	  case O_MAXHDRSLEN:		MaxHeadersLength = atoi(val);		if (MaxHeadersLength > 0 &&		    MaxHeadersLength < (MAXHDRSLEN / 2))			printf("Warning: MaxHeadersLength: headers length limit set lower than %d\n", (MAXHDRSLEN / 2));		break;	  case O_PROCTITLEPREFIX:		if (ProcTitlePrefix != NULL)			free(ProcTitlePrefix);		ProcTitlePrefix = newstr(val);		break;#if SASL	  case O_SASLINFO:#if _FFR_ALLOW_SASLINFO		/*		**  Allow users to select their own authinfo file.		**  However, this is not a "perfect" solution.		**  If mail is queued, the authentication info		**  will not be used in subsequent delivery attempts.		**  If we really want to support this, then it has		**  to be stored in the queue file.		*/		if (!bitset(SUBMIT_MSA, SubmitMode) && RealUid != 0 &&		    RunAsUid != RealUid)		{			errno = 0;			syserr("Error: %s only allowed with -U\n",				o->o_name == NULL ? "<unknown>" : o->o_name);			ExitStat = EX_USAGE;			break;		}#endif /* _FFR_ALLOW_SASLINFO */		if (SASLInfo != NULL)			free(SASLInfo);		SASLInfo = newstr(val);		break;	  case O_SASLMECH:		if (AuthMechanisms != NULL)			free(AuthMechanisms);		if (*val != '\0')			AuthMechanisms = newstr(val);		else			AuthMechanisms = NULL;		break;	  case O_SASLOPTS:		while (val != NULL && *val != '\0')		{			switch(*val)			{			  case 'A':				SASLOpts |= SASL_AUTH_AUTH;				break;# if _FFR_SASL_OPTS			  case 'a':				SASLOpts |= SASL_SEC_NOACTIVE;				break;			  case 'c':				SASLOpts |= SASL_SEC_PASS_CREDENTIALS;				break;			  case 'd':				SASLOpts |= SASL_SEC_NODICTIONARY;				break;			  case 'f':				SASLOpts |= SASL_SEC_FORWARD_SECRECY;				break;			  case 'p':				SASLOpts |= SASL_SEC_NOPLAINTEXT;				break;			  case 'y':				SASLOpts |= SASL_SEC_NOANONYMOUS;				break;# endif /* _FFR_SASL_OPTS */			  default:				printf("Warning: Option: %s unknown parameter '%c'\n",					o->o_name == NULL ? "<unknown>"							  : o->o_name,					(isascii(*val) && isprint(*val)) ? *val									 : '?');				break;			}			++val;			val = strpbrk(val, ", \t");			if (val != NULL)				++val;		}		break;#else /* SASL */	  case O_SASLINFO:	  case O_SASLMECH:	  case O_SASLOPTS:		printf("Warning: Option: %s requires SASL support (-DSASL)\n",			o->o_name == NULL ? "<unknown>" : o->o_name);		break;#endif /* SASL */#if STARTTLS	  case O_SRVCERTFILE:		if (SrvCERTfile != NULL)			free(SrvCERTfile);		SrvCERTfile = newstr(val);		break;	  case O_SRVKEYFILE:		if (Srvkeyfile != NULL)			free(Srvkeyfile);		Srvkeyfile = newstr(val);		break;	  case O_CLTCERTFILE:		if (CltCERTfile != NULL)			free(CltCERTfile);		CltCERTfile = newstr(val);		break;	  case O_CLTKEYFILE:		if (Cltkeyfile != NULL)			free(Cltkeyfile);		Cltkeyfile = newstr(val);		break;	  case O_CACERTFILE:		if (CACERTfile != NULL)			free(CACERTfile);		CACERTfile = newstr(val);		break;	  case O_CACERTPATH:		if (CACERTpath != NULL)			free(CACERTpath);		CACERTpath = newstr(val);		break;	  case O_DHPARAMS:		if (DHParams != NULL)			free(DHParams);		DHParams = newstr(val);		break;#  if _FFR_TLS_1	  case O_DHPARAMS5:		if (DHParams5 != NULL)			free(DHParams5);		DHParams5 = newstr(val);		break;	  case O_CIPHERLIST:		if (CipherList != NULL)			free(CipherList);		CipherList = newstr(val);		break;#  endif /* _FFR_TLS_1 */	  case O_RANDFILE:		if (RandFile != NULL)			free(RandFile);		RandFile= newstr(val);		break;# else /* STARTTLS */	  case O_SRVCERTFILE:	  case O_SRVKEYFILE:	  case O_CLTCERTFILE:	  case O_CLTKEYFILE:	  case O_CACERTFILE:	  case O_CACERTPATH:	  case O_DHPARAMS:#  if _FFR_TLS_1	  case O_DHPARAMS5:	  case O_CIPHERLIST:#  endif /* _FFR_TLS_1 */	  case O_RANDFILE:		printf("Warning: Option: %s requires TLS support\n",			o->o_name == NULL ? "<unknown>" : o->o_name);		break;# endif /* STARTTLS */	  case O_CLIENTPORT:#if DAEMON		setclientoptions(val);#else /* DAEMON */		syserr("ClientPortOptions (O option) set but DAEMON not compiled in");#endif /* DAEMON */		break;	  case O_DF_BUFSIZE:		DataFileBufferSize = atoi(val);		break;	  case O_XF_BUFSIZE:		XscriptFileBufferSize = atoi(val);		break;	  case O_LDAPDEFAULTSPEC:#ifdef LDAPMAP		ldapmap_set_defaults(val);#else /* LDAPMAP */		printf("Warning: Option: %s requires LDAP support (-DLDAPMAP)\n",			o->o_name == NULL ? "<unknown>" : o->o_name);#endif /* LDAPMAP */		break;#if _FFR_MILTER	  case O_INPUTMILTER:		InputFilterList = newstr(val);		break;	  case O_MILTER:		milter_set_option(subopt, val, sticky);		break;#endif /* _FFR_MILTER */#if _FFR_QUEUE_FILE_MODE	  case O_QUEUE_FILE_MODE:	/* queue file mode */		QueueFileMode = atooct(val) & 0777;		break;#endif /* _FFR_QUEUE_FILE_MODE */	  default:		if (tTd(37, 1))		{			if (isascii(opt) && isprint(opt))				dprintf("Warning: option %c unknown\n", opt);			else				dprintf("Warning: option 0x%x unknown\n", opt);		}		break;	}	/*	**  Options with suboptions are responsible for taking care	**  of sticky-ness (e.g., that a command line setting is kept	**  when reading in the sendmail.cf file).  This has to be done	**  when the suboptions are parsed since each suboption must be	**  sticky, not the root option.	*/	if (sticky && !bitset(OI_SUBOPT, o->o_flags))		setbitn(opt, StickyOpt);}