home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1992 March / Source_Code_CD-ROM_Walnut_Creek_March_1992.iso / usenet / compsrcs / unix / volume03 / sndml.mds < prev    next >
Encoding:
Internet Message Format  |  1988-09-11  |  53.0 KB

  1. From: Bruce Israel <talcott!mimsy.umd.edu:gymble!israel>
  2. Subject: translation tables in sendmail
  3. Newsgroups: mod.sources
  4. Approved: jpn@panda.UUCP
  5.  
  6. Mod.sources:  Volume 3, Issue 31
  7. Submitted by: Bruce Israel <talcott!mimsy.umd.edu:gymble!israel>
  8.  
  9.  
  10. Here are my modifications to sendmail that I announced recently.  I
  11. am posting these due to the number of requests.  These modifications
  12. allow translations to be used in the sendmail.cf file, such as
  13. pathalias information and other stuff.  Run the shar in a clean
  14. directory and then read the README.  Enjoy.
  15.  
  16. Bruce Israel
  17.  
  18. University of Maryland, Computer Science Dept.
  19. {rlgvax,seismo}!umcp-cs!israel (Usenet)    israel@Maryland (Arpanet)
  20.  
  21. : Run this shell script with "sh" not "csh"
  22. PATH=:/bin:/usr/bin:/usr/ucb
  23. export PATH
  24. all=FALSE
  25. if [ x$1 = x-a ]; then
  26.     all=TRUE
  27. fi
  28. /bin/echo 'Extracting 4.2diffs'
  29. sed 's/^X//' <<'//go.sysin dd *' >4.2diffs
  30. diff -c main.c.old main.c
  31. *** /usr/4.2/src/usr.lib/sendmail/src/main.c    Sun Sep 25 21:06:10 1983
  32. --- /usr/israel/sendmail/src/main.c    Wed Mar  6 15:45:26 1985
  33. ***************
  34. *** 695,700 ****
  35. --- 695,707 ----
  36.       '*', MATCHZANY,    '+', MATCHANY,    '-', MATCHONE,    '=', MATCHCLASS,
  37.       '~', MATCHNCLASS,
  38.   
  39. + #ifdef ROUTING    /* ******************************** */
  40. +     /* for RHS translation table */
  41. +     '&', EQUIVREPL,
  42. + #endif ROUTING    /* ******************************** */
  43.       /* these are RHS metasymbols */
  44.       '#', CANONNET,    '@', CANONHOST,    ':', CANONUSER,    '>', CALLSUBR,
  45.   
  46. ***************
  47. *** 808,813 ****
  48. --- 815,822 ----
  49.       union frz fhdr;
  50.       extern char edata;
  51.       extern char Version[];
  52. +      extern char **environ;
  53. +      char    **envsave;
  54.   
  55.       if (freezefile == NULL)
  56.           return (FALSE);
  57. ***************
  58. *** 835,840 ****
  59. --- 844,855 ----
  60.           (void) close(f);
  61.           return (FALSE);
  62.       }
  63. +  /**
  64. +   **  Arrrrg!  Since the pointer to the environment is in BSS, and our
  65. +   **  bss get's blasted over when the freeze file is read in, we need to
  66. +   **  save and restore the environ pointer for getenv()
  67. +   **/
  68. +      envsave = environ;        /* save pointer to environment */
  69.   
  70.       /* now read in the freeze file */
  71.       if (read(f, (char *) &edata, fhdr.frzinfo.frzbrk - &edata) !=
  72. ***************
  73. *** 844,849 ****
  74. --- 859,866 ----
  75.           write(2, "Cannot read freeze file\n", 24);
  76.           _exit(EX_SOFTWARE);
  77.       }
  78. +      environ = envsave;
  79.   
  80.       (void) close(f);
  81.       return (TRUE);
  82. diff -c parseaddr.c.old parseaddr.c
  83. *** /usr/4.2/src/usr.lib/sendmail/src/parseaddr.c    Mon Jul 25 23:20:46 1983
  84. --- /usr/israel/sendmail/src/parseaddr.c    Thu Oct 31 17:45:31 1985
  85. ***************
  86. *** 2,7 ****
  87. --- 2,9 ----
  88.   
  89.   SCCSID(@(#)parseaddr.c    4.1        7/25/83);
  90.   
  91. + char **copyplist();
  92.   /*
  93.   **  PARSEADDR -- Parse an address
  94.   **
  95. ***************
  96. *** 204,214 ****
  97. --- 206,241 ----
  98.   
  99.   char    *DelimChar;        /* set to point to the delimiter */
  100.   
  101. + #ifdef ROUTING    /* ******************************** */
  102. + char **prescan1();
  103. + #endif ROUTING    /* ******************************** */
  104.   char **
  105.   prescan(addr, delim)
  106.       char *addr;
  107.       char delim;
  108.   {
  109. +     static char buf[MAXNAME+MAXATOM];
  110. +     static char *av[MAXATOM+1];
  111. + #ifdef ROUTING    /* ******************************** */
  112. +     return(prescan1(addr,delim,buf,av,sizeof buf));
  113. + }
  114. + char **
  115. + prescan1(addr,delim,buf,av,bufsize)
  116. +     char *addr;
  117. +     char delim;
  118. +     char buf[];
  119. +     char *av[];
  120. +     int  bufsize;
  121. + {
  122. + #endif ROUTING    /* ******************************** */
  123.       register char *p;
  124.       register char *q;
  125.       register int c;
  126. ***************
  127. *** 219,226 ****
  128.       char *tok;
  129.       int state;
  130.       int newstate;
  131. -     static char buf[MAXNAME+MAXATOM];
  132. -     static char *av[MAXATOM+1];
  133.   
  134.       q = buf;
  135.       bslashmode = FALSE;
  136. --- 246,251 ----
  137. ***************
  138. *** 249,255 ****
  139.               if (c != NOCHAR)
  140.               {
  141.                   /* squirrel it away */
  142. !                 if (q >= &buf[sizeof buf - 5])
  143.                   {
  144.                       usrerr("Address too long");
  145.                       DelimChar = p;
  146. --- 274,280 ----
  147.               if (c != NOCHAR)
  148.               {
  149.                   /* squirrel it away */
  150. !                 if (q >= &buf[bufsize - 5])
  151.                   {
  152.                       usrerr("Address too long");
  153.                       DelimChar = p;
  154. ***************
  155. *** 396,401 ****
  156. --- 421,429 ----
  157.       }
  158.       if (c == MATCHCLASS || c == MATCHREPL || c == MATCHNCLASS)
  159.           return (ONE);
  160. + #ifdef ROUTING    /* ******************************** */
  161. +     if (c == EQUIVREPL) return (ONE);
  162. + #endif ROUTING    /* ******************************** */
  163.       if (c == '"')
  164.           return (QST);
  165.       if (!isascii(c))
  166. ***************
  167. *** 442,447 ****
  168. --- 470,478 ----
  169.   {
  170.       char    **first;    /* first token matched */
  171.       char    **last;        /* last token matched */
  172. + #ifdef ROUTING    /* ******************************** */
  173. +     char    *equiv;        /* equivalence name for match */
  174. + #endif ROUTING    /* ******************************** */
  175.   };
  176.   
  177.   # define MAXMATCH    9    /* max params per rewrite */
  178. ***************
  179. *** 528,533 ****
  180. --- 559,571 ----
  181.                   else if (*rp == MATCHNCLASS)
  182.                       goto backup;
  183.   
  184. + #ifdef ROUTING    /* ******************************** */
  185. +                 mlp -> equiv = getequiv(rp[1],s);
  186. + #endif ROUTING    /* ******************************** */
  187.                   /* explicit fall-through */
  188.   
  189.                 case MATCHONE:
  190. ***************
  191. *** 536,541 ****
  192. --- 574,582 ----
  193.                   mlp->first = avp;
  194.                   mlp->last = avp++;
  195.                   mlp++;
  196. + #ifdef ROUTING    /* ******************************** */
  197. +                 mlp -> equiv = NULL;
  198. + #endif ROUTING    /* ******************************** */
  199.                   break;
  200.   
  201.                 case MATCHZANY:
  202. ***************
  203. *** 543,548 ****
  204. --- 584,592 ----
  205.                   mlp->first = avp;
  206.                   mlp->last = avp - 1;
  207.                   mlp++;
  208. + #ifdef ROUTING    /* ******************************** */
  209. +                 mlp -> equiv = NULL;
  210. + #endif ROUTING    /* ******************************** */
  211.                   break;
  212.   
  213.                 default:
  214. ***************
  215. *** 576,581 ****
  216. --- 620,628 ----
  217.                   {
  218.                       /* back out binding */
  219.                       mlp--;
  220. + #ifdef ROUTING    /* ******************************** */
  221. +                     mlp -> equiv = NULL;
  222. + #endif ROUTING    /* ******************************** */
  223.                   }
  224.               }
  225.   
  226. ***************
  227. *** 630,636 ****
  228.               register char **pp;
  229.   
  230.               rp = *rvp;
  231. !             if (*rp != MATCHREPL)
  232.               {
  233.                   if (avp >= &npvp[MAXATOM])
  234.                   {
  235. --- 677,687 ----
  236.               register char **pp;
  237.   
  238.               rp = *rvp;
  239. !             if (*rp != MATCHREPL
  240. ! #ifdef ROUTING    /* ******************************** */
  241. !              && *rp != EQUIVREPL
  242. ! #endif ROUTING    /* ******************************** */
  243. !                         )
  244.               {
  245.                   if (avp >= &npvp[MAXATOM])
  246.                   {
  247. ***************
  248. *** 641,651 ****
  249. --- 692,722 ----
  250.                   continue;
  251.               }
  252.   
  253. + #ifdef ROUTING    /* ******************************** */
  254. +             /* if the $& is not followed by a digit, put the
  255. +                '&' on the output string. */
  256. +             if (*rp == EQUIVREPL && (rp[1] < '1' || rp[1] > '9'))
  257. +             {
  258. +                 *avp++ = "&";
  259. +                 continue;
  260. +             }
  261. + #endif ROUTING    /* ******************************** */
  262.               /* substitute from LHS */
  263.               m = &mlist[rp[1] - '1'];
  264.   # ifdef DEBUG
  265.               if (tTd(21, 15))
  266.               {
  267. + #ifdef ROUTING    /* ******************************** */
  268. +                 if (*rp == EQUIVREPL) {
  269. +                     printf("$&%c:%x=\"%s\"\n",
  270. +                     rp[1], *m->equiv, *m->equiv);
  271. +                 }
  272. +                 else {
  273. + #endif ROUTING    /* ******************************** */
  274.                   printf("$%c:", rp[1]);
  275.                   pp = m->first;
  276.                   while (pp <= m->last)
  277. ***************
  278. *** 655,662 ****
  279.                       printf("%s\"", *pp++);
  280.                   }
  281.                   printf("\n");
  282. !             }
  283.   # endif DEBUG
  284.               pp = m->first;
  285.               while (pp <= m->last)
  286.               {
  287. --- 726,763 ----
  288.                       printf("%s\"", *pp++);
  289.                   }
  290.                   printf("\n");
  291. ! #ifdef ROUTING    /* ******************************** */
  292. !                 }
  293. ! #endif ROUTING    /* ******************************** */
  294. !             };
  295.   # endif DEBUG
  296. + #ifdef ROUTING    /* ******************************** */
  297. +               if (*rp == EQUIVREPL) {
  298. +                 char buf[1024];
  299. +             char *av[MAXATOM+1];
  300. +             char *Dchar = DelimChar; /* save! */
  301. +     
  302. +             pp = copyplist(prescan1(m -> equiv,
  303. +                 '\0',buf,av,sizeof buf),TRUE);
  304. +             /* restore saved version, recursive */
  305. +             DelimChar = Dchar;
  306. +             while (*pp)
  307. +             {
  308. +                 if (avp >= &npvp[MAXATOM])
  309. +                 {
  310. +                 syserr("rewrite: expansion too long");
  311. +                 return;
  312. +                 }
  313. +                 *avp++ = *pp++;
  314. +             }
  315. +               }
  316. +               else
  317. +               {
  318. + #endif ROUTING    /* ******************************** */
  319.               pp = m->first;
  320.               while (pp <= m->last)
  321.               {
  322. ***************
  323. *** 667,672 ****
  324. --- 768,776 ----
  325.                   }
  326.                   *avp++ = *pp++;
  327.               }
  328. + #ifdef ROUTING    /* ******************************** */
  329. +               }
  330. + #endif ROUTING    /* ******************************** */
  331.           }
  332.           *avp++ = NULL;
  333.           if (**npvp == CALLSUBR)
  334. diff -c readcf.c.old readcf.c
  335. *** /usr/4.2/src/usr.lib/sendmail/src/readcf.c    Sun Sep 25 21:06:11 1983
  336. --- /usr/israel/sendmail/src/readcf.c    Fri Feb  1 17:59:14 1985
  337. ***************
  338. *** 110,119 ****
  339.                   rwp->r_lhs = copyplist(rwp->r_lhs, TRUE);
  340.   
  341.               /* expand and save the RHS */
  342. !             while (*++p == '\t')
  343.                   continue;
  344.               q = p;
  345. !             while (*p != '\0' && *p != '\t')
  346.                   p++;
  347.               *p = '\0';
  348.               expand(q, exbuf, &exbuf[sizeof exbuf], CurEnv);
  349. --- 110,119 ----
  350.                   rwp->r_lhs = copyplist(rwp->r_lhs, TRUE);
  351.   
  352.               /* expand and save the RHS */
  353. !             while (*++p == '\t' || *p == ' ')
  354.                   continue;
  355.               q = p;
  356. !             while (*p != '\0' && *p != '\t' && *p != ' ')
  357.                   p++;
  358.               *p = '\0';
  359.               expand(q, exbuf, &exbuf[sizeof exbuf], CurEnv);
  360. ***************
  361. *** 140,165 ****
  362.               (void) chompheader(&buf[1], TRUE);
  363.               break;
  364.   
  365. -           case 'C':        /* word class */
  366.             case 'F':        /* word class from file */
  367. !             /* read list of words from argument or file */
  368. !             if (buf[0] == 'F')
  369.               {
  370. !                 /* read from file */
  371. !                 for (p = &buf[2]; *p != '\0' && !isspace(*p); p++)
  372. !                     continue;
  373. !                 if (*p == '\0')
  374. !                     p = "%s";
  375. !                 else
  376. !                 {
  377. !                     *p = '\0';
  378. !                     while (isspace(*++p))
  379. !                         continue;
  380. !                 }
  381. !                 fileclass(buf[1], &buf[2], p);
  382. !                 break;
  383.               }
  384.   
  385.               /* scan the list of words and set class for all */
  386.               for (p = &buf[2]; *p != '\0'; )
  387.               {
  388. --- 140,161 ----
  389.               (void) chompheader(&buf[1], TRUE);
  390.               break;
  391.   
  392.             case 'F':        /* word class from file */
  393. !                 /* read from file */
  394. !             for (p = &buf[2]; *p != '\0' && !isspace(*p); p++)
  395. !                 continue;
  396. !             if (*p == '\0') p = "%s";
  397. !             else
  398.               {
  399. !                 *p = '\0';
  400. !                 while (isspace(*++p)) continue;
  401.               }
  402. +             fileclass(buf[1], &buf[2], p);
  403. +             break;
  404.   
  405. +           case 'C':        /* word class */
  406.               /* scan the list of words and set class for all */
  407.               for (p = &buf[2]; *p != '\0'; )
  408.               {
  409. ***************
  410. *** 179,184 ****
  411. --- 175,221 ----
  412.               }
  413.               break;
  414.   
  415. + #ifdef ROUTING    /* ******************************** */
  416. +           case 'E':        /* word equivalence class */
  417. +             /* scan the list of words as a <word, translation>
  418. +                pair, and set class for all */
  419. +             for (p = &buf[2]; *p != '\0'; )
  420. +             {
  421. +                 register char *wd;
  422. +                 register char *wd2;
  423. +                 char delim;
  424. +                 STAB *s;
  425. +                 while (*p != '\0' && isspace(*p))
  426. +                     p++;
  427. +                 wd = p;
  428. +                 while (*p != '\0' && !isspace(*p))
  429. +                     p++;
  430. +                 delim = *p;
  431. +                 *p = '\0';
  432. +                 if (wd[0] != '\0')
  433. +                     s = setclass(buf[1], wd);
  434. +                 *p = delim;
  435. +                 while (*p != '\0' && isspace(*p))
  436. +                     p++;
  437. +                 wd2 = p;
  438. +                 while (*p != '\0' && !isspace(*p))
  439. +                     p++;
  440. +                 delim = *p;
  441. +                 *p = '\0';
  442. +                 if (*wd != NULL)
  443. +                     makeequiv(buf[1],wd2,s);
  444. +                 *p = delim;
  445. +             }
  446. +             break;
  447. + #endif ROUTING    /* ******************************** */
  448.             case 'M':        /* define mailer */
  449.               makemailer(&buf[1], safe);
  450.               break;
  451. ***************
  452. *** 269,274 ****
  453. --- 306,322 ----
  454.   **
  455.   **        puts all lines in filename that match a scanf into
  456.   **            the named class.
  457. + **
  458. + **    Comment: equivalence class modification
  459. + **        fileclass has been modified so that if you use a format
  460. + **        string returning two strings, i.e.:
  461. + **
  462. + **        FN/usr/lib/net-gateways "%s%s"
  463. + **
  464. + **        it will store the second name as a name translation of
  465. + **        the first, accessable through the $&<digit> macro.
  466. + **                        - BNI 9/5/84
  467. + **
  468.   */
  469.   
  470.   fileclass(class, filename, fmt)
  471. ***************
  472. *** 279,284 ****
  473. --- 327,338 ----
  474.       register FILE *f;
  475.       char buf[MAXLINE];
  476.   
  477. + #ifdef DEBUG
  478. +     if (tTd(86,5))
  479. +         printf("fileclass: class = %c, file = %s, fmt = \"%s\".\n"
  480. +             , class, filename, fmt);
  481. + #endif DEBUG
  482.       f = fopen(filename, "r");
  483.       if (f == NULL)
  484.       {
  485. ***************
  486. *** 291,300 ****
  487. --- 345,391 ----
  488.           register STAB *s;
  489.           char wordbuf[MAXNAME+1];
  490.   
  491. + #ifdef ROUTING    /* ******************************** */
  492. +         char word2[MAXNAME+1];
  493. +         int ssc;
  494. + #ifdef DEBUG
  495. +         if (tTd(86,11))
  496. +             printf("fileclass: got line '%s'.\n",buf);
  497. + #endif DEBUG
  498. +         word2[0] = '\0';
  499. +         
  500. +         if ((ssc=sscanf(buf, fmt, wordbuf, word2, 0)) < 1) {
  501. + #ifdef DEBUG
  502. +             if(tTd(86,8))
  503. +                   printf("fileclass: found nothing on line.\n");
  504. + #endif DEBUG
  505. +             continue;
  506. +         }
  507. + #ifdef DEBUG
  508. +         if (tTd(86,8))
  509. +             if (*word2)
  510. +                 printf("fileclass: found word translation '%s' --> '%s'.\n",
  511. +                 wordbuf,word2);
  512. +             else printf("fileclass: found word '%s'.\n",wordbuf);
  513. + #endif DEBUG
  514. + #else ROUTING    /* ******************************** */
  515.           if (sscanf(buf, fmt, wordbuf) != 1)
  516.               continue;
  517. + #endif ROUTING    /* ******************************** */
  518.           s = stab(wordbuf, ST_CLASS, ST_ENTER);
  519.           setbitn(class, s->s_class);
  520. + #ifdef ROUTING    /* ******************************** */
  521. +         if (*word2 != NULL)
  522. +             makeequiv(class,word2,s);
  523. + #endif ROUTING    /* ******************************** */
  524.       }
  525.   
  526.       (void) fclose(f);
  527. ***************
  528. *** 805,816 ****
  529.   **        word -- the word to enter
  530.   **
  531.   **    Returns:
  532. ! **        none.
  533.   **
  534.   **    Side Effects:
  535.   **        puts the word into the symbol table.
  536.   */
  537.   
  538.   setclass(class, word)
  539.       int class;
  540.       char *word;
  541. --- 896,915 ----
  542.   **        word -- the word to enter
  543.   **
  544.   **    Returns:
  545. ! **        a pointer to the symbol table entry created.
  546. ! **        - changed from 'no return value' 9/5/84 - BNI
  547.   **
  548.   **    Side Effects:
  549.   **        puts the word into the symbol table.
  550.   */
  551.   
  552. + #ifdef ROUTING    /* ******************************** */
  553. + STAB *
  554. + #endif ROUTING    /* ******************************** */
  555.   setclass(class, word)
  556.       int class;
  557.       char *word;
  558. ***************
  559. *** 819,822 ****
  560. --- 918,926 ----
  561.   
  562.       s = stab(word, ST_CLASS, ST_ENTER);
  563.       setbitn(class, s->s_class);
  564. + #ifdef ROUTING    /* ******************************** */
  565. +     return (s);
  566. + #endif ROUTING    /* ******************************** */
  567.   }
  568. diff -c stab.c.old stab.c
  569. *** /usr/4.2/src/usr.lib/sendmail/src/stab.c    Mon Jul 25 23:18:41 1983
  570. --- /usr/israel/sendmail/src/stab.c    Fri Feb  1 17:00:59 1985
  571. ***************
  572. *** 106,108 ****
  573. --- 106,185 ----
  574.   
  575.       return (s);
  576.   }
  577. + #ifdef ROUTING    /* ******************************** */
  578. + /*
  579. + **  MAKEEQUIV -- make a name equivalence entry
  580. + **
  581. + **    Parameters:
  582. + **        class -- the class the equivalence is in.
  583. + **        name  -- The name to be translated into.
  584. + **        s     -- a symbol table entry to the orginal name.
  585. + **
  586. + **    Returns:
  587. + **        none.
  588. + **
  589. + **    Side Effects:
  590. + **        none.
  591. + **
  592. + **    Author:
  593. + **        Bruce Israel  --  9/4/84.
  594. + **
  595. + */
  596. + makeequiv(class,name,s)
  597. + char class;
  598. + char *name;
  599. + STAB *s;
  600. + {
  601. +     EQUIV *eq;
  602. + #ifdef DEBUG
  603. +     if (tTd(87,5))
  604. +         printf("makeequiv: defining '%s' --> '%s' in class '%c'.\n",
  605. +             s -> s_name, name, class);
  606. + #endif DEBUG
  607. +     eq = (EQUIV *) xalloc(sizeof *eq);
  608. +     eq -> class = class;
  609. +     eq -> equivname = newstr(name);
  610. +     eq -> next = s ->s_equiv;
  611. +     s -> s_equiv = eq;
  612. + }
  613. +  /*
  614. + **  GETQUIV -- get a name equivalence for a class
  615. + **
  616. + **    Parameters:
  617. + **        class -- the class the equivalence is in.
  618. + **        s     -- The symbol table entry of the word.
  619. + **
  620. + **    Returns:
  621. + **        a pointer to a string containing the translation
  622. + **        name. If the symbol table entry has no translation
  623. + **        name, the original name will be returned.
  624. + **
  625. + **    Side Effects:
  626. + **        none.
  627. + **
  628. + **    Author:
  629. + **        Bruce Israel  --  9/4/84.
  630. + **
  631. + */
  632. + char *getequiv(class,s)
  633. + char class;
  634. + STAB *s;
  635. + {
  636. +     EQUIV *eq;
  637. +     eq = s -> s_equiv;
  638. +     while (eq != NULL) {
  639. +         if (eq -> class == class) return (eq -> equivname);
  640. +         eq = eq -> next;
  641. +     }
  642. +     return(s -> s_name);
  643. + }
  644. + #endif ROUTING    /* ******************************** */
  645. diff -c sendmail.h.old sendmail.h
  646. *** /usr/4.2/src/usr.lib/sendmail/src/sendmail.h    Sun Sep 25 21:06:12 1983
  647. --- /usr/israel/sendmail/src/sendmail.h    Fri Feb  1 17:00:42 1985
  648. ***************
  649. *** 2,9 ****
  650.   **  SENDMAIL.H -- Global definitions for sendmail.
  651.   */
  652.   
  653.   
  654.   # ifdef _DEFINE
  655.   # define EXTERN
  656.   # ifndef lint
  657. --- 2,9 ----
  658.   **  SENDMAIL.H -- Global definitions for sendmail.
  659.   */
  660.   
  661. + # define ROUTING    /* Mods for equivalence name classes - BNI 9/5/84 */
  662.   
  663.   # ifdef _DEFINE
  664.   # define EXTERN
  665.   # ifndef lint
  666. ***************
  667. *** 290,299 ****
  668. --- 290,319 ----
  669.   # define CONDIF        '\031'    /* conditional if-then */
  670.   # define CONDELSE    '\032'    /* conditional else */
  671.   # define CONDFI        '\033'    /* conditional fi */
  672. + #ifdef ROUTING    /* ******************************** */
  673. + # define EQUIVREPL    '\034'    /* equivalence class replacement */
  674. + #endif ROUTING    /* ******************************** */
  675.    /*
  676.   **  Symbol table definitions
  677.   */
  678.   
  679. + #ifdef ROUTING    /* ******************************** */
  680. + struct equivstr
  681. + {
  682. +     char        class;        /* class the name belongs in */
  683. +     char        *equivname;    /* translated version of name */
  684. +     struct equivstr    *next;        /* next item on equivalence list */
  685. + };
  686. + typedef struct equivstr EQUIV;
  687. + #endif ROUTING    /* ******************************** */
  688.   struct symtab
  689.   {
  690.       char        *s_name;    /* name to be entered */
  691. ***************
  692. *** 306,311 ****
  693. --- 326,334 ----
  694.           MAILER    *sv_mailer;    /* pointer to mailer */
  695.           char    *sv_alias;    /* alias */
  696.       }    s_value;
  697. + #ifdef ROUTING    /* ******************************** */
  698. +     EQUIV        *s_equiv;    /* pointer to equivalence names list */
  699. + #endif ROUTING    /* ******************************** */
  700.   };
  701.   
  702.   typedef struct symtab    STAB;
  703. ***************
  704. *** 323,328 ****
  705. --- 346,358 ----
  706.   # define s_alias    s_value.sv_alias
  707.   
  708.   extern STAB    *stab();
  709. + #ifdef ROUTING    /* ******************************** */
  710. + STAB    *setclass();
  711. + char    *getequiv();
  712. + #endif ROUTING    /* ******************************** */
  713.   
  714.   /* opcodes to stab */
  715.   # define ST_FIND    0    /* find entry */
  716. //go.sysin dd *
  717. if [ `wc -c < 4.2diffs` != 17321 ]; then
  718.     made=FALSE
  719.     /bin/echo 'error transmitting "4.2diffs" --'
  720.     /bin/echo 'length should be 17321, not' `wc -c < 4.2diffs`
  721. else
  722.     made=TRUE
  723. fi
  724. if [ $made = TRUE ]; then
  725.     /bin/chmod 644 4.2diffs
  726.     /bin/echo -n '    '; /bin/ls -ld 4.2diffs
  727. fi
  728. /bin/echo 'Extracting 4.3diffs'
  729. sed 's/^X//' <<'//go.sysin dd *' >4.3diffs
  730. RCS file: RCS/main.c,v
  731. retrieving revision 1.1
  732. diff -c -r1.1 main.c
  733. *** /tmp/,RCSt1001795    Thu Oct 31 18:03:04 1985
  734. --- main.c    Fri Oct 18 19:39:15 1985
  735. ***************
  736. *** 778,783 ****
  737. --- 778,784 ----
  738.   
  739.       /* these are RHS metasymbols */
  740.       '#', CANONNET,    '@', CANONHOST,    ':', CANONUSER,    '>', CALLSUBR,
  741. +     '&', EQUIVREPL,
  742.   
  743.       /* the conditional operations */
  744.       '?', CONDIF,    '|', CONDELSE,    '.', CONDFI,
  745. ===================================================================
  746. RCS file: RCS/parseaddr.c,v
  747. retrieving revision 1.1
  748. diff -c -r1.1 parseaddr.c
  749. *** /tmp/,RCSt1001795    Thu Oct 31 18:03:12 1985
  750. --- parseaddr.c    Fri Oct 18 19:39:19 1985
  751. ***************
  752. *** 213,218 ****
  753. --- 213,222 ----
  754.   **
  755.   **    Side Effects:
  756.   **        none.
  757. + **
  758. + **    N.B.: prescan's work is all done by the internal routine
  759. + **    _prescan, which merely has one additional parameter:
  760. + **        av -- place to put the pointers.
  761.   */
  762.   
  763.   /* states and character types */
  764. ***************
  765. *** 250,255 ****
  766. --- 254,272 ----
  767.       char delim;
  768.       char pvpbuf[];
  769.   {
  770. +     static char *av[MAXATOM+1];
  771. +     char **_prescan();
  772. +     return (_prescan(addr, delim, pvpbuf, av));
  773. + }
  774. + static char **
  775. + _prescan(addr, delim, pvpbuf, av)
  776. +     char *addr;
  777. +     char delim;
  778. +     char pvpbuf[];
  779. +     char *av[];
  780. + {
  781.       register char *p;
  782.       register char *q;
  783.       register int c;
  784. ***************
  785. *** 260,266 ****
  786.       char *tok;
  787.       int state;
  788.       int newstate;
  789. -     static char *av[MAXATOM+1];
  790.       extern int errno;
  791.   
  792.       /* make sure error messages don't have garbage on them */
  793. --- 277,282 ----
  794. ***************
  795. *** 443,449 ****
  796.           expand("\001o", buf, &buf[sizeof buf - 1], CurEnv);
  797.           (void) strcat(buf, DELIMCHARS);
  798.       }
  799. !     if (c == MATCHCLASS || c == MATCHREPL || c == MATCHNCLASS)
  800.           return (ONE);
  801.       if (c == '"')
  802.           return (QST);
  803. --- 459,466 ----
  804.           expand("\001o", buf, &buf[sizeof buf - 1], CurEnv);
  805.           (void) strcat(buf, DELIMCHARS);
  806.       }
  807. !     if (c == MATCHCLASS || c == MATCHREPL || c == MATCHNCLASS ||
  808. !         c == EQUIVREPL)
  809.           return (ONE);
  810.       if (c == '"')
  811.           return (QST);
  812. ***************
  813. *** 491,496 ****
  814. --- 508,514 ----
  815.   {
  816.       char    **first;    /* first token matched */
  817.       char    **last;        /* last token matched */
  818. +     char    *equiv;        /* equivalence name for match */ /* XXX */
  819.   };
  820.   
  821.   # define MAXMATCH    9    /* max params per rewrite */
  822. ***************
  823. *** 576,582 ****
  824.                   }
  825.                   else if (*rp == MATCHNCLASS)
  826.                       goto backup;
  827.                   /* explicit fall-through */
  828.   
  829.                 case MATCHONE:
  830. --- 594,604 ----
  831.                   }
  832.                   else if (*rp == MATCHNCLASS)
  833.                       goto backup;
  834. !                 /*
  835. !                  * XXX    Should only note equiv parameters
  836. !                  *    here, and do translation later.
  837. !                  */
  838. !                 mlp->equiv = getequiv(rp[1], s);
  839.                   /* explicit fall-through */
  840.   
  841.                 case MATCHONE:
  842. ***************
  843. *** 585,590 ****
  844. --- 607,613 ----
  845.                   mlp->first = avp;
  846.                   mlp->last = avp++;
  847.                   mlp++;
  848. +                 mlp->equiv = NULL;
  849.                   break;
  850.   
  851.                 case MATCHZANY:
  852. ***************
  853. *** 592,597 ****
  854. --- 615,621 ----
  855.                   mlp->first = avp;
  856.                   mlp->last = avp - 1;
  857.                   mlp++;
  858. +                 mlp->equiv = NULL;
  859.                   break;
  860.   
  861.                 default:
  862. ***************
  863. *** 625,630 ****
  864. --- 649,655 ----
  865.                   {
  866.                       /* back out binding */
  867.                       mlp--;
  868. +                     mlp->equiv = NULL;
  869.                   }
  870.               }
  871.   
  872. ***************
  873. *** 679,689 ****
  874.               register char **pp;
  875.   
  876.               rp = *rvp;
  877. !             if (*rp == MATCHREPL)
  878.               {
  879.                   /* substitute from LHS */
  880.                   m = &mlist[rp[1] - '1'];
  881. !                 if (m >= mlp)
  882.                   {
  883.                       syserr("rewrite: ruleset %d: replacement out of bounds", ruleset);
  884.                       return;
  885. --- 704,714 ----
  886.               register char **pp;
  887.   
  888.               rp = *rvp;
  889. !             if (*rp == MATCHREPL || *rp == EQUIVREPL)
  890.               {
  891.                   /* substitute from LHS */
  892.                   m = &mlist[rp[1] - '1'];
  893. !                 if (rp[1] < '1' || rp[1] > '9' || m >= mlp)
  894.                   {
  895.                       syserr("rewrite: ruleset %d: replacement out of bounds", ruleset);
  896.                       return;
  897. ***************
  898. *** 691,697 ****
  899.   # ifdef DEBUG
  900.                   if (tTd(21, 15))
  901.                   {
  902. !                     printf("$%c:", rp[1]);
  903.                       pp = m->first;
  904.                       while (pp <= m->last)
  905.                       {
  906. --- 716,725 ----
  907.   # ifdef DEBUG
  908.                   if (tTd(21, 15))
  909.                   {
  910. !                     if (*rp == EQUIVREPL)
  911. !                         printf("$&%c:", rp[1]);
  912. !                     else
  913. !                         printf("$%c:", rp[1]);
  914.                       pp = m->first;
  915.                       while (pp <= m->last)
  916.                       {
  917. ***************
  918. *** 699,716 ****
  919.                           (void) fflush(stdout);
  920.                           printf("%s\"", *pp++);
  921.                       }
  922.                       printf("\n");
  923.                   }
  924.   # endif DEBUG
  925. !                 pp = m->first;
  926. !                 while (pp <= m->last)
  927.                   {
  928. !                     if (avp >= &npvp[MAXATOM])
  929.                       {
  930. !                         syserr("rewrite: expansion too long");
  931. !                         return;
  932.                       }
  933. !                     *avp++ = *pp++;
  934.                   }
  935.               }
  936.               else
  937. --- 727,770 ----
  938.                           (void) fflush(stdout);
  939.                           printf("%s\"", *pp++);
  940.                       }
  941. +                     if (*rp == EQUIVREPL)
  942. +                         printf(" => \"%s\"",
  943. +                             m->equiv);
  944.                       printf("\n");
  945.                   }
  946.   # endif DEBUG
  947. !                 if (*rp == EQUIVREPL)
  948.                   {
  949. !                     char equivbuf[PSBUFSIZE];
  950. !                     char *equivav[MAXATOM+1];
  951. !                     char *saveDelim = DelimChar;
  952. !                     extern char **copyplist();
  953. !                     /*
  954. !                      * XXX    waste of memory!
  955. !                      */
  956. !                     pp = copyplist(_prescan(m->equiv,
  957. !                                 '\0',
  958. !                                 equivbuf,
  959. !                                 equivav),
  960. !                             TRUE);
  961. !                     DelimChar = saveDelim;
  962. !                     while (*pp)
  963.                       {
  964. !                         if (avp >= &npvp[MAXATOM])
  965. !                             goto toolong;
  966. !                         *avp++ = *pp++;
  967.                       }
  968. !                 }
  969. !                 else
  970. !                 {
  971. !                     pp = m->first;
  972. !                     while (pp <= m->last)
  973. !                     {
  974. !                         if (avp >= &npvp[MAXATOM])
  975. !                             goto toolong;
  976. !                         *avp++ = *pp++;
  977. !                     }
  978.                   }
  979.               }
  980.               else
  981. ===================================================================
  982. RCS file: RCS/readcf.c,v
  983. retrieving revision 1.1
  984. diff -c -r1.1 readcf.c
  985. *** /tmp/,RCSt1001795    Thu Oct 31 18:03:23 1985
  986. --- readcf.c    Fri Oct 18 19:39:22 1985
  987. ***************
  988. *** 164,189 ****
  989.               (void) chompheader(&buf[1], TRUE);
  990.               break;
  991.   
  992. -           case 'C':        /* word class */
  993.             case 'F':        /* word class from file */
  994.               /* read list of words from argument or file */
  995. !             if (buf[0] == 'F')
  996.               {
  997. !                 /* read from file */
  998. !                 for (p = &buf[2]; *p != '\0' && !isspace(*p); p++)
  999.                       continue;
  1000. -                 if (*p == '\0')
  1001. -                     p = "%s";
  1002. -                 else
  1003. -                 {
  1004. -                     *p = '\0';
  1005. -                     while (isspace(*++p))
  1006. -                         continue;
  1007. -                 }
  1008. -                 fileclass(buf[1], &buf[2], p);
  1009. -                 break;
  1010.               }
  1011.   
  1012.               /* scan the list of words and set class for all */
  1013.               for (p = &buf[2]; *p != '\0'; )
  1014.               {
  1015. --- 164,186 ----
  1016.               (void) chompheader(&buf[1], TRUE);
  1017.               break;
  1018.   
  1019.             case 'F':        /* word class from file */
  1020.               /* read list of words from argument or file */
  1021. !             /* read from file */
  1022. !             for (p = &buf[2]; *p != '\0' && !isspace(*p); p++)
  1023. !                 continue;
  1024. !             if (*p == '\0')
  1025. !                 p = "%s";
  1026. !             else
  1027.               {
  1028. !                 *p = '\0';
  1029. !                 while (isspace(*++p))
  1030.                       continue;
  1031.               }
  1032. +             fileclass(buf[1], &buf[2], p);
  1033. +             break;
  1034.   
  1035. +           case 'C':        /* word class */
  1036.               /* scan the list of words and set class for all */
  1037.               for (p = &buf[2]; *p != '\0'; )
  1038.               {
  1039. ***************
  1040. *** 203,208 ****
  1041. --- 200,247 ----
  1042.               }
  1043.               break;
  1044.   
  1045. + /* BEGIN STRANGE */
  1046. + /* Do we actually use this??? */
  1047. +           case 'E':        /* word equivalence class */
  1048. +             for (p = &buf[2]; *p != '\0'; )
  1049. +             {
  1050. +                 register char *wd;
  1051. +                 register char *eqwd;
  1052. +                 char delim;
  1053. +                 register STAB *s;
  1054. +                 while (*p != '\0' && isspace(*p))
  1055. +                     p++;
  1056. +                 wd = p;
  1057. +                 while (*p != '\0' && !isspace(*p))
  1058. +                     p++;
  1059. +                 delim = *p;
  1060. +                 *p = '\0';
  1061. +                 if (wd[0] == 0)
  1062. +                 {
  1063. +                     *p = delim;
  1064. +                     break;
  1065. +                 }
  1066. +                 /*
  1067. +                  * Cannot use setclass here as we
  1068. +                  * need the sym entry
  1069. +                  */
  1070. +                 s = stab(wd, ST_CLASS, ST_ENTER);
  1071. +                 setbitn(buf[1], s->s_class);
  1072. +                 *p = delim;
  1073. +                 while (*p != '\0' && isspace(*p))
  1074. +                     p++;
  1075. +                 eqwd = p;
  1076. +                 while (*p != '\0' && !isspace(*p))
  1077. +                     p++;
  1078. +                 delim = *p;
  1079. +                 *p = 0;
  1080. +                 makeequiv(buf[1], eqwd, s);
  1081. +                 *p = delim;
  1082. +             }
  1083. +             break;
  1084. + /* END STRANGE */
  1085.             case 'M':        /* define mailer */
  1086.               makemailer(&buf[1]);
  1087.               break;
  1088. ***************
  1089. *** 314,324 ****
  1090.       {
  1091.           register STAB *s;
  1092.           char wordbuf[MAXNAME+1];
  1093. !         if (sscanf(buf, fmt, wordbuf) != 1)
  1094.               continue;
  1095.           s = stab(wordbuf, ST_CLASS, ST_ENTER);
  1096.           setbitn(class, s->s_class);
  1097.       }
  1098.   
  1099.       (void) fclose(f);
  1100. --- 353,382 ----
  1101.       {
  1102.           register STAB *s;
  1103.           char wordbuf[MAXNAME+1];
  1104. !         char equivbuf[MAXNAME+1];
  1105. !         int nscanned;
  1106. !         
  1107. !         if ((nscanned = sscanf(buf, fmt, wordbuf, equivbuf)) < 1)
  1108. !         {
  1109. ! #ifdef DEBUG
  1110. !             if (tTd(86, 8))
  1111. !                 printf("fileclass: found nothing on line.\n");
  1112. ! #endif DEBUG
  1113.               continue;
  1114. +         }
  1115. + #ifdef DEBUG
  1116. +         if (tTd(86, 8))
  1117. +         {
  1118. +             printf("fileclass: found word \"%s\"", wordbuf);
  1119. +             if (nscanned > 1)
  1120. +                 printf(" => \"%s\"", equivbuf);
  1121. +             printf(".\n");
  1122. +         }
  1123. + #endif DEBUG
  1124.           s = stab(wordbuf, ST_CLASS, ST_ENTER);
  1125.           setbitn(class, s->s_class);
  1126. +         if (nscanned > 1)
  1127. +             makeequiv(class, equivbuf, s);
  1128.       }
  1129.   
  1130.       (void) fclose(f);
  1131. ===================================================================
  1132. RCS file: RCS/sendmail.h,v
  1133. retrieving revision 1.1
  1134. diff -c -r1.1 sendmail.h
  1135. *** /tmp/,RCSt1001795    Thu Oct 31 18:03:32 1985
  1136. --- sendmail.h    Sat Oct 19 03:03:24 1985
  1137. ***************
  1138. *** 57,64 ****
  1139. --- 57,69 ----
  1140.   #define BYTEBITS    8    /* number of bits in a byte */
  1141.   
  1142.   /* internal macros */
  1143. + #if BYTEBITS == 8 && (defined(vax) || defined(mc68000) || defined(ns32000))
  1144. + #define _BITWORD(bit)    ((bit) >> 5)
  1145. + #define    _BITBIT(bit)    (1 << ((bit) & (BYTEBITS * sizeof (int) - 1)))
  1146. + #else BYTEBITS == 8
  1147.   #define _BITWORD(bit)    (bit / (BYTEBITS * sizeof (int)))
  1148.   #define _BITBIT(bit)    (1 << (bit % (BYTEBITS * sizeof (int))))
  1149. + #endif BYTEBITS == 8
  1150.   
  1151.   typedef int    BITMAP[BITMAPBYTES / sizeof (int)];
  1152.   
  1153. ***************
  1154. *** 321,326 ****
  1155. --- 326,334 ----
  1156.   # define HOSTBEGIN    '\035'    /* hostname lookup begin */
  1157.   # define HOSTEND    '\036'    /* hostname lookup end */
  1158.   
  1159. + /* canonicalization */
  1160. + # define EQUIVREPL    '\037'    /* equivalence class replacement */
  1161.   /* \001 is also reserved as the macro expansion character */
  1162.    /*
  1163.   **  Information about hosts that we have looked up recently.
  1164. ***************
  1165. *** 352,357 ****
  1166. --- 360,379 ----
  1167.   **  Symbol table definitions
  1168.   */
  1169.   
  1170. + /*
  1171. +  * The canonicalizing operator $&n looks up names and replacements.
  1172. +  * The replacment name(s) for a name are stored in the following
  1173. +  * linked list, which is then attached to the symbol table entry.
  1174. +  */
  1175. + struct equivstr
  1176. + {
  1177. +     char        class;        /* class the replacement is in */
  1178. +     char        *equivname;    /* the replacement name */
  1179. +     struct equivstr *next;        /* linked list */
  1180. + };
  1181. + typedef struct equivstr EQUIV;
  1182.   struct symtab
  1183.   {
  1184.       char        *s_name;    /* name to be entered */
  1185. ***************
  1186. *** 367,372 ****
  1187. --- 389,395 ----
  1188.           HOSTINFO    sv_host;    /* host information */
  1189.   # endif HOSTINFO
  1190.       }    s_value;
  1191. +     EQUIV        *s_equiv;    /* list of replacements */
  1192.   };
  1193.   
  1194.   typedef struct symtab    STAB;
  1195. ***************
  1196. *** 386,391 ****
  1197. --- 409,415 ----
  1198.   # define s_host        s_value.sv_host
  1199.   
  1200.   extern STAB    *stab();
  1201. + extern char    *getequiv();
  1202.   
  1203.   /* opcodes to stab */
  1204.   # define ST_FIND    0    /* find entry */
  1205. ===================================================================
  1206. RCS file: RCS/stab.c,v
  1207. retrieving revision 1.1
  1208. diff -c -r1.1 stab.c
  1209. *** /tmp/,RCSt1001795    Thu Oct 31 18:03:39 1985
  1210. --- stab.c    Fri Oct 18 19:39:27 1985
  1211. ***************
  1212. *** 118,120 ****
  1213. --- 118,221 ----
  1214.   
  1215.       return (s);
  1216.   }
  1217. +  /*
  1218. + **  MAKEEQUIV -- make a name equivalence entry
  1219. + **
  1220. + **    Parameters:
  1221. + **        class -- the class the equivalence is in.
  1222. + **        name -- the replacement (new) name.
  1223. + **        s -- the symbol table entry of the source (old) name.
  1224. + **
  1225. + **    Returns:
  1226. + **        none.
  1227. + **
  1228. + **    Side Effects:
  1229. + **        Updates the equivalences attached to `s'.
  1230. + **
  1231. + **    Author:
  1232. + **        Bruce Israel -- 9/4/84.
  1233. + **        Fixes 17 Oct 1985, Chris Torek
  1234. + */
  1235. + makeequiv(class, name, s)
  1236. +     register int class;
  1237. +     char *name;
  1238. +     register STAB *s;
  1239. + {
  1240. +     register EQUIV *eq;
  1241. +     for (eq = s->s_equiv; eq != NULL; eq = eq->next)
  1242. +     {
  1243. +         if (eq->class != class)
  1244. +             continue;
  1245. +         /*
  1246. +          * To replace, or to reject: that is the question.
  1247. +          * Whether 'tis nobler to suffer the slings and
  1248. +          * arrows of outrageous remappings, or, by opposing,
  1249. +          * to end them.  ...Chris
  1250. +          */
  1251. + #ifdef DEBUG
  1252. +         if (tTd(87, 5))
  1253. +             printf("makeequiv: attempt to replace \"%s\" => \"%s\" (class %c)\n\twith  => \"%s\" (ignored).\n",
  1254. +                 s->s_name, eq->equivname, class, name);
  1255. + #endif DEBUG
  1256. + #ifdef notdef
  1257. +         free(eq->equivname);
  1258. +         eq->equivname = newstr(name);
  1259. + #endif notdef
  1260. +         return;
  1261. +     }
  1262. +     eq = (EQUIV *)xalloc(sizeof *eq);
  1263. +     eq->class = class;
  1264. +     eq->equivname = newstr(name);
  1265. +     eq->next = s->s_equiv;
  1266. +     s->s_equiv = eq;
  1267. + }
  1268. +  /*
  1269. + **  GETEQUIV -- get the replacement name for a stab entry given a
  1270. + **  class.
  1271. + **
  1272. + **    Parameters:
  1273. + **        class -- the replacement class.
  1274. + **        s -- the old name.
  1275. + **
  1276. + **    Returns:
  1277. + **        a pointer to a string containing the new name.
  1278. + **        If the symbol table entry has no translation
  1279. + **        name, the original name will be returned.
  1280. + **
  1281. + **    Side Effects:
  1282. + **        none.
  1283. + **
  1284. + **    Author:
  1285. + **        Bruce Israel -- 9/4/84.
  1286. + */
  1287. + char *
  1288. + getequiv(class, s)
  1289. +     register int  class;
  1290. +     register STAB *s;
  1291. + {
  1292. +     register EQUIV *eq;
  1293. +     for (eq = s->s_equiv; eq != NULL; eq = eq->next)
  1294. +     {
  1295. +         if (eq->class != class)
  1296. +             continue;
  1297. + #ifdef DEBUG
  1298. +         if (tTd(87, 5))
  1299. +             printf("getequiv: \"%s\" => \"%s\" (class %c).\n",
  1300. +                 s->s_name, eq->equivname, class);
  1301. + #endif DEBUG
  1302. +         return (eq->equivname);
  1303. +     }
  1304. + #ifdef DEBUG
  1305. +     if (tTd(87, 5))
  1306. +         printf("getequiv: \"%s\" not mapped in class %c; unchanged.\n",
  1307. +             s->s_name);
  1308. + #endif DEBUG
  1309. +     return (s->s_name);
  1310. + }
  1311. //go.sysin dd *
  1312. if [ `wc -c < 4.3diffs` != 13636 ]; then
  1313.     made=FALSE
  1314.     /bin/echo 'error transmitting "4.3diffs" --'
  1315.     /bin/echo 'length should be 13636, not' `wc -c < 4.3diffs`
  1316. else
  1317.     made=TRUE
  1318. fi
  1319. if [ $made = TRUE ]; then
  1320.     /bin/chmod 644 4.3diffs
  1321.     /bin/echo -n '    '; /bin/ls -ld 4.3diffs
  1322. fi
  1323. /bin/echo 'Extracting README'
  1324. sed 's/^X//' <<'//go.sysin dd *' >README
  1325. This documents the University of Maryland modifications to sendmail to
  1326. allow translation tables to be used in sendmail.cf.
  1327.  
  1328. There are 5 files here.  They are:
  1329.  
  1330. 4.2diffs
  1331. 4.3diffs - these are diff -c listings for the changes to the sendmail
  1332.     source.  The changes exist in 5 files, parseaddr.c (the meat
  1333.     of the changes), readcf.c, stab.c main.c and sendmail.h.
  1334.  
  1335. mimsy.cf - The standard University of Maryland .cf file.  This file is
  1336.     almost completely host independent, with only the real name, UUCP
  1337.     name, and valid local domain definitions hardcoded into Define's.
  1338.     Any other system information has been moved to files in the
  1339.     directory /usr/lib/hostnames/.
  1340.  
  1341. host-doc - This documents the various files in /usr/lib/hostnames/
  1342.     that are used by the sendmail.cf file.  It is intended to be a
  1343.     README for that directory.
  1344.  
  1345. names - this is a shell script that makes a translation table for all
  1346.     local network users.  It has hard-coded into it all machines on
  1347.     the local network, and when run on a machine, builds a file of
  1348.     accounts and aliases on the local network but NOT on the current
  1349.     host.  This file is used by the .cf file to route mail to users on
  1350.     the local net.  In this fashion, if JOE has an account on one
  1351.     local machine, mail to JOE@<any-local-machine> will get to him.
  1352.     If JOE has an account on multiple machines, it will route his
  1353.     mail to one of them and assume that he has a .forward.  Note
  1354.     that this requires that names on local network machines be unique
  1355.     (i.e. two different people would not be given the same account).
  1356.  
  1357. - How to use these mods -
  1358.  
  1359. After installing the source mods, you will have a sendmail executable
  1360. that has this extra feature of translation tables.  In normal
  1361. sendmails, you use the 'C' and 'F' commands in the .cf file to define
  1362. classes (C for classes define in the .cf file, and F for classes
  1363. defined in an external file).  Translation tables are defined with
  1364. the 'E' and 'F' commands.  A class is a list of items.  A translation
  1365. class is a list of pairs, items and the translated version of the
  1366. item.  i.e. a translation file for some uucp sites to be routed (i.e.
  1367. pathalias stuff) could look like:
  1368.  
  1369. seismo    umcp-cs!seismo
  1370. chimera    gymble!harvard!chimera
  1371. godot    gymble!harvard!think
  1372. elsie    elsie
  1373. ihnp4    umcp-cs!seismo!ihnp4
  1374.  
  1375. To read in a translation table from a file, use 'F' like always but
  1376. give a format string with two %s's in it, i.e.
  1377.  
  1378. FU/usr/lib/hostnames/uucp-routing %s%s
  1379.  
  1380. and both the name and its translation would be read in.  The 'E'
  1381. command is like 'C'.  It reads pairs of items on the current line (and
  1382. continuation lines) and groups them together.  i.e. a list of people
  1383. and the machine that they use might be:
  1384.  
  1385. EPjoe site1 bill site2 john site1 ed site3
  1386.  
  1387. E was added for orthogonality with C, and is unused in the sample
  1388. sendmail.cf file enclosed.
  1389.  
  1390. Accessing Translations
  1391.  
  1392. Normally in sendmail you use $<number> in a RHS to access items
  1393. matched on the LHS.  If you want the translation instead, follow the $
  1394. with an &, i.e. $&3.  For example, rules using the above classes might
  1395. look like:
  1396.  
  1397. R$=U!$+        $:$&1!$2    Expand UUCP paths from file
  1398. R$=P        $1@$&1        Route mail for users to their machine
  1399.  
  1400. Notice that both $num and $&num can be used together.  If a
  1401. class was not specified as a translation table, then the translation
  1402. of any item in that class is equivalent to the item itself.
  1403.  
  1404. For more information, see the examples in mimsy.cf or send mail to
  1405. israel@mimsy.umd.edu (Arpanet) or seismo!umcp-cs!israel (Usenet).
  1406.  
  1407. Enjoy.
  1408. //go.sysin dd *
  1409. if [ `wc -c < README` != 3527 ]; then
  1410.     made=FALSE
  1411.     /bin/echo 'error transmitting "README" --'
  1412.     /bin/echo 'length should be 3527, not' `wc -c < README`
  1413. else
  1414.     made=TRUE
  1415. fi
  1416. if [ $made = TRUE ]; then
  1417.     /bin/chmod 644 README
  1418.     /bin/echo -n '    '; /bin/ls -ld README
  1419. fi
  1420. /bin/echo 'Extracting host-doc'
  1421. sed 's/^X//' <<'//go.sysin dd *' >host-doc
  1422. This file documents the directory /usr/lib/hostnames that is
  1423. frequently used in sendmail.cf.  It is intended to be a README for
  1424. that directory.
  1425.  
  1426. This directory contains all routing tables for sendmail.  The different files
  1427. are used to route mail to different hosts on various nets.  The files are:
  1428.  
  1429. combined-hosts    This file contains sites that are known to be on both the
  1430.         arpanet and USEnet.  For such sites, mail is routed via
  1431.         the ARPAnet if a specific delivery method (i.e. .UUCP) is
  1432.         not specified.
  1433.  
  1434. csnet        This file contains the list of CSNet Phonenet sites.  It is
  1435.         in the form '<alias> <real-name>'.
  1436.  
  1437. cur-site    Aliases for the local site.
  1438.  
  1439. locals        Aliases for all local area network sites.  Lines are of
  1440.         the form '<site-alias> <real-site-name>'.
  1441.  
  1442. mailhosts    list of users and mailing lists on the other machines of
  1443.         the local network.  Lines are of the form:
  1444.         <name> <name>@<site>
  1445.         This file is created by the 'names' executable nightly.
  1446.  
  1447. relays        list of domains and an accessible host that knows how
  1448.         to relay all mail intended for that domain.  For
  1449.         example, 'csnet csnet-relay.arpa'.
  1450.  
  1451. specials    list of hosts that need to be specially processed, and
  1452.         the real way to get to that host.  This can be used for
  1453.         defining special, non-arpanet hosts or hosts who need
  1454.         a special path (like if a connection is broken).  Each
  1455.         line is '<site> <real-site-with-routing>'.  For example:
  1456.         if ARPASITE's arpanet connection is down indefinitely, you
  1457.         might put in: 'ARPASITE ARPASITE.uucp@ARPANEIGHBOR.uucp' and
  1458.         then mail will be routed to ARPANEIGHBOR via UUCP and then
  1459.         to ARPASITE.  Because of the purpose of this file, any
  1460.         path in here overrides all other paths (including user
  1461.         specified paths).
  1462.  
  1463. uucp-direct    List of sites that this site talks to directly via UUCP.
  1464.  
  1465. uucp-routing    List of UUCPnet sites that we know how to route to.
  1466.         Lines are of the form '<name> <route>!<name>'.
  1467. //go.sysin dd *
  1468. if [ `wc -c < host-doc` != 1903 ]; then
  1469.     made=FALSE
  1470.     /bin/echo 'error transmitting "host-doc" --'
  1471.     /bin/echo 'length should be 1903, not' `wc -c < host-doc`
  1472. else
  1473.     made=TRUE
  1474. fi
  1475. if [ $made = TRUE ]; then
  1476.     /bin/chmod 644 host-doc
  1477.     /bin/echo -n '    '; /bin/ls -ld host-doc
  1478. fi
  1479. /bin/echo 'Extracting mimsy.cf'
  1480. sed 's/^X//' <<'//go.sysin dd *' >mimsy.cf
  1481. ############################################################
  1482. ############################################################
  1483. #####
  1484. #####        SENDMAIL CONFIGURATION FILE
  1485. #####
  1486. #####        @(#) U of Maryland, October 1985
  1487. #####               - Bruce Israel israel@mimsy.umd.edu,
  1488. #####                              umcp-cs!israel
  1489. #####
  1490. ############################################################
  1491. ############################################################
  1492.  
  1493.  
  1494.  
  1495. ############################################################
  1496. ###    local info
  1497. ############################################################
  1498.  
  1499. # load to start queuing.  (busted--never queue.  MDW 8/3/84)
  1500. Ox50
  1501.  
  1502. # UUCP name
  1503. DUumcp-cs
  1504. CU$U
  1505.  
  1506. Dwmimsy
  1507.  
  1508. # internet hostname for current host - put into a file for portability
  1509. Fw/usr/lib/hostnames/cur-site
  1510. DA$w
  1511.  
  1512. # domain
  1513. DDumd.edu
  1514. CDumd.edu arpa csnet uucp
  1515.  
  1516. # official hostname
  1517. Dj$w.$D
  1518.  
  1519. # csnet names
  1520. FC/usr/lib/hostnames/csnet %s%s
  1521.  
  1522. # domain relays, (domain relay-site)
  1523. FR/usr/lib/hostnames/relays %s%s
  1524.  
  1525. # UUCP hosts that we talk directly to 
  1526. FW/usr/lib/hostnames/uucp-direct
  1527.  
  1528. # users mailhosts, local network people (user user@real-host)
  1529. FH/usr/lib/hostnames/mailhosts %s%s
  1530.  
  1531. # local network sites (site-alias real-site-name)
  1532. FL/usr/lib/hostnames/locals %s%s
  1533.  
  1534. # uucp routing table (site uucp-path!site)
  1535. FP/usr/lib/hostnames/uucp-routing %s%s
  1536. FP/usr/lib/hostnames/uucp-direct
  1537.  
  1538. # combination uucp/arpanet hosts, all local hosts are networked
  1539. FX/usr/lib/hostnames/combined-hosts
  1540. FX/usr/lib/hostnames/locals %s
  1541.  
  1542. # Hosts to handle specially (site override-path)
  1543. FS/usr/lib/hostnames/specials %s%s
  1544.  
  1545. ############################################################
  1546. #
  1547. #    General configuration information
  1548. #
  1549. #    This information is basically just "boiler-plate"; it must be
  1550. #    there, but is essentially constant.
  1551. #
  1552. #    Information in this file should be independent of location --
  1553. #    i.e., although there are some policy decisions made, they are
  1554. #    not specific to Berkeley per se.
  1555. #
  1556. #        @(#)base.m4    4.3        8/30/83
  1557. #
  1558. ############################################################
  1559.  
  1560. #    @(#)version.m4    4.7        8/31/83
  1561.  
  1562. DV4.7
  1563.  
  1564. ##########################
  1565. ###   Special macros   ###
  1566. ##########################
  1567.  
  1568. # my name
  1569. DnMAILER-DAEMON
  1570. # UNIX header format
  1571. DlFrom $g  $d  $y
  1572. # delimiter (operator) characters
  1573. Do.:%@!^=/[]
  1574. # format of a total name
  1575. # yucky style... Dq$g$?x ($x)$.
  1576. Dq$?x$x $.<$g>
  1577. # SMTP login message
  1578. De$j Sendmail $v/$V (with U of MD hacks) ready at $b
  1579.  
  1580. # forwarding host -- redefine this if you can't talk to the relay directly
  1581. DF$R
  1582.  
  1583. ###################
  1584. ###   Options   ###
  1585. ###################
  1586.  
  1587. # location of alias file
  1588. OA/usr/lib/aliases
  1589. # default delivery mode (deliver in background)
  1590. Odbackground
  1591. # (don't) connect to "expensive" mailers
  1592. #Oc
  1593. # temporary file mode
  1594. OF0644
  1595. # default GID
  1596. Og1
  1597. # location of help file
  1598. OH/usr/lib/sendmail.hf
  1599. # log level
  1600. OL9
  1601. # default messages to old style
  1602. Oo
  1603. # queue directory
  1604. OQ/usr/spool/mqueue
  1605. # read timeout -- violates protocols
  1606. Or2h
  1607. # status file
  1608. OS/usr/lib/sendmail.st
  1609. # queue up everything before starting transmission
  1610. Os
  1611. # default timeout interval
  1612. OT9d
  1613. # time zone names (V6 only)
  1614. OtEST,EDT
  1615. # default UID
  1616. Ou1
  1617.  
  1618. ###############################
  1619. ###   Message precedences   ###
  1620. ###############################
  1621.  
  1622. Pfirst-class=0
  1623. Pspecial-delivery=100
  1624. Pjunk=-100
  1625.  
  1626. #########################
  1627. ###   Trusted users   ###
  1628. #########################
  1629.  
  1630. Troot
  1631. Tdaemon
  1632. Tuucp
  1633. Tmark
  1634. Tisrael
  1635. Tnetwork
  1636. Ttewok
  1637.  
  1638. #############################
  1639. ###   Format of headers   ###
  1640. #############################
  1641.  
  1642. H?P?Return-Path: <$g>
  1643. HReceived: $?sfrom $s $.by $j ($v/$V)
  1644.     id $i; $b
  1645. H?D?Resent-Date: $a
  1646. H?D?Date: $a
  1647. H?F?Resent-From: $q
  1648. H?F?From: $q
  1649. H?x?Full-Name: $x
  1650. HSubject:
  1651. # HPosted-Date: $a
  1652. # H?l?Received-Date: $b
  1653. H?M?Resent-Message-Id: <$t.$i@$j>
  1654. H?M?Message-Id: <$t.$i@$j>
  1655.  
  1656. ###########################
  1657. ###   Rewriting rules   ###
  1658. ###########################
  1659.  
  1660.  
  1661. ################################
  1662. #  Sender Field Pre-rewriting  #
  1663. ################################
  1664. S1
  1665. #R$*<$*>$*        $1$2$3                defocus
  1666.  
  1667. ###################################
  1668. #  Recipient Field Pre-rewriting  #
  1669. ###################################
  1670. S2
  1671. #R$*<$*>$*        $1$2$3                defocus
  1672.  
  1673. #################################
  1674. #  Final Output Post-rewriting  #
  1675. #################################
  1676. S4
  1677.  
  1678. R@            $@                handle <> error addr
  1679.  
  1680. # externalize local domain info
  1681. R$*<$*LOCAL>$*        $1<$2$D>$3            change local info
  1682. R$*<$+>$*        $1$2$3                defocus
  1683. R@$+:$+:$+        $@@$1,$2:$3            <route-addr> canonical
  1684.  
  1685. # UUCP must always be presented in old form
  1686. R$+@$-.UUCP        $2!$1                u@h.UUCP => h!u
  1687.  
  1688. # delete duplicate local names -- mostly for arpaproto.mc
  1689. R$+%$=w@$=w        $1@$3                u%UCB@UCB => u@UCB
  1690. R$+%$=w@$=w.$=D        $1@$3.ARPA            u%UCB@UCB => u@UCB
  1691.  
  1692. ###########################
  1693. #  Name Canonicalization  #
  1694. ###########################
  1695. S3
  1696.  
  1697. # handle "from:<>" special case
  1698. R<>            $@@                turn into magic token
  1699.  
  1700. # basic textual canonicalization
  1701. R$*<$+>$*        $2                basic RFC821/822 parsing
  1702. R$+ at $+        $1@$2                "at" -> "@" for RFC 822
  1703. R$*<$*>$*        $1$2$3                in case recursive
  1704.  
  1705. # make sure <@a,@b,@c:user@d> syntax is easy to parse -- undone later
  1706. R@$+,$+            @$1:$2                change all "," to ":"
  1707.  
  1708. # localize and dispose of domain-based addresses
  1709. R@$+:$+            $@$>6<@$1>:$2            handle <route-addr>
  1710.  
  1711. # more miscellaneous cleanup
  1712. R$+:$*;@$+        $@$>6$1:$2;@$3            list syntax
  1713. R$+@$+            $:$1<@$2>            focus on domain
  1714. R$+<$+@$+>        $1$2<@$3>            move gaze right
  1715. R$+<@$+>        $@$>6$1<@$2>            already canonical
  1716.  
  1717. # convert old-style addresses to a domain-based address
  1718. R$+%$+            $@$>6$1<@$2>            user%host
  1719. R$-:$+            $@$>6$2<@$1>            host:user
  1720. R$-.$+            $@$>6$2<@$1>            host.user
  1721. R$+^$+            $1!$2                convert ^ to !
  1722. R$-!$+            $@$>6$2<@$1.UUCP>        resolve uucp names
  1723. R$-=$+            $@$>6$2<@$1.BITNET>        resolve bitnet names
  1724. R$*            $@$>6$1            process everything else
  1725.  
  1726. ############################################################
  1727. ############################################################
  1728. #####
  1729. #####        RULESET ZERO PREAMBLE
  1730. #####
  1731. #####    The beginning of ruleset zero is constant through all
  1732. #####    configurations.
  1733. #####
  1734. #####        @(#)zerobase.m4    4.1        7/25/83
  1735. #####
  1736. ############################################################
  1737. ############################################################
  1738.  
  1739. S0
  1740.  
  1741. # first make canonical
  1742. R$*<$*>$*        $1$2$3                defocus
  1743. R$+            $:$>3$1                make canonical
  1744.  
  1745. # handle special cases.....
  1746. R@            $#local$:MAILER-DAEMON        handle <> form
  1747. R$*<@[$+]>$*        $#tcp$@[$2]$:$1@[$2]$3        numeric internet spec
  1748.  
  1749. # arrange for local names to be fully qualified
  1750. R$*<$+.ARPA.LOCAL>$*    $1<$2.ARPA>$3            because ARPA is a host
  1751.  
  1752. # now delete the local info
  1753. R$*<$*$=w.LOCAL>$*    $1<$2>$4            thishost.LOCAL
  1754. R$*<$*$=w.ARPA>$*    $1<$2>$4            thishost.ARPA
  1755. R$*<$*$=w.UUCP>$*    $1<$2>$4            thishost.UUCP
  1756. R$*<$*$=w>$*        $1<$2>$4            thishost
  1757. R$*<$*.>$*        $1<$2>$3            drop trailing dot
  1758. R<@>:$*            $@$>0$1                retry after route strip
  1759. R$*<@>            $@$>0$1                strip null trash & retry
  1760.  
  1761. ##################################
  1762. #  End of ruleset zero preamble  #
  1763. ##################################
  1764.  
  1765.  
  1766. ################################################
  1767. ###  Machine dependent part of ruleset zero  ###
  1768. ################################################
  1769.  
  1770. # Do host routing
  1771.  
  1772. R$+<@$=w.$=D>    $#local$:$1    If local host, deliver
  1773. R$+<@$=w.$D>    $#local$:$1    If local host, deliver
  1774. R$+<@$=w>    $#local$:$1    If local host, deliver
  1775.  
  1776. # Do UUCP delivery for known UUCP sites
  1777. R<@$=W.UUCP>$+        $#uucp$@$1$:$2            @host.UUCP: ...
  1778. R$+<@$=W.UUCP>        $#uucp$@$2$:$1            user@host.UUCP
  1779. R$+<@$-.UUCP>        $:$1<@$2.ARPA>            if not uucp, try net
  1780.  
  1781. # resolve ARPA names we can handle locally
  1782. R$*<@$-.ARPA>$*        $#tcp$@$2$:$1<@$2.ARPA>$3    remove ARPA domain
  1783. R$*<@$+>$*        $#tcp$@$2$:$1<@$2>$3        deliver w/ domain
  1784.  
  1785. # catch whatever may have fallen thru the cracks.
  1786. R$+%$+            $:$>28$1%$2            if it still has @ or %,
  1787. R$+@$+            $:$>28$1@$2             then retry after doing
  1788. R$+<@$+>        $@$>0$1<@$2>             simple re-canon.
  1789.  
  1790. # remaining names must be local
  1791. R$+            $#local$:$1            everything else
  1792.  
  1793. ############################################################
  1794. ############################################################
  1795. #####
  1796. #####        Local and Program Mailer specification
  1797. #####
  1798. #####        @(#)localm.m4    4.1        7/25/83
  1799. #####
  1800. ############################################################
  1801. ############################################################
  1802.  
  1803. Mlocal,    P=/bin/mail, F=lsDFMmn, S=10, R=20, A=mail -d $u
  1804.  
  1805. # 4.3 should be:
  1806. #Mlocal,    P=/bin/mail, F=rlsDFMmn, S=10, R=20, A=mail -d $u
  1807.  
  1808. Mprog,    P=/bin/sh,   F=lsDFMe,   S=10, R=20, A=sh -c $u
  1809.  
  1810. S10
  1811. R@            MAILER-DAEMON            errors to mailer-daemon
  1812.  
  1813. ############################################################
  1814. ############################################################
  1815. #####
  1816. #####        Arpanet TCP Mailer specification
  1817. #####
  1818. #####        @(#)tcpm.m4    4.1        7/25/83
  1819. #####
  1820. ############################################################
  1821. ############################################################
  1822.  
  1823. Mtcp,    P=[IPC], F=msDFMueXL, S=14, R=14, A=IPC $h, E=\r\n
  1824.  
  1825. # 4.3 version is:
  1826. #Mtcp,    P=[IPC], F=mDFMueXL, S=14, R=14, A=IPC $h, E=\r\n
  1827.  
  1828. S14
  1829.  
  1830. # pass <route-addr>'s through
  1831. R<@$+>$*        $@<@$1>$2            resolve <route-addr>
  1832.  
  1833. # map colons to dots everywhere.....
  1834. R$*:$*            $1.$2                map colons to dots
  1835.  
  1836. # handle the simple case....
  1837. R$+<@$-.ARPA>        $@$1<@$2.ARPA>            user@host.ARPA
  1838.  
  1839. # output local hosts in user%host@mimsy syntax
  1840. R$+<@LOCAL>        $@$1<@$A>            local names
  1841. R$+<@$+.LOCAL>        $@$1%$2<@$A>            local hosts
  1842.  
  1843. # handle other external cases
  1844. R$+<@$->        $@$1<@$2>            no .ARPA on simple names
  1845. R$+<@$+.$-.ARPA>    $@$1%$2<@$3.ARPA>        approximate something
  1846. R$+<@[$+]>        $@$1<@[$2]>            already ok
  1847.  
  1848. # convert remaining addresses to old format and externalize appropriately
  1849. R$+            $:$>5$1                => old format
  1850. R$-:$+            $@$1.$2<@$A>            convert berk hosts
  1851. R$+<@$+>        $@$1<@$2>            don't pessmize
  1852. R$+            $:$1<@$w.$D>            tack on our hostname
  1853.  
  1854.  
  1855. #####################################################
  1856. #  General code to convert back to old style names  #
  1857. #####################################################
  1858. S5
  1859.  
  1860. R$+<@$-.LOCAL>        $2:$1                u@h.LOCAL => h:u
  1861. R$+<@$-.UUCP>        $2!$1                u@host.UUCP => host!u
  1862. R$+@$+.ARPA        $1@$2                u@host.ARPA => u@host
  1863.  
  1864.  
  1865. Muucp,    P=/usr/bin/uux, F=sDFMhuU, S=13, R=23, M=100000,
  1866.     A=uux - -r $h!rmail ($u)
  1867.  
  1868. # 4.3 version is:
  1869. #Muucp,    P=/usr/bin/uux, F=sDFMmhuU, S=13, R=23, M=100000,
  1870. #    A=uux - -r -z -a$g $h!rmail ($u)
  1871.  
  1872. S13
  1873. R$+            $:$>5$1                convert to old style
  1874. R$=w!$+            $2                strip local name
  1875. R$*<@$->$*        $1<@$2.ARPA>$3            resolve abbreviations
  1876. R$+            $:$U!$1                stick on our host name
  1877. # R$=w!$=R:$+        $:$1!$3                ucbvax!ucbvax:xxx
  1878.  
  1879. S23
  1880. R$+            $:$>5$1                convert to old style
  1881. R$*<@$->$*        $1<@$2.ARPA>$3            resolve abbreviations
  1882.  
  1883. #
  1884. # S6 - Fully qualify all addresses.
  1885. #
  1886. # This ruleset is the last thing that Ruleset 3 calls before returning.
  1887. # it fully qualifies all addresses by making sure that the proper host
  1888. # and domain names are present.  It handles domainifying, mail host
  1889. # routing, and UUCP, csnet, and bitnet routing in the following way:
  1890. #
  1891. # 1) if the address is for an account on another machine on the local
  1892. #    network, it appends the appropriate host of the account.
  1893. # 2) local accounts have the local hostname added, and all local
  1894. #    network machines have the network domain appended.
  1895. # 3) destinations that are handled by relays, i.e. csnet and bitnet
  1896. #    domains, are forwarded to the correct relay machine.
  1897. # 4) addresses destined for a UUCP host have the explicit route
  1898. #    to that host added.
  1899. # 5) any remaining addresses without domains are assumed to be
  1900. #    ARPAnet hosts.
  1901.  
  1902. S6
  1903.  
  1904. # source routing - don't process address at all
  1905.  
  1906. R<@$-.$+>:$*        $@<@$1.$2>:$3
  1907. R<@$*>:$*        $@<@$1.arpa>:$2
  1908.  
  1909. # Handle special hosts.  (i.e. Hosts that need special handling,
  1910. #  such as broken connections, or overriding paths.
  1911.  
  1912. R$*<@$=S$*>        $>28$1%$&2    match on hostname only, ignoring domain
  1913.  
  1914. # local
  1915.  
  1916. R$+<@$=w.$=D>        $:$>29$1    remove all local hosts,
  1917. R$+<@$=w.$D>        $:$>29$1      with any real local
  1918. R$+<@$=w>        $:$>29$1      domain.
  1919.  
  1920. R$*            $:$>28$1    put back in canonical
  1921.  
  1922. # expand mailhosts
  1923. R$=H            $:$>28$&1    modify to mailhost address
  1924.  
  1925. R$-            $@$1<@$w.$D>    if no host, then local (fully qual)
  1926.  
  1927. # add local domain if needed
  1928. R$+<@$=L>        $@$1<@$&2.$D>    if local net host, use local domain
  1929. R$+<@$=L.$=D>        $@$1<@$&2.$D>    if local net host, use local domain
  1930.  
  1931. # do relayed domain
  1932. R$*<@$=C>        $:$1<@$&2.CSNET>    add domain to csnet sites
  1933. R$*<@$+.$=R>        $@$1%$2.$3<@$&3>    if relayed domain, use relay
  1934.  
  1935. # ARPAize appropriate hosts
  1936. R$+<@$=X>        $@$1<@$2.ARPA>        if uucp and arpa, use arpa
  1937.  
  1938. # route known UUCP hosts
  1939. R$+<@$=P>        $:$>29$&2!$1        if unknown but UUCP, use route
  1940. R$+<@$=P.UUCP>        $:$>29$&2!$1        if known but UUCP, use route
  1941.  
  1942. # add ARPA domain to domainless hosts
  1943.  
  1944. R$*<@$->        $@$1<@$2.ARPA>        If still domainless, then ARPA
  1945. R$*<$*>            $@$1<$2>        Return if canonical
  1946.  
  1947. R$*!!$*            $1!$2            Eliminate all double-bangs
  1948. R$-!$+            $@$2<@$1.UUCP>        convert non-can. UUCP to canon.
  1949.  
  1950. # S29 - recursively remove all local host names with either the proper
  1951. #    domain, an ARPA domain, or no domain.
  1952.  
  1953. S29
  1954.  
  1955. R$+@$=w.$=D        $@$>29$1
  1956. R$+@$=w.$D        $@$>29$1
  1957. R$+@$=w            $@$>29$1
  1958.  
  1959. R$+%$=w.$=D        $@$>29$1
  1960. R$+%$=w.$D        $@$>29$1
  1961. R$+%$=w            $@$>29$1
  1962.  
  1963. R$=w!$+            $@$>29$2
  1964.  
  1965. # convert any non-canonical to canonical
  1966.  
  1967. S28
  1968. R$*<@$*>        $@$1<@$2>        Already canonical, accept
  1969.  
  1970. R$*%$*            $1@$2            Convert all %'s to @'s
  1971. R$*@$*@$*        $1%$2@$3        Convert all but last back
  1972.  
  1973. R$*@$*            $@$1<@$2>        make into canonical
  1974. //go.sysin dd *
  1975. if [ `wc -c < mimsy.cf` != 13094 ]; then
  1976.     made=FALSE
  1977.     /bin/echo 'error transmitting "mimsy.cf" --'
  1978.     /bin/echo 'length should be 13094, not' `wc -c < mimsy.cf`
  1979. else
  1980.     made=TRUE
  1981. fi
  1982. if [ $made = TRUE ]; then
  1983.     /bin/chmod 644 mimsy.cf
  1984.     /bin/echo -n '    '; /bin/ls -ld mimsy.cf
  1985. fi
  1986. /bin/echo 'Extracting names'
  1987. sed 's/^X//' <<'//go.sysin dd *' >names
  1988. #! /bin/csh -f
  1989. #
  1990. # names - generate a list of aliases on the current host for addresses
  1991. #    that are on the local network but NOT on the current host.
  1992. #    these will be used by the mail system so that any addresses on
  1993. #    the local network appear to be addresses local to the current
  1994. #    host.
  1995. #
  1996. #    method: all addresses on the local net are processed thru
  1997. #      getting their aliases and passwd files.
  1998. #      aliases on any machine take priority over accounts anywhere.
  1999. #      current machine takes priority over other machines.
  2000. #
  2001. # temp files:    uniq - unique names in list (for eliminating repeats)
  2002. #        list - generated list
  2003. #        tmp1,2 - intermediate processing files
  2004. #
  2005. # set the machines on the local network here (in order of priority).
  2006. set locals = (mimsy tove gymble gyre brilig)
  2007. #
  2008. set uniq = /tmp/names.u.$$ list = /tmp/names.l.$$
  2009. set tmp1 = /tmp/names.1.$$ tmp2 = /tmp/names.2.$$
  2010. cp /dev/null $list
  2011. cp /dev/null $uniq
  2012. foreach file ( /usr/lib/aliases /etc/passwd )
  2013. # process current host addresses from $file first
  2014.     awk -F: '{print $1}' < $file | grep -v "#" | grep -v '^$' | \
  2015.         sort | uniq> $tmp1
  2016. # put current host addresses into uniq file ONLY.  That way they won't be
  2017. # generated from another machine, and the mail system will get them itself
  2018. # from local files.
  2019.     cat $tmp1 $uniq | sort -o $uniq
  2020.     foreach host ( $locals )
  2021.         set work = tmp/$host.$file:t
  2022.         rcp ${host}:${file} $work
  2023. # get name from file, ignoring comments and blank lines
  2024.         awk -F: '{print $1}' <$work | grep -v "#" | \
  2025.         grep -v '^$' | sort | uniq > $tmp1
  2026. # get only names that haven't already been used (i.e. $tmp1 - $uniq)
  2027.         comm -13 $uniq $tmp1 > $tmp2
  2028. # add new names to list with host, and to unique names list
  2029.         awk '{print $1 " " $1 "@'$host'" }' < $tmp2 >> $list
  2030.         cat $tmp2 $uniq | sort -o $uniq
  2031.     end
  2032. end
  2033. sort $list
  2034. rm -f $uniq $list $tmp1 $tmp2
  2035. //go.sysin dd *
  2036. if [ `wc -c < names` != 1834 ]; then
  2037.     made=FALSE
  2038.     /bin/echo 'error transmitting "names" --'
  2039.     /bin/echo 'length should be 1834, not' `wc -c < names`
  2040. else
  2041.     made=TRUE
  2042. fi
  2043. if [ $made = TRUE ]; then
  2044.     /bin/chmod 755 names
  2045.     /bin/echo -n '    '; /bin/ls -ld names
  2046. fi
  2047.  
  2048.