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 + -
显示快捷键?