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: #ifndef lint
  12: static char SccsId[] = "@(#)readcf.c	5.10 (Berkeley) 1/11/86";
  13: #endif not lint
  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:     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: 
 662: # ifdef DEBUG
 663:     if (tTd(37, 1))
 664:         printf("setoption %c=%s", opt, val);
 665: # endif DEBUG
 666: 
 667:     /*
 668: 	**  See if this option is preset for us.
 669: 	*/
 670: 
 671:     if (bitnset(opt, StickyOpt))
 672:     {
 673: # ifdef DEBUG
 674:         if (tTd(37, 1))
 675:             printf(" (ignored)\n");
 676: # endif DEBUG
 677:         return;
 678:     }
 679: 
 680:     /*
 681: 	**  Check to see if this option can be specified by this user.
 682: 	*/
 683: 
 684:     if (!safe && getruid() == 0)
 685:         safe = TRUE;
 686:     if (!safe && index("deiLmorsv", opt) == NULL)
 687:     {
 688: # ifdef DEBUG
 689:         if (tTd(37, 1))
 690:             printf(" (unsafe)");
 691: # endif DEBUG
 692:         if (getruid() != geteuid())
 693:         {
 694:             printf("(Resetting uid)\n");
 695:             (void) setgid(getgid());
 696:             (void) setuid(getuid());
 697:         }
 698:     }
 699: #ifdef DEBUG
 700:     else if (tTd(37, 1))
 701:         printf("\n");
 702: #endif DEBUG
 703: 
 704:     switch (opt)
 705:     {
 706:       case 'A':     /* set default alias file */
 707:         if (val[0] == '\0')
 708:             AliasFile = "aliases";
 709:         else
 710:             AliasFile = newstr(val);
 711:         break;
 712: 
 713:       case 'a':     /* look N minutes for "@:@" in alias file */
 714:         if (val[0] == '\0')
 715:             SafeAlias = 5;
 716:         else
 717:             SafeAlias = atoi(val);
 718:         break;
 719: 
 720:       case 'B':     /* substitution for blank character */
 721:         SpaceSub = val[0];
 722:         if (SpaceSub == '\0')
 723:             SpaceSub = ' ';
 724:         break;
 725: 
 726:       case 'c':     /* don't connect to "expensive" mailers */
 727:         NoConnect = atobool(val);
 728:         break;
 729: 
 730:       case 'C':     /* checkpoint after N connections */
 731:         CheckPointLimit = atoi(val);
 732:         break;
 733: 
 734:       case 'd':     /* delivery mode */
 735:         switch (*val)
 736:         {
 737:           case '\0':
 738:             SendMode = SM_DELIVER;
 739:             break;
 740: 
 741:           case SM_QUEUE:    /* queue only */
 742: #ifndef QUEUE
 743:             syserr("need QUEUE to set -odqueue");
 744: #endif QUEUE
 745:             /* fall through..... */
 746: 
 747:           case SM_DELIVER:  /* do everything */
 748:           case SM_FORK:     /* fork after verification */
 749:             SendMode = *val;
 750:             break;
 751: 
 752:           default:
 753:             syserr("Unknown delivery mode %c", *val);
 754:             exit(EX_USAGE);
 755:         }
 756:         break;
 757: 
 758:       case 'D':     /* rebuild alias database as needed */
 759:         AutoRebuild = atobool(val);
 760:         break;
 761: 
 762:       case 'e':     /* set error processing mode */
 763:         switch (*val)
 764:         {
 765:           case EM_QUIET:    /* be silent about it */
 766:           case EM_MAIL:     /* mail back */
 767:           case EM_BERKNET:  /* do berknet error processing */
 768:           case EM_WRITE:    /* write back (or mail) */
 769:             HoldErrs = TRUE;
 770:             /* fall through... */
 771: 
 772:           case EM_PRINT:    /* print errors normally (default) */
 773:             ErrorMode = *val;
 774:             break;
 775:         }
 776:         break;
 777: 
 778:       case 'F':     /* file mode */
 779:         FileMode = atooct(val) & 0777;
 780:         break;
 781: 
 782:       case 'f':     /* save Unix-style From lines on front */
 783:         SaveFrom = atobool(val);
 784:         break;
 785: 
 786:       case 'g':     /* default gid */
 787:         DefGid = atoi(val);
 788:         break;
 789: 
 790:       case 'H':     /* help file */
 791:         if (val[0] == '\0')
 792:             HelpFile = "sendmail.hf";
 793:         else
 794:             HelpFile = newstr(val);
 795:         break;
 796: 
 797:       case 'i':     /* ignore dot lines in message */
 798:         IgnrDot = atobool(val);
 799:         break;
 800: 
 801:       case 'L':     /* log level */
 802:         LogLevel = atoi(val);
 803:         break;
 804: 
 805:       case 'M':     /* define macro */
 806:         define(val[0], newstr(&val[1]), CurEnv);
 807:         sticky = FALSE;
 808:         break;
 809: 
 810:       case 'm':     /* send to me too */
 811:         MeToo = atobool(val);
 812:         break;
 813: 
 814:       case 'n':     /* validate RHS in newaliases */
 815:         CheckAliases = atobool(val);
 816:         break;
 817: 
 818: # ifdef DAEMON
 819:       case 'N':     /* home (local?) network name */
 820:         NetName = newstr(val);
 821:         break;
 822: # endif DAEMON
 823: 
 824:       case 'o':     /* assume old style headers */
 825:         if (atobool(val))
 826:             CurEnv->e_flags |= EF_OLDSTYLE;
 827:         else
 828:             CurEnv->e_flags &= ~EF_OLDSTYLE;
 829:         break;
 830: 
 831:       case 'P':     /* postmaster copy address for returned mail */
 832:         PostMasterCopy = newstr(val);
 833:         break;
 834: 
 835:       case 'q':     /* slope of queue only function */
 836:         QueueFactor = atoi(val);
 837:         break;
 838: 
 839:       case 'Q':     /* queue directory */
 840:         if (val[0] == '\0')
 841:             QueueDir = "mqueue";
 842:         else
 843:             QueueDir = newstr(val);
 844:         break;
 845: 
 846:       case 'r':     /* read timeout */
 847:         ReadTimeout = convtime(val);
 848:         break;
 849: 
 850:       case 'S':     /* status file */
 851:         if (val[0] == '\0')
 852:             StatFile = "sendmail.st";
 853:         else
 854:             StatFile = newstr(val);
 855:         break;
 856: 
 857:       case 's':     /* be super safe, even if expensive */
 858:         SuperSafe = atobool(val);
 859:         break;
 860: 
 861:       case 'T':     /* queue timeout */
 862:         TimeOut = convtime(val);
 863:         break;
 864: 
 865:       case 't':     /* time zone name */
 866: # ifdef V6
 867:         StdTimezone = newstr(val);
 868:         DstTimezone = index(StdTimeZone, ',');
 869:         if (DstTimezone == NULL)
 870:             syserr("bad time zone spec");
 871:         else
 872:             *DstTimezone++ = '\0';
 873: # endif V6
 874:         break;
 875: 
 876:       case 'u':     /* set default uid */
 877:         DefUid = atoi(val);
 878:         break;
 879: 
 880:       case 'v':     /* run in verbose mode */
 881:         Verbose = atobool(val);
 882:         break;
 883: 
 884: # ifdef SMTP
 885: # ifdef WIZ
 886:       case 'W':     /* set the wizards password */
 887:         WizWord = newstr(val);
 888:         break;
 889: # endif WIZ
 890: # endif SMTP
 891: 
 892:       case 'x':     /* load avg at which to auto-queue msgs */
 893:         QueueLA = atoi(val);
 894:         break;
 895: 
 896:       case 'X':     /* load avg at which to auto-reject connections */
 897:         RefuseLA = atoi(val);
 898:         break;
 899: 
 900:       case 'y':     /* work recipient factor */
 901:         WkRecipFact = atoi(val);
 902:         break;
 903: 
 904:       case 'Y':     /* fork jobs during queue runs */
 905:         ForkQueueRuns = atobool(val);
 906:         break;
 907: 
 908:       case 'z':     /* work message class factor */
 909:         WkClassFact = atoi(val);
 910:         break;
 911: 
 912:       case 'Z':     /* work time factor */
 913:         WkTimeFact = atoi(val);
 914:         break;
 915: 
 916:       default:
 917:         break;
 918:     }
 919:     if (sticky)
 920:         setbitn(opt, StickyOpt);
 921:     return;
 922: }
 923: /*
 924: **  SETCLASS -- set a word into a class
 925: **
 926: **	Parameters:
 927: **		class -- the class to put the word in.
 928: **		word -- the word to enter
 929: **
 930: **	Returns:
 931: **		none.
 932: **
 933: **	Side Effects:
 934: **		puts the word into the symbol table.
 935: */
 936: 
 937: setclass(class, word)
 938:     int class;
 939:     char *word;
 940: {
 941:     register STAB *s;
 942: 
 943:     s = stab(word, ST_CLASS, ST_ENTER);
 944:     setbitn(class, s->s_class);
 945: }

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
setclass defined in line 937; 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: 1986-01-11
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 2359
Valid CSS Valid XHTML 1.0 Strict