1: /*
   2:  * Copyright (c) 1988 Regents of the University of California.
   3:  * All rights reserved.
   4:  *
   5:  * Redistribution and use in source and binary forms are permitted
   6:  * provided that this notice is preserved and that due credit is given
   7:  * to the University of California at Berkeley. The name of the University
   8:  * may not be used to endorse or promote products derived from this
   9:  * software without specific prior written permission. This software
  10:  * is provided ``as is'' without express or implied warranty.
  11:  *
  12:  *  Sendmail
  13:  *  Copyright (c) 1983  Eric P. Allman
  14:  *  Berkeley, California
  15:  */
  16: 
  17: #if !defined(lint) && !defined(NOSCCS)
  18: static char sccsid[] = "@(#)readcf.c	5.12 (Berkeley) 4/1/88";
  19: #endif /* not lint */
  20: 
  21: # include "sendmail.h"
  22: 
  23: /*
  24: **  READCF -- read control file.
  25: **
  26: **	This routine reads the control file and builds the internal
  27: **	form.
  28: **
  29: **	The file is formatted as a sequence of lines, each taken
  30: **	atomically.  The first character of each line describes how
  31: **	the line is to be interpreted.  The lines are:
  32: **		Dxval		Define macro x to have value val.
  33: **		Cxword		Put word into class x.
  34: **		Fxfile [fmt]	Read file for lines to put into
  35: **				class x.  Use scanf string 'fmt'
  36: **				or "%s" if not present.  Fmt should
  37: **				only produce one string-valued result.
  38: **		Hname: value	Define header with field-name 'name'
  39: **				and value as specified; this will be
  40: **				macro expanded immediately before
  41: **				use.
  42: **		Sn		Use rewriting set n.
  43: **		Rlhs rhs	Rewrite addresses that match lhs to
  44: **				be rhs.
  45: **		Mn arg=val...	Define mailer.  n is the internal name.
  46: **				Args specify mailer parameters.
  47: **		Oxvalue		Set option x to value.
  48: **		Pname=value	Set precedence name to value.
  49: **
  50: **	Parameters:
  51: **		cfname -- control file name.
  52: **
  53: **	Returns:
  54: **		none.
  55: **
  56: **	Side Effects:
  57: **		Builds several internal tables.
  58: */
  59: 
  60: readcf(cfname)
  61:     char *cfname;
  62: {
  63:     FILE *cf;
  64:     int ruleset = 0;
  65:     char *q;
  66:     char **pv;
  67:     struct rewrite *rwp = NULL;
  68:     char buf[MAXLINE];
  69:     register char *p;
  70:     extern char **prescan();
  71:     extern char **copyplist();
  72:     char exbuf[MAXLINE];
  73:     char pvpbuf[PSBUFSIZE];
  74:     extern char *fgetfolded();
  75:     extern char *munchstring();
  76: 
  77:     cf = fopen(cfname, "r");
  78:     if (cf == NULL)
  79:     {
  80:         syserr("cannot open %s", cfname);
  81:         exit(EX_OSFILE);
  82:     }
  83: 
  84:     FileName = cfname;
  85:     LineNumber = 0;
  86:     while (fgetfolded(buf, sizeof buf, cf) != NULL)
  87:     {
  88:         /* map $ into \001 (ASCII SOH) for macro expansion */
  89:         for (p = buf; *p != '\0'; p++)
  90:         {
  91:             if (*p != '$')
  92:                 continue;
  93: 
  94:             if (p[1] == '$')
  95:             {
  96:                 /* actual dollar sign.... */
  97:                 (void) strcpy(p, p + 1);
  98:                 continue;
  99:             }
 100: 
 101:             /* convert to macro expansion character */
 102:             *p = '\001';
 103:         }
 104: 
 105:         /* interpret this line */
 106:         switch (buf[0])
 107:         {
 108:           case '\0':
 109:           case '#':     /* comment */
 110:             break;
 111: 
 112:           case 'R':     /* rewriting rule */
 113:             for (p = &buf[1]; *p != '\0' && *p != '\t'; p++)
 114:                 continue;
 115: 
 116:             if (*p == '\0')
 117:             {
 118:                 syserr("invalid rewrite line \"%s\"", buf);
 119:                 break;
 120:             }
 121: 
 122:             /* allocate space for the rule header */
 123:             if (rwp == NULL)
 124:             {
 125:                 RewriteRules[ruleset] = rwp =
 126:                     (struct rewrite *) xalloc(sizeof *rwp);
 127:             }
 128:             else
 129:             {
 130:                 rwp->r_next = (struct rewrite *) xalloc(sizeof *rwp);
 131:                 rwp = rwp->r_next;
 132:             }
 133:             rwp->r_next = NULL;
 134: 
 135:             /* expand and save the LHS */
 136:             *p = '\0';
 137:             expand(&buf[1], exbuf, &exbuf[sizeof exbuf], CurEnv);
 138:             rwp->r_lhs = prescan(exbuf, '\t', pvpbuf);
 139:             if (rwp->r_lhs != NULL)
 140:                 rwp->r_lhs = copyplist(rwp->r_lhs, TRUE);
 141: 
 142:             /* expand and save the RHS */
 143:             while (*++p == '\t')
 144:                 continue;
 145:             q = p;
 146:             while (*p != '\0' && *p != '\t')
 147:                 p++;
 148:             *p = '\0';
 149:             expand(q, exbuf, &exbuf[sizeof exbuf], CurEnv);
 150:             rwp->r_rhs = prescan(exbuf, '\t', pvpbuf);
 151:             if (rwp->r_rhs != NULL)
 152:                 rwp->r_rhs = copyplist(rwp->r_rhs, TRUE);
 153:             break;
 154: 
 155:           case 'S':     /* select rewriting set */
 156:             ruleset = atoi(&buf[1]);
 157:             if (ruleset >= MAXRWSETS || ruleset < 0)
 158:             {
 159:                 syserr("bad ruleset %d (%d max)", ruleset, MAXRWSETS);
 160:                 ruleset = 0;
 161:             }
 162:             rwp = NULL;
 163:             break;
 164: 
 165:           case 'D':     /* macro definition */
 166:             define(buf[1], newstr(munchstring(&buf[2])), CurEnv);
 167:             break;
 168: 
 169:           case 'H':     /* required header line */
 170:             (void) chompheader(&buf[1], TRUE);
 171:             break;
 172: 
 173:           case 'C':     /* word class */
 174:           case 'F':     /* word class from file */
 175:             /* read list of words from argument or file */
 176:             if (buf[0] == 'F')
 177:             {
 178:                 /* read from file */
 179:                 for (p = &buf[2]; *p != '\0' && !isspace(*p); p++)
 180:                     continue;
 181:                 if (*p == '\0')
 182:                     p = "%s";
 183:                 else
 184:                 {
 185:                     *p = '\0';
 186:                     while (isspace(*++p))
 187:                         continue;
 188:                 }
 189:                 fileclass(buf[1], &buf[2], p);
 190:                 break;
 191:             }
 192: 
 193:             /* scan the list of words and set class for all */
 194:             for (p = &buf[2]; *p != '\0'; )
 195:             {
 196:                 register char *wd;
 197:                 char delim;
 198: 
 199:                 while (*p != '\0' && isspace(*p))
 200:                     p++;
 201:                 wd = p;
 202:                 while (*p != '\0' && !isspace(*p))
 203:                     p++;
 204:                 delim = *p;
 205:                 *p = '\0';
 206:                 if (wd[0] != '\0')
 207:                     setclass(buf[1], wd);
 208:                 *p = delim;
 209:             }
 210:             break;
 211: 
 212:           case 'M':     /* define mailer */
 213:             makemailer(&buf[1]);
 214:             break;
 215: 
 216:           case 'O':     /* set option */
 217:             setoption(buf[1], &buf[2], TRUE, FALSE);
 218:             break;
 219: 
 220:           case 'P':     /* set precedence */
 221:             if (NumPriorities >= MAXPRIORITIES)
 222:             {
 223:                 toomany('P', MAXPRIORITIES);
 224:                 break;
 225:             }
 226:             for (p = &buf[1]; *p != '\0' && *p != '=' && *p != '\t'; p++)
 227:                 continue;
 228:             if (*p == '\0')
 229:                 goto badline;
 230:             *p = '\0';
 231:             Priorities[NumPriorities].pri_name = newstr(&buf[1]);
 232:             Priorities[NumPriorities].pri_val = atoi(++p);
 233:             NumPriorities++;
 234:             break;
 235: 
 236:           case 'T':     /* trusted user(s) */
 237:             p = &buf[1];
 238:             while (*p != '\0')
 239:             {
 240:                 while (isspace(*p))
 241:                     p++;
 242:                 q = p;
 243:                 while (*p != '\0' && !isspace(*p))
 244:                     p++;
 245:                 if (*p != '\0')
 246:                     *p++ = '\0';
 247:                 if (*q == '\0')
 248:                     continue;
 249:                 for (pv = TrustedUsers; *pv != NULL; pv++)
 250:                     continue;
 251:                 if (pv >= &TrustedUsers[MAXTRUST])
 252:                 {
 253:                     toomany('T', MAXTRUST);
 254:                     break;
 255:                 }
 256:                 *pv = newstr(q);
 257:             }
 258:             break;
 259: 
 260:           default:
 261:           badline:
 262:             syserr("unknown control line \"%s\"", buf);
 263:         }
 264:     }
 265:     FileName = NULL;
 266: }
 267: /*
 268: **  TOOMANY -- signal too many of some option
 269: **
 270: **	Parameters:
 271: **		id -- the id of the error line
 272: **		maxcnt -- the maximum possible values
 273: **
 274: **	Returns:
 275: **		none.
 276: **
 277: **	Side Effects:
 278: **		gives a syserr.
 279: */
 280: 
 281: toomany(id, maxcnt)
 282:     char id;
 283:     int maxcnt;
 284: {
 285:     syserr("too many %c lines, %d max", id, maxcnt);
 286: }
 287: /*
 288: **  FILECLASS -- read members of a class from a file
 289: **
 290: **	Parameters:
 291: **		class -- class to define.
 292: **		filename -- name of file to read.
 293: **		fmt -- scanf string to use for match.
 294: **
 295: **	Returns:
 296: **		none
 297: **
 298: **	Side Effects:
 299: **
 300: **		puts all lines in filename that match a scanf into
 301: **			the named class.
 302: */
 303: 
 304: fileclass(class, filename, fmt)
 305:     int class;
 306:     char *filename;
 307:     char *fmt;
 308: {
 309:     FILE *f;
 310:     char buf[MAXLINE];
 311: 
 312:     f = fopen(filename, "r");
 313:     if (f == NULL)
 314:     {
 315:         syserr("cannot open %s", filename);
 316:         return;
 317:     }
 318: 
 319:     while (fgets(buf, sizeof buf, f) != NULL)
 320:     {
 321:         register STAB *s;
 322:         register char *p;
 323: # ifdef SCANF
 324:         char wordbuf[MAXNAME+1];
 325: 
 326:         if (sscanf(buf, fmt, wordbuf) != 1)
 327:             continue;
 328:         p = wordbuf;
 329: # else SCANF
 330:         p = buf;
 331: # endif SCANF
 332: 
 333:         /*
 334: 		**  Break up the match into words.
 335: 		*/
 336: 
 337:         while (*p != '\0')
 338:         {
 339:             register char *q;
 340: 
 341:             /* strip leading spaces */
 342:             while (isspace(*p))
 343:                 p++;
 344:             if (*p == '\0')
 345:                 break;
 346: 
 347:             /* find the end of the word */
 348:             q = p;
 349:             while (*p != '\0' && !isspace(*p))
 350:                 p++;
 351:             if (*p != '\0')
 352:                 *p++ = '\0';
 353: 
 354:             /* enter the word in the symbol table */
 355:             s = stab(q, ST_CLASS, ST_ENTER);
 356:             setbitn(class, s->s_class);
 357:         }
 358:     }
 359: 
 360:     (void) fclose(f);
 361: }
 362: /*
 363: **  MAKEMAILER -- define a new mailer.
 364: **
 365: **	Parameters:
 366: **		line -- description of mailer.  This is in labeled
 367: **			fields.  The fields are:
 368: **			   P -- the path to the mailer
 369: **			   F -- the flags associated with the mailer
 370: **			   A -- the argv for this mailer
 371: **			   S -- the sender rewriting set
 372: **			   R -- the recipient rewriting set
 373: **			   E -- the eol string
 374: **			The first word is the canonical name of the mailer.
 375: **
 376: **	Returns:
 377: **		none.
 378: **
 379: **	Side Effects:
 380: **		enters the mailer into the mailer table.
 381: */
 382: 
 383: makemailer(line)
 384:     char *line;
 385: {
 386:     register char *p;
 387:     register struct mailer *m;
 388:     register STAB *s;
 389:     int i;
 390:     char fcode;
 391:     extern int NextMailer;
 392:     extern char **makeargv();
 393:     extern char *munchstring();
 394:     extern char *DelimChar;
 395:     extern long atol();
 396: 
 397:     /* allocate a mailer and set up defaults */
 398:     m = (struct mailer *) xalloc(sizeof *m);
 399:     bzero((char *) m, sizeof *m);
 400:     m->m_mno = NextMailer;
 401:     m->m_eol = "\n";
 402: 
 403:     /* collect the mailer name */
 404:     for (p = line; *p != '\0' && *p != ',' && !isspace(*p); p++)
 405:         continue;
 406:     if (*p != '\0')
 407:         *p++ = '\0';
 408:     m->m_name = newstr(line);
 409: 
 410:     /* now scan through and assign info from the fields */
 411:     while (*p != '\0')
 412:     {
 413:         while (*p != '\0' && (*p == ',' || isspace(*p)))
 414:             p++;
 415: 
 416:         /* p now points to field code */
 417:         fcode = *p;
 418:         while (*p != '\0' && *p != '=' && *p != ',')
 419:             p++;
 420:         if (*p++ != '=')
 421:         {
 422:             syserr("`=' expected");
 423:             return;
 424:         }
 425:         while (isspace(*p))
 426:             p++;
 427: 
 428:         /* p now points to the field body */
 429:         p = munchstring(p);
 430: 
 431:         /* install the field into the mailer struct */
 432:         switch (fcode)
 433:         {
 434:           case 'P':     /* pathname */
 435:             m->m_mailer = newstr(p);
 436:             break;
 437: 
 438:           case 'F':     /* flags */
 439:             for (; *p != '\0'; p++)
 440:                 setbitn(*p, m->m_flags);
 441:             break;
 442: 
 443:           case 'S':     /* sender rewriting ruleset */
 444:           case 'R':     /* recipient rewriting ruleset */
 445:             i = atoi(p);
 446:             if (i < 0 || i >= MAXRWSETS)
 447:             {
 448:                 syserr("invalid rewrite set, %d max", MAXRWSETS);
 449:                 return;
 450:             }
 451:             if (fcode == 'S')
 452:                 m->m_s_rwset = i;
 453:             else
 454:                 m->m_r_rwset = i;
 455:             break;
 456: 
 457:           case 'E':     /* end of line string */
 458:             m->m_eol = newstr(p);
 459:             break;
 460: 
 461:           case 'A':     /* argument vector */
 462:             m->m_argv = makeargv(p);
 463:             break;
 464: 
 465:           case 'M':     /* maximum message size */
 466:             m->m_maxsize = atol(p);
 467:             break;
 468:         }
 469: 
 470:         p = DelimChar;
 471:     }
 472: 
 473:     /* now store the mailer away */
 474:     if (NextMailer >= MAXMAILERS)
 475:     {
 476:         syserr("too many mailers defined (%d max)", MAXMAILERS);
 477:         return;
 478:     }
 479:     Mailer[NextMailer++] = m;
 480:     s = stab(m->m_name, ST_MAILER, ST_ENTER);
 481:     s->s_mailer = m;
 482: }
 483: /*
 484: **  MUNCHSTRING -- translate a string into internal form.
 485: **
 486: **	Parameters:
 487: **		p -- the string to munch.
 488: **
 489: **	Returns:
 490: **		the munched string.
 491: **
 492: **	Side Effects:
 493: **		Sets "DelimChar" to point to the string that caused us
 494: **		to stop.
 495: */
 496: 
 497: char *
 498: munchstring(p)
 499:     register char *p;
 500: {
 501:     register char *q;
 502:     bool backslash = FALSE;
 503:     bool quotemode = FALSE;
 504:     static char buf[MAXLINE];
 505:     extern char *DelimChar;
 506: 
 507:     for (q = buf; *p != '\0'; p++)
 508:     {
 509:         if (backslash)
 510:         {
 511:             /* everything is roughly literal */
 512:             backslash = FALSE;
 513:             switch (*p)
 514:             {
 515:               case 'r':     /* carriage return */
 516:                 *q++ = '\r';
 517:                 continue;
 518: 
 519:               case 'n':     /* newline */
 520:                 *q++ = '\n';
 521:                 continue;
 522: 
 523:               case 'f':     /* form feed */
 524:                 *q++ = '\f';
 525:                 continue;
 526: 
 527:               case 'b':     /* backspace */
 528:                 *q++ = '\b';
 529:                 continue;
 530:             }
 531:             *q++ = *p;
 532:         }
 533:         else
 534:         {
 535:             if (*p == '\\')
 536:                 backslash = TRUE;
 537:             else if (*p == '"')
 538:                 quotemode = !quotemode;
 539:             else if (quotemode || *p != ',')
 540:                 *q++ = *p;
 541:             else
 542:                 break;
 543:         }
 544:     }
 545: 
 546:     DelimChar = p;
 547:     *q++ = '\0';
 548:     return (buf);
 549: }
 550: /*
 551: **  MAKEARGV -- break up a string into words
 552: **
 553: **	Parameters:
 554: **		p -- the string to break up.
 555: **
 556: **	Returns:
 557: **		a char **argv (dynamically allocated)
 558: **
 559: **	Side Effects:
 560: **		munges p.
 561: */
 562: 
 563: char **
 564: makeargv(p)
 565:     register char *p;
 566: {
 567:     char *q;
 568:     int i;
 569:     char **avp;
 570:     char *argv[MAXPV + 1];
 571: 
 572:     /* take apart the words */
 573:     i = 0;
 574:     while (*p != '\0' && i < MAXPV)
 575:     {
 576:         q = p;
 577:         while (*p != '\0' && !isspace(*p))
 578:             p++;
 579:         while (isspace(*p))
 580:             *p++ = '\0';
 581:         argv[i++] = newstr(q);
 582:     }
 583:     argv[i++] = NULL;
 584: 
 585:     /* now make a copy of the argv */
 586:     avp = (char **) xalloc(sizeof *avp * i);
 587:     bcopy((char *) argv, (char *) avp, sizeof *avp * i);
 588: 
 589:     return (avp);
 590: }
 591: /*
 592: **  PRINTRULES -- print rewrite rules (for debugging)
 593: **
 594: **	Parameters:
 595: **		none.
 596: **
 597: **	Returns:
 598: **		none.
 599: **
 600: **	Side Effects:
 601: **		prints rewrite rules.
 602: */
 603: 
 604: # ifdef DEBUG
 605: 
 606: printrules()
 607: {
 608:     register struct rewrite *rwp;
 609:     register int ruleset;
 610: 
 611:     for (ruleset = 0; ruleset < 10; ruleset++)
 612:     {
 613:         if (RewriteRules[ruleset] == NULL)
 614:             continue;
 615:         printf("\n----Rule Set %d:", ruleset);
 616: 
 617:         for (rwp = RewriteRules[ruleset]; rwp != NULL; rwp = rwp->r_next)
 618:         {
 619:             printf("\nLHS:");
 620:             printav(rwp->r_lhs);
 621:             printf("RHS:");
 622:             printav(rwp->r_rhs);
 623:         }
 624:     }
 625: }
 626: 
 627: # endif DEBUG
 628: /*
 629: **  SETOPTION -- set global processing option
 630: **
 631: **	Parameters:
 632: **		opt -- option name.
 633: **		val -- option value (as a text string).
 634: **		safe -- set if this came from a configuration file.
 635: **			Some options (if set from the command line) will
 636: **			reset the user id to avoid security problems.
 637: **		sticky -- if set, don't let other setoptions override
 638: **			this value.
 639: **
 640: **	Returns:
 641: **		none.
 642: **
 643: **	Side Effects:
 644: **		Sets options as implied by the arguments.
 645: */
 646: 
 647: static BITMAP   StickyOpt;      /* set if option is stuck */
 648: extern char *NetName;       /* name of home (local) network */
 649: # ifdef SMTP
 650: # ifdef WIZ
 651: extern char *WizWord;       /* the stored wizard password */
 652: # endif WIZ
 653: # endif SMTP
 654: 
 655: setoption(opt, val, safe, sticky)
 656:     char opt;
 657:     char *val;
 658:     bool safe;
 659:     bool sticky;
 660: {
 661:     extern bool atobool();
 662:     extern time_t convtime();
 663:     extern int QueueLA;
 664:     extern int RefuseLA;
 665:     extern bool trusteduser();
 666:     extern char *username();
 667: 
 668: # ifdef DEBUG
 669:     if (tTd(37, 1))
 670:         printf("setoption %c=%s", opt, val);
 671: # endif DEBUG
 672: 
 673:     /*
 674: 	**  See if this option is preset for us.
 675: 	*/
 676: 
 677:     if (bitnset(opt, StickyOpt))
 678:     {
 679: # ifdef DEBUG
 680:         if (tTd(37, 1))
 681:             printf(" (ignored)\n");
 682: # endif DEBUG
 683:         return;
 684:     }
 685: 
 686:     /*
 687: 	**  Check to see if this option can be specified by this user.
 688: 	*/
 689: 
 690:     if (!safe && getruid() == 0)
 691:         safe = TRUE;
 692:     if (!safe && index("deiLmorsv", opt) == NULL)
 693:     {
 694: # ifdef DEBUG
 695:         if (tTd(37, 1))
 696:             printf(" (unsafe)");
 697: # endif DEBUG
 698:         if (getruid() != geteuid())
 699:         {
 700:             printf("(Resetting uid)\n");
 701:             (void) setgid(getgid());
 702:             (void) setuid(getuid());
 703:         }
 704:     }
 705: #ifdef DEBUG
 706:     else if (tTd(37, 1))
 707:         printf("\n");
 708: #endif DEBUG
 709: 
 710:     switch (opt)
 711:     {
 712:       case 'A':     /* set default alias file */
 713:         if (val[0] == '\0')
 714:             AliasFile = "aliases";
 715:         else
 716:             AliasFile = newstr(val);
 717:         break;
 718: 
 719:       case 'a':     /* look N minutes for "@:@" in alias file */
 720:         if (val[0] == '\0')
 721:             SafeAlias = 5;
 722:         else
 723:             SafeAlias = atoi(val);
 724:         break;
 725: 
 726:       case 'B':     /* substitution for blank character */
 727:         SpaceSub = val[0];
 728:         if (SpaceSub == '\0')
 729:             SpaceSub = ' ';
 730:         break;
 731: 
 732:       case 'c':     /* don't connect to "expensive" mailers */
 733:         NoConnect = atobool(val);
 734:         break;
 735: 
 736:       case 'C':     /* checkpoint after N connections */
 737:         CheckPointLimit = atoi(val);
 738:         break;
 739: 
 740:       case 'd':     /* delivery mode */
 741:         switch (*val)
 742:         {
 743:           case '\0':
 744:             SendMode = SM_DELIVER;
 745:             break;
 746: 
 747:           case SM_QUEUE:    /* queue only */
 748: #ifndef QUEUE
 749:             syserr("need QUEUE to set -odqueue");
 750: #endif QUEUE
 751:             /* fall through..... */
 752: 
 753:           case SM_DELIVER:  /* do everything */
 754:           case SM_FORK:     /* fork after verification */
 755:             SendMode = *val;
 756:             break;
 757: 
 758:           default:
 759:             syserr("Unknown delivery mode %c", *val);
 760:             exit(EX_USAGE);
 761:         }
 762:         break;
 763: 
 764:       case 'D':     /* rebuild alias database as needed */
 765:         AutoRebuild = atobool(val);
 766:         break;
 767: 
 768:       case 'e':     /* set error processing mode */
 769:         switch (*val)
 770:         {
 771:           case EM_QUIET:    /* be silent about it */
 772:           case EM_MAIL:     /* mail back */
 773:           case EM_BERKNET:  /* do berknet error processing */
 774:           case EM_WRITE:    /* write back (or mail) */
 775:             HoldErrs = TRUE;
 776:             /* fall through... */
 777: 
 778:           case EM_PRINT:    /* print errors normally (default) */
 779:             ErrorMode = *val;
 780:             break;
 781:         }
 782:         break;
 783: 
 784:       case 'F':     /* file mode */
 785:         FileMode = atooct(val) & 0777;
 786:         break;
 787: 
 788:       case 'f':     /* save Unix-style From lines on front */
 789:         SaveFrom = atobool(val);
 790:         break;
 791: 
 792:       case 'g':     /* default gid */
 793:         DefGid = atoi(val);
 794:         break;
 795: 
 796:       case 'H':     /* help file */
 797:         if (val[0] == '\0')
 798:             HelpFile = "sendmail.hf";
 799:         else
 800:             HelpFile = newstr(val);
 801:         break;
 802: 
 803:       case 'i':     /* ignore dot lines in message */
 804:         IgnrDot = atobool(val);
 805:         break;
 806: 
 807:       case 'L':     /* log level */
 808:         LogLevel = atoi(val);
 809:         break;
 810: 
 811:       case 'M':     /* define macro */
 812:         define(val[0], newstr(&val[1]), CurEnv);
 813:         sticky = FALSE;
 814:         break;
 815: 
 816:       case 'm':     /* send to me too */
 817:         MeToo = atobool(val);
 818:         break;
 819: 
 820:       case 'n':     /* validate RHS in newaliases */
 821:         CheckAliases = atobool(val);
 822:         break;
 823: 
 824: # ifdef DAEMON
 825:       case 'N':     /* home (local?) network name */
 826:         NetName = newstr(val);
 827:         break;
 828: # endif DAEMON
 829: 
 830:       case 'o':     /* assume old style headers */
 831:         if (atobool(val))
 832:             CurEnv->e_flags |= EF_OLDSTYLE;
 833:         else
 834:             CurEnv->e_flags &= ~EF_OLDSTYLE;
 835:         break;
 836: 
 837:       case 'P':     /* postmaster copy address for returned mail */
 838:         PostMasterCopy = newstr(val);
 839:         break;
 840: 
 841:       case 'q':     /* slope of queue only function */
 842:         QueueFactor = atoi(val);
 843:         break;
 844: 
 845:       case 'Q':     /* queue directory */
 846:         if (val[0] == '\0')
 847:             QueueDir = "mqueue";
 848:         else
 849:             QueueDir = newstr(val);
 850:         break;
 851: 
 852:       case 'r':     /* read timeout */
 853:         ReadTimeout = convtime(val);
 854:         break;
 855: 
 856:       case 'S':     /* status file */
 857:         if (val[0] == '\0')
 858:             StatFile = "sendmail.st";
 859:         else
 860:             StatFile = newstr(val);
 861:         break;
 862: 
 863:       case 's':     /* be super safe, even if expensive */
 864:         SuperSafe = atobool(val);
 865:         break;
 866: 
 867:       case 'T':     /* queue timeout */
 868:         TimeOut = convtime(val);
 869:         /*FALLTHROUGH*/
 870: 
 871:       case 't':     /* time zone name */
 872:         break;
 873: 
 874:       case 'u':     /* set default uid */
 875:         DefUid = atoi(val);
 876:         break;
 877: 
 878:       case 'v':     /* run in verbose mode */
 879:         Verbose = atobool(val);
 880:         break;
 881: 
 882: # ifdef SMTP
 883: # ifdef WIZ
 884:       case 'W':     /* set the wizards password */
 885:         WizWord = newstr(val);
 886:         break;
 887: # endif WIZ
 888: # endif SMTP
 889: 
 890:       case 'x':     /* load avg at which to auto-queue msgs */
 891:         QueueLA = atoi(val);
 892:         break;
 893: 
 894:       case 'X':     /* load avg at which to auto-reject connections */
 895:         RefuseLA = atoi(val);
 896:         break;
 897: 
 898:       case 'y':     /* work recipient factor */
 899:         WkRecipFact = atoi(val);
 900:         break;
 901: 
 902:       case 'Y':     /* fork jobs during queue runs */
 903:         ForkQueueRuns = atobool(val);
 904:         break;
 905: 
 906:       case 'z':     /* work message class factor */
 907:         WkClassFact = atoi(val);
 908:         break;
 909: 
 910:       case 'Z':     /* work time factor */
 911:         WkTimeFact = atoi(val);
 912:         break;
 913: 
 914:       default:
 915:         break;
 916:     }
 917:     if (sticky)
 918:         setbitn(opt, StickyOpt);
 919:     return;
 920: }
 921: /*
 922: **  SETCLASS -- set a word into a class
 923: **
 924: **	Parameters:
 925: **		class -- the class to put the word in.
 926: **		word -- the word to enter
 927: **
 928: **	Returns:
 929: **		none.
 930: **
 931: **	Side Effects:
 932: **		puts the word into the symbol table.
 933: */
 934: 
 935: setclass(class, word)
 936:     int class;
 937:     char *word;
 938: {
 939:     register STAB *s;
 940: 
 941:     s = stab(word, ST_CLASS, ST_ENTER);
 942:     setbitn(class, s->s_class);
 943: }

Defined functions

fileclass defined in line 304; used 1 times
makeargv defined in line 563; used 2 times
makemailer defined in line 383; used 1 times
munchstring defined in line 497; used 4 times
printrules defined in line 606; used 1 times
readcf defined in line 60; used 1 times
setclass defined in line 935; used 3 times
setoption defined in line 655; used 6 times
toomany defined in line 281; used 2 times

Defined variables

StickyOpt defined in line 647; used 2 times
sccsid defined in line 18; never used
Last modified: 1988-09-14
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 4515
Valid CSS Valid XHTML 1.0 Strict