X-Git-Url: https://git.subgeniuskitty.com/unix-history/.git/blobdiff_plain/a444c81bfb6a6f42cb5c433a7a23ed80b0e6a790..af359dea2e5ab3e937b62107ecd6a51d78189ed7:/usr/src/usr.sbin/sendmail/src/readcf.c diff --git a/usr/src/usr.sbin/sendmail/src/readcf.c b/usr/src/usr.sbin/sendmail/src/readcf.c index 6f3926c2d9..bd2bad74dd 100644 --- a/usr/src/usr.sbin/sendmail/src/readcf.c +++ b/usr/src/usr.sbin/sendmail/src/readcf.c @@ -1,6 +1,42 @@ -# 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. @@ -24,19 +60,13 @@ SCCSID(@(#)readcf.c 3.32 %G%); ** 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. @@ -45,20 +75,22 @@ SCCSID(@(#)readcf.c 3.32 %G%); ** 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) @@ -67,9 +99,28 @@ readcf(cfname, safe) 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': @@ -82,8 +133,7 @@ readcf(cfname, safe) if (*p == '\0') { - syserr("line %d: invalid rewrite line \"%s\"", - LineNumber, buf); + syserr("invalid rewrite line \"%s\"", buf); break; } @@ -103,7 +153,7 @@ readcf(cfname, safe) /* 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); @@ -115,7 +165,7 @@ readcf(cfname, safe) 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; @@ -124,15 +174,14 @@ readcf(cfname, safe) 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 */ @@ -141,14 +190,6 @@ readcf(cfname, safe) 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') { @@ -163,7 +204,7 @@ readcf(cfname, safe) while (isspace(*++p)) continue; } - fileclass(class, &buf[2], p); + fileclass(buf[1], &buf[2], p); break; } @@ -172,7 +213,6 @@ readcf(cfname, safe) { register char *wd; char delim; - register STAB *s; while (*p != '\0' && isspace(*p)) p++; @@ -182,33 +222,26 @@ readcf(cfname, safe) 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; @@ -218,12 +251,56 @@ readcf(cfname, safe) 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; +} + /* +** 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); } /* ** FILECLASS -- read members of a class from a file @@ -247,7 +324,7 @@ fileclass(class, filename, fmt) char *filename; char *fmt; { - register FILE *f; + FILE *f; char buf[MAXLINE]; f = fopen(filename, "r"); @@ -260,12 +337,42 @@ fileclass(class, filename, fmt) 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); @@ -274,18 +381,15 @@ fileclass(class, filename, fmt) ** 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. @@ -294,93 +398,213 @@ fileclass(class, filename, fmt) ** 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; +} + /* +** 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); +} + /* +** 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); } /* ** PRINTRULES -- print rewrite rules (for debugging) @@ -395,8 +619,6 @@ makemailer(line, safe) ** prints rewrite rules. */ -# ifdef DEBUG - printrules() { register struct rewrite *rwp; @@ -418,98 +640,310 @@ printrules() } } -# endif DEBUG /* -** 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; } /* -** 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); }