1c2aa98e2SPeter Wemm /* 2c2aa98e2SPeter Wemm * Copyright (c) 1998 Sendmail, Inc. All rights reserved. 3c2aa98e2SPeter Wemm * Copyright (c) 1983, 1995-1997 Eric P. Allman. All rights reserved. 4c2aa98e2SPeter Wemm * Copyright (c) 1988, 1993 5c2aa98e2SPeter Wemm * The Regents of the University of California. All rights reserved. 6c2aa98e2SPeter Wemm * 7c2aa98e2SPeter Wemm * By using this file, you agree to the terms and conditions set 8c2aa98e2SPeter Wemm * forth in the LICENSE file which can be found at the top level of 9c2aa98e2SPeter Wemm * the sendmail distribution. 10c2aa98e2SPeter Wemm * 11c2aa98e2SPeter Wemm */ 12c2aa98e2SPeter Wemm 13c2aa98e2SPeter Wemm #ifndef lint 142e43090eSPeter Wemm static char sccsid[] = "@(#)readcf.c 8.238 (Berkeley) 1/28/1999"; 15c2aa98e2SPeter Wemm #endif /* not lint */ 16c2aa98e2SPeter Wemm 17c2aa98e2SPeter Wemm # include "sendmail.h" 18c2aa98e2SPeter Wemm # include <grp.h> 19c2aa98e2SPeter Wemm #if NAMED_BIND 20c2aa98e2SPeter Wemm # include <resolv.h> 21c2aa98e2SPeter Wemm #endif 22c2aa98e2SPeter Wemm 23c2aa98e2SPeter Wemm /* 24c2aa98e2SPeter Wemm ** READCF -- read configuration file. 25c2aa98e2SPeter Wemm ** 26c2aa98e2SPeter Wemm ** This routine reads the configuration file and builds the internal 27c2aa98e2SPeter Wemm ** form. 28c2aa98e2SPeter Wemm ** 29c2aa98e2SPeter Wemm ** The file is formatted as a sequence of lines, each taken 30c2aa98e2SPeter Wemm ** atomically. The first character of each line describes how 31c2aa98e2SPeter Wemm ** the line is to be interpreted. The lines are: 32c2aa98e2SPeter Wemm ** Dxval Define macro x to have value val. 33c2aa98e2SPeter Wemm ** Cxword Put word into class x. 34c2aa98e2SPeter Wemm ** Fxfile [fmt] Read file for lines to put into 35c2aa98e2SPeter Wemm ** class x. Use scanf string 'fmt' 36c2aa98e2SPeter Wemm ** or "%s" if not present. Fmt should 37c2aa98e2SPeter Wemm ** only produce one string-valued result. 38c2aa98e2SPeter Wemm ** Hname: value Define header with field-name 'name' 39c2aa98e2SPeter Wemm ** and value as specified; this will be 40c2aa98e2SPeter Wemm ** macro expanded immediately before 41c2aa98e2SPeter Wemm ** use. 42c2aa98e2SPeter Wemm ** Sn Use rewriting set n. 43c2aa98e2SPeter Wemm ** Rlhs rhs Rewrite addresses that match lhs to 44c2aa98e2SPeter Wemm ** be rhs. 45c2aa98e2SPeter Wemm ** Mn arg=val... Define mailer. n is the internal name. 46c2aa98e2SPeter Wemm ** Args specify mailer parameters. 47c2aa98e2SPeter Wemm ** Oxvalue Set option x to value. 48c2aa98e2SPeter Wemm ** Pname=value Set precedence name to value. 49c2aa98e2SPeter Wemm ** Vversioncode[/vendorcode] 50c2aa98e2SPeter Wemm ** Version level/vendor name of 51c2aa98e2SPeter Wemm ** configuration syntax. 52c2aa98e2SPeter Wemm ** Kmapname mapclass arguments.... 53c2aa98e2SPeter Wemm ** Define keyed lookup of a given class. 54c2aa98e2SPeter Wemm ** Arguments are class dependent. 55c2aa98e2SPeter Wemm ** Eenvar=value Set the environment value to the given value. 56c2aa98e2SPeter Wemm ** 57c2aa98e2SPeter Wemm ** Parameters: 58c2aa98e2SPeter Wemm ** cfname -- configuration file name. 59c2aa98e2SPeter Wemm ** safe -- TRUE if this is the system config file; 60c2aa98e2SPeter Wemm ** FALSE otherwise. 61c2aa98e2SPeter Wemm ** e -- the main envelope. 62c2aa98e2SPeter Wemm ** 63c2aa98e2SPeter Wemm ** Returns: 64c2aa98e2SPeter Wemm ** none. 65c2aa98e2SPeter Wemm ** 66c2aa98e2SPeter Wemm ** Side Effects: 67c2aa98e2SPeter Wemm ** Builds several internal tables. 68c2aa98e2SPeter Wemm */ 69c2aa98e2SPeter Wemm 70c2aa98e2SPeter Wemm void 71c2aa98e2SPeter Wemm readcf(cfname, safe, e) 72c2aa98e2SPeter Wemm char *cfname; 73c2aa98e2SPeter Wemm bool safe; 74c2aa98e2SPeter Wemm register ENVELOPE *e; 75c2aa98e2SPeter Wemm { 76c2aa98e2SPeter Wemm FILE *cf; 77c2aa98e2SPeter Wemm int ruleset = 0; 78c2aa98e2SPeter Wemm char *q; 79c2aa98e2SPeter Wemm struct rewrite *rwp = NULL; 80c2aa98e2SPeter Wemm char *bp; 81c2aa98e2SPeter Wemm auto char *ep; 82c2aa98e2SPeter Wemm int nfuzzy; 83c2aa98e2SPeter Wemm char *file; 84c2aa98e2SPeter Wemm bool optional; 85c2aa98e2SPeter Wemm int mid; 86c2aa98e2SPeter Wemm register char *p; 87c2aa98e2SPeter Wemm int sff = SFF_OPENASROOT; 88c2aa98e2SPeter Wemm struct stat statb; 89c2aa98e2SPeter Wemm char buf[MAXLINE]; 90c2aa98e2SPeter Wemm char exbuf[MAXLINE]; 91c2aa98e2SPeter Wemm char pvpbuf[MAXLINE + MAXATOM]; 92c2aa98e2SPeter Wemm static char *null_list[1] = { NULL }; 93c2aa98e2SPeter Wemm extern char **copyplist __P((char **, bool)); 94c2aa98e2SPeter Wemm extern char *munchstring __P((char *, char **, int)); 95c2aa98e2SPeter Wemm extern void fileclass __P((int, char *, char *, bool, bool)); 96c2aa98e2SPeter Wemm extern void toomany __P((int, int)); 97c2aa98e2SPeter Wemm extern void translate_dollars __P((char *)); 98c2aa98e2SPeter Wemm extern void inithostmaps __P((void)); 99c2aa98e2SPeter Wemm 100c2aa98e2SPeter Wemm FileName = cfname; 101c2aa98e2SPeter Wemm LineNumber = 0; 102c2aa98e2SPeter Wemm 103c2aa98e2SPeter Wemm if (DontLockReadFiles) 104c2aa98e2SPeter Wemm sff |= SFF_NOLOCK; 105c2aa98e2SPeter Wemm cf = safefopen(cfname, O_RDONLY, 0444, sff); 106c2aa98e2SPeter Wemm if (cf == NULL) 107c2aa98e2SPeter Wemm { 108c2aa98e2SPeter Wemm syserr("cannot open"); 109065a643dSPeter Wemm finis(FALSE, EX_OSFILE); 110c2aa98e2SPeter Wemm } 111c2aa98e2SPeter Wemm 112c2aa98e2SPeter Wemm if (fstat(fileno(cf), &statb) < 0) 113c2aa98e2SPeter Wemm { 114c2aa98e2SPeter Wemm syserr("cannot fstat"); 115065a643dSPeter Wemm finis(FALSE, EX_OSFILE); 116c2aa98e2SPeter Wemm } 117c2aa98e2SPeter Wemm 118c2aa98e2SPeter Wemm if (!S_ISREG(statb.st_mode)) 119c2aa98e2SPeter Wemm { 120c2aa98e2SPeter Wemm syserr("not a plain file"); 121065a643dSPeter Wemm finis(FALSE, EX_OSFILE); 122c2aa98e2SPeter Wemm } 123c2aa98e2SPeter Wemm 124c2aa98e2SPeter Wemm if (OpMode != MD_TEST && bitset(S_IWGRP|S_IWOTH, statb.st_mode)) 125c2aa98e2SPeter Wemm { 126c2aa98e2SPeter Wemm if (OpMode == MD_DAEMON || OpMode == MD_INITALIAS) 127c2aa98e2SPeter Wemm fprintf(stderr, "%s: WARNING: dangerous write permissions\n", 128c2aa98e2SPeter Wemm FileName); 129c2aa98e2SPeter Wemm if (LogLevel > 0) 130c2aa98e2SPeter Wemm sm_syslog(LOG_CRIT, NOQID, 131c2aa98e2SPeter Wemm "%s: WARNING: dangerous write permissions", 132c2aa98e2SPeter Wemm FileName); 133c2aa98e2SPeter Wemm } 134c2aa98e2SPeter Wemm 135c2aa98e2SPeter Wemm #ifdef XLA 136c2aa98e2SPeter Wemm xla_zero(); 137c2aa98e2SPeter Wemm #endif 138c2aa98e2SPeter Wemm 139c2aa98e2SPeter Wemm while ((bp = fgetfolded(buf, sizeof buf, cf)) != NULL) 140c2aa98e2SPeter Wemm { 141c2aa98e2SPeter Wemm if (bp[0] == '#') 142c2aa98e2SPeter Wemm { 143c2aa98e2SPeter Wemm if (bp != buf) 144c2aa98e2SPeter Wemm free(bp); 145c2aa98e2SPeter Wemm continue; 146c2aa98e2SPeter Wemm } 147c2aa98e2SPeter Wemm 148c2aa98e2SPeter Wemm /* do macro expansion mappings */ 149c2aa98e2SPeter Wemm translate_dollars(bp); 150c2aa98e2SPeter Wemm 151c2aa98e2SPeter Wemm /* interpret this line */ 152c2aa98e2SPeter Wemm errno = 0; 153c2aa98e2SPeter Wemm switch (bp[0]) 154c2aa98e2SPeter Wemm { 155c2aa98e2SPeter Wemm case '\0': 156c2aa98e2SPeter Wemm case '#': /* comment */ 157c2aa98e2SPeter Wemm break; 158c2aa98e2SPeter Wemm 159c2aa98e2SPeter Wemm case 'R': /* rewriting rule */ 160c2aa98e2SPeter Wemm for (p = &bp[1]; *p != '\0' && *p != '\t'; p++) 161c2aa98e2SPeter Wemm continue; 162c2aa98e2SPeter Wemm 163c2aa98e2SPeter Wemm if (*p == '\0') 164c2aa98e2SPeter Wemm { 165c2aa98e2SPeter Wemm syserr("invalid rewrite line \"%s\" (tab expected)", bp); 166c2aa98e2SPeter Wemm break; 167c2aa98e2SPeter Wemm } 168c2aa98e2SPeter Wemm 169c2aa98e2SPeter Wemm /* allocate space for the rule header */ 170c2aa98e2SPeter Wemm if (rwp == NULL) 171c2aa98e2SPeter Wemm { 172c2aa98e2SPeter Wemm RewriteRules[ruleset] = rwp = 173c2aa98e2SPeter Wemm (struct rewrite *) xalloc(sizeof *rwp); 174c2aa98e2SPeter Wemm } 175c2aa98e2SPeter Wemm else 176c2aa98e2SPeter Wemm { 177c2aa98e2SPeter Wemm rwp->r_next = (struct rewrite *) xalloc(sizeof *rwp); 178c2aa98e2SPeter Wemm rwp = rwp->r_next; 179c2aa98e2SPeter Wemm } 180c2aa98e2SPeter Wemm rwp->r_next = NULL; 181c2aa98e2SPeter Wemm 182c2aa98e2SPeter Wemm /* expand and save the LHS */ 183c2aa98e2SPeter Wemm *p = '\0'; 184c2aa98e2SPeter Wemm expand(&bp[1], exbuf, sizeof exbuf, e); 185c2aa98e2SPeter Wemm rwp->r_lhs = prescan(exbuf, '\t', pvpbuf, 186c2aa98e2SPeter Wemm sizeof pvpbuf, NULL, NULL); 187c2aa98e2SPeter Wemm nfuzzy = 0; 188c2aa98e2SPeter Wemm if (rwp->r_lhs != NULL) 189c2aa98e2SPeter Wemm { 190c2aa98e2SPeter Wemm register char **ap; 191c2aa98e2SPeter Wemm 192c2aa98e2SPeter Wemm rwp->r_lhs = copyplist(rwp->r_lhs, TRUE); 193c2aa98e2SPeter Wemm 194c2aa98e2SPeter Wemm /* count the number of fuzzy matches in LHS */ 195c2aa98e2SPeter Wemm for (ap = rwp->r_lhs; *ap != NULL; ap++) 196c2aa98e2SPeter Wemm { 197c2aa98e2SPeter Wemm char *botch; 198c2aa98e2SPeter Wemm 199c2aa98e2SPeter Wemm botch = NULL; 200c2aa98e2SPeter Wemm switch (**ap & 0377) 201c2aa98e2SPeter Wemm { 202c2aa98e2SPeter Wemm case MATCHZANY: 203c2aa98e2SPeter Wemm case MATCHANY: 204c2aa98e2SPeter Wemm case MATCHONE: 205c2aa98e2SPeter Wemm case MATCHCLASS: 206c2aa98e2SPeter Wemm case MATCHNCLASS: 207c2aa98e2SPeter Wemm nfuzzy++; 208c2aa98e2SPeter Wemm break; 209c2aa98e2SPeter Wemm 210c2aa98e2SPeter Wemm case MATCHREPL: 211c2aa98e2SPeter Wemm botch = "$0-$9"; 212c2aa98e2SPeter Wemm break; 213c2aa98e2SPeter Wemm 214c2aa98e2SPeter Wemm case CANONUSER: 215c2aa98e2SPeter Wemm botch = "$:"; 216c2aa98e2SPeter Wemm break; 217c2aa98e2SPeter Wemm 218c2aa98e2SPeter Wemm case CALLSUBR: 219c2aa98e2SPeter Wemm botch = "$>"; 220c2aa98e2SPeter Wemm break; 221c2aa98e2SPeter Wemm 222c2aa98e2SPeter Wemm case CONDIF: 223c2aa98e2SPeter Wemm botch = "$?"; 224c2aa98e2SPeter Wemm break; 225c2aa98e2SPeter Wemm 226c2aa98e2SPeter Wemm case CONDFI: 227c2aa98e2SPeter Wemm botch = "$."; 228c2aa98e2SPeter Wemm break; 229c2aa98e2SPeter Wemm 230c2aa98e2SPeter Wemm case HOSTBEGIN: 231c2aa98e2SPeter Wemm botch = "$["; 232c2aa98e2SPeter Wemm break; 233c2aa98e2SPeter Wemm 234c2aa98e2SPeter Wemm case HOSTEND: 235c2aa98e2SPeter Wemm botch = "$]"; 236c2aa98e2SPeter Wemm break; 237c2aa98e2SPeter Wemm 238c2aa98e2SPeter Wemm case LOOKUPBEGIN: 239c2aa98e2SPeter Wemm botch = "$("; 240c2aa98e2SPeter Wemm break; 241c2aa98e2SPeter Wemm 242c2aa98e2SPeter Wemm case LOOKUPEND: 243c2aa98e2SPeter Wemm botch = "$)"; 244c2aa98e2SPeter Wemm break; 245c2aa98e2SPeter Wemm } 246c2aa98e2SPeter Wemm if (botch != NULL) 247c2aa98e2SPeter Wemm syserr("Inappropriate use of %s on LHS", 248c2aa98e2SPeter Wemm botch); 249c2aa98e2SPeter Wemm } 250c2aa98e2SPeter Wemm } 251c2aa98e2SPeter Wemm else 252c2aa98e2SPeter Wemm { 253c2aa98e2SPeter Wemm syserr("R line: null LHS"); 254c2aa98e2SPeter Wemm rwp->r_lhs = null_list; 255c2aa98e2SPeter Wemm } 256c2aa98e2SPeter Wemm 257c2aa98e2SPeter Wemm /* expand and save the RHS */ 258c2aa98e2SPeter Wemm while (*++p == '\t') 259c2aa98e2SPeter Wemm continue; 260c2aa98e2SPeter Wemm q = p; 261c2aa98e2SPeter Wemm while (*p != '\0' && *p != '\t') 262c2aa98e2SPeter Wemm p++; 263c2aa98e2SPeter Wemm *p = '\0'; 264c2aa98e2SPeter Wemm expand(q, exbuf, sizeof exbuf, e); 265c2aa98e2SPeter Wemm rwp->r_rhs = prescan(exbuf, '\t', pvpbuf, 266c2aa98e2SPeter Wemm sizeof pvpbuf, NULL, NULL); 267c2aa98e2SPeter Wemm if (rwp->r_rhs != NULL) 268c2aa98e2SPeter Wemm { 269c2aa98e2SPeter Wemm register char **ap; 270c2aa98e2SPeter Wemm 271c2aa98e2SPeter Wemm rwp->r_rhs = copyplist(rwp->r_rhs, TRUE); 272c2aa98e2SPeter Wemm 273c2aa98e2SPeter Wemm /* check no out-of-bounds replacements */ 274c2aa98e2SPeter Wemm nfuzzy += '0'; 275c2aa98e2SPeter Wemm for (ap = rwp->r_rhs; *ap != NULL; ap++) 276c2aa98e2SPeter Wemm { 277c2aa98e2SPeter Wemm char *botch; 278c2aa98e2SPeter Wemm 279c2aa98e2SPeter Wemm botch = NULL; 280c2aa98e2SPeter Wemm switch (**ap & 0377) 281c2aa98e2SPeter Wemm { 282c2aa98e2SPeter Wemm case MATCHREPL: 283c2aa98e2SPeter Wemm if ((*ap)[1] <= '0' || (*ap)[1] > nfuzzy) 284c2aa98e2SPeter Wemm { 285c2aa98e2SPeter Wemm syserr("replacement $%c out of bounds", 286c2aa98e2SPeter Wemm (*ap)[1]); 287c2aa98e2SPeter Wemm } 288c2aa98e2SPeter Wemm break; 289c2aa98e2SPeter Wemm 290c2aa98e2SPeter Wemm case MATCHZANY: 291c2aa98e2SPeter Wemm botch = "$*"; 292c2aa98e2SPeter Wemm break; 293c2aa98e2SPeter Wemm 294c2aa98e2SPeter Wemm case MATCHANY: 295c2aa98e2SPeter Wemm botch = "$+"; 296c2aa98e2SPeter Wemm break; 297c2aa98e2SPeter Wemm 298c2aa98e2SPeter Wemm case MATCHONE: 299c2aa98e2SPeter Wemm botch = "$-"; 300c2aa98e2SPeter Wemm break; 301c2aa98e2SPeter Wemm 302c2aa98e2SPeter Wemm case MATCHCLASS: 303c2aa98e2SPeter Wemm botch = "$="; 304c2aa98e2SPeter Wemm break; 305c2aa98e2SPeter Wemm 306c2aa98e2SPeter Wemm case MATCHNCLASS: 307c2aa98e2SPeter Wemm botch = "$~"; 308c2aa98e2SPeter Wemm break; 309c2aa98e2SPeter Wemm } 310c2aa98e2SPeter Wemm if (botch != NULL) 311c2aa98e2SPeter Wemm syserr("Inappropriate use of %s on RHS", 312c2aa98e2SPeter Wemm botch); 313c2aa98e2SPeter Wemm } 314c2aa98e2SPeter Wemm } 315c2aa98e2SPeter Wemm else 316c2aa98e2SPeter Wemm { 317c2aa98e2SPeter Wemm syserr("R line: null RHS"); 318c2aa98e2SPeter Wemm rwp->r_rhs = null_list; 319c2aa98e2SPeter Wemm } 320c2aa98e2SPeter Wemm break; 321c2aa98e2SPeter Wemm 322c2aa98e2SPeter Wemm case 'S': /* select rewriting set */ 323c2aa98e2SPeter Wemm expand(&bp[1], exbuf, sizeof exbuf, e); 324c2aa98e2SPeter Wemm ruleset = strtorwset(exbuf, NULL, ST_ENTER); 325c2aa98e2SPeter Wemm if (ruleset < 0) 326c2aa98e2SPeter Wemm break; 327c2aa98e2SPeter Wemm rwp = RewriteRules[ruleset]; 328c2aa98e2SPeter Wemm if (rwp != NULL) 329c2aa98e2SPeter Wemm { 330c2aa98e2SPeter Wemm if (OpMode == MD_TEST || tTd(37, 1)) 331c2aa98e2SPeter Wemm printf("WARNING: Ruleset %s has multiple definitions\n", 332c2aa98e2SPeter Wemm &bp[1]); 333c2aa98e2SPeter Wemm while (rwp->r_next != NULL) 334c2aa98e2SPeter Wemm rwp = rwp->r_next; 335c2aa98e2SPeter Wemm } 336c2aa98e2SPeter Wemm break; 337c2aa98e2SPeter Wemm 338c2aa98e2SPeter Wemm case 'D': /* macro definition */ 339c2aa98e2SPeter Wemm mid = macid(&bp[1], &ep); 340c2aa98e2SPeter Wemm p = munchstring(ep, NULL, '\0'); 341c2aa98e2SPeter Wemm define(mid, newstr(p), e); 342c2aa98e2SPeter Wemm break; 343c2aa98e2SPeter Wemm 344c2aa98e2SPeter Wemm case 'H': /* required header line */ 345c2aa98e2SPeter Wemm (void) chompheader(&bp[1], TRUE, NULL, e); 346c2aa98e2SPeter Wemm break; 347c2aa98e2SPeter Wemm 348c2aa98e2SPeter Wemm case 'C': /* word class */ 349c2aa98e2SPeter Wemm case 'T': /* trusted user (set class `t') */ 350c2aa98e2SPeter Wemm if (bp[0] == 'C') 351c2aa98e2SPeter Wemm { 352c2aa98e2SPeter Wemm mid = macid(&bp[1], &ep); 353c2aa98e2SPeter Wemm expand(ep, exbuf, sizeof exbuf, e); 354c2aa98e2SPeter Wemm p = exbuf; 355c2aa98e2SPeter Wemm } 356c2aa98e2SPeter Wemm else 357c2aa98e2SPeter Wemm { 358c2aa98e2SPeter Wemm mid = 't'; 359c2aa98e2SPeter Wemm p = &bp[1]; 360c2aa98e2SPeter Wemm } 361c2aa98e2SPeter Wemm while (*p != '\0') 362c2aa98e2SPeter Wemm { 363c2aa98e2SPeter Wemm register char *wd; 364c2aa98e2SPeter Wemm char delim; 365c2aa98e2SPeter Wemm 366c2aa98e2SPeter Wemm while (*p != '\0' && isascii(*p) && isspace(*p)) 367c2aa98e2SPeter Wemm p++; 368c2aa98e2SPeter Wemm wd = p; 369c2aa98e2SPeter Wemm while (*p != '\0' && !(isascii(*p) && isspace(*p))) 370c2aa98e2SPeter Wemm p++; 371c2aa98e2SPeter Wemm delim = *p; 372c2aa98e2SPeter Wemm *p = '\0'; 373c2aa98e2SPeter Wemm if (wd[0] != '\0') 374c2aa98e2SPeter Wemm setclass(mid, wd); 375c2aa98e2SPeter Wemm *p = delim; 376c2aa98e2SPeter Wemm } 377c2aa98e2SPeter Wemm break; 378c2aa98e2SPeter Wemm 379c2aa98e2SPeter Wemm case 'F': /* word class from file */ 380c2aa98e2SPeter Wemm mid = macid(&bp[1], &ep); 381c2aa98e2SPeter Wemm for (p = ep; isascii(*p) && isspace(*p); ) 382c2aa98e2SPeter Wemm p++; 383c2aa98e2SPeter Wemm if (p[0] == '-' && p[1] == 'o') 384c2aa98e2SPeter Wemm { 385c2aa98e2SPeter Wemm optional = TRUE; 386c2aa98e2SPeter Wemm while (*p != '\0' && !(isascii(*p) && isspace(*p))) 387c2aa98e2SPeter Wemm p++; 388c2aa98e2SPeter Wemm while (isascii(*p) && isspace(*p)) 389c2aa98e2SPeter Wemm p++; 390c2aa98e2SPeter Wemm } 391c2aa98e2SPeter Wemm else 392c2aa98e2SPeter Wemm optional = FALSE; 393c2aa98e2SPeter Wemm file = p; 394c2aa98e2SPeter Wemm if (*file == '|') 395c2aa98e2SPeter Wemm p = "%s"; 396c2aa98e2SPeter Wemm else 397c2aa98e2SPeter Wemm { 398c2aa98e2SPeter Wemm while (*p != '\0' && !(isascii(*p) && isspace(*p))) 399c2aa98e2SPeter Wemm p++; 400c2aa98e2SPeter Wemm if (*p == '\0') 401c2aa98e2SPeter Wemm p = "%s"; 402c2aa98e2SPeter Wemm else 403c2aa98e2SPeter Wemm { 404c2aa98e2SPeter Wemm *p = '\0'; 405c2aa98e2SPeter Wemm while (isascii(*++p) && isspace(*p)) 406c2aa98e2SPeter Wemm continue; 407c2aa98e2SPeter Wemm } 408c2aa98e2SPeter Wemm } 409c2aa98e2SPeter Wemm fileclass(mid, file, p, safe, optional); 410c2aa98e2SPeter Wemm break; 411c2aa98e2SPeter Wemm 412c2aa98e2SPeter Wemm #ifdef XLA 413c2aa98e2SPeter Wemm case 'L': /* extended load average description */ 414c2aa98e2SPeter Wemm xla_init(&bp[1]); 415c2aa98e2SPeter Wemm break; 416c2aa98e2SPeter Wemm #endif 417c2aa98e2SPeter Wemm 418c2aa98e2SPeter Wemm #if defined(SUN_EXTENSIONS) && defined(SUN_LOOKUP_MACRO) 419c2aa98e2SPeter Wemm case 'L': /* lookup macro */ 420c2aa98e2SPeter Wemm case 'G': /* lookup class */ 421c2aa98e2SPeter Wemm /* reserved for Sun -- NIS+ database lookup */ 422c2aa98e2SPeter Wemm if (VendorCode != VENDOR_SUN) 423c2aa98e2SPeter Wemm goto badline; 424c2aa98e2SPeter Wemm sun_lg_config_line(bp, e); 425c2aa98e2SPeter Wemm break; 426c2aa98e2SPeter Wemm #endif 427c2aa98e2SPeter Wemm 428c2aa98e2SPeter Wemm case 'M': /* define mailer */ 429c2aa98e2SPeter Wemm makemailer(&bp[1]); 430c2aa98e2SPeter Wemm break; 431c2aa98e2SPeter Wemm 432c2aa98e2SPeter Wemm case 'O': /* set option */ 433c2aa98e2SPeter Wemm setoption(bp[1], &bp[2], safe, FALSE, e); 434c2aa98e2SPeter Wemm break; 435c2aa98e2SPeter Wemm 436c2aa98e2SPeter Wemm case 'P': /* set precedence */ 437c2aa98e2SPeter Wemm if (NumPriorities >= MAXPRIORITIES) 438c2aa98e2SPeter Wemm { 439c2aa98e2SPeter Wemm toomany('P', MAXPRIORITIES); 440c2aa98e2SPeter Wemm break; 441c2aa98e2SPeter Wemm } 442c2aa98e2SPeter Wemm for (p = &bp[1]; *p != '\0' && *p != '='; p++) 443c2aa98e2SPeter Wemm continue; 444c2aa98e2SPeter Wemm if (*p == '\0') 445c2aa98e2SPeter Wemm goto badline; 446c2aa98e2SPeter Wemm *p = '\0'; 447c2aa98e2SPeter Wemm Priorities[NumPriorities].pri_name = newstr(&bp[1]); 448c2aa98e2SPeter Wemm Priorities[NumPriorities].pri_val = atoi(++p); 449c2aa98e2SPeter Wemm NumPriorities++; 450c2aa98e2SPeter Wemm break; 451c2aa98e2SPeter Wemm 452c2aa98e2SPeter Wemm case 'V': /* configuration syntax version */ 453c2aa98e2SPeter Wemm for (p = &bp[1]; isascii(*p) && isspace(*p); p++) 454c2aa98e2SPeter Wemm continue; 455c2aa98e2SPeter Wemm if (!isascii(*p) || !isdigit(*p)) 456c2aa98e2SPeter Wemm { 457c2aa98e2SPeter Wemm syserr("invalid argument to V line: \"%.20s\"", 458c2aa98e2SPeter Wemm &bp[1]); 459c2aa98e2SPeter Wemm break; 460c2aa98e2SPeter Wemm } 461c2aa98e2SPeter Wemm ConfigLevel = strtol(p, &ep, 10); 462c2aa98e2SPeter Wemm 463c2aa98e2SPeter Wemm /* 464c2aa98e2SPeter Wemm ** Do heuristic tweaking for back compatibility. 465c2aa98e2SPeter Wemm */ 466c2aa98e2SPeter Wemm 467c2aa98e2SPeter Wemm if (ConfigLevel >= 5) 468c2aa98e2SPeter Wemm { 469c2aa98e2SPeter Wemm /* level 5 configs have short name in $w */ 470c2aa98e2SPeter Wemm p = macvalue('w', e); 471c2aa98e2SPeter Wemm if (p != NULL && (p = strchr(p, '.')) != NULL) 472c2aa98e2SPeter Wemm *p = '\0'; 473c2aa98e2SPeter Wemm define('w', macvalue('w', e), e); 474c2aa98e2SPeter Wemm } 475c2aa98e2SPeter Wemm if (ConfigLevel >= 6) 476c2aa98e2SPeter Wemm { 477c2aa98e2SPeter Wemm ColonOkInAddr = FALSE; 478c2aa98e2SPeter Wemm } 479c2aa98e2SPeter Wemm 480c2aa98e2SPeter Wemm /* 481c2aa98e2SPeter Wemm ** Look for vendor code. 482c2aa98e2SPeter Wemm */ 483c2aa98e2SPeter Wemm 484c2aa98e2SPeter Wemm if (*ep++ == '/') 485c2aa98e2SPeter Wemm { 486c2aa98e2SPeter Wemm extern bool setvendor __P((char *)); 487c2aa98e2SPeter Wemm 488c2aa98e2SPeter Wemm /* extract vendor code */ 489c2aa98e2SPeter Wemm for (p = ep; isascii(*p) && isalpha(*p); ) 490c2aa98e2SPeter Wemm p++; 491c2aa98e2SPeter Wemm *p = '\0'; 492c2aa98e2SPeter Wemm 493c2aa98e2SPeter Wemm if (!setvendor(ep)) 494c2aa98e2SPeter Wemm syserr("invalid V line vendor code: \"%s\"", 495c2aa98e2SPeter Wemm ep); 496c2aa98e2SPeter Wemm } 497c2aa98e2SPeter Wemm break; 498c2aa98e2SPeter Wemm 499c2aa98e2SPeter Wemm case 'K': 500c2aa98e2SPeter Wemm expand(&bp[1], exbuf, sizeof exbuf, e); 501c2aa98e2SPeter Wemm (void) makemapentry(exbuf); 502c2aa98e2SPeter Wemm break; 503c2aa98e2SPeter Wemm 504c2aa98e2SPeter Wemm case 'E': 505c2aa98e2SPeter Wemm p = strchr(bp, '='); 506c2aa98e2SPeter Wemm if (p != NULL) 507c2aa98e2SPeter Wemm *p++ = '\0'; 508c2aa98e2SPeter Wemm setuserenv(&bp[1], p); 509c2aa98e2SPeter Wemm break; 510c2aa98e2SPeter Wemm 511c2aa98e2SPeter Wemm default: 512c2aa98e2SPeter Wemm badline: 513c2aa98e2SPeter Wemm syserr("unknown configuration line \"%s\"", bp); 514c2aa98e2SPeter Wemm } 515c2aa98e2SPeter Wemm if (bp != buf) 516c2aa98e2SPeter Wemm free(bp); 517c2aa98e2SPeter Wemm } 518c2aa98e2SPeter Wemm if (ferror(cf)) 519c2aa98e2SPeter Wemm { 520c2aa98e2SPeter Wemm syserr("I/O read error"); 521065a643dSPeter Wemm finis(FALSE, EX_OSFILE); 522c2aa98e2SPeter Wemm } 523c2aa98e2SPeter Wemm fclose(cf); 524c2aa98e2SPeter Wemm FileName = NULL; 525c2aa98e2SPeter Wemm 526c2aa98e2SPeter Wemm /* initialize host maps from local service tables */ 527c2aa98e2SPeter Wemm inithostmaps(); 528c2aa98e2SPeter Wemm 529c2aa98e2SPeter Wemm /* determine if we need to do special name-server frotz */ 530c2aa98e2SPeter Wemm { 531c2aa98e2SPeter Wemm int nmaps; 532c2aa98e2SPeter Wemm char *maptype[MAXMAPSTACK]; 533c2aa98e2SPeter Wemm short mapreturn[MAXMAPACTIONS]; 534c2aa98e2SPeter Wemm 535c2aa98e2SPeter Wemm nmaps = switch_map_find("hosts", maptype, mapreturn); 536c2aa98e2SPeter Wemm UseNameServer = FALSE; 537c2aa98e2SPeter Wemm if (nmaps > 0 && nmaps <= MAXMAPSTACK) 538c2aa98e2SPeter Wemm { 539c2aa98e2SPeter Wemm register int mapno; 540c2aa98e2SPeter Wemm 541c2aa98e2SPeter Wemm for (mapno = 0; mapno < nmaps && !UseNameServer; mapno++) 542c2aa98e2SPeter Wemm { 543c2aa98e2SPeter Wemm if (strcmp(maptype[mapno], "dns") == 0) 544c2aa98e2SPeter Wemm UseNameServer = TRUE; 545c2aa98e2SPeter Wemm } 546c2aa98e2SPeter Wemm } 547c2aa98e2SPeter Wemm 548c2aa98e2SPeter Wemm #ifdef HESIOD 549c2aa98e2SPeter Wemm nmaps = switch_map_find("passwd", maptype, mapreturn); 550c2aa98e2SPeter Wemm UseHesiod = FALSE; 551c2aa98e2SPeter Wemm if (nmaps > 0 && nmaps <= MAXMAPSTACK) 552c2aa98e2SPeter Wemm { 553c2aa98e2SPeter Wemm register int mapno; 554c2aa98e2SPeter Wemm 555c2aa98e2SPeter Wemm for (mapno = 0; mapno < nmaps && !UseHesiod; mapno++) 556c2aa98e2SPeter Wemm { 557c2aa98e2SPeter Wemm if (strcmp(maptype[mapno], "hesiod") == 0) 558c2aa98e2SPeter Wemm UseHesiod = TRUE; 559c2aa98e2SPeter Wemm } 560c2aa98e2SPeter Wemm } 561c2aa98e2SPeter Wemm #endif 562c2aa98e2SPeter Wemm } 563c2aa98e2SPeter Wemm } 564c2aa98e2SPeter Wemm /* 565c2aa98e2SPeter Wemm ** TRANSLATE_DOLLARS -- convert $x into internal form 566c2aa98e2SPeter Wemm ** 567c2aa98e2SPeter Wemm ** Actually does all appropriate pre-processing of a config line 568c2aa98e2SPeter Wemm ** to turn it into internal form. 569c2aa98e2SPeter Wemm ** 570c2aa98e2SPeter Wemm ** Parameters: 571c2aa98e2SPeter Wemm ** bp -- the buffer to translate. 572c2aa98e2SPeter Wemm ** 573c2aa98e2SPeter Wemm ** Returns: 574c2aa98e2SPeter Wemm ** None. The buffer is translated in place. Since the 575c2aa98e2SPeter Wemm ** translations always make the buffer shorter, this is 576c2aa98e2SPeter Wemm ** safe without a size parameter. 577c2aa98e2SPeter Wemm */ 578c2aa98e2SPeter Wemm 579c2aa98e2SPeter Wemm void 580c2aa98e2SPeter Wemm translate_dollars(bp) 581c2aa98e2SPeter Wemm char *bp; 582c2aa98e2SPeter Wemm { 583c2aa98e2SPeter Wemm register char *p; 584c2aa98e2SPeter Wemm auto char *ep; 585c2aa98e2SPeter Wemm 586c2aa98e2SPeter Wemm for (p = bp; *p != '\0'; p++) 587c2aa98e2SPeter Wemm { 588c2aa98e2SPeter Wemm if (*p == '#' && p > bp && ConfigLevel >= 3) 589c2aa98e2SPeter Wemm { 590c2aa98e2SPeter Wemm /* this is an on-line comment */ 591c2aa98e2SPeter Wemm register char *e; 592c2aa98e2SPeter Wemm 593c2aa98e2SPeter Wemm switch (*--p & 0377) 594c2aa98e2SPeter Wemm { 595c2aa98e2SPeter Wemm case MACROEXPAND: 596c2aa98e2SPeter Wemm /* it's from $# -- let it go through */ 597c2aa98e2SPeter Wemm p++; 598c2aa98e2SPeter Wemm break; 599c2aa98e2SPeter Wemm 600c2aa98e2SPeter Wemm case '\\': 601c2aa98e2SPeter Wemm /* it's backslash escaped */ 602c2aa98e2SPeter Wemm (void) strcpy(p, p + 1); 603c2aa98e2SPeter Wemm break; 604c2aa98e2SPeter Wemm 605c2aa98e2SPeter Wemm default: 606c2aa98e2SPeter Wemm /* delete preceeding white space */ 607c2aa98e2SPeter Wemm while (isascii(*p) && isspace(*p) && 608c2aa98e2SPeter Wemm *p != '\n' && p > bp) 609c2aa98e2SPeter Wemm p--; 610c2aa98e2SPeter Wemm if ((e = strchr(++p, '\n')) != NULL) 611c2aa98e2SPeter Wemm (void) strcpy(p, e); 612c2aa98e2SPeter Wemm else 613c2aa98e2SPeter Wemm *p-- = '\0'; 614c2aa98e2SPeter Wemm break; 615c2aa98e2SPeter Wemm } 616c2aa98e2SPeter Wemm continue; 617c2aa98e2SPeter Wemm } 618c2aa98e2SPeter Wemm 619c2aa98e2SPeter Wemm if (*p != '$' || p[1] == '\0') 620c2aa98e2SPeter Wemm continue; 621c2aa98e2SPeter Wemm 622c2aa98e2SPeter Wemm if (p[1] == '$') 623c2aa98e2SPeter Wemm { 624c2aa98e2SPeter Wemm /* actual dollar sign.... */ 625c2aa98e2SPeter Wemm (void) strcpy(p, p + 1); 626c2aa98e2SPeter Wemm continue; 627c2aa98e2SPeter Wemm } 628c2aa98e2SPeter Wemm 629c2aa98e2SPeter Wemm /* convert to macro expansion character */ 630c2aa98e2SPeter Wemm *p++ = MACROEXPAND; 631c2aa98e2SPeter Wemm 632c2aa98e2SPeter Wemm /* special handling for $=, $~, $&, and $? */ 633c2aa98e2SPeter Wemm if (*p == '=' || *p == '~' || *p == '&' || *p == '?') 634c2aa98e2SPeter Wemm p++; 635c2aa98e2SPeter Wemm 636c2aa98e2SPeter Wemm /* convert macro name to code */ 637c2aa98e2SPeter Wemm *p = macid(p, &ep); 638c2aa98e2SPeter Wemm if (ep != p) 639c2aa98e2SPeter Wemm strcpy(p + 1, ep); 640c2aa98e2SPeter Wemm } 641c2aa98e2SPeter Wemm 642c2aa98e2SPeter Wemm /* strip trailing white space from the line */ 643c2aa98e2SPeter Wemm while (--p > bp && isascii(*p) && isspace(*p)) 644c2aa98e2SPeter Wemm *p = '\0'; 645c2aa98e2SPeter Wemm } 646c2aa98e2SPeter Wemm /* 647c2aa98e2SPeter Wemm ** TOOMANY -- signal too many of some option 648c2aa98e2SPeter Wemm ** 649c2aa98e2SPeter Wemm ** Parameters: 650c2aa98e2SPeter Wemm ** id -- the id of the error line 651c2aa98e2SPeter Wemm ** maxcnt -- the maximum possible values 652c2aa98e2SPeter Wemm ** 653c2aa98e2SPeter Wemm ** Returns: 654c2aa98e2SPeter Wemm ** none. 655c2aa98e2SPeter Wemm ** 656c2aa98e2SPeter Wemm ** Side Effects: 657c2aa98e2SPeter Wemm ** gives a syserr. 658c2aa98e2SPeter Wemm */ 659c2aa98e2SPeter Wemm 660c2aa98e2SPeter Wemm void 661c2aa98e2SPeter Wemm toomany(id, maxcnt) 662c2aa98e2SPeter Wemm int id; 663c2aa98e2SPeter Wemm int maxcnt; 664c2aa98e2SPeter Wemm { 665c2aa98e2SPeter Wemm syserr("too many %c lines, %d max", id, maxcnt); 666c2aa98e2SPeter Wemm } 667c2aa98e2SPeter Wemm /* 668c2aa98e2SPeter Wemm ** FILECLASS -- read members of a class from a file 669c2aa98e2SPeter Wemm ** 670c2aa98e2SPeter Wemm ** Parameters: 671c2aa98e2SPeter Wemm ** class -- class to define. 672c2aa98e2SPeter Wemm ** filename -- name of file to read. 673c2aa98e2SPeter Wemm ** fmt -- scanf string to use for match. 674c2aa98e2SPeter Wemm ** safe -- if set, this is a safe read. 675c2aa98e2SPeter Wemm ** optional -- if set, it is not an error for the file to 676c2aa98e2SPeter Wemm ** not exist. 677c2aa98e2SPeter Wemm ** 678c2aa98e2SPeter Wemm ** Returns: 679c2aa98e2SPeter Wemm ** none 680c2aa98e2SPeter Wemm ** 681c2aa98e2SPeter Wemm ** Side Effects: 682c2aa98e2SPeter Wemm ** 683c2aa98e2SPeter Wemm ** puts all lines in filename that match a scanf into 684c2aa98e2SPeter Wemm ** the named class. 685c2aa98e2SPeter Wemm */ 686c2aa98e2SPeter Wemm 687c2aa98e2SPeter Wemm void 688c2aa98e2SPeter Wemm fileclass(class, filename, fmt, safe, optional) 689c2aa98e2SPeter Wemm int class; 690c2aa98e2SPeter Wemm char *filename; 691c2aa98e2SPeter Wemm char *fmt; 692c2aa98e2SPeter Wemm bool safe; 693c2aa98e2SPeter Wemm bool optional; 694c2aa98e2SPeter Wemm { 695c2aa98e2SPeter Wemm FILE *f; 696c2aa98e2SPeter Wemm int sff; 697c2aa98e2SPeter Wemm pid_t pid; 698c2aa98e2SPeter Wemm register char *p; 699c2aa98e2SPeter Wemm char buf[MAXLINE]; 700c2aa98e2SPeter Wemm 701c2aa98e2SPeter Wemm if (tTd(37, 2)) 702c2aa98e2SPeter Wemm printf("fileclass(%s, fmt=%s)\n", filename, fmt); 703c2aa98e2SPeter Wemm 704c2aa98e2SPeter Wemm if (filename[0] == '|') 705c2aa98e2SPeter Wemm { 706c2aa98e2SPeter Wemm auto int fd; 707c2aa98e2SPeter Wemm int i; 708c2aa98e2SPeter Wemm char *argv[MAXPV + 1]; 709c2aa98e2SPeter Wemm 710c2aa98e2SPeter Wemm i = 0; 711c2aa98e2SPeter Wemm for (p = strtok(&filename[1], " \t"); p != NULL; p = strtok(NULL, " \t")) 712c2aa98e2SPeter Wemm { 713c2aa98e2SPeter Wemm if (i >= MAXPV) 714c2aa98e2SPeter Wemm break; 715c2aa98e2SPeter Wemm argv[i++] = p; 716c2aa98e2SPeter Wemm } 717c2aa98e2SPeter Wemm argv[i] = NULL; 718c2aa98e2SPeter Wemm pid = prog_open(argv, &fd, CurEnv); 719c2aa98e2SPeter Wemm if (pid < 0) 720c2aa98e2SPeter Wemm f = NULL; 721c2aa98e2SPeter Wemm else 722c2aa98e2SPeter Wemm f = fdopen(fd, "r"); 723c2aa98e2SPeter Wemm } 724c2aa98e2SPeter Wemm else 725c2aa98e2SPeter Wemm { 726c2aa98e2SPeter Wemm pid = -1; 727c2aa98e2SPeter Wemm sff = SFF_REGONLY; 728c2aa98e2SPeter Wemm if (!bitset(DBS_CLASSFILEINUNSAFEDIRPATH, DontBlameSendmail)) 729c2aa98e2SPeter Wemm sff |= SFF_SAFEDIRPATH; 730c2aa98e2SPeter Wemm if (!bitset(DBS_LINKEDCLASSFILEINWRITABLEDIR, DontBlameSendmail)) 731c2aa98e2SPeter Wemm sff |= SFF_NOWLINK; 732c2aa98e2SPeter Wemm if (safe) 733c2aa98e2SPeter Wemm sff |= SFF_OPENASROOT; 734c2aa98e2SPeter Wemm if (DontLockReadFiles) 735c2aa98e2SPeter Wemm sff |= SFF_NOLOCK; 736c2aa98e2SPeter Wemm f = safefopen(filename, O_RDONLY, 0, sff); 737c2aa98e2SPeter Wemm } 738c2aa98e2SPeter Wemm if (f == NULL) 739c2aa98e2SPeter Wemm { 740c2aa98e2SPeter Wemm if (!optional) 741c2aa98e2SPeter Wemm syserr("fileclass: cannot open %s", filename); 742c2aa98e2SPeter Wemm return; 743c2aa98e2SPeter Wemm } 744c2aa98e2SPeter Wemm 745c2aa98e2SPeter Wemm while (fgets(buf, sizeof buf, f) != NULL) 746c2aa98e2SPeter Wemm { 747c2aa98e2SPeter Wemm register char *p; 748c2aa98e2SPeter Wemm # if SCANF 749c2aa98e2SPeter Wemm char wordbuf[MAXLINE + 1]; 750c2aa98e2SPeter Wemm # endif 751c2aa98e2SPeter Wemm 752c2aa98e2SPeter Wemm if (buf[0] == '#') 753c2aa98e2SPeter Wemm continue; 754c2aa98e2SPeter Wemm # if SCANF 755c2aa98e2SPeter Wemm if (sscanf(buf, fmt, wordbuf) != 1) 756c2aa98e2SPeter Wemm continue; 757c2aa98e2SPeter Wemm p = wordbuf; 758c2aa98e2SPeter Wemm # else /* SCANF */ 759c2aa98e2SPeter Wemm p = buf; 760c2aa98e2SPeter Wemm # endif /* SCANF */ 761c2aa98e2SPeter Wemm 762c2aa98e2SPeter Wemm /* 763c2aa98e2SPeter Wemm ** Break up the match into words. 764c2aa98e2SPeter Wemm */ 765c2aa98e2SPeter Wemm 766c2aa98e2SPeter Wemm while (*p != '\0') 767c2aa98e2SPeter Wemm { 768c2aa98e2SPeter Wemm register char *q; 769c2aa98e2SPeter Wemm 770c2aa98e2SPeter Wemm /* strip leading spaces */ 771c2aa98e2SPeter Wemm while (isascii(*p) && isspace(*p)) 772c2aa98e2SPeter Wemm p++; 773c2aa98e2SPeter Wemm if (*p == '\0') 774c2aa98e2SPeter Wemm break; 775c2aa98e2SPeter Wemm 776c2aa98e2SPeter Wemm /* find the end of the word */ 777c2aa98e2SPeter Wemm q = p; 778c2aa98e2SPeter Wemm while (*p != '\0' && !(isascii(*p) && isspace(*p))) 779c2aa98e2SPeter Wemm p++; 780c2aa98e2SPeter Wemm if (*p != '\0') 781c2aa98e2SPeter Wemm *p++ = '\0'; 782c2aa98e2SPeter Wemm 783c2aa98e2SPeter Wemm /* enter the word in the symbol table */ 784c2aa98e2SPeter Wemm setclass(class, q); 785c2aa98e2SPeter Wemm } 786c2aa98e2SPeter Wemm } 787c2aa98e2SPeter Wemm 788c2aa98e2SPeter Wemm (void) fclose(f); 789c2aa98e2SPeter Wemm if (pid > 0) 790c2aa98e2SPeter Wemm (void) waitfor(pid); 791c2aa98e2SPeter Wemm } 792c2aa98e2SPeter Wemm /* 793c2aa98e2SPeter Wemm ** MAKEMAILER -- define a new mailer. 794c2aa98e2SPeter Wemm ** 795c2aa98e2SPeter Wemm ** Parameters: 796c2aa98e2SPeter Wemm ** line -- description of mailer. This is in labeled 797c2aa98e2SPeter Wemm ** fields. The fields are: 798c2aa98e2SPeter Wemm ** A -- the argv for this mailer 799c2aa98e2SPeter Wemm ** C -- the character set for MIME conversions 800c2aa98e2SPeter Wemm ** D -- the directory to run in 801c2aa98e2SPeter Wemm ** E -- the eol string 802c2aa98e2SPeter Wemm ** F -- the flags associated with the mailer 803c2aa98e2SPeter Wemm ** L -- the maximum line length 804c2aa98e2SPeter Wemm ** M -- the maximum message size 805c2aa98e2SPeter Wemm ** N -- the niceness at which to run 806c2aa98e2SPeter Wemm ** P -- the path to the mailer 807c2aa98e2SPeter Wemm ** R -- the recipient rewriting set 808c2aa98e2SPeter Wemm ** S -- the sender rewriting set 809c2aa98e2SPeter Wemm ** T -- the mailer type (for DSNs) 810c2aa98e2SPeter Wemm ** U -- the uid to run as 811c2aa98e2SPeter Wemm ** The first word is the canonical name of the mailer. 812c2aa98e2SPeter Wemm ** 813c2aa98e2SPeter Wemm ** Returns: 814c2aa98e2SPeter Wemm ** none. 815c2aa98e2SPeter Wemm ** 816c2aa98e2SPeter Wemm ** Side Effects: 817c2aa98e2SPeter Wemm ** enters the mailer into the mailer table. 818c2aa98e2SPeter Wemm */ 819c2aa98e2SPeter Wemm 820c2aa98e2SPeter Wemm void 821c2aa98e2SPeter Wemm makemailer(line) 822c2aa98e2SPeter Wemm char *line; 823c2aa98e2SPeter Wemm { 824c2aa98e2SPeter Wemm register char *p; 825c2aa98e2SPeter Wemm register struct mailer *m; 826c2aa98e2SPeter Wemm register STAB *s; 827c2aa98e2SPeter Wemm int i; 828c2aa98e2SPeter Wemm char fcode; 829c2aa98e2SPeter Wemm auto char *endp; 830c2aa98e2SPeter Wemm extern int NextMailer; 831c2aa98e2SPeter Wemm extern char **makeargv __P((char *)); 832c2aa98e2SPeter Wemm extern char *munchstring __P((char *, char **, int)); 833c2aa98e2SPeter Wemm 834c2aa98e2SPeter Wemm /* allocate a mailer and set up defaults */ 835c2aa98e2SPeter Wemm m = (struct mailer *) xalloc(sizeof *m); 836c2aa98e2SPeter Wemm bzero((char *) m, sizeof *m); 837c2aa98e2SPeter Wemm 838c2aa98e2SPeter Wemm /* collect the mailer name */ 839c2aa98e2SPeter Wemm for (p = line; *p != '\0' && *p != ',' && !(isascii(*p) && isspace(*p)); p++) 840c2aa98e2SPeter Wemm continue; 841c2aa98e2SPeter Wemm if (*p != '\0') 842c2aa98e2SPeter Wemm *p++ = '\0'; 843c2aa98e2SPeter Wemm if (line[0] == '\0') 844c2aa98e2SPeter Wemm syserr("name required for mailer"); 845c2aa98e2SPeter Wemm m->m_name = newstr(line); 846c2aa98e2SPeter Wemm 847c2aa98e2SPeter Wemm /* now scan through and assign info from the fields */ 848c2aa98e2SPeter Wemm while (*p != '\0') 849c2aa98e2SPeter Wemm { 850c2aa98e2SPeter Wemm auto char *delimptr; 851c2aa98e2SPeter Wemm 852c2aa98e2SPeter Wemm while (*p != '\0' && (*p == ',' || (isascii(*p) && isspace(*p)))) 853c2aa98e2SPeter Wemm p++; 854c2aa98e2SPeter Wemm 855c2aa98e2SPeter Wemm /* p now points to field code */ 856c2aa98e2SPeter Wemm fcode = *p; 857c2aa98e2SPeter Wemm while (*p != '\0' && *p != '=' && *p != ',') 858c2aa98e2SPeter Wemm p++; 859c2aa98e2SPeter Wemm if (*p++ != '=') 860c2aa98e2SPeter Wemm { 861c2aa98e2SPeter Wemm syserr("mailer %s: `=' expected", m->m_name); 862c2aa98e2SPeter Wemm return; 863c2aa98e2SPeter Wemm } 864c2aa98e2SPeter Wemm while (isascii(*p) && isspace(*p)) 865c2aa98e2SPeter Wemm p++; 866c2aa98e2SPeter Wemm 867c2aa98e2SPeter Wemm /* p now points to the field body */ 868c2aa98e2SPeter Wemm p = munchstring(p, &delimptr, ','); 869c2aa98e2SPeter Wemm 870c2aa98e2SPeter Wemm /* install the field into the mailer struct */ 871c2aa98e2SPeter Wemm switch (fcode) 872c2aa98e2SPeter Wemm { 873c2aa98e2SPeter Wemm case 'P': /* pathname */ 874c2aa98e2SPeter Wemm if (*p == '\0') 875c2aa98e2SPeter Wemm syserr("mailer %s: empty path name", m->m_name); 876c2aa98e2SPeter Wemm m->m_mailer = newstr(p); 877c2aa98e2SPeter Wemm break; 878c2aa98e2SPeter Wemm 879c2aa98e2SPeter Wemm case 'F': /* flags */ 880c2aa98e2SPeter Wemm for (; *p != '\0'; p++) 881c2aa98e2SPeter Wemm if (!(isascii(*p) && isspace(*p))) 882c2aa98e2SPeter Wemm setbitn(*p, m->m_flags); 883c2aa98e2SPeter Wemm break; 884c2aa98e2SPeter Wemm 885c2aa98e2SPeter Wemm case 'S': /* sender rewriting ruleset */ 886c2aa98e2SPeter Wemm case 'R': /* recipient rewriting ruleset */ 887c2aa98e2SPeter Wemm i = strtorwset(p, &endp, ST_ENTER); 888c2aa98e2SPeter Wemm if (i < 0) 889c2aa98e2SPeter Wemm return; 890c2aa98e2SPeter Wemm if (fcode == 'S') 891c2aa98e2SPeter Wemm m->m_sh_rwset = m->m_se_rwset = i; 892c2aa98e2SPeter Wemm else 893c2aa98e2SPeter Wemm m->m_rh_rwset = m->m_re_rwset = i; 894c2aa98e2SPeter Wemm 895c2aa98e2SPeter Wemm p = endp; 896c2aa98e2SPeter Wemm if (*p++ == '/') 897c2aa98e2SPeter Wemm { 898c2aa98e2SPeter Wemm i = strtorwset(p, NULL, ST_ENTER); 899c2aa98e2SPeter Wemm if (i < 0) 900c2aa98e2SPeter Wemm return; 901c2aa98e2SPeter Wemm if (fcode == 'S') 902c2aa98e2SPeter Wemm m->m_sh_rwset = i; 903c2aa98e2SPeter Wemm else 904c2aa98e2SPeter Wemm m->m_rh_rwset = i; 905c2aa98e2SPeter Wemm } 906c2aa98e2SPeter Wemm break; 907c2aa98e2SPeter Wemm 908c2aa98e2SPeter Wemm case 'E': /* end of line string */ 909c2aa98e2SPeter Wemm if (*p == '\0') 910c2aa98e2SPeter Wemm syserr("mailer %s: null end-of-line string", 911c2aa98e2SPeter Wemm m->m_name); 912c2aa98e2SPeter Wemm m->m_eol = newstr(p); 913c2aa98e2SPeter Wemm break; 914c2aa98e2SPeter Wemm 915c2aa98e2SPeter Wemm case 'A': /* argument vector */ 916c2aa98e2SPeter Wemm if (*p == '\0') 917c2aa98e2SPeter Wemm syserr("mailer %s: null argument vector", 918c2aa98e2SPeter Wemm m->m_name); 919c2aa98e2SPeter Wemm m->m_argv = makeargv(p); 920c2aa98e2SPeter Wemm break; 921c2aa98e2SPeter Wemm 922c2aa98e2SPeter Wemm case 'M': /* maximum message size */ 923c2aa98e2SPeter Wemm m->m_maxsize = atol(p); 924c2aa98e2SPeter Wemm break; 925c2aa98e2SPeter Wemm 926c2aa98e2SPeter Wemm case 'L': /* maximum line length */ 927c2aa98e2SPeter Wemm m->m_linelimit = atoi(p); 928c2aa98e2SPeter Wemm if (m->m_linelimit < 0) 929c2aa98e2SPeter Wemm m->m_linelimit = 0; 930c2aa98e2SPeter Wemm break; 931c2aa98e2SPeter Wemm 932c2aa98e2SPeter Wemm case 'N': /* run niceness */ 933c2aa98e2SPeter Wemm m->m_nice = atoi(p); 934c2aa98e2SPeter Wemm break; 935c2aa98e2SPeter Wemm 936c2aa98e2SPeter Wemm case 'D': /* working directory */ 937c2aa98e2SPeter Wemm if (*p == '\0') 938c2aa98e2SPeter Wemm syserr("mailer %s: null working directory", 939c2aa98e2SPeter Wemm m->m_name); 940c2aa98e2SPeter Wemm m->m_execdir = newstr(p); 941c2aa98e2SPeter Wemm break; 942c2aa98e2SPeter Wemm 943c2aa98e2SPeter Wemm case 'C': /* default charset */ 944c2aa98e2SPeter Wemm if (*p == '\0') 945c2aa98e2SPeter Wemm syserr("mailer %s: null charset", m->m_name); 946c2aa98e2SPeter Wemm m->m_defcharset = newstr(p); 947c2aa98e2SPeter Wemm break; 948c2aa98e2SPeter Wemm 949c2aa98e2SPeter Wemm case 'T': /* MTA-Name/Address/Diagnostic types */ 950c2aa98e2SPeter Wemm /* extract MTA name type; default to "dns" */ 951c2aa98e2SPeter Wemm m->m_mtatype = newstr(p); 952c2aa98e2SPeter Wemm p = strchr(m->m_mtatype, '/'); 953c2aa98e2SPeter Wemm if (p != NULL) 954c2aa98e2SPeter Wemm { 955c2aa98e2SPeter Wemm *p++ = '\0'; 956c2aa98e2SPeter Wemm if (*p == '\0') 957c2aa98e2SPeter Wemm p = NULL; 958c2aa98e2SPeter Wemm } 959c2aa98e2SPeter Wemm if (*m->m_mtatype == '\0') 960c2aa98e2SPeter Wemm m->m_mtatype = "dns"; 961c2aa98e2SPeter Wemm 962c2aa98e2SPeter Wemm /* extract address type; default to "rfc822" */ 963c2aa98e2SPeter Wemm m->m_addrtype = p; 964c2aa98e2SPeter Wemm if (p != NULL) 965c2aa98e2SPeter Wemm p = strchr(p, '/'); 966c2aa98e2SPeter Wemm if (p != NULL) 967c2aa98e2SPeter Wemm { 968c2aa98e2SPeter Wemm *p++ = '\0'; 969c2aa98e2SPeter Wemm if (*p == '\0') 970c2aa98e2SPeter Wemm p = NULL; 971c2aa98e2SPeter Wemm } 972c2aa98e2SPeter Wemm if (m->m_addrtype == NULL || *m->m_addrtype == '\0') 973c2aa98e2SPeter Wemm m->m_addrtype = "rfc822"; 974c2aa98e2SPeter Wemm 975c2aa98e2SPeter Wemm /* extract diagnostic type; default to "smtp" */ 976c2aa98e2SPeter Wemm m->m_diagtype = p; 977c2aa98e2SPeter Wemm if (m->m_diagtype == NULL || *m->m_diagtype == '\0') 978c2aa98e2SPeter Wemm m->m_diagtype = "smtp"; 979c2aa98e2SPeter Wemm break; 980c2aa98e2SPeter Wemm 981c2aa98e2SPeter Wemm case 'U': /* user id */ 982c2aa98e2SPeter Wemm if (isascii(*p) && !isdigit(*p)) 983c2aa98e2SPeter Wemm { 984c2aa98e2SPeter Wemm char *q = p; 985c2aa98e2SPeter Wemm struct passwd *pw; 986c2aa98e2SPeter Wemm 987c2aa98e2SPeter Wemm while (*p != '\0' && isascii(*p) && 988c2aa98e2SPeter Wemm (isalnum(*p) || strchr("-_", *p) != NULL)) 989c2aa98e2SPeter Wemm p++; 990c2aa98e2SPeter Wemm while (isascii(*p) && isspace(*p)) 991c2aa98e2SPeter Wemm *p++ = '\0'; 992c2aa98e2SPeter Wemm if (*p != '\0') 993c2aa98e2SPeter Wemm *p++ = '\0'; 994c2aa98e2SPeter Wemm if (*q == '\0') 995c2aa98e2SPeter Wemm syserr("mailer %s: null user name", 996c2aa98e2SPeter Wemm m->m_name); 997c2aa98e2SPeter Wemm pw = sm_getpwnam(q); 998c2aa98e2SPeter Wemm if (pw == NULL) 999c2aa98e2SPeter Wemm syserr("readcf: mailer U= flag: unknown user %s", q); 1000c2aa98e2SPeter Wemm else 1001c2aa98e2SPeter Wemm { 1002c2aa98e2SPeter Wemm m->m_uid = pw->pw_uid; 1003c2aa98e2SPeter Wemm m->m_gid = pw->pw_gid; 1004c2aa98e2SPeter Wemm } 1005c2aa98e2SPeter Wemm } 1006c2aa98e2SPeter Wemm else 1007c2aa98e2SPeter Wemm { 1008c2aa98e2SPeter Wemm auto char *q; 1009c2aa98e2SPeter Wemm 1010c2aa98e2SPeter Wemm m->m_uid = strtol(p, &q, 0); 1011c2aa98e2SPeter Wemm p = q; 1012c2aa98e2SPeter Wemm while (isascii(*p) && isspace(*p)) 1013c2aa98e2SPeter Wemm p++; 1014c2aa98e2SPeter Wemm if (*p != '\0') 1015c2aa98e2SPeter Wemm p++; 1016c2aa98e2SPeter Wemm } 1017c2aa98e2SPeter Wemm while (isascii(*p) && isspace(*p)) 1018c2aa98e2SPeter Wemm p++; 1019c2aa98e2SPeter Wemm if (*p == '\0') 1020c2aa98e2SPeter Wemm break; 1021c2aa98e2SPeter Wemm if (isascii(*p) && !isdigit(*p)) 1022c2aa98e2SPeter Wemm { 1023c2aa98e2SPeter Wemm char *q = p; 1024c2aa98e2SPeter Wemm struct group *gr; 1025c2aa98e2SPeter Wemm 1026c2aa98e2SPeter Wemm while (isascii(*p) && isalnum(*p)) 1027c2aa98e2SPeter Wemm p++; 1028c2aa98e2SPeter Wemm *p++ = '\0'; 1029c2aa98e2SPeter Wemm if (*q == '\0') 1030c2aa98e2SPeter Wemm syserr("mailer %s: null group name", 1031c2aa98e2SPeter Wemm m->m_name); 1032c2aa98e2SPeter Wemm gr = getgrnam(q); 1033c2aa98e2SPeter Wemm if (gr == NULL) 1034c2aa98e2SPeter Wemm syserr("readcf: mailer U= flag: unknown group %s", q); 1035c2aa98e2SPeter Wemm else 1036c2aa98e2SPeter Wemm m->m_gid = gr->gr_gid; 1037c2aa98e2SPeter Wemm } 1038c2aa98e2SPeter Wemm else 1039c2aa98e2SPeter Wemm { 1040c2aa98e2SPeter Wemm m->m_gid = strtol(p, NULL, 0); 1041c2aa98e2SPeter Wemm } 1042c2aa98e2SPeter Wemm break; 1043c2aa98e2SPeter Wemm } 1044c2aa98e2SPeter Wemm 1045c2aa98e2SPeter Wemm p = delimptr; 1046c2aa98e2SPeter Wemm } 1047c2aa98e2SPeter Wemm 1048c2aa98e2SPeter Wemm /* do some rationality checking */ 1049c2aa98e2SPeter Wemm if (m->m_argv == NULL) 1050c2aa98e2SPeter Wemm { 1051c2aa98e2SPeter Wemm syserr("M%s: A= argument required", m->m_name); 1052c2aa98e2SPeter Wemm return; 1053c2aa98e2SPeter Wemm } 1054c2aa98e2SPeter Wemm if (m->m_mailer == NULL) 1055c2aa98e2SPeter Wemm { 1056c2aa98e2SPeter Wemm syserr("M%s: P= argument required", m->m_name); 1057c2aa98e2SPeter Wemm return; 1058c2aa98e2SPeter Wemm } 1059c2aa98e2SPeter Wemm 1060c2aa98e2SPeter Wemm if (NextMailer >= MAXMAILERS) 1061c2aa98e2SPeter Wemm { 1062c2aa98e2SPeter Wemm syserr("too many mailers defined (%d max)", MAXMAILERS); 1063c2aa98e2SPeter Wemm return; 1064c2aa98e2SPeter Wemm } 1065c2aa98e2SPeter Wemm 1066c2aa98e2SPeter Wemm /* do some heuristic cleanup for back compatibility */ 1067c2aa98e2SPeter Wemm if (bitnset(M_LIMITS, m->m_flags)) 1068c2aa98e2SPeter Wemm { 1069c2aa98e2SPeter Wemm if (m->m_linelimit == 0) 1070c2aa98e2SPeter Wemm m->m_linelimit = SMTPLINELIM; 1071c2aa98e2SPeter Wemm if (ConfigLevel < 2) 1072c2aa98e2SPeter Wemm setbitn(M_7BITS, m->m_flags); 1073c2aa98e2SPeter Wemm } 1074c2aa98e2SPeter Wemm 1075c2aa98e2SPeter Wemm if (strcmp(m->m_mailer, "[IPC]") == 0 || 1076c2aa98e2SPeter Wemm strcmp(m->m_mailer, "[TCP]") == 0) 1077c2aa98e2SPeter Wemm { 1078c2aa98e2SPeter Wemm if (m->m_mtatype == NULL) 1079c2aa98e2SPeter Wemm m->m_mtatype = "dns"; 1080c2aa98e2SPeter Wemm if (m->m_addrtype == NULL) 1081c2aa98e2SPeter Wemm m->m_addrtype = "rfc822"; 1082c2aa98e2SPeter Wemm if (m->m_diagtype == NULL) 1083c2aa98e2SPeter Wemm m->m_diagtype = "smtp"; 1084c2aa98e2SPeter Wemm } 1085c2aa98e2SPeter Wemm 1086c2aa98e2SPeter Wemm if (strcmp(m->m_mailer, "[FILE]") == 0) 1087c2aa98e2SPeter Wemm { 1088c2aa98e2SPeter Wemm /* Use the second argument for filename */ 1089c2aa98e2SPeter Wemm if (m->m_argv[0] == NULL || m->m_argv[1] == NULL || 1090c2aa98e2SPeter Wemm m->m_argv[2] != NULL) 1091c2aa98e2SPeter Wemm { 1092c2aa98e2SPeter Wemm syserr("M%s: too %s parameters for [FILE] mailer", 1093c2aa98e2SPeter Wemm m->m_name, 1094c2aa98e2SPeter Wemm (m->m_argv[0] == NULL || 1095c2aa98e2SPeter Wemm m->m_argv[1] == NULL) ? "few" : "many"); 1096c2aa98e2SPeter Wemm } 1097c2aa98e2SPeter Wemm else if (strcmp(m->m_argv[0], "FILE") != 0) 1098c2aa98e2SPeter Wemm { 1099c2aa98e2SPeter Wemm syserr("M%s: first argument in [FILE] mailer must be FILE", 1100c2aa98e2SPeter Wemm m->m_name); 1101c2aa98e2SPeter Wemm } 1102c2aa98e2SPeter Wemm } 1103c2aa98e2SPeter Wemm 1104c2aa98e2SPeter Wemm if (m->m_eol == NULL) 1105c2aa98e2SPeter Wemm { 1106c2aa98e2SPeter Wemm char **pp; 1107c2aa98e2SPeter Wemm 1108c2aa98e2SPeter Wemm /* default for SMTP is \r\n; use \n for local delivery */ 1109c2aa98e2SPeter Wemm for (pp = m->m_argv; *pp != NULL; pp++) 1110c2aa98e2SPeter Wemm { 1111c2aa98e2SPeter Wemm char *p; 1112c2aa98e2SPeter Wemm 1113c2aa98e2SPeter Wemm for (p = *pp; *p != '\0'; ) 1114c2aa98e2SPeter Wemm { 1115c2aa98e2SPeter Wemm if ((*p++ & 0377) == MACROEXPAND && *p == 'u') 1116c2aa98e2SPeter Wemm break; 1117c2aa98e2SPeter Wemm } 1118c2aa98e2SPeter Wemm if (*p != '\0') 1119c2aa98e2SPeter Wemm break; 1120c2aa98e2SPeter Wemm } 1121c2aa98e2SPeter Wemm if (*pp == NULL) 1122c2aa98e2SPeter Wemm m->m_eol = "\r\n"; 1123c2aa98e2SPeter Wemm else 1124c2aa98e2SPeter Wemm m->m_eol = "\n"; 1125c2aa98e2SPeter Wemm } 1126c2aa98e2SPeter Wemm 1127c2aa98e2SPeter Wemm /* enter the mailer into the symbol table */ 1128c2aa98e2SPeter Wemm s = stab(m->m_name, ST_MAILER, ST_ENTER); 1129c2aa98e2SPeter Wemm if (s->s_mailer != NULL) 1130c2aa98e2SPeter Wemm { 1131c2aa98e2SPeter Wemm i = s->s_mailer->m_mno; 1132c2aa98e2SPeter Wemm free(s->s_mailer); 1133c2aa98e2SPeter Wemm } 1134c2aa98e2SPeter Wemm else 1135c2aa98e2SPeter Wemm { 1136c2aa98e2SPeter Wemm i = NextMailer++; 1137c2aa98e2SPeter Wemm } 1138c2aa98e2SPeter Wemm Mailer[i] = s->s_mailer = m; 1139c2aa98e2SPeter Wemm m->m_mno = i; 1140c2aa98e2SPeter Wemm } 1141c2aa98e2SPeter Wemm /* 1142c2aa98e2SPeter Wemm ** MUNCHSTRING -- translate a string into internal form. 1143c2aa98e2SPeter Wemm ** 1144c2aa98e2SPeter Wemm ** Parameters: 1145c2aa98e2SPeter Wemm ** p -- the string to munch. 1146c2aa98e2SPeter Wemm ** delimptr -- if non-NULL, set to the pointer of the 1147c2aa98e2SPeter Wemm ** field delimiter character. 1148c2aa98e2SPeter Wemm ** delim -- the delimiter for the field. 1149c2aa98e2SPeter Wemm ** 1150c2aa98e2SPeter Wemm ** Returns: 1151c2aa98e2SPeter Wemm ** the munched string. 1152c2aa98e2SPeter Wemm */ 1153c2aa98e2SPeter Wemm 1154c2aa98e2SPeter Wemm char * 1155c2aa98e2SPeter Wemm munchstring(p, delimptr, delim) 1156c2aa98e2SPeter Wemm register char *p; 1157c2aa98e2SPeter Wemm char **delimptr; 1158c2aa98e2SPeter Wemm int delim; 1159c2aa98e2SPeter Wemm { 1160c2aa98e2SPeter Wemm register char *q; 1161c2aa98e2SPeter Wemm bool backslash = FALSE; 1162c2aa98e2SPeter Wemm bool quotemode = FALSE; 1163c2aa98e2SPeter Wemm static char buf[MAXLINE]; 1164c2aa98e2SPeter Wemm 1165c2aa98e2SPeter Wemm for (q = buf; *p != '\0' && q < &buf[sizeof buf - 1]; p++) 1166c2aa98e2SPeter Wemm { 1167c2aa98e2SPeter Wemm if (backslash) 1168c2aa98e2SPeter Wemm { 1169c2aa98e2SPeter Wemm /* everything is roughly literal */ 1170c2aa98e2SPeter Wemm backslash = FALSE; 1171c2aa98e2SPeter Wemm switch (*p) 1172c2aa98e2SPeter Wemm { 1173c2aa98e2SPeter Wemm case 'r': /* carriage return */ 1174c2aa98e2SPeter Wemm *q++ = '\r'; 1175c2aa98e2SPeter Wemm continue; 1176c2aa98e2SPeter Wemm 1177c2aa98e2SPeter Wemm case 'n': /* newline */ 1178c2aa98e2SPeter Wemm *q++ = '\n'; 1179c2aa98e2SPeter Wemm continue; 1180c2aa98e2SPeter Wemm 1181c2aa98e2SPeter Wemm case 'f': /* form feed */ 1182c2aa98e2SPeter Wemm *q++ = '\f'; 1183c2aa98e2SPeter Wemm continue; 1184c2aa98e2SPeter Wemm 1185c2aa98e2SPeter Wemm case 'b': /* backspace */ 1186c2aa98e2SPeter Wemm *q++ = '\b'; 1187c2aa98e2SPeter Wemm continue; 1188c2aa98e2SPeter Wemm } 1189c2aa98e2SPeter Wemm *q++ = *p; 1190c2aa98e2SPeter Wemm } 1191c2aa98e2SPeter Wemm else 1192c2aa98e2SPeter Wemm { 1193c2aa98e2SPeter Wemm if (*p == '\\') 1194c2aa98e2SPeter Wemm backslash = TRUE; 1195c2aa98e2SPeter Wemm else if (*p == '"') 1196c2aa98e2SPeter Wemm quotemode = !quotemode; 1197c2aa98e2SPeter Wemm else if (quotemode || *p != delim) 1198c2aa98e2SPeter Wemm *q++ = *p; 1199c2aa98e2SPeter Wemm else 1200c2aa98e2SPeter Wemm break; 1201c2aa98e2SPeter Wemm } 1202c2aa98e2SPeter Wemm } 1203c2aa98e2SPeter Wemm 1204c2aa98e2SPeter Wemm if (delimptr != NULL) 1205c2aa98e2SPeter Wemm *delimptr = p; 1206c2aa98e2SPeter Wemm *q++ = '\0'; 1207c2aa98e2SPeter Wemm return (buf); 1208c2aa98e2SPeter Wemm } 1209c2aa98e2SPeter Wemm /* 1210c2aa98e2SPeter Wemm ** MAKEARGV -- break up a string into words 1211c2aa98e2SPeter Wemm ** 1212c2aa98e2SPeter Wemm ** Parameters: 1213c2aa98e2SPeter Wemm ** p -- the string to break up. 1214c2aa98e2SPeter Wemm ** 1215c2aa98e2SPeter Wemm ** Returns: 1216c2aa98e2SPeter Wemm ** a char **argv (dynamically allocated) 1217c2aa98e2SPeter Wemm ** 1218c2aa98e2SPeter Wemm ** Side Effects: 1219c2aa98e2SPeter Wemm ** munges p. 1220c2aa98e2SPeter Wemm */ 1221c2aa98e2SPeter Wemm 1222c2aa98e2SPeter Wemm char ** 1223c2aa98e2SPeter Wemm makeargv(p) 1224c2aa98e2SPeter Wemm register char *p; 1225c2aa98e2SPeter Wemm { 1226c2aa98e2SPeter Wemm char *q; 1227c2aa98e2SPeter Wemm int i; 1228c2aa98e2SPeter Wemm char **avp; 1229c2aa98e2SPeter Wemm char *argv[MAXPV + 1]; 1230c2aa98e2SPeter Wemm 1231c2aa98e2SPeter Wemm /* take apart the words */ 1232c2aa98e2SPeter Wemm i = 0; 1233c2aa98e2SPeter Wemm while (*p != '\0' && i < MAXPV) 1234c2aa98e2SPeter Wemm { 1235c2aa98e2SPeter Wemm q = p; 1236c2aa98e2SPeter Wemm while (*p != '\0' && !(isascii(*p) && isspace(*p))) 1237c2aa98e2SPeter Wemm p++; 1238c2aa98e2SPeter Wemm while (isascii(*p) && isspace(*p)) 1239c2aa98e2SPeter Wemm *p++ = '\0'; 1240c2aa98e2SPeter Wemm argv[i++] = newstr(q); 1241c2aa98e2SPeter Wemm } 1242c2aa98e2SPeter Wemm argv[i++] = NULL; 1243c2aa98e2SPeter Wemm 1244c2aa98e2SPeter Wemm /* now make a copy of the argv */ 1245c2aa98e2SPeter Wemm avp = (char **) xalloc(sizeof *avp * i); 1246c2aa98e2SPeter Wemm bcopy((char *) argv, (char *) avp, sizeof *avp * i); 1247c2aa98e2SPeter Wemm 1248c2aa98e2SPeter Wemm return (avp); 1249c2aa98e2SPeter Wemm } 1250c2aa98e2SPeter Wemm /* 1251c2aa98e2SPeter Wemm ** PRINTRULES -- print rewrite rules (for debugging) 1252c2aa98e2SPeter Wemm ** 1253c2aa98e2SPeter Wemm ** Parameters: 1254c2aa98e2SPeter Wemm ** none. 1255c2aa98e2SPeter Wemm ** 1256c2aa98e2SPeter Wemm ** Returns: 1257c2aa98e2SPeter Wemm ** none. 1258c2aa98e2SPeter Wemm ** 1259c2aa98e2SPeter Wemm ** Side Effects: 1260c2aa98e2SPeter Wemm ** prints rewrite rules. 1261c2aa98e2SPeter Wemm */ 1262c2aa98e2SPeter Wemm 1263c2aa98e2SPeter Wemm void 1264c2aa98e2SPeter Wemm printrules() 1265c2aa98e2SPeter Wemm { 1266c2aa98e2SPeter Wemm register struct rewrite *rwp; 1267c2aa98e2SPeter Wemm register int ruleset; 1268c2aa98e2SPeter Wemm 1269c2aa98e2SPeter Wemm for (ruleset = 0; ruleset < 10; ruleset++) 1270c2aa98e2SPeter Wemm { 1271c2aa98e2SPeter Wemm if (RewriteRules[ruleset] == NULL) 1272c2aa98e2SPeter Wemm continue; 1273c2aa98e2SPeter Wemm printf("\n----Rule Set %d:", ruleset); 1274c2aa98e2SPeter Wemm 1275c2aa98e2SPeter Wemm for (rwp = RewriteRules[ruleset]; rwp != NULL; rwp = rwp->r_next) 1276c2aa98e2SPeter Wemm { 1277c2aa98e2SPeter Wemm printf("\nLHS:"); 1278c2aa98e2SPeter Wemm printav(rwp->r_lhs); 1279c2aa98e2SPeter Wemm printf("RHS:"); 1280c2aa98e2SPeter Wemm printav(rwp->r_rhs); 1281c2aa98e2SPeter Wemm } 1282c2aa98e2SPeter Wemm } 1283c2aa98e2SPeter Wemm } 1284c2aa98e2SPeter Wemm /* 1285c2aa98e2SPeter Wemm ** PRINTMAILER -- print mailer structure (for debugging) 1286c2aa98e2SPeter Wemm ** 1287c2aa98e2SPeter Wemm ** Parameters: 1288c2aa98e2SPeter Wemm ** m -- the mailer to print 1289c2aa98e2SPeter Wemm ** 1290c2aa98e2SPeter Wemm ** Returns: 1291c2aa98e2SPeter Wemm ** none. 1292c2aa98e2SPeter Wemm */ 1293c2aa98e2SPeter Wemm 1294c2aa98e2SPeter Wemm void 1295c2aa98e2SPeter Wemm printmailer(m) 1296c2aa98e2SPeter Wemm register MAILER *m; 1297c2aa98e2SPeter Wemm { 1298c2aa98e2SPeter Wemm int j; 1299c2aa98e2SPeter Wemm 1300c2aa98e2SPeter Wemm printf("mailer %d (%s): P=%s S=%d/%d R=%d/%d M=%ld U=%d:%d F=", 1301c2aa98e2SPeter Wemm m->m_mno, m->m_name, 1302c2aa98e2SPeter Wemm m->m_mailer, m->m_se_rwset, m->m_sh_rwset, 1303c2aa98e2SPeter Wemm m->m_re_rwset, m->m_rh_rwset, m->m_maxsize, 1304c2aa98e2SPeter Wemm (int) m->m_uid, (int) m->m_gid); 1305c2aa98e2SPeter Wemm for (j = '\0'; j <= '\177'; j++) 1306c2aa98e2SPeter Wemm if (bitnset(j, m->m_flags)) 1307c2aa98e2SPeter Wemm (void) putchar(j); 1308c2aa98e2SPeter Wemm printf(" L=%d E=", m->m_linelimit); 1309c2aa98e2SPeter Wemm xputs(m->m_eol); 1310c2aa98e2SPeter Wemm if (m->m_defcharset != NULL) 1311c2aa98e2SPeter Wemm printf(" C=%s", m->m_defcharset); 1312c2aa98e2SPeter Wemm printf(" T=%s/%s/%s", 1313c2aa98e2SPeter Wemm m->m_mtatype == NULL ? "<undefined>" : m->m_mtatype, 1314c2aa98e2SPeter Wemm m->m_addrtype == NULL ? "<undefined>" : m->m_addrtype, 1315c2aa98e2SPeter Wemm m->m_diagtype == NULL ? "<undefined>" : m->m_diagtype); 1316c2aa98e2SPeter Wemm if (m->m_argv != NULL) 1317c2aa98e2SPeter Wemm { 1318c2aa98e2SPeter Wemm char **a = m->m_argv; 1319c2aa98e2SPeter Wemm 1320c2aa98e2SPeter Wemm printf(" A="); 1321c2aa98e2SPeter Wemm while (*a != NULL) 1322c2aa98e2SPeter Wemm { 1323c2aa98e2SPeter Wemm if (a != m->m_argv) 1324c2aa98e2SPeter Wemm printf(" "); 1325c2aa98e2SPeter Wemm xputs(*a++); 1326c2aa98e2SPeter Wemm } 1327c2aa98e2SPeter Wemm } 1328c2aa98e2SPeter Wemm printf("\n"); 1329c2aa98e2SPeter Wemm } 1330c2aa98e2SPeter Wemm /* 1331c2aa98e2SPeter Wemm ** SETOPTION -- set global processing option 1332c2aa98e2SPeter Wemm ** 1333c2aa98e2SPeter Wemm ** Parameters: 1334c2aa98e2SPeter Wemm ** opt -- option name. 1335c2aa98e2SPeter Wemm ** val -- option value (as a text string). 1336c2aa98e2SPeter Wemm ** safe -- set if this came from a configuration file. 1337c2aa98e2SPeter Wemm ** Some options (if set from the command line) will 1338c2aa98e2SPeter Wemm ** reset the user id to avoid security problems. 1339c2aa98e2SPeter Wemm ** sticky -- if set, don't let other setoptions override 1340c2aa98e2SPeter Wemm ** this value. 1341c2aa98e2SPeter Wemm ** e -- the main envelope. 1342c2aa98e2SPeter Wemm ** 1343c2aa98e2SPeter Wemm ** Returns: 1344c2aa98e2SPeter Wemm ** none. 1345c2aa98e2SPeter Wemm ** 1346c2aa98e2SPeter Wemm ** Side Effects: 1347c2aa98e2SPeter Wemm ** Sets options as implied by the arguments. 1348c2aa98e2SPeter Wemm */ 1349c2aa98e2SPeter Wemm 1350c2aa98e2SPeter Wemm static BITMAP StickyOpt; /* set if option is stuck */ 1351c2aa98e2SPeter Wemm extern void settimeout __P((char *, char *)); 1352c2aa98e2SPeter Wemm 1353c2aa98e2SPeter Wemm 1354c2aa98e2SPeter Wemm #if NAMED_BIND 1355c2aa98e2SPeter Wemm 1356c2aa98e2SPeter Wemm struct resolverflags 1357c2aa98e2SPeter Wemm { 1358c2aa98e2SPeter Wemm char *rf_name; /* name of the flag */ 1359c2aa98e2SPeter Wemm long rf_bits; /* bits to set/clear */ 1360c2aa98e2SPeter Wemm } ResolverFlags[] = 1361c2aa98e2SPeter Wemm { 1362c2aa98e2SPeter Wemm { "debug", RES_DEBUG }, 1363c2aa98e2SPeter Wemm { "aaonly", RES_AAONLY }, 1364c2aa98e2SPeter Wemm { "usevc", RES_USEVC }, 1365c2aa98e2SPeter Wemm { "primary", RES_PRIMARY }, 1366c2aa98e2SPeter Wemm { "igntc", RES_IGNTC }, 1367c2aa98e2SPeter Wemm { "recurse", RES_RECURSE }, 1368c2aa98e2SPeter Wemm { "defnames", RES_DEFNAMES }, 1369c2aa98e2SPeter Wemm { "stayopen", RES_STAYOPEN }, 1370c2aa98e2SPeter Wemm { "dnsrch", RES_DNSRCH }, 1371c2aa98e2SPeter Wemm { "true", 0 }, /* avoid error on old syntax */ 1372c2aa98e2SPeter Wemm { NULL, 0 } 1373c2aa98e2SPeter Wemm }; 1374c2aa98e2SPeter Wemm 1375c2aa98e2SPeter Wemm #endif 1376c2aa98e2SPeter Wemm 1377c2aa98e2SPeter Wemm struct optioninfo 1378c2aa98e2SPeter Wemm { 1379c2aa98e2SPeter Wemm char *o_name; /* long name of option */ 1380c2aa98e2SPeter Wemm u_char o_code; /* short name of option */ 1381c2aa98e2SPeter Wemm bool o_safe; /* safe for random people to use */ 1382c2aa98e2SPeter Wemm } OptionTab[] = 1383c2aa98e2SPeter Wemm { 1384c2aa98e2SPeter Wemm { "SevenBitInput", '7', TRUE }, 1385c2aa98e2SPeter Wemm #if MIME8TO7 1386c2aa98e2SPeter Wemm { "EightBitMode", '8', TRUE }, 1387c2aa98e2SPeter Wemm #endif 1388c2aa98e2SPeter Wemm { "AliasFile", 'A', FALSE }, 1389c2aa98e2SPeter Wemm { "AliasWait", 'a', FALSE }, 1390c2aa98e2SPeter Wemm { "BlankSub", 'B', FALSE }, 1391c2aa98e2SPeter Wemm { "MinFreeBlocks", 'b', TRUE }, 1392c2aa98e2SPeter Wemm { "CheckpointInterval", 'C', TRUE }, 1393c2aa98e2SPeter Wemm { "HoldExpensive", 'c', FALSE }, 1394c2aa98e2SPeter Wemm { "AutoRebuildAliases", 'D', FALSE }, 1395c2aa98e2SPeter Wemm { "DeliveryMode", 'd', TRUE }, 1396c2aa98e2SPeter Wemm { "ErrorHeader", 'E', FALSE }, 1397c2aa98e2SPeter Wemm { "ErrorMode", 'e', TRUE }, 1398c2aa98e2SPeter Wemm { "TempFileMode", 'F', FALSE }, 1399c2aa98e2SPeter Wemm { "SaveFromLine", 'f', FALSE }, 1400c2aa98e2SPeter Wemm { "MatchGECOS", 'G', FALSE }, 1401c2aa98e2SPeter Wemm { "HelpFile", 'H', FALSE }, 1402c2aa98e2SPeter Wemm { "MaxHopCount", 'h', FALSE }, 1403c2aa98e2SPeter Wemm { "ResolverOptions", 'I', FALSE }, 1404c2aa98e2SPeter Wemm { "IgnoreDots", 'i', TRUE }, 1405c2aa98e2SPeter Wemm { "ForwardPath", 'J', FALSE }, 1406c2aa98e2SPeter Wemm { "SendMimeErrors", 'j', TRUE }, 1407c2aa98e2SPeter Wemm { "ConnectionCacheSize", 'k', FALSE }, 1408c2aa98e2SPeter Wemm { "ConnectionCacheTimeout", 'K', FALSE }, 1409c2aa98e2SPeter Wemm { "UseErrorsTo", 'l', FALSE }, 1410c2aa98e2SPeter Wemm { "LogLevel", 'L', TRUE }, 1411c2aa98e2SPeter Wemm { "MeToo", 'm', TRUE }, 1412c2aa98e2SPeter Wemm { "CheckAliases", 'n', FALSE }, 1413c2aa98e2SPeter Wemm { "OldStyleHeaders", 'o', TRUE }, 1414c2aa98e2SPeter Wemm { "DaemonPortOptions", 'O', FALSE }, 1415c2aa98e2SPeter Wemm { "PrivacyOptions", 'p', TRUE }, 1416c2aa98e2SPeter Wemm { "PostmasterCopy", 'P', FALSE }, 1417c2aa98e2SPeter Wemm { "QueueFactor", 'q', FALSE }, 1418c2aa98e2SPeter Wemm { "QueueDirectory", 'Q', FALSE }, 1419c2aa98e2SPeter Wemm { "DontPruneRoutes", 'R', FALSE }, 1420c2aa98e2SPeter Wemm { "Timeout", 'r', FALSE }, 1421c2aa98e2SPeter Wemm { "StatusFile", 'S', FALSE }, 1422c2aa98e2SPeter Wemm { "SuperSafe", 's', TRUE }, 1423c2aa98e2SPeter Wemm { "QueueTimeout", 'T', FALSE }, 1424c2aa98e2SPeter Wemm { "TimeZoneSpec", 't', FALSE }, 1425c2aa98e2SPeter Wemm { "UserDatabaseSpec", 'U', FALSE }, 1426c2aa98e2SPeter Wemm { "DefaultUser", 'u', FALSE }, 1427c2aa98e2SPeter Wemm { "FallbackMXhost", 'V', FALSE }, 1428c2aa98e2SPeter Wemm { "Verbose", 'v', TRUE }, 1429c2aa98e2SPeter Wemm { "TryNullMXList", 'w', FALSE }, 1430c2aa98e2SPeter Wemm { "QueueLA", 'x', FALSE }, 1431c2aa98e2SPeter Wemm { "RefuseLA", 'X', FALSE }, 1432c2aa98e2SPeter Wemm { "RecipientFactor", 'y', FALSE }, 1433c2aa98e2SPeter Wemm { "ForkEachJob", 'Y', FALSE }, 1434c2aa98e2SPeter Wemm { "ClassFactor", 'z', FALSE }, 1435c2aa98e2SPeter Wemm { "RetryFactor", 'Z', FALSE }, 1436c2aa98e2SPeter Wemm #define O_QUEUESORTORD 0x81 1437c2aa98e2SPeter Wemm { "QueueSortOrder", O_QUEUESORTORD, TRUE }, 1438c2aa98e2SPeter Wemm #define O_HOSTSFILE 0x82 1439c2aa98e2SPeter Wemm { "HostsFile", O_HOSTSFILE, FALSE }, 1440c2aa98e2SPeter Wemm #define O_MQA 0x83 1441c2aa98e2SPeter Wemm { "MinQueueAge", O_MQA, TRUE }, 1442c2aa98e2SPeter Wemm #define O_DEFCHARSET 0x85 1443c2aa98e2SPeter Wemm { "DefaultCharSet", O_DEFCHARSET, TRUE }, 1444c2aa98e2SPeter Wemm #define O_SSFILE 0x86 1445c2aa98e2SPeter Wemm { "ServiceSwitchFile", O_SSFILE, FALSE }, 1446c2aa98e2SPeter Wemm #define O_DIALDELAY 0x87 1447c2aa98e2SPeter Wemm { "DialDelay", O_DIALDELAY, TRUE }, 1448c2aa98e2SPeter Wemm #define O_NORCPTACTION 0x88 1449c2aa98e2SPeter Wemm { "NoRecipientAction", O_NORCPTACTION, TRUE }, 1450c2aa98e2SPeter Wemm #define O_SAFEFILEENV 0x89 1451c2aa98e2SPeter Wemm { "SafeFileEnvironment", O_SAFEFILEENV, FALSE }, 1452c2aa98e2SPeter Wemm #define O_MAXMSGSIZE 0x8a 1453c2aa98e2SPeter Wemm { "MaxMessageSize", O_MAXMSGSIZE, FALSE }, 1454c2aa98e2SPeter Wemm #define O_COLONOKINADDR 0x8b 1455c2aa98e2SPeter Wemm { "ColonOkInAddr", O_COLONOKINADDR, TRUE }, 1456c2aa98e2SPeter Wemm #define O_MAXQUEUERUN 0x8c 1457c2aa98e2SPeter Wemm { "MaxQueueRunSize", O_MAXQUEUERUN, TRUE }, 1458c2aa98e2SPeter Wemm #define O_MAXCHILDREN 0x8d 1459c2aa98e2SPeter Wemm { "MaxDaemonChildren", O_MAXCHILDREN, FALSE }, 1460c2aa98e2SPeter Wemm #define O_KEEPCNAMES 0x8e 1461c2aa98e2SPeter Wemm { "DontExpandCnames", O_KEEPCNAMES, FALSE }, 1462c2aa98e2SPeter Wemm #define O_MUSTQUOTE 0x8f 1463c2aa98e2SPeter Wemm { "MustQuoteChars", O_MUSTQUOTE, FALSE }, 1464c2aa98e2SPeter Wemm #define O_SMTPGREETING 0x90 1465c2aa98e2SPeter Wemm { "SmtpGreetingMessage", O_SMTPGREETING, FALSE }, 1466c2aa98e2SPeter Wemm #define O_UNIXFROM 0x91 1467c2aa98e2SPeter Wemm { "UnixFromLine", O_UNIXFROM, FALSE }, 1468c2aa98e2SPeter Wemm #define O_OPCHARS 0x92 1469c2aa98e2SPeter Wemm { "OperatorChars", O_OPCHARS, FALSE }, 1470c2aa98e2SPeter Wemm #define O_DONTINITGRPS 0x93 1471c2aa98e2SPeter Wemm { "DontInitGroups", O_DONTINITGRPS, FALSE }, 1472c2aa98e2SPeter Wemm #define O_SLFH 0x94 1473c2aa98e2SPeter Wemm { "SingleLineFromHeader", O_SLFH, TRUE }, 1474c2aa98e2SPeter Wemm #define O_ABH 0x95 1475c2aa98e2SPeter Wemm { "AllowBogusHELO", O_ABH, TRUE }, 1476c2aa98e2SPeter Wemm #define O_CONNTHROT 0x97 1477c2aa98e2SPeter Wemm { "ConnectionRateThrottle", O_CONNTHROT, FALSE }, 1478c2aa98e2SPeter Wemm #define O_UGW 0x99 1479c2aa98e2SPeter Wemm { "UnsafeGroupWrites", O_UGW, FALSE }, 1480c2aa98e2SPeter Wemm #define O_DBLBOUNCE 0x9a 1481c2aa98e2SPeter Wemm { "DoubleBounceAddress", O_DBLBOUNCE, FALSE }, 1482c2aa98e2SPeter Wemm #define O_HSDIR 0x9b 1483c2aa98e2SPeter Wemm { "HostStatusDirectory", O_HSDIR, FALSE }, 1484c2aa98e2SPeter Wemm #define O_SINGTHREAD 0x9c 1485c2aa98e2SPeter Wemm { "SingleThreadDelivery", O_SINGTHREAD, FALSE }, 1486c2aa98e2SPeter Wemm #define O_RUNASUSER 0x9d 1487c2aa98e2SPeter Wemm { "RunAsUser", O_RUNASUSER, FALSE }, 1488c2aa98e2SPeter Wemm #if _FFR_DSN_RRT_OPTION 1489c2aa98e2SPeter Wemm #define O_DSN_RRT 0x9e 1490c2aa98e2SPeter Wemm { "RrtImpliesDsn", O_DSN_RRT, FALSE }, 1491c2aa98e2SPeter Wemm #endif 1492c2aa98e2SPeter Wemm #if _FFR_PIDFILE_OPTION 1493c2aa98e2SPeter Wemm #define O_PIDFILE 0x9f 1494c2aa98e2SPeter Wemm { "PidFile", O_PIDFILE, FALSE }, 1495c2aa98e2SPeter Wemm #endif 1496c2aa98e2SPeter Wemm #define O_DONTBLAMESENDMAIL 0xa0 1497c2aa98e2SPeter Wemm { "DontBlameSendmail", O_DONTBLAMESENDMAIL, FALSE }, 1498c2aa98e2SPeter Wemm #define O_DPI 0xa1 1499c2aa98e2SPeter Wemm { "DontProbeInterfaces", O_DPI, FALSE }, 1500c2aa98e2SPeter Wemm #define O_MAXRCPT 0xa2 1501c2aa98e2SPeter Wemm { "MaxRecipientsPerMessage", O_MAXRCPT, FALSE }, 1502c2aa98e2SPeter Wemm #if _FFR_DEADLETTERDROP_OPTION 1503c2aa98e2SPeter Wemm #define O_DEADLETTER 0xa3 1504c2aa98e2SPeter Wemm { "DeadLetterDrop", O_DEADLETTER, FALSE }, 1505c2aa98e2SPeter Wemm #endif 1506c2aa98e2SPeter Wemm #if _FFR_DONTLOCKFILESFORREAD_OPTION 1507c2aa98e2SPeter Wemm #define O_DONTLOCK 0xa4 1508c2aa98e2SPeter Wemm { "DontLockFilesForRead", O_DONTLOCK, FALSE }, 1509c2aa98e2SPeter Wemm #endif 1510c2aa98e2SPeter Wemm #if _FFR_MAXALIASRECURSION_OPTION 1511c2aa98e2SPeter Wemm #define O_MAXALIASRCSN 0xa5 1512c2aa98e2SPeter Wemm { "MaxAliasRecursion", O_MAXALIASRCSN, FALSE }, 1513c2aa98e2SPeter Wemm #endif 1514c2aa98e2SPeter Wemm #if _FFR_CONNECTONLYTO_OPTION 1515c2aa98e2SPeter Wemm #define O_CNCTONLYTO 0xa6 1516c2aa98e2SPeter Wemm { "ConnectOnlyTo", O_CNCTONLYTO, FALSE }, 1517c2aa98e2SPeter Wemm #endif 1518065a643dSPeter Wemm #if _FFR_TRUSTED_USER 1519065a643dSPeter Wemm #define O_TRUSTUSER 0xa7 1520065a643dSPeter Wemm { "TrustedUser", O_TRUSTUSER, FALSE }, 1521c2aa98e2SPeter Wemm #endif 1522065a643dSPeter Wemm #if _FFR_MAX_MIME_HEADER_LENGTH 1523065a643dSPeter Wemm #define O_MAXMIMEHDRLEN 0xa8 1524065a643dSPeter Wemm { "MaxMimeHeaderLength", O_MAXMIMEHDRLEN, FALSE }, 1525065a643dSPeter Wemm #endif 1526065a643dSPeter Wemm #if _FFR_CONTROL_SOCKET 1527065a643dSPeter Wemm #define O_CONTROLSOCKET 0xa9 1528065a643dSPeter Wemm { "ControlSocketName", O_CONTROLSOCKET, FALSE }, 1529065a643dSPeter Wemm #endif 15302e43090eSPeter Wemm #if _FFR_MAX_HEADERS_LENGTH 15312e43090eSPeter Wemm #define O_MAXHDRSLEN 0xaa 15322e43090eSPeter Wemm { "MaxHeadersLength", O_MAXHDRSLEN, FALSE }, 153325bab6e9SPeter Wemm #endif 1534c2aa98e2SPeter Wemm { NULL, '\0', FALSE } 1535c2aa98e2SPeter Wemm }; 1536c2aa98e2SPeter Wemm 1537c2aa98e2SPeter Wemm 1538c2aa98e2SPeter Wemm 1539c2aa98e2SPeter Wemm void 1540c2aa98e2SPeter Wemm setoption(opt, val, safe, sticky, e) 1541c2aa98e2SPeter Wemm int opt; 1542c2aa98e2SPeter Wemm char *val; 1543c2aa98e2SPeter Wemm bool safe; 1544c2aa98e2SPeter Wemm bool sticky; 1545c2aa98e2SPeter Wemm register ENVELOPE *e; 1546c2aa98e2SPeter Wemm { 1547c2aa98e2SPeter Wemm register char *p; 1548c2aa98e2SPeter Wemm register struct optioninfo *o; 1549c2aa98e2SPeter Wemm char *subopt; 1550c2aa98e2SPeter Wemm int mid; 1551c2aa98e2SPeter Wemm bool can_setuid = RunAsUid == 0; 1552c2aa98e2SPeter Wemm auto char *ep; 1553c2aa98e2SPeter Wemm char buf[50]; 1554c2aa98e2SPeter Wemm extern bool atobool __P((char *)); 1555c2aa98e2SPeter Wemm extern time_t convtime __P((char *, char)); 1556c2aa98e2SPeter Wemm extern int QueueLA; 1557c2aa98e2SPeter Wemm extern int RefuseLA; 1558c2aa98e2SPeter Wemm extern bool Warn_Q_option; 1559c2aa98e2SPeter Wemm extern void setalias __P((char *)); 1560c2aa98e2SPeter Wemm extern int atooct __P((char *)); 1561c2aa98e2SPeter Wemm extern void setdefuser __P((void)); 1562c2aa98e2SPeter Wemm extern void setdaemonoptions __P((char *)); 1563c2aa98e2SPeter Wemm 1564c2aa98e2SPeter Wemm errno = 0; 1565c2aa98e2SPeter Wemm if (opt == ' ') 1566c2aa98e2SPeter Wemm { 1567c2aa98e2SPeter Wemm /* full word options */ 1568c2aa98e2SPeter Wemm struct optioninfo *sel; 1569c2aa98e2SPeter Wemm 1570c2aa98e2SPeter Wemm p = strchr(val, '='); 1571c2aa98e2SPeter Wemm if (p == NULL) 1572c2aa98e2SPeter Wemm p = &val[strlen(val)]; 1573c2aa98e2SPeter Wemm while (*--p == ' ') 1574c2aa98e2SPeter Wemm continue; 1575c2aa98e2SPeter Wemm while (*++p == ' ') 1576c2aa98e2SPeter Wemm *p = '\0'; 1577c2aa98e2SPeter Wemm if (p == val) 1578c2aa98e2SPeter Wemm { 1579c2aa98e2SPeter Wemm syserr("readcf: null option name"); 1580c2aa98e2SPeter Wemm return; 1581c2aa98e2SPeter Wemm } 1582c2aa98e2SPeter Wemm if (*p == '=') 1583c2aa98e2SPeter Wemm *p++ = '\0'; 1584c2aa98e2SPeter Wemm while (*p == ' ') 1585c2aa98e2SPeter Wemm p++; 1586c2aa98e2SPeter Wemm subopt = strchr(val, '.'); 1587c2aa98e2SPeter Wemm if (subopt != NULL) 1588c2aa98e2SPeter Wemm *subopt++ = '\0'; 1589c2aa98e2SPeter Wemm sel = NULL; 1590c2aa98e2SPeter Wemm for (o = OptionTab; o->o_name != NULL; o++) 1591c2aa98e2SPeter Wemm { 1592c2aa98e2SPeter Wemm if (strncasecmp(o->o_name, val, strlen(val)) != 0) 1593c2aa98e2SPeter Wemm continue; 1594c2aa98e2SPeter Wemm if (strlen(o->o_name) == strlen(val)) 1595c2aa98e2SPeter Wemm { 1596c2aa98e2SPeter Wemm /* completely specified -- this must be it */ 1597c2aa98e2SPeter Wemm sel = NULL; 1598c2aa98e2SPeter Wemm break; 1599c2aa98e2SPeter Wemm } 1600c2aa98e2SPeter Wemm if (sel != NULL) 1601c2aa98e2SPeter Wemm break; 1602c2aa98e2SPeter Wemm sel = o; 1603c2aa98e2SPeter Wemm } 1604c2aa98e2SPeter Wemm if (sel != NULL && o->o_name == NULL) 1605c2aa98e2SPeter Wemm o = sel; 1606c2aa98e2SPeter Wemm else if (o->o_name == NULL) 1607c2aa98e2SPeter Wemm { 1608c2aa98e2SPeter Wemm syserr("readcf: unknown option name %s", val); 1609c2aa98e2SPeter Wemm return; 1610c2aa98e2SPeter Wemm } 1611c2aa98e2SPeter Wemm else if (sel != NULL) 1612c2aa98e2SPeter Wemm { 1613c2aa98e2SPeter Wemm syserr("readcf: ambiguous option name %s (matches %s and %s)", 1614c2aa98e2SPeter Wemm val, sel->o_name, o->o_name); 1615c2aa98e2SPeter Wemm return; 1616c2aa98e2SPeter Wemm } 1617c2aa98e2SPeter Wemm if (strlen(val) != strlen(o->o_name)) 1618c2aa98e2SPeter Wemm { 1619c2aa98e2SPeter Wemm int oldVerbose = Verbose; 1620c2aa98e2SPeter Wemm 1621c2aa98e2SPeter Wemm Verbose = 1; 1622c2aa98e2SPeter Wemm message("Option %s used as abbreviation for %s", 1623c2aa98e2SPeter Wemm val, o->o_name); 1624c2aa98e2SPeter Wemm Verbose = oldVerbose; 1625c2aa98e2SPeter Wemm } 1626c2aa98e2SPeter Wemm opt = o->o_code; 1627c2aa98e2SPeter Wemm val = p; 1628c2aa98e2SPeter Wemm } 1629c2aa98e2SPeter Wemm else 1630c2aa98e2SPeter Wemm { 1631c2aa98e2SPeter Wemm for (o = OptionTab; o->o_name != NULL; o++) 1632c2aa98e2SPeter Wemm { 1633c2aa98e2SPeter Wemm if (o->o_code == opt) 1634c2aa98e2SPeter Wemm break; 1635c2aa98e2SPeter Wemm } 1636c2aa98e2SPeter Wemm subopt = NULL; 1637c2aa98e2SPeter Wemm } 1638c2aa98e2SPeter Wemm 1639c2aa98e2SPeter Wemm if (tTd(37, 1)) 1640c2aa98e2SPeter Wemm { 1641c2aa98e2SPeter Wemm printf(isascii(opt) && isprint(opt) ? 1642c2aa98e2SPeter Wemm "setoption %s (%c).%s=" : 1643c2aa98e2SPeter Wemm "setoption %s (0x%x).%s=", 1644c2aa98e2SPeter Wemm o->o_name == NULL ? "<unknown>" : o->o_name, 1645c2aa98e2SPeter Wemm opt, 1646c2aa98e2SPeter Wemm subopt == NULL ? "" : subopt); 1647c2aa98e2SPeter Wemm xputs(val); 1648c2aa98e2SPeter Wemm } 1649c2aa98e2SPeter Wemm 1650c2aa98e2SPeter Wemm /* 1651c2aa98e2SPeter Wemm ** See if this option is preset for us. 1652c2aa98e2SPeter Wemm */ 1653c2aa98e2SPeter Wemm 1654c2aa98e2SPeter Wemm if (!sticky && bitnset(opt, StickyOpt)) 1655c2aa98e2SPeter Wemm { 1656c2aa98e2SPeter Wemm if (tTd(37, 1)) 1657c2aa98e2SPeter Wemm printf(" (ignored)\n"); 1658c2aa98e2SPeter Wemm return; 1659c2aa98e2SPeter Wemm } 1660c2aa98e2SPeter Wemm 1661c2aa98e2SPeter Wemm /* 1662c2aa98e2SPeter Wemm ** Check to see if this option can be specified by this user. 1663c2aa98e2SPeter Wemm */ 1664c2aa98e2SPeter Wemm 1665c2aa98e2SPeter Wemm if (!safe && RealUid == 0) 1666c2aa98e2SPeter Wemm safe = TRUE; 1667c2aa98e2SPeter Wemm if (!safe && !o->o_safe) 1668c2aa98e2SPeter Wemm { 1669c2aa98e2SPeter Wemm if (opt != 'M' || (val[0] != 'r' && val[0] != 's')) 1670c2aa98e2SPeter Wemm { 1671c2aa98e2SPeter Wemm if (tTd(37, 1)) 1672c2aa98e2SPeter Wemm printf(" (unsafe)"); 1673c2aa98e2SPeter Wemm (void) drop_privileges(TRUE); 1674c2aa98e2SPeter Wemm } 1675c2aa98e2SPeter Wemm } 1676c2aa98e2SPeter Wemm if (tTd(37, 1)) 1677c2aa98e2SPeter Wemm printf("\n"); 1678c2aa98e2SPeter Wemm 1679c2aa98e2SPeter Wemm switch (opt & 0xff) 1680c2aa98e2SPeter Wemm { 1681c2aa98e2SPeter Wemm case '7': /* force seven-bit input */ 1682c2aa98e2SPeter Wemm SevenBitInput = atobool(val); 1683c2aa98e2SPeter Wemm break; 1684c2aa98e2SPeter Wemm 1685c2aa98e2SPeter Wemm #if MIME8TO7 1686c2aa98e2SPeter Wemm case '8': /* handling of 8-bit input */ 1687c2aa98e2SPeter Wemm switch (*val) 1688c2aa98e2SPeter Wemm { 1689c2aa98e2SPeter Wemm case 'm': /* convert 8-bit, convert MIME */ 1690c2aa98e2SPeter Wemm MimeMode = MM_CVTMIME|MM_MIME8BIT; 1691c2aa98e2SPeter Wemm break; 1692c2aa98e2SPeter Wemm 1693c2aa98e2SPeter Wemm case 'p': /* pass 8 bit, convert MIME */ 1694c2aa98e2SPeter Wemm MimeMode = MM_CVTMIME|MM_PASS8BIT; 1695c2aa98e2SPeter Wemm break; 1696c2aa98e2SPeter Wemm 1697c2aa98e2SPeter Wemm case 's': /* strict adherence */ 1698c2aa98e2SPeter Wemm MimeMode = MM_CVTMIME; 1699c2aa98e2SPeter Wemm break; 1700c2aa98e2SPeter Wemm 1701c2aa98e2SPeter Wemm #if 0 1702c2aa98e2SPeter Wemm case 'r': /* reject 8-bit, don't convert MIME */ 1703c2aa98e2SPeter Wemm MimeMode = 0; 1704c2aa98e2SPeter Wemm break; 1705c2aa98e2SPeter Wemm 1706c2aa98e2SPeter Wemm case 'j': /* "just send 8" */ 1707c2aa98e2SPeter Wemm MimeMode = MM_PASS8BIT; 1708c2aa98e2SPeter Wemm break; 1709c2aa98e2SPeter Wemm 1710c2aa98e2SPeter Wemm case 'a': /* encode 8 bit if available */ 1711c2aa98e2SPeter Wemm MimeMode = MM_MIME8BIT|MM_PASS8BIT|MM_CVTMIME; 1712c2aa98e2SPeter Wemm break; 1713c2aa98e2SPeter Wemm 1714c2aa98e2SPeter Wemm case 'c': /* convert 8 bit to MIME, never 7 bit */ 1715c2aa98e2SPeter Wemm MimeMode = MM_MIME8BIT; 1716c2aa98e2SPeter Wemm break; 1717c2aa98e2SPeter Wemm #endif 1718c2aa98e2SPeter Wemm 1719c2aa98e2SPeter Wemm default: 1720c2aa98e2SPeter Wemm syserr("Unknown 8-bit mode %c", *val); 1721065a643dSPeter Wemm finis(FALSE, EX_USAGE); 1722c2aa98e2SPeter Wemm } 1723c2aa98e2SPeter Wemm break; 1724c2aa98e2SPeter Wemm #endif 1725c2aa98e2SPeter Wemm 1726c2aa98e2SPeter Wemm case 'A': /* set default alias file */ 1727c2aa98e2SPeter Wemm if (val[0] == '\0') 1728c2aa98e2SPeter Wemm setalias("aliases"); 1729c2aa98e2SPeter Wemm else 1730c2aa98e2SPeter Wemm setalias(val); 1731c2aa98e2SPeter Wemm break; 1732c2aa98e2SPeter Wemm 1733c2aa98e2SPeter Wemm case 'a': /* look N minutes for "@:@" in alias file */ 1734c2aa98e2SPeter Wemm if (val[0] == '\0') 1735c2aa98e2SPeter Wemm SafeAlias = 5 * 60; /* five minutes */ 1736c2aa98e2SPeter Wemm else 1737c2aa98e2SPeter Wemm SafeAlias = convtime(val, 'm'); 1738c2aa98e2SPeter Wemm break; 1739c2aa98e2SPeter Wemm 1740c2aa98e2SPeter Wemm case 'B': /* substitution for blank character */ 1741c2aa98e2SPeter Wemm SpaceSub = val[0]; 1742c2aa98e2SPeter Wemm if (SpaceSub == '\0') 1743c2aa98e2SPeter Wemm SpaceSub = ' '; 1744c2aa98e2SPeter Wemm break; 1745c2aa98e2SPeter Wemm 1746c2aa98e2SPeter Wemm case 'b': /* min blocks free on queue fs/max msg size */ 1747c2aa98e2SPeter Wemm p = strchr(val, '/'); 1748c2aa98e2SPeter Wemm if (p != NULL) 1749c2aa98e2SPeter Wemm { 1750c2aa98e2SPeter Wemm *p++ = '\0'; 1751c2aa98e2SPeter Wemm MaxMessageSize = atol(p); 1752c2aa98e2SPeter Wemm } 1753c2aa98e2SPeter Wemm MinBlocksFree = atol(val); 1754c2aa98e2SPeter Wemm break; 1755c2aa98e2SPeter Wemm 1756c2aa98e2SPeter Wemm case 'c': /* don't connect to "expensive" mailers */ 1757c2aa98e2SPeter Wemm NoConnect = atobool(val); 1758c2aa98e2SPeter Wemm break; 1759c2aa98e2SPeter Wemm 1760c2aa98e2SPeter Wemm case 'C': /* checkpoint every N addresses */ 1761c2aa98e2SPeter Wemm CheckpointInterval = atoi(val); 1762c2aa98e2SPeter Wemm break; 1763c2aa98e2SPeter Wemm 1764c2aa98e2SPeter Wemm case 'd': /* delivery mode */ 1765c2aa98e2SPeter Wemm switch (*val) 1766c2aa98e2SPeter Wemm { 1767c2aa98e2SPeter Wemm case '\0': 1768c2aa98e2SPeter Wemm e->e_sendmode = SM_DELIVER; 1769c2aa98e2SPeter Wemm break; 1770c2aa98e2SPeter Wemm 1771c2aa98e2SPeter Wemm case SM_QUEUE: /* queue only */ 1772c2aa98e2SPeter Wemm case SM_DEFER: /* queue only and defer map lookups */ 1773c2aa98e2SPeter Wemm #if !QUEUE 1774c2aa98e2SPeter Wemm syserr("need QUEUE to set -odqueue or -oddefer"); 1775c2aa98e2SPeter Wemm #endif /* QUEUE */ 1776c2aa98e2SPeter Wemm /* fall through..... */ 1777c2aa98e2SPeter Wemm 1778c2aa98e2SPeter Wemm case SM_DELIVER: /* do everything */ 1779c2aa98e2SPeter Wemm case SM_FORK: /* fork after verification */ 1780c2aa98e2SPeter Wemm e->e_sendmode = *val; 1781c2aa98e2SPeter Wemm break; 1782c2aa98e2SPeter Wemm 1783c2aa98e2SPeter Wemm default: 1784c2aa98e2SPeter Wemm syserr("Unknown delivery mode %c", *val); 1785065a643dSPeter Wemm finis(FALSE, EX_USAGE); 1786c2aa98e2SPeter Wemm } 1787c2aa98e2SPeter Wemm buf[0] = (char)e->e_sendmode; 1788c2aa98e2SPeter Wemm buf[1] = '\0'; 1789c2aa98e2SPeter Wemm define(macid("{deliveryMode}", NULL), newstr(buf), e); 1790c2aa98e2SPeter Wemm break; 1791c2aa98e2SPeter Wemm 1792c2aa98e2SPeter Wemm case 'D': /* rebuild alias database as needed */ 1793c2aa98e2SPeter Wemm AutoRebuild = atobool(val); 1794c2aa98e2SPeter Wemm break; 1795c2aa98e2SPeter Wemm 1796c2aa98e2SPeter Wemm case 'E': /* error message header/header file */ 1797c2aa98e2SPeter Wemm if (*val != '\0') 1798c2aa98e2SPeter Wemm ErrMsgFile = newstr(val); 1799c2aa98e2SPeter Wemm break; 1800c2aa98e2SPeter Wemm 1801c2aa98e2SPeter Wemm case 'e': /* set error processing mode */ 1802c2aa98e2SPeter Wemm switch (*val) 1803c2aa98e2SPeter Wemm { 1804c2aa98e2SPeter Wemm case EM_QUIET: /* be silent about it */ 1805c2aa98e2SPeter Wemm case EM_MAIL: /* mail back */ 1806c2aa98e2SPeter Wemm case EM_BERKNET: /* do berknet error processing */ 1807c2aa98e2SPeter Wemm case EM_WRITE: /* write back (or mail) */ 1808c2aa98e2SPeter Wemm case EM_PRINT: /* print errors normally (default) */ 1809c2aa98e2SPeter Wemm e->e_errormode = *val; 1810c2aa98e2SPeter Wemm break; 1811c2aa98e2SPeter Wemm } 1812c2aa98e2SPeter Wemm break; 1813c2aa98e2SPeter Wemm 1814c2aa98e2SPeter Wemm case 'F': /* file mode */ 1815c2aa98e2SPeter Wemm FileMode = atooct(val) & 0777; 1816c2aa98e2SPeter Wemm break; 1817c2aa98e2SPeter Wemm 1818c2aa98e2SPeter Wemm case 'f': /* save Unix-style From lines on front */ 1819c2aa98e2SPeter Wemm SaveFrom = atobool(val); 1820c2aa98e2SPeter Wemm break; 1821c2aa98e2SPeter Wemm 1822c2aa98e2SPeter Wemm case 'G': /* match recipients against GECOS field */ 1823c2aa98e2SPeter Wemm MatchGecos = atobool(val); 1824c2aa98e2SPeter Wemm break; 1825c2aa98e2SPeter Wemm 1826c2aa98e2SPeter Wemm case 'g': /* default gid */ 1827c2aa98e2SPeter Wemm g_opt: 1828c2aa98e2SPeter Wemm if (isascii(*val) && isdigit(*val)) 1829c2aa98e2SPeter Wemm DefGid = atoi(val); 1830c2aa98e2SPeter Wemm else 1831c2aa98e2SPeter Wemm { 1832c2aa98e2SPeter Wemm register struct group *gr; 1833c2aa98e2SPeter Wemm 1834c2aa98e2SPeter Wemm DefGid = -1; 1835c2aa98e2SPeter Wemm gr = getgrnam(val); 1836c2aa98e2SPeter Wemm if (gr == NULL) 1837c2aa98e2SPeter Wemm syserr("readcf: option %c: unknown group %s", 1838c2aa98e2SPeter Wemm opt, val); 1839c2aa98e2SPeter Wemm else 1840c2aa98e2SPeter Wemm DefGid = gr->gr_gid; 1841c2aa98e2SPeter Wemm } 1842c2aa98e2SPeter Wemm break; 1843c2aa98e2SPeter Wemm 1844c2aa98e2SPeter Wemm case 'H': /* help file */ 1845c2aa98e2SPeter Wemm if (val[0] == '\0') 1846c2aa98e2SPeter Wemm HelpFile = "sendmail.hf"; 1847c2aa98e2SPeter Wemm else 1848c2aa98e2SPeter Wemm HelpFile = newstr(val); 1849c2aa98e2SPeter Wemm break; 1850c2aa98e2SPeter Wemm 1851c2aa98e2SPeter Wemm case 'h': /* maximum hop count */ 1852c2aa98e2SPeter Wemm MaxHopCount = atoi(val); 1853c2aa98e2SPeter Wemm break; 1854c2aa98e2SPeter Wemm 1855c2aa98e2SPeter Wemm case 'I': /* use internet domain name server */ 1856c2aa98e2SPeter Wemm #if NAMED_BIND 1857c2aa98e2SPeter Wemm for (p = val; *p != 0; ) 1858c2aa98e2SPeter Wemm { 1859c2aa98e2SPeter Wemm bool clearmode; 1860c2aa98e2SPeter Wemm char *q; 1861c2aa98e2SPeter Wemm struct resolverflags *rfp; 1862c2aa98e2SPeter Wemm 1863c2aa98e2SPeter Wemm while (*p == ' ') 1864c2aa98e2SPeter Wemm p++; 1865c2aa98e2SPeter Wemm if (*p == '\0') 1866c2aa98e2SPeter Wemm break; 1867c2aa98e2SPeter Wemm clearmode = FALSE; 1868c2aa98e2SPeter Wemm if (*p == '-') 1869c2aa98e2SPeter Wemm clearmode = TRUE; 1870c2aa98e2SPeter Wemm else if (*p != '+') 1871c2aa98e2SPeter Wemm p--; 1872c2aa98e2SPeter Wemm p++; 1873c2aa98e2SPeter Wemm q = p; 1874c2aa98e2SPeter Wemm while (*p != '\0' && !(isascii(*p) && isspace(*p))) 1875c2aa98e2SPeter Wemm p++; 1876c2aa98e2SPeter Wemm if (*p != '\0') 1877c2aa98e2SPeter Wemm *p++ = '\0'; 1878c2aa98e2SPeter Wemm if (strcasecmp(q, "HasWildcardMX") == 0) 1879c2aa98e2SPeter Wemm { 1880c2aa98e2SPeter Wemm HasWildcardMX = !clearmode; 1881c2aa98e2SPeter Wemm continue; 1882c2aa98e2SPeter Wemm } 1883c2aa98e2SPeter Wemm for (rfp = ResolverFlags; rfp->rf_name != NULL; rfp++) 1884c2aa98e2SPeter Wemm { 1885c2aa98e2SPeter Wemm if (strcasecmp(q, rfp->rf_name) == 0) 1886c2aa98e2SPeter Wemm break; 1887c2aa98e2SPeter Wemm } 1888c2aa98e2SPeter Wemm if (rfp->rf_name == NULL) 1889c2aa98e2SPeter Wemm syserr("readcf: I option value %s unrecognized", q); 1890c2aa98e2SPeter Wemm else if (clearmode) 1891c2aa98e2SPeter Wemm _res.options &= ~rfp->rf_bits; 1892c2aa98e2SPeter Wemm else 1893c2aa98e2SPeter Wemm _res.options |= rfp->rf_bits; 1894c2aa98e2SPeter Wemm } 1895c2aa98e2SPeter Wemm if (tTd(8, 2)) 1896c2aa98e2SPeter Wemm printf("_res.options = %x, HasWildcardMX = %d\n", 1897c2aa98e2SPeter Wemm (u_int) _res.options, HasWildcardMX); 1898c2aa98e2SPeter Wemm #else 1899c2aa98e2SPeter Wemm usrerr("name server (I option) specified but BIND not compiled in"); 1900c2aa98e2SPeter Wemm #endif 1901c2aa98e2SPeter Wemm break; 1902c2aa98e2SPeter Wemm 1903c2aa98e2SPeter Wemm case 'i': /* ignore dot lines in message */ 1904c2aa98e2SPeter Wemm IgnrDot = atobool(val); 1905c2aa98e2SPeter Wemm break; 1906c2aa98e2SPeter Wemm 1907c2aa98e2SPeter Wemm case 'j': /* send errors in MIME (RFC 1341) format */ 1908c2aa98e2SPeter Wemm SendMIMEErrors = atobool(val); 1909c2aa98e2SPeter Wemm break; 1910c2aa98e2SPeter Wemm 1911c2aa98e2SPeter Wemm case 'J': /* .forward search path */ 1912c2aa98e2SPeter Wemm ForwardPath = newstr(val); 1913c2aa98e2SPeter Wemm break; 1914c2aa98e2SPeter Wemm 1915c2aa98e2SPeter Wemm case 'k': /* connection cache size */ 1916c2aa98e2SPeter Wemm MaxMciCache = atoi(val); 1917c2aa98e2SPeter Wemm if (MaxMciCache < 0) 1918c2aa98e2SPeter Wemm MaxMciCache = 0; 1919c2aa98e2SPeter Wemm break; 1920c2aa98e2SPeter Wemm 1921c2aa98e2SPeter Wemm case 'K': /* connection cache timeout */ 1922c2aa98e2SPeter Wemm MciCacheTimeout = convtime(val, 'm'); 1923c2aa98e2SPeter Wemm break; 1924c2aa98e2SPeter Wemm 1925c2aa98e2SPeter Wemm case 'l': /* use Errors-To: header */ 1926c2aa98e2SPeter Wemm UseErrorsTo = atobool(val); 1927c2aa98e2SPeter Wemm break; 1928c2aa98e2SPeter Wemm 1929c2aa98e2SPeter Wemm case 'L': /* log level */ 1930c2aa98e2SPeter Wemm if (safe || LogLevel < atoi(val)) 1931c2aa98e2SPeter Wemm LogLevel = atoi(val); 1932c2aa98e2SPeter Wemm break; 1933c2aa98e2SPeter Wemm 1934c2aa98e2SPeter Wemm case 'M': /* define macro */ 1935c2aa98e2SPeter Wemm mid = macid(val, &ep); 1936c2aa98e2SPeter Wemm p = newstr(ep); 1937c2aa98e2SPeter Wemm if (!safe) 1938c2aa98e2SPeter Wemm cleanstrcpy(p, p, MAXNAME); 1939c2aa98e2SPeter Wemm define(mid, p, CurEnv); 1940c2aa98e2SPeter Wemm sticky = FALSE; 1941c2aa98e2SPeter Wemm break; 1942c2aa98e2SPeter Wemm 1943c2aa98e2SPeter Wemm case 'm': /* send to me too */ 1944c2aa98e2SPeter Wemm MeToo = atobool(val); 1945c2aa98e2SPeter Wemm break; 1946c2aa98e2SPeter Wemm 1947c2aa98e2SPeter Wemm case 'n': /* validate RHS in newaliases */ 1948c2aa98e2SPeter Wemm CheckAliases = atobool(val); 1949c2aa98e2SPeter Wemm break; 1950c2aa98e2SPeter Wemm 1951c2aa98e2SPeter Wemm /* 'N' available -- was "net name" */ 1952c2aa98e2SPeter Wemm 1953c2aa98e2SPeter Wemm case 'O': /* daemon options */ 1954c2aa98e2SPeter Wemm #if DAEMON 1955c2aa98e2SPeter Wemm setdaemonoptions(val); 1956c2aa98e2SPeter Wemm #else 1957c2aa98e2SPeter Wemm syserr("DaemonPortOptions (O option) set but DAEMON not compiled in"); 1958c2aa98e2SPeter Wemm #endif 1959c2aa98e2SPeter Wemm break; 1960c2aa98e2SPeter Wemm 1961c2aa98e2SPeter Wemm case 'o': /* assume old style headers */ 1962c2aa98e2SPeter Wemm if (atobool(val)) 1963c2aa98e2SPeter Wemm CurEnv->e_flags |= EF_OLDSTYLE; 1964c2aa98e2SPeter Wemm else 1965c2aa98e2SPeter Wemm CurEnv->e_flags &= ~EF_OLDSTYLE; 1966c2aa98e2SPeter Wemm break; 1967c2aa98e2SPeter Wemm 1968c2aa98e2SPeter Wemm case 'p': /* select privacy level */ 1969c2aa98e2SPeter Wemm p = val; 1970c2aa98e2SPeter Wemm for (;;) 1971c2aa98e2SPeter Wemm { 1972c2aa98e2SPeter Wemm register struct prival *pv; 1973c2aa98e2SPeter Wemm extern struct prival PrivacyValues[]; 1974c2aa98e2SPeter Wemm 1975c2aa98e2SPeter Wemm while (isascii(*p) && (isspace(*p) || ispunct(*p))) 1976c2aa98e2SPeter Wemm p++; 1977c2aa98e2SPeter Wemm if (*p == '\0') 1978c2aa98e2SPeter Wemm break; 1979c2aa98e2SPeter Wemm val = p; 1980c2aa98e2SPeter Wemm while (isascii(*p) && isalnum(*p)) 1981c2aa98e2SPeter Wemm p++; 1982c2aa98e2SPeter Wemm if (*p != '\0') 1983c2aa98e2SPeter Wemm *p++ = '\0'; 1984c2aa98e2SPeter Wemm 1985c2aa98e2SPeter Wemm for (pv = PrivacyValues; pv->pv_name != NULL; pv++) 1986c2aa98e2SPeter Wemm { 1987c2aa98e2SPeter Wemm if (strcasecmp(val, pv->pv_name) == 0) 1988c2aa98e2SPeter Wemm break; 1989c2aa98e2SPeter Wemm } 1990c2aa98e2SPeter Wemm if (pv->pv_name == NULL) 1991c2aa98e2SPeter Wemm syserr("readcf: Op line: %s unrecognized", val); 1992c2aa98e2SPeter Wemm PrivacyFlags |= pv->pv_flag; 1993c2aa98e2SPeter Wemm } 1994c2aa98e2SPeter Wemm sticky = FALSE; 1995c2aa98e2SPeter Wemm break; 1996c2aa98e2SPeter Wemm 1997c2aa98e2SPeter Wemm case 'P': /* postmaster copy address for returned mail */ 1998c2aa98e2SPeter Wemm PostMasterCopy = newstr(val); 1999c2aa98e2SPeter Wemm break; 2000c2aa98e2SPeter Wemm 2001c2aa98e2SPeter Wemm case 'q': /* slope of queue only function */ 2002c2aa98e2SPeter Wemm QueueFactor = atoi(val); 2003c2aa98e2SPeter Wemm break; 2004c2aa98e2SPeter Wemm 2005c2aa98e2SPeter Wemm case 'Q': /* queue directory */ 2006c2aa98e2SPeter Wemm if (val[0] == '\0') 2007c2aa98e2SPeter Wemm QueueDir = "mqueue"; 2008c2aa98e2SPeter Wemm else 2009c2aa98e2SPeter Wemm QueueDir = newstr(val); 2010c2aa98e2SPeter Wemm if (RealUid != 0 && !safe) 2011c2aa98e2SPeter Wemm Warn_Q_option = TRUE; 2012c2aa98e2SPeter Wemm break; 2013c2aa98e2SPeter Wemm 2014c2aa98e2SPeter Wemm case 'R': /* don't prune routes */ 2015c2aa98e2SPeter Wemm DontPruneRoutes = atobool(val); 2016c2aa98e2SPeter Wemm break; 2017c2aa98e2SPeter Wemm 2018c2aa98e2SPeter Wemm case 'r': /* read timeout */ 2019c2aa98e2SPeter Wemm if (subopt == NULL) 2020c2aa98e2SPeter Wemm inittimeouts(val); 2021c2aa98e2SPeter Wemm else 2022c2aa98e2SPeter Wemm settimeout(subopt, val); 2023c2aa98e2SPeter Wemm break; 2024c2aa98e2SPeter Wemm 2025c2aa98e2SPeter Wemm case 'S': /* status file */ 2026c2aa98e2SPeter Wemm if (val[0] == '\0') 2027c2aa98e2SPeter Wemm StatFile = "sendmail.st"; 2028c2aa98e2SPeter Wemm else 2029c2aa98e2SPeter Wemm StatFile = newstr(val); 2030c2aa98e2SPeter Wemm break; 2031c2aa98e2SPeter Wemm 2032c2aa98e2SPeter Wemm case 's': /* be super safe, even if expensive */ 2033c2aa98e2SPeter Wemm SuperSafe = atobool(val); 2034c2aa98e2SPeter Wemm break; 2035c2aa98e2SPeter Wemm 2036c2aa98e2SPeter Wemm case 'T': /* queue timeout */ 2037c2aa98e2SPeter Wemm p = strchr(val, '/'); 2038c2aa98e2SPeter Wemm if (p != NULL) 2039c2aa98e2SPeter Wemm { 2040c2aa98e2SPeter Wemm *p++ = '\0'; 2041c2aa98e2SPeter Wemm settimeout("queuewarn", p); 2042c2aa98e2SPeter Wemm } 2043c2aa98e2SPeter Wemm settimeout("queuereturn", val); 2044c2aa98e2SPeter Wemm break; 2045c2aa98e2SPeter Wemm 2046c2aa98e2SPeter Wemm case 't': /* time zone name */ 2047c2aa98e2SPeter Wemm TimeZoneSpec = newstr(val); 2048c2aa98e2SPeter Wemm break; 2049c2aa98e2SPeter Wemm 2050c2aa98e2SPeter Wemm case 'U': /* location of user database */ 2051c2aa98e2SPeter Wemm UdbSpec = newstr(val); 2052c2aa98e2SPeter Wemm break; 2053c2aa98e2SPeter Wemm 2054c2aa98e2SPeter Wemm case 'u': /* set default uid */ 2055c2aa98e2SPeter Wemm for (p = val; *p != '\0'; p++) 2056c2aa98e2SPeter Wemm { 2057c2aa98e2SPeter Wemm if (*p == '.' || *p == '/' || *p == ':') 2058c2aa98e2SPeter Wemm { 2059c2aa98e2SPeter Wemm *p++ = '\0'; 2060c2aa98e2SPeter Wemm break; 2061c2aa98e2SPeter Wemm } 2062c2aa98e2SPeter Wemm } 2063c2aa98e2SPeter Wemm if (isascii(*val) && isdigit(*val)) 2064c2aa98e2SPeter Wemm { 2065c2aa98e2SPeter Wemm DefUid = atoi(val); 2066c2aa98e2SPeter Wemm setdefuser(); 2067c2aa98e2SPeter Wemm } 2068c2aa98e2SPeter Wemm else 2069c2aa98e2SPeter Wemm { 2070c2aa98e2SPeter Wemm register struct passwd *pw; 2071c2aa98e2SPeter Wemm 2072c2aa98e2SPeter Wemm DefUid = -1; 2073c2aa98e2SPeter Wemm pw = sm_getpwnam(val); 2074c2aa98e2SPeter Wemm if (pw == NULL) 2075c2aa98e2SPeter Wemm syserr("readcf: option u: unknown user %s", val); 2076c2aa98e2SPeter Wemm else 2077c2aa98e2SPeter Wemm { 2078c2aa98e2SPeter Wemm DefUid = pw->pw_uid; 2079c2aa98e2SPeter Wemm DefGid = pw->pw_gid; 2080c2aa98e2SPeter Wemm DefUser = newstr(pw->pw_name); 2081c2aa98e2SPeter Wemm } 2082c2aa98e2SPeter Wemm } 2083c2aa98e2SPeter Wemm 2084c2aa98e2SPeter Wemm #ifdef UID_MAX 2085c2aa98e2SPeter Wemm if (DefUid > UID_MAX) 2086c2aa98e2SPeter Wemm { 2087c2aa98e2SPeter Wemm syserr("readcf: option u: uid value (%ld) > UID_MAX (%ld); ignored", 2088c2aa98e2SPeter Wemm DefUid, UID_MAX); 2089c2aa98e2SPeter Wemm } 2090c2aa98e2SPeter Wemm #endif 2091c2aa98e2SPeter Wemm 2092c2aa98e2SPeter Wemm /* handle the group if it is there */ 2093c2aa98e2SPeter Wemm if (*p == '\0') 2094c2aa98e2SPeter Wemm break; 2095c2aa98e2SPeter Wemm val = p; 2096c2aa98e2SPeter Wemm goto g_opt; 2097c2aa98e2SPeter Wemm 2098c2aa98e2SPeter Wemm case 'V': /* fallback MX host */ 2099c2aa98e2SPeter Wemm if (val[0] != '\0') 2100c2aa98e2SPeter Wemm FallBackMX = newstr(val); 2101c2aa98e2SPeter Wemm break; 2102c2aa98e2SPeter Wemm 2103c2aa98e2SPeter Wemm case 'v': /* run in verbose mode */ 2104c2aa98e2SPeter Wemm Verbose = atobool(val) ? 1 : 0; 2105c2aa98e2SPeter Wemm break; 2106c2aa98e2SPeter Wemm 2107c2aa98e2SPeter Wemm case 'w': /* if we are best MX, try host directly */ 2108c2aa98e2SPeter Wemm TryNullMXList = atobool(val); 2109c2aa98e2SPeter Wemm break; 2110c2aa98e2SPeter Wemm 2111c2aa98e2SPeter Wemm /* 'W' available -- was wizard password */ 2112c2aa98e2SPeter Wemm 2113c2aa98e2SPeter Wemm case 'x': /* load avg at which to auto-queue msgs */ 2114c2aa98e2SPeter Wemm QueueLA = atoi(val); 2115c2aa98e2SPeter Wemm break; 2116c2aa98e2SPeter Wemm 2117c2aa98e2SPeter Wemm case 'X': /* load avg at which to auto-reject connections */ 2118c2aa98e2SPeter Wemm RefuseLA = atoi(val); 2119c2aa98e2SPeter Wemm break; 2120c2aa98e2SPeter Wemm 2121c2aa98e2SPeter Wemm case 'y': /* work recipient factor */ 2122c2aa98e2SPeter Wemm WkRecipFact = atoi(val); 2123c2aa98e2SPeter Wemm break; 2124c2aa98e2SPeter Wemm 2125c2aa98e2SPeter Wemm case 'Y': /* fork jobs during queue runs */ 2126c2aa98e2SPeter Wemm ForkQueueRuns = atobool(val); 2127c2aa98e2SPeter Wemm break; 2128c2aa98e2SPeter Wemm 2129c2aa98e2SPeter Wemm case 'z': /* work message class factor */ 2130c2aa98e2SPeter Wemm WkClassFact = atoi(val); 2131c2aa98e2SPeter Wemm break; 2132c2aa98e2SPeter Wemm 2133c2aa98e2SPeter Wemm case 'Z': /* work time factor */ 2134c2aa98e2SPeter Wemm WkTimeFact = atoi(val); 2135c2aa98e2SPeter Wemm break; 2136c2aa98e2SPeter Wemm 2137c2aa98e2SPeter Wemm case O_QUEUESORTORD: /* queue sorting order */ 2138c2aa98e2SPeter Wemm switch (*val) 2139c2aa98e2SPeter Wemm { 2140c2aa98e2SPeter Wemm case 'h': /* Host first */ 2141c2aa98e2SPeter Wemm case 'H': 2142c2aa98e2SPeter Wemm QueueSortOrder = QS_BYHOST; 2143c2aa98e2SPeter Wemm break; 2144c2aa98e2SPeter Wemm 2145c2aa98e2SPeter Wemm case 'p': /* Priority order */ 2146c2aa98e2SPeter Wemm case 'P': 2147c2aa98e2SPeter Wemm QueueSortOrder = QS_BYPRIORITY; 2148c2aa98e2SPeter Wemm break; 2149c2aa98e2SPeter Wemm 2150c2aa98e2SPeter Wemm case 't': /* Submission time */ 2151c2aa98e2SPeter Wemm case 'T': 2152c2aa98e2SPeter Wemm QueueSortOrder = QS_BYTIME; 2153c2aa98e2SPeter Wemm break; 2154c2aa98e2SPeter Wemm 2155c2aa98e2SPeter Wemm default: 2156c2aa98e2SPeter Wemm syserr("Invalid queue sort order \"%s\"", val); 2157c2aa98e2SPeter Wemm } 2158c2aa98e2SPeter Wemm break; 2159c2aa98e2SPeter Wemm 2160c2aa98e2SPeter Wemm case O_HOSTSFILE: /* pathname of /etc/hosts file */ 2161c2aa98e2SPeter Wemm HostsFile = newstr(val); 2162c2aa98e2SPeter Wemm break; 2163c2aa98e2SPeter Wemm 2164c2aa98e2SPeter Wemm case O_MQA: /* minimum queue age between deliveries */ 2165c2aa98e2SPeter Wemm MinQueueAge = convtime(val, 'm'); 2166c2aa98e2SPeter Wemm break; 2167c2aa98e2SPeter Wemm 2168c2aa98e2SPeter Wemm case O_DEFCHARSET: /* default character set for mimefying */ 2169c2aa98e2SPeter Wemm DefaultCharSet = newstr(denlstring(val, TRUE, TRUE)); 2170c2aa98e2SPeter Wemm break; 2171c2aa98e2SPeter Wemm 2172c2aa98e2SPeter Wemm case O_SSFILE: /* service switch file */ 2173c2aa98e2SPeter Wemm ServiceSwitchFile = newstr(val); 2174c2aa98e2SPeter Wemm break; 2175c2aa98e2SPeter Wemm 2176c2aa98e2SPeter Wemm case O_DIALDELAY: /* delay for dial-on-demand operation */ 2177c2aa98e2SPeter Wemm DialDelay = convtime(val, 's'); 2178c2aa98e2SPeter Wemm break; 2179c2aa98e2SPeter Wemm 2180c2aa98e2SPeter Wemm case O_NORCPTACTION: /* what to do if no recipient */ 2181c2aa98e2SPeter Wemm if (strcasecmp(val, "none") == 0) 2182c2aa98e2SPeter Wemm NoRecipientAction = NRA_NO_ACTION; 2183c2aa98e2SPeter Wemm else if (strcasecmp(val, "add-to") == 0) 2184c2aa98e2SPeter Wemm NoRecipientAction = NRA_ADD_TO; 2185c2aa98e2SPeter Wemm else if (strcasecmp(val, "add-apparently-to") == 0) 2186c2aa98e2SPeter Wemm NoRecipientAction = NRA_ADD_APPARENTLY_TO; 2187c2aa98e2SPeter Wemm else if (strcasecmp(val, "add-bcc") == 0) 2188c2aa98e2SPeter Wemm NoRecipientAction = NRA_ADD_BCC; 2189c2aa98e2SPeter Wemm else if (strcasecmp(val, "add-to-undisclosed") == 0) 2190c2aa98e2SPeter Wemm NoRecipientAction = NRA_ADD_TO_UNDISCLOSED; 2191c2aa98e2SPeter Wemm else 2192c2aa98e2SPeter Wemm syserr("Invalid NoRecipientAction: %s", val); 2193c2aa98e2SPeter Wemm break; 2194c2aa98e2SPeter Wemm 2195c2aa98e2SPeter Wemm case O_SAFEFILEENV: /* chroot() environ for writing to files */ 2196c2aa98e2SPeter Wemm SafeFileEnv = newstr(val); 2197c2aa98e2SPeter Wemm break; 2198c2aa98e2SPeter Wemm 2199c2aa98e2SPeter Wemm case O_MAXMSGSIZE: /* maximum message size */ 2200c2aa98e2SPeter Wemm MaxMessageSize = atol(val); 2201c2aa98e2SPeter Wemm break; 2202c2aa98e2SPeter Wemm 2203c2aa98e2SPeter Wemm case O_COLONOKINADDR: /* old style handling of colon addresses */ 2204c2aa98e2SPeter Wemm ColonOkInAddr = atobool(val); 2205c2aa98e2SPeter Wemm break; 2206c2aa98e2SPeter Wemm 2207c2aa98e2SPeter Wemm case O_MAXQUEUERUN: /* max # of jobs in a single queue run */ 2208c2aa98e2SPeter Wemm MaxQueueRun = atol(val); 2209c2aa98e2SPeter Wemm break; 2210c2aa98e2SPeter Wemm 2211c2aa98e2SPeter Wemm case O_MAXCHILDREN: /* max # of children of daemon */ 2212c2aa98e2SPeter Wemm MaxChildren = atoi(val); 2213c2aa98e2SPeter Wemm break; 2214c2aa98e2SPeter Wemm 2215c2aa98e2SPeter Wemm case O_KEEPCNAMES: /* don't expand CNAME records */ 2216c2aa98e2SPeter Wemm DontExpandCnames = atobool(val); 2217c2aa98e2SPeter Wemm break; 2218c2aa98e2SPeter Wemm 2219c2aa98e2SPeter Wemm case O_MUSTQUOTE: /* must quote these characters in phrases */ 2220c2aa98e2SPeter Wemm strcpy(buf, "@,;:\\()[]"); 2221c2aa98e2SPeter Wemm if (strlen(val) < (SIZE_T) sizeof buf - 10) 2222c2aa98e2SPeter Wemm strcat(buf, val); 2223c2aa98e2SPeter Wemm MustQuoteChars = newstr(buf); 2224c2aa98e2SPeter Wemm break; 2225c2aa98e2SPeter Wemm 2226c2aa98e2SPeter Wemm case O_SMTPGREETING: /* SMTP greeting message (old $e macro) */ 2227c2aa98e2SPeter Wemm SmtpGreeting = newstr(munchstring(val, NULL, '\0')); 2228c2aa98e2SPeter Wemm break; 2229c2aa98e2SPeter Wemm 2230c2aa98e2SPeter Wemm case O_UNIXFROM: /* UNIX From_ line (old $l macro) */ 2231c2aa98e2SPeter Wemm UnixFromLine = newstr(munchstring(val, NULL, '\0')); 2232c2aa98e2SPeter Wemm break; 2233c2aa98e2SPeter Wemm 2234c2aa98e2SPeter Wemm case O_OPCHARS: /* operator characters (old $o macro) */ 2235c2aa98e2SPeter Wemm OperatorChars = newstr(munchstring(val, NULL, '\0')); 2236c2aa98e2SPeter Wemm break; 2237c2aa98e2SPeter Wemm 2238c2aa98e2SPeter Wemm case O_DONTINITGRPS: /* don't call initgroups(3) */ 2239c2aa98e2SPeter Wemm DontInitGroups = atobool(val); 2240c2aa98e2SPeter Wemm break; 2241c2aa98e2SPeter Wemm 2242c2aa98e2SPeter Wemm case O_SLFH: /* make sure from fits on one line */ 2243c2aa98e2SPeter Wemm SingleLineFromHeader = atobool(val); 2244c2aa98e2SPeter Wemm break; 2245c2aa98e2SPeter Wemm 2246c2aa98e2SPeter Wemm case O_ABH: /* allow HELO commands with syntax errors */ 2247c2aa98e2SPeter Wemm AllowBogusHELO = atobool(val); 2248c2aa98e2SPeter Wemm break; 2249c2aa98e2SPeter Wemm 2250c2aa98e2SPeter Wemm case O_CONNTHROT: /* connection rate throttle */ 2251c2aa98e2SPeter Wemm ConnRateThrottle = atoi(val); 2252c2aa98e2SPeter Wemm break; 2253c2aa98e2SPeter Wemm 2254c2aa98e2SPeter Wemm case O_UGW: /* group writable files are unsafe */ 2255c2aa98e2SPeter Wemm if (!atobool(val)) 2256c2aa98e2SPeter Wemm DontBlameSendmail |= DBS_GROUPWRITABLEFORWARDFILESAFE|DBS_GROUPWRITABLEINCLUDEFILESAFE; 2257c2aa98e2SPeter Wemm break; 2258c2aa98e2SPeter Wemm 2259c2aa98e2SPeter Wemm case O_DBLBOUNCE: /* address to which to send double bounces */ 2260c2aa98e2SPeter Wemm if (val[0] != '\0') 2261c2aa98e2SPeter Wemm DoubleBounceAddr = newstr(val); 2262c2aa98e2SPeter Wemm else 2263c2aa98e2SPeter Wemm syserr("readcf: option DoubleBounceAddress: value required"); 2264c2aa98e2SPeter Wemm break; 2265c2aa98e2SPeter Wemm 2266c2aa98e2SPeter Wemm case O_HSDIR: /* persistent host status directory */ 2267c2aa98e2SPeter Wemm if (val[0] != '\0') 2268c2aa98e2SPeter Wemm HostStatDir = newstr(val); 2269c2aa98e2SPeter Wemm break; 2270c2aa98e2SPeter Wemm 2271c2aa98e2SPeter Wemm case O_SINGTHREAD: /* single thread deliveries (requires hsdir) */ 2272c2aa98e2SPeter Wemm SingleThreadDelivery = atobool(val); 2273c2aa98e2SPeter Wemm break; 2274c2aa98e2SPeter Wemm 2275c2aa98e2SPeter Wemm case O_RUNASUSER: /* run bulk of code as this user */ 2276c2aa98e2SPeter Wemm for (p = val; *p != '\0'; p++) 2277c2aa98e2SPeter Wemm { 2278c2aa98e2SPeter Wemm if (*p == '.' || *p == '/' || *p == ':') 2279c2aa98e2SPeter Wemm { 2280c2aa98e2SPeter Wemm *p++ = '\0'; 2281c2aa98e2SPeter Wemm break; 2282c2aa98e2SPeter Wemm } 2283c2aa98e2SPeter Wemm } 2284c2aa98e2SPeter Wemm if (isascii(*val) && isdigit(*val)) 2285c2aa98e2SPeter Wemm { 2286c2aa98e2SPeter Wemm if (can_setuid) 2287c2aa98e2SPeter Wemm RunAsUid = atoi(val); 2288c2aa98e2SPeter Wemm } 2289c2aa98e2SPeter Wemm else 2290c2aa98e2SPeter Wemm { 2291c2aa98e2SPeter Wemm register struct passwd *pw; 2292c2aa98e2SPeter Wemm 2293c2aa98e2SPeter Wemm pw = sm_getpwnam(val); 2294c2aa98e2SPeter Wemm if (pw == NULL) 2295c2aa98e2SPeter Wemm syserr("readcf: option RunAsUser: unknown user %s", val); 2296c2aa98e2SPeter Wemm else if (can_setuid) 2297c2aa98e2SPeter Wemm { 2298c2aa98e2SPeter Wemm if (*p == '\0') 2299c2aa98e2SPeter Wemm RunAsUserName = newstr(val); 2300c2aa98e2SPeter Wemm RunAsUid = pw->pw_uid; 2301c2aa98e2SPeter Wemm RunAsGid = pw->pw_gid; 2302c2aa98e2SPeter Wemm } 2303c2aa98e2SPeter Wemm } 2304c2aa98e2SPeter Wemm #ifdef UID_MAX 2305c2aa98e2SPeter Wemm if (RunAsUid > UID_MAX) 2306c2aa98e2SPeter Wemm { 2307c2aa98e2SPeter Wemm syserr("readcf: option RunAsUser: uid value (%ld) > UID_MAX (%ld); ignored", 2308c2aa98e2SPeter Wemm RunAsUid, UID_MAX); 2309c2aa98e2SPeter Wemm } 2310c2aa98e2SPeter Wemm #endif 2311c2aa98e2SPeter Wemm if (*p != '\0') 2312c2aa98e2SPeter Wemm { 2313c2aa98e2SPeter Wemm if (isascii(*p) && isdigit(*p)) 2314c2aa98e2SPeter Wemm { 2315c2aa98e2SPeter Wemm if (can_setuid) 2316c2aa98e2SPeter Wemm RunAsGid = atoi(p); 2317c2aa98e2SPeter Wemm } 2318c2aa98e2SPeter Wemm else 2319c2aa98e2SPeter Wemm { 2320c2aa98e2SPeter Wemm register struct group *gr; 2321c2aa98e2SPeter Wemm 2322c2aa98e2SPeter Wemm gr = getgrnam(p); 2323c2aa98e2SPeter Wemm if (gr == NULL) 2324c2aa98e2SPeter Wemm syserr("readcf: option RunAsUser: unknown group %s", 2325c2aa98e2SPeter Wemm p); 2326c2aa98e2SPeter Wemm else if (can_setuid) 2327c2aa98e2SPeter Wemm RunAsGid = gr->gr_gid; 2328c2aa98e2SPeter Wemm } 2329c2aa98e2SPeter Wemm } 2330c2aa98e2SPeter Wemm if (tTd(47, 5)) 2331c2aa98e2SPeter Wemm printf("readcf: RunAsUser = %d:%d\n", (int)RunAsUid, (int)RunAsGid); 2332c2aa98e2SPeter Wemm break; 2333c2aa98e2SPeter Wemm 2334c2aa98e2SPeter Wemm #if _FFR_DSN_RRT_OPTION 2335c2aa98e2SPeter Wemm case O_DSN_RRT: 2336c2aa98e2SPeter Wemm RrtImpliesDsn = atobool(val); 2337c2aa98e2SPeter Wemm break; 2338c2aa98e2SPeter Wemm #endif 2339c2aa98e2SPeter Wemm 2340c2aa98e2SPeter Wemm #if _FFR_PIDFILE_OPTION 2341c2aa98e2SPeter Wemm case O_PIDFILE: 2342c2aa98e2SPeter Wemm free(PidFile); 2343c2aa98e2SPeter Wemm PidFile = newstr(val); 2344c2aa98e2SPeter Wemm break; 2345c2aa98e2SPeter Wemm #endif 2346c2aa98e2SPeter Wemm 2347c2aa98e2SPeter Wemm case O_DONTBLAMESENDMAIL: 2348c2aa98e2SPeter Wemm p = val; 2349c2aa98e2SPeter Wemm for (;;) 2350c2aa98e2SPeter Wemm { 2351c2aa98e2SPeter Wemm register struct dbsval *dbs; 2352c2aa98e2SPeter Wemm extern struct dbsval DontBlameSendmailValues[]; 2353c2aa98e2SPeter Wemm 2354c2aa98e2SPeter Wemm while (isascii(*p) && (isspace(*p) || ispunct(*p))) 2355c2aa98e2SPeter Wemm p++; 2356c2aa98e2SPeter Wemm if (*p == '\0') 2357c2aa98e2SPeter Wemm break; 2358c2aa98e2SPeter Wemm val = p; 2359c2aa98e2SPeter Wemm while (isascii(*p) && isalnum(*p)) 2360c2aa98e2SPeter Wemm p++; 2361c2aa98e2SPeter Wemm if (*p != '\0') 2362c2aa98e2SPeter Wemm *p++ = '\0'; 2363c2aa98e2SPeter Wemm 2364c2aa98e2SPeter Wemm for (dbs = DontBlameSendmailValues; 2365c2aa98e2SPeter Wemm dbs->dbs_name != NULL; dbs++) 2366c2aa98e2SPeter Wemm { 2367c2aa98e2SPeter Wemm if (strcasecmp(val, dbs->dbs_name) == 0) 2368c2aa98e2SPeter Wemm break; 2369c2aa98e2SPeter Wemm } 2370c2aa98e2SPeter Wemm if (dbs->dbs_name == NULL) 2371c2aa98e2SPeter Wemm syserr("readcf: DontBlameSendmail option: %s unrecognized", val); 2372c2aa98e2SPeter Wemm else if (dbs->dbs_flag == DBS_SAFE) 2373c2aa98e2SPeter Wemm DontBlameSendmail = DBS_SAFE; 2374c2aa98e2SPeter Wemm else 2375c2aa98e2SPeter Wemm DontBlameSendmail |= dbs->dbs_flag; 2376c2aa98e2SPeter Wemm } 2377c2aa98e2SPeter Wemm sticky = FALSE; 2378c2aa98e2SPeter Wemm break; 2379c2aa98e2SPeter Wemm 2380c2aa98e2SPeter Wemm case O_DPI: 2381c2aa98e2SPeter Wemm DontProbeInterfaces = atobool(val); 2382c2aa98e2SPeter Wemm break; 2383c2aa98e2SPeter Wemm 2384c2aa98e2SPeter Wemm case O_MAXRCPT: 2385c2aa98e2SPeter Wemm MaxRcptPerMsg = atoi(val); 2386c2aa98e2SPeter Wemm break; 2387c2aa98e2SPeter Wemm 2388c2aa98e2SPeter Wemm #if _FFR_DEADLETTERDROP_OPTION 2389c2aa98e2SPeter Wemm case O_DEADLETTER: 2390c2aa98e2SPeter Wemm if (DeadLetterDrop != NULL) 2391c2aa98e2SPeter Wemm free(DeadLetterDrop); 2392c2aa98e2SPeter Wemm DeadLetterDrop = newstr(val); 2393c2aa98e2SPeter Wemm break; 2394c2aa98e2SPeter Wemm #endif 2395c2aa98e2SPeter Wemm 2396c2aa98e2SPeter Wemm #if _FFR_DONTLOCKFILESFORREAD_OPTION 2397c2aa98e2SPeter Wemm case O_DONTLOCK: 2398c2aa98e2SPeter Wemm DontLockReadFiles = atobool(val); 2399c2aa98e2SPeter Wemm break; 2400c2aa98e2SPeter Wemm #endif 2401c2aa98e2SPeter Wemm 2402c2aa98e2SPeter Wemm #if _FFR_MAXALIASRECURSION_OPTION 2403c2aa98e2SPeter Wemm case O_MAXALIASRCSN: 2404c2aa98e2SPeter Wemm MaxAliasRecursion = atoi(val); 2405c2aa98e2SPeter Wemm break; 2406c2aa98e2SPeter Wemm #endif 2407c2aa98e2SPeter Wemm 2408c2aa98e2SPeter Wemm #if _FFR_CONNECTONLYTO_OPTION 2409c2aa98e2SPeter Wemm case O_CNCTONLYTO: 2410c2aa98e2SPeter Wemm /* XXX should probably use gethostbyname */ 2411c2aa98e2SPeter Wemm ConnectOnlyTo = inet_addr(val); 2412c2aa98e2SPeter Wemm break; 2413c2aa98e2SPeter Wemm #endif 2414c2aa98e2SPeter Wemm 2415065a643dSPeter Wemm #if _FFR_TRUSTED_USER 2416065a643dSPeter Wemm case O_TRUSTUSER: 2417c2aa98e2SPeter Wemm if (isascii(*val) && isdigit(*val)) 2418065a643dSPeter Wemm TrustedUid = atoi(val); 2419c2aa98e2SPeter Wemm else 2420c2aa98e2SPeter Wemm { 2421c2aa98e2SPeter Wemm register struct passwd *pw; 2422c2aa98e2SPeter Wemm 2423065a643dSPeter Wemm TrustedUid = 0; 2424c2aa98e2SPeter Wemm pw = sm_getpwnam(val); 2425c2aa98e2SPeter Wemm if (pw == NULL) 2426065a643dSPeter Wemm syserr("readcf: option TrustedUser: unknown user %s", val); 2427c2aa98e2SPeter Wemm else 2428065a643dSPeter Wemm TrustedUid = pw->pw_uid; 2429c2aa98e2SPeter Wemm } 2430c2aa98e2SPeter Wemm 2431c2aa98e2SPeter Wemm #ifdef UID_MAX 2432065a643dSPeter Wemm if (TrustedUid > UID_MAX) 2433c2aa98e2SPeter Wemm { 2434065a643dSPeter Wemm syserr("readcf: option TrustedUser: uid value (%ld) > UID_MAX (%ld)", 2435065a643dSPeter Wemm TrustedUid, UID_MAX); 2436065a643dSPeter Wemm TrustedUid = 0; 2437c2aa98e2SPeter Wemm } 2438c2aa98e2SPeter Wemm #endif 2439c2aa98e2SPeter Wemm break; 2440c2aa98e2SPeter Wemm #endif 2441c2aa98e2SPeter Wemm 2442065a643dSPeter Wemm #if _FFR_MAX_MIME_HEADER_LENGTH 2443065a643dSPeter Wemm case O_MAXMIMEHDRLEN: 2444065a643dSPeter Wemm p = strchr(val, '/'); 2445065a643dSPeter Wemm if (p != NULL) 2446065a643dSPeter Wemm *p++ = '\0'; 2447065a643dSPeter Wemm MaxMimeHeaderLength = atoi(val); 2448065a643dSPeter Wemm if (p != NULL && *p != '\0') 2449065a643dSPeter Wemm MaxMimeFieldLength = atoi(p); 2450065a643dSPeter Wemm else 2451065a643dSPeter Wemm MaxMimeFieldLength = MaxMimeHeaderLength / 2; 2452065a643dSPeter Wemm 2453065a643dSPeter Wemm if (MaxMimeHeaderLength < 0) 2454065a643dSPeter Wemm MaxMimeHeaderLength = 0; 2455065a643dSPeter Wemm else if (MaxMimeHeaderLength < 128) 2456065a643dSPeter Wemm printf("Warning: MaxMimeHeaderLength: header length limit set lower than 128\n"); 2457065a643dSPeter Wemm 2458065a643dSPeter Wemm if (MaxMimeFieldLength < 0) 2459065a643dSPeter Wemm MaxMimeFieldLength = 0; 2460065a643dSPeter Wemm else if (MaxMimeFieldLength < 40) 2461065a643dSPeter Wemm printf("Warning: MaxMimeHeaderLength: field length limit set lower than 40\n"); 2462065a643dSPeter Wemm break; 2463065a643dSPeter Wemm #endif 2464065a643dSPeter Wemm 2465065a643dSPeter Wemm #if _FFR_CONTROL_SOCKET 2466065a643dSPeter Wemm case O_CONTROLSOCKET: 2467065a643dSPeter Wemm if (ControlSocketName != NULL) 2468065a643dSPeter Wemm free(ControlSocketName); 2469065a643dSPeter Wemm ControlSocketName = newstr(val); 2470065a643dSPeter Wemm break; 2471065a643dSPeter Wemm #endif 2472065a643dSPeter Wemm 24732e43090eSPeter Wemm #if _FFR_MAX_HEADERS_LENGTH 24742e43090eSPeter Wemm case O_MAXHDRSLEN: 24752e43090eSPeter Wemm MaxHeadersLength = atoi(val); 247625bab6e9SPeter Wemm 24772e43090eSPeter Wemm if (MaxHeadersLength > 0 && 24782e43090eSPeter Wemm MaxHeadersLength < (MAXHDRSLEN / 2)) 24792e43090eSPeter Wemm printf("Warning: MaxHeadersLength: headers length limit set lower than %d\n", MAXHDRSLEN); 248025bab6e9SPeter Wemm break; 248125bab6e9SPeter Wemm #endif 248225bab6e9SPeter Wemm 2483c2aa98e2SPeter Wemm default: 2484c2aa98e2SPeter Wemm if (tTd(37, 1)) 2485c2aa98e2SPeter Wemm { 2486c2aa98e2SPeter Wemm if (isascii(opt) && isprint(opt)) 2487c2aa98e2SPeter Wemm printf("Warning: option %c unknown\n", opt); 2488c2aa98e2SPeter Wemm else 2489c2aa98e2SPeter Wemm printf("Warning: option 0x%x unknown\n", opt); 2490c2aa98e2SPeter Wemm } 2491c2aa98e2SPeter Wemm break; 2492c2aa98e2SPeter Wemm } 2493c2aa98e2SPeter Wemm if (sticky) 2494c2aa98e2SPeter Wemm setbitn(opt, StickyOpt); 2495c2aa98e2SPeter Wemm } 2496c2aa98e2SPeter Wemm /* 2497c2aa98e2SPeter Wemm ** SETCLASS -- set a string into a class 2498c2aa98e2SPeter Wemm ** 2499c2aa98e2SPeter Wemm ** Parameters: 2500c2aa98e2SPeter Wemm ** class -- the class to put the string in. 2501c2aa98e2SPeter Wemm ** str -- the string to enter 2502c2aa98e2SPeter Wemm ** 2503c2aa98e2SPeter Wemm ** Returns: 2504c2aa98e2SPeter Wemm ** none. 2505c2aa98e2SPeter Wemm ** 2506c2aa98e2SPeter Wemm ** Side Effects: 2507c2aa98e2SPeter Wemm ** puts the word into the symbol table. 2508c2aa98e2SPeter Wemm */ 2509c2aa98e2SPeter Wemm 2510c2aa98e2SPeter Wemm void 2511c2aa98e2SPeter Wemm setclass(class, str) 2512c2aa98e2SPeter Wemm int class; 2513c2aa98e2SPeter Wemm char *str; 2514c2aa98e2SPeter Wemm { 2515c2aa98e2SPeter Wemm register STAB *s; 2516c2aa98e2SPeter Wemm 2517c2aa98e2SPeter Wemm if (tTd(37, 8)) 2518c2aa98e2SPeter Wemm printf("setclass(%s, %s)\n", macname(class), str); 2519c2aa98e2SPeter Wemm s = stab(str, ST_CLASS, ST_ENTER); 2520c2aa98e2SPeter Wemm setbitn(class, s->s_class); 2521c2aa98e2SPeter Wemm } 2522c2aa98e2SPeter Wemm /* 2523c2aa98e2SPeter Wemm ** MAKEMAPENTRY -- create a map entry 2524c2aa98e2SPeter Wemm ** 2525c2aa98e2SPeter Wemm ** Parameters: 2526c2aa98e2SPeter Wemm ** line -- the config file line 2527c2aa98e2SPeter Wemm ** 2528c2aa98e2SPeter Wemm ** Returns: 2529c2aa98e2SPeter Wemm ** A pointer to the map that has been created. 2530c2aa98e2SPeter Wemm ** NULL if there was a syntax error. 2531c2aa98e2SPeter Wemm ** 2532c2aa98e2SPeter Wemm ** Side Effects: 2533c2aa98e2SPeter Wemm ** Enters the map into the dictionary. 2534c2aa98e2SPeter Wemm */ 2535c2aa98e2SPeter Wemm 2536c2aa98e2SPeter Wemm MAP * 2537c2aa98e2SPeter Wemm makemapentry(line) 2538c2aa98e2SPeter Wemm char *line; 2539c2aa98e2SPeter Wemm { 2540c2aa98e2SPeter Wemm register char *p; 2541c2aa98e2SPeter Wemm char *mapname; 2542c2aa98e2SPeter Wemm char *classname; 2543c2aa98e2SPeter Wemm register STAB *s; 2544c2aa98e2SPeter Wemm STAB *class; 2545c2aa98e2SPeter Wemm 2546c2aa98e2SPeter Wemm for (p = line; isascii(*p) && isspace(*p); p++) 2547c2aa98e2SPeter Wemm continue; 2548c2aa98e2SPeter Wemm if (!(isascii(*p) && isalnum(*p))) 2549c2aa98e2SPeter Wemm { 2550c2aa98e2SPeter Wemm syserr("readcf: config K line: no map name"); 2551c2aa98e2SPeter Wemm return NULL; 2552c2aa98e2SPeter Wemm } 2553c2aa98e2SPeter Wemm 2554c2aa98e2SPeter Wemm mapname = p; 2555c2aa98e2SPeter Wemm while ((isascii(*++p) && isalnum(*p)) || *p == '_' || *p == '.') 2556c2aa98e2SPeter Wemm continue; 2557c2aa98e2SPeter Wemm if (*p != '\0') 2558c2aa98e2SPeter Wemm *p++ = '\0'; 2559c2aa98e2SPeter Wemm while (isascii(*p) && isspace(*p)) 2560c2aa98e2SPeter Wemm p++; 2561c2aa98e2SPeter Wemm if (!(isascii(*p) && isalnum(*p))) 2562c2aa98e2SPeter Wemm { 2563c2aa98e2SPeter Wemm syserr("readcf: config K line, map %s: no map class", mapname); 2564c2aa98e2SPeter Wemm return NULL; 2565c2aa98e2SPeter Wemm } 2566c2aa98e2SPeter Wemm classname = p; 2567c2aa98e2SPeter Wemm while (isascii(*++p) && isalnum(*p)) 2568c2aa98e2SPeter Wemm continue; 2569c2aa98e2SPeter Wemm if (*p != '\0') 2570c2aa98e2SPeter Wemm *p++ = '\0'; 2571c2aa98e2SPeter Wemm while (isascii(*p) && isspace(*p)) 2572c2aa98e2SPeter Wemm p++; 2573c2aa98e2SPeter Wemm 2574c2aa98e2SPeter Wemm /* look up the class */ 2575c2aa98e2SPeter Wemm class = stab(classname, ST_MAPCLASS, ST_FIND); 2576c2aa98e2SPeter Wemm if (class == NULL) 2577c2aa98e2SPeter Wemm { 2578c2aa98e2SPeter Wemm syserr("readcf: map %s: class %s not available", mapname, classname); 2579c2aa98e2SPeter Wemm return NULL; 2580c2aa98e2SPeter Wemm } 2581c2aa98e2SPeter Wemm 2582c2aa98e2SPeter Wemm /* enter the map */ 2583c2aa98e2SPeter Wemm s = stab(mapname, ST_MAP, ST_ENTER); 2584c2aa98e2SPeter Wemm s->s_map.map_class = &class->s_mapclass; 2585c2aa98e2SPeter Wemm s->s_map.map_mname = newstr(mapname); 2586c2aa98e2SPeter Wemm 2587c2aa98e2SPeter Wemm if (class->s_mapclass.map_parse(&s->s_map, p)) 2588c2aa98e2SPeter Wemm s->s_map.map_mflags |= MF_VALID; 2589c2aa98e2SPeter Wemm 2590c2aa98e2SPeter Wemm if (tTd(37, 5)) 2591c2aa98e2SPeter Wemm { 2592c2aa98e2SPeter Wemm printf("map %s, class %s, flags %lx, file %s,\n", 2593c2aa98e2SPeter Wemm s->s_map.map_mname, s->s_map.map_class->map_cname, 2594c2aa98e2SPeter Wemm s->s_map.map_mflags, 2595c2aa98e2SPeter Wemm s->s_map.map_file == NULL ? "(null)" : s->s_map.map_file); 2596c2aa98e2SPeter Wemm printf("\tapp %s, domain %s, rebuild %s\n", 2597c2aa98e2SPeter Wemm s->s_map.map_app == NULL ? "(null)" : s->s_map.map_app, 2598c2aa98e2SPeter Wemm s->s_map.map_domain == NULL ? "(null)" : s->s_map.map_domain, 2599c2aa98e2SPeter Wemm s->s_map.map_rebuild == NULL ? "(null)" : s->s_map.map_rebuild); 2600c2aa98e2SPeter Wemm } 2601c2aa98e2SPeter Wemm 2602c2aa98e2SPeter Wemm return &s->s_map; 2603c2aa98e2SPeter Wemm } 2604c2aa98e2SPeter Wemm /* 2605c2aa98e2SPeter Wemm ** STRTORWSET -- convert string to rewriting set number 2606c2aa98e2SPeter Wemm ** 2607c2aa98e2SPeter Wemm ** Parameters: 2608c2aa98e2SPeter Wemm ** p -- the pointer to the string to decode. 2609c2aa98e2SPeter Wemm ** endp -- if set, store the trailing delimiter here. 2610c2aa98e2SPeter Wemm ** stabmode -- ST_ENTER to create this entry, ST_FIND if 2611c2aa98e2SPeter Wemm ** it must already exist. 2612c2aa98e2SPeter Wemm ** 2613c2aa98e2SPeter Wemm ** Returns: 2614c2aa98e2SPeter Wemm ** The appropriate ruleset number. 2615c2aa98e2SPeter Wemm ** -1 if it is not valid (error already printed) 2616c2aa98e2SPeter Wemm */ 2617c2aa98e2SPeter Wemm 2618c2aa98e2SPeter Wemm int 2619c2aa98e2SPeter Wemm strtorwset(p, endp, stabmode) 2620c2aa98e2SPeter Wemm char *p; 2621c2aa98e2SPeter Wemm char **endp; 2622c2aa98e2SPeter Wemm int stabmode; 2623c2aa98e2SPeter Wemm { 2624c2aa98e2SPeter Wemm int ruleset; 2625c2aa98e2SPeter Wemm static int nextruleset = MAXRWSETS; 2626c2aa98e2SPeter Wemm 2627c2aa98e2SPeter Wemm while (isascii(*p) && isspace(*p)) 2628c2aa98e2SPeter Wemm p++; 2629c2aa98e2SPeter Wemm if (!isascii(*p)) 2630c2aa98e2SPeter Wemm { 2631c2aa98e2SPeter Wemm syserr("invalid ruleset name: \"%.20s\"", p); 2632c2aa98e2SPeter Wemm return -1; 2633c2aa98e2SPeter Wemm } 2634c2aa98e2SPeter Wemm if (isdigit(*p)) 2635c2aa98e2SPeter Wemm { 2636c2aa98e2SPeter Wemm ruleset = strtol(p, endp, 10); 2637c2aa98e2SPeter Wemm if (ruleset >= MAXRWSETS / 2 || ruleset < 0) 2638c2aa98e2SPeter Wemm { 2639c2aa98e2SPeter Wemm syserr("bad ruleset %d (%d max)", 2640c2aa98e2SPeter Wemm ruleset, MAXRWSETS / 2); 2641c2aa98e2SPeter Wemm ruleset = -1; 2642c2aa98e2SPeter Wemm } 2643c2aa98e2SPeter Wemm } 2644c2aa98e2SPeter Wemm else 2645c2aa98e2SPeter Wemm { 2646c2aa98e2SPeter Wemm STAB *s; 2647c2aa98e2SPeter Wemm char delim; 2648c2aa98e2SPeter Wemm char *q; 2649c2aa98e2SPeter Wemm 2650c2aa98e2SPeter Wemm q = p; 2651c2aa98e2SPeter Wemm while (*p != '\0' && isascii(*p) && 2652c2aa98e2SPeter Wemm (isalnum(*p) || *p == '_')) 2653c2aa98e2SPeter Wemm p++; 2654c2aa98e2SPeter Wemm if (q == p || !(isascii(*q) && isalpha(*q))) 2655c2aa98e2SPeter Wemm { 2656c2aa98e2SPeter Wemm /* no valid characters */ 2657c2aa98e2SPeter Wemm syserr("invalid ruleset name: \"%.20s\"", q); 2658c2aa98e2SPeter Wemm return -1; 2659c2aa98e2SPeter Wemm } 2660c2aa98e2SPeter Wemm while (isascii(*p) && isspace(*p)) 2661c2aa98e2SPeter Wemm *p++ = '\0'; 2662c2aa98e2SPeter Wemm delim = *p; 2663c2aa98e2SPeter Wemm if (delim != '\0') 2664c2aa98e2SPeter Wemm *p = '\0'; 2665c2aa98e2SPeter Wemm s = stab(q, ST_RULESET, stabmode); 2666c2aa98e2SPeter Wemm if (delim != '\0') 2667c2aa98e2SPeter Wemm *p = delim; 2668c2aa98e2SPeter Wemm 2669c2aa98e2SPeter Wemm if (s == NULL) 2670c2aa98e2SPeter Wemm return -1; 2671c2aa98e2SPeter Wemm 2672c2aa98e2SPeter Wemm if (stabmode == ST_ENTER && delim == '=') 2673c2aa98e2SPeter Wemm { 2674c2aa98e2SPeter Wemm while (isascii(*++p) && isspace(*p)) 2675c2aa98e2SPeter Wemm continue; 2676c2aa98e2SPeter Wemm if (!(isascii(*p) && isdigit(*p))) 2677c2aa98e2SPeter Wemm { 2678c2aa98e2SPeter Wemm syserr("bad ruleset definition \"%s\" (number required after `=')", q); 2679c2aa98e2SPeter Wemm ruleset = -1; 2680c2aa98e2SPeter Wemm } 2681c2aa98e2SPeter Wemm else 2682c2aa98e2SPeter Wemm { 2683c2aa98e2SPeter Wemm ruleset = strtol(p, endp, 10); 2684c2aa98e2SPeter Wemm if (ruleset >= MAXRWSETS / 2 || ruleset < 0) 2685c2aa98e2SPeter Wemm { 2686c2aa98e2SPeter Wemm syserr("bad ruleset number %d in \"%s\" (%d max)", 2687c2aa98e2SPeter Wemm ruleset, q, MAXRWSETS / 2); 2688c2aa98e2SPeter Wemm ruleset = -1; 2689c2aa98e2SPeter Wemm } 2690c2aa98e2SPeter Wemm } 2691c2aa98e2SPeter Wemm } 2692c2aa98e2SPeter Wemm else 2693c2aa98e2SPeter Wemm { 2694c2aa98e2SPeter Wemm if (endp != NULL) 2695c2aa98e2SPeter Wemm *endp = p; 2696c2aa98e2SPeter Wemm if (s->s_ruleset > 0) 2697c2aa98e2SPeter Wemm ruleset = s->s_ruleset; 2698c2aa98e2SPeter Wemm else if ((ruleset = --nextruleset) < MAXRWSETS / 2) 2699c2aa98e2SPeter Wemm { 2700c2aa98e2SPeter Wemm syserr("%s: too many named rulesets (%d max)", 2701c2aa98e2SPeter Wemm q, MAXRWSETS / 2); 2702c2aa98e2SPeter Wemm ruleset = -1; 2703c2aa98e2SPeter Wemm } 2704c2aa98e2SPeter Wemm } 2705c2aa98e2SPeter Wemm if (s->s_ruleset > 0 && ruleset >= 0 && ruleset != s->s_ruleset) 2706c2aa98e2SPeter Wemm { 2707c2aa98e2SPeter Wemm syserr("%s: ruleset changed value (old %d, new %d)", 2708c2aa98e2SPeter Wemm q, s->s_ruleset, ruleset); 2709c2aa98e2SPeter Wemm ruleset = s->s_ruleset; 2710c2aa98e2SPeter Wemm } 2711c2aa98e2SPeter Wemm else if (ruleset > 0) 2712c2aa98e2SPeter Wemm { 2713c2aa98e2SPeter Wemm s->s_ruleset = ruleset; 2714c2aa98e2SPeter Wemm } 2715c2aa98e2SPeter Wemm } 2716c2aa98e2SPeter Wemm return ruleset; 2717c2aa98e2SPeter Wemm } 2718c2aa98e2SPeter Wemm /* 2719c2aa98e2SPeter Wemm ** INITTIMEOUTS -- parse and set timeout values 2720c2aa98e2SPeter Wemm ** 2721c2aa98e2SPeter Wemm ** Parameters: 2722c2aa98e2SPeter Wemm ** val -- a pointer to the values. If NULL, do initial 2723c2aa98e2SPeter Wemm ** settings. 2724c2aa98e2SPeter Wemm ** 2725c2aa98e2SPeter Wemm ** Returns: 2726c2aa98e2SPeter Wemm ** none. 2727c2aa98e2SPeter Wemm ** 2728c2aa98e2SPeter Wemm ** Side Effects: 2729c2aa98e2SPeter Wemm ** Initializes the TimeOuts structure 2730c2aa98e2SPeter Wemm */ 2731c2aa98e2SPeter Wemm 2732c2aa98e2SPeter Wemm #define SECONDS 2733c2aa98e2SPeter Wemm #define MINUTES * 60 2734c2aa98e2SPeter Wemm #define HOUR * 3600 2735c2aa98e2SPeter Wemm 2736c2aa98e2SPeter Wemm void 2737c2aa98e2SPeter Wemm inittimeouts(val) 2738c2aa98e2SPeter Wemm register char *val; 2739c2aa98e2SPeter Wemm { 2740c2aa98e2SPeter Wemm register char *p; 2741c2aa98e2SPeter Wemm extern time_t convtime __P((char *, char)); 2742c2aa98e2SPeter Wemm 2743c2aa98e2SPeter Wemm if (tTd(37, 2)) 2744c2aa98e2SPeter Wemm printf("inittimeouts(%s)\n", val == NULL ? "<NULL>" : val); 2745c2aa98e2SPeter Wemm if (val == NULL) 2746c2aa98e2SPeter Wemm { 2747c2aa98e2SPeter Wemm TimeOuts.to_connect = (time_t) 0 SECONDS; 2748c2aa98e2SPeter Wemm TimeOuts.to_initial = (time_t) 5 MINUTES; 2749c2aa98e2SPeter Wemm TimeOuts.to_helo = (time_t) 5 MINUTES; 2750c2aa98e2SPeter Wemm TimeOuts.to_mail = (time_t) 10 MINUTES; 2751c2aa98e2SPeter Wemm TimeOuts.to_rcpt = (time_t) 1 HOUR; 2752c2aa98e2SPeter Wemm TimeOuts.to_datainit = (time_t) 5 MINUTES; 2753c2aa98e2SPeter Wemm TimeOuts.to_datablock = (time_t) 1 HOUR; 2754c2aa98e2SPeter Wemm TimeOuts.to_datafinal = (time_t) 1 HOUR; 2755c2aa98e2SPeter Wemm TimeOuts.to_rset = (time_t) 5 MINUTES; 2756c2aa98e2SPeter Wemm TimeOuts.to_quit = (time_t) 2 MINUTES; 2757c2aa98e2SPeter Wemm TimeOuts.to_nextcommand = (time_t) 1 HOUR; 2758c2aa98e2SPeter Wemm TimeOuts.to_miscshort = (time_t) 2 MINUTES; 2759c2aa98e2SPeter Wemm #if IDENTPROTO 2760c2aa98e2SPeter Wemm TimeOuts.to_ident = (time_t) 30 SECONDS; 2761c2aa98e2SPeter Wemm #else 2762c2aa98e2SPeter Wemm TimeOuts.to_ident = (time_t) 0 SECONDS; 2763c2aa98e2SPeter Wemm #endif 2764c2aa98e2SPeter Wemm TimeOuts.to_fileopen = (time_t) 60 SECONDS; 2765c2aa98e2SPeter Wemm if (tTd(37, 5)) 2766c2aa98e2SPeter Wemm { 2767c2aa98e2SPeter Wemm printf("Timeouts:\n"); 2768c2aa98e2SPeter Wemm printf(" connect = %ld\n", (long)TimeOuts.to_connect); 2769c2aa98e2SPeter Wemm printf(" initial = %ld\n", (long)TimeOuts.to_initial); 2770c2aa98e2SPeter Wemm printf(" helo = %ld\n", (long)TimeOuts.to_helo); 2771c2aa98e2SPeter Wemm printf(" mail = %ld\n", (long)TimeOuts.to_mail); 2772c2aa98e2SPeter Wemm printf(" rcpt = %ld\n", (long)TimeOuts.to_rcpt); 2773c2aa98e2SPeter Wemm printf(" datainit = %ld\n", (long)TimeOuts.to_datainit); 2774c2aa98e2SPeter Wemm printf(" datablock = %ld\n", (long)TimeOuts.to_datablock); 2775c2aa98e2SPeter Wemm printf(" datafinal = %ld\n", (long)TimeOuts.to_datafinal); 2776c2aa98e2SPeter Wemm printf(" rset = %ld\n", (long)TimeOuts.to_rset); 2777c2aa98e2SPeter Wemm printf(" quit = %ld\n", (long)TimeOuts.to_quit); 2778c2aa98e2SPeter Wemm printf(" nextcommand = %ld\n", (long)TimeOuts.to_nextcommand); 2779c2aa98e2SPeter Wemm printf(" miscshort = %ld\n", (long)TimeOuts.to_miscshort); 2780c2aa98e2SPeter Wemm printf(" ident = %ld\n", (long)TimeOuts.to_ident); 2781c2aa98e2SPeter Wemm printf(" fileopen = %ld\n", (long)TimeOuts.to_fileopen); 2782c2aa98e2SPeter Wemm } 2783c2aa98e2SPeter Wemm return; 2784c2aa98e2SPeter Wemm } 2785c2aa98e2SPeter Wemm 2786c2aa98e2SPeter Wemm for (;; val = p) 2787c2aa98e2SPeter Wemm { 2788c2aa98e2SPeter Wemm while (isascii(*val) && isspace(*val)) 2789c2aa98e2SPeter Wemm val++; 2790c2aa98e2SPeter Wemm if (*val == '\0') 2791c2aa98e2SPeter Wemm break; 2792c2aa98e2SPeter Wemm for (p = val; *p != '\0' && *p != ','; p++) 2793c2aa98e2SPeter Wemm continue; 2794c2aa98e2SPeter Wemm if (*p != '\0') 2795c2aa98e2SPeter Wemm *p++ = '\0'; 2796c2aa98e2SPeter Wemm 2797c2aa98e2SPeter Wemm if (isascii(*val) && isdigit(*val)) 2798c2aa98e2SPeter Wemm { 2799c2aa98e2SPeter Wemm /* old syntax -- set everything */ 2800c2aa98e2SPeter Wemm TimeOuts.to_mail = convtime(val, 'm'); 2801c2aa98e2SPeter Wemm TimeOuts.to_rcpt = TimeOuts.to_mail; 2802c2aa98e2SPeter Wemm TimeOuts.to_datainit = TimeOuts.to_mail; 2803c2aa98e2SPeter Wemm TimeOuts.to_datablock = TimeOuts.to_mail; 2804c2aa98e2SPeter Wemm TimeOuts.to_datafinal = TimeOuts.to_mail; 2805c2aa98e2SPeter Wemm TimeOuts.to_nextcommand = TimeOuts.to_mail; 2806c2aa98e2SPeter Wemm continue; 2807c2aa98e2SPeter Wemm } 2808c2aa98e2SPeter Wemm else 2809c2aa98e2SPeter Wemm { 2810c2aa98e2SPeter Wemm register char *q = strchr(val, ':'); 2811c2aa98e2SPeter Wemm 2812c2aa98e2SPeter Wemm if (q == NULL && (q = strchr(val, '=')) == NULL) 2813c2aa98e2SPeter Wemm { 2814c2aa98e2SPeter Wemm /* syntax error */ 2815c2aa98e2SPeter Wemm continue; 2816c2aa98e2SPeter Wemm } 2817c2aa98e2SPeter Wemm *q++ = '\0'; 2818c2aa98e2SPeter Wemm settimeout(val, q); 2819c2aa98e2SPeter Wemm } 2820c2aa98e2SPeter Wemm } 2821c2aa98e2SPeter Wemm } 2822c2aa98e2SPeter Wemm /* 2823c2aa98e2SPeter Wemm ** SETTIMEOUT -- set an individual timeout 2824c2aa98e2SPeter Wemm ** 2825c2aa98e2SPeter Wemm ** Parameters: 2826c2aa98e2SPeter Wemm ** name -- the name of the timeout. 2827c2aa98e2SPeter Wemm ** val -- the value of the timeout. 2828c2aa98e2SPeter Wemm ** 2829c2aa98e2SPeter Wemm ** Returns: 2830c2aa98e2SPeter Wemm ** none. 2831c2aa98e2SPeter Wemm */ 2832c2aa98e2SPeter Wemm 2833c2aa98e2SPeter Wemm void 2834c2aa98e2SPeter Wemm settimeout(name, val) 2835c2aa98e2SPeter Wemm char *name; 2836c2aa98e2SPeter Wemm char *val; 2837c2aa98e2SPeter Wemm { 2838c2aa98e2SPeter Wemm register char *p; 2839c2aa98e2SPeter Wemm time_t to; 2840c2aa98e2SPeter Wemm extern time_t convtime __P((char *, char)); 2841c2aa98e2SPeter Wemm 2842c2aa98e2SPeter Wemm if (tTd(37, 2)) 2843c2aa98e2SPeter Wemm printf("settimeout(%s = %s)\n", name, val); 2844c2aa98e2SPeter Wemm 2845c2aa98e2SPeter Wemm to = convtime(val, 'm'); 2846c2aa98e2SPeter Wemm p = strchr(name, '.'); 2847c2aa98e2SPeter Wemm if (p != NULL) 2848c2aa98e2SPeter Wemm *p++ = '\0'; 2849c2aa98e2SPeter Wemm 2850c2aa98e2SPeter Wemm if (strcasecmp(name, "initial") == 0) 2851c2aa98e2SPeter Wemm TimeOuts.to_initial = to; 2852c2aa98e2SPeter Wemm else if (strcasecmp(name, "mail") == 0) 2853c2aa98e2SPeter Wemm TimeOuts.to_mail = to; 2854c2aa98e2SPeter Wemm else if (strcasecmp(name, "rcpt") == 0) 2855c2aa98e2SPeter Wemm TimeOuts.to_rcpt = to; 2856c2aa98e2SPeter Wemm else if (strcasecmp(name, "datainit") == 0) 2857c2aa98e2SPeter Wemm TimeOuts.to_datainit = to; 2858c2aa98e2SPeter Wemm else if (strcasecmp(name, "datablock") == 0) 2859c2aa98e2SPeter Wemm TimeOuts.to_datablock = to; 2860c2aa98e2SPeter Wemm else if (strcasecmp(name, "datafinal") == 0) 2861c2aa98e2SPeter Wemm TimeOuts.to_datafinal = to; 2862c2aa98e2SPeter Wemm else if (strcasecmp(name, "command") == 0) 2863c2aa98e2SPeter Wemm TimeOuts.to_nextcommand = to; 2864c2aa98e2SPeter Wemm else if (strcasecmp(name, "rset") == 0) 2865c2aa98e2SPeter Wemm TimeOuts.to_rset = to; 2866c2aa98e2SPeter Wemm else if (strcasecmp(name, "helo") == 0) 2867c2aa98e2SPeter Wemm TimeOuts.to_helo = to; 2868c2aa98e2SPeter Wemm else if (strcasecmp(name, "quit") == 0) 2869c2aa98e2SPeter Wemm TimeOuts.to_quit = to; 2870c2aa98e2SPeter Wemm else if (strcasecmp(name, "misc") == 0) 2871c2aa98e2SPeter Wemm TimeOuts.to_miscshort = to; 2872c2aa98e2SPeter Wemm else if (strcasecmp(name, "ident") == 0) 2873c2aa98e2SPeter Wemm TimeOuts.to_ident = to; 2874c2aa98e2SPeter Wemm else if (strcasecmp(name, "fileopen") == 0) 2875c2aa98e2SPeter Wemm TimeOuts.to_fileopen = to; 2876c2aa98e2SPeter Wemm else if (strcasecmp(name, "connect") == 0) 2877c2aa98e2SPeter Wemm TimeOuts.to_connect = to; 2878c2aa98e2SPeter Wemm else if (strcasecmp(name, "iconnect") == 0) 2879c2aa98e2SPeter Wemm TimeOuts.to_iconnect = to; 2880c2aa98e2SPeter Wemm else if (strcasecmp(name, "queuewarn") == 0) 2881c2aa98e2SPeter Wemm { 2882c2aa98e2SPeter Wemm to = convtime(val, 'h'); 2883c2aa98e2SPeter Wemm if (p == NULL || strcmp(p, "*") == 0) 2884c2aa98e2SPeter Wemm { 2885c2aa98e2SPeter Wemm TimeOuts.to_q_warning[TOC_NORMAL] = to; 2886c2aa98e2SPeter Wemm TimeOuts.to_q_warning[TOC_URGENT] = to; 2887c2aa98e2SPeter Wemm TimeOuts.to_q_warning[TOC_NONURGENT] = to; 2888c2aa98e2SPeter Wemm } 2889c2aa98e2SPeter Wemm else if (strcasecmp(p, "normal") == 0) 2890c2aa98e2SPeter Wemm TimeOuts.to_q_warning[TOC_NORMAL] = to; 2891c2aa98e2SPeter Wemm else if (strcasecmp(p, "urgent") == 0) 2892c2aa98e2SPeter Wemm TimeOuts.to_q_warning[TOC_URGENT] = to; 2893c2aa98e2SPeter Wemm else if (strcasecmp(p, "non-urgent") == 0) 2894c2aa98e2SPeter Wemm TimeOuts.to_q_warning[TOC_NONURGENT] = to; 2895c2aa98e2SPeter Wemm else 2896c2aa98e2SPeter Wemm syserr("settimeout: invalid queuewarn subtimeout %s", p); 2897c2aa98e2SPeter Wemm } 2898c2aa98e2SPeter Wemm else if (strcasecmp(name, "queuereturn") == 0) 2899c2aa98e2SPeter Wemm { 2900c2aa98e2SPeter Wemm to = convtime(val, 'd'); 2901c2aa98e2SPeter Wemm if (p == NULL || strcmp(p, "*") == 0) 2902c2aa98e2SPeter Wemm { 2903c2aa98e2SPeter Wemm TimeOuts.to_q_return[TOC_NORMAL] = to; 2904c2aa98e2SPeter Wemm TimeOuts.to_q_return[TOC_URGENT] = to; 2905c2aa98e2SPeter Wemm TimeOuts.to_q_return[TOC_NONURGENT] = to; 2906c2aa98e2SPeter Wemm } 2907c2aa98e2SPeter Wemm else if (strcasecmp(p, "normal") == 0) 2908c2aa98e2SPeter Wemm TimeOuts.to_q_return[TOC_NORMAL] = to; 2909c2aa98e2SPeter Wemm else if (strcasecmp(p, "urgent") == 0) 2910c2aa98e2SPeter Wemm TimeOuts.to_q_return[TOC_URGENT] = to; 2911c2aa98e2SPeter Wemm else if (strcasecmp(p, "non-urgent") == 0) 2912c2aa98e2SPeter Wemm TimeOuts.to_q_return[TOC_NONURGENT] = to; 2913c2aa98e2SPeter Wemm else 2914c2aa98e2SPeter Wemm syserr("settimeout: invalid queuereturn subtimeout %s", p); 2915c2aa98e2SPeter Wemm } 2916c2aa98e2SPeter Wemm else if (strcasecmp(name, "hoststatus") == 0) 2917c2aa98e2SPeter Wemm MciInfoTimeout = convtime(val, 'm'); 2918c2aa98e2SPeter Wemm else 2919c2aa98e2SPeter Wemm syserr("settimeout: invalid timeout %s", name); 2920c2aa98e2SPeter Wemm } 2921