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

Defined functions

fileclass defined in line 298; used 1 times
makeargv defined in line 557; used 2 times
makemailer defined in line 377; used 1 times
munchstring defined in line 491; used 4 times
printrules defined in line 600; used 1 times
readcf defined in line 54; used 1 times
setclass defined in line 933; used 3 times
setoption defined in line 649; used 6 times
toomany defined in line 275; used 2 times

Defined variables

SccsId defined in line 12; never used
StickyOpt defined in line 641; used 2 times
Last modified: 1995-03-08
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 2613
Valid CSS Valid XHTML 1.0 Strict