diff options
author | gshapiro <gshapiro@FreeBSD.org> | 2000-08-12 21:55:49 +0000 |
---|---|---|
committer | gshapiro <gshapiro@FreeBSD.org> | 2000-08-12 21:55:49 +0000 |
commit | c3cd75415d60bc002b20182ffd3383ea9e901a80 (patch) | |
tree | 211dfd0f771f89d6abe14fa94cab53985a9d0116 /contrib/sendmail/src/readcf.c | |
parent | 231592eb7942ebd4becae24ea8e018acea3742a9 (diff) | |
parent | 4332139a9a11f773ffe5109bed871561e3c290a1 (diff) | |
download | FreeBSD-src-c3cd75415d60bc002b20182ffd3383ea9e901a80.zip FreeBSD-src-c3cd75415d60bc002b20182ffd3383ea9e901a80.tar.gz |
This commit was generated by cvs2svn to compensate for changes in r64562,
which included commits to RCS files with non-trunk default branches.
Diffstat (limited to 'contrib/sendmail/src/readcf.c')
-rw-r--r-- | contrib/sendmail/src/readcf.c | 1508 |
1 files changed, 1102 insertions, 406 deletions
diff --git a/contrib/sendmail/src/readcf.c b/contrib/sendmail/src/readcf.c index df40097..2521435 100644 --- a/contrib/sendmail/src/readcf.c +++ b/contrib/sendmail/src/readcf.c @@ -1,5 +1,6 @@ /* - * Copyright (c) 1998 Sendmail, Inc. All rights reserved. + * Copyright (c) 1998-2000 Sendmail, Inc. and its suppliers. + * All rights reserved. * Copyright (c) 1983, 1995-1997 Eric P. Allman. All rights reserved. * Copyright (c) 1988, 1993 * The Regents of the University of California. All rights reserved. @@ -11,14 +12,25 @@ */ #ifndef lint -static char sccsid[] = "@(#)readcf.c 8.238 (Berkeley) 1/28/1999"; -#endif /* not lint */ +static char id[] = "@(#)$Id: readcf.c,v 8.382.4.14 2000/07/12 00:00:27 geir Exp $"; +#endif /* ! lint */ -# include "sendmail.h" -# include <grp.h> -#if NAMED_BIND -# include <resolv.h> -#endif +#include <sendmail.h> + + +#if NETINET || NETINET6 +# include <arpa/inet.h> +#endif /* NETINET || NETINET6 */ + +#define SECONDS +#define MINUTES * 60 +#define HOUR * 3600 +#define HOURS HOUR + +static void fileclass __P((int, char *, char *, bool, bool)); +static char **makeargv __P((char *)); +static void settimeout __P((char *, char *, bool)); +static void toomany __P((int, int)); /* ** READCF -- read configuration file. @@ -74,7 +86,7 @@ readcf(cfname, safe, e) register ENVELOPE *e; { FILE *cf; - int ruleset = 0; + int ruleset = -1; char *q; struct rewrite *rwp = NULL; char *bp; @@ -84,18 +96,13 @@ readcf(cfname, safe, e) bool optional; int mid; register char *p; - int sff = SFF_OPENASROOT; + long sff = SFF_OPENASROOT; struct stat statb; char buf[MAXLINE]; char exbuf[MAXLINE]; char pvpbuf[MAXLINE + MAXATOM]; static char *null_list[1] = { NULL }; - extern char **copyplist __P((char **, bool)); - extern char *munchstring __P((char *, char **, int)); - extern void fileclass __P((int, char *, char *, bool, bool)); - extern void toomany __P((int, int)); - extern void translate_dollars __P((char *)); - extern void inithostmaps __P((void)); + extern u_char TokTypeNoC[]; FileName = cfname; LineNumber = 0; @@ -128,13 +135,13 @@ readcf(cfname, safe, e) FileName); if (LogLevel > 0) sm_syslog(LOG_CRIT, NOQID, - "%s: WARNING: dangerous write permissions", - FileName); + "%s: WARNING: dangerous write permissions", + FileName); } #ifdef XLA xla_zero(); -#endif +#endif /* XLA */ while ((bp = fgetfolded(buf, sizeof buf, cf)) != NULL) { @@ -157,6 +164,11 @@ readcf(cfname, safe, e) break; case 'R': /* rewriting rule */ + if (ruleset < 0) + { + syserr("missing valid ruleset for \"%s\"", bp); + break; + } for (p = &bp[1]; *p != '\0' && *p != '\t'; p++) continue; @@ -183,7 +195,8 @@ readcf(cfname, safe, e) *p = '\0'; expand(&bp[1], exbuf, sizeof exbuf, e); rwp->r_lhs = prescan(exbuf, '\t', pvpbuf, - sizeof pvpbuf, NULL, NULL); + sizeof pvpbuf, NULL, + ConfigLevel >= 9 ? TokTypeNoC : NULL); nfuzzy = 0; if (rwp->r_lhs != NULL) { @@ -247,6 +260,7 @@ readcf(cfname, safe, e) syserr("Inappropriate use of %s on LHS", botch); } + rwp->r_line = LineNumber; } else { @@ -263,7 +277,8 @@ readcf(cfname, safe, e) *p = '\0'; expand(q, exbuf, sizeof exbuf, e); rwp->r_rhs = prescan(exbuf, '\t', pvpbuf, - sizeof pvpbuf, NULL, NULL); + sizeof pvpbuf, NULL, + ConfigLevel >= 9 ? TokTypeNoC : NULL); if (rwp->r_rhs != NULL) { register char **ap; @@ -324,11 +339,15 @@ readcf(cfname, safe, e) ruleset = strtorwset(exbuf, NULL, ST_ENTER); if (ruleset < 0) break; + rwp = RewriteRules[ruleset]; if (rwp != NULL) { - if (OpMode == MD_TEST || tTd(37, 1)) + if (OpMode == MD_TEST) printf("WARNING: Ruleset %s has multiple definitions\n", + &bp[1]); + if (tTd(37, 1)) + dprintf("WARNING: Ruleset %s has multiple definitions\n", &bp[1]); while (rwp->r_next != NULL) rwp = rwp->r_next; @@ -342,7 +361,7 @@ readcf(cfname, safe, e) break; case 'H': /* required header line */ - (void) chompheader(&bp[1], TRUE, NULL, e); + (void) chompheader(&bp[1], CHHDR_DEF, NULL, e); break; case 'C': /* word class */ @@ -390,13 +409,16 @@ readcf(cfname, safe, e) } else optional = FALSE; + file = p; + q = p; + while (*q != '\0' && !(isascii(*q) && isspace(*q))) + q++; if (*file == '|') p = "%s"; else { - while (*p != '\0' && !(isascii(*p) && isspace(*p))) - p++; + p = q; if (*p == '\0') p = "%s"; else @@ -413,7 +435,7 @@ readcf(cfname, safe, e) case 'L': /* extended load average description */ xla_init(&bp[1]); break; -#endif +#endif /* XLA */ #if defined(SUN_EXTENSIONS) && defined(SUN_LOOKUP_MACRO) case 'L': /* lookup macro */ @@ -423,7 +445,7 @@ readcf(cfname, safe, e) goto badline; sun_lg_config_line(bp, e); break; -#endif +#endif /* defined(SUN_EXTENSIONS) && defined(SUN_LOOKUP_MACRO) */ case 'M': /* define mailer */ makemailer(&bp[1]); @@ -454,7 +476,7 @@ readcf(cfname, safe, e) continue; if (!isascii(*p) || !isdigit(*p)) { - syserr("invalid argument to V line: \"%.20s\"", + syserr("invalid argument to V line: \"%.20s\"", &bp[1]); break; } @@ -483,8 +505,6 @@ readcf(cfname, safe, e) if (*ep++ == '/') { - extern bool setvendor __P((char *)); - /* extract vendor code */ for (p = ep; isascii(*p) && isalpha(*p); ) p++; @@ -508,6 +528,12 @@ readcf(cfname, safe, e) setuserenv(&bp[1], p); break; +#if _FFR_MILTER + case 'X': /* mail filter */ + milter_setup(&bp[1]); + break; +#endif /* _FFR_MILTER */ + default: badline: syserr("unknown configuration line \"%s\"", bp); @@ -520,12 +546,15 @@ readcf(cfname, safe, e) syserr("I/O read error"); finis(FALSE, EX_OSFILE); } - fclose(cf); + (void) fclose(cf); FileName = NULL; /* initialize host maps from local service tables */ inithostmaps(); + /* initialize daemon (if not defined yet) */ + initdaemon(); + /* determine if we need to do special name-server frotz */ { int nmaps; @@ -558,7 +587,7 @@ readcf(cfname, safe, e) UseHesiod = TRUE; } } -#endif +#endif /* HESIOD */ } } /* @@ -599,16 +628,16 @@ translate_dollars(bp) case '\\': /* it's backslash escaped */ - (void) strcpy(p, p + 1); + (void) strlcpy(p, p + 1, strlen(p)); break; default: - /* delete preceeding white space */ + /* delete leading white space */ while (isascii(*p) && isspace(*p) && *p != '\n' && p > bp) p--; if ((e = strchr(++p, '\n')) != NULL) - (void) strcpy(p, e); + (void) strlcpy(p, e, strlen(p)); else *p-- = '\0'; break; @@ -622,7 +651,7 @@ translate_dollars(bp) if (p[1] == '$') { /* actual dollar sign.... */ - (void) strcpy(p, p + 1); + (void) strlcpy(p, p + 1, strlen(p)); continue; } @@ -635,8 +664,8 @@ translate_dollars(bp) /* convert macro name to code */ *p = macid(p, &ep); - if (ep != p) - strcpy(p + 1, ep); + if (ep != p + 1) + (void) strlcpy(p + 1, ep, strlen(p + 1)); } /* strip trailing white space from the line */ @@ -657,7 +686,7 @@ translate_dollars(bp) ** gives a syserr. */ -void +static void toomany(id, maxcnt) int id; int maxcnt; @@ -684,7 +713,7 @@ toomany(id, maxcnt) ** the named class. */ -void +static void fileclass(class, filename, fmt, safe, optional) int class; char *filename; @@ -693,13 +722,13 @@ fileclass(class, filename, fmt, safe, optional) bool optional; { FILE *f; - int sff; + long sff; pid_t pid; register char *p; char buf[MAXLINE]; if (tTd(37, 2)) - printf("fileclass(%s, fmt=%s)\n", filename, fmt); + dprintf("fileclass(%s, fmt=%s)\n", filename, fmt); if (filename[0] == '|') { @@ -725,9 +754,10 @@ fileclass(class, filename, fmt, safe, optional) { pid = -1; sff = SFF_REGONLY; - if (!bitset(DBS_CLASSFILEINUNSAFEDIRPATH, DontBlameSendmail)) + if (!bitnset(DBS_CLASSFILEINUNSAFEDIRPATH, DontBlameSendmail)) sff |= SFF_SAFEDIRPATH; - if (!bitset(DBS_LINKEDCLASSFILEINWRITABLEDIR, DontBlameSendmail)) + if (!bitnset(DBS_LINKEDCLASSFILEINWRITABLEDIR, + DontBlameSendmail)) sff |= SFF_NOWLINK; if (safe) sff |= SFF_OPENASROOT; @@ -738,26 +768,25 @@ fileclass(class, filename, fmt, safe, optional) if (f == NULL) { if (!optional) - syserr("fileclass: cannot open %s", filename); + syserr("fileclass: cannot open '%s'", filename); return; } while (fgets(buf, sizeof buf, f) != NULL) { - register char *p; -# if SCANF +#if SCANF char wordbuf[MAXLINE + 1]; -# endif +#endif /* SCANF */ if (buf[0] == '#') continue; -# if SCANF +#if SCANF if (sscanf(buf, fmt, wordbuf) != 1) continue; p = wordbuf; -# else /* SCANF */ +#else /* SCANF */ p = buf; -# endif /* SCANF */ +#endif /* SCANF */ /* ** Break up the match into words. @@ -808,6 +837,7 @@ fileclass(class, filename, fmt, safe, optional) ** S -- the sender rewriting set ** T -- the mailer type (for DSNs) ** U -- the uid to run as +** W -- the time to wait at the end ** The first word is the canonical name of the mailer. ** ** Returns: @@ -828,12 +858,10 @@ makemailer(line) char fcode; auto char *endp; extern int NextMailer; - extern char **makeargv __P((char *)); - extern char *munchstring __P((char *, char **, int)); /* allocate a mailer and set up defaults */ m = (struct mailer *) xalloc(sizeof *m); - bzero((char *) m, sizeof *m); + memset((char *) m, '\0', sizeof *m); /* collect the mailer name */ for (p = line; *p != '\0' && *p != ',' && !(isascii(*p) && isspace(*p)); p++) @@ -923,6 +951,16 @@ makemailer(line) m->m_maxsize = atol(p); break; + case 'm': /* maximum messages per connection */ + m->m_maxdeliveries = atoi(p); + break; + +#if _FFR_DYNAMIC_TOBUF + case 'r': /* max recipient per envelope */ + m->m_maxrcpt = atoi(p); + break; +#endif /* _FFR_DYNAMIC_TOBUF */ + case 'L': /* maximum line length */ m->m_linelimit = atoi(p); if (m->m_linelimit < 0) @@ -1040,6 +1078,23 @@ makemailer(line) m->m_gid = strtol(p, NULL, 0); } break; + + case 'W': /* wait timeout */ + m->m_wait = convtime(p, 's'); + break; + + case '/': /* new root directory */ + if (*p == '\0') + syserr("mailer %s: null root directory", + m->m_name); + else + m->m_rootdir = newstr(p); + break; + + default: + syserr("M%s: unknown mailer equate %c=", + m->m_name, fcode); + break; } p = delimptr; @@ -1063,6 +1118,11 @@ makemailer(line) return; } +#if _FFR_DYNAMIC_TOBUF + if (m->m_maxrcpt <= 0) + m->m_maxrcpt = DEFAULT_MAX_RCPT; +#endif /* _FFR_DYNAMIC_TOBUF */ + /* do some heuristic cleanup for back compatibility */ if (bitnset(M_LIMITS, m->m_flags)) { @@ -1072,18 +1132,51 @@ makemailer(line) setbitn(M_7BITS, m->m_flags); } - if (strcmp(m->m_mailer, "[IPC]") == 0 || - strcmp(m->m_mailer, "[TCP]") == 0) + if (strcmp(m->m_mailer, "[TCP]") == 0) { - if (m->m_mtatype == NULL) - m->m_mtatype = "dns"; - if (m->m_addrtype == NULL) - m->m_addrtype = "rfc822"; - if (m->m_diagtype == NULL) - m->m_diagtype = "smtp"; +#if _FFR_REMOVE_TCP_PATH + syserr("M%s: P=[TCP] is deprecated, use P=[IPC] instead\n", + m->m_name); +#else /* _FFR_REMOVE_TCP_PATH */ + printf("M%s: Warning: P=[TCP] is deprecated, use P=[IPC] instead\n", + m->m_name); +#endif /* _FFR_REMOVE_TCP_PATH */ } - if (strcmp(m->m_mailer, "[FILE]") == 0) + if (strcmp(m->m_mailer, "[IPC]") == 0 || +#if !_FFR_REMOVE_TCP_MAILER_PATH + strcmp(m->m_mailer, "[TCP]") == 0 +#endif /* !_FFR_REMOVE_TCP_MAILER_PATH */ + ) + { + /* Use the second argument for host or path to socket */ + if (m->m_argv[0] == NULL || m->m_argv[1] == NULL || + m->m_argv[1][0] == '\0') + { + syserr("M%s: too few parameters for %s mailer", + m->m_name, m->m_mailer); + } + if (strcmp(m->m_argv[0], "TCP") != 0 && +#if NETUNIX + strcmp(m->m_argv[0], "FILE") != 0 && +#endif /* NETUNIX */ +#if !_FFR_DEPRECATE_IPC_MAILER_ARG + strcmp(m->m_argv[0], "IPC") != 0 +#endif /* !_FFR_DEPRECATE_IPC_MAILER_ARG */ + ) + { + printf("M%s: Warning: first argument in %s mailer must be %s\n", + m->m_name, m->m_mailer, +#if NETUNIX + "TCP or FILE" +#else /* NETUNIX */ + "TCP" +#endif /* NETUNIX */ + ); + } + + } + else if (strcmp(m->m_mailer, "[FILE]") == 0) { /* Use the second argument for filename */ if (m->m_argv[0] == NULL || m->m_argv[1] == NULL || @@ -1101,6 +1194,23 @@ makemailer(line) } } + if (strcmp(m->m_mailer, "[IPC]") == 0 || + strcmp(m->m_mailer, "[TCP]") == 0) + { + if (m->m_mtatype == NULL) + m->m_mtatype = "dns"; + if (m->m_addrtype == NULL) + m->m_addrtype = "rfc822"; + if (m->m_diagtype == NULL) + { + if (m->m_argv[0] != NULL && + strcmp(m->m_argv[0], "FILE") == 0) + m->m_diagtype = "x-unix"; + else + m->m_diagtype = "smtp"; + } + } + if (m->m_eol == NULL) { char **pp; @@ -1108,8 +1218,6 @@ makemailer(line) /* default for SMTP is \r\n; use \n for local delivery */ for (pp = m->m_argv; *pp != NULL; pp++) { - char *p; - for (p = *pp; *p != '\0'; ) { if ((*p++ & 0377) == MACROEXPAND && *p == 'u') @@ -1149,6 +1257,10 @@ makemailer(line) ** ** Returns: ** the munched string. +** +** Side Effects: +** the munched string is a local static buffer. +** it must be copied before the function is called again. */ char * @@ -1204,7 +1316,7 @@ munchstring(p, delimptr, delim) if (delimptr != NULL) *delimptr = p; *q++ = '\0'; - return (buf); + return buf; } /* ** MAKEARGV -- break up a string into words @@ -1219,7 +1331,7 @@ munchstring(p, delimptr, delim) ** munges p. */ -char ** +static char ** makeargv(p) register char *p; { @@ -1243,9 +1355,9 @@ makeargv(p) /* now make a copy of the argv */ avp = (char **) xalloc(sizeof *avp * i); - bcopy((char *) argv, (char *) avp, sizeof *avp * i); + memmove((char *) avp, (char *) argv, sizeof *avp * i); - return (avp); + return avp; } /* ** PRINTRULES -- print rewrite rules (for debugging) @@ -1297,11 +1409,25 @@ printmailer(m) { int j; - printf("mailer %d (%s): P=%s S=%d/%d R=%d/%d M=%ld U=%d:%d F=", - m->m_mno, m->m_name, - m->m_mailer, m->m_se_rwset, m->m_sh_rwset, - m->m_re_rwset, m->m_rh_rwset, m->m_maxsize, - (int) m->m_uid, (int) m->m_gid); + printf("mailer %d (%s): P=%s S=", m->m_mno, m->m_name, m->m_mailer); + if (RuleSetNames[m->m_se_rwset] == NULL) + printf("%d/", m->m_se_rwset); + else + printf("%s/", RuleSetNames[m->m_se_rwset]); + if (RuleSetNames[m->m_sh_rwset] == NULL) + printf("%d R=", m->m_sh_rwset); + else + printf("%s R=", RuleSetNames[m->m_sh_rwset]); + if (RuleSetNames[m->m_re_rwset] == NULL) + printf("%d/", m->m_re_rwset); + else + printf("%s/", RuleSetNames[m->m_re_rwset]); + if (RuleSetNames[m->m_rh_rwset] == NULL) + printf("%d ", m->m_rh_rwset); + else + printf("%s ", RuleSetNames[m->m_rh_rwset]); + printf("M=%ld U=%d:%d F=", m->m_maxsize, + (int) m->m_uid, (int) m->m_gid); for (j = '\0'; j <= '\177'; j++) if (bitnset(j, m->m_flags)) (void) putchar(j); @@ -1313,6 +1439,9 @@ printmailer(m) m->m_mtatype == NULL ? "<undefined>" : m->m_mtatype, m->m_addrtype == NULL ? "<undefined>" : m->m_addrtype, m->m_diagtype == NULL ? "<undefined>" : m->m_diagtype); +#if _FFR_DYNAMIC_TOBUF + printf(" r=%d", m->m_maxrcpt); +#endif /* _FFR_DYNAMIC_TOBUF */ if (m->m_argv != NULL) { char **a = m->m_argv; @@ -1347,13 +1476,11 @@ printmailer(m) ** Sets options as implied by the arguments. */ -static BITMAP StickyOpt; /* set if option is stuck */ -extern void settimeout __P((char *, char *)); - +static BITMAP256 StickyOpt; /* set if option is stuck */ #if NAMED_BIND -struct resolverflags +static struct resolverflags { char *rf_name; /* name of the flag */ long rf_bits; /* bits to set/clear */ @@ -1372,170 +1499,219 @@ struct resolverflags { NULL, 0 } }; -#endif +#endif /* NAMED_BIND */ + +#define OI_NONE 0 /* no special treatment */ +#define OI_SAFE 0x0001 /* safe for random people to use */ +#define OI_SUBOPT 0x0002 /* option has suboptions */ -struct optioninfo +static struct optioninfo { char *o_name; /* long name of option */ u_char o_code; /* short name of option */ - bool o_safe; /* safe for random people to use */ + u_short o_flags; /* option flags */ } OptionTab[] = { - { "SevenBitInput", '7', TRUE }, +#if defined(SUN_EXTENSIONS) && defined(REMOTE_MODE) + { "RemoteMode", '>', OI_NONE }, +#endif /* defined(SUN_EXTENSIONS) && defined(REMOTE_MODE) */ + { "SevenBitInput", '7', OI_SAFE }, #if MIME8TO7 - { "EightBitMode", '8', TRUE }, -#endif - { "AliasFile", 'A', FALSE }, - { "AliasWait", 'a', FALSE }, - { "BlankSub", 'B', FALSE }, - { "MinFreeBlocks", 'b', TRUE }, - { "CheckpointInterval", 'C', TRUE }, - { "HoldExpensive", 'c', FALSE }, - { "AutoRebuildAliases", 'D', FALSE }, - { "DeliveryMode", 'd', TRUE }, - { "ErrorHeader", 'E', FALSE }, - { "ErrorMode", 'e', TRUE }, - { "TempFileMode", 'F', FALSE }, - { "SaveFromLine", 'f', FALSE }, - { "MatchGECOS", 'G', FALSE }, - { "HelpFile", 'H', FALSE }, - { "MaxHopCount", 'h', FALSE }, - { "ResolverOptions", 'I', FALSE }, - { "IgnoreDots", 'i', TRUE }, - { "ForwardPath", 'J', FALSE }, - { "SendMimeErrors", 'j', TRUE }, - { "ConnectionCacheSize", 'k', FALSE }, - { "ConnectionCacheTimeout", 'K', FALSE }, - { "UseErrorsTo", 'l', FALSE }, - { "LogLevel", 'L', TRUE }, - { "MeToo", 'm', TRUE }, - { "CheckAliases", 'n', FALSE }, - { "OldStyleHeaders", 'o', TRUE }, - { "DaemonPortOptions", 'O', FALSE }, - { "PrivacyOptions", 'p', TRUE }, - { "PostmasterCopy", 'P', FALSE }, - { "QueueFactor", 'q', FALSE }, - { "QueueDirectory", 'Q', FALSE }, - { "DontPruneRoutes", 'R', FALSE }, - { "Timeout", 'r', FALSE }, - { "StatusFile", 'S', FALSE }, - { "SuperSafe", 's', TRUE }, - { "QueueTimeout", 'T', FALSE }, - { "TimeZoneSpec", 't', FALSE }, - { "UserDatabaseSpec", 'U', FALSE }, - { "DefaultUser", 'u', FALSE }, - { "FallbackMXhost", 'V', FALSE }, - { "Verbose", 'v', TRUE }, - { "TryNullMXList", 'w', FALSE }, - { "QueueLA", 'x', FALSE }, - { "RefuseLA", 'X', FALSE }, - { "RecipientFactor", 'y', FALSE }, - { "ForkEachJob", 'Y', FALSE }, - { "ClassFactor", 'z', FALSE }, - { "RetryFactor", 'Z', FALSE }, + { "EightBitMode", '8', OI_SAFE }, +#endif /* MIME8TO7 */ + { "AliasFile", 'A', OI_NONE }, + { "AliasWait", 'a', OI_NONE }, + { "BlankSub", 'B', OI_NONE }, + { "MinFreeBlocks", 'b', OI_SAFE }, + { "CheckpointInterval", 'C', OI_SAFE }, + { "HoldExpensive", 'c', OI_NONE }, +#if !_FFR_REMOVE_AUTOREBUILD + { "AutoRebuildAliases", 'D', OI_NONE }, +#endif /* !_FFR_REMOVE_AUTOREBUILD */ + { "DeliveryMode", 'd', OI_SAFE }, + { "ErrorHeader", 'E', OI_NONE }, + { "ErrorMode", 'e', OI_SAFE }, + { "TempFileMode", 'F', OI_NONE }, + { "SaveFromLine", 'f', OI_NONE }, + { "MatchGECOS", 'G', OI_NONE }, + { "HelpFile", 'H', OI_NONE }, + { "MaxHopCount", 'h', OI_NONE }, + { "ResolverOptions", 'I', OI_NONE }, + { "IgnoreDots", 'i', OI_SAFE }, + { "ForwardPath", 'J', OI_NONE }, + { "SendMimeErrors", 'j', OI_SAFE }, + { "ConnectionCacheSize", 'k', OI_NONE }, + { "ConnectionCacheTimeout", 'K', OI_NONE }, + { "UseErrorsTo", 'l', OI_NONE }, + { "LogLevel", 'L', OI_SAFE }, + { "MeToo", 'm', OI_SAFE }, + { "CheckAliases", 'n', OI_NONE }, + { "OldStyleHeaders", 'o', OI_SAFE }, + { "DaemonPortOptions", 'O', OI_NONE }, + { "PrivacyOptions", 'p', OI_SAFE }, + { "PostmasterCopy", 'P', OI_NONE }, + { "QueueFactor", 'q', OI_NONE }, + { "QueueDirectory", 'Q', OI_NONE }, + { "DontPruneRoutes", 'R', OI_NONE }, + { "Timeout", 'r', OI_SUBOPT }, + { "StatusFile", 'S', OI_NONE }, + { "SuperSafe", 's', OI_SAFE }, + { "QueueTimeout", 'T', OI_NONE }, + { "TimeZoneSpec", 't', OI_NONE }, + { "UserDatabaseSpec", 'U', OI_NONE }, + { "DefaultUser", 'u', OI_NONE }, + { "FallbackMXhost", 'V', OI_NONE }, + { "Verbose", 'v', OI_SAFE }, + { "TryNullMXList", 'w', OI_NONE }, + { "QueueLA", 'x', OI_NONE }, + { "RefuseLA", 'X', OI_NONE }, + { "RecipientFactor", 'y', OI_NONE }, + { "ForkEachJob", 'Y', OI_NONE }, + { "ClassFactor", 'z', OI_NONE }, + { "RetryFactor", 'Z', OI_NONE }, #define O_QUEUESORTORD 0x81 - { "QueueSortOrder", O_QUEUESORTORD, TRUE }, + { "QueueSortOrder", O_QUEUESORTORD, OI_SAFE }, #define O_HOSTSFILE 0x82 - { "HostsFile", O_HOSTSFILE, FALSE }, + { "HostsFile", O_HOSTSFILE, OI_NONE }, #define O_MQA 0x83 - { "MinQueueAge", O_MQA, TRUE }, + { "MinQueueAge", O_MQA, OI_SAFE }, #define O_DEFCHARSET 0x85 - { "DefaultCharSet", O_DEFCHARSET, TRUE }, + { "DefaultCharSet", O_DEFCHARSET, OI_SAFE }, #define O_SSFILE 0x86 - { "ServiceSwitchFile", O_SSFILE, FALSE }, + { "ServiceSwitchFile", O_SSFILE, OI_NONE }, #define O_DIALDELAY 0x87 - { "DialDelay", O_DIALDELAY, TRUE }, + { "DialDelay", O_DIALDELAY, OI_SAFE }, #define O_NORCPTACTION 0x88 - { "NoRecipientAction", O_NORCPTACTION, TRUE }, + { "NoRecipientAction", O_NORCPTACTION, OI_SAFE }, #define O_SAFEFILEENV 0x89 - { "SafeFileEnvironment", O_SAFEFILEENV, FALSE }, + { "SafeFileEnvironment", O_SAFEFILEENV, OI_NONE }, #define O_MAXMSGSIZE 0x8a - { "MaxMessageSize", O_MAXMSGSIZE, FALSE }, + { "MaxMessageSize", O_MAXMSGSIZE, OI_NONE }, #define O_COLONOKINADDR 0x8b - { "ColonOkInAddr", O_COLONOKINADDR, TRUE }, + { "ColonOkInAddr", O_COLONOKINADDR, OI_SAFE }, #define O_MAXQUEUERUN 0x8c - { "MaxQueueRunSize", O_MAXQUEUERUN, TRUE }, + { "MaxQueueRunSize", O_MAXQUEUERUN, OI_SAFE }, #define O_MAXCHILDREN 0x8d - { "MaxDaemonChildren", O_MAXCHILDREN, FALSE }, + { "MaxDaemonChildren", O_MAXCHILDREN, OI_NONE }, #define O_KEEPCNAMES 0x8e - { "DontExpandCnames", O_KEEPCNAMES, FALSE }, + { "DontExpandCnames", O_KEEPCNAMES, OI_NONE }, #define O_MUSTQUOTE 0x8f - { "MustQuoteChars", O_MUSTQUOTE, FALSE }, + { "MustQuoteChars", O_MUSTQUOTE, OI_NONE }, #define O_SMTPGREETING 0x90 - { "SmtpGreetingMessage", O_SMTPGREETING, FALSE }, + { "SmtpGreetingMessage", O_SMTPGREETING, OI_NONE }, #define O_UNIXFROM 0x91 - { "UnixFromLine", O_UNIXFROM, FALSE }, + { "UnixFromLine", O_UNIXFROM, OI_NONE }, #define O_OPCHARS 0x92 - { "OperatorChars", O_OPCHARS, FALSE }, + { "OperatorChars", O_OPCHARS, OI_NONE }, #define O_DONTINITGRPS 0x93 - { "DontInitGroups", O_DONTINITGRPS, FALSE }, + { "DontInitGroups", O_DONTINITGRPS, OI_NONE }, #define O_SLFH 0x94 - { "SingleLineFromHeader", O_SLFH, TRUE }, + { "SingleLineFromHeader", O_SLFH, OI_SAFE }, #define O_ABH 0x95 - { "AllowBogusHELO", O_ABH, TRUE }, + { "AllowBogusHELO", O_ABH, OI_SAFE }, #define O_CONNTHROT 0x97 - { "ConnectionRateThrottle", O_CONNTHROT, FALSE }, + { "ConnectionRateThrottle", O_CONNTHROT, OI_NONE }, #define O_UGW 0x99 - { "UnsafeGroupWrites", O_UGW, FALSE }, + { "UnsafeGroupWrites", O_UGW, OI_NONE }, #define O_DBLBOUNCE 0x9a - { "DoubleBounceAddress", O_DBLBOUNCE, FALSE }, + { "DoubleBounceAddress", O_DBLBOUNCE, OI_NONE }, #define O_HSDIR 0x9b - { "HostStatusDirectory", O_HSDIR, FALSE }, + { "HostStatusDirectory", O_HSDIR, OI_NONE }, #define O_SINGTHREAD 0x9c - { "SingleThreadDelivery", O_SINGTHREAD, FALSE }, + { "SingleThreadDelivery", O_SINGTHREAD, OI_NONE }, #define O_RUNASUSER 0x9d - { "RunAsUser", O_RUNASUSER, FALSE }, -#if _FFR_DSN_RRT_OPTION + { "RunAsUser", O_RUNASUSER, OI_NONE }, #define O_DSN_RRT 0x9e - { "RrtImpliesDsn", O_DSN_RRT, FALSE }, -#endif -#if _FFR_PIDFILE_OPTION + { "RrtImpliesDsn", O_DSN_RRT, OI_NONE }, #define O_PIDFILE 0x9f - { "PidFile", O_PIDFILE, FALSE }, -#endif + { "PidFile", O_PIDFILE, OI_NONE }, #define O_DONTBLAMESENDMAIL 0xa0 - { "DontBlameSendmail", O_DONTBLAMESENDMAIL, FALSE }, + { "DontBlameSendmail", O_DONTBLAMESENDMAIL, OI_NONE }, #define O_DPI 0xa1 - { "DontProbeInterfaces", O_DPI, FALSE }, + { "DontProbeInterfaces", O_DPI, OI_NONE }, #define O_MAXRCPT 0xa2 - { "MaxRecipientsPerMessage", O_MAXRCPT, FALSE }, -#if _FFR_DEADLETTERDROP_OPTION + { "MaxRecipientsPerMessage", O_MAXRCPT, OI_SAFE }, #define O_DEADLETTER 0xa3 - { "DeadLetterDrop", O_DEADLETTER, FALSE }, -#endif + { "DeadLetterDrop", O_DEADLETTER, OI_NONE }, #if _FFR_DONTLOCKFILESFORREAD_OPTION -#define O_DONTLOCK 0xa4 - { "DontLockFilesForRead", O_DONTLOCK, FALSE }, -#endif -#if _FFR_MAXALIASRECURSION_OPTION +# define O_DONTLOCK 0xa4 + { "DontLockFilesForRead", O_DONTLOCK, OI_NONE }, +#endif /* _FFR_DONTLOCKFILESFORREAD_OPTION */ #define O_MAXALIASRCSN 0xa5 - { "MaxAliasRecursion", O_MAXALIASRCSN, FALSE }, -#endif -#if _FFR_CONNECTONLYTO_OPTION + { "MaxAliasRecursion", O_MAXALIASRCSN, OI_NONE }, #define O_CNCTONLYTO 0xa6 - { "ConnectOnlyTo", O_CNCTONLYTO, FALSE }, -#endif -#if _FFR_TRUSTED_USER + { "ConnectOnlyTo", O_CNCTONLYTO, OI_NONE }, #define O_TRUSTUSER 0xa7 - { "TrustedUser", O_TRUSTUSER, FALSE }, -#endif -#if _FFR_MAX_MIME_HEADER_LENGTH + { "TrustedUser", O_TRUSTUSER, OI_NONE }, #define O_MAXMIMEHDRLEN 0xa8 - { "MaxMimeHeaderLength", O_MAXMIMEHDRLEN, FALSE }, -#endif -#if _FFR_CONTROL_SOCKET + { "MaxMimeHeaderLength", O_MAXMIMEHDRLEN, OI_NONE }, #define O_CONTROLSOCKET 0xa9 - { "ControlSocketName", O_CONTROLSOCKET, FALSE }, -#endif -#if _FFR_MAX_HEADERS_LENGTH + { "ControlSocketName", O_CONTROLSOCKET, OI_NONE }, #define O_MAXHDRSLEN 0xaa - { "MaxHeadersLength", O_MAXHDRSLEN, FALSE }, -#endif - { NULL, '\0', FALSE } + { "MaxHeadersLength", O_MAXHDRSLEN, OI_NONE }, +#if _FFR_MAX_FORWARD_ENTRIES +# define O_MAXFORWARD 0xab + { "MaxForwardEntries", O_MAXFORWARD, OI_NONE }, +#endif /* _FFR_MAX_FORWARD_ENTRIES */ +#define O_PROCTITLEPREFIX 0xac + { "ProcessTitlePrefix", O_PROCTITLEPREFIX, OI_NONE }, +#define O_SASLINFO 0xad +#if _FFR_ALLOW_SASLINFO + { "DefaultAuthInfo", O_SASLINFO, OI_SAFE }, +#else /* _FFR_ALLOW_SASLINFO */ + { "DefaultAuthInfo", O_SASLINFO, OI_NONE }, +#endif /* _FFR_ALLOW_SASLINFO */ +#define O_SASLMECH 0xae + { "AuthMechanisms", O_SASLMECH, OI_NONE }, +#define O_CLIENTPORT 0xaf + { "ClientPortOptions", O_CLIENTPORT, OI_NONE }, +#define O_DF_BUFSIZE 0xb0 + { "DataFileBufferSize", O_DF_BUFSIZE, OI_NONE }, +#define O_XF_BUFSIZE 0xb1 + { "XscriptFileBufferSize", O_XF_BUFSIZE, OI_NONE }, +# define O_LDAPDEFAULTSPEC 0xb2 + { "LDAPDefaultSpec", O_LDAPDEFAULTSPEC, OI_NONE }, +#if _FFR_QUEUEDELAY +#define O_QUEUEDELAY 0xb3 + { "QueueDelay", O_QUEUEDELAY, OI_NONE }, +#endif /* _FFR_QUEUEDELAY */ +# define O_SRVCERTFILE 0xb4 + { "ServerCertFile", O_SRVCERTFILE, OI_NONE }, +# define O_SRVKEYFILE 0xb5 + { "Serverkeyfile", O_SRVKEYFILE, OI_NONE }, +# define O_CLTCERTFILE 0xb6 + { "ClientCertFile", O_CLTCERTFILE, OI_NONE }, +# define O_CLTKEYFILE 0xb7 + { "Clientkeyfile", O_CLTKEYFILE, OI_NONE }, +# define O_CACERTFILE 0xb8 + { "CACERTFile", O_CACERTFILE, OI_NONE }, +# define O_CACERTPATH 0xb9 + { "CACERTPath", O_CACERTPATH, OI_NONE }, +# define O_DHPARAMS 0xba + { "DHParameters", O_DHPARAMS, OI_NONE }, +#if _FFR_MILTER +#define O_INPUTMILTER 0xbb + { "InputMailFilters", O_INPUTMILTER, OI_NONE }, +#define O_MILTER 0xbc + { "Milter", O_MILTER, OI_SUBOPT }, +#endif /* _FFR_MILTER */ +#define O_SASLOPTS 0xbd + { "AuthOptions", O_SASLOPTS, OI_NONE }, +#if _FFR_QUEUE_FILE_MODE +#define O_QUEUE_FILE_MODE 0xbe + { "QueueFileMode", O_QUEUE_FILE_MODE, OI_NONE }, +#endif /* _FFR_QUEUE_FILE_MODE */ +# if _FFR_TLS_1 +# define O_DHPARAMS5 0xbf + { "DHParameters512", O_DHPARAMS5, OI_NONE }, +# define O_CIPHERLIST 0xc0 + { "CipherList", O_CIPHERLIST, OI_NONE }, +# endif /* _FFR_TLS_1 */ +# define O_RANDFILE 0xc1 + { "RandFile", O_RANDFILE, OI_NONE }, + { NULL, '\0', OI_NONE } }; - - void setoption(opt, val, safe, sticky, e) int opt; @@ -1551,15 +1727,10 @@ setoption(opt, val, safe, sticky, e) bool can_setuid = RunAsUid == 0; auto char *ep; char buf[50]; - extern bool atobool __P((char *)); - extern time_t convtime __P((char *, char)); - extern int QueueLA; - extern int RefuseLA; extern bool Warn_Q_option; - extern void setalias __P((char *)); - extern int atooct __P((char *)); - extern void setdefuser __P((void)); - extern void setdaemonoptions __P((char *)); +#if _FFR_ALLOW_SASLINFO + extern int SubmitMode; +#endif /* _FFR_ALLOW_SASLINFO */ errno = 0; if (opt == ' ') @@ -1636,13 +1807,23 @@ setoption(opt, val, safe, sticky, e) subopt = NULL; } + if (subopt != NULL && !bitset(OI_SUBOPT, o->o_flags)) + { + if (tTd(37, 1)) + dprintf("setoption: %s does not support suboptions, ignoring .%s\n", + o->o_name == NULL ? "<unknown>" : o->o_name, + subopt); + subopt = NULL; + } + if (tTd(37, 1)) { - printf(isascii(opt) && isprint(opt) ? - "setoption %s (%c).%s=" : - "setoption %s (0x%x).%s=", + dprintf(isascii(opt) && isprint(opt) ? + "setoption %s (%c)%s%s=" : + "setoption %s (0x%x)%s%s=", o->o_name == NULL ? "<unknown>" : o->o_name, opt, + subopt == NULL ? "" : ".", subopt == NULL ? "" : subopt); xputs(val); } @@ -1654,7 +1835,7 @@ setoption(opt, val, safe, sticky, e) if (!sticky && bitnset(opt, StickyOpt)) { if (tTd(37, 1)) - printf(" (ignored)\n"); + dprintf(" (ignored)\n"); return; } @@ -1664,17 +1845,20 @@ setoption(opt, val, safe, sticky, e) if (!safe && RealUid == 0) safe = TRUE; - if (!safe && !o->o_safe) + if (!safe && !bitset(OI_SAFE, o->o_flags)) { if (opt != 'M' || (val[0] != 'r' && val[0] != 's')) { + int dp; + if (tTd(37, 1)) - printf(" (unsafe)"); - (void) drop_privileges(TRUE); + dprintf(" (unsafe)"); + dp = drop_privileges(TRUE); + setstat(dp); } } if (tTd(37, 1)) - printf("\n"); + dprintf("\n"); switch (opt & 0xff) { @@ -1698,7 +1882,7 @@ setoption(opt, val, safe, sticky, e) MimeMode = MM_CVTMIME; break; -#if 0 +# if 0 case 'r': /* reject 8-bit, don't convert MIME */ MimeMode = 0; break; @@ -1714,14 +1898,14 @@ setoption(opt, val, safe, sticky, e) case 'c': /* convert 8 bit to MIME, never 7 bit */ MimeMode = MM_MIME8BIT; break; -#endif +# endif /* 0 */ default: syserr("Unknown 8-bit mode %c", *val); finis(FALSE, EX_USAGE); } break; -#endif +#endif /* MIME8TO7 */ case 'A': /* set default alias file */ if (val[0] == '\0') @@ -1765,33 +1949,32 @@ setoption(opt, val, safe, sticky, e) switch (*val) { case '\0': - e->e_sendmode = SM_DELIVER; + set_delivery_mode(SM_DELIVER, e); break; case SM_QUEUE: /* queue only */ case SM_DEFER: /* queue only and defer map lookups */ #if !QUEUE syserr("need QUEUE to set -odqueue or -oddefer"); -#endif /* QUEUE */ - /* fall through..... */ +#endif /* !QUEUE */ + /* FALLTHROUGH */ case SM_DELIVER: /* do everything */ case SM_FORK: /* fork after verification */ - e->e_sendmode = *val; + set_delivery_mode(*val, e); break; default: syserr("Unknown delivery mode %c", *val); finis(FALSE, EX_USAGE); } - buf[0] = (char)e->e_sendmode; - buf[1] = '\0'; - define(macid("{deliveryMode}", NULL), newstr(buf), e); break; +#if !_FFR_REMOVE_AUTOREBUILD case 'D': /* rebuild alias database as needed */ AutoRebuild = atobool(val); break; +#endif /* !_FFR_REMOVE_AUTOREBUILD */ case 'E': /* error message header/header file */ if (*val != '\0') @@ -1843,7 +2026,7 @@ setoption(opt, val, safe, sticky, e) case 'H': /* help file */ if (val[0] == '\0') - HelpFile = "sendmail.hf"; + HelpFile = "helpfile"; else HelpFile = newstr(val); break; @@ -1893,11 +2076,11 @@ setoption(opt, val, safe, sticky, e) _res.options |= rfp->rf_bits; } if (tTd(8, 2)) - printf("_res.options = %x, HasWildcardMX = %d\n", + dprintf("_res.options = %x, HasWildcardMX = %d\n", (u_int) _res.options, HasWildcardMX); -#else +#else /* NAMED_BIND */ usrerr("name server (I option) specified but BIND not compiled in"); -#endif +#endif /* NAMED_BIND */ break; case 'i': /* ignore dot lines in message */ @@ -1952,10 +2135,13 @@ setoption(opt, val, safe, sticky, e) case 'O': /* daemon options */ #if DAEMON - setdaemonoptions(val); -#else + if (!setdaemonoptions(val)) + { + syserr("too many daemons defined (%d max)", MAXDAEMONS); + } +#else /* DAEMON */ syserr("DaemonPortOptions (O option) set but DAEMON not compiled in"); -#endif +#endif /* DAEMON */ break; case 'o': /* assume old style headers */ @@ -2017,14 +2203,14 @@ setoption(opt, val, safe, sticky, e) case 'r': /* read timeout */ if (subopt == NULL) - inittimeouts(val); + inittimeouts(val, sticky); else - settimeout(subopt, val); + settimeout(subopt, val, sticky); break; case 'S': /* status file */ if (val[0] == '\0') - StatFile = "sendmail.st"; + StatFile = "statistics"; else StatFile = newstr(val); break; @@ -2038,9 +2224,9 @@ setoption(opt, val, safe, sticky, e) if (p != NULL) { *p++ = '\0'; - settimeout("queuewarn", p); + settimeout("queuewarn", p, sticky); } - settimeout("queuereturn", val); + settimeout("queuereturn", val, sticky); break; case 't': /* time zone name */ @@ -2087,7 +2273,7 @@ setoption(opt, val, safe, sticky, e) syserr("readcf: option u: uid value (%ld) > UID_MAX (%ld); ignored", DefUid, UID_MAX); } -#endif +#endif /* UID_MAX */ /* handle the group if it is there */ if (*p == '\0') @@ -2134,22 +2320,28 @@ setoption(opt, val, safe, sticky, e) WkTimeFact = atoi(val); break; + case O_QUEUESORTORD: /* queue sorting order */ switch (*val) { case 'h': /* Host first */ case 'H': - QueueSortOrder = QS_BYHOST; + QueueSortOrder = QSO_BYHOST; break; case 'p': /* Priority order */ case 'P': - QueueSortOrder = QS_BYPRIORITY; + QueueSortOrder = QSO_BYPRIORITY; break; case 't': /* Submission time */ case 'T': - QueueSortOrder = QS_BYTIME; + QueueSortOrder = QSO_BYTIME; + break; + + case 'f': /* File Name */ + case 'F': + QueueSortOrder = QSO_BYFILENAME; break; default: @@ -2157,6 +2349,43 @@ setoption(opt, val, safe, sticky, e) } break; +#if _FFR_QUEUEDELAY + case O_QUEUEDELAY: /* queue delay algorithm */ + switch (*val) + { + case 'e': /* exponential */ + case 'E': + QueueAlg = QD_EXP; + QueueInitDelay = 10 MINUTES; + QueueMaxDelay = 2 HOURS; + p = strchr(val, '/'); + if (p != NULL) + { + char *q; + + *p++ = '\0'; + q = strchr(p, '/'); + if (q != NULL) + *q++ = '\0'; + QueueInitDelay = convtime(p, 's'); + if (q != NULL) + { + QueueMaxDelay = convtime(q, 's'); + } + } + break; + + case 'l': /* linear */ + case 'L': + QueueAlg = QD_LINEAR; + break; + + default: + syserr("Invalid queue delay algorithm \"%s\"", val); + } + break; +#endif /* _FFR_QUEUEDELAY */ + case O_HOSTSFILE: /* pathname of /etc/hosts file */ HostsFile = newstr(val); break; @@ -2212,14 +2441,22 @@ setoption(opt, val, safe, sticky, e) MaxChildren = atoi(val); break; +#if _FFR_MAX_FORWARD_ENTRIES + case O_MAXFORWARD: /* max # of forward entries */ + MaxForwardEntries = atoi(val); + break; +#endif /* _FFR_MAX_FORWARD_ENTRIES */ + case O_KEEPCNAMES: /* don't expand CNAME records */ DontExpandCnames = atobool(val); break; case O_MUSTQUOTE: /* must quote these characters in phrases */ - strcpy(buf, "@,;:\\()[]"); + (void) strlcpy(buf, "@,;:\\()[]", sizeof buf); if (strlen(val) < (SIZE_T) sizeof buf - 10) - strcat(buf, val); + (void) strlcat(buf, val, sizeof buf); + else + printf("Warning: MustQuoteChars too long, ignored.\n"); MustQuoteChars = newstr(buf); break; @@ -2232,6 +2469,8 @@ setoption(opt, val, safe, sticky, e) break; case O_OPCHARS: /* operator characters (old $o macro) */ + if (OperatorChars != NULL) + printf("Warning: OperatorChars is being redefined.\n It should only be set before ruleset definitions.\n"); OperatorChars = newstr(munchstring(val, NULL, '\0')); break; @@ -2253,7 +2492,12 @@ setoption(opt, val, safe, sticky, e) case O_UGW: /* group writable files are unsafe */ if (!atobool(val)) - DontBlameSendmail |= DBS_GROUPWRITABLEFORWARDFILESAFE|DBS_GROUPWRITABLEINCLUDEFILESAFE; + { + setbitn(DBS_GROUPWRITABLEFORWARDFILESAFE, + DontBlameSendmail); + setbitn(DBS_GROUPWRITABLEINCLUDEFILESAFE, + DontBlameSendmail); + } break; case O_DBLBOUNCE: /* address to which to send double bounces */ @@ -2307,7 +2551,7 @@ setoption(opt, val, safe, sticky, e) syserr("readcf: option RunAsUser: uid value (%ld) > UID_MAX (%ld); ignored", RunAsUid, UID_MAX); } -#endif +#endif /* UID_MAX */ if (*p != '\0') { if (isascii(*p) && isdigit(*p)) @@ -2318,7 +2562,7 @@ setoption(opt, val, safe, sticky, e) else { register struct group *gr; - + gr = getgrnam(p); if (gr == NULL) syserr("readcf: option RunAsUser: unknown group %s", @@ -2328,21 +2572,19 @@ setoption(opt, val, safe, sticky, e) } } if (tTd(47, 5)) - printf("readcf: RunAsUser = %d:%d\n", (int)RunAsUid, (int)RunAsGid); + dprintf("readcf: RunAsUser = %d:%d\n", + (int)RunAsUid, (int)RunAsGid); break; -#if _FFR_DSN_RRT_OPTION case O_DSN_RRT: RrtImpliesDsn = atobool(val); break; -#endif -#if _FFR_PIDFILE_OPTION case O_PIDFILE: - free(PidFile); + if (PidFile != NULL) + free(PidFile); PidFile = newstr(val); break; -#endif case O_DONTBLAMESENDMAIL: p = val; @@ -2370,9 +2612,9 @@ setoption(opt, val, safe, sticky, e) if (dbs->dbs_name == NULL) syserr("readcf: DontBlameSendmail option: %s unrecognized", val); else if (dbs->dbs_flag == DBS_SAFE) - DontBlameSendmail = DBS_SAFE; + clrbitmap(DontBlameSendmail); else - DontBlameSendmail |= dbs->dbs_flag; + setbitn(dbs->dbs_flag, DontBlameSendmail); } sticky = FALSE; break; @@ -2385,35 +2627,45 @@ setoption(opt, val, safe, sticky, e) MaxRcptPerMsg = atoi(val); break; -#if _FFR_DEADLETTERDROP_OPTION case O_DEADLETTER: if (DeadLetterDrop != NULL) free(DeadLetterDrop); DeadLetterDrop = newstr(val); break; -#endif #if _FFR_DONTLOCKFILESFORREAD_OPTION case O_DONTLOCK: DontLockReadFiles = atobool(val); break; -#endif +#endif /* _FFR_DONTLOCKFILESFORREAD_OPTION */ -#if _FFR_MAXALIASRECURSION_OPTION case O_MAXALIASRCSN: MaxAliasRecursion = atoi(val); break; -#endif -#if _FFR_CONNECTONLYTO_OPTION case O_CNCTONLYTO: /* XXX should probably use gethostbyname */ - ConnectOnlyTo = inet_addr(val); +#if NETINET || NETINET6 +# if NETINET6 + if (inet_addr(val) == INADDR_NONE) + { + ConnectOnlyTo.sa.sa_family = AF_INET6; + if (inet_pton(AF_INET6, val, + &ConnectOnlyTo.sin6.sin6_addr) != 1) + syserr("readcf: option ConnectOnlyTo: invalid IP address %s", + val); + } + else +# endif /* NETINET6 */ + { + ConnectOnlyTo.sa.sa_family = AF_INET; + ConnectOnlyTo.sin.sin_addr.s_addr = inet_addr(val); + } +#endif /* NETINET || NETINET6 */ break; -#endif -#if _FFR_TRUSTED_USER case O_TRUSTUSER: +#if HASFCHOWN if (isascii(*val) && isdigit(*val)) TrustedUid = atoi(val); else @@ -2428,18 +2680,19 @@ setoption(opt, val, safe, sticky, e) TrustedUid = pw->pw_uid; } -#ifdef UID_MAX +# ifdef UID_MAX if (TrustedUid > UID_MAX) { syserr("readcf: option TrustedUser: uid value (%ld) > UID_MAX (%ld)", TrustedUid, UID_MAX); TrustedUid = 0; } -#endif +# endif /* UID_MAX */ +#else /* HASFCHOWN */ + syserr("readcf: option TrustedUser: can not be used on systems which do not support fchown()"); +#endif /* HASFCHOWN */ break; -#endif -#if _FFR_MAX_MIME_HEADER_LENGTH case O_MAXMIMEHDRLEN: p = strchr(val, '/'); if (p != NULL) @@ -2460,37 +2713,257 @@ setoption(opt, val, safe, sticky, e) else if (MaxMimeFieldLength < 40) printf("Warning: MaxMimeHeaderLength: field length limit set lower than 40\n"); break; -#endif -#if _FFR_CONTROL_SOCKET case O_CONTROLSOCKET: if (ControlSocketName != NULL) free(ControlSocketName); ControlSocketName = newstr(val); break; -#endif -#if _FFR_MAX_HEADERS_LENGTH case O_MAXHDRSLEN: MaxHeadersLength = atoi(val); if (MaxHeadersLength > 0 && MaxHeadersLength < (MAXHDRSLEN / 2)) - printf("Warning: MaxHeadersLength: headers length limit set lower than %d\n", MAXHDRSLEN); + printf("Warning: MaxHeadersLength: headers length limit set lower than %d\n", (MAXHDRSLEN / 2)); + break; + + case O_PROCTITLEPREFIX: + if (ProcTitlePrefix != NULL) + free(ProcTitlePrefix); + ProcTitlePrefix = newstr(val); + break; + +#if SASL + case O_SASLINFO: +#if _FFR_ALLOW_SASLINFO + /* + ** Allow users to select their own authinfo file. + ** However, this is not a "perfect" solution. + ** If mail is queued, the authentication info + ** will not be used in subsequent delivery attempts. + ** If we really want to support this, then it has + ** to be stored in the queue file. + */ + if (!bitset(SUBMIT_MSA, SubmitMode) && RealUid != 0 && + RunAsUid != RealUid) + { + errno = 0; + syserr("Error: %s only allowed with -U\n", + o->o_name == NULL ? "<unknown>" : o->o_name); + ExitStat = EX_USAGE; + break; + } +#endif /* _FFR_ALLOW_SASLINFO */ + if (SASLInfo != NULL) + free(SASLInfo); + SASLInfo = newstr(val); + break; + + case O_SASLMECH: + if (AuthMechanisms != NULL) + free(AuthMechanisms); + if (*val != '\0') + AuthMechanisms = newstr(val); + else + AuthMechanisms = NULL; + break; + + case O_SASLOPTS: + while (val != NULL && *val != '\0') + { + switch(*val) + { + case 'A': + SASLOpts |= SASL_AUTH_AUTH; + break; +# if _FFR_SASL_OPTS + case 'a': + SASLOpts |= SASL_SEC_NOACTIVE; + break; + case 'c': + SASLOpts |= SASL_SEC_PASS_CREDENTIALS; + break; + case 'd': + SASLOpts |= SASL_SEC_NODICTIONARY; + break; + case 'f': + SASLOpts |= SASL_SEC_FORWARD_SECRECY; + break; + case 'p': + SASLOpts |= SASL_SEC_NOPLAINTEXT; + break; + case 'y': + SASLOpts |= SASL_SEC_NOANONYMOUS; + break; +# endif /* _FFR_SASL_OPTS */ + default: + printf("Warning: Option: %s unknown parameter '%c'\n", + o->o_name == NULL ? "<unknown>" + : o->o_name, + (isascii(*val) && isprint(*val)) ? *val + : '?'); + break; + } + ++val; + val = strpbrk(val, ", \t"); + if (val != NULL) + ++val; + } + break; + +#else /* SASL */ + case O_SASLINFO: + case O_SASLMECH: + case O_SASLOPTS: + printf("Warning: Option: %s requires SASL support (-DSASL)\n", + o->o_name == NULL ? "<unknown>" : o->o_name); + break; +#endif /* SASL */ + +#if STARTTLS + case O_SRVCERTFILE: + if (SrvCERTfile != NULL) + free(SrvCERTfile); + SrvCERTfile = newstr(val); + break; + + case O_SRVKEYFILE: + if (Srvkeyfile != NULL) + free(Srvkeyfile); + Srvkeyfile = newstr(val); + break; + + case O_CLTCERTFILE: + if (CltCERTfile != NULL) + free(CltCERTfile); + CltCERTfile = newstr(val); + break; + + case O_CLTKEYFILE: + if (Cltkeyfile != NULL) + free(Cltkeyfile); + Cltkeyfile = newstr(val); + break; + + case O_CACERTFILE: + if (CACERTfile != NULL) + free(CACERTfile); + CACERTfile = newstr(val); + break; + + case O_CACERTPATH: + if (CACERTpath != NULL) + free(CACERTpath); + CACERTpath = newstr(val); + break; + + case O_DHPARAMS: + if (DHParams != NULL) + free(DHParams); + DHParams = newstr(val); + break; + +# if _FFR_TLS_1 + case O_DHPARAMS5: + if (DHParams5 != NULL) + free(DHParams5); + DHParams5 = newstr(val); + break; + + case O_CIPHERLIST: + if (CipherList != NULL) + free(CipherList); + CipherList = newstr(val); + break; +# endif /* _FFR_TLS_1 */ + + case O_RANDFILE: + if (RandFile != NULL) + free(RandFile); + RandFile= newstr(val); + break; + +# else /* STARTTLS */ + case O_SRVCERTFILE: + case O_SRVKEYFILE: + case O_CLTCERTFILE: + case O_CLTKEYFILE: + case O_CACERTFILE: + case O_CACERTPATH: + case O_DHPARAMS: +# if _FFR_TLS_1 + case O_DHPARAMS5: + case O_CIPHERLIST: +# endif /* _FFR_TLS_1 */ + case O_RANDFILE: + printf("Warning: Option: %s requires TLS support\n", + o->o_name == NULL ? "<unknown>" : o->o_name); + break; + +# endif /* STARTTLS */ + + case O_CLIENTPORT: +#if DAEMON + setclientoptions(val); +#else /* DAEMON */ + syserr("ClientPortOptions (O option) set but DAEMON not compiled in"); +#endif /* DAEMON */ + break; + + case O_DF_BUFSIZE: + DataFileBufferSize = atoi(val); break; -#endif + + case O_XF_BUFSIZE: + XscriptFileBufferSize = atoi(val); + break; + + case O_LDAPDEFAULTSPEC: +#ifdef LDAPMAP + ldapmap_set_defaults(val); +#else /* LDAPMAP */ + printf("Warning: Option: %s requires LDAP support (-DLDAPMAP)\n", + o->o_name == NULL ? "<unknown>" : o->o_name); +#endif /* LDAPMAP */ + break; + +#if _FFR_MILTER + case O_INPUTMILTER: + InputFilterList = newstr(val); + break; + + case O_MILTER: + milter_set_option(subopt, val, sticky); + break; +#endif /* _FFR_MILTER */ + +#if _FFR_QUEUE_FILE_MODE + case O_QUEUE_FILE_MODE: /* queue file mode */ + QueueFileMode = atooct(val) & 0777; + break; +#endif /* _FFR_QUEUE_FILE_MODE */ default: if (tTd(37, 1)) { if (isascii(opt) && isprint(opt)) - printf("Warning: option %c unknown\n", opt); + dprintf("Warning: option %c unknown\n", opt); else - printf("Warning: option 0x%x unknown\n", opt); + dprintf("Warning: option 0x%x unknown\n", opt); } break; } - if (sticky) + + /* + ** Options with suboptions are responsible for taking care + ** of sticky-ness (e.g., that a command line setting is kept + ** when reading in the sendmail.cf file). This has to be done + ** when the suboptions are parsed since each suboption must be + ** sticky, not the root option. + */ + + if (sticky && !bitset(OI_SUBOPT, o->o_flags)) setbitn(opt, StickyOpt); } /* @@ -2514,10 +2987,28 @@ setclass(class, str) { register STAB *s; - if (tTd(37, 8)) - printf("setclass(%s, %s)\n", macname(class), str); - s = stab(str, ST_CLASS, ST_ENTER); - setbitn(class, s->s_class); + if ((*str & 0377) == MATCHCLASS) + { + int mid; + + str++; + mid = macid(str, NULL); + if (mid == '\0') + return; + + if (tTd(37, 8)) + dprintf("setclass(%s, $=%s)\n", + macname(class), macname(mid)); + copy_class(mid, class); + } + else + { + if (tTd(37, 8)) + dprintf("setclass(%s, %s)\n", macname(class), str); + + s = stab(str, ST_CLASS, ST_ENTER); + setbitn(class, s->s_class); + } } /* ** MAKEMAPENTRY -- create a map entry @@ -2589,11 +3080,11 @@ makemapentry(line) if (tTd(37, 5)) { - printf("map %s, class %s, flags %lx, file %s,\n", + dprintf("map %s, class %s, flags %lx, file %s,\n", s->s_map.map_mname, s->s_map.map_class->map_cname, s->s_map.map_mflags, s->s_map.map_file == NULL ? "(null)" : s->s_map.map_file); - printf("\tapp %s, domain %s, rebuild %s\n", + dprintf("\tapp %s, domain %s, rebuild %s\n", s->s_map.map_app == NULL ? "(null)" : s->s_map.map_app, s->s_map.map_domain == NULL ? "(null)" : s->s_map.map_domain, s->s_map.map_rebuild == NULL ? "(null)" : s->s_map.map_rebuild); @@ -2645,7 +3136,7 @@ strtorwset(p, endp, stabmode) { STAB *s; char delim; - char *q; + char *q = NULL; q = p; while (*p != '\0' && isascii(*p) && @@ -2693,7 +3184,7 @@ strtorwset(p, endp, stabmode) { if (endp != NULL) *endp = p; - if (s->s_ruleset > 0) + if (s->s_ruleset >= 0) ruleset = s->s_ruleset; else if ((ruleset = --nextruleset) < MAXRWSETS / 2) { @@ -2702,25 +3193,322 @@ strtorwset(p, endp, stabmode) ruleset = -1; } } - if (s->s_ruleset > 0 && ruleset >= 0 && ruleset != s->s_ruleset) + if (s->s_ruleset >= 0 && + ruleset >= 0 && + ruleset != s->s_ruleset) { syserr("%s: ruleset changed value (old %d, new %d)", q, s->s_ruleset, ruleset); ruleset = s->s_ruleset; } - else if (ruleset > 0) + else if (ruleset >= 0) { s->s_ruleset = ruleset; } + if (stabmode == ST_ENTER) + { + char *h = NULL; + + if (RuleSetNames[ruleset] != NULL) + free(RuleSetNames[ruleset]); + if (delim != '\0' && (h = strchr(q, delim)) != NULL) + *h = '\0'; + RuleSetNames[ruleset] = newstr(q); + if (delim == '/' && h != NULL) + *h = delim; /* put back delim */ + } } return ruleset; } /* +** SETTIMEOUT -- set an individual timeout +** +** Parameters: +** name -- the name of the timeout. +** val -- the value of the timeout. +** sticky -- if set, don't let other setoptions override +** this value. +** +** Returns: +** none. +*/ + +/* set if Timeout sub-option is stuck */ +static BITMAP256 StickyTimeoutOpt; + +static struct timeoutinfo +{ + char *to_name; /* long name of timeout */ + u_char to_code; /* code for option */ +} TimeOutTab[] = +{ +#define TO_INITIAL 0x01 + { "initial", TO_INITIAL }, +#define TO_MAIL 0x02 + { "mail", TO_MAIL }, +#define TO_RCPT 0x03 + { "rcpt", TO_RCPT }, +#define TO_DATAINIT 0x04 + { "datainit", TO_DATAINIT }, +#define TO_DATABLOCK 0x05 + { "datablock", TO_DATABLOCK }, +#define TO_DATAFINAL 0x06 + { "datafinal", TO_DATAFINAL }, +#define TO_COMMAND 0x07 + { "command", TO_COMMAND }, +#define TO_RSET 0x08 + { "rset", TO_RSET }, +#define TO_HELO 0x09 + { "helo", TO_HELO }, +#define TO_QUIT 0x0A + { "quit", TO_QUIT }, +#define TO_MISC 0x0B + { "misc", TO_MISC }, +#define TO_IDENT 0x0C + { "ident", TO_IDENT }, +#define TO_FILEOPEN 0x0D + { "fileopen", TO_FILEOPEN }, +#define TO_CONNECT 0x0E + { "connect", TO_CONNECT }, +#define TO_ICONNECT 0x0F + { "iconnect", TO_ICONNECT }, +#define TO_QUEUEWARN 0x10 + { "queuewarn", TO_QUEUEWARN }, + { "queuewarn.*", TO_QUEUEWARN }, +#define TO_QUEUEWARN_NORMAL 0x11 + { "queuewarn.normal", TO_QUEUEWARN_NORMAL }, +#define TO_QUEUEWARN_URGENT 0x12 + { "queuewarn.urgent", TO_QUEUEWARN_URGENT }, +#define TO_QUEUEWARN_NON_URGENT 0x13 + { "queuewarn.non-urgent", TO_QUEUEWARN_NON_URGENT }, +#define TO_QUEUERETURN 0x14 + { "queuereturn", TO_QUEUERETURN }, + { "queuereturn.*", TO_QUEUERETURN }, +#define TO_QUEUERETURN_NORMAL 0x15 + { "queuereturn.normal", TO_QUEUERETURN_NORMAL }, +#define TO_QUEUERETURN_URGENT 0x16 + { "queuereturn.urgent", TO_QUEUERETURN_URGENT }, +#define TO_QUEUERETURN_NON_URGENT 0x17 + { "queuereturn.non-urgent", TO_QUEUERETURN_NON_URGENT }, +#define TO_HOSTSTATUS 0x18 + { "hoststatus", TO_HOSTSTATUS }, +#define TO_RESOLVER_RETRANS 0x19 + { "resolver.retrans", TO_RESOLVER_RETRANS }, +#define TO_RESOLVER_RETRANS_NORMAL 0x1A + { "resolver.retrans.normal", TO_RESOLVER_RETRANS_NORMAL }, +#define TO_RESOLVER_RETRANS_FIRST 0x1B + { "resolver.retrans.first", TO_RESOLVER_RETRANS_FIRST }, +#define TO_RESOLVER_RETRY 0x1C + { "resolver.retry", TO_RESOLVER_RETRY }, +#define TO_RESOLVER_RETRY_NORMAL 0x1D + { "resolver.retry.normal", TO_RESOLVER_RETRY_NORMAL }, +#define TO_RESOLVER_RETRY_FIRST 0x1E + { "resolver.retry.first", TO_RESOLVER_RETRY_FIRST }, +#define TO_CONTROL 0x1F + { "control", TO_CONTROL }, + { NULL, 0 }, +}; + + +static void +settimeout(name, val, sticky) + char *name; + char *val; + bool sticky; +{ + register struct timeoutinfo *to; + int i; + time_t toval; + + if (tTd(37, 2)) + dprintf("settimeout(%s = %s)", name, val); + + for (to = TimeOutTab; to->to_name != NULL; to++) + { + if (strcasecmp(to->to_name, name) == 0) + break; + } + + if (to->to_name == NULL) + syserr("settimeout: invalid timeout %s", name); + + /* + ** See if this option is preset for us. + */ + + if (!sticky && bitnset(to->to_code, StickyTimeoutOpt)) + { + if (tTd(37, 2)) + dprintf(" (ignored)\n"); + return; + } + + if (tTd(37, 2)) + dprintf("\n"); + + toval = convtime(val, 'm'); + + switch (to->to_code) + { + case TO_INITIAL: + TimeOuts.to_initial = toval; + break; + + case TO_MAIL: + TimeOuts.to_mail = toval; + break; + + case TO_RCPT: + TimeOuts.to_rcpt = toval; + break; + + case TO_DATAINIT: + TimeOuts.to_datainit = toval; + break; + + case TO_DATABLOCK: + TimeOuts.to_datablock = toval; + break; + + case TO_DATAFINAL: + TimeOuts.to_datafinal = toval; + break; + + case TO_COMMAND: + TimeOuts.to_nextcommand = toval; + break; + + case TO_RSET: + TimeOuts.to_rset = toval; + break; + + case TO_HELO: + TimeOuts.to_helo = toval; + break; + + case TO_QUIT: + TimeOuts.to_quit = toval; + break; + + case TO_MISC: + TimeOuts.to_miscshort = toval; + break; + + case TO_IDENT: + TimeOuts.to_ident = toval; + break; + + case TO_FILEOPEN: + TimeOuts.to_fileopen = toval; + break; + + case TO_CONNECT: + TimeOuts.to_connect = toval; + break; + + case TO_ICONNECT: + TimeOuts.to_iconnect = toval; + break; + + case TO_QUEUEWARN: + toval = convtime(val, 'h'); + TimeOuts.to_q_warning[TOC_NORMAL] = toval; + TimeOuts.to_q_warning[TOC_URGENT] = toval; + TimeOuts.to_q_warning[TOC_NONURGENT] = toval; + break; + + case TO_QUEUEWARN_NORMAL: + toval = convtime(val, 'h'); + TimeOuts.to_q_warning[TOC_NORMAL] = toval; + break; + + case TO_QUEUEWARN_URGENT: + toval = convtime(val, 'h'); + TimeOuts.to_q_warning[TOC_URGENT] = toval; + break; + + case TO_QUEUEWARN_NON_URGENT: + toval = convtime(val, 'h'); + TimeOuts.to_q_warning[TOC_NONURGENT] = toval; + break; + + case TO_QUEUERETURN: + toval = convtime(val, 'd'); + TimeOuts.to_q_return[TOC_NORMAL] = toval; + TimeOuts.to_q_return[TOC_URGENT] = toval; + TimeOuts.to_q_return[TOC_NONURGENT] = toval; + break; + + case TO_QUEUERETURN_NORMAL: + toval = convtime(val, 'd'); + TimeOuts.to_q_return[TOC_NORMAL] = toval; + break; + + case TO_QUEUERETURN_URGENT: + toval = convtime(val, 'd'); + TimeOuts.to_q_return[TOC_URGENT] = toval; + break; + + case TO_QUEUERETURN_NON_URGENT: + toval = convtime(val, 'd'); + TimeOuts.to_q_return[TOC_NONURGENT] = toval; + break; + + + case TO_HOSTSTATUS: + MciInfoTimeout = toval; + break; + + case TO_RESOLVER_RETRANS: + toval = convtime(val, 's'); + TimeOuts.res_retrans[RES_TO_DEFAULT] = toval; + TimeOuts.res_retrans[RES_TO_FIRST] = toval; + TimeOuts.res_retrans[RES_TO_NORMAL] = toval; + break; + + case TO_RESOLVER_RETRY: + i = atoi(val); + TimeOuts.res_retry[RES_TO_DEFAULT] = i; + TimeOuts.res_retry[RES_TO_FIRST] = i; + TimeOuts.res_retry[RES_TO_NORMAL] = i; + break; + + case TO_RESOLVER_RETRANS_NORMAL: + TimeOuts.res_retrans[RES_TO_NORMAL] = convtime(val, 's'); + break; + + case TO_RESOLVER_RETRY_NORMAL: + TimeOuts.res_retry[RES_TO_NORMAL] = atoi(val); + break; + + case TO_RESOLVER_RETRANS_FIRST: + TimeOuts.res_retrans[RES_TO_FIRST] = convtime(val, 's'); + break; + + case TO_RESOLVER_RETRY_FIRST: + TimeOuts.res_retry[RES_TO_FIRST] = atoi(val); + break; + + case TO_CONTROL: + TimeOuts.to_control = toval; + break; + + default: + syserr("settimeout: invalid timeout %s", name); + break; + } + + if (sticky) + setbitn(to->to_code, StickyTimeoutOpt); +} +/* ** INITTIMEOUTS -- parse and set timeout values ** ** Parameters: ** val -- a pointer to the values. If NULL, do initial ** settings. +** sticky -- if set, don't let other setoptions override +** this suboption value. ** ** Returns: ** none. @@ -2729,19 +3517,15 @@ strtorwset(p, endp, stabmode) ** Initializes the TimeOuts structure */ -#define SECONDS -#define MINUTES * 60 -#define HOUR * 3600 - void -inittimeouts(val) +inittimeouts(val, sticky) register char *val; + bool sticky; { register char *p; - extern time_t convtime __P((char *, char)); if (tTd(37, 2)) - printf("inittimeouts(%s)\n", val == NULL ? "<NULL>" : val); + dprintf("inittimeouts(%s)\n", val == NULL ? "<NULL>" : val); if (val == NULL) { TimeOuts.to_connect = (time_t) 0 SECONDS; @@ -2757,28 +3541,30 @@ inittimeouts(val) TimeOuts.to_nextcommand = (time_t) 1 HOUR; TimeOuts.to_miscshort = (time_t) 2 MINUTES; #if IDENTPROTO - TimeOuts.to_ident = (time_t) 30 SECONDS; -#else + TimeOuts.to_ident = (time_t) 5 SECONDS; +#else /* IDENTPROTO */ TimeOuts.to_ident = (time_t) 0 SECONDS; -#endif +#endif /* IDENTPROTO */ TimeOuts.to_fileopen = (time_t) 60 SECONDS; + TimeOuts.to_control = (time_t) 2 MINUTES; if (tTd(37, 5)) { - printf("Timeouts:\n"); - printf(" connect = %ld\n", (long)TimeOuts.to_connect); - printf(" initial = %ld\n", (long)TimeOuts.to_initial); - printf(" helo = %ld\n", (long)TimeOuts.to_helo); - printf(" mail = %ld\n", (long)TimeOuts.to_mail); - printf(" rcpt = %ld\n", (long)TimeOuts.to_rcpt); - printf(" datainit = %ld\n", (long)TimeOuts.to_datainit); - printf(" datablock = %ld\n", (long)TimeOuts.to_datablock); - printf(" datafinal = %ld\n", (long)TimeOuts.to_datafinal); - printf(" rset = %ld\n", (long)TimeOuts.to_rset); - printf(" quit = %ld\n", (long)TimeOuts.to_quit); - printf(" nextcommand = %ld\n", (long)TimeOuts.to_nextcommand); - printf(" miscshort = %ld\n", (long)TimeOuts.to_miscshort); - printf(" ident = %ld\n", (long)TimeOuts.to_ident); - printf(" fileopen = %ld\n", (long)TimeOuts.to_fileopen); + dprintf("Timeouts:\n"); + dprintf(" connect = %ld\n", (long)TimeOuts.to_connect); + dprintf(" initial = %ld\n", (long)TimeOuts.to_initial); + dprintf(" helo = %ld\n", (long)TimeOuts.to_helo); + dprintf(" mail = %ld\n", (long)TimeOuts.to_mail); + dprintf(" rcpt = %ld\n", (long)TimeOuts.to_rcpt); + dprintf(" datainit = %ld\n", (long)TimeOuts.to_datainit); + dprintf(" datablock = %ld\n", (long)TimeOuts.to_datablock); + dprintf(" datafinal = %ld\n", (long)TimeOuts.to_datafinal); + dprintf(" rset = %ld\n", (long)TimeOuts.to_rset); + dprintf(" quit = %ld\n", (long)TimeOuts.to_quit); + dprintf(" nextcommand = %ld\n", (long)TimeOuts.to_nextcommand); + dprintf(" miscshort = %ld\n", (long)TimeOuts.to_miscshort); + dprintf(" ident = %ld\n", (long)TimeOuts.to_ident); + dprintf(" fileopen = %ld\n", (long)TimeOuts.to_fileopen); + dprintf(" control = %ld\n", (long)TimeOuts.to_control); } return; } @@ -2803,6 +3589,15 @@ inittimeouts(val) TimeOuts.to_datablock = TimeOuts.to_mail; TimeOuts.to_datafinal = TimeOuts.to_mail; TimeOuts.to_nextcommand = TimeOuts.to_mail; + if (sticky) + { + setbitn(TO_MAIL, StickyTimeoutOpt); + setbitn(TO_RCPT, StickyTimeoutOpt); + setbitn(TO_DATAINIT, StickyTimeoutOpt); + setbitn(TO_DATABLOCK, StickyTimeoutOpt); + setbitn(TO_DATAFINAL, StickyTimeoutOpt); + setbitn(TO_COMMAND, StickyTimeoutOpt); + } continue; } else @@ -2815,106 +3610,7 @@ inittimeouts(val) continue; } *q++ = '\0'; - settimeout(val, q); + settimeout(val, q, sticky); } } } -/* -** SETTIMEOUT -- set an individual timeout -** -** Parameters: -** name -- the name of the timeout. -** val -- the value of the timeout. -** -** Returns: -** none. -*/ - -void -settimeout(name, val) - char *name; - char *val; -{ - register char *p; - time_t to; - extern time_t convtime __P((char *, char)); - - if (tTd(37, 2)) - printf("settimeout(%s = %s)\n", name, val); - - to = convtime(val, 'm'); - p = strchr(name, '.'); - if (p != NULL) - *p++ = '\0'; - - if (strcasecmp(name, "initial") == 0) - TimeOuts.to_initial = to; - else if (strcasecmp(name, "mail") == 0) - TimeOuts.to_mail = to; - else if (strcasecmp(name, "rcpt") == 0) - TimeOuts.to_rcpt = to; - else if (strcasecmp(name, "datainit") == 0) - TimeOuts.to_datainit = to; - else if (strcasecmp(name, "datablock") == 0) - TimeOuts.to_datablock = to; - else if (strcasecmp(name, "datafinal") == 0) - TimeOuts.to_datafinal = to; - else if (strcasecmp(name, "command") == 0) - TimeOuts.to_nextcommand = to; - else if (strcasecmp(name, "rset") == 0) - TimeOuts.to_rset = to; - else if (strcasecmp(name, "helo") == 0) - TimeOuts.to_helo = to; - else if (strcasecmp(name, "quit") == 0) - TimeOuts.to_quit = to; - else if (strcasecmp(name, "misc") == 0) - TimeOuts.to_miscshort = to; - else if (strcasecmp(name, "ident") == 0) - TimeOuts.to_ident = to; - else if (strcasecmp(name, "fileopen") == 0) - TimeOuts.to_fileopen = to; - else if (strcasecmp(name, "connect") == 0) - TimeOuts.to_connect = to; - else if (strcasecmp(name, "iconnect") == 0) - TimeOuts.to_iconnect = to; - else if (strcasecmp(name, "queuewarn") == 0) - { - to = convtime(val, 'h'); - if (p == NULL || strcmp(p, "*") == 0) - { - TimeOuts.to_q_warning[TOC_NORMAL] = to; - TimeOuts.to_q_warning[TOC_URGENT] = to; - TimeOuts.to_q_warning[TOC_NONURGENT] = to; - } - else if (strcasecmp(p, "normal") == 0) - TimeOuts.to_q_warning[TOC_NORMAL] = to; - else if (strcasecmp(p, "urgent") == 0) - TimeOuts.to_q_warning[TOC_URGENT] = to; - else if (strcasecmp(p, "non-urgent") == 0) - TimeOuts.to_q_warning[TOC_NONURGENT] = to; - else - syserr("settimeout: invalid queuewarn subtimeout %s", p); - } - else if (strcasecmp(name, "queuereturn") == 0) - { - to = convtime(val, 'd'); - if (p == NULL || strcmp(p, "*") == 0) - { - TimeOuts.to_q_return[TOC_NORMAL] = to; - TimeOuts.to_q_return[TOC_URGENT] = to; - TimeOuts.to_q_return[TOC_NONURGENT] = to; - } - else if (strcasecmp(p, "normal") == 0) - TimeOuts.to_q_return[TOC_NORMAL] = to; - else if (strcasecmp(p, "urgent") == 0) - TimeOuts.to_q_return[TOC_URGENT] = to; - else if (strcasecmp(p, "non-urgent") == 0) - TimeOuts.to_q_return[TOC_NONURGENT] = to; - else - syserr("settimeout: invalid queuereturn subtimeout %s", p); - } - else if (strcasecmp(name, "hoststatus") == 0) - MciInfoTimeout = convtime(val, 'm'); - else - syserr("settimeout: invalid timeout %s", name); -} |