-# include "sendmail.h"
+/*
+ * Copyright (c) 1983 Eric P. Allman
+ * Copyright (c) 1988 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 lint
+static char sccsid[] = "@(#)readcf.c 5.22 (Berkeley) 3/12/91";
+#endif /* not lint */
-SCCSID(@(#)readcf.c 3.32 %G%);
+# include "sendmail.h"
/*
** READCF -- read control file.
** Sn Use rewriting set n.
** Rlhs rhs Rewrite addresses that match lhs to
** be rhs.
-** Mn p f s r a Define mailer. n - internal name,
-** p - pathname, f - flags, s - rewriting
-** ruleset for sender, s - rewriting ruleset
-** for recipients, a - argument vector.
+** 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.
**
** Parameters:
** cfname -- control file name.
-** safe -- set if this is a system configuration file.
-** Non-system configuration files can not do
-** certain things (e.g., leave the SUID bit on
-** when executing mailers).
**
** Returns:
** none.
** Builds several internal tables.
*/
-readcf(cfname, safe)
+readcf(cfname)
char *cfname;
- bool safe;
{
FILE *cf;
+ int ruleset = 0;
+ char *q;
+ char **pv;
+ struct rewrite *rwp = NULL;
char buf[MAXLINE];
register char *p;
- struct rewrite *rwp = NULL;
extern char **prescan();
extern char **copyplist();
- int class;
- int ruleset = 0;
char exbuf[MAXLINE];
- char *q;
+ char pvpbuf[PSBUFSIZE];
+ extern char *fgetfolded();
+ extern char *munchstring();
cf = fopen(cfname, "r");
if (cf == NULL)
exit(EX_OSFILE);
}
+ FileName = cfname;
LineNumber = 0;
while (fgetfolded(buf, sizeof buf, cf) != NULL)
{
+ /* map $ into \001 (ASCII SOH) for macro expansion */
+ for (p = buf; *p != '\0'; p++)
+ {
+ if (*p != '$')
+ continue;
+
+ if (p[1] == '$')
+ {
+ /* actual dollar sign.... */
+ (void) strcpy(p, p + 1);
+ continue;
+ }
+
+ /* convert to macro expansion character */
+ *p = '\001';
+ }
+
+ /* interpret this line */
switch (buf[0])
{
case '\0':
if (*p == '\0')
{
- syserr("line %d: invalid rewrite line \"%s\"",
- LineNumber, buf);
+ syserr("invalid rewrite line \"%s\"", buf);
break;
}
/* expand and save the LHS */
*p = '\0';
expand(&buf[1], exbuf, &exbuf[sizeof exbuf], CurEnv);
- rwp->r_lhs = prescan(exbuf, '\t');
+ rwp->r_lhs = prescan(exbuf, '\t', pvpbuf);
if (rwp->r_lhs != NULL)
rwp->r_lhs = copyplist(rwp->r_lhs, TRUE);
p++;
*p = '\0';
expand(q, exbuf, &exbuf[sizeof exbuf], CurEnv);
- rwp->r_rhs = prescan(exbuf, '\t');
+ rwp->r_rhs = prescan(exbuf, '\t', pvpbuf);
if (rwp->r_rhs != NULL)
rwp->r_rhs = copyplist(rwp->r_rhs, TRUE);
break;
ruleset = atoi(&buf[1]);
if (ruleset >= MAXRWSETS || ruleset < 0)
{
- syserr("readcf: line %d: bad ruleset %d (%d max)",
- LineNumber, ruleset, MAXRWSETS);
+ syserr("bad ruleset %d (%d max)", ruleset, MAXRWSETS);
ruleset = 0;
}
rwp = NULL;
break;
case 'D': /* macro definition */
- define(buf[1], newstr(&buf[2]));
+ define(buf[1], newstr(munchstring(&buf[2])), CurEnv);
break;
case 'H': /* required header line */
case 'C': /* word class */
case 'F': /* word class from file */
- class = buf[1];
- if (!isalpha(class))
- goto badline;
- if (isupper(class))
- class -= 'A';
- else
- class -= 'a';
-
/* read list of words from argument or file */
if (buf[0] == 'F')
{
while (isspace(*++p))
continue;
}
- fileclass(class, &buf[2], p);
+ fileclass(buf[1], &buf[2], p);
break;
}
{
register char *wd;
char delim;
- register STAB *s;
while (*p != '\0' && isspace(*p))
p++;
delim = *p;
*p = '\0';
if (wd[0] != '\0')
- {
- s = stab(wd, ST_CLASS, ST_ENTER);
- s->s_class |= 1L << class;
- }
+ setclass(buf[1], wd);
*p = delim;
}
break;
case 'M': /* define mailer */
- makemailer(&buf[1], safe);
+ makemailer(&buf[1]);
break;
case 'O': /* set option */
- if (buf[2] == '\0')
- Option[buf[1]] = "";
- else
- Option[buf[1]] = newstr(&buf[2]);
+ setoption(buf[1], &buf[2], TRUE, FALSE);
break;
case 'P': /* set precedence */
if (NumPriorities >= MAXPRIORITIES)
{
- syserr("readcf: line %d: too many P lines, %d max",
- LineNumber, MAXPRIORITIES);
+ toomany('P', MAXPRIORITIES);
break;
}
- for (p = &buf[1]; *p != '\0' && *p != '='; p++)
+ for (p = &buf[1]; *p != '\0' && *p != '=' && *p != '\t'; p++)
continue;
if (*p == '\0')
goto badline;
NumPriorities++;
break;
+ case 'T': /* trusted user(s) */
+ p = &buf[1];
+ while (*p != '\0')
+ {
+ while (isspace(*p))
+ p++;
+ q = p;
+ while (*p != '\0' && !isspace(*p))
+ p++;
+ if (*p != '\0')
+ *p++ = '\0';
+ if (*q == '\0')
+ continue;
+ for (pv = TrustedUsers; *pv != NULL; pv++)
+ continue;
+ if (pv >= &TrustedUsers[MAXTRUST])
+ {
+ toomany('T', MAXTRUST);
+ break;
+ }
+ *pv = newstr(q);
+ }
+ break;
+
default:
badline:
- syserr("readcf: line %d: unknown control line \"%s\"",
- LineNumber, buf);
+ syserr("unknown control line \"%s\"", buf);
}
}
+ FileName = NULL;
+}
+\f/*
+** TOOMANY -- signal too many of some option
+**
+** Parameters:
+** id -- the id of the error line
+** maxcnt -- the maximum possible values
+**
+** Returns:
+** none.
+**
+** Side Effects:
+** gives a syserr.
+*/
+
+toomany(id, maxcnt)
+ char id;
+ int maxcnt;
+{
+ syserr("too many %c lines, %d max", id, maxcnt);
}
\f/*
** FILECLASS -- read members of a class from a file
char *filename;
char *fmt;
{
- register FILE *f;
+ FILE *f;
char buf[MAXLINE];
f = fopen(filename, "r");
while (fgets(buf, sizeof buf, f) != NULL)
{
register STAB *s;
+ register char *p;
+# ifdef SCANF
char wordbuf[MAXNAME+1];
if (sscanf(buf, fmt, wordbuf) != 1)
continue;
- s = stab(wordbuf, ST_CLASS, ST_ENTER);
- s->s_class |= 1L << class;
+ p = wordbuf;
+# else SCANF
+ p = buf;
+# endif SCANF
+
+ /*
+ ** Break up the match into words.
+ */
+
+ while (*p != '\0')
+ {
+ register char *q;
+
+ /* strip leading spaces */
+ while (isspace(*p))
+ p++;
+ if (*p == '\0')
+ break;
+
+ /* find the end of the word */
+ q = p;
+ while (*p != '\0' && !isspace(*p))
+ p++;
+ if (*p != '\0')
+ *p++ = '\0';
+
+ /* enter the word in the symbol table */
+ s = stab(q, ST_CLASS, ST_ENTER);
+ setbitn(class, s->s_class);
+ }
}
(void) fclose(f);
** MAKEMAILER -- define a new mailer.
**
** Parameters:
-** line -- description of mailer. This is in tokens
-** separated by white space. The fields are:
-** * the name of the mailer, as refered to
-** in the rewriting rules.
-** * the pathname of the program to fork to
-** execute it.
-** * the options needed by this program.
-** * the macro string needed to translate
-** a local "from" name to one that can be
-** returned to this machine.
-** * the argument vector (a series of parameters).
-** safe -- set if this is a safe configuration file.
+** line -- description of mailer. This is in labeled
+** fields. The fields are:
+** P -- the path to the mailer
+** F -- the flags associated with the mailer
+** A -- the argv for this mailer
+** S -- the sender rewriting set
+** R -- the recipient rewriting set
+** E -- the eol string
+** The first word is the canonical name of the mailer.
**
** Returns:
** none.
** enters the mailer into the mailer table.
*/
-# define SETWORD \
- { \
- while (*p != '\0' && isspace(*p)) \
- p++; \
- q = p; \
- while (*p != '\0' && !isspace(*p)) \
- p++; \
- if (*p != '\0') \
- *p++ = '\0'; \
- }
-
-makemailer(line, safe)
+makemailer(line)
char *line;
- bool safe;
{
register char *p;
- register char *q;
register struct mailer *m;
register STAB *s;
int i;
- char *mname;
- char *mpath;
- u_long mopts;
- short mrset, msset;
- char *margv[MAXPV + 1];
- extern u_long mfencode();
+ char fcode;
extern int NextMailer;
+ extern char **makeargv();
+ extern char *munchstring();
+ extern char *DelimChar;
+ extern long atol();
- if (NextMailer >= MAXMAILERS)
+ /* allocate a mailer and set up defaults */
+ m = (struct mailer *) xalloc(sizeof *m);
+ bzero((char *) m, sizeof *m);
+ m->m_mno = NextMailer;
+ m->m_eol = "\n";
+
+ /* collect the mailer name */
+ for (p = line; *p != '\0' && *p != ',' && !isspace(*p); p++)
+ continue;
+ if (*p != '\0')
+ *p++ = '\0';
+ m->m_name = newstr(line);
+
+ /* now scan through and assign info from the fields */
+ while (*p != '\0')
{
- syserr("readcf: line %d: too many mailers defined (%d max)",
- LineNumber, MAXMAILERS);
- return;
+ while (*p != '\0' && (*p == ',' || isspace(*p)))
+ p++;
+
+ /* p now points to field code */
+ fcode = *p;
+ while (*p != '\0' && *p != '=' && *p != ',')
+ p++;
+ if (*p++ != '=')
+ {
+ syserr("`=' expected");
+ return;
+ }
+ while (isspace(*p))
+ p++;
+
+ /* p now points to the field body */
+ p = munchstring(p);
+
+ /* install the field into the mailer struct */
+ switch (fcode)
+ {
+ case 'P': /* pathname */
+ m->m_mailer = newstr(p);
+ break;
+
+ case 'F': /* flags */
+ for (; *p != '\0'; p++)
+ setbitn(*p, m->m_flags);
+ break;
+
+ case 'S': /* sender rewriting ruleset */
+ case 'R': /* recipient rewriting ruleset */
+ i = atoi(p);
+ if (i < 0 || i >= MAXRWSETS)
+ {
+ syserr("invalid rewrite set, %d max", MAXRWSETS);
+ return;
+ }
+ if (fcode == 'S')
+ m->m_s_rwset = i;
+ else
+ m->m_r_rwset = i;
+ break;
+
+ case 'E': /* end of line string */
+ m->m_eol = newstr(p);
+ break;
+
+ case 'A': /* argument vector */
+ m->m_argv = makeargv(p);
+ break;
+
+ case 'M': /* maximum message size */
+ m->m_maxsize = atol(p);
+ break;
+ }
+
+ p = DelimChar;
}
- /* collect initial information */
- p = line;
- SETWORD;
- mname = q;
- SETWORD;
- mpath = q;
- SETWORD;
- mopts = mfencode(q);
- if (!safe)
- mopts &= ~M_RESTR;
- SETWORD;
- msset = atoi(q);
- SETWORD;
- mrset = atoi(q);
-
- if (*p == '\0')
+ /* now store the mailer away */
+ if (NextMailer >= MAXMAILERS)
{
- syserr("readcf: line %d: invalid M line in configuration file",
- LineNumber);
+ syserr("too many mailers defined (%d max)", MAXMAILERS);
return;
}
- if (msset >= MAXRWSETS || mrset >= MAXRWSETS)
+ Mailer[NextMailer++] = m;
+ s = stab(m->m_name, ST_MAILER, ST_ENTER);
+ s->s_mailer = m;
+}
+\f/*
+** MUNCHSTRING -- translate a string into internal form.
+**
+** Parameters:
+** p -- the string to munch.
+**
+** Returns:
+** the munched string.
+**
+** Side Effects:
+** Sets "DelimChar" to point to the string that caused us
+** to stop.
+*/
+
+char *
+munchstring(p)
+ register char *p;
+{
+ register char *q;
+ bool backslash = FALSE;
+ bool quotemode = FALSE;
+ static char buf[MAXLINE];
+ extern char *DelimChar;
+
+ for (q = buf; *p != '\0'; p++)
{
- syserr("readcf: line %d: invalid rewrite set, %d max",
- LineNumber, MAXRWSETS);
- return;
+ if (backslash)
+ {
+ /* everything is roughly literal */
+ backslash = FALSE;
+ switch (*p)
+ {
+ case 'r': /* carriage return */
+ *q++ = '\r';
+ continue;
+
+ case 'n': /* newline */
+ *q++ = '\n';
+ continue;
+
+ case 'f': /* form feed */
+ *q++ = '\f';
+ continue;
+
+ case 'b': /* backspace */
+ *q++ = '\b';
+ continue;
+ }
+ *q++ = *p;
+ }
+ else
+ {
+ if (*p == '\\')
+ backslash = TRUE;
+ else if (*p == '"')
+ quotemode = !quotemode;
+ else if (quotemode || *p != ',')
+ *q++ = *p;
+ else
+ break;
+ }
}
- /* allocate a mailer */
- m = (struct mailer *) xalloc(sizeof *m);
- m->m_name = newstr(mname);
- m->m_mailer = newstr(mpath);
- m->m_flags = mopts;
- m->m_r_rwset = mrset;
- m->m_s_rwset = msset;
- m->m_badstat = EX_UNAVAILABLE;
- m->m_mno = NextMailer;
- Mailer[NextMailer++] = m;
+ DelimChar = p;
+ *q++ = '\0';
+ return (buf);
+}
+\f/*
+** MAKEARGV -- break up a string into words
+**
+** Parameters:
+** p -- the string to break up.
+**
+** Returns:
+** a char **argv (dynamically allocated)
+**
+** Side Effects:
+** munges p.
+*/
+
+char **
+makeargv(p)
+ register char *p;
+{
+ char *q;
+ int i;
+ char **avp;
+ char *argv[MAXPV + 1];
- /* collect the argument vector */
- for (i = 0; i < MAXPV - 1 && *p != '\0'; i++)
+ /* take apart the words */
+ i = 0;
+ while (*p != '\0' && i < MAXPV)
{
- SETWORD;
- margv[i] = newstr(q);
+ q = p;
+ while (*p != '\0' && !isspace(*p))
+ p++;
+ while (isspace(*p))
+ *p++ = '\0';
+ argv[i++] = newstr(q);
}
- margv[i++] = NULL;
+ argv[i++] = NULL;
- /* save the argv */
- m->m_argv = (char **) xalloc(sizeof margv[0] * i);
- bmove((char *) margv, (char *) m->m_argv, sizeof margv[0] * i);
- s = stab(m->m_name, ST_MAILER, ST_ENTER);
- s->s_mailer = m;
+ /* now make a copy of the argv */
+ avp = (char **) xalloc(sizeof *avp * i);
+ bcopy((char *) argv, (char *) avp, sizeof *avp * i);
+
+ return (avp);
}
\f/*
** PRINTRULES -- print rewrite rules (for debugging)
** prints rewrite rules.
*/
-# ifdef DEBUG
-
printrules()
{
register struct rewrite *rwp;
}
}
-# endif DEBUG
\f/*
-** MFENCODE -- crack mailer options
-**
-** These options modify the functioning of the mailer
-** from the configuration table.
+** SETOPTION -- set global processing option
**
** Parameters:
-** p -- pointer to vector of options.
+** opt -- option name.
+** val -- option value (as a text string).
+** safe -- set if this came from a configuration file.
+** Some options (if set from the command line) will
+** reset the user id to avoid security problems.
+** sticky -- if set, don't let other setoptions override
+** this value.
**
** Returns:
-** option list in binary.
+** none.
**
** Side Effects:
-** none.
+** Sets options as implied by the arguments.
*/
-struct optlist
-{
- char opt_name; /* external name of option */
- u_long opt_value; /* internal name of option */
-};
-struct optlist OptList[] =
-{
- 'f', M_FOPT,
- 'r', M_ROPT,
- 'q', M_QUIET,
- 'S', M_RESTR,
- 'n', M_NHDR,
- 'l', M_LOCAL,
- 's', M_STRIPQ,
- 'm', M_MUSER,
- 'F', M_NEEDFROM,
- 'D', M_NEEDDATE,
- 'M', M_MSGID,
- 'u', M_USR_UPPER,
- 'h', M_HST_UPPER,
- 'x', M_FULLNAME,
- 'A', M_ARPAFMT,
- 'U', M_UGLYUUCP,
- 'e', M_EXPENSIVE,
- 'X', M_FULLSMTP,
- 'C', M_CANONICAL,
- '\0', 0
-};
-
-u_long
-mfencode(p)
- register char *p;
+static BITMAP StickyOpt; /* set if option is stuck */
+extern char *NetName; /* name of home (local) network */
+
+setoption(opt, val, safe, sticky)
+ char opt;
+ char *val;
+ bool safe;
+ bool sticky;
{
- register struct optlist *o;
- register u_long opts = 0;
+ extern bool atobool();
+ extern time_t convtime();
+ extern int QueueLA;
+ extern int RefuseLA;
+ extern bool trusteduser();
+ extern char *username();
- while (*p != '\0')
+ if (tTd(37, 1))
+ printf("setoption %c=%s", opt, val);
+
+ /*
+ ** See if this option is preset for us.
+ */
+
+ if (bitnset(opt, StickyOpt))
{
- for (o = OptList; o->opt_name != '\0' && o->opt_name != *p; o++)
- continue;
- if (o->opt_name == '\0')
- syserr("bad mailer option %c", *p);
- opts |= o->opt_value;
- p++;
+ if (tTd(37, 1))
+ printf(" (ignored)\n");
+ return;
+ }
+
+ /*
+ ** Check to see if this option can be specified by this user.
+ */
+
+ if (!safe && getuid() == 0)
+ safe = TRUE;
+ if (!safe && index("deiLmorsv", opt) == NULL)
+ {
+ if (opt != 'M' || (val[0] != 'r' && val[0] != 's'))
+ {
+ if (tTd(37, 1))
+ printf(" (unsafe)");
+ if (getuid() != geteuid())
+ {
+ printf("(Resetting uid)\n");
+ (void) setgid(getgid());
+ (void) setuid(getuid());
+ }
+ }
+ }
+ else if (tTd(37, 1))
+ printf("\n");
+
+ switch (opt)
+ {
+ case 'A': /* set default alias file */
+ if (val[0] == '\0')
+ AliasFile = "aliases";
+ else
+ AliasFile = newstr(val);
+ break;
+
+ case 'a': /* look N minutes for "@:@" in alias file */
+ if (val[0] == '\0')
+ SafeAlias = 5;
+ else
+ SafeAlias = atoi(val);
+ break;
+
+ case 'B': /* substitution for blank character */
+ SpaceSub = val[0];
+ if (SpaceSub == '\0')
+ SpaceSub = ' ';
+ break;
+
+ case 'c': /* don't connect to "expensive" mailers */
+ NoConnect = atobool(val);
+ break;
+
+ case 'C': /* checkpoint after N connections */
+ CheckPointLimit = atoi(val);
+ break;
+
+ case 'd': /* delivery mode */
+ switch (*val)
+ {
+ case '\0':
+ SendMode = SM_DELIVER;
+ break;
+
+ case SM_QUEUE: /* queue only */
+#ifndef QUEUE
+ syserr("need QUEUE to set -odqueue");
+#endif QUEUE
+ /* fall through..... */
+
+ case SM_DELIVER: /* do everything */
+ case SM_FORK: /* fork after verification */
+ SendMode = *val;
+ break;
+
+ default:
+ syserr("Unknown delivery mode %c", *val);
+ exit(EX_USAGE);
+ }
+ break;
+
+ case 'D': /* rebuild alias database as needed */
+ AutoRebuild = atobool(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) */
+ HoldErrs = TRUE;
+ /* fall through... */
+
+ case EM_PRINT: /* print errors normally (default) */
+ 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': /* default gid */
+ DefGid = atoi(val);
+ break;
+
+ case 'H': /* help file */
+ if (val[0] == '\0')
+ HelpFile = "sendmail.hf";
+ else
+ HelpFile = newstr(val);
+ break;
+
+ case 'I': /* use internet domain name server */
+ UseNameServer = atobool(val);
+ break;
+
+ case 'i': /* ignore dot lines in message */
+ IgnrDot = atobool(val);
+ break;
+
+ case 'k': /* checkpoint every N addresses */
+ CheckpointInterval = atoi(val);
+ break;
+
+ case 'L': /* log level */
+ LogLevel = atoi(val);
+ break;
+
+ case 'M': /* define macro */
+ define(val[0], newstr(&val[1]), CurEnv);
+ sticky = FALSE;
+ break;
+
+ case 'm': /* send to me too */
+ MeToo = atobool(val);
+ break;
+
+ case 'n': /* validate RHS in newaliases */
+ CheckAliases = atobool(val);
+ break;
+
+# ifdef DAEMON
+ case 'N': /* home (local?) network name */
+ NetName = newstr(val);
+ break;
+# endif DAEMON
+
+ case 'o': /* assume old style headers */
+ if (atobool(val))
+ CurEnv->e_flags |= EF_OLDSTYLE;
+ else
+ CurEnv->e_flags &= ~EF_OLDSTYLE;
+ 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);
+ break;
+
+ case 'r': /* read timeout */
+ ReadTimeout = convtime(val);
+ break;
+
+ case 'S': /* status file */
+ if (val[0] == '\0')
+ StatFile = "sendmail.st";
+ else
+ StatFile = newstr(val);
+ break;
+
+ case 's': /* be super safe, even if expensive */
+ SuperSafe = atobool(val);
+ break;
+
+ case 'T': /* queue timeout */
+ TimeOut = convtime(val);
+ /*FALLTHROUGH*/
+
+ case 't': /* time zone name */
+ break;
+
+ case 'u': /* set default uid */
+ DefUid = atoi(val);
+ setdefuser();
+ break;
+
+ case 'v': /* run in verbose mode */
+ Verbose = atobool(val);
+ break;
+
+ 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;
+
+ default:
+ break;
}
- return (opts);
+ if (sticky)
+ setbitn(opt, StickyOpt);
+ return;
}
\f/*
-** MFDECODE -- decode mailer flags into external form.
+** SETCLASS -- set a word into a class
**
** Parameters:
-** flags -- value of flags to decode.
-** f -- file to write them onto.
+** class -- the class to put the word in.
+** word -- the word to enter
**
** Returns:
** none.
**
** Side Effects:
-** none.
+** puts the word into the symbol table.
*/
-mfdecode(flags, f)
- u_long flags;
- FILE *f;
+setclass(class, word)
+ int class;
+ char *word;
{
- register struct optlist *o;
+ register STAB *s;
- putc('?', f);
- for (o = OptList; o->opt_name != '\0'; o++)
- {
- if ((o->opt_value & flags) == o->opt_value)
- {
- flags &= ~o->opt_value;
- putc(o->opt_name, f);
- }
- }
- putc('?', f);
+ s = stab(word, ST_CLASS, ST_ENTER);
+ setbitn(class, s->s_class);
}