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

Defined functions

fileclass defined in line 274; used 1 times
makeargv defined in line 507; used 2 times
makemailer defined in line 324; used 1 times
munchstring defined in line 441; used 4 times
printrules defined in line 550; used 1 times
setclass defined in line 814; used 3 times
setoption defined in line 592; used 6 times
toomany defined in line 251; used 2 times

Defined variables

StickyOpt defined in line 589; used 2 times
Last modified: 1983-12-09
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 1439
Valid CSS Valid XHTML 1.0 Strict