readcf.c revision 98841
138032Speter/* 294334Sgshapiro * Copyright (c) 1998-2002 Sendmail, Inc. and its suppliers. 364562Sgshapiro * All rights reserved. 438032Speter * Copyright (c) 1983, 1995-1997 Eric P. Allman. All rights reserved. 538032Speter * Copyright (c) 1988, 1993 638032Speter * The Regents of the University of California. All rights reserved. 738032Speter * 838032Speter * By using this file, you agree to the terms and conditions set 938032Speter * forth in the LICENSE file which can be found at the top level of 1038032Speter * the sendmail distribution. 1138032Speter * 1238032Speter */ 1338032Speter 1464562Sgshapiro#include <sendmail.h> 1538032Speter 1698841SgshapiroSM_RCSID("@(#)$Id: readcf.c,v 8.607 2002/06/14 16:57:32 ca Exp $") 1764562Sgshapiro 1864562Sgshapiro#if NETINET || NETINET6 1964562Sgshapiro# include <arpa/inet.h> 2064562Sgshapiro#endif /* NETINET || NETINET6 */ 2164562Sgshapiro 2264562Sgshapiro#define SECONDS 2364562Sgshapiro#define MINUTES * 60 2464562Sgshapiro#define HOUR * 3600 2564562Sgshapiro#define HOURS HOUR 2664562Sgshapiro 2794334Sgshapirostatic void fileclass __P((int, char *, char *, bool, bool, bool)); 2864562Sgshapirostatic char **makeargv __P((char *)); 2964562Sgshapirostatic void settimeout __P((char *, char *, bool)); 3064562Sgshapirostatic void toomany __P((int, int)); 3190792Sgshapirostatic char *extrquotstr __P((char *, char **, char *, bool *)); 3264562Sgshapiro 3338032Speter/* 3438032Speter** READCF -- read configuration file. 3538032Speter** 3638032Speter** This routine reads the configuration file and builds the internal 3738032Speter** form. 3838032Speter** 3938032Speter** The file is formatted as a sequence of lines, each taken 4038032Speter** atomically. The first character of each line describes how 4138032Speter** the line is to be interpreted. The lines are: 4238032Speter** Dxval Define macro x to have value val. 4338032Speter** Cxword Put word into class x. 4438032Speter** Fxfile [fmt] Read file for lines to put into 4538032Speter** class x. Use scanf string 'fmt' 4638032Speter** or "%s" if not present. Fmt should 4738032Speter** only produce one string-valued result. 4838032Speter** Hname: value Define header with field-name 'name' 4938032Speter** and value as specified; this will be 5038032Speter** macro expanded immediately before 5138032Speter** use. 5238032Speter** Sn Use rewriting set n. 5338032Speter** Rlhs rhs Rewrite addresses that match lhs to 5438032Speter** be rhs. 5538032Speter** Mn arg=val... Define mailer. n is the internal name. 5638032Speter** Args specify mailer parameters. 5738032Speter** Oxvalue Set option x to value. 5890792Sgshapiro** O option value Set option (long name) to value. 5938032Speter** Pname=value Set precedence name to value. 6090792Sgshapiro** Qn arg=val... Define queue groups. n is the internal name. 6190792Sgshapiro** Args specify queue parameters. 6238032Speter** Vversioncode[/vendorcode] 6338032Speter** Version level/vendor name of 6438032Speter** configuration syntax. 6538032Speter** Kmapname mapclass arguments.... 6638032Speter** Define keyed lookup of a given class. 6738032Speter** Arguments are class dependent. 6838032Speter** Eenvar=value Set the environment value to the given value. 6938032Speter** 7038032Speter** Parameters: 7138032Speter** cfname -- configuration file name. 7290792Sgshapiro** safe -- true if this is the system config file; 7390792Sgshapiro** false otherwise. 7438032Speter** e -- the main envelope. 7538032Speter** 7638032Speter** Returns: 7738032Speter** none. 7838032Speter** 7938032Speter** Side Effects: 8038032Speter** Builds several internal tables. 8138032Speter*/ 8238032Speter 8338032Spetervoid 8438032Speterreadcf(cfname, safe, e) 8538032Speter char *cfname; 8638032Speter bool safe; 8738032Speter register ENVELOPE *e; 8838032Speter{ 8990792Sgshapiro SM_FILE_T *cf; 9064562Sgshapiro int ruleset = -1; 9138032Speter char *q; 9238032Speter struct rewrite *rwp = NULL; 9338032Speter char *bp; 9438032Speter auto char *ep; 9538032Speter int nfuzzy; 9638032Speter char *file; 9738032Speter bool optional; 9890792Sgshapiro bool ok; 9994334Sgshapiro bool ismap; 10038032Speter int mid; 10138032Speter register char *p; 10264562Sgshapiro long sff = SFF_OPENASROOT; 10338032Speter struct stat statb; 10438032Speter char buf[MAXLINE]; 10538032Speter char exbuf[MAXLINE]; 10638032Speter char pvpbuf[MAXLINE + MAXATOM]; 10738032Speter static char *null_list[1] = { NULL }; 10890792Sgshapiro extern unsigned char TokTypeNoC[]; 10938032Speter 11038032Speter FileName = cfname; 11138032Speter LineNumber = 0; 11238032Speter 11338032Speter if (DontLockReadFiles) 11438032Speter sff |= SFF_NOLOCK; 11538032Speter cf = safefopen(cfname, O_RDONLY, 0444, sff); 11638032Speter if (cf == NULL) 11738032Speter { 11838032Speter syserr("cannot open"); 11990792Sgshapiro finis(false, true, EX_OSFILE); 12038032Speter } 12138032Speter 12290792Sgshapiro if (fstat(sm_io_getinfo(cf, SM_IO_WHAT_FD, NULL), &statb) < 0) 12338032Speter { 12438032Speter syserr("cannot fstat"); 12590792Sgshapiro finis(false, true, EX_OSFILE); 12638032Speter } 12738032Speter 12838032Speter if (!S_ISREG(statb.st_mode)) 12938032Speter { 13038032Speter syserr("not a plain file"); 13190792Sgshapiro finis(false, true, EX_OSFILE); 13238032Speter } 13338032Speter 13438032Speter if (OpMode != MD_TEST && bitset(S_IWGRP|S_IWOTH, statb.st_mode)) 13538032Speter { 13638032Speter if (OpMode == MD_DAEMON || OpMode == MD_INITALIAS) 13790792Sgshapiro (void) sm_io_fprintf(smioerr, SM_TIME_DEFAULT, 13890792Sgshapiro "%s: WARNING: dangerous write permissions\n", 13990792Sgshapiro FileName); 14038032Speter if (LogLevel > 0) 14138032Speter sm_syslog(LOG_CRIT, NOQID, 14264562Sgshapiro "%s: WARNING: dangerous write permissions", 14364562Sgshapiro FileName); 14438032Speter } 14538032Speter 14690792Sgshapiro#if XLA 14738032Speter xla_zero(); 14864562Sgshapiro#endif /* XLA */ 14938032Speter 15038032Speter while ((bp = fgetfolded(buf, sizeof buf, cf)) != NULL) 15138032Speter { 15238032Speter if (bp[0] == '#') 15338032Speter { 15438032Speter if (bp != buf) 15590792Sgshapiro sm_free(bp); /* XXX */ 15638032Speter continue; 15738032Speter } 15838032Speter 15938032Speter /* do macro expansion mappings */ 16038032Speter translate_dollars(bp); 16138032Speter 16238032Speter /* interpret this line */ 16338032Speter errno = 0; 16438032Speter switch (bp[0]) 16538032Speter { 16638032Speter case '\0': 16738032Speter case '#': /* comment */ 16838032Speter break; 16938032Speter 17038032Speter case 'R': /* rewriting rule */ 17164562Sgshapiro if (ruleset < 0) 17264562Sgshapiro { 17364562Sgshapiro syserr("missing valid ruleset for \"%s\"", bp); 17464562Sgshapiro break; 17564562Sgshapiro } 17638032Speter for (p = &bp[1]; *p != '\0' && *p != '\t'; p++) 17738032Speter continue; 17838032Speter 17938032Speter if (*p == '\0') 18038032Speter { 18138032Speter syserr("invalid rewrite line \"%s\" (tab expected)", bp); 18238032Speter break; 18338032Speter } 18438032Speter 18538032Speter /* allocate space for the rule header */ 18638032Speter if (rwp == NULL) 18738032Speter { 18838032Speter RewriteRules[ruleset] = rwp = 18938032Speter (struct rewrite *) xalloc(sizeof *rwp); 19038032Speter } 19138032Speter else 19238032Speter { 19338032Speter rwp->r_next = (struct rewrite *) xalloc(sizeof *rwp); 19438032Speter rwp = rwp->r_next; 19538032Speter } 19638032Speter rwp->r_next = NULL; 19738032Speter 19838032Speter /* expand and save the LHS */ 19938032Speter *p = '\0'; 20038032Speter expand(&bp[1], exbuf, sizeof exbuf, e); 20138032Speter rwp->r_lhs = prescan(exbuf, '\t', pvpbuf, 20264562Sgshapiro sizeof pvpbuf, NULL, 20364562Sgshapiro ConfigLevel >= 9 ? TokTypeNoC : NULL); 20438032Speter nfuzzy = 0; 20538032Speter if (rwp->r_lhs != NULL) 20638032Speter { 20738032Speter register char **ap; 20838032Speter 20990792Sgshapiro rwp->r_lhs = copyplist(rwp->r_lhs, true, NULL); 21038032Speter 21138032Speter /* count the number of fuzzy matches in LHS */ 21238032Speter for (ap = rwp->r_lhs; *ap != NULL; ap++) 21338032Speter { 21438032Speter char *botch; 21538032Speter 21638032Speter botch = NULL; 21738032Speter switch (**ap & 0377) 21838032Speter { 21938032Speter case MATCHZANY: 22038032Speter case MATCHANY: 22138032Speter case MATCHONE: 22238032Speter case MATCHCLASS: 22338032Speter case MATCHNCLASS: 22438032Speter nfuzzy++; 22538032Speter break; 22638032Speter 22738032Speter case MATCHREPL: 22838032Speter botch = "$0-$9"; 22938032Speter break; 23038032Speter 23138032Speter case CANONUSER: 23238032Speter botch = "$:"; 23338032Speter break; 23438032Speter 23538032Speter case CALLSUBR: 23638032Speter botch = "$>"; 23738032Speter break; 23838032Speter 23938032Speter case CONDIF: 24038032Speter botch = "$?"; 24138032Speter break; 24238032Speter 24338032Speter case CONDFI: 24438032Speter botch = "$."; 24538032Speter break; 24638032Speter 24738032Speter case HOSTBEGIN: 24838032Speter botch = "$["; 24938032Speter break; 25038032Speter 25138032Speter case HOSTEND: 25238032Speter botch = "$]"; 25338032Speter break; 25438032Speter 25538032Speter case LOOKUPBEGIN: 25638032Speter botch = "$("; 25738032Speter break; 25838032Speter 25938032Speter case LOOKUPEND: 26038032Speter botch = "$)"; 26138032Speter break; 26238032Speter } 26338032Speter if (botch != NULL) 26438032Speter syserr("Inappropriate use of %s on LHS", 26538032Speter botch); 26638032Speter } 26764562Sgshapiro rwp->r_line = LineNumber; 26838032Speter } 26938032Speter else 27038032Speter { 27138032Speter syserr("R line: null LHS"); 27238032Speter rwp->r_lhs = null_list; 27338032Speter } 27482017Sgshapiro if (nfuzzy > MAXMATCH) 27582017Sgshapiro { 27682017Sgshapiro syserr("R line: too many wildcards"); 27782017Sgshapiro rwp->r_lhs = null_list; 27882017Sgshapiro } 27938032Speter 28038032Speter /* expand and save the RHS */ 28138032Speter while (*++p == '\t') 28238032Speter continue; 28338032Speter q = p; 28438032Speter while (*p != '\0' && *p != '\t') 28538032Speter p++; 28638032Speter *p = '\0'; 28738032Speter expand(q, exbuf, sizeof exbuf, e); 28838032Speter rwp->r_rhs = prescan(exbuf, '\t', pvpbuf, 28964562Sgshapiro sizeof pvpbuf, NULL, 29064562Sgshapiro ConfigLevel >= 9 ? TokTypeNoC : NULL); 29138032Speter if (rwp->r_rhs != NULL) 29238032Speter { 29338032Speter register char **ap; 29438032Speter 29590792Sgshapiro rwp->r_rhs = copyplist(rwp->r_rhs, true, NULL); 29638032Speter 29738032Speter /* check no out-of-bounds replacements */ 29838032Speter nfuzzy += '0'; 29938032Speter for (ap = rwp->r_rhs; *ap != NULL; ap++) 30038032Speter { 30138032Speter char *botch; 30238032Speter 30338032Speter botch = NULL; 30438032Speter switch (**ap & 0377) 30538032Speter { 30638032Speter case MATCHREPL: 30738032Speter if ((*ap)[1] <= '0' || (*ap)[1] > nfuzzy) 30838032Speter { 30938032Speter syserr("replacement $%c out of bounds", 31038032Speter (*ap)[1]); 31138032Speter } 31238032Speter break; 31338032Speter 31438032Speter case MATCHZANY: 31538032Speter botch = "$*"; 31638032Speter break; 31738032Speter 31838032Speter case MATCHANY: 31938032Speter botch = "$+"; 32038032Speter break; 32138032Speter 32238032Speter case MATCHONE: 32338032Speter botch = "$-"; 32438032Speter break; 32538032Speter 32638032Speter case MATCHCLASS: 32738032Speter botch = "$="; 32838032Speter break; 32938032Speter 33038032Speter case MATCHNCLASS: 33138032Speter botch = "$~"; 33238032Speter break; 33390792Sgshapiro 33490792Sgshapiro#if 0 33590792Sgshapiro/* 33690792Sgshapiro** This doesn't work yet as there are maps defined *after* the cf 33790792Sgshapiro** is read such as host, user, and alias. So for now, it's removed. 33890792Sgshapiro** When it comes back, the RELEASE_NOTES entry will be: 33990792Sgshapiro** Emit warnings for unknown maps when reading the .cf file. Based on 34090792Sgshapiro** patch from Robert Harker of Harker Systems. 34190792Sgshapiro*/ 34290792Sgshapiro 34390792Sgshapiro case LOOKUPBEGIN: 34490792Sgshapiro /* 34590792Sgshapiro ** Got a database lookup, 34690792Sgshapiro ** check if map is defined. 34790792Sgshapiro */ 34890792Sgshapiro 34990792Sgshapiro ep = *(ap + 1); 35090792Sgshapiro if ((*ep & 0377) != MACRODEXPAND && 35190792Sgshapiro stab(ep, ST_MAP, 35290792Sgshapiro ST_FIND) == NULL) 35390792Sgshapiro { 35490792Sgshapiro (void) sm_io_fprintf(smioout, 35590792Sgshapiro SM_TIME_DEFAULT, 35690792Sgshapiro "Warning: %s: line %d: map %s not found\n", 35790792Sgshapiro FileName, 35890792Sgshapiro LineNumber, 35990792Sgshapiro ep); 36090792Sgshapiro } 36190792Sgshapiro break; 36290792Sgshapiro#endif /* 0 */ 36338032Speter } 36438032Speter if (botch != NULL) 36538032Speter syserr("Inappropriate use of %s on RHS", 36638032Speter botch); 36738032Speter } 36838032Speter } 36938032Speter else 37038032Speter { 37138032Speter syserr("R line: null RHS"); 37238032Speter rwp->r_rhs = null_list; 37338032Speter } 37438032Speter break; 37538032Speter 37638032Speter case 'S': /* select rewriting set */ 37738032Speter expand(&bp[1], exbuf, sizeof exbuf, e); 37838032Speter ruleset = strtorwset(exbuf, NULL, ST_ENTER); 37938032Speter if (ruleset < 0) 38038032Speter break; 38164562Sgshapiro 38238032Speter rwp = RewriteRules[ruleset]; 38338032Speter if (rwp != NULL) 38438032Speter { 38564562Sgshapiro if (OpMode == MD_TEST) 38690792Sgshapiro (void) sm_io_fprintf(smioout, 38790792Sgshapiro SM_TIME_DEFAULT, 38890792Sgshapiro "WARNING: Ruleset %s has multiple definitions\n", 38990792Sgshapiro &bp[1]); 39064562Sgshapiro if (tTd(37, 1)) 39190792Sgshapiro sm_dprintf("WARNING: Ruleset %s has multiple definitions\n", 39290792Sgshapiro &bp[1]); 39338032Speter while (rwp->r_next != NULL) 39438032Speter rwp = rwp->r_next; 39538032Speter } 39638032Speter break; 39738032Speter 39838032Speter case 'D': /* macro definition */ 39990792Sgshapiro mid = macid_parse(&bp[1], &ep); 40071345Sgshapiro if (mid == 0) 40171345Sgshapiro break; 40238032Speter p = munchstring(ep, NULL, '\0'); 40390792Sgshapiro macdefine(&e->e_macro, A_TEMP, mid, p); 40438032Speter break; 40538032Speter 40638032Speter case 'H': /* required header line */ 40764562Sgshapiro (void) chompheader(&bp[1], CHHDR_DEF, NULL, e); 40838032Speter break; 40938032Speter 41038032Speter case 'C': /* word class */ 41138032Speter case 'T': /* trusted user (set class `t') */ 41238032Speter if (bp[0] == 'C') 41338032Speter { 41490792Sgshapiro mid = macid_parse(&bp[1], &ep); 41571345Sgshapiro if (mid == 0) 41671345Sgshapiro break; 41738032Speter expand(ep, exbuf, sizeof exbuf, e); 41838032Speter p = exbuf; 41938032Speter } 42038032Speter else 42138032Speter { 42238032Speter mid = 't'; 42338032Speter p = &bp[1]; 42438032Speter } 42538032Speter while (*p != '\0') 42638032Speter { 42738032Speter register char *wd; 42838032Speter char delim; 42938032Speter 43038032Speter while (*p != '\0' && isascii(*p) && isspace(*p)) 43138032Speter p++; 43238032Speter wd = p; 43338032Speter while (*p != '\0' && !(isascii(*p) && isspace(*p))) 43438032Speter p++; 43538032Speter delim = *p; 43638032Speter *p = '\0'; 43738032Speter if (wd[0] != '\0') 43838032Speter setclass(mid, wd); 43938032Speter *p = delim; 44038032Speter } 44138032Speter break; 44238032Speter 44338032Speter case 'F': /* word class from file */ 44490792Sgshapiro mid = macid_parse(&bp[1], &ep); 44571345Sgshapiro if (mid == 0) 44671345Sgshapiro break; 44738032Speter for (p = ep; isascii(*p) && isspace(*p); ) 44838032Speter p++; 44938032Speter if (p[0] == '-' && p[1] == 'o') 45038032Speter { 45190792Sgshapiro optional = true; 45290792Sgshapiro while (*p != '\0' && 45390792Sgshapiro !(isascii(*p) && isspace(*p))) 45438032Speter p++; 45538032Speter while (isascii(*p) && isspace(*p)) 45638032Speter p++; 45790792Sgshapiro file = p; 45838032Speter } 45938032Speter else 46090792Sgshapiro optional = false; 46164562Sgshapiro 46294334Sgshapiro /* check if [key]@map:spec */ 46394334Sgshapiro ismap = false; 46494334Sgshapiro if (!SM_IS_DIR_DELIM(*p) && 46594334Sgshapiro *p != '|' && 46694334Sgshapiro (q = strchr(p, '@')) != NULL) 46790792Sgshapiro { 46894334Sgshapiro q++; 46994334Sgshapiro 47094334Sgshapiro /* look for @LDAP or @map: in string */ 47194334Sgshapiro if (strcmp(q, "LDAP") == 0 || 47294334Sgshapiro (*q != ':' && 47394334Sgshapiro strchr(q, ':') != NULL)) 47494334Sgshapiro ismap = true; 47594334Sgshapiro } 47694334Sgshapiro 47794334Sgshapiro if (ismap) 47894334Sgshapiro { 47990792Sgshapiro /* use entire spec */ 48090792Sgshapiro file = p; 48190792Sgshapiro } 48290792Sgshapiro else 48390792Sgshapiro { 48490792Sgshapiro file = extrquotstr(p, &q, " ", &ok); 48590792Sgshapiro if (!ok) 48690792Sgshapiro { 48790792Sgshapiro syserr("illegal filename '%s'", p); 48890792Sgshapiro break; 48990792Sgshapiro } 49090792Sgshapiro } 49190792Sgshapiro 49294334Sgshapiro if (*file == '|' || ismap) 49338032Speter p = "%s"; 49438032Speter else 49538032Speter { 49664562Sgshapiro p = q; 49738032Speter if (*p == '\0') 49838032Speter p = "%s"; 49938032Speter else 50038032Speter { 50138032Speter *p = '\0'; 50238032Speter while (isascii(*++p) && isspace(*p)) 50338032Speter continue; 50438032Speter } 50538032Speter } 50694334Sgshapiro fileclass(mid, file, p, ismap, safe, optional); 50738032Speter break; 50838032Speter 50990792Sgshapiro#if XLA 51038032Speter case 'L': /* extended load average description */ 51138032Speter xla_init(&bp[1]); 51238032Speter break; 51364562Sgshapiro#endif /* XLA */ 51438032Speter 51538032Speter#if defined(SUN_EXTENSIONS) && defined(SUN_LOOKUP_MACRO) 51638032Speter case 'L': /* lookup macro */ 51738032Speter case 'G': /* lookup class */ 51838032Speter /* reserved for Sun -- NIS+ database lookup */ 51938032Speter if (VendorCode != VENDOR_SUN) 52038032Speter goto badline; 52138032Speter sun_lg_config_line(bp, e); 52238032Speter break; 52364562Sgshapiro#endif /* defined(SUN_EXTENSIONS) && defined(SUN_LOOKUP_MACRO) */ 52438032Speter 52538032Speter case 'M': /* define mailer */ 52638032Speter makemailer(&bp[1]); 52738032Speter break; 52838032Speter 52938032Speter case 'O': /* set option */ 53090792Sgshapiro setoption(bp[1], &bp[2], safe, false, e); 53138032Speter break; 53238032Speter 53338032Speter case 'P': /* set precedence */ 53438032Speter if (NumPriorities >= MAXPRIORITIES) 53538032Speter { 53638032Speter toomany('P', MAXPRIORITIES); 53738032Speter break; 53838032Speter } 53938032Speter for (p = &bp[1]; *p != '\0' && *p != '='; p++) 54038032Speter continue; 54138032Speter if (*p == '\0') 54238032Speter goto badline; 54338032Speter *p = '\0'; 54438032Speter Priorities[NumPriorities].pri_name = newstr(&bp[1]); 54538032Speter Priorities[NumPriorities].pri_val = atoi(++p); 54638032Speter NumPriorities++; 54738032Speter break; 54838032Speter 54990792Sgshapiro case 'Q': /* define queue */ 55090792Sgshapiro makequeue(&bp[1], true); 55190792Sgshapiro break; 55290792Sgshapiro 55338032Speter case 'V': /* configuration syntax version */ 55438032Speter for (p = &bp[1]; isascii(*p) && isspace(*p); p++) 55538032Speter continue; 55638032Speter if (!isascii(*p) || !isdigit(*p)) 55738032Speter { 55864562Sgshapiro syserr("invalid argument to V line: \"%.20s\"", 55938032Speter &bp[1]); 56038032Speter break; 56138032Speter } 56238032Speter ConfigLevel = strtol(p, &ep, 10); 56338032Speter 56438032Speter /* 56538032Speter ** Do heuristic tweaking for back compatibility. 56638032Speter */ 56738032Speter 56838032Speter if (ConfigLevel >= 5) 56938032Speter { 57038032Speter /* level 5 configs have short name in $w */ 57138032Speter p = macvalue('w', e); 57238032Speter if (p != NULL && (p = strchr(p, '.')) != NULL) 57390792Sgshapiro { 57438032Speter *p = '\0'; 57590792Sgshapiro macdefine(&e->e_macro, A_TEMP, 'w', 57690792Sgshapiro macvalue('w', e)); 57790792Sgshapiro } 57838032Speter } 57938032Speter if (ConfigLevel >= 6) 58038032Speter { 58190792Sgshapiro ColonOkInAddr = false; 58238032Speter } 58338032Speter 58438032Speter /* 58538032Speter ** Look for vendor code. 58638032Speter */ 58738032Speter 58838032Speter if (*ep++ == '/') 58938032Speter { 59038032Speter /* extract vendor code */ 59138032Speter for (p = ep; isascii(*p) && isalpha(*p); ) 59238032Speter p++; 59338032Speter *p = '\0'; 59438032Speter 59538032Speter if (!setvendor(ep)) 59638032Speter syserr("invalid V line vendor code: \"%s\"", 59738032Speter ep); 59838032Speter } 59938032Speter break; 60038032Speter 60138032Speter case 'K': 60238032Speter expand(&bp[1], exbuf, sizeof exbuf, e); 60338032Speter (void) makemapentry(exbuf); 60438032Speter break; 60538032Speter 60638032Speter case 'E': 60738032Speter p = strchr(bp, '='); 60838032Speter if (p != NULL) 60938032Speter *p++ = '\0'; 61038032Speter setuserenv(&bp[1], p); 61138032Speter break; 61238032Speter 61364562Sgshapiro case 'X': /* mail filter */ 61490792Sgshapiro#if MILTER 61564562Sgshapiro milter_setup(&bp[1]); 61690792Sgshapiro#else /* MILTER */ 61790792Sgshapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 61890792Sgshapiro "Warning: Filter usage ('X') requires Milter support (-DMILTER)\n"); 61990792Sgshapiro#endif /* MILTER */ 62064562Sgshapiro break; 62164562Sgshapiro 62238032Speter default: 62338032Speter badline: 62438032Speter syserr("unknown configuration line \"%s\"", bp); 62538032Speter } 62638032Speter if (bp != buf) 62790792Sgshapiro sm_free(bp); /* XXX */ 62838032Speter } 62990792Sgshapiro if (sm_io_error(cf)) 63038032Speter { 63138032Speter syserr("I/O read error"); 63290792Sgshapiro finis(false, true, EX_OSFILE); 63338032Speter } 63490792Sgshapiro (void) sm_io_close(cf, SM_TIME_DEFAULT); 63538032Speter FileName = NULL; 63638032Speter 63738032Speter /* initialize host maps from local service tables */ 63838032Speter inithostmaps(); 63938032Speter 64064562Sgshapiro /* initialize daemon (if not defined yet) */ 64164562Sgshapiro initdaemon(); 64264562Sgshapiro 64338032Speter /* determine if we need to do special name-server frotz */ 64438032Speter { 64538032Speter int nmaps; 64638032Speter char *maptype[MAXMAPSTACK]; 64738032Speter short mapreturn[MAXMAPACTIONS]; 64838032Speter 64938032Speter nmaps = switch_map_find("hosts", maptype, mapreturn); 65090792Sgshapiro UseNameServer = false; 65138032Speter if (nmaps > 0 && nmaps <= MAXMAPSTACK) 65238032Speter { 65338032Speter register int mapno; 65438032Speter 65590792Sgshapiro for (mapno = 0; mapno < nmaps && !UseNameServer; 65690792Sgshapiro mapno++) 65738032Speter { 65838032Speter if (strcmp(maptype[mapno], "dns") == 0) 65990792Sgshapiro UseNameServer = true; 66038032Speter } 66138032Speter } 66238032Speter } 66338032Speter} 66490792Sgshapiro/* 66538032Speter** TRANSLATE_DOLLARS -- convert $x into internal form 66638032Speter** 66738032Speter** Actually does all appropriate pre-processing of a config line 66838032Speter** to turn it into internal form. 66938032Speter** 67038032Speter** Parameters: 67138032Speter** bp -- the buffer to translate. 67238032Speter** 67338032Speter** Returns: 67438032Speter** None. The buffer is translated in place. Since the 67538032Speter** translations always make the buffer shorter, this is 67638032Speter** safe without a size parameter. 67738032Speter*/ 67838032Speter 67938032Spetervoid 68038032Spetertranslate_dollars(bp) 68138032Speter char *bp; 68238032Speter{ 68338032Speter register char *p; 68438032Speter auto char *ep; 68538032Speter 68638032Speter for (p = bp; *p != '\0'; p++) 68738032Speter { 68838032Speter if (*p == '#' && p > bp && ConfigLevel >= 3) 68938032Speter { 69038032Speter register char *e; 69138032Speter 69238032Speter switch (*--p & 0377) 69338032Speter { 69438032Speter case MACROEXPAND: 69538032Speter /* it's from $# -- let it go through */ 69638032Speter p++; 69738032Speter break; 69838032Speter 69938032Speter case '\\': 70038032Speter /* it's backslash escaped */ 70190792Sgshapiro (void) sm_strlcpy(p, p + 1, strlen(p)); 70238032Speter break; 70338032Speter 70438032Speter default: 70564562Sgshapiro /* delete leading white space */ 70638032Speter while (isascii(*p) && isspace(*p) && 70738032Speter *p != '\n' && p > bp) 70838032Speter p--; 70938032Speter if ((e = strchr(++p, '\n')) != NULL) 71090792Sgshapiro (void) sm_strlcpy(p, e, strlen(p)); 71138032Speter else 71238032Speter *p-- = '\0'; 71338032Speter break; 71438032Speter } 71538032Speter continue; 71638032Speter } 71738032Speter 71838032Speter if (*p != '$' || p[1] == '\0') 71938032Speter continue; 72038032Speter 72138032Speter if (p[1] == '$') 72238032Speter { 72338032Speter /* actual dollar sign.... */ 72490792Sgshapiro (void) sm_strlcpy(p, p + 1, strlen(p)); 72538032Speter continue; 72638032Speter } 72738032Speter 72838032Speter /* convert to macro expansion character */ 72938032Speter *p++ = MACROEXPAND; 73038032Speter 73138032Speter /* special handling for $=, $~, $&, and $? */ 73238032Speter if (*p == '=' || *p == '~' || *p == '&' || *p == '?') 73338032Speter p++; 73438032Speter 73538032Speter /* convert macro name to code */ 73690792Sgshapiro *p = macid_parse(p, &ep); 73764562Sgshapiro if (ep != p + 1) 73890792Sgshapiro (void) sm_strlcpy(p + 1, ep, strlen(p + 1)); 73938032Speter } 74038032Speter 74138032Speter /* strip trailing white space from the line */ 74238032Speter while (--p > bp && isascii(*p) && isspace(*p)) 74338032Speter *p = '\0'; 74438032Speter} 74590792Sgshapiro/* 74638032Speter** TOOMANY -- signal too many of some option 74738032Speter** 74838032Speter** Parameters: 74938032Speter** id -- the id of the error line 75038032Speter** maxcnt -- the maximum possible values 75138032Speter** 75238032Speter** Returns: 75338032Speter** none. 75438032Speter** 75538032Speter** Side Effects: 75638032Speter** gives a syserr. 75738032Speter*/ 75838032Speter 75964562Sgshapirostatic void 76038032Spetertoomany(id, maxcnt) 76138032Speter int id; 76238032Speter int maxcnt; 76338032Speter{ 76438032Speter syserr("too many %c lines, %d max", id, maxcnt); 76538032Speter} 76690792Sgshapiro/* 76738032Speter** FILECLASS -- read members of a class from a file 76838032Speter** 76938032Speter** Parameters: 77038032Speter** class -- class to define. 77138032Speter** filename -- name of file to read. 77238032Speter** fmt -- scanf string to use for match. 77394334Sgshapiro** ismap -- if set, this is a map lookup. 77438032Speter** safe -- if set, this is a safe read. 77538032Speter** optional -- if set, it is not an error for the file to 77638032Speter** not exist. 77738032Speter** 77838032Speter** Returns: 77938032Speter** none 78038032Speter** 78138032Speter** Side Effects: 78238032Speter** puts all lines in filename that match a scanf into 78338032Speter** the named class. 78438032Speter*/ 78538032Speter 78690792Sgshapiro/* 78790792Sgshapiro** Break up the match into words and add to class. 78890792Sgshapiro*/ 78990792Sgshapiro 79064562Sgshapirostatic void 79190792Sgshapiroparse_class_words(class, line) 79290792Sgshapiro int class; 79390792Sgshapiro char *line; 79490792Sgshapiro{ 79590792Sgshapiro while (line != NULL && *line != '\0') 79690792Sgshapiro { 79790792Sgshapiro register char *q; 79890792Sgshapiro 79990792Sgshapiro /* strip leading spaces */ 80090792Sgshapiro while (isascii(*line) && isspace(*line)) 80190792Sgshapiro line++; 80290792Sgshapiro if (*line == '\0') 80390792Sgshapiro break; 80490792Sgshapiro 80590792Sgshapiro /* find the end of the word */ 80690792Sgshapiro q = line; 80790792Sgshapiro while (*line != '\0' && !(isascii(*line) && isspace(*line))) 80890792Sgshapiro line++; 80990792Sgshapiro if (*line != '\0') 81090792Sgshapiro *line++ = '\0'; 81190792Sgshapiro 81290792Sgshapiro /* enter the word in the symbol table */ 81390792Sgshapiro setclass(class, q); 81490792Sgshapiro } 81590792Sgshapiro} 81690792Sgshapiro 81790792Sgshapirostatic void 81894334Sgshapirofileclass(class, filename, fmt, ismap, safe, optional) 81938032Speter int class; 82038032Speter char *filename; 82138032Speter char *fmt; 82294334Sgshapiro bool ismap; 82338032Speter bool safe; 82438032Speter bool optional; 82538032Speter{ 82690792Sgshapiro SM_FILE_T *f; 82764562Sgshapiro long sff; 82838032Speter pid_t pid; 82938032Speter register char *p; 83038032Speter char buf[MAXLINE]; 83138032Speter 83238032Speter if (tTd(37, 2)) 83390792Sgshapiro sm_dprintf("fileclass(%s, fmt=%s)\n", filename, fmt); 83438032Speter 83590792Sgshapiro if (*filename == '\0') 83638032Speter { 83790792Sgshapiro syserr("fileclass: missing file name"); 83890792Sgshapiro return; 83990792Sgshapiro } 84094334Sgshapiro else if (ismap) 84190792Sgshapiro { 84290792Sgshapiro int status = 0; 84390792Sgshapiro char *key; 84490792Sgshapiro char *mn; 84590792Sgshapiro char *cl, *spec; 84690792Sgshapiro STAB *mapclass; 84790792Sgshapiro MAP map; 84890792Sgshapiro 84990792Sgshapiro mn = newstr(macname(class)); 85090792Sgshapiro 85190792Sgshapiro key = filename; 85290792Sgshapiro 85394334Sgshapiro /* skip past key */ 85494334Sgshapiro if ((p = strchr(filename, '@')) == NULL) 85594334Sgshapiro { 85694334Sgshapiro /* should not happen */ 85794334Sgshapiro syserr("fileclass: bogus map specification"); 85894334Sgshapiro sm_free(mn); 85994334Sgshapiro return; 86094334Sgshapiro } 86194334Sgshapiro 86290792Sgshapiro /* skip past '@' */ 86390792Sgshapiro *p++ = '\0'; 86490792Sgshapiro cl = p; 86590792Sgshapiro 86690792Sgshapiro if (strcmp(cl, "LDAP") == 0) 86790792Sgshapiro { 86890792Sgshapiro int n; 86990792Sgshapiro char *lc; 87090792Sgshapiro char jbuf[MAXHOSTNAMELEN]; 87190792Sgshapiro char lcbuf[MAXLINE]; 87290792Sgshapiro 87390792Sgshapiro /* Get $j */ 87490792Sgshapiro expand("\201j", jbuf, sizeof jbuf, &BlankEnvelope); 87590792Sgshapiro if (jbuf[0] == '\0') 87690792Sgshapiro { 87790792Sgshapiro (void) sm_strlcpy(jbuf, "localhost", 87890792Sgshapiro sizeof jbuf); 87990792Sgshapiro } 88090792Sgshapiro 88190792Sgshapiro /* impose the default schema */ 88290792Sgshapiro lc = macvalue(macid("{sendmailMTACluster}"), CurEnv); 88390792Sgshapiro if (lc == NULL) 88490792Sgshapiro lc = ""; 88590792Sgshapiro else 88690792Sgshapiro { 88790792Sgshapiro expand(lc, lcbuf, sizeof lcbuf, CurEnv); 88890792Sgshapiro lc = lcbuf; 88990792Sgshapiro } 89090792Sgshapiro 89190792Sgshapiro cl = "ldap"; 89290792Sgshapiro n = sm_snprintf(buf, sizeof buf, 89390792Sgshapiro "-k (&(objectClass=sendmailMTAClass)(sendmailMTAClassName=%s)(|(sendmailMTACluster=%s)(sendmailMTAHost=%s))) -v sendmailMTAClassValue", 89490792Sgshapiro mn, lc, jbuf); 89590792Sgshapiro if (n >= sizeof buf) 89690792Sgshapiro { 89790792Sgshapiro syserr("fileclass: F{%s}: Default LDAP string too long", 89890792Sgshapiro mn); 89990792Sgshapiro sm_free(mn); 90090792Sgshapiro return; 90190792Sgshapiro } 90290792Sgshapiro spec = buf; 90390792Sgshapiro } 90490792Sgshapiro else 90590792Sgshapiro { 90690792Sgshapiro if ((spec = strchr(cl, ':')) == NULL) 90790792Sgshapiro { 90890792Sgshapiro syserr("fileclass: F{%s}: missing map class", 90990792Sgshapiro mn); 91090792Sgshapiro sm_free(mn); 91190792Sgshapiro return; 91290792Sgshapiro } 91390792Sgshapiro *spec++ ='\0'; 91490792Sgshapiro } 91590792Sgshapiro 91690792Sgshapiro /* set up map structure */ 91790792Sgshapiro mapclass = stab(cl, ST_MAPCLASS, ST_FIND); 91890792Sgshapiro if (mapclass == NULL) 91990792Sgshapiro { 92090792Sgshapiro syserr("fileclass: F{%s}: class %s not available", 92190792Sgshapiro mn, cl); 92290792Sgshapiro sm_free(mn); 92390792Sgshapiro return; 92490792Sgshapiro } 92590792Sgshapiro memset(&map, '\0', sizeof map); 92690792Sgshapiro map.map_class = &mapclass->s_mapclass; 92790792Sgshapiro map.map_mname = mn; 92890792Sgshapiro map.map_mflags |= MF_FILECLASS; 92990792Sgshapiro 93094334Sgshapiro if (tTd(37, 5)) 93194334Sgshapiro sm_dprintf("fileclass: F{%s}: map class %s, key %s, spec %s\n", 93294334Sgshapiro mn, cl, key, spec); 93394334Sgshapiro 93494334Sgshapiro 93590792Sgshapiro /* parse map spec */ 93690792Sgshapiro if (!map.map_class->map_parse(&map, spec)) 93790792Sgshapiro { 93890792Sgshapiro /* map_parse() showed the error already */ 93990792Sgshapiro sm_free(mn); 94090792Sgshapiro return; 94190792Sgshapiro } 94290792Sgshapiro map.map_mflags |= MF_VALID; 94390792Sgshapiro 94490792Sgshapiro /* open map */ 94590792Sgshapiro if (map.map_class->map_open(&map, O_RDONLY)) 94690792Sgshapiro { 94790792Sgshapiro map.map_mflags |= MF_OPEN; 94890792Sgshapiro map.map_pid = getpid(); 94990792Sgshapiro } 95090792Sgshapiro else 95190792Sgshapiro { 95290792Sgshapiro if (!optional && 95390792Sgshapiro !bitset(MF_OPTIONAL, map.map_mflags)) 95490792Sgshapiro syserr("fileclass: F{%s}: map open failed", 95590792Sgshapiro mn); 95690792Sgshapiro sm_free(mn); 95790792Sgshapiro return; 95890792Sgshapiro } 95990792Sgshapiro 96090792Sgshapiro /* lookup */ 96190792Sgshapiro p = (*map.map_class->map_lookup)(&map, key, NULL, &status); 96290792Sgshapiro if (status != EX_OK && status != EX_NOTFOUND) 96390792Sgshapiro { 96490792Sgshapiro if (!optional) 96590792Sgshapiro syserr("fileclass: F{%s}: map lookup failed", 96690792Sgshapiro mn); 96790792Sgshapiro p = NULL; 96890792Sgshapiro } 96990792Sgshapiro 97090792Sgshapiro /* use the results */ 97190792Sgshapiro if (p != NULL) 97290792Sgshapiro parse_class_words(class, p); 97390792Sgshapiro 97490792Sgshapiro /* close map */ 97590792Sgshapiro map.map_mflags |= MF_CLOSING; 97690792Sgshapiro map.map_class->map_close(&map); 97790792Sgshapiro map.map_mflags &= ~(MF_OPEN|MF_WRITABLE|MF_CLOSING); 97890792Sgshapiro sm_free(mn); 97990792Sgshapiro return; 98090792Sgshapiro } 98190792Sgshapiro else if (filename[0] == '|') 98290792Sgshapiro { 98338032Speter auto int fd; 98438032Speter int i; 98538032Speter char *argv[MAXPV + 1]; 98638032Speter 98738032Speter i = 0; 98890792Sgshapiro for (p = strtok(&filename[1], " \t"); 98990792Sgshapiro p != NULL && i < MAXPV; 99090792Sgshapiro p = strtok(NULL, " \t")) 99138032Speter argv[i++] = p; 99238032Speter argv[i] = NULL; 99338032Speter pid = prog_open(argv, &fd, CurEnv); 99438032Speter if (pid < 0) 99538032Speter f = NULL; 99638032Speter else 99790792Sgshapiro f = sm_io_open(SmFtStdiofd, SM_TIME_DEFAULT, 99890792Sgshapiro (void *) &fd, SM_IO_RDONLY, NULL); 99938032Speter } 100038032Speter else 100138032Speter { 100238032Speter pid = -1; 100338032Speter sff = SFF_REGONLY; 100464562Sgshapiro if (!bitnset(DBS_CLASSFILEINUNSAFEDIRPATH, DontBlameSendmail)) 100538032Speter sff |= SFF_SAFEDIRPATH; 100664562Sgshapiro if (!bitnset(DBS_LINKEDCLASSFILEINWRITABLEDIR, 100764562Sgshapiro DontBlameSendmail)) 100838032Speter sff |= SFF_NOWLINK; 100938032Speter if (safe) 101038032Speter sff |= SFF_OPENASROOT; 101190792Sgshapiro else if (RealUid == 0) 101290792Sgshapiro sff |= SFF_ROOTOK; 101338032Speter if (DontLockReadFiles) 101438032Speter sff |= SFF_NOLOCK; 101538032Speter f = safefopen(filename, O_RDONLY, 0, sff); 101638032Speter } 101738032Speter if (f == NULL) 101838032Speter { 101938032Speter if (!optional) 102064562Sgshapiro syserr("fileclass: cannot open '%s'", filename); 102138032Speter return; 102238032Speter } 102338032Speter 102490792Sgshapiro while (sm_io_fgets(f, SM_TIME_DEFAULT, buf, sizeof buf) != NULL) 102538032Speter { 102664562Sgshapiro#if SCANF 102738032Speter char wordbuf[MAXLINE + 1]; 102864562Sgshapiro#endif /* SCANF */ 102938032Speter 103038032Speter if (buf[0] == '#') 103138032Speter continue; 103264562Sgshapiro#if SCANF 103390792Sgshapiro if (sm_io_sscanf(buf, fmt, wordbuf) != 1) 103438032Speter continue; 103538032Speter p = wordbuf; 103664562Sgshapiro#else /* SCANF */ 103738032Speter p = buf; 103864562Sgshapiro#endif /* SCANF */ 103938032Speter 104090792Sgshapiro parse_class_words(class, p); 104190792Sgshapiro 104238032Speter /* 104390792Sgshapiro ** If anything else is added here, 104490792Sgshapiro ** check if the '@' map case above 104590792Sgshapiro ** needs the code as well. 104638032Speter */ 104738032Speter } 104838032Speter 104990792Sgshapiro (void) sm_io_close(f, SM_TIME_DEFAULT); 105038032Speter if (pid > 0) 105138032Speter (void) waitfor(pid); 105238032Speter} 105390792Sgshapiro/* 105438032Speter** MAKEMAILER -- define a new mailer. 105538032Speter** 105638032Speter** Parameters: 105738032Speter** line -- description of mailer. This is in labeled 105838032Speter** fields. The fields are: 105938032Speter** A -- the argv for this mailer 106038032Speter** C -- the character set for MIME conversions 106138032Speter** D -- the directory to run in 106238032Speter** E -- the eol string 106338032Speter** F -- the flags associated with the mailer 106438032Speter** L -- the maximum line length 106538032Speter** M -- the maximum message size 106638032Speter** N -- the niceness at which to run 106738032Speter** P -- the path to the mailer 106890792Sgshapiro** Q -- the queue group for the mailer 106938032Speter** R -- the recipient rewriting set 107038032Speter** S -- the sender rewriting set 107138032Speter** T -- the mailer type (for DSNs) 107238032Speter** U -- the uid to run as 107364562Sgshapiro** W -- the time to wait at the end 107473188Sgshapiro** m -- maximum messages per connection 107590792Sgshapiro** r -- maximum number of recipients per message 107673188Sgshapiro** / -- new root directory 107738032Speter** The first word is the canonical name of the mailer. 107838032Speter** 107938032Speter** Returns: 108038032Speter** none. 108138032Speter** 108238032Speter** Side Effects: 108338032Speter** enters the mailer into the mailer table. 108438032Speter*/ 108538032Speter 108638032Spetervoid 108738032Spetermakemailer(line) 108838032Speter char *line; 108938032Speter{ 109038032Speter register char *p; 109138032Speter register struct mailer *m; 109238032Speter register STAB *s; 109338032Speter int i; 109438032Speter char fcode; 109538032Speter auto char *endp; 109690792Sgshapiro static int nextmailer = 0; /* "free" index into Mailer struct */ 109738032Speter 109838032Speter /* allocate a mailer and set up defaults */ 109938032Speter m = (struct mailer *) xalloc(sizeof *m); 110064562Sgshapiro memset((char *) m, '\0', sizeof *m); 110190792Sgshapiro errno = 0; /* avoid bogus error text */ 110238032Speter 110338032Speter /* collect the mailer name */ 110490792Sgshapiro for (p = line; 110590792Sgshapiro *p != '\0' && *p != ',' && !(isascii(*p) && isspace(*p)); 110690792Sgshapiro p++) 110738032Speter continue; 110838032Speter if (*p != '\0') 110938032Speter *p++ = '\0'; 111038032Speter if (line[0] == '\0') 111171345Sgshapiro { 111238032Speter syserr("name required for mailer"); 111371345Sgshapiro return; 111471345Sgshapiro } 111538032Speter m->m_name = newstr(line); 111694334Sgshapiro m->m_qgrp = NOQGRP; 111738032Speter 111838032Speter /* now scan through and assign info from the fields */ 111938032Speter while (*p != '\0') 112038032Speter { 112138032Speter auto char *delimptr; 112238032Speter 112390792Sgshapiro while (*p != '\0' && 112490792Sgshapiro (*p == ',' || (isascii(*p) && isspace(*p)))) 112538032Speter p++; 112638032Speter 112738032Speter /* p now points to field code */ 112838032Speter fcode = *p; 112938032Speter while (*p != '\0' && *p != '=' && *p != ',') 113038032Speter p++; 113138032Speter if (*p++ != '=') 113238032Speter { 113338032Speter syserr("mailer %s: `=' expected", m->m_name); 113438032Speter return; 113538032Speter } 113638032Speter while (isascii(*p) && isspace(*p)) 113738032Speter p++; 113838032Speter 113938032Speter /* p now points to the field body */ 114038032Speter p = munchstring(p, &delimptr, ','); 114138032Speter 114238032Speter /* install the field into the mailer struct */ 114338032Speter switch (fcode) 114438032Speter { 114538032Speter case 'P': /* pathname */ 114690792Sgshapiro if (*p != '\0') /* error is issued below */ 114771345Sgshapiro m->m_mailer = newstr(p); 114838032Speter break; 114938032Speter 115038032Speter case 'F': /* flags */ 115138032Speter for (; *p != '\0'; p++) 115290792Sgshapiro { 115338032Speter if (!(isascii(*p) && isspace(*p))) 115490792Sgshapiro { 115590792Sgshapiro#if _FFR_DEPRECATE_MAILER_FLAG_I 115690792Sgshapiro if (*p == M_INTERNAL) 115790792Sgshapiro sm_syslog(LOG_WARNING, NOQID, 115890792Sgshapiro "WARNING: mailer=%s, flag=%c deprecated", 115990792Sgshapiro m->m_name, *p); 116090792Sgshapiro#endif /* _FFR_DEPRECATE_MAILER_FLAG_I */ 116171345Sgshapiro setbitn(bitidx(*p), m->m_flags); 116290792Sgshapiro } 116390792Sgshapiro } 116438032Speter break; 116538032Speter 116638032Speter case 'S': /* sender rewriting ruleset */ 116738032Speter case 'R': /* recipient rewriting ruleset */ 116838032Speter i = strtorwset(p, &endp, ST_ENTER); 116938032Speter if (i < 0) 117038032Speter return; 117138032Speter if (fcode == 'S') 117238032Speter m->m_sh_rwset = m->m_se_rwset = i; 117338032Speter else 117438032Speter m->m_rh_rwset = m->m_re_rwset = i; 117538032Speter 117638032Speter p = endp; 117738032Speter if (*p++ == '/') 117838032Speter { 117938032Speter i = strtorwset(p, NULL, ST_ENTER); 118038032Speter if (i < 0) 118138032Speter return; 118238032Speter if (fcode == 'S') 118338032Speter m->m_sh_rwset = i; 118438032Speter else 118538032Speter m->m_rh_rwset = i; 118638032Speter } 118738032Speter break; 118838032Speter 118938032Speter case 'E': /* end of line string */ 119038032Speter if (*p == '\0') 119138032Speter syserr("mailer %s: null end-of-line string", 119238032Speter m->m_name); 119371345Sgshapiro else 119471345Sgshapiro m->m_eol = newstr(p); 119538032Speter break; 119638032Speter 119738032Speter case 'A': /* argument vector */ 119890792Sgshapiro if (*p != '\0') /* error is issued below */ 119971345Sgshapiro m->m_argv = makeargv(p); 120038032Speter break; 120138032Speter 120238032Speter case 'M': /* maximum message size */ 120338032Speter m->m_maxsize = atol(p); 120438032Speter break; 120538032Speter 120664562Sgshapiro case 'm': /* maximum messages per connection */ 120764562Sgshapiro m->m_maxdeliveries = atoi(p); 120864562Sgshapiro break; 120964562Sgshapiro 121064562Sgshapiro case 'r': /* max recipient per envelope */ 121164562Sgshapiro m->m_maxrcpt = atoi(p); 121264562Sgshapiro break; 121364562Sgshapiro 121438032Speter case 'L': /* maximum line length */ 121538032Speter m->m_linelimit = atoi(p); 121638032Speter if (m->m_linelimit < 0) 121738032Speter m->m_linelimit = 0; 121838032Speter break; 121938032Speter 122038032Speter case 'N': /* run niceness */ 122138032Speter m->m_nice = atoi(p); 122238032Speter break; 122338032Speter 122438032Speter case 'D': /* working directory */ 122538032Speter if (*p == '\0') 122638032Speter syserr("mailer %s: null working directory", 122738032Speter m->m_name); 122871345Sgshapiro else 122971345Sgshapiro m->m_execdir = newstr(p); 123038032Speter break; 123138032Speter 123238032Speter case 'C': /* default charset */ 123338032Speter if (*p == '\0') 123438032Speter syserr("mailer %s: null charset", m->m_name); 123571345Sgshapiro else 123671345Sgshapiro m->m_defcharset = newstr(p); 123738032Speter break; 123838032Speter 123990792Sgshapiro case 'Q': /* queue for this mailer */ 124090792Sgshapiro if (*p == '\0') 124190792Sgshapiro { 124290792Sgshapiro syserr("mailer %s: null queue", m->m_name); 124390792Sgshapiro break; 124490792Sgshapiro } 124590792Sgshapiro s = stab(p, ST_QUEUE, ST_FIND); 124690792Sgshapiro if (s == NULL) 124790792Sgshapiro syserr("mailer %s: unknown queue %s", 124890792Sgshapiro m->m_name, p); 124990792Sgshapiro else 125090792Sgshapiro m->m_qgrp = s->s_quegrp->qg_index; 125190792Sgshapiro break; 125290792Sgshapiro 125338032Speter case 'T': /* MTA-Name/Address/Diagnostic types */ 125438032Speter /* extract MTA name type; default to "dns" */ 125538032Speter m->m_mtatype = newstr(p); 125638032Speter p = strchr(m->m_mtatype, '/'); 125738032Speter if (p != NULL) 125838032Speter { 125938032Speter *p++ = '\0'; 126038032Speter if (*p == '\0') 126138032Speter p = NULL; 126238032Speter } 126338032Speter if (*m->m_mtatype == '\0') 126438032Speter m->m_mtatype = "dns"; 126538032Speter 126638032Speter /* extract address type; default to "rfc822" */ 126738032Speter m->m_addrtype = p; 126838032Speter if (p != NULL) 126938032Speter p = strchr(p, '/'); 127038032Speter if (p != NULL) 127138032Speter { 127238032Speter *p++ = '\0'; 127338032Speter if (*p == '\0') 127438032Speter p = NULL; 127538032Speter } 127638032Speter if (m->m_addrtype == NULL || *m->m_addrtype == '\0') 127738032Speter m->m_addrtype = "rfc822"; 127838032Speter 127938032Speter /* extract diagnostic type; default to "smtp" */ 128038032Speter m->m_diagtype = p; 128138032Speter if (m->m_diagtype == NULL || *m->m_diagtype == '\0') 128238032Speter m->m_diagtype = "smtp"; 128338032Speter break; 128438032Speter 128538032Speter case 'U': /* user id */ 128638032Speter if (isascii(*p) && !isdigit(*p)) 128738032Speter { 128838032Speter char *q = p; 128938032Speter struct passwd *pw; 129038032Speter 129138032Speter while (*p != '\0' && isascii(*p) && 129238032Speter (isalnum(*p) || strchr("-_", *p) != NULL)) 129338032Speter p++; 129438032Speter while (isascii(*p) && isspace(*p)) 129538032Speter *p++ = '\0'; 129638032Speter if (*p != '\0') 129738032Speter *p++ = '\0'; 129838032Speter if (*q == '\0') 129971345Sgshapiro { 130038032Speter syserr("mailer %s: null user name", 130138032Speter m->m_name); 130271345Sgshapiro break; 130371345Sgshapiro } 130438032Speter pw = sm_getpwnam(q); 130538032Speter if (pw == NULL) 130671345Sgshapiro { 130738032Speter syserr("readcf: mailer U= flag: unknown user %s", q); 130871345Sgshapiro break; 130971345Sgshapiro } 131038032Speter else 131138032Speter { 131238032Speter m->m_uid = pw->pw_uid; 131338032Speter m->m_gid = pw->pw_gid; 131438032Speter } 131538032Speter } 131638032Speter else 131738032Speter { 131838032Speter auto char *q; 131938032Speter 132038032Speter m->m_uid = strtol(p, &q, 0); 132138032Speter p = q; 132238032Speter while (isascii(*p) && isspace(*p)) 132338032Speter p++; 132438032Speter if (*p != '\0') 132538032Speter p++; 132638032Speter } 132738032Speter while (isascii(*p) && isspace(*p)) 132838032Speter p++; 132938032Speter if (*p == '\0') 133038032Speter break; 133138032Speter if (isascii(*p) && !isdigit(*p)) 133238032Speter { 133338032Speter char *q = p; 133438032Speter struct group *gr; 133538032Speter 133638032Speter while (isascii(*p) && isalnum(*p)) 133738032Speter p++; 133838032Speter *p++ = '\0'; 133938032Speter if (*q == '\0') 134071345Sgshapiro { 134138032Speter syserr("mailer %s: null group name", 134238032Speter m->m_name); 134371345Sgshapiro break; 134471345Sgshapiro } 134538032Speter gr = getgrnam(q); 134638032Speter if (gr == NULL) 134771345Sgshapiro { 134838032Speter syserr("readcf: mailer U= flag: unknown group %s", q); 134971345Sgshapiro break; 135071345Sgshapiro } 135138032Speter else 135238032Speter m->m_gid = gr->gr_gid; 135338032Speter } 135438032Speter else 135538032Speter { 135638032Speter m->m_gid = strtol(p, NULL, 0); 135738032Speter } 135838032Speter break; 135964562Sgshapiro 136064562Sgshapiro case 'W': /* wait timeout */ 136164562Sgshapiro m->m_wait = convtime(p, 's'); 136264562Sgshapiro break; 136364562Sgshapiro 136464562Sgshapiro case '/': /* new root directory */ 136564562Sgshapiro if (*p == '\0') 136664562Sgshapiro syserr("mailer %s: null root directory", 136764562Sgshapiro m->m_name); 136864562Sgshapiro else 136964562Sgshapiro m->m_rootdir = newstr(p); 137064562Sgshapiro break; 137164562Sgshapiro 137264562Sgshapiro default: 137364562Sgshapiro syserr("M%s: unknown mailer equate %c=", 137464562Sgshapiro m->m_name, fcode); 137564562Sgshapiro break; 137638032Speter } 137738032Speter 137838032Speter p = delimptr; 137938032Speter } 138038032Speter 138190792Sgshapiro#if !HASRRESVPORT 138290792Sgshapiro if (bitnset(M_SECURE_PORT, m->m_flags)) 138390792Sgshapiro { 138490792Sgshapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 138590792Sgshapiro "M%s: Warning: F=%c set on system that doesn't support rresvport()\n", 138690792Sgshapiro m->m_name, M_SECURE_PORT); 138790792Sgshapiro } 138890792Sgshapiro#endif /* !HASRRESVPORT */ 138990792Sgshapiro 139090792Sgshapiro#if !HASNICE 139190792Sgshapiro if (m->m_nice != 0) 139290792Sgshapiro { 139390792Sgshapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 139490792Sgshapiro "M%s: Warning: N= set on system that doesn't support nice()\n", 139590792Sgshapiro m->m_name); 139690792Sgshapiro } 139790792Sgshapiro#endif /* !HASNICE */ 139890792Sgshapiro 139938032Speter /* do some rationality checking */ 140038032Speter if (m->m_argv == NULL) 140138032Speter { 140238032Speter syserr("M%s: A= argument required", m->m_name); 140338032Speter return; 140438032Speter } 140538032Speter if (m->m_mailer == NULL) 140638032Speter { 140738032Speter syserr("M%s: P= argument required", m->m_name); 140838032Speter return; 140938032Speter } 141038032Speter 141190792Sgshapiro if (nextmailer >= MAXMAILERS) 141238032Speter { 141338032Speter syserr("too many mailers defined (%d max)", MAXMAILERS); 141438032Speter return; 141538032Speter } 141638032Speter 141764562Sgshapiro if (m->m_maxrcpt <= 0) 141864562Sgshapiro m->m_maxrcpt = DEFAULT_MAX_RCPT; 141964562Sgshapiro 142038032Speter /* do some heuristic cleanup for back compatibility */ 142138032Speter if (bitnset(M_LIMITS, m->m_flags)) 142238032Speter { 142338032Speter if (m->m_linelimit == 0) 142438032Speter m->m_linelimit = SMTPLINELIM; 142538032Speter if (ConfigLevel < 2) 142638032Speter setbitn(M_7BITS, m->m_flags); 142738032Speter } 142838032Speter 142964562Sgshapiro if (strcmp(m->m_mailer, "[TCP]") == 0) 143038032Speter { 143190792Sgshapiro syserr("M%s: P=[TCP] must be replaced by P=[IPC]", m->m_name); 143271345Sgshapiro return; 143338032Speter } 143438032Speter 143590792Sgshapiro if (strcmp(m->m_mailer, "[IPC]") == 0) 143638032Speter { 143764562Sgshapiro /* Use the second argument for host or path to socket */ 143864562Sgshapiro if (m->m_argv[0] == NULL || m->m_argv[1] == NULL || 143964562Sgshapiro m->m_argv[1][0] == '\0') 144064562Sgshapiro { 144164562Sgshapiro syserr("M%s: too few parameters for %s mailer", 144264562Sgshapiro m->m_name, m->m_mailer); 144371345Sgshapiro return; 144464562Sgshapiro } 144566494Sgshapiro if (strcmp(m->m_argv[0], "TCP") != 0 144664562Sgshapiro#if NETUNIX 144766494Sgshapiro && strcmp(m->m_argv[0], "FILE") != 0 144864562Sgshapiro#endif /* NETUNIX */ 144964562Sgshapiro ) 145064562Sgshapiro { 145190792Sgshapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 145290792Sgshapiro "M%s: Warning: first argument in %s mailer must be %s\n", 145390792Sgshapiro m->m_name, m->m_mailer, 145464562Sgshapiro#if NETUNIX 145590792Sgshapiro "TCP or FILE" 145664562Sgshapiro#else /* NETUNIX */ 145790792Sgshapiro "TCP" 145864562Sgshapiro#endif /* NETUNIX */ 145990792Sgshapiro ); 146064562Sgshapiro } 146190792Sgshapiro if (m->m_mtatype == NULL) 146290792Sgshapiro m->m_mtatype = "dns"; 146390792Sgshapiro if (m->m_addrtype == NULL) 146490792Sgshapiro m->m_addrtype = "rfc822"; 146590792Sgshapiro if (m->m_diagtype == NULL) 146690792Sgshapiro { 146790792Sgshapiro if (m->m_argv[0] != NULL && 146890792Sgshapiro strcmp(m->m_argv[0], "FILE") == 0) 146990792Sgshapiro m->m_diagtype = "x-unix"; 147090792Sgshapiro else 147190792Sgshapiro m->m_diagtype = "smtp"; 147290792Sgshapiro } 147364562Sgshapiro } 147464562Sgshapiro else if (strcmp(m->m_mailer, "[FILE]") == 0) 147564562Sgshapiro { 147638032Speter /* Use the second argument for filename */ 147738032Speter if (m->m_argv[0] == NULL || m->m_argv[1] == NULL || 147838032Speter m->m_argv[2] != NULL) 147938032Speter { 148038032Speter syserr("M%s: too %s parameters for [FILE] mailer", 148138032Speter m->m_name, 148238032Speter (m->m_argv[0] == NULL || 148338032Speter m->m_argv[1] == NULL) ? "few" : "many"); 148471345Sgshapiro return; 148538032Speter } 148638032Speter else if (strcmp(m->m_argv[0], "FILE") != 0) 148738032Speter { 148838032Speter syserr("M%s: first argument in [FILE] mailer must be FILE", 148938032Speter m->m_name); 149071345Sgshapiro return; 149138032Speter } 149238032Speter } 149338032Speter 149438032Speter if (m->m_eol == NULL) 149538032Speter { 149638032Speter char **pp; 149738032Speter 149838032Speter /* default for SMTP is \r\n; use \n for local delivery */ 149938032Speter for (pp = m->m_argv; *pp != NULL; pp++) 150038032Speter { 150138032Speter for (p = *pp; *p != '\0'; ) 150238032Speter { 150338032Speter if ((*p++ & 0377) == MACROEXPAND && *p == 'u') 150438032Speter break; 150538032Speter } 150638032Speter if (*p != '\0') 150738032Speter break; 150838032Speter } 150938032Speter if (*pp == NULL) 151038032Speter m->m_eol = "\r\n"; 151138032Speter else 151238032Speter m->m_eol = "\n"; 151338032Speter } 151438032Speter 151538032Speter /* enter the mailer into the symbol table */ 151638032Speter s = stab(m->m_name, ST_MAILER, ST_ENTER); 151738032Speter if (s->s_mailer != NULL) 151838032Speter { 151938032Speter i = s->s_mailer->m_mno; 152090792Sgshapiro sm_free(s->s_mailer); /* XXX */ 152138032Speter } 152238032Speter else 152338032Speter { 152490792Sgshapiro i = nextmailer++; 152538032Speter } 152638032Speter Mailer[i] = s->s_mailer = m; 152738032Speter m->m_mno = i; 152838032Speter} 152990792Sgshapiro/* 153038032Speter** MUNCHSTRING -- translate a string into internal form. 153138032Speter** 153238032Speter** Parameters: 153338032Speter** p -- the string to munch. 153438032Speter** delimptr -- if non-NULL, set to the pointer of the 153538032Speter** field delimiter character. 153638032Speter** delim -- the delimiter for the field. 153738032Speter** 153838032Speter** Returns: 153938032Speter** the munched string. 154064562Sgshapiro** 154164562Sgshapiro** Side Effects: 154264562Sgshapiro** the munched string is a local static buffer. 154364562Sgshapiro** it must be copied before the function is called again. 154438032Speter*/ 154538032Speter 154638032Speterchar * 154738032Spetermunchstring(p, delimptr, delim) 154838032Speter register char *p; 154938032Speter char **delimptr; 155038032Speter int delim; 155138032Speter{ 155238032Speter register char *q; 155390792Sgshapiro bool backslash = false; 155490792Sgshapiro bool quotemode = false; 155538032Speter static char buf[MAXLINE]; 155638032Speter 155738032Speter for (q = buf; *p != '\0' && q < &buf[sizeof buf - 1]; p++) 155838032Speter { 155938032Speter if (backslash) 156038032Speter { 156138032Speter /* everything is roughly literal */ 156290792Sgshapiro backslash = false; 156338032Speter switch (*p) 156438032Speter { 156538032Speter case 'r': /* carriage return */ 156638032Speter *q++ = '\r'; 156738032Speter continue; 156838032Speter 156938032Speter case 'n': /* newline */ 157038032Speter *q++ = '\n'; 157138032Speter continue; 157238032Speter 157338032Speter case 'f': /* form feed */ 157438032Speter *q++ = '\f'; 157538032Speter continue; 157638032Speter 157738032Speter case 'b': /* backspace */ 157838032Speter *q++ = '\b'; 157938032Speter continue; 158038032Speter } 158138032Speter *q++ = *p; 158238032Speter } 158338032Speter else 158438032Speter { 158538032Speter if (*p == '\\') 158690792Sgshapiro backslash = true; 158738032Speter else if (*p == '"') 158838032Speter quotemode = !quotemode; 158938032Speter else if (quotemode || *p != delim) 159038032Speter *q++ = *p; 159138032Speter else 159238032Speter break; 159338032Speter } 159438032Speter } 159538032Speter 159638032Speter if (delimptr != NULL) 159738032Speter *delimptr = p; 159838032Speter *q++ = '\0'; 159964562Sgshapiro return buf; 160038032Speter} 160190792Sgshapiro/* 160290792Sgshapiro** EXTRQUOTSTR -- extract a (quoted) string. 160390792Sgshapiro** 160490792Sgshapiro** This routine deals with quoted (") strings and escaped 160590792Sgshapiro** spaces (\\ ). 160690792Sgshapiro** 160790792Sgshapiro** Parameters: 160890792Sgshapiro** p -- source string. 160990792Sgshapiro** delimptr -- if non-NULL, set to the pointer of the 161090792Sgshapiro** field delimiter character. 161190792Sgshapiro** delimbuf -- delimiters for the field. 161290792Sgshapiro** st -- if non-NULL, store the return value (whether the 161390792Sgshapiro** string was correctly quoted) here. 161490792Sgshapiro** 161590792Sgshapiro** Returns: 161690792Sgshapiro** the extracted string. 161790792Sgshapiro** 161890792Sgshapiro** Side Effects: 161990792Sgshapiro** the returned string is a local static buffer. 162090792Sgshapiro** it must be copied before the function is called again. 162190792Sgshapiro*/ 162290792Sgshapiro 162390792Sgshapirostatic char * 162490792Sgshapiroextrquotstr(p, delimptr, delimbuf, st) 162590792Sgshapiro register char *p; 162690792Sgshapiro char **delimptr; 162790792Sgshapiro char *delimbuf; 162890792Sgshapiro bool *st; 162990792Sgshapiro{ 163090792Sgshapiro register char *q; 163190792Sgshapiro bool backslash = false; 163290792Sgshapiro bool quotemode = false; 163390792Sgshapiro static char buf[MAXLINE]; 163490792Sgshapiro 163590792Sgshapiro for (q = buf; *p != '\0' && q < &buf[sizeof buf - 1]; p++) 163690792Sgshapiro { 163790792Sgshapiro if (backslash) 163890792Sgshapiro { 163990792Sgshapiro backslash = false; 164090792Sgshapiro if (*p != ' ') 164190792Sgshapiro *q++ = '\\'; 164290792Sgshapiro } 164390792Sgshapiro if (*p == '\\') 164490792Sgshapiro backslash = true; 164590792Sgshapiro else if (*p == '"') 164690792Sgshapiro quotemode = !quotemode; 164790792Sgshapiro else if (quotemode || 164890792Sgshapiro strchr(delimbuf, (int) *p) == NULL) 164990792Sgshapiro *q++ = *p; 165090792Sgshapiro else 165190792Sgshapiro break; 165290792Sgshapiro } 165390792Sgshapiro 165490792Sgshapiro if (delimptr != NULL) 165590792Sgshapiro *delimptr = p; 165690792Sgshapiro *q++ = '\0'; 165790792Sgshapiro if (st != NULL) 165890792Sgshapiro *st = !(quotemode || backslash); 165990792Sgshapiro return buf; 166090792Sgshapiro} 166190792Sgshapiro/* 166238032Speter** MAKEARGV -- break up a string into words 166338032Speter** 166438032Speter** Parameters: 166538032Speter** p -- the string to break up. 166638032Speter** 166738032Speter** Returns: 166838032Speter** a char **argv (dynamically allocated) 166938032Speter** 167038032Speter** Side Effects: 167138032Speter** munges p. 167238032Speter*/ 167338032Speter 167464562Sgshapirostatic char ** 167538032Spetermakeargv(p) 167638032Speter register char *p; 167738032Speter{ 167838032Speter char *q; 167938032Speter int i; 168038032Speter char **avp; 168138032Speter char *argv[MAXPV + 1]; 168238032Speter 168338032Speter /* take apart the words */ 168438032Speter i = 0; 168538032Speter while (*p != '\0' && i < MAXPV) 168638032Speter { 168738032Speter q = p; 168838032Speter while (*p != '\0' && !(isascii(*p) && isspace(*p))) 168938032Speter p++; 169038032Speter while (isascii(*p) && isspace(*p)) 169138032Speter *p++ = '\0'; 169238032Speter argv[i++] = newstr(q); 169338032Speter } 169438032Speter argv[i++] = NULL; 169538032Speter 169638032Speter /* now make a copy of the argv */ 169738032Speter avp = (char **) xalloc(sizeof *avp * i); 169864562Sgshapiro memmove((char *) avp, (char *) argv, sizeof *avp * i); 169938032Speter 170064562Sgshapiro return avp; 170138032Speter} 170290792Sgshapiro/* 170338032Speter** PRINTRULES -- print rewrite rules (for debugging) 170438032Speter** 170538032Speter** Parameters: 170638032Speter** none. 170738032Speter** 170838032Speter** Returns: 170938032Speter** none. 171038032Speter** 171138032Speter** Side Effects: 171238032Speter** prints rewrite rules. 171338032Speter*/ 171438032Speter 171538032Spetervoid 171638032Speterprintrules() 171738032Speter{ 171838032Speter register struct rewrite *rwp; 171938032Speter register int ruleset; 172038032Speter 172138032Speter for (ruleset = 0; ruleset < 10; ruleset++) 172238032Speter { 172338032Speter if (RewriteRules[ruleset] == NULL) 172438032Speter continue; 172590792Sgshapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 172690792Sgshapiro "\n----Rule Set %d:", ruleset); 172738032Speter 172838032Speter for (rwp = RewriteRules[ruleset]; rwp != NULL; rwp = rwp->r_next) 172938032Speter { 173090792Sgshapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 173190792Sgshapiro "\nLHS:"); 173238032Speter printav(rwp->r_lhs); 173390792Sgshapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 173490792Sgshapiro "RHS:"); 173538032Speter printav(rwp->r_rhs); 173638032Speter } 173738032Speter } 173838032Speter} 173990792Sgshapiro/* 174038032Speter** PRINTMAILER -- print mailer structure (for debugging) 174138032Speter** 174238032Speter** Parameters: 174338032Speter** m -- the mailer to print 174438032Speter** 174538032Speter** Returns: 174638032Speter** none. 174738032Speter*/ 174838032Speter 174938032Spetervoid 175038032Speterprintmailer(m) 175138032Speter register MAILER *m; 175238032Speter{ 175338032Speter int j; 175438032Speter 175590792Sgshapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 175690792Sgshapiro "mailer %d (%s): P=%s S=", m->m_mno, m->m_name, 175790792Sgshapiro m->m_mailer); 175864562Sgshapiro if (RuleSetNames[m->m_se_rwset] == NULL) 175990792Sgshapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, "%d/", 176090792Sgshapiro m->m_se_rwset); 176164562Sgshapiro else 176290792Sgshapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, "%s/", 176390792Sgshapiro RuleSetNames[m->m_se_rwset]); 176464562Sgshapiro if (RuleSetNames[m->m_sh_rwset] == NULL) 176590792Sgshapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, "%d R=", 176690792Sgshapiro m->m_sh_rwset); 176764562Sgshapiro else 176890792Sgshapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, "%s R=", 176990792Sgshapiro RuleSetNames[m->m_sh_rwset]); 177064562Sgshapiro if (RuleSetNames[m->m_re_rwset] == NULL) 177190792Sgshapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, "%d/", 177290792Sgshapiro m->m_re_rwset); 177364562Sgshapiro else 177490792Sgshapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, "%s/", 177590792Sgshapiro RuleSetNames[m->m_re_rwset]); 177664562Sgshapiro if (RuleSetNames[m->m_rh_rwset] == NULL) 177790792Sgshapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, "%d ", 177890792Sgshapiro m->m_rh_rwset); 177964562Sgshapiro else 178090792Sgshapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, "%s ", 178190792Sgshapiro RuleSetNames[m->m_rh_rwset]); 178290792Sgshapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, "M=%ld U=%d:%d F=", 178390792Sgshapiro m->m_maxsize, (int) m->m_uid, (int) m->m_gid); 178438032Speter for (j = '\0'; j <= '\177'; j++) 178538032Speter if (bitnset(j, m->m_flags)) 178690792Sgshapiro (void) sm_io_putc(smioout, SM_TIME_DEFAULT, j); 178790792Sgshapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, " L=%d E=", 178890792Sgshapiro m->m_linelimit); 178938032Speter xputs(m->m_eol); 179038032Speter if (m->m_defcharset != NULL) 179190792Sgshapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, " C=%s", 179290792Sgshapiro m->m_defcharset); 179390792Sgshapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, " T=%s/%s/%s", 179490792Sgshapiro m->m_mtatype == NULL 179590792Sgshapiro ? "<undefined>" : m->m_mtatype, 179690792Sgshapiro m->m_addrtype == NULL 179790792Sgshapiro ? "<undefined>" : m->m_addrtype, 179890792Sgshapiro m->m_diagtype == NULL 179990792Sgshapiro ? "<undefined>" : m->m_diagtype); 180090792Sgshapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, " r=%d", m->m_maxrcpt); 180138032Speter if (m->m_argv != NULL) 180238032Speter { 180338032Speter char **a = m->m_argv; 180438032Speter 180590792Sgshapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, " A="); 180638032Speter while (*a != NULL) 180738032Speter { 180838032Speter if (a != m->m_argv) 180990792Sgshapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 181090792Sgshapiro " "); 181138032Speter xputs(*a++); 181238032Speter } 181338032Speter } 181490792Sgshapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, "\n"); 181538032Speter} 181690792Sgshapiro/* 181738032Speter** SETOPTION -- set global processing option 181838032Speter** 181938032Speter** Parameters: 182038032Speter** opt -- option name. 182138032Speter** val -- option value (as a text string). 182238032Speter** safe -- set if this came from a configuration file. 182338032Speter** Some options (if set from the command line) will 182438032Speter** reset the user id to avoid security problems. 182538032Speter** sticky -- if set, don't let other setoptions override 182638032Speter** this value. 182738032Speter** e -- the main envelope. 182838032Speter** 182938032Speter** Returns: 183038032Speter** none. 183138032Speter** 183238032Speter** Side Effects: 183338032Speter** Sets options as implied by the arguments. 183438032Speter*/ 183538032Speter 183664562Sgshapirostatic BITMAP256 StickyOpt; /* set if option is stuck */ 183738032Speter 183838032Speter#if NAMED_BIND 183938032Speter 184064562Sgshapirostatic struct resolverflags 184138032Speter{ 184238032Speter char *rf_name; /* name of the flag */ 184338032Speter long rf_bits; /* bits to set/clear */ 184438032Speter} ResolverFlags[] = 184538032Speter{ 184638032Speter { "debug", RES_DEBUG }, 184738032Speter { "aaonly", RES_AAONLY }, 184838032Speter { "usevc", RES_USEVC }, 184938032Speter { "primary", RES_PRIMARY }, 185038032Speter { "igntc", RES_IGNTC }, 185138032Speter { "recurse", RES_RECURSE }, 185238032Speter { "defnames", RES_DEFNAMES }, 185338032Speter { "stayopen", RES_STAYOPEN }, 185438032Speter { "dnsrch", RES_DNSRCH }, 185590792Sgshapiro# ifdef RES_USE_INET6 185690792Sgshapiro { "use_inet6", RES_USE_INET6 }, 185790792Sgshapiro# endif /* RES_USE_INET6 */ 185838032Speter { "true", 0 }, /* avoid error on old syntax */ 185938032Speter { NULL, 0 } 186038032Speter}; 186138032Speter 186264562Sgshapiro#endif /* NAMED_BIND */ 186338032Speter 186464562Sgshapiro#define OI_NONE 0 /* no special treatment */ 186564562Sgshapiro#define OI_SAFE 0x0001 /* safe for random people to use */ 186664562Sgshapiro#define OI_SUBOPT 0x0002 /* option has suboptions */ 186764562Sgshapiro 186864562Sgshapirostatic struct optioninfo 186938032Speter{ 187090792Sgshapiro char *o_name; /* long name of option */ 187190792Sgshapiro unsigned char o_code; /* short name of option */ 187290792Sgshapiro unsigned short o_flags; /* option flags */ 187338032Speter} OptionTab[] = 187438032Speter{ 187564562Sgshapiro#if defined(SUN_EXTENSIONS) && defined(REMOTE_MODE) 187664562Sgshapiro { "RemoteMode", '>', OI_NONE }, 187764562Sgshapiro#endif /* defined(SUN_EXTENSIONS) && defined(REMOTE_MODE) */ 187864562Sgshapiro { "SevenBitInput", '7', OI_SAFE }, 187964562Sgshapiro { "EightBitMode", '8', OI_SAFE }, 188064562Sgshapiro { "AliasFile", 'A', OI_NONE }, 188164562Sgshapiro { "AliasWait", 'a', OI_NONE }, 188264562Sgshapiro { "BlankSub", 'B', OI_NONE }, 188364562Sgshapiro { "MinFreeBlocks", 'b', OI_SAFE }, 188464562Sgshapiro { "CheckpointInterval", 'C', OI_SAFE }, 188564562Sgshapiro { "HoldExpensive", 'c', OI_NONE }, 188664562Sgshapiro { "DeliveryMode", 'd', OI_SAFE }, 188764562Sgshapiro { "ErrorHeader", 'E', OI_NONE }, 188864562Sgshapiro { "ErrorMode", 'e', OI_SAFE }, 188964562Sgshapiro { "TempFileMode", 'F', OI_NONE }, 189064562Sgshapiro { "SaveFromLine", 'f', OI_NONE }, 189164562Sgshapiro { "MatchGECOS", 'G', OI_NONE }, 189290792Sgshapiro 189390792Sgshapiro /* no long name, just here to avoid problems in setoption */ 189490792Sgshapiro { "", 'g', OI_NONE }, 189564562Sgshapiro { "HelpFile", 'H', OI_NONE }, 189664562Sgshapiro { "MaxHopCount", 'h', OI_NONE }, 189764562Sgshapiro { "ResolverOptions", 'I', OI_NONE }, 189864562Sgshapiro { "IgnoreDots", 'i', OI_SAFE }, 189964562Sgshapiro { "ForwardPath", 'J', OI_NONE }, 190064562Sgshapiro { "SendMimeErrors", 'j', OI_SAFE }, 190164562Sgshapiro { "ConnectionCacheSize", 'k', OI_NONE }, 190264562Sgshapiro { "ConnectionCacheTimeout", 'K', OI_NONE }, 190364562Sgshapiro { "UseErrorsTo", 'l', OI_NONE }, 190464562Sgshapiro { "LogLevel", 'L', OI_SAFE }, 190564562Sgshapiro { "MeToo", 'm', OI_SAFE }, 190690792Sgshapiro 190790792Sgshapiro /* no long name, just here to avoid problems in setoption */ 190890792Sgshapiro { "", 'M', OI_NONE }, 190964562Sgshapiro { "CheckAliases", 'n', OI_NONE }, 191064562Sgshapiro { "OldStyleHeaders", 'o', OI_SAFE }, 191164562Sgshapiro { "DaemonPortOptions", 'O', OI_NONE }, 191264562Sgshapiro { "PrivacyOptions", 'p', OI_SAFE }, 191364562Sgshapiro { "PostmasterCopy", 'P', OI_NONE }, 191464562Sgshapiro { "QueueFactor", 'q', OI_NONE }, 191564562Sgshapiro { "QueueDirectory", 'Q', OI_NONE }, 191664562Sgshapiro { "DontPruneRoutes", 'R', OI_NONE }, 191764562Sgshapiro { "Timeout", 'r', OI_SUBOPT }, 191864562Sgshapiro { "StatusFile", 'S', OI_NONE }, 191964562Sgshapiro { "SuperSafe", 's', OI_SAFE }, 192064562Sgshapiro { "QueueTimeout", 'T', OI_NONE }, 192164562Sgshapiro { "TimeZoneSpec", 't', OI_NONE }, 192264562Sgshapiro { "UserDatabaseSpec", 'U', OI_NONE }, 192364562Sgshapiro { "DefaultUser", 'u', OI_NONE }, 192464562Sgshapiro { "FallbackMXhost", 'V', OI_NONE }, 192564562Sgshapiro { "Verbose", 'v', OI_SAFE }, 192664562Sgshapiro { "TryNullMXList", 'w', OI_NONE }, 192764562Sgshapiro { "QueueLA", 'x', OI_NONE }, 192864562Sgshapiro { "RefuseLA", 'X', OI_NONE }, 192964562Sgshapiro { "RecipientFactor", 'y', OI_NONE }, 193064562Sgshapiro { "ForkEachJob", 'Y', OI_NONE }, 193164562Sgshapiro { "ClassFactor", 'z', OI_NONE }, 193264562Sgshapiro { "RetryFactor", 'Z', OI_NONE }, 193338032Speter#define O_QUEUESORTORD 0x81 193464562Sgshapiro { "QueueSortOrder", O_QUEUESORTORD, OI_SAFE }, 193538032Speter#define O_HOSTSFILE 0x82 193664562Sgshapiro { "HostsFile", O_HOSTSFILE, OI_NONE }, 193738032Speter#define O_MQA 0x83 193864562Sgshapiro { "MinQueueAge", O_MQA, OI_SAFE }, 193938032Speter#define O_DEFCHARSET 0x85 194064562Sgshapiro { "DefaultCharSet", O_DEFCHARSET, OI_SAFE }, 194138032Speter#define O_SSFILE 0x86 194264562Sgshapiro { "ServiceSwitchFile", O_SSFILE, OI_NONE }, 194338032Speter#define O_DIALDELAY 0x87 194464562Sgshapiro { "DialDelay", O_DIALDELAY, OI_SAFE }, 194538032Speter#define O_NORCPTACTION 0x88 194664562Sgshapiro { "NoRecipientAction", O_NORCPTACTION, OI_SAFE }, 194738032Speter#define O_SAFEFILEENV 0x89 194864562Sgshapiro { "SafeFileEnvironment", O_SAFEFILEENV, OI_NONE }, 194938032Speter#define O_MAXMSGSIZE 0x8a 195064562Sgshapiro { "MaxMessageSize", O_MAXMSGSIZE, OI_NONE }, 195138032Speter#define O_COLONOKINADDR 0x8b 195264562Sgshapiro { "ColonOkInAddr", O_COLONOKINADDR, OI_SAFE }, 195338032Speter#define O_MAXQUEUERUN 0x8c 195464562Sgshapiro { "MaxQueueRunSize", O_MAXQUEUERUN, OI_SAFE }, 195538032Speter#define O_MAXCHILDREN 0x8d 195664562Sgshapiro { "MaxDaemonChildren", O_MAXCHILDREN, OI_NONE }, 195738032Speter#define O_KEEPCNAMES 0x8e 195864562Sgshapiro { "DontExpandCnames", O_KEEPCNAMES, OI_NONE }, 195938032Speter#define O_MUSTQUOTE 0x8f 196064562Sgshapiro { "MustQuoteChars", O_MUSTQUOTE, OI_NONE }, 196138032Speter#define O_SMTPGREETING 0x90 196264562Sgshapiro { "SmtpGreetingMessage", O_SMTPGREETING, OI_NONE }, 196338032Speter#define O_UNIXFROM 0x91 196464562Sgshapiro { "UnixFromLine", O_UNIXFROM, OI_NONE }, 196538032Speter#define O_OPCHARS 0x92 196664562Sgshapiro { "OperatorChars", O_OPCHARS, OI_NONE }, 196738032Speter#define O_DONTINITGRPS 0x93 196864562Sgshapiro { "DontInitGroups", O_DONTINITGRPS, OI_NONE }, 196938032Speter#define O_SLFH 0x94 197064562Sgshapiro { "SingleLineFromHeader", O_SLFH, OI_SAFE }, 197138032Speter#define O_ABH 0x95 197264562Sgshapiro { "AllowBogusHELO", O_ABH, OI_SAFE }, 197338032Speter#define O_CONNTHROT 0x97 197464562Sgshapiro { "ConnectionRateThrottle", O_CONNTHROT, OI_NONE }, 197538032Speter#define O_UGW 0x99 197664562Sgshapiro { "UnsafeGroupWrites", O_UGW, OI_NONE }, 197738032Speter#define O_DBLBOUNCE 0x9a 197864562Sgshapiro { "DoubleBounceAddress", O_DBLBOUNCE, OI_NONE }, 197938032Speter#define O_HSDIR 0x9b 198064562Sgshapiro { "HostStatusDirectory", O_HSDIR, OI_NONE }, 198138032Speter#define O_SINGTHREAD 0x9c 198264562Sgshapiro { "SingleThreadDelivery", O_SINGTHREAD, OI_NONE }, 198338032Speter#define O_RUNASUSER 0x9d 198464562Sgshapiro { "RunAsUser", O_RUNASUSER, OI_NONE }, 198538032Speter#define O_DSN_RRT 0x9e 198664562Sgshapiro { "RrtImpliesDsn", O_DSN_RRT, OI_NONE }, 198738032Speter#define O_PIDFILE 0x9f 198864562Sgshapiro { "PidFile", O_PIDFILE, OI_NONE }, 198938032Speter#define O_DONTBLAMESENDMAIL 0xa0 199064562Sgshapiro { "DontBlameSendmail", O_DONTBLAMESENDMAIL, OI_NONE }, 199138032Speter#define O_DPI 0xa1 199264562Sgshapiro { "DontProbeInterfaces", O_DPI, OI_NONE }, 199338032Speter#define O_MAXRCPT 0xa2 199464562Sgshapiro { "MaxRecipientsPerMessage", O_MAXRCPT, OI_SAFE }, 199538032Speter#define O_DEADLETTER 0xa3 199664562Sgshapiro { "DeadLetterDrop", O_DEADLETTER, OI_NONE }, 199738032Speter#if _FFR_DONTLOCKFILESFORREAD_OPTION 199864562Sgshapiro# define O_DONTLOCK 0xa4 199964562Sgshapiro { "DontLockFilesForRead", O_DONTLOCK, OI_NONE }, 200064562Sgshapiro#endif /* _FFR_DONTLOCKFILESFORREAD_OPTION */ 200138032Speter#define O_MAXALIASRCSN 0xa5 200264562Sgshapiro { "MaxAliasRecursion", O_MAXALIASRCSN, OI_NONE }, 200338032Speter#define O_CNCTONLYTO 0xa6 200464562Sgshapiro { "ConnectOnlyTo", O_CNCTONLYTO, OI_NONE }, 200542575Speter#define O_TRUSTUSER 0xa7 200664562Sgshapiro { "TrustedUser", O_TRUSTUSER, OI_NONE }, 200742575Speter#define O_MAXMIMEHDRLEN 0xa8 200864562Sgshapiro { "MaxMimeHeaderLength", O_MAXMIMEHDRLEN, OI_NONE }, 200942575Speter#define O_CONTROLSOCKET 0xa9 201064562Sgshapiro { "ControlSocketName", O_CONTROLSOCKET, OI_NONE }, 201143730Speter#define O_MAXHDRSLEN 0xaa 201264562Sgshapiro { "MaxHeadersLength", O_MAXHDRSLEN, OI_NONE }, 201364562Sgshapiro#if _FFR_MAX_FORWARD_ENTRIES 201464562Sgshapiro# define O_MAXFORWARD 0xab 201564562Sgshapiro { "MaxForwardEntries", O_MAXFORWARD, OI_NONE }, 201664562Sgshapiro#endif /* _FFR_MAX_FORWARD_ENTRIES */ 201764562Sgshapiro#define O_PROCTITLEPREFIX 0xac 201864562Sgshapiro { "ProcessTitlePrefix", O_PROCTITLEPREFIX, OI_NONE }, 201964562Sgshapiro#define O_SASLINFO 0xad 202064562Sgshapiro#if _FFR_ALLOW_SASLINFO 202164562Sgshapiro { "DefaultAuthInfo", O_SASLINFO, OI_SAFE }, 202264562Sgshapiro#else /* _FFR_ALLOW_SASLINFO */ 202364562Sgshapiro { "DefaultAuthInfo", O_SASLINFO, OI_NONE }, 202464562Sgshapiro#endif /* _FFR_ALLOW_SASLINFO */ 202564562Sgshapiro#define O_SASLMECH 0xae 202664562Sgshapiro { "AuthMechanisms", O_SASLMECH, OI_NONE }, 202764562Sgshapiro#define O_CLIENTPORT 0xaf 202864562Sgshapiro { "ClientPortOptions", O_CLIENTPORT, OI_NONE }, 202964562Sgshapiro#define O_DF_BUFSIZE 0xb0 203064562Sgshapiro { "DataFileBufferSize", O_DF_BUFSIZE, OI_NONE }, 203164562Sgshapiro#define O_XF_BUFSIZE 0xb1 203264562Sgshapiro { "XscriptFileBufferSize", O_XF_BUFSIZE, OI_NONE }, 203390792Sgshapiro#define O_LDAPDEFAULTSPEC 0xb2 203464562Sgshapiro { "LDAPDefaultSpec", O_LDAPDEFAULTSPEC, OI_NONE }, 203564562Sgshapiro#if _FFR_QUEUEDELAY 203690792Sgshapiro# define O_QUEUEDELAY 0xb3 203764562Sgshapiro { "QueueDelay", O_QUEUEDELAY, OI_NONE }, 203864562Sgshapiro#endif /* _FFR_QUEUEDELAY */ 203990792Sgshapiro#define O_SRVCERTFILE 0xb4 204064562Sgshapiro { "ServerCertFile", O_SRVCERTFILE, OI_NONE }, 204190792Sgshapiro#define O_SRVKEYFILE 0xb5 204264562Sgshapiro { "Serverkeyfile", O_SRVKEYFILE, OI_NONE }, 204390792Sgshapiro#define O_CLTCERTFILE 0xb6 204464562Sgshapiro { "ClientCertFile", O_CLTCERTFILE, OI_NONE }, 204590792Sgshapiro#define O_CLTKEYFILE 0xb7 204664562Sgshapiro { "Clientkeyfile", O_CLTKEYFILE, OI_NONE }, 204790792Sgshapiro#define O_CACERTFILE 0xb8 204864562Sgshapiro { "CACERTFile", O_CACERTFILE, OI_NONE }, 204990792Sgshapiro#define O_CACERTPATH 0xb9 205064562Sgshapiro { "CACERTPath", O_CACERTPATH, OI_NONE }, 205190792Sgshapiro#define O_DHPARAMS 0xba 205264562Sgshapiro { "DHParameters", O_DHPARAMS, OI_NONE }, 205364562Sgshapiro#define O_INPUTMILTER 0xbb 205464562Sgshapiro { "InputMailFilters", O_INPUTMILTER, OI_NONE }, 205564562Sgshapiro#define O_MILTER 0xbc 205664562Sgshapiro { "Milter", O_MILTER, OI_SUBOPT }, 205764562Sgshapiro#define O_SASLOPTS 0xbd 205864562Sgshapiro { "AuthOptions", O_SASLOPTS, OI_NONE }, 205964562Sgshapiro#define O_QUEUE_FILE_MODE 0xbe 206064562Sgshapiro { "QueueFileMode", O_QUEUE_FILE_MODE, OI_NONE }, 206190792Sgshapiro#if _FFR_TLS_1 206264562Sgshapiro# define O_DHPARAMS5 0xbf 206364562Sgshapiro { "DHParameters512", O_DHPARAMS5, OI_NONE }, 206464562Sgshapiro# define O_CIPHERLIST 0xc0 206564562Sgshapiro { "CipherList", O_CIPHERLIST, OI_NONE }, 206690792Sgshapiro#endif /* _FFR_TLS_1 */ 206790792Sgshapiro#define O_RANDFILE 0xc1 206864562Sgshapiro { "RandFile", O_RANDFILE, OI_NONE }, 206990792Sgshapiro#define O_TLS_SRV_OPTS 0xc2 207090792Sgshapiro { "TLSSrvOptions", O_TLS_SRV_OPTS, OI_NONE }, 207190792Sgshapiro#define O_RCPTTHROT 0xc3 207290792Sgshapiro { "BadRcptThrottle", O_RCPTTHROT, OI_SAFE }, 207390792Sgshapiro#define O_DLVR_MIN 0xc4 207490792Sgshapiro { "DeliverByMin", O_DLVR_MIN, OI_NONE }, 207590792Sgshapiro#define O_MAXQUEUECHILDREN 0xc5 207690792Sgshapiro { "MaxQueueChildren", O_MAXQUEUECHILDREN, OI_NONE }, 207790792Sgshapiro#define O_MAXRUNNERSPERQUEUE 0xc6 207890792Sgshapiro { "MaxRunnersPerQueue", O_MAXRUNNERSPERQUEUE, OI_NONE }, 207990792Sgshapiro#define O_DIRECTSUBMODIFIERS 0xc7 208090792Sgshapiro { "DirectSubmissionModifiers", O_DIRECTSUBMODIFIERS, OI_NONE }, 208190792Sgshapiro#define O_NICEQUEUERUN 0xc8 208290792Sgshapiro { "NiceQueueRun", O_NICEQUEUERUN, OI_NONE }, 208390792Sgshapiro#define O_SHMKEY 0xc9 208490792Sgshapiro { "SharedMemoryKey", O_SHMKEY, OI_NONE }, 208590792Sgshapiro#define O_SASLBITS 0xca 208690792Sgshapiro { "AuthMaxBits", O_SASLBITS, OI_NONE }, 208790792Sgshapiro#define O_MBDB 0xcb 208890792Sgshapiro { "MailboxDatabase", O_MBDB, OI_NONE }, 208990792Sgshapiro#define O_MSQ 0xcc 209090792Sgshapiro { "UseMSP", O_MSQ, OI_NONE }, 209190792Sgshapiro#define O_DELAY_LA 0xcd 209290792Sgshapiro { "DelayLA", O_DELAY_LA, OI_NONE }, 209390792Sgshapiro#define O_FASTSPLIT 0xce 209490792Sgshapiro { "FastSplit", O_FASTSPLIT, OI_NONE }, 209590792Sgshapiro#if _FFR_SOFT_BOUNCE 209690792Sgshapiro# define O_SOFTBOUNCE 0xcf 209790792Sgshapiro { "SoftBounce", O_SOFTBOUNCE, OI_NONE }, 209890792Sgshapiro#endif /* _FFR_SOFT_BOUNCE */ 209994334Sgshapiro#if _FFR_SELECT_SHM 210094334Sgshapiro# define O_SHMKEYFILE 0xd0 210194334Sgshapiro { "SharedMemoryKeyFile", O_SHMKEYFILE, OI_NONE }, 210294334Sgshapiro#endif /* _FFR_SELECT_SHM */ 210364562Sgshapiro { NULL, '\0', OI_NONE } 210438032Speter}; 210538032Speter 210690792Sgshapiro# define CANONIFY(val) 210790792Sgshapiro 210890792Sgshapiro# define SET_OPT_DEFAULT(opt, val) opt = val 210990792Sgshapiro 211090792Sgshapiro/* set a string option by expanding the value and assigning it */ 211190792Sgshapiro/* WARNING this belongs ONLY into a case statement! */ 211290792Sgshapiro#define SET_STRING_EXP(str) \ 211390792Sgshapiro expand(val, exbuf, sizeof exbuf, e); \ 211490792Sgshapiro newval = sm_pstrdup_x(exbuf); \ 211590792Sgshapiro if (str != NULL) \ 211690792Sgshapiro sm_free(str); \ 211790792Sgshapiro CANONIFY(newval); \ 211890792Sgshapiro str = newval; \ 211990792Sgshapiro break 212090792Sgshapiro 212190792Sgshapiro#define OPTNAME o->o_name == NULL ? "<unknown>" : o->o_name 212290792Sgshapiro 212338032Spetervoid 212438032Spetersetoption(opt, val, safe, sticky, e) 212538032Speter int opt; 212638032Speter char *val; 212738032Speter bool safe; 212838032Speter bool sticky; 212938032Speter register ENVELOPE *e; 213038032Speter{ 213138032Speter register char *p; 213238032Speter register struct optioninfo *o; 213338032Speter char *subopt; 213438032Speter int mid; 213538032Speter bool can_setuid = RunAsUid == 0; 213638032Speter auto char *ep; 213738032Speter char buf[50]; 213838032Speter extern bool Warn_Q_option; 213964562Sgshapiro#if _FFR_ALLOW_SASLINFO 214090792Sgshapiro extern unsigned int SubmitMode; 214164562Sgshapiro#endif /* _FFR_ALLOW_SASLINFO */ 214290792Sgshapiro#if STARTTLS 214390792Sgshapiro char *newval; 214490792Sgshapiro char exbuf[MAXLINE]; 214590792Sgshapiro#endif /* STARTTLS */ 214638032Speter 214738032Speter errno = 0; 214838032Speter if (opt == ' ') 214938032Speter { 215038032Speter /* full word options */ 215138032Speter struct optioninfo *sel; 215238032Speter 215338032Speter p = strchr(val, '='); 215438032Speter if (p == NULL) 215538032Speter p = &val[strlen(val)]; 215638032Speter while (*--p == ' ') 215738032Speter continue; 215838032Speter while (*++p == ' ') 215938032Speter *p = '\0'; 216038032Speter if (p == val) 216138032Speter { 216238032Speter syserr("readcf: null option name"); 216338032Speter return; 216438032Speter } 216538032Speter if (*p == '=') 216638032Speter *p++ = '\0'; 216738032Speter while (*p == ' ') 216838032Speter p++; 216938032Speter subopt = strchr(val, '.'); 217038032Speter if (subopt != NULL) 217138032Speter *subopt++ = '\0'; 217238032Speter sel = NULL; 217338032Speter for (o = OptionTab; o->o_name != NULL; o++) 217438032Speter { 217590792Sgshapiro if (sm_strncasecmp(o->o_name, val, strlen(val)) != 0) 217638032Speter continue; 217738032Speter if (strlen(o->o_name) == strlen(val)) 217838032Speter { 217938032Speter /* completely specified -- this must be it */ 218038032Speter sel = NULL; 218138032Speter break; 218238032Speter } 218338032Speter if (sel != NULL) 218438032Speter break; 218538032Speter sel = o; 218638032Speter } 218738032Speter if (sel != NULL && o->o_name == NULL) 218838032Speter o = sel; 218938032Speter else if (o->o_name == NULL) 219038032Speter { 219138032Speter syserr("readcf: unknown option name %s", val); 219238032Speter return; 219338032Speter } 219438032Speter else if (sel != NULL) 219538032Speter { 219638032Speter syserr("readcf: ambiguous option name %s (matches %s and %s)", 219738032Speter val, sel->o_name, o->o_name); 219838032Speter return; 219938032Speter } 220038032Speter if (strlen(val) != strlen(o->o_name)) 220138032Speter { 220238032Speter int oldVerbose = Verbose; 220338032Speter 220438032Speter Verbose = 1; 220538032Speter message("Option %s used as abbreviation for %s", 220638032Speter val, o->o_name); 220738032Speter Verbose = oldVerbose; 220838032Speter } 220938032Speter opt = o->o_code; 221038032Speter val = p; 221138032Speter } 221238032Speter else 221338032Speter { 221438032Speter for (o = OptionTab; o->o_name != NULL; o++) 221538032Speter { 221638032Speter if (o->o_code == opt) 221738032Speter break; 221838032Speter } 221990792Sgshapiro if (o->o_name == NULL) 222090792Sgshapiro { 222190792Sgshapiro syserr("readcf: unknown option name 0x%x", opt & 0xff); 222290792Sgshapiro return; 222390792Sgshapiro } 222438032Speter subopt = NULL; 222538032Speter } 222638032Speter 222764562Sgshapiro if (subopt != NULL && !bitset(OI_SUBOPT, o->o_flags)) 222864562Sgshapiro { 222964562Sgshapiro if (tTd(37, 1)) 223090792Sgshapiro sm_dprintf("setoption: %s does not support suboptions, ignoring .%s\n", 223190792Sgshapiro OPTNAME, subopt); 223264562Sgshapiro subopt = NULL; 223364562Sgshapiro } 223464562Sgshapiro 223538032Speter if (tTd(37, 1)) 223638032Speter { 223790792Sgshapiro sm_dprintf(isascii(opt) && isprint(opt) ? 223890792Sgshapiro "setoption %s (%c)%s%s=" : 223990792Sgshapiro "setoption %s (0x%x)%s%s=", 224090792Sgshapiro OPTNAME, opt, subopt == NULL ? "" : ".", 224190792Sgshapiro subopt == NULL ? "" : subopt); 224238032Speter xputs(val); 224338032Speter } 224438032Speter 224538032Speter /* 224638032Speter ** See if this option is preset for us. 224738032Speter */ 224838032Speter 224938032Speter if (!sticky && bitnset(opt, StickyOpt)) 225038032Speter { 225138032Speter if (tTd(37, 1)) 225290792Sgshapiro sm_dprintf(" (ignored)\n"); 225338032Speter return; 225438032Speter } 225538032Speter 225638032Speter /* 225738032Speter ** Check to see if this option can be specified by this user. 225838032Speter */ 225938032Speter 226038032Speter if (!safe && RealUid == 0) 226190792Sgshapiro safe = true; 226264562Sgshapiro if (!safe && !bitset(OI_SAFE, o->o_flags)) 226338032Speter { 226438032Speter if (opt != 'M' || (val[0] != 'r' && val[0] != 's')) 226538032Speter { 226664562Sgshapiro int dp; 226764562Sgshapiro 226838032Speter if (tTd(37, 1)) 226990792Sgshapiro sm_dprintf(" (unsafe)"); 227090792Sgshapiro dp = drop_privileges(true); 227164562Sgshapiro setstat(dp); 227238032Speter } 227338032Speter } 227438032Speter if (tTd(37, 1)) 227590792Sgshapiro sm_dprintf("\n"); 227638032Speter 227738032Speter switch (opt & 0xff) 227838032Speter { 227938032Speter case '7': /* force seven-bit input */ 228038032Speter SevenBitInput = atobool(val); 228138032Speter break; 228238032Speter 228377349Sgshapiro case '8': /* handling of 8-bit input */ 228438032Speter#if MIME8TO7 228538032Speter switch (*val) 228638032Speter { 228790792Sgshapiro case 'p': /* pass 8 bit, convert MIME */ 228890792Sgshapiro MimeMode = MM_CVTMIME|MM_PASS8BIT; 228990792Sgshapiro break; 229090792Sgshapiro 229138032Speter case 'm': /* convert 8-bit, convert MIME */ 229238032Speter MimeMode = MM_CVTMIME|MM_MIME8BIT; 229338032Speter break; 229438032Speter 229538032Speter case 's': /* strict adherence */ 229638032Speter MimeMode = MM_CVTMIME; 229738032Speter break; 229838032Speter 229964562Sgshapiro# if 0 230038032Speter case 'r': /* reject 8-bit, don't convert MIME */ 230138032Speter MimeMode = 0; 230238032Speter break; 230338032Speter 230438032Speter case 'j': /* "just send 8" */ 230538032Speter MimeMode = MM_PASS8BIT; 230638032Speter break; 230738032Speter 230838032Speter case 'a': /* encode 8 bit if available */ 230938032Speter MimeMode = MM_MIME8BIT|MM_PASS8BIT|MM_CVTMIME; 231038032Speter break; 231138032Speter 231238032Speter case 'c': /* convert 8 bit to MIME, never 7 bit */ 231338032Speter MimeMode = MM_MIME8BIT; 231438032Speter break; 231564562Sgshapiro# endif /* 0 */ 231638032Speter 231738032Speter default: 231838032Speter syserr("Unknown 8-bit mode %c", *val); 231990792Sgshapiro finis(false, true, EX_USAGE); 232038032Speter } 232177349Sgshapiro#else /* MIME8TO7 */ 232290792Sgshapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 232390792Sgshapiro "Warning: Option: %s requires MIME8TO7 support\n", 232490792Sgshapiro OPTNAME); 232577349Sgshapiro#endif /* MIME8TO7 */ 232638032Speter break; 232738032Speter 232838032Speter case 'A': /* set default alias file */ 232938032Speter if (val[0] == '\0') 233090792Sgshapiro { 233190792Sgshapiro char *al; 233290792Sgshapiro 233390792Sgshapiro SET_OPT_DEFAULT(al, "aliases"); 233490792Sgshapiro setalias(al); 233590792Sgshapiro } 233638032Speter else 233738032Speter setalias(val); 233838032Speter break; 233938032Speter 234038032Speter case 'a': /* look N minutes for "@:@" in alias file */ 234138032Speter if (val[0] == '\0') 234290792Sgshapiro SafeAlias = 5 MINUTES; 234338032Speter else 234438032Speter SafeAlias = convtime(val, 'm'); 234538032Speter break; 234638032Speter 234738032Speter case 'B': /* substitution for blank character */ 234838032Speter SpaceSub = val[0]; 234938032Speter if (SpaceSub == '\0') 235038032Speter SpaceSub = ' '; 235138032Speter break; 235238032Speter 235338032Speter case 'b': /* min blocks free on queue fs/max msg size */ 235438032Speter p = strchr(val, '/'); 235538032Speter if (p != NULL) 235638032Speter { 235738032Speter *p++ = '\0'; 235838032Speter MaxMessageSize = atol(p); 235938032Speter } 236038032Speter MinBlocksFree = atol(val); 236138032Speter break; 236238032Speter 236338032Speter case 'c': /* don't connect to "expensive" mailers */ 236438032Speter NoConnect = atobool(val); 236538032Speter break; 236638032Speter 236738032Speter case 'C': /* checkpoint every N addresses */ 236838032Speter CheckpointInterval = atoi(val); 236938032Speter break; 237038032Speter 237138032Speter case 'd': /* delivery mode */ 237238032Speter switch (*val) 237338032Speter { 237438032Speter case '\0': 237564562Sgshapiro set_delivery_mode(SM_DELIVER, e); 237638032Speter break; 237738032Speter 237838032Speter case SM_QUEUE: /* queue only */ 237938032Speter case SM_DEFER: /* queue only and defer map lookups */ 238038032Speter case SM_DELIVER: /* do everything */ 238138032Speter case SM_FORK: /* fork after verification */ 238264562Sgshapiro set_delivery_mode(*val, e); 238338032Speter break; 238438032Speter 238538032Speter default: 238638032Speter syserr("Unknown delivery mode %c", *val); 238790792Sgshapiro finis(false, true, EX_USAGE); 238838032Speter } 238938032Speter break; 239038032Speter 239138032Speter case 'E': /* error message header/header file */ 239238032Speter if (*val != '\0') 239338032Speter ErrMsgFile = newstr(val); 239438032Speter break; 239538032Speter 239638032Speter case 'e': /* set error processing mode */ 239738032Speter switch (*val) 239838032Speter { 239938032Speter case EM_QUIET: /* be silent about it */ 240038032Speter case EM_MAIL: /* mail back */ 240138032Speter case EM_BERKNET: /* do berknet error processing */ 240238032Speter case EM_WRITE: /* write back (or mail) */ 240338032Speter case EM_PRINT: /* print errors normally (default) */ 240438032Speter e->e_errormode = *val; 240538032Speter break; 240638032Speter } 240738032Speter break; 240838032Speter 240938032Speter case 'F': /* file mode */ 241038032Speter FileMode = atooct(val) & 0777; 241138032Speter break; 241238032Speter 241338032Speter case 'f': /* save Unix-style From lines on front */ 241438032Speter SaveFrom = atobool(val); 241538032Speter break; 241638032Speter 241738032Speter case 'G': /* match recipients against GECOS field */ 241838032Speter MatchGecos = atobool(val); 241938032Speter break; 242038032Speter 242138032Speter case 'g': /* default gid */ 242238032Speter g_opt: 242338032Speter if (isascii(*val) && isdigit(*val)) 242438032Speter DefGid = atoi(val); 242538032Speter else 242638032Speter { 242738032Speter register struct group *gr; 242838032Speter 242938032Speter DefGid = -1; 243038032Speter gr = getgrnam(val); 243138032Speter if (gr == NULL) 243238032Speter syserr("readcf: option %c: unknown group %s", 243338032Speter opt, val); 243438032Speter else 243538032Speter DefGid = gr->gr_gid; 243638032Speter } 243738032Speter break; 243838032Speter 243938032Speter case 'H': /* help file */ 244038032Speter if (val[0] == '\0') 244190792Sgshapiro { 244290792Sgshapiro SET_OPT_DEFAULT(HelpFile, "helpfile"); 244390792Sgshapiro } 244438032Speter else 244573188Sgshapiro { 244690792Sgshapiro CANONIFY(val); 244738032Speter HelpFile = newstr(val); 244873188Sgshapiro } 244938032Speter break; 245038032Speter 245138032Speter case 'h': /* maximum hop count */ 245238032Speter MaxHopCount = atoi(val); 245338032Speter break; 245438032Speter 245538032Speter case 'I': /* use internet domain name server */ 245638032Speter#if NAMED_BIND 245738032Speter for (p = val; *p != 0; ) 245838032Speter { 245938032Speter bool clearmode; 246038032Speter char *q; 246138032Speter struct resolverflags *rfp; 246238032Speter 246338032Speter while (*p == ' ') 246438032Speter p++; 246538032Speter if (*p == '\0') 246638032Speter break; 246790792Sgshapiro clearmode = false; 246838032Speter if (*p == '-') 246990792Sgshapiro clearmode = true; 247038032Speter else if (*p != '+') 247138032Speter p--; 247238032Speter p++; 247338032Speter q = p; 247438032Speter while (*p != '\0' && !(isascii(*p) && isspace(*p))) 247538032Speter p++; 247638032Speter if (*p != '\0') 247738032Speter *p++ = '\0'; 247890792Sgshapiro if (sm_strcasecmp(q, "HasWildcardMX") == 0) 247938032Speter { 248038032Speter HasWildcardMX = !clearmode; 248138032Speter continue; 248238032Speter } 248373188Sgshapiro if (sm_strcasecmp(q, "WorkAroundBrokenAAAA") == 0) 248473188Sgshapiro { 248573188Sgshapiro WorkAroundBrokenAAAA = !clearmode; 248673188Sgshapiro continue; 248773188Sgshapiro } 248838032Speter for (rfp = ResolverFlags; rfp->rf_name != NULL; rfp++) 248938032Speter { 249090792Sgshapiro if (sm_strcasecmp(q, rfp->rf_name) == 0) 249138032Speter break; 249238032Speter } 249338032Speter if (rfp->rf_name == NULL) 249438032Speter syserr("readcf: I option value %s unrecognized", q); 249538032Speter else if (clearmode) 249638032Speter _res.options &= ~rfp->rf_bits; 249738032Speter else 249838032Speter _res.options |= rfp->rf_bits; 249938032Speter } 250038032Speter if (tTd(8, 2)) 250190792Sgshapiro sm_dprintf("_res.options = %x, HasWildcardMX = %d\n", 250290792Sgshapiro (unsigned int) _res.options, HasWildcardMX); 250364562Sgshapiro#else /* NAMED_BIND */ 250438032Speter usrerr("name server (I option) specified but BIND not compiled in"); 250564562Sgshapiro#endif /* NAMED_BIND */ 250638032Speter break; 250738032Speter 250838032Speter case 'i': /* ignore dot lines in message */ 250938032Speter IgnrDot = atobool(val); 251038032Speter break; 251138032Speter 251238032Speter case 'j': /* send errors in MIME (RFC 1341) format */ 251338032Speter SendMIMEErrors = atobool(val); 251438032Speter break; 251538032Speter 251638032Speter case 'J': /* .forward search path */ 251790792Sgshapiro CANONIFY(val); 251838032Speter ForwardPath = newstr(val); 251938032Speter break; 252038032Speter 252138032Speter case 'k': /* connection cache size */ 252238032Speter MaxMciCache = atoi(val); 252338032Speter if (MaxMciCache < 0) 252438032Speter MaxMciCache = 0; 252538032Speter break; 252638032Speter 252738032Speter case 'K': /* connection cache timeout */ 252838032Speter MciCacheTimeout = convtime(val, 'm'); 252938032Speter break; 253038032Speter 253138032Speter case 'l': /* use Errors-To: header */ 253238032Speter UseErrorsTo = atobool(val); 253338032Speter break; 253438032Speter 253538032Speter case 'L': /* log level */ 253638032Speter if (safe || LogLevel < atoi(val)) 253738032Speter LogLevel = atoi(val); 253838032Speter break; 253938032Speter 254038032Speter case 'M': /* define macro */ 254190792Sgshapiro sticky = false; 254290792Sgshapiro mid = macid_parse(val, &ep); 254371345Sgshapiro if (mid == 0) 254471345Sgshapiro break; 254538032Speter p = newstr(ep); 254638032Speter if (!safe) 254738032Speter cleanstrcpy(p, p, MAXNAME); 254890792Sgshapiro macdefine(&CurEnv->e_macro, A_TEMP, mid, p); 254938032Speter break; 255038032Speter 255138032Speter case 'm': /* send to me too */ 255238032Speter MeToo = atobool(val); 255338032Speter break; 255438032Speter 255538032Speter case 'n': /* validate RHS in newaliases */ 255638032Speter CheckAliases = atobool(val); 255738032Speter break; 255838032Speter 255938032Speter /* 'N' available -- was "net name" */ 256038032Speter 256138032Speter case 'O': /* daemon options */ 256264562Sgshapiro if (!setdaemonoptions(val)) 256364562Sgshapiro syserr("too many daemons defined (%d max)", MAXDAEMONS); 256438032Speter break; 256538032Speter 256638032Speter case 'o': /* assume old style headers */ 256738032Speter if (atobool(val)) 256838032Speter CurEnv->e_flags |= EF_OLDSTYLE; 256938032Speter else 257038032Speter CurEnv->e_flags &= ~EF_OLDSTYLE; 257138032Speter break; 257238032Speter 257338032Speter case 'p': /* select privacy level */ 257438032Speter p = val; 257538032Speter for (;;) 257638032Speter { 257738032Speter register struct prival *pv; 257838032Speter extern struct prival PrivacyValues[]; 257938032Speter 258038032Speter while (isascii(*p) && (isspace(*p) || ispunct(*p))) 258138032Speter p++; 258238032Speter if (*p == '\0') 258338032Speter break; 258438032Speter val = p; 258538032Speter while (isascii(*p) && isalnum(*p)) 258638032Speter p++; 258738032Speter if (*p != '\0') 258838032Speter *p++ = '\0'; 258938032Speter 259038032Speter for (pv = PrivacyValues; pv->pv_name != NULL; pv++) 259138032Speter { 259290792Sgshapiro if (sm_strcasecmp(val, pv->pv_name) == 0) 259338032Speter break; 259438032Speter } 259538032Speter if (pv->pv_name == NULL) 259638032Speter syserr("readcf: Op line: %s unrecognized", val); 259771345Sgshapiro else 259871345Sgshapiro PrivacyFlags |= pv->pv_flag; 259938032Speter } 260090792Sgshapiro sticky = false; 260138032Speter break; 260238032Speter 260338032Speter case 'P': /* postmaster copy address for returned mail */ 260438032Speter PostMasterCopy = newstr(val); 260538032Speter break; 260638032Speter 260738032Speter case 'q': /* slope of queue only function */ 260838032Speter QueueFactor = atoi(val); 260938032Speter break; 261038032Speter 261138032Speter case 'Q': /* queue directory */ 261238032Speter if (val[0] == '\0') 261366494Sgshapiro { 261438032Speter QueueDir = "mqueue"; 261566494Sgshapiro } 261638032Speter else 261766494Sgshapiro { 261838032Speter QueueDir = newstr(val); 261966494Sgshapiro } 262038032Speter if (RealUid != 0 && !safe) 262190792Sgshapiro Warn_Q_option = true; 262238032Speter break; 262338032Speter 262438032Speter case 'R': /* don't prune routes */ 262538032Speter DontPruneRoutes = atobool(val); 262638032Speter break; 262738032Speter 262838032Speter case 'r': /* read timeout */ 262938032Speter if (subopt == NULL) 263064562Sgshapiro inittimeouts(val, sticky); 263138032Speter else 263264562Sgshapiro settimeout(subopt, val, sticky); 263338032Speter break; 263438032Speter 263538032Speter case 'S': /* status file */ 263638032Speter if (val[0] == '\0') 263790792Sgshapiro { 263890792Sgshapiro SET_OPT_DEFAULT(StatFile, "statistics"); 263990792Sgshapiro } 264038032Speter else 264173188Sgshapiro { 264290792Sgshapiro CANONIFY(val); 264338032Speter StatFile = newstr(val); 264473188Sgshapiro } 264538032Speter break; 264638032Speter 264738032Speter case 's': /* be super safe, even if expensive */ 264890792Sgshapiro if (tolower(*val) == 'i') 264990792Sgshapiro SuperSafe = SAFE_INTERACTIVE; 265090792Sgshapiro else 265190792Sgshapiro SuperSafe = atobool(val) ? SAFE_REALLY : SAFE_NO; 265238032Speter break; 265338032Speter 265438032Speter case 'T': /* queue timeout */ 265538032Speter p = strchr(val, '/'); 265638032Speter if (p != NULL) 265738032Speter { 265838032Speter *p++ = '\0'; 265964562Sgshapiro settimeout("queuewarn", p, sticky); 266038032Speter } 266164562Sgshapiro settimeout("queuereturn", val, sticky); 266238032Speter break; 266338032Speter 266438032Speter case 't': /* time zone name */ 266538032Speter TimeZoneSpec = newstr(val); 266638032Speter break; 266738032Speter 266838032Speter case 'U': /* location of user database */ 266938032Speter UdbSpec = newstr(val); 267038032Speter break; 267138032Speter 267238032Speter case 'u': /* set default uid */ 267338032Speter for (p = val; *p != '\0'; p++) 267438032Speter { 267594334Sgshapiro# if _FFR_DOTTED_USERNAMES 267690792Sgshapiro if (*p == '/' || *p == ':') 267794334Sgshapiro# else /* _FFR_DOTTED_USERNAMES */ 267838032Speter if (*p == '.' || *p == '/' || *p == ':') 267994334Sgshapiro# endif /* _FFR_DOTTED_USERNAMES */ 268038032Speter { 268138032Speter *p++ = '\0'; 268238032Speter break; 268338032Speter } 268438032Speter } 268538032Speter if (isascii(*val) && isdigit(*val)) 268638032Speter { 268738032Speter DefUid = atoi(val); 268838032Speter setdefuser(); 268938032Speter } 269038032Speter else 269138032Speter { 269238032Speter register struct passwd *pw; 269338032Speter 269438032Speter DefUid = -1; 269538032Speter pw = sm_getpwnam(val); 269638032Speter if (pw == NULL) 269771345Sgshapiro { 269838032Speter syserr("readcf: option u: unknown user %s", val); 269971345Sgshapiro break; 270071345Sgshapiro } 270138032Speter else 270238032Speter { 270338032Speter DefUid = pw->pw_uid; 270438032Speter DefGid = pw->pw_gid; 270538032Speter DefUser = newstr(pw->pw_name); 270638032Speter } 270738032Speter } 270838032Speter 270990792Sgshapiro# ifdef UID_MAX 271038032Speter if (DefUid > UID_MAX) 271138032Speter { 271238032Speter syserr("readcf: option u: uid value (%ld) > UID_MAX (%ld); ignored", 271390792Sgshapiro (long)DefUid, (long)UID_MAX); 271471345Sgshapiro break; 271538032Speter } 271690792Sgshapiro# endif /* UID_MAX */ 271738032Speter 271838032Speter /* handle the group if it is there */ 271938032Speter if (*p == '\0') 272038032Speter break; 272138032Speter val = p; 272238032Speter goto g_opt; 272338032Speter 272438032Speter case 'V': /* fallback MX host */ 272538032Speter if (val[0] != '\0') 272638032Speter FallBackMX = newstr(val); 272738032Speter break; 272838032Speter 272938032Speter case 'v': /* run in verbose mode */ 273038032Speter Verbose = atobool(val) ? 1 : 0; 273138032Speter break; 273238032Speter 273338032Speter case 'w': /* if we are best MX, try host directly */ 273438032Speter TryNullMXList = atobool(val); 273538032Speter break; 273638032Speter 273738032Speter /* 'W' available -- was wizard password */ 273838032Speter 273938032Speter case 'x': /* load avg at which to auto-queue msgs */ 274038032Speter QueueLA = atoi(val); 274138032Speter break; 274238032Speter 274390792Sgshapiro case 'X': /* load avg at which to auto-reject connections */ 274438032Speter RefuseLA = atoi(val); 274538032Speter break; 274638032Speter 274790792Sgshapiro case O_DELAY_LA: /* load avg at which to delay connections */ 274890792Sgshapiro DelayLA = atoi(val); 274990792Sgshapiro break; 275090792Sgshapiro 275138032Speter case 'y': /* work recipient factor */ 275238032Speter WkRecipFact = atoi(val); 275338032Speter break; 275438032Speter 275538032Speter case 'Y': /* fork jobs during queue runs */ 275638032Speter ForkQueueRuns = atobool(val); 275738032Speter break; 275838032Speter 275938032Speter case 'z': /* work message class factor */ 276038032Speter WkClassFact = atoi(val); 276138032Speter break; 276238032Speter 276338032Speter case 'Z': /* work time factor */ 276438032Speter WkTimeFact = atoi(val); 276538032Speter break; 276638032Speter 276764562Sgshapiro 276894334Sgshapiro#if _FFR_QUEUE_GROUP_SORTORDER 276994334Sgshapiro /* coordinate this with makequeue() */ 277094334Sgshapiro#endif /* _FFR_QUEUE_GROUP_SORTORDER */ 277138032Speter case O_QUEUESORTORD: /* queue sorting order */ 277238032Speter switch (*val) 277338032Speter { 277490792Sgshapiro case 'f': /* File Name */ 277590792Sgshapiro case 'F': 277690792Sgshapiro QueueSortOrder = QSO_BYFILENAME; 277790792Sgshapiro break; 277890792Sgshapiro 277938032Speter case 'h': /* Host first */ 278038032Speter case 'H': 278164562Sgshapiro QueueSortOrder = QSO_BYHOST; 278238032Speter break; 278338032Speter 278490792Sgshapiro case 'm': /* Modification time */ 278590792Sgshapiro case 'M': 278690792Sgshapiro QueueSortOrder = QSO_BYMODTIME; 278790792Sgshapiro break; 278890792Sgshapiro 278938032Speter case 'p': /* Priority order */ 279038032Speter case 'P': 279164562Sgshapiro QueueSortOrder = QSO_BYPRIORITY; 279238032Speter break; 279338032Speter 279438032Speter case 't': /* Submission time */ 279538032Speter case 'T': 279664562Sgshapiro QueueSortOrder = QSO_BYTIME; 279738032Speter break; 279838032Speter 279990792Sgshapiro case 'r': /* Random */ 280090792Sgshapiro case 'R': 280190792Sgshapiro QueueSortOrder = QSO_RANDOM; 280264562Sgshapiro break; 280364562Sgshapiro 280490792Sgshapiro#if _FFR_RHS 280590792Sgshapiro case 's': /* Shuffled host name */ 280690792Sgshapiro case 'S': 280790792Sgshapiro QueueSortOrder = QSO_BYSHUFFLE; 280890792Sgshapiro break; 280990792Sgshapiro#endif /* _FFR_RHS */ 281090792Sgshapiro 281138032Speter default: 281238032Speter syserr("Invalid queue sort order \"%s\"", val); 281338032Speter } 281438032Speter break; 281538032Speter 281664562Sgshapiro#if _FFR_QUEUEDELAY 281764562Sgshapiro case O_QUEUEDELAY: /* queue delay algorithm */ 281864562Sgshapiro switch (*val) 281964562Sgshapiro { 282064562Sgshapiro case 'e': /* exponential */ 282164562Sgshapiro case 'E': 282264562Sgshapiro QueueAlg = QD_EXP; 282364562Sgshapiro QueueInitDelay = 10 MINUTES; 282464562Sgshapiro QueueMaxDelay = 2 HOURS; 282564562Sgshapiro p = strchr(val, '/'); 282664562Sgshapiro if (p != NULL) 282764562Sgshapiro { 282864562Sgshapiro char *q; 282964562Sgshapiro 283064562Sgshapiro *p++ = '\0'; 283164562Sgshapiro q = strchr(p, '/'); 283264562Sgshapiro if (q != NULL) 283364562Sgshapiro *q++ = '\0'; 283464562Sgshapiro QueueInitDelay = convtime(p, 's'); 283564562Sgshapiro if (q != NULL) 283664562Sgshapiro { 283764562Sgshapiro QueueMaxDelay = convtime(q, 's'); 283864562Sgshapiro } 283964562Sgshapiro } 284064562Sgshapiro break; 284164562Sgshapiro 284264562Sgshapiro case 'l': /* linear */ 284364562Sgshapiro case 'L': 284464562Sgshapiro QueueAlg = QD_LINEAR; 284564562Sgshapiro break; 284664562Sgshapiro 284764562Sgshapiro default: 284864562Sgshapiro syserr("Invalid queue delay algorithm \"%s\"", val); 284964562Sgshapiro } 285064562Sgshapiro break; 285164562Sgshapiro#endif /* _FFR_QUEUEDELAY */ 285264562Sgshapiro 285338032Speter case O_HOSTSFILE: /* pathname of /etc/hosts file */ 285490792Sgshapiro CANONIFY(val); 285538032Speter HostsFile = newstr(val); 285638032Speter break; 285738032Speter 285838032Speter case O_MQA: /* minimum queue age between deliveries */ 285938032Speter MinQueueAge = convtime(val, 'm'); 286038032Speter break; 286138032Speter 286238032Speter case O_DEFCHARSET: /* default character set for mimefying */ 286390792Sgshapiro DefaultCharSet = newstr(denlstring(val, true, true)); 286438032Speter break; 286538032Speter 286638032Speter case O_SSFILE: /* service switch file */ 286790792Sgshapiro CANONIFY(val); 286838032Speter ServiceSwitchFile = newstr(val); 286938032Speter break; 287038032Speter 287138032Speter case O_DIALDELAY: /* delay for dial-on-demand operation */ 287238032Speter DialDelay = convtime(val, 's'); 287338032Speter break; 287438032Speter 287538032Speter case O_NORCPTACTION: /* what to do if no recipient */ 287690792Sgshapiro if (sm_strcasecmp(val, "none") == 0) 287738032Speter NoRecipientAction = NRA_NO_ACTION; 287890792Sgshapiro else if (sm_strcasecmp(val, "add-to") == 0) 287938032Speter NoRecipientAction = NRA_ADD_TO; 288090792Sgshapiro else if (sm_strcasecmp(val, "add-apparently-to") == 0) 288138032Speter NoRecipientAction = NRA_ADD_APPARENTLY_TO; 288290792Sgshapiro else if (sm_strcasecmp(val, "add-bcc") == 0) 288338032Speter NoRecipientAction = NRA_ADD_BCC; 288490792Sgshapiro else if (sm_strcasecmp(val, "add-to-undisclosed") == 0) 288538032Speter NoRecipientAction = NRA_ADD_TO_UNDISCLOSED; 288638032Speter else 288738032Speter syserr("Invalid NoRecipientAction: %s", val); 288838032Speter break; 288938032Speter 289038032Speter case O_SAFEFILEENV: /* chroot() environ for writing to files */ 289194334Sgshapiro if (*val == '\0') 289294334Sgshapiro break; 289394334Sgshapiro 289494334Sgshapiro /* strip trailing slashes */ 289594334Sgshapiro p = val + strlen(val) - 1; 289694334Sgshapiro while (p >= val && *p == '/') 289794334Sgshapiro *p-- = '\0'; 289894334Sgshapiro 289994334Sgshapiro if (*val == '\0') 290094334Sgshapiro break; 290194334Sgshapiro 290238032Speter SafeFileEnv = newstr(val); 290338032Speter break; 290438032Speter 290538032Speter case O_MAXMSGSIZE: /* maximum message size */ 290638032Speter MaxMessageSize = atol(val); 290738032Speter break; 290838032Speter 290938032Speter case O_COLONOKINADDR: /* old style handling of colon addresses */ 291038032Speter ColonOkInAddr = atobool(val); 291138032Speter break; 291238032Speter 291338032Speter case O_MAXQUEUERUN: /* max # of jobs in a single queue run */ 291490792Sgshapiro MaxQueueRun = atoi(val); 291538032Speter break; 291638032Speter 291738032Speter case O_MAXCHILDREN: /* max # of children of daemon */ 291838032Speter MaxChildren = atoi(val); 291938032Speter break; 292038032Speter 292190792Sgshapiro case O_MAXQUEUECHILDREN: /* max # of children of daemon */ 292290792Sgshapiro MaxQueueChildren = atoi(val); 292390792Sgshapiro break; 292490792Sgshapiro 292590792Sgshapiro case O_MAXRUNNERSPERQUEUE: /* max # runners in a queue group */ 292690792Sgshapiro MaxRunnersPerQueue = atoi(val); 292790792Sgshapiro break; 292890792Sgshapiro 292990792Sgshapiro case O_NICEQUEUERUN: /* nice queue runs */ 293090792Sgshapiro#if !HASNICE 293190792Sgshapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 293290792Sgshapiro "Warning: NiceQueueRun set on system that doesn't support nice()\n"); 293390792Sgshapiro#endif /* !HASNICE */ 293490792Sgshapiro 293590792Sgshapiro /* XXX do we want to check the range? > 0 ? */ 293690792Sgshapiro NiceQueueRun = atoi(val); 293790792Sgshapiro break; 293890792Sgshapiro 293994334Sgshapiro case O_SHMKEY: /* shared memory key */ 294090792Sgshapiro#if SM_CONF_SHM 294190792Sgshapiro ShmKey = atol(val); 294290792Sgshapiro#else /* SM_CONF_SHM */ 294390792Sgshapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 294490792Sgshapiro "Warning: Option: %s requires shared memory support (-DSM_CONF_SHM)\n", 294590792Sgshapiro OPTNAME); 294690792Sgshapiro#endif /* SM_CONF_SHM */ 294790792Sgshapiro break; 294890792Sgshapiro 294994334Sgshapiro#if _FFR_SELECT_SHM 295094334Sgshapiro case O_SHMKEYFILE: /* shared memory key file */ 295194334Sgshapiro# if SM_CONF_SHM 295298841Sgshapiro SET_STRING_EXP(ShmKeyFile); 295394334Sgshapiro# else /* SM_CONF_SHM */ 295494334Sgshapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 295594334Sgshapiro "Warning: Option: %s requires shared memory support (-DSM_CONF_SHM)\n", 295694334Sgshapiro OPTNAME); 295798841Sgshapiro break; 295894334Sgshapiro# endif /* SM_CONF_SHM */ 295994334Sgshapiro#endif /* _FFR_SELECT_SHM */ 296094334Sgshapiro 296164562Sgshapiro#if _FFR_MAX_FORWARD_ENTRIES 296264562Sgshapiro case O_MAXFORWARD: /* max # of forward entries */ 296364562Sgshapiro MaxForwardEntries = atoi(val); 296464562Sgshapiro break; 296564562Sgshapiro#endif /* _FFR_MAX_FORWARD_ENTRIES */ 296664562Sgshapiro 296738032Speter case O_KEEPCNAMES: /* don't expand CNAME records */ 296838032Speter DontExpandCnames = atobool(val); 296938032Speter break; 297038032Speter 297138032Speter case O_MUSTQUOTE: /* must quote these characters in phrases */ 297290792Sgshapiro (void) sm_strlcpy(buf, "@,;:\\()[]", sizeof buf); 297390792Sgshapiro if (strlen(val) < sizeof buf - 10) 297490792Sgshapiro (void) sm_strlcat(buf, val, sizeof buf); 297564562Sgshapiro else 297690792Sgshapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 297790792Sgshapiro "Warning: MustQuoteChars too long, ignored.\n"); 297838032Speter MustQuoteChars = newstr(buf); 297938032Speter break; 298038032Speter 298138032Speter case O_SMTPGREETING: /* SMTP greeting message (old $e macro) */ 298238032Speter SmtpGreeting = newstr(munchstring(val, NULL, '\0')); 298338032Speter break; 298438032Speter 298538032Speter case O_UNIXFROM: /* UNIX From_ line (old $l macro) */ 298638032Speter UnixFromLine = newstr(munchstring(val, NULL, '\0')); 298738032Speter break; 298838032Speter 298938032Speter case O_OPCHARS: /* operator characters (old $o macro) */ 299064562Sgshapiro if (OperatorChars != NULL) 299190792Sgshapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 299290792Sgshapiro "Warning: OperatorChars is being redefined.\n It should only be set before ruleset definitions.\n"); 299338032Speter OperatorChars = newstr(munchstring(val, NULL, '\0')); 299438032Speter break; 299538032Speter 299638032Speter case O_DONTINITGRPS: /* don't call initgroups(3) */ 299738032Speter DontInitGroups = atobool(val); 299838032Speter break; 299938032Speter 300038032Speter case O_SLFH: /* make sure from fits on one line */ 300138032Speter SingleLineFromHeader = atobool(val); 300238032Speter break; 300338032Speter 300438032Speter case O_ABH: /* allow HELO commands with syntax errors */ 300538032Speter AllowBogusHELO = atobool(val); 300638032Speter break; 300738032Speter 300838032Speter case O_CONNTHROT: /* connection rate throttle */ 300938032Speter ConnRateThrottle = atoi(val); 301038032Speter break; 301138032Speter 301238032Speter case O_UGW: /* group writable files are unsafe */ 301338032Speter if (!atobool(val)) 301464562Sgshapiro { 301564562Sgshapiro setbitn(DBS_GROUPWRITABLEFORWARDFILESAFE, 301664562Sgshapiro DontBlameSendmail); 301764562Sgshapiro setbitn(DBS_GROUPWRITABLEINCLUDEFILESAFE, 301864562Sgshapiro DontBlameSendmail); 301964562Sgshapiro } 302038032Speter break; 302138032Speter 302238032Speter case O_DBLBOUNCE: /* address to which to send double bounces */ 302390792Sgshapiro DoubleBounceAddr = newstr(val); 302438032Speter break; 302538032Speter 302638032Speter case O_HSDIR: /* persistent host status directory */ 302738032Speter if (val[0] != '\0') 302873188Sgshapiro { 302990792Sgshapiro CANONIFY(val); 303038032Speter HostStatDir = newstr(val); 303173188Sgshapiro } 303238032Speter break; 303338032Speter 303438032Speter case O_SINGTHREAD: /* single thread deliveries (requires hsdir) */ 303538032Speter SingleThreadDelivery = atobool(val); 303638032Speter break; 303738032Speter 303838032Speter case O_RUNASUSER: /* run bulk of code as this user */ 303938032Speter for (p = val; *p != '\0'; p++) 304038032Speter { 304194334Sgshapiro# if _FFR_DOTTED_USERNAMES 304290792Sgshapiro if (*p == '/' || *p == ':') 304394334Sgshapiro# else /* _FFR_DOTTED_USERNAMES */ 304438032Speter if (*p == '.' || *p == '/' || *p == ':') 304594334Sgshapiro# endif /* _FFR_DOTTED_USERNAMES */ 304638032Speter { 304738032Speter *p++ = '\0'; 304838032Speter break; 304938032Speter } 305038032Speter } 305138032Speter if (isascii(*val) && isdigit(*val)) 305238032Speter { 305338032Speter if (can_setuid) 305438032Speter RunAsUid = atoi(val); 305538032Speter } 305638032Speter else 305738032Speter { 305838032Speter register struct passwd *pw; 305938032Speter 306038032Speter pw = sm_getpwnam(val); 306138032Speter if (pw == NULL) 306271345Sgshapiro { 306338032Speter syserr("readcf: option RunAsUser: unknown user %s", val); 306471345Sgshapiro break; 306571345Sgshapiro } 306638032Speter else if (can_setuid) 306738032Speter { 306838032Speter if (*p == '\0') 306938032Speter RunAsUserName = newstr(val); 307038032Speter RunAsUid = pw->pw_uid; 307138032Speter RunAsGid = pw->pw_gid; 307238032Speter } 307390792Sgshapiro else if (EffGid == pw->pw_gid) 307490792Sgshapiro RunAsGid = pw->pw_gid; 307590792Sgshapiro else if (UseMSP && *p == '\0') 307690792Sgshapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 307790792Sgshapiro "WARNING: RunAsGid for MSP ignored, check group ids (egid=%d, want=%d)\n", 307890792Sgshapiro (int) EffGid, 307990792Sgshapiro (int) pw->pw_gid); 308038032Speter } 308190792Sgshapiro# ifdef UID_MAX 308238032Speter if (RunAsUid > UID_MAX) 308338032Speter { 308438032Speter syserr("readcf: option RunAsUser: uid value (%ld) > UID_MAX (%ld); ignored", 308571345Sgshapiro (long) RunAsUid, (long) UID_MAX); 308671345Sgshapiro break; 308738032Speter } 308890792Sgshapiro# endif /* UID_MAX */ 308938032Speter if (*p != '\0') 309038032Speter { 309138032Speter if (isascii(*p) && isdigit(*p)) 309238032Speter { 309390792Sgshapiro gid_t runasgid; 309490792Sgshapiro 309590792Sgshapiro runasgid = (gid_t) atoi(p); 309690792Sgshapiro if (can_setuid || EffGid == runasgid) 309790792Sgshapiro RunAsGid = runasgid; 309890792Sgshapiro else if (UseMSP) 309990792Sgshapiro (void) sm_io_fprintf(smioout, 310090792Sgshapiro SM_TIME_DEFAULT, 310190792Sgshapiro "WARNING: RunAsGid for MSP ignored, check group ids (egid=%d, want=%d)\n", 310290792Sgshapiro (int) EffGid, 310390792Sgshapiro (int) runasgid); 310438032Speter } 310538032Speter else 310638032Speter { 310738032Speter register struct group *gr; 310864562Sgshapiro 310938032Speter gr = getgrnam(p); 311038032Speter if (gr == NULL) 311138032Speter syserr("readcf: option RunAsUser: unknown group %s", 311238032Speter p); 311390792Sgshapiro else if (can_setuid || EffGid == gr->gr_gid) 311438032Speter RunAsGid = gr->gr_gid; 311590792Sgshapiro else if (UseMSP) 311690792Sgshapiro (void) sm_io_fprintf(smioout, 311790792Sgshapiro SM_TIME_DEFAULT, 311890792Sgshapiro "WARNING: RunAsGid for MSP ignored, check group ids (egid=%d, want=%d)\n", 311990792Sgshapiro (int) EffGid, 312090792Sgshapiro (int) gr->gr_gid); 312138032Speter } 312238032Speter } 312338032Speter if (tTd(47, 5)) 312490792Sgshapiro sm_dprintf("readcf: RunAsUser = %d:%d\n", 312590792Sgshapiro (int) RunAsUid, (int) RunAsGid); 312638032Speter break; 312738032Speter 312838032Speter case O_DSN_RRT: 312938032Speter RrtImpliesDsn = atobool(val); 313038032Speter break; 313138032Speter 313238032Speter case O_PIDFILE: 313390792Sgshapiro PSTRSET(PidFile, val); 313438032Speter break; 313538032Speter 313690792Sgshapiro case O_DONTBLAMESENDMAIL: 313738032Speter p = val; 313838032Speter for (;;) 313938032Speter { 314038032Speter register struct dbsval *dbs; 314138032Speter extern struct dbsval DontBlameSendmailValues[]; 314238032Speter 314338032Speter while (isascii(*p) && (isspace(*p) || ispunct(*p))) 314438032Speter p++; 314538032Speter if (*p == '\0') 314638032Speter break; 314738032Speter val = p; 314838032Speter while (isascii(*p) && isalnum(*p)) 314938032Speter p++; 315038032Speter if (*p != '\0') 315138032Speter *p++ = '\0'; 315238032Speter 315338032Speter for (dbs = DontBlameSendmailValues; 315438032Speter dbs->dbs_name != NULL; dbs++) 315538032Speter { 315690792Sgshapiro if (sm_strcasecmp(val, dbs->dbs_name) == 0) 315738032Speter break; 315838032Speter } 315938032Speter if (dbs->dbs_name == NULL) 316038032Speter syserr("readcf: DontBlameSendmail option: %s unrecognized", val); 316138032Speter else if (dbs->dbs_flag == DBS_SAFE) 316264562Sgshapiro clrbitmap(DontBlameSendmail); 316338032Speter else 316464562Sgshapiro setbitn(dbs->dbs_flag, DontBlameSendmail); 316538032Speter } 316690792Sgshapiro sticky = false; 316738032Speter break; 316838032Speter 316938032Speter case O_DPI: 317090792Sgshapiro if (sm_strcasecmp(val, "loopback") == 0) 317190792Sgshapiro DontProbeInterfaces = DPI_SKIPLOOPBACK; 317290792Sgshapiro else if (atobool(val)) 317390792Sgshapiro DontProbeInterfaces = DPI_PROBENONE; 317490792Sgshapiro else 317590792Sgshapiro DontProbeInterfaces = DPI_PROBEALL; 317638032Speter break; 317738032Speter 317838032Speter case O_MAXRCPT: 317938032Speter MaxRcptPerMsg = atoi(val); 318038032Speter break; 318138032Speter 318290792Sgshapiro case O_RCPTTHROT: 318390792Sgshapiro BadRcptThrottle = atoi(val); 318490792Sgshapiro break; 318590792Sgshapiro 318638032Speter case O_DEADLETTER: 318790792Sgshapiro CANONIFY(val); 318890792Sgshapiro PSTRSET(DeadLetterDrop, val); 318938032Speter break; 319038032Speter 319138032Speter#if _FFR_DONTLOCKFILESFORREAD_OPTION 319238032Speter case O_DONTLOCK: 319338032Speter DontLockReadFiles = atobool(val); 319438032Speter break; 319564562Sgshapiro#endif /* _FFR_DONTLOCKFILESFORREAD_OPTION */ 319638032Speter 319738032Speter case O_MAXALIASRCSN: 319838032Speter MaxAliasRecursion = atoi(val); 319938032Speter break; 320038032Speter 320138032Speter case O_CNCTONLYTO: 320238032Speter /* XXX should probably use gethostbyname */ 320364562Sgshapiro#if NETINET || NETINET6 320490792Sgshapiro ConnectOnlyTo.sa.sa_family = AF_UNSPEC; 320564562Sgshapiro# if NETINET6 320690792Sgshapiro if (anynet_pton(AF_INET6, val, 320790792Sgshapiro &ConnectOnlyTo.sin6.sin6_addr) != 1) 320864562Sgshapiro ConnectOnlyTo.sa.sa_family = AF_INET6; 320964562Sgshapiro else 321064562Sgshapiro# endif /* NETINET6 */ 321190792Sgshapiro# if NETINET 321264562Sgshapiro { 321364562Sgshapiro ConnectOnlyTo.sin.sin_addr.s_addr = inet_addr(val); 321490792Sgshapiro if (ConnectOnlyTo.sin.sin_addr.s_addr != INADDR_NONE) 321590792Sgshapiro ConnectOnlyTo.sa.sa_family = AF_INET; 321664562Sgshapiro } 321790792Sgshapiro 321890792Sgshapiro# endif /* NETINET */ 321990792Sgshapiro if (ConnectOnlyTo.sa.sa_family == AF_UNSPEC) 322090792Sgshapiro { 322190792Sgshapiro syserr("readcf: option ConnectOnlyTo: invalid IP address %s", 322290792Sgshapiro val); 322390792Sgshapiro break; 322490792Sgshapiro } 322564562Sgshapiro#endif /* NETINET || NETINET6 */ 322638032Speter break; 322738032Speter 322842575Speter case O_TRUSTUSER: 322990792Sgshapiro# if !HASFCHOWN && !defined(_FFR_DROP_TRUSTUSER_WARNING) 323090792Sgshapiro if (!UseMSP) 323190792Sgshapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 323290792Sgshapiro "readcf: option TrustedUser may cause problems on systems\n which do not support fchown() if UseMSP is not set.\n"); 323390792Sgshapiro# endif /* !HASFCHOWN && !defined(_FFR_DROP_TRUSTUSER_WARNING) */ 323438032Speter if (isascii(*val) && isdigit(*val)) 323542575Speter TrustedUid = atoi(val); 323638032Speter else 323738032Speter { 323838032Speter register struct passwd *pw; 323938032Speter 324042575Speter TrustedUid = 0; 324138032Speter pw = sm_getpwnam(val); 324238032Speter if (pw == NULL) 324371345Sgshapiro { 324442575Speter syserr("readcf: option TrustedUser: unknown user %s", val); 324571345Sgshapiro break; 324671345Sgshapiro } 324738032Speter else 324842575Speter TrustedUid = pw->pw_uid; 324938032Speter } 325038032Speter 325164562Sgshapiro# ifdef UID_MAX 325242575Speter if (TrustedUid > UID_MAX) 325338032Speter { 325442575Speter syserr("readcf: option TrustedUser: uid value (%ld) > UID_MAX (%ld)", 325571345Sgshapiro (long) TrustedUid, (long) UID_MAX); 325642575Speter TrustedUid = 0; 325738032Speter } 325864562Sgshapiro# endif /* UID_MAX */ 325938032Speter break; 326038032Speter 326142575Speter case O_MAXMIMEHDRLEN: 326242575Speter p = strchr(val, '/'); 326342575Speter if (p != NULL) 326442575Speter *p++ = '\0'; 326542575Speter MaxMimeHeaderLength = atoi(val); 326642575Speter if (p != NULL && *p != '\0') 326742575Speter MaxMimeFieldLength = atoi(p); 326842575Speter else 326942575Speter MaxMimeFieldLength = MaxMimeHeaderLength / 2; 327042575Speter 327142575Speter if (MaxMimeHeaderLength < 0) 327242575Speter MaxMimeHeaderLength = 0; 327342575Speter else if (MaxMimeHeaderLength < 128) 327490792Sgshapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 327590792Sgshapiro "Warning: MaxMimeHeaderLength: header length limit set lower than 128\n"); 327642575Speter 327742575Speter if (MaxMimeFieldLength < 0) 327842575Speter MaxMimeFieldLength = 0; 327942575Speter else if (MaxMimeFieldLength < 40) 328090792Sgshapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 328190792Sgshapiro "Warning: MaxMimeHeaderLength: field length limit set lower than 40\n"); 328242575Speter break; 328342575Speter 328442575Speter case O_CONTROLSOCKET: 328590792Sgshapiro PSTRSET(ControlSocketName, val); 328642575Speter break; 328742575Speter 328843730Speter case O_MAXHDRSLEN: 328943730Speter MaxHeadersLength = atoi(val); 329043148Speter 329143730Speter if (MaxHeadersLength > 0 && 329243730Speter MaxHeadersLength < (MAXHDRSLEN / 2)) 329390792Sgshapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 329490792Sgshapiro "Warning: MaxHeadersLength: headers length limit set lower than %d\n", 329590792Sgshapiro (MAXHDRSLEN / 2)); 329643148Speter break; 329743148Speter 329864562Sgshapiro case O_PROCTITLEPREFIX: 329990792Sgshapiro PSTRSET(ProcTitlePrefix, val); 330064562Sgshapiro break; 330164562Sgshapiro 330264562Sgshapiro#if SASL 330364562Sgshapiro case O_SASLINFO: 330490792Sgshapiro# if _FFR_ALLOW_SASLINFO 330564562Sgshapiro /* 330690792Sgshapiro ** Allow users to select their own authinfo file 330790792Sgshapiro ** under certain circumstances, otherwise just ignore 330890792Sgshapiro ** the option. If the option isn't ignored, several 330990792Sgshapiro ** commands don't work very well, e.g., mailq. 331064562Sgshapiro ** However, this is not a "perfect" solution. 331164562Sgshapiro ** If mail is queued, the authentication info 331264562Sgshapiro ** will not be used in subsequent delivery attempts. 331364562Sgshapiro ** If we really want to support this, then it has 331464562Sgshapiro ** to be stored in the queue file. 331564562Sgshapiro */ 331664562Sgshapiro if (!bitset(SUBMIT_MSA, SubmitMode) && RealUid != 0 && 331764562Sgshapiro RunAsUid != RealUid) 331864562Sgshapiro break; 331990792Sgshapiro# endif /* _FFR_ALLOW_SASLINFO */ 332090792Sgshapiro PSTRSET(SASLInfo, val); 332164562Sgshapiro break; 332264562Sgshapiro 332364562Sgshapiro case O_SASLMECH: 332464562Sgshapiro if (AuthMechanisms != NULL) 332590792Sgshapiro sm_free(AuthMechanisms); /* XXX */ 332664562Sgshapiro if (*val != '\0') 332764562Sgshapiro AuthMechanisms = newstr(val); 332864562Sgshapiro else 332964562Sgshapiro AuthMechanisms = NULL; 333064562Sgshapiro break; 333164562Sgshapiro 333264562Sgshapiro case O_SASLOPTS: 333364562Sgshapiro while (val != NULL && *val != '\0') 333464562Sgshapiro { 333590792Sgshapiro switch (*val) 333664562Sgshapiro { 333764562Sgshapiro case 'A': 333864562Sgshapiro SASLOpts |= SASL_AUTH_AUTH; 333964562Sgshapiro break; 334064562Sgshapiro case 'a': 334164562Sgshapiro SASLOpts |= SASL_SEC_NOACTIVE; 334264562Sgshapiro break; 334364562Sgshapiro case 'c': 334464562Sgshapiro SASLOpts |= SASL_SEC_PASS_CREDENTIALS; 334564562Sgshapiro break; 334664562Sgshapiro case 'd': 334764562Sgshapiro SASLOpts |= SASL_SEC_NODICTIONARY; 334864562Sgshapiro break; 334964562Sgshapiro case 'f': 335064562Sgshapiro SASLOpts |= SASL_SEC_FORWARD_SECRECY; 335164562Sgshapiro break; 335298121Sgshapiro# if _FFR_SASL_OPT_M 335398121Sgshapiro/* to be activated in 8.13 */ 335498121Sgshapiro# if SASL >= 20101 335598121Sgshapiro case 'm': 335698121Sgshapiro SASLOpts |= SASL_SEC_MUTUAL_AUTH; 335798121Sgshapiro break; 335898121Sgshapiro# endif /* SASL >= 20101 */ 335998121Sgshapiro# endif /* _FFR_SASL_OPT_M */ 336064562Sgshapiro case 'p': 336164562Sgshapiro SASLOpts |= SASL_SEC_NOPLAINTEXT; 336264562Sgshapiro break; 336364562Sgshapiro case 'y': 336464562Sgshapiro SASLOpts |= SASL_SEC_NOANONYMOUS; 336564562Sgshapiro break; 336690792Sgshapiro case ' ': /* ignore */ 336790792Sgshapiro case '\t': /* ignore */ 336890792Sgshapiro case ',': /* ignore */ 336990792Sgshapiro break; 337064562Sgshapiro default: 337190792Sgshapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 337290792Sgshapiro "Warning: Option: %s unknown parameter '%c'\n", 337390792Sgshapiro OPTNAME, 337490792Sgshapiro (isascii(*val) && 337590792Sgshapiro isprint(*val)) 337690792Sgshapiro ? *val : '?'); 337764562Sgshapiro break; 337864562Sgshapiro } 337964562Sgshapiro ++val; 338064562Sgshapiro val = strpbrk(val, ", \t"); 338164562Sgshapiro if (val != NULL) 338264562Sgshapiro ++val; 338364562Sgshapiro } 338464562Sgshapiro break; 338590792Sgshapiro case O_SASLBITS: 338690792Sgshapiro MaxSLBits = atoi(val); 338790792Sgshapiro break; 338864562Sgshapiro 338964562Sgshapiro#else /* SASL */ 339064562Sgshapiro case O_SASLINFO: 339164562Sgshapiro case O_SASLMECH: 339264562Sgshapiro case O_SASLOPTS: 339390792Sgshapiro case O_SASLBITS: 339490792Sgshapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 339590792Sgshapiro "Warning: Option: %s requires SASL support (-DSASL)\n", 339690792Sgshapiro OPTNAME); 339764562Sgshapiro break; 339864562Sgshapiro#endif /* SASL */ 339964562Sgshapiro 340064562Sgshapiro#if STARTTLS 340164562Sgshapiro case O_SRVCERTFILE: 340290792Sgshapiro SET_STRING_EXP(SrvCERTfile); 340364562Sgshapiro case O_SRVKEYFILE: 340490792Sgshapiro SET_STRING_EXP(Srvkeyfile); 340564562Sgshapiro case O_CLTCERTFILE: 340690792Sgshapiro SET_STRING_EXP(CltCERTfile); 340764562Sgshapiro case O_CLTKEYFILE: 340890792Sgshapiro SET_STRING_EXP(Cltkeyfile); 340964562Sgshapiro case O_CACERTFILE: 341090792Sgshapiro SET_STRING_EXP(CACERTfile); 341164562Sgshapiro case O_CACERTPATH: 341290792Sgshapiro SET_STRING_EXP(CACERTpath); 341364562Sgshapiro case O_DHPARAMS: 341490792Sgshapiro SET_STRING_EXP(DHParams); 341590792Sgshapiro# if _FFR_TLS_1 341664562Sgshapiro case O_DHPARAMS5: 341790792Sgshapiro SET_STRING_EXP(DHParams5); 341890792Sgshapiro case O_CIPHERLIST: 341990792Sgshapiro SET_STRING_EXP(CipherList); 342090792Sgshapiro# endif /* _FFR_TLS_1 */ 342164562Sgshapiro 342290792Sgshapiro /* 342390792Sgshapiro ** XXX How about options per daemon/client instead of globally? 342490792Sgshapiro ** This doesn't work well for some options, e.g., no server cert, 342590792Sgshapiro ** but fine for others. 342690792Sgshapiro ** 342790792Sgshapiro ** XXX Some people may want different certs per server. 342890792Sgshapiro ** 342990792Sgshapiro ** See also srvfeatures() 343090792Sgshapiro */ 343190792Sgshapiro 343290792Sgshapiro case O_TLS_SRV_OPTS: 343390792Sgshapiro while (val != NULL && *val != '\0') 343490792Sgshapiro { 343590792Sgshapiro switch (*val) 343690792Sgshapiro { 343790792Sgshapiro case 'V': 343890792Sgshapiro TLS_Srv_Opts |= TLS_I_NO_VRFY; 343990792Sgshapiro break; 344090792Sgshapiro# if _FFR_TLS_1 344190792Sgshapiro /* 344290792Sgshapiro ** Server without a cert? That works only if 344390792Sgshapiro ** AnonDH is enabled as cipher, which is not in the 344490792Sgshapiro ** default list. Hence the CipherList option must 344590792Sgshapiro ** be available. Moreover: which clients support this 344690792Sgshapiro ** besides sendmail with this setting? 344790792Sgshapiro */ 344890792Sgshapiro 344990792Sgshapiro case 'C': 345090792Sgshapiro TLS_Srv_Opts &= ~TLS_I_SRV_CERT; 345190792Sgshapiro break; 345290792Sgshapiro# endif /* _FFR_TLS_1 */ 345390792Sgshapiro case ' ': /* ignore */ 345490792Sgshapiro case '\t': /* ignore */ 345590792Sgshapiro case ',': /* ignore */ 345690792Sgshapiro break; 345790792Sgshapiro default: 345890792Sgshapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 345990792Sgshapiro "Warning: Option: %s unknown parameter '%c'\n", 346090792Sgshapiro OPTNAME, 346190792Sgshapiro (isascii(*val) && 346290792Sgshapiro isprint(*val)) 346390792Sgshapiro ? *val : '?'); 346490792Sgshapiro break; 346590792Sgshapiro } 346690792Sgshapiro ++val; 346790792Sgshapiro val = strpbrk(val, ", \t"); 346890792Sgshapiro if (val != NULL) 346990792Sgshapiro ++val; 347090792Sgshapiro } 347164562Sgshapiro break; 347264562Sgshapiro 347364562Sgshapiro case O_RANDFILE: 347490792Sgshapiro PSTRSET(RandFile, val); 347564562Sgshapiro break; 347664562Sgshapiro 347790792Sgshapiro#else /* STARTTLS */ 347864562Sgshapiro case O_SRVCERTFILE: 347964562Sgshapiro case O_SRVKEYFILE: 348064562Sgshapiro case O_CLTCERTFILE: 348164562Sgshapiro case O_CLTKEYFILE: 348264562Sgshapiro case O_CACERTFILE: 348364562Sgshapiro case O_CACERTPATH: 348464562Sgshapiro case O_DHPARAMS: 348590792Sgshapiro# if _FFR_TLS_1 348664562Sgshapiro case O_DHPARAMS5: 348764562Sgshapiro case O_CIPHERLIST: 348890792Sgshapiro# endif /* _FFR_TLS_1 */ 348964562Sgshapiro case O_RANDFILE: 349090792Sgshapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 349190792Sgshapiro "Warning: Option: %s requires TLS support\n", 349290792Sgshapiro OPTNAME); 349364562Sgshapiro break; 349464562Sgshapiro 349590792Sgshapiro#endif /* STARTTLS */ 349664562Sgshapiro 349764562Sgshapiro case O_CLIENTPORT: 349864562Sgshapiro setclientoptions(val); 349964562Sgshapiro break; 350064562Sgshapiro 350164562Sgshapiro case O_DF_BUFSIZE: 350264562Sgshapiro DataFileBufferSize = atoi(val); 350364562Sgshapiro break; 350464562Sgshapiro 350564562Sgshapiro case O_XF_BUFSIZE: 350664562Sgshapiro XscriptFileBufferSize = atoi(val); 350764562Sgshapiro break; 350864562Sgshapiro 350964562Sgshapiro case O_LDAPDEFAULTSPEC: 351090792Sgshapiro#if LDAPMAP 351164562Sgshapiro ldapmap_set_defaults(val); 351264562Sgshapiro#else /* LDAPMAP */ 351390792Sgshapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 351490792Sgshapiro "Warning: Option: %s requires LDAP support (-DLDAPMAP)\n", 351590792Sgshapiro OPTNAME); 351664562Sgshapiro#endif /* LDAPMAP */ 351764562Sgshapiro break; 351864562Sgshapiro 351964562Sgshapiro case O_INPUTMILTER: 352090792Sgshapiro#if MILTER 352164562Sgshapiro InputFilterList = newstr(val); 352290792Sgshapiro#else /* MILTER */ 352390792Sgshapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 352490792Sgshapiro "Warning: Option: %s requires Milter support (-DMILTER)\n", 352590792Sgshapiro OPTNAME); 352690792Sgshapiro#endif /* MILTER */ 352764562Sgshapiro break; 352864562Sgshapiro 352964562Sgshapiro case O_MILTER: 353090792Sgshapiro#if MILTER 353164562Sgshapiro milter_set_option(subopt, val, sticky); 353290792Sgshapiro#else /* MILTER */ 353390792Sgshapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 353490792Sgshapiro "Warning: Option: %s requires Milter support (-DMILTER)\n", 353590792Sgshapiro OPTNAME); 353690792Sgshapiro#endif /* MILTER */ 353764562Sgshapiro break; 353864562Sgshapiro 353964562Sgshapiro case O_QUEUE_FILE_MODE: /* queue file mode */ 354064562Sgshapiro QueueFileMode = atooct(val) & 0777; 354164562Sgshapiro break; 354264562Sgshapiro 354390792Sgshapiro case O_DLVR_MIN: /* deliver by minimum time */ 354490792Sgshapiro DeliverByMin = convtime(val, 's'); 354590792Sgshapiro break; 354690792Sgshapiro 354790792Sgshapiro /* modifiers {daemon_flags} for direct submissions */ 354890792Sgshapiro case O_DIRECTSUBMODIFIERS: 354990792Sgshapiro { 355090792Sgshapiro BITMAP256 m; /* ignored */ 355190792Sgshapiro extern ENVELOPE BlankEnvelope; 355290792Sgshapiro 355390792Sgshapiro macdefine(&BlankEnvelope.e_macro, A_PERM, 355490792Sgshapiro macid("{daemon_flags}"), 355590792Sgshapiro getmodifiers(val, m)); 355690792Sgshapiro } 355790792Sgshapiro break; 355890792Sgshapiro 355990792Sgshapiro case O_FASTSPLIT: 356090792Sgshapiro FastSplit = atoi(val); 356190792Sgshapiro break; 356290792Sgshapiro 356390792Sgshapiro case O_MBDB: 356490792Sgshapiro Mbdb = newstr(val); 356590792Sgshapiro break; 356690792Sgshapiro 356790792Sgshapiro case O_MSQ: 356890792Sgshapiro UseMSP = atobool(val); 356990792Sgshapiro break; 357090792Sgshapiro 357190792Sgshapiro#if _FFR_SOFT_BOUNCE 357290792Sgshapiro case O_SOFTBOUNCE: 357390792Sgshapiro SoftBounce = atobool(val); 357490792Sgshapiro break; 357590792Sgshapiro#endif /* _FFR_SOFT_BOUNCE */ 357690792Sgshapiro 357738032Speter default: 357838032Speter if (tTd(37, 1)) 357938032Speter { 358038032Speter if (isascii(opt) && isprint(opt)) 358190792Sgshapiro sm_dprintf("Warning: option %c unknown\n", opt); 358238032Speter else 358390792Sgshapiro sm_dprintf("Warning: option 0x%x unknown\n", opt); 358438032Speter } 358538032Speter break; 358638032Speter } 358764562Sgshapiro 358864562Sgshapiro /* 358964562Sgshapiro ** Options with suboptions are responsible for taking care 359064562Sgshapiro ** of sticky-ness (e.g., that a command line setting is kept 359164562Sgshapiro ** when reading in the sendmail.cf file). This has to be done 359264562Sgshapiro ** when the suboptions are parsed since each suboption must be 359364562Sgshapiro ** sticky, not the root option. 359464562Sgshapiro */ 359564562Sgshapiro 359664562Sgshapiro if (sticky && !bitset(OI_SUBOPT, o->o_flags)) 359738032Speter setbitn(opt, StickyOpt); 359838032Speter} 359990792Sgshapiro/* 360038032Speter** SETCLASS -- set a string into a class 360138032Speter** 360238032Speter** Parameters: 360338032Speter** class -- the class to put the string in. 360438032Speter** str -- the string to enter 360538032Speter** 360638032Speter** Returns: 360738032Speter** none. 360838032Speter** 360938032Speter** Side Effects: 361038032Speter** puts the word into the symbol table. 361138032Speter*/ 361238032Speter 361338032Spetervoid 361438032Spetersetclass(class, str) 361538032Speter int class; 361638032Speter char *str; 361738032Speter{ 361838032Speter register STAB *s; 361938032Speter 362064562Sgshapiro if ((*str & 0377) == MATCHCLASS) 362164562Sgshapiro { 362264562Sgshapiro int mid; 362364562Sgshapiro 362464562Sgshapiro str++; 362590792Sgshapiro mid = macid(str); 362671345Sgshapiro if (mid == 0) 362764562Sgshapiro return; 362864562Sgshapiro 362964562Sgshapiro if (tTd(37, 8)) 363090792Sgshapiro sm_dprintf("setclass(%s, $=%s)\n", 363190792Sgshapiro macname(class), macname(mid)); 363264562Sgshapiro copy_class(mid, class); 363364562Sgshapiro } 363464562Sgshapiro else 363564562Sgshapiro { 363664562Sgshapiro if (tTd(37, 8)) 363790792Sgshapiro sm_dprintf("setclass(%s, %s)\n", macname(class), str); 363864562Sgshapiro 363964562Sgshapiro s = stab(str, ST_CLASS, ST_ENTER); 364071345Sgshapiro setbitn(bitidx(class), s->s_class); 364164562Sgshapiro } 364238032Speter} 364390792Sgshapiro/* 364438032Speter** MAKEMAPENTRY -- create a map entry 364538032Speter** 364638032Speter** Parameters: 364738032Speter** line -- the config file line 364838032Speter** 364938032Speter** Returns: 365038032Speter** A pointer to the map that has been created. 365138032Speter** NULL if there was a syntax error. 365238032Speter** 365338032Speter** Side Effects: 365438032Speter** Enters the map into the dictionary. 365538032Speter*/ 365638032Speter 365738032SpeterMAP * 365838032Spetermakemapentry(line) 365938032Speter char *line; 366038032Speter{ 366138032Speter register char *p; 366238032Speter char *mapname; 366338032Speter char *classname; 366438032Speter register STAB *s; 366538032Speter STAB *class; 366638032Speter 366738032Speter for (p = line; isascii(*p) && isspace(*p); p++) 366838032Speter continue; 366938032Speter if (!(isascii(*p) && isalnum(*p))) 367038032Speter { 367138032Speter syserr("readcf: config K line: no map name"); 367238032Speter return NULL; 367338032Speter } 367438032Speter 367538032Speter mapname = p; 367638032Speter while ((isascii(*++p) && isalnum(*p)) || *p == '_' || *p == '.') 367738032Speter continue; 367838032Speter if (*p != '\0') 367938032Speter *p++ = '\0'; 368038032Speter while (isascii(*p) && isspace(*p)) 368138032Speter p++; 368238032Speter if (!(isascii(*p) && isalnum(*p))) 368338032Speter { 368438032Speter syserr("readcf: config K line, map %s: no map class", mapname); 368538032Speter return NULL; 368638032Speter } 368738032Speter classname = p; 368838032Speter while (isascii(*++p) && isalnum(*p)) 368938032Speter continue; 369038032Speter if (*p != '\0') 369138032Speter *p++ = '\0'; 369238032Speter while (isascii(*p) && isspace(*p)) 369338032Speter p++; 369438032Speter 369538032Speter /* look up the class */ 369638032Speter class = stab(classname, ST_MAPCLASS, ST_FIND); 369738032Speter if (class == NULL) 369838032Speter { 369990792Sgshapiro syserr("readcf: map %s: class %s not available", mapname, 370090792Sgshapiro classname); 370138032Speter return NULL; 370238032Speter } 370338032Speter 370438032Speter /* enter the map */ 370538032Speter s = stab(mapname, ST_MAP, ST_ENTER); 370638032Speter s->s_map.map_class = &class->s_mapclass; 370738032Speter s->s_map.map_mname = newstr(mapname); 370838032Speter 370938032Speter if (class->s_mapclass.map_parse(&s->s_map, p)) 371038032Speter s->s_map.map_mflags |= MF_VALID; 371138032Speter 371238032Speter if (tTd(37, 5)) 371338032Speter { 371490792Sgshapiro sm_dprintf("map %s, class %s, flags %lx, file %s,\n", 371590792Sgshapiro s->s_map.map_mname, s->s_map.map_class->map_cname, 371690792Sgshapiro s->s_map.map_mflags, s->s_map.map_file); 371790792Sgshapiro sm_dprintf("\tapp %s, domain %s, rebuild %s\n", 371890792Sgshapiro s->s_map.map_app, s->s_map.map_domain, 371990792Sgshapiro s->s_map.map_rebuild); 372038032Speter } 372138032Speter return &s->s_map; 372238032Speter} 372390792Sgshapiro/* 372438032Speter** STRTORWSET -- convert string to rewriting set number 372538032Speter** 372638032Speter** Parameters: 372738032Speter** p -- the pointer to the string to decode. 372838032Speter** endp -- if set, store the trailing delimiter here. 372938032Speter** stabmode -- ST_ENTER to create this entry, ST_FIND if 373038032Speter** it must already exist. 373138032Speter** 373238032Speter** Returns: 373338032Speter** The appropriate ruleset number. 373438032Speter** -1 if it is not valid (error already printed) 373538032Speter*/ 373638032Speter 373738032Speterint 373838032Speterstrtorwset(p, endp, stabmode) 373938032Speter char *p; 374038032Speter char **endp; 374138032Speter int stabmode; 374238032Speter{ 374338032Speter int ruleset; 374438032Speter static int nextruleset = MAXRWSETS; 374538032Speter 374638032Speter while (isascii(*p) && isspace(*p)) 374738032Speter p++; 374838032Speter if (!isascii(*p)) 374938032Speter { 375038032Speter syserr("invalid ruleset name: \"%.20s\"", p); 375138032Speter return -1; 375238032Speter } 375338032Speter if (isdigit(*p)) 375438032Speter { 375538032Speter ruleset = strtol(p, endp, 10); 375638032Speter if (ruleset >= MAXRWSETS / 2 || ruleset < 0) 375738032Speter { 375838032Speter syserr("bad ruleset %d (%d max)", 375938032Speter ruleset, MAXRWSETS / 2); 376038032Speter ruleset = -1; 376138032Speter } 376238032Speter } 376338032Speter else 376438032Speter { 376538032Speter STAB *s; 376638032Speter char delim; 376764562Sgshapiro char *q = NULL; 376838032Speter 376938032Speter q = p; 377038032Speter while (*p != '\0' && isascii(*p) && 377138032Speter (isalnum(*p) || *p == '_')) 377238032Speter p++; 377338032Speter if (q == p || !(isascii(*q) && isalpha(*q))) 377438032Speter { 377538032Speter /* no valid characters */ 377638032Speter syserr("invalid ruleset name: \"%.20s\"", q); 377738032Speter return -1; 377838032Speter } 377938032Speter while (isascii(*p) && isspace(*p)) 378038032Speter *p++ = '\0'; 378138032Speter delim = *p; 378238032Speter if (delim != '\0') 378338032Speter *p = '\0'; 378438032Speter s = stab(q, ST_RULESET, stabmode); 378538032Speter if (delim != '\0') 378638032Speter *p = delim; 378738032Speter 378838032Speter if (s == NULL) 378938032Speter return -1; 379038032Speter 379138032Speter if (stabmode == ST_ENTER && delim == '=') 379238032Speter { 379338032Speter while (isascii(*++p) && isspace(*p)) 379438032Speter continue; 379538032Speter if (!(isascii(*p) && isdigit(*p))) 379638032Speter { 379738032Speter syserr("bad ruleset definition \"%s\" (number required after `=')", q); 379838032Speter ruleset = -1; 379938032Speter } 380038032Speter else 380138032Speter { 380238032Speter ruleset = strtol(p, endp, 10); 380338032Speter if (ruleset >= MAXRWSETS / 2 || ruleset < 0) 380438032Speter { 380538032Speter syserr("bad ruleset number %d in \"%s\" (%d max)", 380638032Speter ruleset, q, MAXRWSETS / 2); 380738032Speter ruleset = -1; 380838032Speter } 380938032Speter } 381038032Speter } 381138032Speter else 381238032Speter { 381338032Speter if (endp != NULL) 381438032Speter *endp = p; 381564562Sgshapiro if (s->s_ruleset >= 0) 381638032Speter ruleset = s->s_ruleset; 381738032Speter else if ((ruleset = --nextruleset) < MAXRWSETS / 2) 381838032Speter { 381938032Speter syserr("%s: too many named rulesets (%d max)", 382038032Speter q, MAXRWSETS / 2); 382138032Speter ruleset = -1; 382238032Speter } 382338032Speter } 382464562Sgshapiro if (s->s_ruleset >= 0 && 382564562Sgshapiro ruleset >= 0 && 382664562Sgshapiro ruleset != s->s_ruleset) 382738032Speter { 382838032Speter syserr("%s: ruleset changed value (old %d, new %d)", 382938032Speter q, s->s_ruleset, ruleset); 383038032Speter ruleset = s->s_ruleset; 383138032Speter } 383264562Sgshapiro else if (ruleset >= 0) 383338032Speter { 383438032Speter s->s_ruleset = ruleset; 383538032Speter } 383671345Sgshapiro if (stabmode == ST_ENTER && ruleset >= 0) 383764562Sgshapiro { 383864562Sgshapiro char *h = NULL; 383964562Sgshapiro 384064562Sgshapiro if (RuleSetNames[ruleset] != NULL) 384190792Sgshapiro sm_free(RuleSetNames[ruleset]); /* XXX */ 384264562Sgshapiro if (delim != '\0' && (h = strchr(q, delim)) != NULL) 384364562Sgshapiro *h = '\0'; 384464562Sgshapiro RuleSetNames[ruleset] = newstr(q); 384564562Sgshapiro if (delim == '/' && h != NULL) 384664562Sgshapiro *h = delim; /* put back delim */ 384764562Sgshapiro } 384838032Speter } 384938032Speter return ruleset; 385038032Speter} 385190792Sgshapiro/* 385264562Sgshapiro** SETTIMEOUT -- set an individual timeout 385364562Sgshapiro** 385464562Sgshapiro** Parameters: 385564562Sgshapiro** name -- the name of the timeout. 385664562Sgshapiro** val -- the value of the timeout. 385764562Sgshapiro** sticky -- if set, don't let other setoptions override 385864562Sgshapiro** this value. 385964562Sgshapiro** 386064562Sgshapiro** Returns: 386164562Sgshapiro** none. 386264562Sgshapiro*/ 386364562Sgshapiro 386464562Sgshapiro/* set if Timeout sub-option is stuck */ 386564562Sgshapirostatic BITMAP256 StickyTimeoutOpt; 386664562Sgshapiro 386764562Sgshapirostatic struct timeoutinfo 386864562Sgshapiro{ 386990792Sgshapiro char *to_name; /* long name of timeout */ 387090792Sgshapiro unsigned char to_code; /* code for option */ 387164562Sgshapiro} TimeOutTab[] = 387264562Sgshapiro{ 387364562Sgshapiro#define TO_INITIAL 0x01 387464562Sgshapiro { "initial", TO_INITIAL }, 387564562Sgshapiro#define TO_MAIL 0x02 387664562Sgshapiro { "mail", TO_MAIL }, 387764562Sgshapiro#define TO_RCPT 0x03 387864562Sgshapiro { "rcpt", TO_RCPT }, 387964562Sgshapiro#define TO_DATAINIT 0x04 388064562Sgshapiro { "datainit", TO_DATAINIT }, 388164562Sgshapiro#define TO_DATABLOCK 0x05 388264562Sgshapiro { "datablock", TO_DATABLOCK }, 388364562Sgshapiro#define TO_DATAFINAL 0x06 388464562Sgshapiro { "datafinal", TO_DATAFINAL }, 388564562Sgshapiro#define TO_COMMAND 0x07 388664562Sgshapiro { "command", TO_COMMAND }, 388764562Sgshapiro#define TO_RSET 0x08 388864562Sgshapiro { "rset", TO_RSET }, 388964562Sgshapiro#define TO_HELO 0x09 389064562Sgshapiro { "helo", TO_HELO }, 389164562Sgshapiro#define TO_QUIT 0x0A 389264562Sgshapiro { "quit", TO_QUIT }, 389364562Sgshapiro#define TO_MISC 0x0B 389464562Sgshapiro { "misc", TO_MISC }, 389564562Sgshapiro#define TO_IDENT 0x0C 389664562Sgshapiro { "ident", TO_IDENT }, 389764562Sgshapiro#define TO_FILEOPEN 0x0D 389864562Sgshapiro { "fileopen", TO_FILEOPEN }, 389964562Sgshapiro#define TO_CONNECT 0x0E 390064562Sgshapiro { "connect", TO_CONNECT }, 390164562Sgshapiro#define TO_ICONNECT 0x0F 390264562Sgshapiro { "iconnect", TO_ICONNECT }, 390364562Sgshapiro#define TO_QUEUEWARN 0x10 390464562Sgshapiro { "queuewarn", TO_QUEUEWARN }, 390564562Sgshapiro { "queuewarn.*", TO_QUEUEWARN }, 390664562Sgshapiro#define TO_QUEUEWARN_NORMAL 0x11 390764562Sgshapiro { "queuewarn.normal", TO_QUEUEWARN_NORMAL }, 390864562Sgshapiro#define TO_QUEUEWARN_URGENT 0x12 390964562Sgshapiro { "queuewarn.urgent", TO_QUEUEWARN_URGENT }, 391064562Sgshapiro#define TO_QUEUEWARN_NON_URGENT 0x13 391164562Sgshapiro { "queuewarn.non-urgent", TO_QUEUEWARN_NON_URGENT }, 391264562Sgshapiro#define TO_QUEUERETURN 0x14 391364562Sgshapiro { "queuereturn", TO_QUEUERETURN }, 391464562Sgshapiro { "queuereturn.*", TO_QUEUERETURN }, 391564562Sgshapiro#define TO_QUEUERETURN_NORMAL 0x15 391664562Sgshapiro { "queuereturn.normal", TO_QUEUERETURN_NORMAL }, 391764562Sgshapiro#define TO_QUEUERETURN_URGENT 0x16 391864562Sgshapiro { "queuereturn.urgent", TO_QUEUERETURN_URGENT }, 391964562Sgshapiro#define TO_QUEUERETURN_NON_URGENT 0x17 392064562Sgshapiro { "queuereturn.non-urgent", TO_QUEUERETURN_NON_URGENT }, 392164562Sgshapiro#define TO_HOSTSTATUS 0x18 392264562Sgshapiro { "hoststatus", TO_HOSTSTATUS }, 392364562Sgshapiro#define TO_RESOLVER_RETRANS 0x19 392464562Sgshapiro { "resolver.retrans", TO_RESOLVER_RETRANS }, 392564562Sgshapiro#define TO_RESOLVER_RETRANS_NORMAL 0x1A 392664562Sgshapiro { "resolver.retrans.normal", TO_RESOLVER_RETRANS_NORMAL }, 392764562Sgshapiro#define TO_RESOLVER_RETRANS_FIRST 0x1B 392864562Sgshapiro { "resolver.retrans.first", TO_RESOLVER_RETRANS_FIRST }, 392964562Sgshapiro#define TO_RESOLVER_RETRY 0x1C 393064562Sgshapiro { "resolver.retry", TO_RESOLVER_RETRY }, 393164562Sgshapiro#define TO_RESOLVER_RETRY_NORMAL 0x1D 393264562Sgshapiro { "resolver.retry.normal", TO_RESOLVER_RETRY_NORMAL }, 393364562Sgshapiro#define TO_RESOLVER_RETRY_FIRST 0x1E 393464562Sgshapiro { "resolver.retry.first", TO_RESOLVER_RETRY_FIRST }, 393564562Sgshapiro#define TO_CONTROL 0x1F 393664562Sgshapiro { "control", TO_CONTROL }, 393790792Sgshapiro#define TO_LHLO 0x20 393890792Sgshapiro { "lhlo", TO_LHLO }, 393990792Sgshapiro#define TO_AUTH 0x21 394090792Sgshapiro { "auth", TO_AUTH }, 394190792Sgshapiro#define TO_STARTTLS 0x22 394290792Sgshapiro { "starttls", TO_STARTTLS }, 394390792Sgshapiro#define TO_ACONNECT 0x23 394490792Sgshapiro { "aconnect", TO_ACONNECT }, 394564562Sgshapiro { NULL, 0 }, 394664562Sgshapiro}; 394764562Sgshapiro 394864562Sgshapiro 394964562Sgshapirostatic void 395064562Sgshapirosettimeout(name, val, sticky) 395164562Sgshapiro char *name; 395264562Sgshapiro char *val; 395364562Sgshapiro bool sticky; 395464562Sgshapiro{ 395564562Sgshapiro register struct timeoutinfo *to; 395690792Sgshapiro int i, addopts; 395764562Sgshapiro time_t toval; 395864562Sgshapiro 395964562Sgshapiro if (tTd(37, 2)) 396090792Sgshapiro sm_dprintf("settimeout(%s = %s)", name, val); 396164562Sgshapiro 396264562Sgshapiro for (to = TimeOutTab; to->to_name != NULL; to++) 396364562Sgshapiro { 396490792Sgshapiro if (sm_strcasecmp(to->to_name, name) == 0) 396564562Sgshapiro break; 396664562Sgshapiro } 396764562Sgshapiro 396864562Sgshapiro if (to->to_name == NULL) 396971345Sgshapiro { 397071345Sgshapiro errno = 0; /* avoid bogus error text */ 397164562Sgshapiro syserr("settimeout: invalid timeout %s", name); 397271345Sgshapiro return; 397371345Sgshapiro } 397464562Sgshapiro 397564562Sgshapiro /* 397664562Sgshapiro ** See if this option is preset for us. 397764562Sgshapiro */ 397864562Sgshapiro 397964562Sgshapiro if (!sticky && bitnset(to->to_code, StickyTimeoutOpt)) 398064562Sgshapiro { 398164562Sgshapiro if (tTd(37, 2)) 398290792Sgshapiro sm_dprintf(" (ignored)\n"); 398364562Sgshapiro return; 398464562Sgshapiro } 398564562Sgshapiro 398664562Sgshapiro if (tTd(37, 2)) 398790792Sgshapiro sm_dprintf("\n"); 398864562Sgshapiro 398964562Sgshapiro toval = convtime(val, 'm'); 399080785Sgshapiro addopts = 0; 399164562Sgshapiro 399264562Sgshapiro switch (to->to_code) 399364562Sgshapiro { 399464562Sgshapiro case TO_INITIAL: 399564562Sgshapiro TimeOuts.to_initial = toval; 399664562Sgshapiro break; 399764562Sgshapiro 399864562Sgshapiro case TO_MAIL: 399964562Sgshapiro TimeOuts.to_mail = toval; 400064562Sgshapiro break; 400164562Sgshapiro 400264562Sgshapiro case TO_RCPT: 400364562Sgshapiro TimeOuts.to_rcpt = toval; 400464562Sgshapiro break; 400564562Sgshapiro 400664562Sgshapiro case TO_DATAINIT: 400764562Sgshapiro TimeOuts.to_datainit = toval; 400864562Sgshapiro break; 400964562Sgshapiro 401064562Sgshapiro case TO_DATABLOCK: 401164562Sgshapiro TimeOuts.to_datablock = toval; 401264562Sgshapiro break; 401364562Sgshapiro 401464562Sgshapiro case TO_DATAFINAL: 401564562Sgshapiro TimeOuts.to_datafinal = toval; 401664562Sgshapiro break; 401764562Sgshapiro 401864562Sgshapiro case TO_COMMAND: 401964562Sgshapiro TimeOuts.to_nextcommand = toval; 402064562Sgshapiro break; 402164562Sgshapiro 402264562Sgshapiro case TO_RSET: 402364562Sgshapiro TimeOuts.to_rset = toval; 402464562Sgshapiro break; 402564562Sgshapiro 402664562Sgshapiro case TO_HELO: 402764562Sgshapiro TimeOuts.to_helo = toval; 402864562Sgshapiro break; 402964562Sgshapiro 403064562Sgshapiro case TO_QUIT: 403164562Sgshapiro TimeOuts.to_quit = toval; 403264562Sgshapiro break; 403364562Sgshapiro 403464562Sgshapiro case TO_MISC: 403564562Sgshapiro TimeOuts.to_miscshort = toval; 403664562Sgshapiro break; 403764562Sgshapiro 403864562Sgshapiro case TO_IDENT: 403964562Sgshapiro TimeOuts.to_ident = toval; 404064562Sgshapiro break; 404164562Sgshapiro 404264562Sgshapiro case TO_FILEOPEN: 404364562Sgshapiro TimeOuts.to_fileopen = toval; 404464562Sgshapiro break; 404564562Sgshapiro 404664562Sgshapiro case TO_CONNECT: 404764562Sgshapiro TimeOuts.to_connect = toval; 404864562Sgshapiro break; 404964562Sgshapiro 405064562Sgshapiro case TO_ICONNECT: 405164562Sgshapiro TimeOuts.to_iconnect = toval; 405264562Sgshapiro break; 405364562Sgshapiro 405490792Sgshapiro case TO_ACONNECT: 405590792Sgshapiro TimeOuts.to_aconnect = toval; 405690792Sgshapiro break; 405790792Sgshapiro 405864562Sgshapiro case TO_QUEUEWARN: 405964562Sgshapiro toval = convtime(val, 'h'); 406064562Sgshapiro TimeOuts.to_q_warning[TOC_NORMAL] = toval; 406164562Sgshapiro TimeOuts.to_q_warning[TOC_URGENT] = toval; 406264562Sgshapiro TimeOuts.to_q_warning[TOC_NONURGENT] = toval; 406380785Sgshapiro addopts = 2; 406464562Sgshapiro break; 406564562Sgshapiro 406664562Sgshapiro case TO_QUEUEWARN_NORMAL: 406764562Sgshapiro toval = convtime(val, 'h'); 406864562Sgshapiro TimeOuts.to_q_warning[TOC_NORMAL] = toval; 406964562Sgshapiro break; 407064562Sgshapiro 407164562Sgshapiro case TO_QUEUEWARN_URGENT: 407264562Sgshapiro toval = convtime(val, 'h'); 407364562Sgshapiro TimeOuts.to_q_warning[TOC_URGENT] = toval; 407464562Sgshapiro break; 407564562Sgshapiro 407664562Sgshapiro case TO_QUEUEWARN_NON_URGENT: 407764562Sgshapiro toval = convtime(val, 'h'); 407864562Sgshapiro TimeOuts.to_q_warning[TOC_NONURGENT] = toval; 407964562Sgshapiro break; 408064562Sgshapiro 408164562Sgshapiro case TO_QUEUERETURN: 408264562Sgshapiro toval = convtime(val, 'd'); 408364562Sgshapiro TimeOuts.to_q_return[TOC_NORMAL] = toval; 408464562Sgshapiro TimeOuts.to_q_return[TOC_URGENT] = toval; 408564562Sgshapiro TimeOuts.to_q_return[TOC_NONURGENT] = toval; 408680785Sgshapiro addopts = 2; 408764562Sgshapiro break; 408864562Sgshapiro 408964562Sgshapiro case TO_QUEUERETURN_NORMAL: 409064562Sgshapiro toval = convtime(val, 'd'); 409164562Sgshapiro TimeOuts.to_q_return[TOC_NORMAL] = toval; 409264562Sgshapiro break; 409364562Sgshapiro 409464562Sgshapiro case TO_QUEUERETURN_URGENT: 409564562Sgshapiro toval = convtime(val, 'd'); 409664562Sgshapiro TimeOuts.to_q_return[TOC_URGENT] = toval; 409764562Sgshapiro break; 409864562Sgshapiro 409964562Sgshapiro case TO_QUEUERETURN_NON_URGENT: 410064562Sgshapiro toval = convtime(val, 'd'); 410164562Sgshapiro TimeOuts.to_q_return[TOC_NONURGENT] = toval; 410264562Sgshapiro break; 410364562Sgshapiro 410464562Sgshapiro 410564562Sgshapiro case TO_HOSTSTATUS: 410664562Sgshapiro MciInfoTimeout = toval; 410764562Sgshapiro break; 410864562Sgshapiro 410964562Sgshapiro case TO_RESOLVER_RETRANS: 411064562Sgshapiro toval = convtime(val, 's'); 411164562Sgshapiro TimeOuts.res_retrans[RES_TO_DEFAULT] = toval; 411264562Sgshapiro TimeOuts.res_retrans[RES_TO_FIRST] = toval; 411364562Sgshapiro TimeOuts.res_retrans[RES_TO_NORMAL] = toval; 411480785Sgshapiro addopts = 2; 411564562Sgshapiro break; 411664562Sgshapiro 411764562Sgshapiro case TO_RESOLVER_RETRY: 411864562Sgshapiro i = atoi(val); 411964562Sgshapiro TimeOuts.res_retry[RES_TO_DEFAULT] = i; 412064562Sgshapiro TimeOuts.res_retry[RES_TO_FIRST] = i; 412164562Sgshapiro TimeOuts.res_retry[RES_TO_NORMAL] = i; 412280785Sgshapiro addopts = 2; 412364562Sgshapiro break; 412464562Sgshapiro 412564562Sgshapiro case TO_RESOLVER_RETRANS_NORMAL: 412664562Sgshapiro TimeOuts.res_retrans[RES_TO_NORMAL] = convtime(val, 's'); 412764562Sgshapiro break; 412864562Sgshapiro 412964562Sgshapiro case TO_RESOLVER_RETRY_NORMAL: 413064562Sgshapiro TimeOuts.res_retry[RES_TO_NORMAL] = atoi(val); 413164562Sgshapiro break; 413264562Sgshapiro 413364562Sgshapiro case TO_RESOLVER_RETRANS_FIRST: 413464562Sgshapiro TimeOuts.res_retrans[RES_TO_FIRST] = convtime(val, 's'); 413564562Sgshapiro break; 413664562Sgshapiro 413764562Sgshapiro case TO_RESOLVER_RETRY_FIRST: 413864562Sgshapiro TimeOuts.res_retry[RES_TO_FIRST] = atoi(val); 413964562Sgshapiro break; 414064562Sgshapiro 414164562Sgshapiro case TO_CONTROL: 414264562Sgshapiro TimeOuts.to_control = toval; 414364562Sgshapiro break; 414464562Sgshapiro 414590792Sgshapiro case TO_LHLO: 414690792Sgshapiro TimeOuts.to_lhlo = toval; 414790792Sgshapiro break; 414890792Sgshapiro 414990792Sgshapiro#if SASL 415090792Sgshapiro case TO_AUTH: 415190792Sgshapiro TimeOuts.to_auth = toval; 415290792Sgshapiro break; 415390792Sgshapiro#endif /* SASL */ 415490792Sgshapiro 415590792Sgshapiro#if STARTTLS 415690792Sgshapiro case TO_STARTTLS: 415790792Sgshapiro TimeOuts.to_starttls = toval; 415890792Sgshapiro break; 415990792Sgshapiro#endif /* STARTTLS */ 416090792Sgshapiro 416164562Sgshapiro default: 416264562Sgshapiro syserr("settimeout: invalid timeout %s", name); 416364562Sgshapiro break; 416464562Sgshapiro } 416564562Sgshapiro 416664562Sgshapiro if (sticky) 416780785Sgshapiro { 416880785Sgshapiro for (i = 0; i <= addopts; i++) 416980785Sgshapiro setbitn(to->to_code + i, StickyTimeoutOpt); 417080785Sgshapiro } 417164562Sgshapiro} 417290792Sgshapiro/* 417338032Speter** INITTIMEOUTS -- parse and set timeout values 417438032Speter** 417538032Speter** Parameters: 417638032Speter** val -- a pointer to the values. If NULL, do initial 417738032Speter** settings. 417864562Sgshapiro** sticky -- if set, don't let other setoptions override 417964562Sgshapiro** this suboption value. 418038032Speter** 418138032Speter** Returns: 418238032Speter** none. 418338032Speter** 418438032Speter** Side Effects: 418538032Speter** Initializes the TimeOuts structure 418638032Speter*/ 418738032Speter 418838032Spetervoid 418964562Sgshapiroinittimeouts(val, sticky) 419038032Speter register char *val; 419164562Sgshapiro bool sticky; 419238032Speter{ 419338032Speter register char *p; 419438032Speter 419538032Speter if (tTd(37, 2)) 419690792Sgshapiro sm_dprintf("inittimeouts(%s)\n", val == NULL ? "<NULL>" : val); 419738032Speter if (val == NULL) 419838032Speter { 419938032Speter TimeOuts.to_connect = (time_t) 0 SECONDS; 420090792Sgshapiro TimeOuts.to_aconnect = (time_t) 0 SECONDS; 420194334Sgshapiro TimeOuts.to_iconnect = (time_t) 0 SECONDS; 420238032Speter TimeOuts.to_initial = (time_t) 5 MINUTES; 420338032Speter TimeOuts.to_helo = (time_t) 5 MINUTES; 420438032Speter TimeOuts.to_mail = (time_t) 10 MINUTES; 420538032Speter TimeOuts.to_rcpt = (time_t) 1 HOUR; 420638032Speter TimeOuts.to_datainit = (time_t) 5 MINUTES; 420738032Speter TimeOuts.to_datablock = (time_t) 1 HOUR; 420838032Speter TimeOuts.to_datafinal = (time_t) 1 HOUR; 420938032Speter TimeOuts.to_rset = (time_t) 5 MINUTES; 421038032Speter TimeOuts.to_quit = (time_t) 2 MINUTES; 421138032Speter TimeOuts.to_nextcommand = (time_t) 1 HOUR; 421238032Speter TimeOuts.to_miscshort = (time_t) 2 MINUTES; 421338032Speter#if IDENTPROTO 421464562Sgshapiro TimeOuts.to_ident = (time_t) 5 SECONDS; 421564562Sgshapiro#else /* IDENTPROTO */ 421638032Speter TimeOuts.to_ident = (time_t) 0 SECONDS; 421764562Sgshapiro#endif /* IDENTPROTO */ 421838032Speter TimeOuts.to_fileopen = (time_t) 60 SECONDS; 421964562Sgshapiro TimeOuts.to_control = (time_t) 2 MINUTES; 422090792Sgshapiro TimeOuts.to_lhlo = (time_t) 2 MINUTES; 422190792Sgshapiro#if SASL 422290792Sgshapiro TimeOuts.to_auth = (time_t) 10 MINUTES; 422390792Sgshapiro#endif /* SASL */ 422490792Sgshapiro#if STARTTLS 422590792Sgshapiro TimeOuts.to_starttls = (time_t) 1 HOUR; 422690792Sgshapiro#endif /* STARTTLS */ 422738032Speter if (tTd(37, 5)) 422838032Speter { 422990792Sgshapiro sm_dprintf("Timeouts:\n"); 423090792Sgshapiro sm_dprintf(" connect = %ld\n", 423190792Sgshapiro (long) TimeOuts.to_connect); 423290792Sgshapiro sm_dprintf(" aconnect = %ld\n", 423390792Sgshapiro (long) TimeOuts.to_aconnect); 423490792Sgshapiro sm_dprintf(" initial = %ld\n", 423590792Sgshapiro (long) TimeOuts.to_initial); 423690792Sgshapiro sm_dprintf(" helo = %ld\n", (long) TimeOuts.to_helo); 423790792Sgshapiro sm_dprintf(" mail = %ld\n", (long) TimeOuts.to_mail); 423890792Sgshapiro sm_dprintf(" rcpt = %ld\n", (long) TimeOuts.to_rcpt); 423990792Sgshapiro sm_dprintf(" datainit = %ld\n", 424090792Sgshapiro (long) TimeOuts.to_datainit); 424190792Sgshapiro sm_dprintf(" datablock = %ld\n", 424290792Sgshapiro (long) TimeOuts.to_datablock); 424390792Sgshapiro sm_dprintf(" datafinal = %ld\n", 424490792Sgshapiro (long) TimeOuts.to_datafinal); 424590792Sgshapiro sm_dprintf(" rset = %ld\n", (long) TimeOuts.to_rset); 424690792Sgshapiro sm_dprintf(" quit = %ld\n", (long) TimeOuts.to_quit); 424790792Sgshapiro sm_dprintf(" nextcommand = %ld\n", 424890792Sgshapiro (long) TimeOuts.to_nextcommand); 424990792Sgshapiro sm_dprintf(" miscshort = %ld\n", 425090792Sgshapiro (long) TimeOuts.to_miscshort); 425190792Sgshapiro sm_dprintf(" ident = %ld\n", (long) TimeOuts.to_ident); 425290792Sgshapiro sm_dprintf(" fileopen = %ld\n", 425390792Sgshapiro (long) TimeOuts.to_fileopen); 425490792Sgshapiro sm_dprintf(" lhlo = %ld\n", 425590792Sgshapiro (long) TimeOuts.to_lhlo); 425690792Sgshapiro sm_dprintf(" control = %ld\n", 425790792Sgshapiro (long) TimeOuts.to_control); 425838032Speter } 425938032Speter return; 426038032Speter } 426138032Speter 426238032Speter for (;; val = p) 426338032Speter { 426438032Speter while (isascii(*val) && isspace(*val)) 426538032Speter val++; 426638032Speter if (*val == '\0') 426738032Speter break; 426838032Speter for (p = val; *p != '\0' && *p != ','; p++) 426938032Speter continue; 427038032Speter if (*p != '\0') 427138032Speter *p++ = '\0'; 427238032Speter 427338032Speter if (isascii(*val) && isdigit(*val)) 427438032Speter { 427538032Speter /* old syntax -- set everything */ 427638032Speter TimeOuts.to_mail = convtime(val, 'm'); 427738032Speter TimeOuts.to_rcpt = TimeOuts.to_mail; 427838032Speter TimeOuts.to_datainit = TimeOuts.to_mail; 427938032Speter TimeOuts.to_datablock = TimeOuts.to_mail; 428038032Speter TimeOuts.to_datafinal = TimeOuts.to_mail; 428138032Speter TimeOuts.to_nextcommand = TimeOuts.to_mail; 428264562Sgshapiro if (sticky) 428364562Sgshapiro { 428464562Sgshapiro setbitn(TO_MAIL, StickyTimeoutOpt); 428564562Sgshapiro setbitn(TO_RCPT, StickyTimeoutOpt); 428664562Sgshapiro setbitn(TO_DATAINIT, StickyTimeoutOpt); 428764562Sgshapiro setbitn(TO_DATABLOCK, StickyTimeoutOpt); 428864562Sgshapiro setbitn(TO_DATAFINAL, StickyTimeoutOpt); 428964562Sgshapiro setbitn(TO_COMMAND, StickyTimeoutOpt); 429064562Sgshapiro } 429138032Speter continue; 429238032Speter } 429338032Speter else 429438032Speter { 429538032Speter register char *q = strchr(val, ':'); 429638032Speter 429738032Speter if (q == NULL && (q = strchr(val, '=')) == NULL) 429838032Speter { 429938032Speter /* syntax error */ 430038032Speter continue; 430138032Speter } 430238032Speter *q++ = '\0'; 430364562Sgshapiro settimeout(val, q, sticky); 430438032Speter } 430538032Speter } 430638032Speter} 4307