home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / unix / volume11 / smail3 / part03 < prev    next >
Text File  |  1987-09-21  |  48KB  |  2,206 lines

  1. Subject:  v11i071:  Smail, UUCP domain maielr, Part03/03
  2. Newsgroups: comp.sources.unix
  3. Sender: sources
  4. Approved: rs@uunet.UU.NET
  5.  
  6. Submitted-by: Larry Auton <clyde.ATT.COM!lda>
  7. Posting-number: Volume 11, Issue 71
  8. Archive-name: smail3/Part03
  9.  
  10. # This is a shell archive.  Remove anything before this line, then
  11. # unpack it by saving it in a file and typing "sh file".  (Files
  12. # unpacked will be owned by you and have default permissions.)
  13. #
  14. # This archive contains:
  15. # lcasep.c main.c make.cf.sh map.c misc.c mkfnames.sh nptx.c patchlevel
  16. # pathproc.sh pw.c resolve.c smail.prompt str.c svbinmail.c sysexits.h
  17. # template.cf
  18.  
  19. echo x - lcasep.c
  20. cat > "lcasep.c" << '//E*O*F lcasep.c//'
  21. /*
  22. ** convert the host name on a pathalias line to lower case
  23. */
  24.  
  25. #ifndef lint
  26. static char     *sccsid="@(#)lcasep.c    2.5 (smail) 9/15/87";
  27. #endif
  28.  
  29. #include <stdio.h>
  30. #include <ctype.h>
  31.  
  32. # define lower(c)         ( isupper(c) ? c-'A'+'a' : c )
  33.  
  34. void exit(), perror();
  35.  
  36. main(argc, argv)
  37. int argc;
  38. char *argv[];
  39. {
  40.     FILE *ifp, *ofp;
  41.     char buf[BUFSIZ];
  42.     register char *p;
  43.     int c;
  44.  
  45.     extern int optind;
  46.     extern char *optarg;
  47.  
  48.     ifp = stdin;
  49.     ofp = stdout;
  50.  
  51.     while((c = getopt(argc, argv, "f:o:")) != EOF) {
  52.         switch(c) {
  53.         case 'f':
  54.             if((ifp = fopen(optarg, "r")) == NULL) {
  55.                 (void) fprintf(stderr, "%s: can't open %s: ",
  56.                     argv[0], optarg);
  57.                 perror("");
  58.                 exit(1);
  59.             }
  60.             break;
  61.         case 'o':
  62.             if((ofp = fopen(optarg, "w")) == NULL) {
  63.                 (void) fprintf(stderr, "%s: can't open %s: ",
  64.                     argv[0], optarg);
  65.                 perror("");
  66.                 exit(1);
  67.             }
  68.             break;
  69.         default:
  70.             (void) fprintf(stderr,
  71.                 "usage: %s [-f file] [-o outfile]\n", argv[0]);
  72.             exit(1);
  73.             /* NOTREACHED */
  74.             break;
  75.         }
  76.     }
  77.  
  78.     while(fgets(buf, sizeof(buf), ifp) != NULL) {
  79.         for(p = buf; *p != '\t' && *p != '\0' ; p++) {
  80.             (void) fputc(lower(*p), ofp);
  81.         }
  82.         (void) fputs(p, ofp);
  83.     }
  84.     return(0);
  85. }
  86. //E*O*F lcasep.c//
  87.  
  88. echo x - main.c
  89. cat > "main.c" << '//E*O*F main.c//'
  90. /*
  91. **
  92. **  rmail/smail - UUCP mailer with automatic routing.
  93. **
  94. **  Christopher Seiwald        /+\
  95. **  chris@cbosgd.att.com    +\
  96. **  January, 1985        \+/
  97. **
  98. */
  99.  
  100. #ifndef lint
  101. static char     *sccsid="@(#)main.c    2.5 (smail) 9/15/87";
  102. #endif
  103.  
  104. /*
  105. **
  106. **  usage:      rmail [options] address...
  107. **        smail [options] address...
  108. **  options:
  109. **        -d         debug - verbose and don't invoke mailers.
  110. **        -v        verbose - just verbose.
  111. **        -A        print mapped addresses.  don't invoke mailers.
  112. **        -h hostname    set hostname 
  113. **        -H hostdomain    set hostdomain (default hostname.MYDOM)
  114. **        -p pathfile    path database filename
  115. **        -r        force routing of host!address
  116. **        -R        reroute even explicit path!user
  117. **        -l        user@domain goes to local mailer
  118. **        -L        all mail goes local
  119. **        -q number    mail queueing cost threshold
  120. **        -m number    limit on number of uux_noqueue jobs
  121. **        -u string    string of flags for uux
  122. **              -F address      name to substitute in From: line
  123. **        -a aliasfile    aliases filename (not used with SENDMAIL)
  124. **        -n namelist    list of full names for simple aliases
  125. */
  126.  
  127. #include    <stdio.h>
  128. #include    <ctype.h>
  129. #include    "defs.h"
  130.  
  131. int exitstat = 0;        /* exit status, set by resolve, deliver    */
  132.  
  133. enum edebug debug     = NO;    /* set by -d or -v option        */
  134. enum ehandle handle   = HANDLE;    /* which mail we can handle, see defs.h    */
  135. enum erouting routing = ROUTING;/* to route or not to route, see defs.h */
  136.  
  137. char hostname[SMLBUF]   = "";    /* set by -h, defaults in defs.h     */
  138. char hostdomain[SMLBUF] = "";    /* set by -H, defaults in defs.h     */
  139. char hostuucp[SMLBUF] = "";    /* built with hostname+".UUCP"         */
  140.  
  141. char *pathfile  = PATHS;    /* or set by -p             */
  142. char *uuxargs   = NULL;        /* or set by -u                */
  143.  
  144. char *aliasfile =
  145. #ifdef ALIAS
  146.         ALIAS;        /* or set by -a                */
  147. #else
  148.         NULL;
  149. #endif
  150.  
  151. char *fnlist    =
  152. #ifdef FULLNAME
  153.         FULLNAME;    /* or set by -n                */
  154. #else
  155.         NULL;
  156. #endif
  157.  
  158. int  queuecost  = QUEUECOST;    /* or set by -q                */
  159. char *from_addr = NULL;        /* or set by -F                */
  160. int  maxnoqueue = MAXNOQUEUE;    /* or set by -m                         */
  161.  
  162. int  getcost    = 
  163. #ifdef GETCOST
  164.         1;    /* get cost of path even if not routing */
  165. #else
  166.         0;
  167. #endif
  168.  
  169. char *spoolfile = NULL;        /* name of the file containing letter   */
  170. FILE *spoolfp;            /* file pointer to spoolfile        */
  171. int  spoolmaster = 0;        /* indicates 'control' of spoolfile     */
  172.  
  173. void spool();
  174.  
  175.  
  176. /*
  177. **
  178. **  rmail/smail: mail stdin letter to argv addresses.
  179. **
  180. **  After processing command line options and finding our host and domain 
  181. **  names, we map addresses into <host,user,form,cost> sets.  Then we deliver.
  182. **
  183. */
  184.  
  185. main(argc, argv)
  186. int argc;
  187. char *argv[];
  188. {
  189.     char *hostv[MAXARGS];        /* UUCP neighbor         */
  190.     char *userv[MAXARGS];        /* address given to host     */
  191.     int  costv[MAXARGS];        /* cost of resolved route    */
  192.     enum eform formv[MAXARGS];    /* invalid, local, or uucp     */
  193.     char *p;
  194.     int c;
  195.     int  printaddr  = 0;        /* or set by -A            */
  196.     int nargc;
  197.     char **nargv, **alias();
  198.  
  199.     char *optstr = "cdvArRlLH:h:p:u:q:a:n:m:f:F:";
  200.     extern char *optarg;
  201.     extern int optind;
  202.  
  203. /*
  204. **  see if we aren't invoked as rmail
  205. */
  206.     if((p = rindex(argv[0], '/')) == NULL) {
  207.         p = argv[0];
  208.     } else {
  209.         p++;
  210.     }
  211.  
  212.     if(*p != 'r' ) {
  213.         handle = ALL;
  214.     }
  215.  
  216. /*
  217. **  Process command line arguments
  218. */
  219.     while ((c = getopt(argc, argv, optstr)) != EOF) {
  220.         switch ( c ) {
  221.         case 'd': debug      = YES;         break;
  222.         case 'v': debug      = VERBOSE;     break; 
  223.         case 'A': printaddr  = 1;         break; 
  224.         case 'F': from_addr  = optarg;        break;
  225.         case 'r': routing    = ALWAYS;        break;
  226.         case 'R': routing    = REROUTE;        break;
  227.         case 'l': handle     = JUSTUUCP;    break;
  228.         case 'L': handle     = NONE;        break;
  229.         case 'f': spoolfile  = optarg;        break;
  230.         case 'p': pathfile   = optarg;         break;
  231.         case 'u': uuxargs    = optarg;         break;
  232.         case 'a': aliasfile  = optarg;         break;
  233.         case 'n': fnlist     = optarg;         break;
  234.         case 'H': (void) strcpy(hostdomain, optarg);    break;
  235.         case 'h': (void) strcpy(hostname, optarg);     break;
  236.         case 'm': if(isdigit(*optarg)) {
  237.                   maxnoqueue = atoi(optarg);
  238.               }
  239.               break;
  240.         case 'c': getcost     = 1;        break;
  241.         case 'q': if(isdigit(*optarg)) {
  242.                   queuecost = atoi(optarg);
  243.               }
  244.               break;
  245.         default:
  246.             error( EX_USAGE, "valid flags are %s\n", optstr);
  247.         }
  248.     }
  249.     if ( argc <= optind ) {
  250.         error( EX_USAGE, "usage: %s [flags] address...\n", argv[0] );
  251.     }
  252.  
  253. /*
  254. **  Get our default hostname and hostdomain.
  255. */
  256.     getmynames();
  257.  
  258. /*
  259. **  Spool the letter in a temporary file.
  260. */
  261.     nargc = argc - optind;
  262.     if(printaddr == 0) {
  263.         spool(nargc, &argv[optind]);
  264.     }
  265.  
  266. /*
  267. ** Do aliasing and fullname resolution
  268. */
  269.     nargv = alias(&nargc, &argv[optind]);
  270.  
  271. /*
  272. **  Map argv addresses to <host, user, form, cost>.
  273. */
  274.     map(nargc, nargv, hostv, userv, formv, costv);
  275. /*
  276. **  If all we want it mapped addresses, print them and exit.
  277. */
  278.     if(printaddr) {
  279.         int i;
  280.         char abuf[SMLBUF];
  281.         for(i=nargc-1; i >= 0; i--) {
  282.             if(formv[i] == ERROR) {
  283.                 (void) strcpy(abuf, nargv[i]);
  284.             } else {
  285.                 build(hostv[i], userv[i], formv[i], abuf);
  286.             }
  287.             (void) fputs(abuf, stdout);
  288.             if(i != 0) (void) putchar(' ');
  289.         }
  290.         (void) putchar('\n');
  291.         exit(0);
  292.     }
  293. /*
  294. **  Deliver.
  295. */
  296.     deliver(nargc, hostv, userv, formv, costv);
  297. /*
  298. **  Exitstat was set if any resolve or deliver failed, otherwise 0.
  299. */
  300.     return( exitstat );
  301. }
  302. //E*O*F main.c//
  303.  
  304. echo x - make.cf.sh
  305. cat > "make.cf.sh" << '//E*O*F make.cf.sh//'
  306. #! /bin/sh
  307. #
  308. # @(#)make.cf.sh    2.5 (smail) 9/15/87
  309. #
  310. cat <<!EOM!
  311. This script will prompt you for the automatically configurable parameters
  312. in the stock version of the sendmail configuration file.  Naturally, any
  313. local extensions will have to be added manually.
  314.  
  315. Clyde is a VAX running AT&T System V Release 2.0, with a port of sendmail.
  316. Clyde is a gateway for the domain .att.com.
  317.  
  318. Below is a trace of the session that
  319. configured the sendmail.cf on clyde.ATT.COM:
  320. ===
  321.  
  322. !EOM!
  323.  
  324. echo "press return to continue"; read foo
  325.  
  326. cat <<!EOM!
  327. Enter Date (MM-DD-YY):
  328. 06-24-86
  329. Enter This Host's Name:
  330. clyde
  331. Enter This Host's Official Domain:
  332. ATT.COM
  333. Enter Any Equivalent Domain Classes:
  334. ATT
  335. Enter Any Domains For Which This Host Is An Authority:
  336. ATT.UUCP
  337. Does This Host Have SMTP Connections (y/n)?
  338. no
  339. Enter Full Path to Executable That Will Provide Local Mail Delivery:
  340. /bin/lmail
  341. Is /bin/lmail A Berkeley Mailer [i.e., use -r to specify sender] (y/n)?
  342. no
  343. Will This Host Act As A Gateway Between Domains (y/n)?
  344. yes
  345. Are subdomains beneath this hosts' domain to be hidden (y/n)?
  346. yes
  347. ===
  348. !EOM!
  349. # get date of configuration
  350. CF_DATE=`/bin/sh ./smail.prompt string "Enter Date (MM-DD-YY):"`
  351.  
  352. # get host name
  353. CF_HOST=`/bin/sh ./smail.prompt string "Enter This Host's Name:"`
  354.  
  355. # get host domain
  356. CF_DOMAIN=`/bin/sh ./smail.prompt string "Enter This Host's Official Domain:"`
  357.  
  358. # get domain classes
  359. CF_DCLASS=`/bin/sh ./smail.prompt string "Enter Any Equivalent Domain Classes:"`
  360.  
  361. # get domain authority
  362. CF_AUTHORITY=`/bin/sh ./smail.prompt string "Enter Any Domains For Which This Host Is An Authority:"`
  363.  
  364. CF_SMTP=`/bin/sh ./smail.prompt yesno "Does This Host Have SMTP Connections (y/n)?"`
  365. if test "$CF_SMTP" = "yes"
  366. then
  367.  
  368. #get list of local SMTP connections
  369.     CF_SMTP=`/bin/sh ./smail.prompt file "Enter Full Path to File that Contains List of SMTP Connections:"`
  370.  
  371.     CF_SMTP="FE$CF_SMTP %s"
  372. else
  373.     CF_SMTP=""
  374. fi
  375.  
  376. # get path to local delivery agent
  377. CF_LOCALMAIL=`/bin/sh ./smail.prompt file "Enter Full Path to Executable That Will Provide Local Mail Delivery:"`
  378.  
  379. CF_SYSTEM=`/bin/sh ./smail.prompt yesno "Is $CF_LOCALMAIL A Berkeley Mailer [i.e., use -r to specify sender] (y/n)?"`
  380. if test "$CF_SYSTEM" = "yes"
  381. then
  382.     CF_SVMAIL="#"
  383.     CF_BSMAIL=""
  384. else
  385.     CF_SVMAIL=""
  386.     CF_BSMAIL="#"
  387. fi
  388.  
  389. CF_GATEWAY=`/bin/sh ./smail.prompt yesno "Will This Host Act As A Gateway Between Domains(y/n)?"`
  390. if test "$CF_GATEWAY" = "yes"
  391. then
  392.     CF_GATEWAY=""
  393. else
  394.     CF_GATEWAY="#"
  395. fi
  396.  
  397. CF_HIDDENHOSTS=`/bin/sh ./smail.prompt yesno "Are subdomains beneath this hosts' domain to be hidden (y/n)?"`
  398. if test "$CF_HIDDENHOSTS" = "yes"
  399. then
  400.     CF_HIDDENHOSTS=""
  401. else
  402.     CF_HIDDENHOSTS="#"
  403. fi
  404.  
  405. sed     \
  406.     -e "s/CF_HOST/Dw$CF_HOST/" \
  407.     -e "s/CF_DOMAIN/DD$CF_DOMAIN/" \
  408.     -e "s/CF_AUTHORITY/DA$CF_AUTHORITY/" \
  409.     -e "s/CF_DCLASS/CDUUCP $CF_DCLASS/" \
  410.     -e "s;CF_SMTP;$CF_SMTP;" \
  411.     -e "s;CF_DATE;$CF_DATE;" \
  412.     -e "s;CF_LOCALMAIL;$CF_LOCALMAIL;" \
  413.     -e "s;CF_BSMAIL;$CF_BSMAIL;" \
  414.     -e "s;CF_SVMAIL;$CF_SVMAIL;" \
  415.     -e "s;CF_GATEWAY;$CF_GATEWAY;" \
  416.     -e "s;CF_HIDDENHOSTS;$CF_HIDDENHOSTS;" \
  417.     template.cf > sendmail.cf
  418. //E*O*F make.cf.sh//
  419.  
  420. echo x - map.c
  421. cat > "map.c" << '//E*O*F map.c//'
  422. #ifndef lint
  423. static char     *sccsid="@(#)map.c    2.5 (smail) 9/15/87";
  424. #endif
  425.  
  426. # include    <stdio.h>
  427. # include    <sys/types.h>
  428. # include    "defs.h"
  429.  
  430. extern int queuecost;
  431.  
  432. /*
  433. **
  434. **  map(): map addresses into <host, user, form, cost> sets.
  435. **
  436. **  Calls resolve() for each address of argv.  The result is hostv and 
  437. **  userv arrays (pointing into buffers userz and hostz), and formv array.
  438. **
  439. */
  440.  
  441. map(argc, argv, hostv, userv, formv, costv)
  442. int argc;                /* address count         */
  443. char **argv;                /* address vector         */
  444. char *hostv[];                /* remote host vector         */
  445. char *userv[];                /* user name vector         */
  446. enum eform formv[];            /* address format vector     */
  447. int costv[];                /* cost vector             */
  448. {
  449.     int i, cost;
  450.     enum eform resolve();
  451.     char *c;
  452.     static char userbuf[BIGBUF], *userz;
  453.     static char hostbuf[BIGBUF], *hostz;
  454.  
  455.     userz = userbuf;
  456.     hostz = hostbuf;
  457.  
  458.     for( i=0; i<argc; i++ ) {
  459. #ifdef DEFQUEUE
  460.         cost = queuecost+1;        /* default is queueing */
  461. #else
  462.         cost = queuecost-1;        /* default is no queueing */
  463. #endif
  464.         userv[i] = userz;        /* put results here */
  465.         hostv[i] = hostz;
  466.         if ( **argv == '(' ) {        /* strip () */
  467.             ++*argv;
  468.             c = index( *argv, ')' );
  469.             if (c)
  470.                 *c = '\0';
  471.         }
  472.                         /* here it comes! */
  473.         formv[i] = resolve(*argv++, hostz, userz, &cost);
  474.         costv[i] = cost;
  475.         userz += strlen( userz ) + 1;    /* skip past \0 */
  476.         hostz += strlen( hostz ) + 1;
  477.     }
  478. }
  479. //E*O*F map.c//
  480.  
  481. echo x - misc.c
  482. cat > "misc.c" << '//E*O*F misc.c//'
  483.  
  484. /*
  485. **  Miscellaneous support functions for smail/rmail
  486. */
  487.  
  488. #ifndef lint
  489. static char     *sccsid="@(#)misc.c    2.5 (smail) 9/15/87";
  490. #endif
  491.  
  492. # include    <stdio.h>
  493. # include    <sys/types.h>
  494. # include    <ctype.h>
  495. # include    "defs.h"
  496. #ifdef BSD
  497. # include    <sys/time.h>
  498. # include    <sys/timeb.h>
  499. #else
  500. # include    <time.h>
  501. # include    <sys/utsname.h>
  502. #endif
  503.  
  504. extern int  exitstat;        /* set if a forked mailer fails */
  505. extern enum edebug debug;    /* how verbose we are         */ 
  506. extern enum ehandle handle;    /* what we handle        */
  507. extern char *uuxargs;        /* arguments given to uux       */
  508. extern int  queuecost;        /* threshold for queueing mail  */
  509. extern int  maxnoqueue;        /* max number of uucico's       */
  510. extern enum erouting routing;    /* when to route addresses    */
  511. extern char hostdomain[];    /* */
  512. extern char hostname[];        /* */
  513. extern char hostuucp[];        /* */
  514. extern char *pathfile;        /* location of path database    */
  515. extern char *spoolfile;        /* file name of spooled message */
  516. extern FILE *spoolfp;        /* file ptr  to spooled message */
  517. extern int spoolmaster;        /* set if creator of spoolfile  */
  518.  
  519. extern struct tm *localtime();
  520.  
  521. struct tm *gmt, *loc;        /* GMT and local time structure    */
  522. time_t now;            /* current system time        */
  523. char nows[50];            /* time in ctime format        */
  524. char arpanows[50];        /* time in arpa format        */
  525.  
  526. # ifdef LOG
  527. void
  528. log(command, from, size)
  529. char *command, *from;
  530. long size;
  531. {
  532.     FILE *fd;
  533.     char *logtime, tbuf[50];
  534.     int cmask;
  535.  
  536.     logtime = strcpy(tbuf, nows);
  537.     logtime[16] = '\0';
  538.     logtime += 4;
  539.  
  540.     cmask = umask(0);
  541.     fd = fopen(LOG, "a");
  542.     (void) umask(cmask);
  543.  
  544.     if (fd != NULL) {
  545.         (void) fprintf(fd, "%s\t%ld\t%s\t%s\n",
  546.             logtime, size, from, command);
  547.         (void) fclose(fd);
  548.     }
  549. }
  550. # endif
  551.  
  552. # ifdef RECORD
  553. FILE *
  554. record(command, from, size)
  555. char *command, *from;
  556. long size;
  557. {
  558.     FILE *fd;
  559.     char *logtime, buf[SMLBUF];
  560.     int cmask;
  561.  
  562.     logtime = strcpy(buf, nows);
  563.     logtime[16] = 0;
  564.     logtime += 4;
  565.  
  566.     cmask = umask(0);
  567.     fd = fopen(RECORD, "a");
  568.     (void) umask(cmask);
  569.  
  570.     if (fd != NULL) {
  571.         (void) fprintf(fd, "%s: %s, from %s, %ld bytes\n", 
  572.             logtime, command, from, size);
  573.     }
  574.     while(fgets(buf, sizeof(buf), spoolfp) != NULL) {
  575.         (void) fputs(buf, fd);
  576.     }
  577.     (void) fclose(fd);
  578. }
  579. # endif
  580.  
  581.  
  582. setdates()
  583. {
  584.     time_t time();
  585.     struct tm *gmtime();
  586.     char *ctime(), *arpadate();
  587.  
  588.     (void) time(&now);
  589.     (void) strcpy(nows, ctime(&now));
  590.     gmt = gmtime(&now);
  591.     loc = localtime(&now);
  592.     (void) strcpy(arpanows, arpadate(nows));
  593. }
  594.  
  595. /*
  596. **  Note: This routine was taken from sendmail
  597. **
  598. **  ARPADATE -- Create date in ARPANET format
  599. **
  600. **    Parameters:
  601. **        ud -- unix style date string.  if NULL, one is created.
  602. **
  603. **    Returns:
  604. **        pointer to an ARPANET date field
  605. **
  606. **    Side Effects:
  607. **        none
  608. **
  609. **    WARNING:
  610. **        date is stored in a local buffer -- subsequent
  611. **        calls will overwrite.
  612. **
  613. **    Bugs:
  614. **        Timezone is computed from local time, rather than
  615. **        from whereever (and whenever) the message was sent.
  616. **        To do better is very hard.
  617. **
  618. **        Some sites are now inserting the timezone into the
  619. **        local date.  This routine should figure out what
  620. **        the format is and work appropriately.
  621. */
  622.  
  623. char *
  624. arpadate(ud)
  625.     register char *ud;
  626. {
  627.     register char *p;
  628.     register char *q;
  629.     static char b[40];
  630.     extern char *ctime();
  631.     register int i;
  632. #ifndef BSD
  633.     extern char *tzname[];
  634.     time_t t, time();
  635. #else
  636.     /* V7 and 4BSD */
  637.     struct timeb t;
  638.     extern struct timeb *ftime();
  639.     extern char *timezone();
  640. #endif
  641.  
  642.     /*
  643.     **  Get current time.
  644.     **    This will be used if a null argument is passed and
  645.     **    to resolve the timezone.
  646.     */
  647.  
  648. #ifndef BSD
  649.     (void) time(&t);
  650.     if (ud == NULL)
  651.         ud = ctime(&t);
  652. #else
  653.     /* V7 or 4BSD */
  654.     ftime(&t);
  655.     if (ud == NULL)
  656.         ud = ctime(&t.time);
  657. #endif
  658.  
  659.     /*
  660.     **  Crack the UNIX date line in a singularly unoriginal way.
  661.     */
  662.  
  663.     q = b;
  664.  
  665.     p = &ud[8];        /* 16 */
  666.     if (*p == ' ')
  667.         p++;
  668.     else
  669.         *q++ = *p++;
  670.     *q++ = *p++;
  671.     *q++ = ' ';
  672.  
  673.     p = &ud[4];        /* Sep */
  674.     *q++ = *p++;
  675.     *q++ = *p++;
  676.     *q++ = *p++;
  677.     *q++ = ' ';
  678.  
  679.     p = &ud[22];        /* 1979 */
  680.     *q++ = *p++;
  681.     *q++ = *p++;
  682.     *q++ = ' ';
  683.  
  684.     p = &ud[11];        /* 01:03:52 */
  685.     for (i = 8; i > 0; i--)
  686.         *q++ = *p++;
  687.  
  688.                 /* -PST or -PDT */
  689. #ifndef BSD
  690.     p = tzname[localtime(&t)->tm_isdst];
  691. #else
  692.     p = timezone(t.timezone, localtime(&t.time)->tm_isdst);
  693. #endif
  694.     if (p[3] != '\0')
  695.     {
  696.         /* hours from GMT */
  697.         p += 3;
  698.         *q++ = *p++;
  699.         if (p[1] == ':')
  700.             *q++ = '0';
  701.         else
  702.             *q++ = *p++;
  703.         *q++ = *p++;
  704.         p++;        /* skip ``:'' */
  705.         *q++ = *p++;
  706.         *q++ = *p++;
  707.     }
  708.     else
  709.     {
  710.         *q++ = ' ';
  711.         *q++ = *p++;
  712.         *q++ = *p++;
  713.         *q++ = *p++;
  714.     }
  715.  
  716.     p = &ud[0];        /* Mon */
  717.     *q++ = ' ';
  718.     *q++ = '(';
  719.     *q++ = *p++;
  720.     *q++ = *p++;
  721.     *q++ = *p++;
  722.     *q++ = ')';
  723.  
  724.     *q = '\0';
  725.     return (b);
  726. }
  727.  
  728. /*
  729.  *    The user name "postmaster" must be accepted regardless of what
  730.  *    combination of upper and lower case is used.  This function is
  731.  *    used to convert all case variants of "postmaster" to all lower
  732.  *    case.  If the user name passed in is not "postmaster", it is
  733.  *    returned unchanged.
  734.  */
  735. char *
  736. postmaster(user)
  737. char *user;
  738. {
  739.     static char *pm = "postmaster";
  740.  
  741.     if(strcmpic(user, pm) == 0) {
  742.         return(pm);
  743.     } else {
  744.         return(user);
  745.     }
  746. }
  747.  
  748. /*
  749.  * Return 1 iff the string is "UUCP" (ignore case).
  750.  */
  751. isuucp(str)
  752. char *str;
  753. {
  754.     if(strcmpic(str, "UUCP") == 0) {
  755.         return(1);
  756.     } else {
  757.         return(0);
  758.     }
  759. }
  760.  
  761. /*
  762. ** sform(form) returns a pointer to a string that tells what 'form' means
  763. */
  764.  
  765. char *
  766. sform(form)
  767. enum eform form;
  768. {
  769.     if(form == ERROR)  return("ERROR");
  770.     if(form == LOCAL)  return("LOCAL");
  771.     if(form == DOMAIN) return("DOMAIN");
  772.     if(form == UUCP)   return("UUCP");
  773.     if(form == ROUTE)  return("ROUTE");
  774.     return("UNKNOWN");
  775. }
  776.  
  777. /*
  778. **
  779. **  getmynames(): what is my host name and host domain?
  780. **
  781. **  Hostname set by -h, failing that by #define HOSTNAME, failing
  782. **  that by gethostname() or uname().
  783. **  
  784. **  Hostdomain set by -h, failing that by #define HOSTDOMAIN,
  785. **  failing that as hostname.MYDOM, or as just hostname.
  786. **
  787. **  See defs.h for the inside story.
  788. **
  789. */
  790.  
  791. getmynames()
  792. {
  793. #ifdef HOSTNAME
  794.     if (!*hostname)
  795.         (void) strcpy(hostname, HOSTNAME);
  796. #endif
  797. #ifdef GETHOSTNAME
  798.     if (!*hostname)
  799.         gethostname(hostname, SMLBUF - 1);
  800. #endif
  801. #ifdef UNAME
  802.     if (!*hostname) {
  803.         struct utsname site;
  804.  
  805.         if (uname(&site) < 0)
  806.             error(EX_SOFTWARE, "uname() call failed", 0);
  807.         (void) strcpy(hostname, site.nodename);
  808.     }
  809. #endif
  810.     if (!*hostname)
  811.         error(EX_SOFTWARE, "can't determine hostname.\n", 0);
  812. #ifdef HOSTDOMAIN
  813.     if (!*hostdomain)
  814.         (void) strcpy(hostdomain, HOSTDOMAIN);
  815. #endif
  816. #ifdef MYDOM
  817.     if (!*hostdomain)
  818.         (void) strcat(strcpy(hostdomain, hostname), MYDOM);
  819. #endif
  820.     if (!*hostdomain)
  821.         (void) strcpy(hostdomain, hostname);
  822.  
  823.     (void) strcat(strcpy(hostuucp, hostname), ".UUCP");
  824. }
  825. //E*O*F misc.c//
  826.  
  827. echo x - mkfnames.sh
  828. cat > "mkfnames.sh" << '//E*O*F mkfnames.sh//'
  829. #! /bin/sh
  830. #
  831. # @(#)mkfnames.sh    2.5 (smail) 9/15/87
  832. #
  833. if test $# = 0
  834. then
  835.     sed 's/\(.*\):.*:.*:.*:\(.*\):.*:.*/\1    \2/' /etc/passwd
  836. else
  837.     cat $*
  838. fi    |    # at this point, we have a list of login\tFull Name pairs
  839. nptx    |
  840. lcasep    |
  841. sort -u +0 -1
  842. //E*O*F mkfnames.sh//
  843.  
  844. echo x - nptx.c
  845. cat > "nptx.c" << '//E*O*F nptx.c//'
  846. #ifndef lint
  847. static char *sccsid = "@(#)nptx.c    2.5 (smail) 9/15/87";
  848. #endif
  849.  
  850. #include <stdio.h>
  851. #include <sys/types.h>
  852. #include <sys/stat.h>
  853. #include <pwd.h>
  854. #include "defs.h"
  855. #include <ctype.h>
  856.  
  857. char *malloc(), *index(), *fullname();
  858. void nptx(), free(), dotspace();
  859.  
  860. enum edebug debug;    /* not used by nptx */
  861. char *fnlist = NULL;    /* not used by nptx */
  862.  
  863. main()
  864. {
  865.     int i;
  866.     char buf[SMLBUF], *p, *name, *last, *nick, *ctmp;
  867.  
  868.     while(gets(buf) != NULL) {
  869.         /*  line should be in form
  870.         **
  871.         **  login    First Last
  872.         ** or
  873.         **  login    First Last(Nickname)
  874.         **
  875.         */
  876.         if((p = index(buf, '\t')) == NULL) {
  877.             (void) fprintf(stderr, "format error: %s\n", buf);
  878.             continue;
  879.         }
  880.  
  881.         *p++ = '\0';
  882.         name = fullname(p);
  883.         dotspace(name);
  884.  
  885.         if (last = rindex(name, '.')) {
  886.             last++;
  887.         } else {
  888.             last = NULL;
  889.         }
  890.  
  891.         if ((nick = index(p, '(')) != NULL) {
  892.             nick++;
  893.             if ((ctmp = index(nick, ')')) == NULL) {
  894.                 nick = NULL;
  895.             } else {
  896.                 *ctmp = '\0';
  897.             }
  898.         }
  899.  
  900.         nptx(buf, name);
  901.  
  902.         if((last != NULL) && (nick != NULL)) {
  903.             i=strlen(nick) + strlen(last) + 2;
  904.             if((name = malloc(i)) != NULL) {
  905.                 (void) strcpy(name, nick);
  906.                 (void) strcat(name, ".");
  907.                 (void) strcat(name, last);
  908.                 dotspace(name);
  909.                 nptx(buf, name);
  910.                 free(name);
  911.             }
  912.         }
  913.     }
  914.     return(0);
  915. }
  916.  
  917. void
  918. dotspace(s)
  919. char *s;
  920. {
  921.     register char *p, *t;
  922.  
  923.     /* turn whitespace to '.' */
  924.     for(p = s; *p != '\0'; p++) {
  925.         if((*p == ' ') || (*p == '\t')) {
  926.             *p = '.';
  927.         }
  928.     }
  929.  
  930.     /* elide leading '.'s */
  931.     for(p = s; *p == '.' ; p++)
  932.         ;
  933.  
  934.     /* elide mulitple '.'s and all "'"s */
  935.     for(t = s; *p != '\0'; p++, t++) {
  936.         *t = *p;
  937.  
  938.         if(*t == '\'') {
  939.             t--;
  940.             continue;
  941.         }
  942.  
  943.         if(*p == '.') {
  944.             while(*(++p) == '.')
  945.                 ;
  946.             p--;
  947.         }
  948.     }
  949.     *t = '\0';
  950.  
  951.     /* elide trailing '.' */
  952.     if((t > s) && (*(--t) == '.')) *t = '\0';
  953. }
  954.  
  955. void
  956. nptx(login, name)
  957. char *login, *name;
  958. {
  959.     int i,j,k,N,lim,mask;
  960.     int ii,ji,ki,Ni,limi,maski;
  961.     char nl[11][100], il[11][100];
  962.     char *pi, *p, *rindex();
  963.     char buf[100];
  964.     char bufi[100];
  965.  
  966.     if((name == NULL) || (*name == '\0')) {
  967.         return;
  968.     }
  969.  
  970.     for(i=0; i < 10; i++) {
  971.         if((p = rindex(name, '.')) == NULL) break;
  972.         (void) strcpy(nl[i], p+1);
  973.         *p = NULL;
  974.     }
  975.     (void) strcpy(nl[i], name);
  976.  
  977.     while((strcmpic(nl[i], "Mr"  ) == 0)
  978.      ||   (strcmpic(nl[i], "Dr"  ) == 0)
  979.      ||   (strcmpic(nl[i], "Mrs" ) == 0)
  980.      ||   (strcmpic(nl[i], "Miss") == 0)
  981.      ||   (strcmpic(nl[i], "Ms"  ) == 0)) {
  982.         i--;
  983.     }
  984.  
  985.     while((strcmpic(nl[0], "Jr") == 0)
  986.      ||   (strcmpic(nl[0], "Sr") == 0)) {
  987.         for(j=0; j < i; j++) {
  988.             (void) strcpy(nl[j], nl[j+1]);
  989.         }
  990.         i--;
  991.     }
  992.  
  993.     N = i;
  994.     lim = 1 << (N+1);
  995.     for(mask = 1 << N ; mask < lim ; mask++) {
  996.         buf[0] = '\0';
  997.         for(j = 1, k = N; j < lim; j <<=1, k--) {
  998.             if(j & mask) {
  999.                 (void) strcat(buf, nl[k]);
  1000.                 (void) strcat(buf, ".");
  1001.             }
  1002.         }
  1003.         if((p = rindex(buf, '.')) != NULL) {
  1004.             *p = '\0';
  1005.         }
  1006.  
  1007.         for(ii=0; ii < 10; ii++) {
  1008.             if((pi = rindex(buf, '.')) == NULL) break;
  1009.             (void) strcpy(il[ii], pi+1);
  1010.             *pi = NULL;
  1011.         }
  1012.         (void) strcpy(il[ii], buf);
  1013.         Ni = ii;
  1014.         limi = 1 << (Ni+1);
  1015.         for(maski = 1 << Ni /* 0 */ ; maski < limi ; maski++) {
  1016.             bufi[0] = '\0';
  1017.             for(ji = 1, ki = Ni; ji < limi; ji <<=1, ki--) {
  1018.                 if(ji & maski) {
  1019.                     (void) strcat(bufi, il[ki]);
  1020.                 } else {
  1021.                     char init[3];
  1022.                     init[0] = il[ki][0];
  1023.                     init[1] = '\0';
  1024.                     (void) strcat(bufi, init);
  1025.                 }
  1026.                 (void) strcat(bufi, ".");
  1027.             }
  1028.             if((pi = rindex(bufi, '.')) != NULL) {
  1029.                 *pi = '\0';
  1030.             }
  1031. #ifdef DOT_REQD
  1032.             if(index(bufi, '.') == NULL) {
  1033.                 continue;
  1034.             }
  1035. #endif /* DOT_REQD */
  1036.             (void) printf("%s\t%s\n",bufi, login); /* */
  1037.         }
  1038.     }
  1039. }
  1040. //E*O*F nptx.c//
  1041.  
  1042. echo x - patchlevel
  1043. cat > "patchlevel" << '//E*O*F patchlevel//'
  1044. Patch #: 00
  1045. //E*O*F patchlevel//
  1046.  
  1047. echo x - pathproc.sh
  1048. cat > "pathproc.sh" << '//E*O*F pathproc.sh//'
  1049. #
  1050. #    @(#)pathproc.sh    2.5 (smail) 9/15/87
  1051. #
  1052. # This script will do all that's necessary for
  1053. # transforming the output of pathalias -f into
  1054. # the format of a 'paths' file for smail.
  1055. #
  1056. # format of the pathalias -f output is
  1057. # cost    host    route
  1058. #
  1059. # format of a 'paths' file for smail is
  1060. # host    route    first_hop_cost
  1061. #
  1062. # move cost field to end of line
  1063. #
  1064. sed 's/\(.*\)    \(.*\)    \(.*\)/\2    \3    \1/'|
  1065. #
  1066. # convert target domain/host to lower case
  1067. #
  1068. lcasep |
  1069. #
  1070. # sort the stream
  1071. #
  1072. sort
  1073. //E*O*F pathproc.sh//
  1074.  
  1075. echo x - pw.c
  1076. cat > "pw.c" << '//E*O*F pw.c//'
  1077. #ifndef lint
  1078. static char *sccsid = "@(#)pw.c    2.5 (smail) 9/15/87";
  1079. #endif
  1080.  
  1081. #include <stdio.h>
  1082. #include <sys/types.h>
  1083. #include <sys/stat.h>
  1084. #include <pwd.h>
  1085. #include "defs.h"
  1086. #include <ctype.h>
  1087.  
  1088. char *malloc();
  1089. void free();
  1090.  
  1091. typedef struct pw_node pwlist;
  1092.  
  1093. struct pw_node {
  1094.     char *lname;            /* login name */
  1095.     char *fname;            /* full name  */
  1096.     int  uid;            /* user-id    */
  1097.     char *home;            /* login name */
  1098.     pwlist *vlink;            /* link to next item */
  1099. };
  1100.  
  1101. pwlist *pwhead;        /* head of linked list */
  1102. pwlist *pwparse();    /* head of linked list */
  1103.  
  1104. #define PNULL    ((pwlist *) 0)
  1105.  
  1106. char *
  1107. pwfnam(user)
  1108. char *user;
  1109. {
  1110.     pwlist *f;
  1111.  
  1112.     /*
  1113.     ** check for previously cached user
  1114.     */
  1115.  
  1116.     for(f=pwhead; f != NULL; f=f->vlink) {
  1117.         if(strcmp(user, f->lname) == 0) {
  1118.             return(f->fname);
  1119.         }
  1120.     }
  1121.     /*
  1122.     ** not found parse the password file
  1123.     */
  1124.  
  1125.     while((f=pwparse()) != PNULL) {
  1126.         if(strcmp(user, f->lname) == 0) {
  1127.             return(f->fname);
  1128.         }
  1129.     }
  1130.     return(NULL);
  1131. }
  1132.  
  1133. char *
  1134. pwuid(uid)
  1135. int uid;
  1136. {
  1137.     pwlist *f;
  1138.  
  1139.     /*
  1140.     ** check for previously cached user
  1141.     */
  1142.  
  1143.     for(f=pwhead; f != NULL; f=f->vlink) {
  1144.         if(uid == f->uid) {
  1145.             return(f->lname);
  1146.         }
  1147.     }
  1148.     /*
  1149.     ** not found parse the password file
  1150.     */
  1151.  
  1152.     while((f=pwparse()) != PNULL) {
  1153.         if(uid == f->uid) {
  1154.             return(f->lname);
  1155.         }
  1156.     }
  1157.     return(NULL);
  1158. }
  1159.  
  1160. #ifndef SENDMAIL
  1161. char *
  1162. tilde(user)
  1163. char *user;
  1164. {
  1165.     pwlist *f;
  1166.  
  1167.     /*
  1168.     ** check for previously cached user
  1169.     */
  1170.  
  1171.     for(f=pwhead; f != NULL; f=f->vlink) {
  1172.         if(strcmp(user, f->lname) == 0) {
  1173.             return(f->home);
  1174.         }
  1175.     }
  1176.     /*
  1177.     ** not found parse the password file
  1178.     */
  1179.  
  1180.     while((f=pwparse()) != PNULL) {
  1181.         if(strcmp(user, f->lname) == 0) {
  1182.             return(f->home);
  1183.         }
  1184.     }
  1185.     return(NULL);
  1186. }
  1187. #endif /* not SENDMAIL */
  1188.  
  1189. char *
  1190. fullname(gecos)
  1191. char *gecos;
  1192. {
  1193.     static char fname[SMLBUF];
  1194.     register char *cend;
  1195.  
  1196.     (void) strcpy(fname, gecos);
  1197.     if (cend = index(fname, ','))
  1198.         *cend = '\0';
  1199.     if (cend = index(fname, '('))
  1200.         *cend = '\0';
  1201.     /*
  1202.     ** Skip USG-style 0000-Name nonsense if necessary.
  1203.     */
  1204.     if (isdigit(*(cend = fname))) {
  1205.         if ((cend = index(fname, '-')) != NULL)
  1206.             cend++;
  1207.         else
  1208.             /*
  1209.             ** There was no `-' following digits.
  1210.             */
  1211.             cend = fname;
  1212.     }
  1213.     return (cend);
  1214. }
  1215.  
  1216. pwlist *
  1217. pwparse()
  1218. {
  1219.     pwlist *f;
  1220.     char *p, *name;
  1221.     struct passwd *pwent, *getpwent();
  1222.     unsigned int i;
  1223.     static int pw_eof = 0;
  1224.  
  1225.     if((pw_eof == 1)
  1226.     || ((pwent = getpwent()) == (struct passwd *) NULL)) {
  1227.         pw_eof = 1;
  1228.         return(PNULL);
  1229.     }
  1230.     /*
  1231.     ** Get an entry from the password file.
  1232.     ** Parse relevant strings.
  1233.     */
  1234.     f = (pwlist *) malloc(sizeof(pwlist));
  1235.     if(f == PNULL) return(PNULL);
  1236.  
  1237.     f->vlink = pwhead;
  1238.     pwhead   = f;
  1239.     f->uid   = pwent->pw_uid;
  1240.  
  1241.     i=strlen(pwent->pw_name)+1;
  1242.     p = malloc(i);
  1243.     if(p == NULL) return(PNULL);
  1244.     f->lname = strcpy(p, pwent->pw_name);
  1245.  
  1246.     i=strlen(pwent->pw_dir)+1;
  1247.     p = malloc(i);
  1248.     if(p == NULL) return(PNULL);
  1249.     f->home  = strcpy(p, pwent->pw_dir);
  1250.  
  1251.     name = fullname(pwent->pw_gecos);
  1252.     i=strlen(name)+1;
  1253.     p = malloc(i);
  1254.     if(p == NULL) return(PNULL);
  1255.     f->fname = strcpy(p, name);
  1256.     return(f);
  1257. }
  1258.  
  1259. #ifdef FULLNAME
  1260. /*
  1261. ** Resolve a full name to a login name.
  1262. ** Not too much smarts here.
  1263. */
  1264.  
  1265. char *
  1266. res_fname(user)
  1267. register char *user;
  1268. {
  1269.     long pos, middle, hi, lo;
  1270.     static long pathlength = 0;
  1271.     register char *s;
  1272.     int c;
  1273.     static FILE *file;
  1274.     int flag;
  1275.     char namebuf[SMLBUF], *path;
  1276.     extern enum edebug debug;
  1277.     extern char *fnlist;
  1278.  
  1279.  
  1280.  
  1281. DEBUG("res_fname: looking for '%s'\n", user);
  1282.  
  1283.     if(pathlength == 0) {    /* open file on first use */
  1284.         if((file=fopen(fnlist, "r")) == NULL) {
  1285.             DEBUG( "can't access %s.\n", fnlist);
  1286.             pathlength = -1;
  1287.         } else {
  1288.             (void) fseek(file, 0L, 2);     /* find length */
  1289.             pathlength = ftell(file);
  1290.         }
  1291.     }
  1292.  
  1293.     if(pathlength == -1 ) return(NULL);
  1294.  
  1295.     lo = 0;
  1296.     hi = pathlength;
  1297.     path = namebuf;
  1298.  
  1299.     (void) strcpy( path, user );
  1300.     (void) strcat( path, "\t" );
  1301.  
  1302.     for( ;; ) {
  1303.         pos = middle = ( hi+lo+1 )/2;
  1304.         (void) fseek( file, pos, 0 );    /* find midpoint */
  1305.         if (pos != 0)        /* to beginning of next line */
  1306.             while( ( c=getc( file ) ) != EOF && c != '\n' );
  1307.         for( flag = 0, s = path; flag == 0; s++ ) { /* match??? */
  1308.             if ( *s == '\0' ) {
  1309.                 goto solved;
  1310.             }
  1311.             c = getc( file );
  1312.             flag = lower( c ) - lower( *s );
  1313.         } 
  1314.         if (lo >= middle)        /* failure? */
  1315.             return(NULL);
  1316.  
  1317.         if(c != EOF && flag < 0)    /* close window */
  1318.             lo = middle;
  1319.         else 
  1320.             hi = middle - 1;
  1321.     }
  1322. /* 
  1323. ** Now just copy the result.
  1324. */
  1325. solved:
  1326.     while(((c  = getc(file)) != EOF) && (c != '\t') && (c != '\n')) {
  1327.         *path++ = c;
  1328.     }
  1329.  
  1330.     if(path == namebuf) {    /* NULL alias field */
  1331.         return(NULL);
  1332.     }
  1333.  
  1334.     *path = '\0';
  1335.     if((path = malloc((unsigned) strlen(namebuf)+1)) == NULL) {
  1336.         return(NULL);    /* sorry, no memory */
  1337.     }
  1338.  
  1339.     (void) strcpy(path, namebuf);
  1340.     return(path);
  1341.  
  1342. }
  1343. #endif    /* FULLNAME */
  1344. //E*O*F pw.c//
  1345.  
  1346. echo x - resolve.c
  1347. cat > "resolve.c" << '//E*O*F resolve.c//'
  1348. /*
  1349. **
  1350. **  Resolve.c
  1351. **
  1352. **  Routes then resolves addresses into UUCP or LOCAL.
  1353. **
  1354. */
  1355. #ifndef lint
  1356. static char     *sccsid="@(#)resolve.c    2.5 (smail) 9/15/87";
  1357. #endif
  1358.  
  1359. #include    <ctype.h>
  1360. #include    <stdio.h>
  1361. #include    "defs.h"
  1362.  
  1363. extern int exitstat;        /* set if address doesn't resolve     */
  1364. extern enum ehandle handle;    /* what mail we can handle        */
  1365. extern enum edebug debug;    /* verbose and debug modes        */
  1366. extern enum erouting routing;    /* when to route addresses        */
  1367. extern char hostdomain[];    /* */
  1368. extern char hostname[];        /* */
  1369. extern char *pathfile;        /* location of path database        */
  1370. extern int getcost;        /* get path cost even if not routing    */
  1371.  
  1372. char *sform();
  1373.  
  1374. /*
  1375. **
  1376. **  rsvp(): how to resolve addresses.
  1377. **
  1378. **  After parsing an address into <form>, the resolved form will be
  1379. **  rsvp( form ).  If == ROUTE, we route the parsed address and parse again.
  1380. **
  1381. */
  1382.  
  1383. # define rsvp(a) table[(int)a][(int)handle]
  1384.  
  1385. enum eform table[5][3] = {
  1386. /*    all        justuucp    none */
  1387. {    ERROR,         ERROR,         ERROR },     /* error */
  1388. {    LOCAL,         LOCAL,         LOCAL },     /* local */
  1389. {    ROUTE,         LOCAL,         LOCAL },     /* domain */
  1390. {    UUCP,         UUCP,         LOCAL },     /* uucp */
  1391. {    ERROR,         ERROR,         ERROR }};    /* route */
  1392.  
  1393. /*
  1394. **
  1395. **  resolve(): resolve addresses to <host, user, form>.
  1396. **
  1397. **  This is a gnarly piece of code, but it does it all.  Each section 
  1398. **  is documented.
  1399. **
  1400. */
  1401.  
  1402. enum eform
  1403. resolve( address, domain, user , cost)
  1404. char *address;                /* the input address     */
  1405. char *domain;                /* the returned domain     */
  1406. char *user;                /* the returned user     */
  1407. int *cost;                /* the returned cost     */
  1408. {
  1409.     enum eform form;        /* the returned form    */ 
  1410.     enum eform parse();        /* to crack addresses    */
  1411.     int parts;            /* to ssplit addresses    */
  1412.     char *partv[MAXPATH];        /* "  "      "        */
  1413.     char temp[SMLBUF];        /* "  "      "        */
  1414.     int i;
  1415.         
  1416.  
  1417. /*
  1418. **  If we set REROUTE and are prepared to deliver UUCP mail, we split the 
  1419. **  address apart at !'s and try to resolve successively larger righthand 
  1420. **  substrings until we succeed.  Otherwise, we just resolve the whole thing 
  1421. **  once.
  1422. */
  1423.     if ((routing == REROUTE) && (rsvp( UUCP ) == UUCP)) {
  1424.         parts = ssplit( address, '!', partv );
  1425.     } else {
  1426.         parts = 1;
  1427.         partv[0] = address;
  1428.     }
  1429. /*
  1430. **  This for(i) loop selects successively larger
  1431. **  righthand substrings of the address.
  1432. */
  1433.     for( i = parts - 1; i >= 0; i-- ) {
  1434. /*
  1435. **  Parse the address.
  1436. */
  1437.         (void) strcpy( temp, partv[i] );
  1438.         form = parse( temp, domain, user );
  1439.  
  1440. DEBUG("resolve: parse address '%s' = '%s' @ '%s' (%s)\n",
  1441.     temp,user,domain,sform(form));
  1442.  
  1443. /*
  1444. **  If we are looking at a substring (that's not the entire string)
  1445. **  which parses to a LOCAL address, we skip to the next larger substring.
  1446. */
  1447.         if((i != 0) && (form == LOCAL))
  1448.             continue;
  1449. /*
  1450. **  Routing, when required, is the next step.
  1451. **  We route the address if we have a ROUTE form
  1452. **  or if we have a UUCP form and we are told to
  1453. **  route ALWAYS or REROUTE (i.e., routing != JUSTDOMAIN)
  1454. */
  1455.         if((rsvp( form ) == ROUTE)
  1456.          ||((rsvp( form ) == UUCP) && (routing != JUSTDOMAIN ))) {
  1457.  
  1458.             int look_smart = 0;
  1459.  
  1460.             if((routing == REROUTE) && (i == 0)) {
  1461.                 look_smart = 1; /* last chance */
  1462.             }
  1463.  
  1464.             /* route() puts the new route in 'temp' */
  1465.             if(route(domain,user,look_smart,temp,cost) != EX_OK) {
  1466.                 continue;    /* If routing fails, try
  1467.                         /* next larger substring.
  1468.                         /* */
  1469.             }
  1470. /*
  1471. **  After routing, reparse the new route into domain and user. 
  1472. */
  1473.             form = parse( temp, domain, user );
  1474.  
  1475. DEBUG("resolve: parse route '%s' = '%s' @ '%s' (%s)\n",
  1476.     temp,user,domain,sform(form));
  1477.  
  1478.         } else if((getcost) && (rsvp(form) == UUCP)) {
  1479.             /* get the cost of the route
  1480.             ** even if we're not going route the mail.
  1481.             ** this allows smart decisions about using
  1482.             ** the -r flag to uux when we're not routing.
  1483.             */
  1484.             char junk[SMLBUF];
  1485.             if(route(domain,user,0,junk,cost) != EX_OK) {
  1486.                 continue;    /* If routing fails, try
  1487.                         /* next larger substring.
  1488.                         /* */
  1489.             }
  1490.         }
  1491.         break;    /* route is resolved */
  1492.     }
  1493. /*
  1494. **  For LOCAL mail in non-local format, we rewrite the full address into 
  1495. **  <user> and leave <domain> blank.
  1496. */
  1497.     if ((rsvp( form ) == LOCAL) && (form != LOCAL )) {
  1498.         build( domain, user, form, temp );
  1499.         (void) strcpy( user, temp );
  1500.         (void) strcpy( domain, "" );
  1501.         form = LOCAL;
  1502.     }
  1503. /*
  1504. **  If we were supposed to route an address but failed (form == ERROR), 
  1505. **  or after routing we are left with an address that still needs to
  1506. **  be routed (rsvp( form ) == ROUTE), complain.
  1507. */
  1508.     if ((form == ERROR) || (rsvp( form ) == ROUTE )) {
  1509.         exitstat = EX_NOHOST;
  1510.         ADVISE("resolve failed '%s' = '%s' @ '%s' (%s)\n",
  1511.             address, user, domain, sform(form));
  1512.         form = ERROR;
  1513.     } else {
  1514.         ADVISE("resolve '%s' = '%s' @ '%s' (%s)\n",
  1515.             address, user, domain, sform(form));
  1516.     }
  1517.     return ( form );
  1518. }
  1519.  
  1520. /*
  1521. **
  1522. **  route(): route domain, plug in user.
  1523. **
  1524. **  Less complicated than it looks.  Each section is documented.
  1525. **
  1526. */
  1527.  
  1528. route(domain, user, look_smart, result, cost)
  1529. char *domain;            /* domain or host name     */
  1530. char *user;            /* user name         */
  1531. int look_smart;            /* do we try to route through a smarter host? */
  1532. char *result;            /* output route     */
  1533. int *cost;            /* cost of output route */
  1534. {
  1535.     int    uucpdom = 0;
  1536.     int    domains, step;            /* to split domain    */
  1537.     char    *domainv[MAXDOMS];        /* "  "     "        */
  1538.     char    temp[SMLBUF], path[SMLBUF];
  1539.  
  1540. /*
  1541. **  Fully qualify the domain, and then strip the last (top level domain) 
  1542. **  component off, so that we look it up separately.
  1543. */
  1544.     temp[0] = '.';
  1545.     (void) strcpy(temp+1, domain );
  1546.  
  1547.     domains = ssplit( temp+1, '.', domainv );
  1548.  
  1549. /*
  1550. ** check target domain for the local host name and host domain.
  1551. ** if it matches, then skip the lookup in the database.
  1552. ** this prevents mail loops for cases where SMARTHOST is defined
  1553. ** in the routing table, but the local host is not.  It also is
  1554. ** a little faster when the local host is the target domain.
  1555. */
  1556.     if((strcmpic(domain, hostname) == 0)
  1557.     || (strcmpic(domain, hostdomain) == 0)) {
  1558.         step = 0;
  1559.         *cost = 0;
  1560.         (void) strcpy(path, "%s");
  1561. DEBUG("route: '%s' is local\n", domain);
  1562.         goto route_complete;
  1563.     }
  1564.  
  1565.     /* If the domain ends in .UUCP, trim that off. */
  1566.     if((domains > 0) && isuucp(domainv[domains-1])) {
  1567.         domains--;
  1568.         domainv[domains][-1] = '\0';
  1569.         uucpdom = 1;
  1570.     }
  1571. /*
  1572. **  Try to get the path for successive components of the domain.  
  1573. **  Example for osgd.cb.att.uucp:
  1574. **    osgd.cb.att
  1575. **    cb.att
  1576. **    att
  1577. **    uucp ( remember stripping top level? )
  1578. **    SMARTHOST
  1579. **  Returns with error if we find no path.
  1580. */
  1581.     for(step = 0; (step < domains); step++) {
  1582.         if((getpath(domainv[step]-1, path, cost) == EX_OK) /* w/ dot */
  1583.         || (getpath(domainv[step]  , path, cost) == EX_OK))/* no dot */
  1584.             break;
  1585.     }
  1586.  
  1587.     if(step == domains) {
  1588.     /*
  1589.     ** we've looked at each component of the domain without success
  1590.     */
  1591.         /*
  1592.         ** If domain is a UUCP address, look for a UUCP gateway.
  1593.         */
  1594.         if((uucpdom == 0) || (getpath(".UUCP", path, cost) != EX_OK)) {
  1595.             /*
  1596.             ** The domain not is a UUCP address, or we can't
  1597.             ** find a UUCP gateway.  If this is our last chance,
  1598.             ** look for a smarter host to deliver the mail.
  1599.             */
  1600.             if((look_smart == 0)
  1601.             || (getpath(SMARTHOST, path, cost) != EX_OK)) {
  1602.                 /*
  1603.                 ** All our efforts have been in vain.
  1604.                 ** Tell them the bad news.
  1605.                 */
  1606.                 DEBUG("route '%s' failed\n", domain);
  1607.                 return( EX_NOHOST );
  1608.             }
  1609.         }
  1610.     }
  1611.  
  1612. route_complete:
  1613.  
  1614. DEBUG("route:  '%s' (%s) = '%s' (%d)\n", domain, domainv[step]?domainv[step]:"NULL", path, *cost);
  1615.  
  1616. /*
  1617. **  If we matched on the entire domain name, this address is fully resolved, 
  1618. **  and we plug <user> into it.  If we matched on only part of the domain 
  1619. **  name, we plug <domain>!<user> in.  
  1620. */
  1621.     build(domain, user, (step == 0) ? LOCAL : UUCP, temp);
  1622.     (void) sprintf(result, path, temp);
  1623.     return( EX_OK );
  1624. }
  1625. //E*O*F resolve.c//
  1626.  
  1627. echo x - smail.prompt
  1628. cat > "smail.prompt" << '//E*O*F smail.prompt//'
  1629. #
  1630. # @(#)smail.prompt    2.5 (smail) 9/15/87
  1631. #
  1632.  
  1633. loop=true
  1634. while test $loop = true
  1635. do 
  1636.     case "$1" in
  1637.     string)
  1638.         echo "$2" 1>&2
  1639.         read ans
  1640.         if test ! -z "$ans"
  1641.         then
  1642.             echo $ans
  1643.             loop=false;
  1644.         fi
  1645.     ;;
  1646.     file)
  1647.         echo "$2" 1>&2
  1648.         read ans
  1649.         case "$ans" in
  1650.         /*)
  1651.             if test -f "$ans"
  1652.             then
  1653.                 echo $ans
  1654.                 loop=false;
  1655.             else
  1656.                 echo "file '$ans' not found" 1>&2
  1657.             fi
  1658.         ;;
  1659.         *)
  1660.             echo "must give FULL PATH to file" 1>&2
  1661.         ;;
  1662.         esac
  1663.     ;;
  1664.     yesno)
  1665.         echo "$2" 1>&2
  1666.         read ans
  1667.         case "$ans" in
  1668.         y|Y|yes|Yes|YES)
  1669.             echo "yes"
  1670.             loop=false
  1671.         ;;
  1672.         n|N|no|No|NO)
  1673.             echo "no"
  1674.             loop=false
  1675.         ;;
  1676.         *)
  1677.             echo "Please enter yes or no" 1>&2
  1678.         ;;
  1679.         esac
  1680.     ;;
  1681.     *)
  1682.  
  1683.         echo "usage: $0 string|yesno prompt_message" 1>&2
  1684.         echo BOGUS_PROMPT_STRING
  1685.         loop=false
  1686.     ;;
  1687.     esac
  1688. done
  1689. //E*O*F smail.prompt//
  1690.  
  1691. echo x - str.c
  1692. cat > "str.c" << '//E*O*F str.c//'
  1693. #ifndef lint
  1694. static char     *sccsid="@(#)str.c    2.5 (smail) 9/15/87";
  1695. #endif
  1696.  
  1697. #include "defs.h"
  1698. #include <ctype.h>
  1699.  
  1700. /*
  1701. **    strncmpic: string compare, ignore case, stop after 'n' chars
  1702. */
  1703.  
  1704. strncmpic(s1, s2, n)
  1705. char *s1, *s2;
  1706. int n;
  1707. {
  1708.     register char *u = s1;
  1709.     register char *p = s2;
  1710.  
  1711.     while((n > 0) && (*p != '\0')) {
  1712.         /* chars match or only case different */
  1713.         if(lower(*u) == lower(*p)) {
  1714.             p++;    /* examine next char */
  1715.             u++;
  1716.         } else {
  1717.             break;    /* no match - stop comparison */
  1718.         }
  1719.         n--;
  1720.     }
  1721.     if(n > 0) {
  1722.         return(lower(*u) - lower(*p)); /* return "difference" */
  1723.     } else {
  1724.         return(0);
  1725.     }
  1726. }
  1727.  
  1728. /*
  1729. **    strcmpic: string compare, ignore case
  1730. */
  1731.  
  1732. strcmpic(s1, s2)
  1733. char *s1, *s2;
  1734. {
  1735.     register char *u = s1;
  1736.     register char *p = s2;
  1737.  
  1738.     while(*p != '\0') {
  1739.         /* chars match or only case different */
  1740.         if(lower(*u) == lower(*p)) {
  1741.             p++;    /* examine next char */
  1742.             u++;
  1743.         } else {
  1744.             break;    /* no match - stop comparison */
  1745.         }
  1746.     }
  1747.  
  1748.     return(lower(*u) - lower(*p)); /* return "difference" */
  1749. }
  1750.  
  1751. //E*O*F str.c//
  1752.  
  1753. echo x - svbinmail.c
  1754. cat > "svbinmail.c" << '//E*O*F svbinmail.c//'
  1755. #ifndef lint
  1756. static char    *sccsid = "@(#)svbinmail.c    2.5 (smail) 9/15/87";
  1757. #endif
  1758. /* */
  1759. /* This program will be used in place of /bin/mail on SVR2 sites.
  1760. /* It looks at the arguments and decides whether to call
  1761. /* SENDER for sending mail, or READER for reading mail.
  1762. /*
  1763. /* before installing as /bin/mail, move the stock /bin/mail to /bin/lmail
  1764. /*
  1765. /*  */
  1766.  
  1767. #include <stdio.h>
  1768. #include "defs.h"
  1769.  
  1770. #ifdef SENDMAIL
  1771. #define SENDER    SENDMAIL
  1772. #else
  1773. #define    SENDER    "/bin/rmail"
  1774. #endif
  1775.  
  1776. #define    READER    "/bin/lmail"
  1777.  
  1778. #define TRUE 1
  1779. #define FALSE 0
  1780.  
  1781. char prog[128];
  1782.  
  1783. void    perror(), exit(), usage();
  1784.  
  1785. main(argc, argv)
  1786. int argc;
  1787. char *argv[];
  1788. {
  1789.     extern int optind;
  1790.     extern char *optarg;
  1791.  
  1792.     int i, j, c;
  1793.     int reading, sending;
  1794.  
  1795.     reading = sending = FALSE;
  1796.  
  1797.     (void) strcpy(prog, argv[0]);
  1798.  
  1799.     if(argc == 1) {
  1800.         reading = TRUE;
  1801.     } else {
  1802.         while((c = getopt(argc, argv, "epqrtf:")) != EOF) {
  1803.             switch(c) {
  1804.             case 'e':
  1805.             case 'p':
  1806.             case 'q':
  1807.             case 'r':
  1808.             case 'f':
  1809.                 reading = TRUE;
  1810.                 break;
  1811.             case 't':
  1812.                 sending = TRUE;
  1813.                 break;
  1814.             default:
  1815.                 usage();
  1816.                 return(1);
  1817.             }
  1818.         }
  1819.     }
  1820.  
  1821.     /* any arguments left over -> sending */
  1822.     if(argc > optind) {
  1823.         sending = TRUE;
  1824.     }
  1825.  
  1826.     if((reading == TRUE) && (sending == TRUE)) {
  1827.         usage();
  1828.         return(1);
  1829.     }
  1830.  
  1831.     if(sending == TRUE) {
  1832.         argv[0] = SENDER;
  1833.         for(i = 1, j = optind; j < argc; i++, j++) {
  1834.             argv[i] = argv[j];
  1835.         }
  1836.         argv[i] = NULL;
  1837.     } else {
  1838.         argv[0] = READER;
  1839.     }
  1840.  
  1841.     (void) execvp(argv[0], argv);
  1842.     (void) fprintf(stderr, "%s: execvp(\"%s\", argv) failed: ",
  1843.         prog, argv[0]);
  1844.     perror("");
  1845.     return(1);
  1846. }
  1847.  
  1848. void
  1849. usage()
  1850. {
  1851.     (void) fprintf(stderr, "usage:\t%s [ -epqr ] [ -f file ]\n", prog);
  1852.     (void) fprintf(stderr, "\t%s [ -t ] persons\n", prog);
  1853. }
  1854. //E*O*F svbinmail.c//
  1855.  
  1856. echo x - sysexits.h
  1857. cat > "sysexits.h" << '//E*O*F sysexits.h//'
  1858. /*
  1859. **    @(#)sysexits.h    2.5 (smail) 9/15/87
  1860. */
  1861.  
  1862. # define EX_OK        0    /* successful termination */
  1863. # define EX_USAGE    64    /* command line usage error */
  1864. # define EX_NOHOST    68    /* host name unknown */
  1865. # define EX_UNAVAILABLE    69    /* service unavailable */
  1866. # define EX_SOFTWARE    70    /* internal software error */
  1867. # define EX_OSFILE    72    /* critical OS file missing */
  1868. # define EX_CANTCREAT    73    /* can't create (user) output file */
  1869. # define EX_TEMPFAIL    75    /* temp failure; user is invited to retry */
  1870. //E*O*F sysexits.h//
  1871.  
  1872. echo x - template.cf
  1873. cat > "template.cf" << '//E*O*F template.cf//'
  1874. ############################################################
  1875. #
  1876. #    SENDMAIL CONFIGURATION FILE
  1877. #
  1878. #    supports internet style addressing
  1879. #    over UUCP and ethernet links.
  1880. #
  1881. #    A product of the UUCP Project.
  1882. #
  1883. #    @(#)template.cf    2.5 (smail) 9/15/87
  1884. #
  1885. ############################################################
  1886.  
  1887.  
  1888. ############################################################
  1889. #
  1890. #  Local configuration options - HINTS
  1891. #
  1892. # Host name and domain name macros.
  1893. #
  1894. #    Dw sets $w
  1895. #    DD sets $D
  1896. #    CD sets $=D
  1897. #
  1898. # $D and $=D list all domains in which this host sits.
  1899. # $D goes into outbound addresses, i.e. "user@$w.$D".
  1900. # $A is another domain for which this host is 'authoritative'
  1901. # it will will be turned into $D.
  1902.  
  1903. CF_HOST
  1904. CF_DOMAIN
  1905. CF_AUTHORITY
  1906. CF_DCLASS
  1907.  
  1908. # Preemptive ether connections.  We prefer these connections 
  1909. # over both designated transport mechanisms and the general depository.
  1910. # You can add more classes (here and in S0).
  1911.  
  1912. # /etc/hosts.smtp might be a link to /etc/hosts
  1913. #
  1914. CF_SMTP
  1915.  
  1916. # Mock top-level domain names.  These name designate a transport mechanism
  1917. # and appear internally only, set in S3, used in S0, and removed in S4 and
  1918. # (possibly) the ruleset for the particular mailer.  
  1919.  
  1920. CTETHER UUX
  1921.  
  1922. # Relay host.  Used at the end of S0 as the general depository for 
  1923. # addresses which didn't resolve locally.  
  1924.  
  1925. DRrelay
  1926.  
  1927. #
  1928. #  End Local configuration options
  1929. #
  1930. ############################################################
  1931.  
  1932. ############################################################
  1933. #
  1934. #    General configuration information
  1935. #
  1936. ############################################################
  1937.  
  1938. DVsmail2.5/CF_DATE
  1939.  
  1940. ##########################
  1941. #     Special macros     #
  1942. ##########################
  1943.  
  1944. # official hostname
  1945. Dj$w.$D
  1946. # my name
  1947. DnMAILER-DAEMON
  1948. # UNIX header format
  1949. DlFrom $g  $d
  1950. # delimiter (operator) characters
  1951. Do.:%@!^=/[]
  1952. # format of a total name
  1953. Dq$g$?x ($x)$.
  1954. # SMTP login message
  1955. De$j Sendmail $v/$V ready at $b
  1956.  
  1957.  
  1958. ###################
  1959. #     Options     #
  1960. ###################
  1961.  
  1962. # location of alias file
  1963. OA/usr/lib/aliases
  1964. # default delivery mode (deliver in background)
  1965. Odbackground
  1966. # (don't) connect to "expensive" mailers
  1967. #Oc
  1968. # temporary file mode
  1969. OF0644
  1970. # default GID
  1971. Og1
  1972. # location of help file
  1973. OH/usr/lib/sendmail.hf
  1974. # log level
  1975. OL9
  1976. # default messages to old style
  1977. Oo
  1978. # queue directory
  1979. OQ/usr/spool/mqueue
  1980. # read timeout -- violates protocols
  1981. Or2h
  1982. # status file
  1983. OS/usr/lib/sendmail.st
  1984. # queue up everything before starting transmission
  1985. Os
  1986. # default timeout interval
  1987. OT3d
  1988. # time zone names (V6 only)
  1989. OtPST,PDT
  1990. # default UID
  1991. Ou1
  1992. # wizard's password
  1993. OWvoidpasswords
  1994.  
  1995. ###############################
  1996. #     Message precedences     #
  1997. ###############################
  1998.  
  1999. Pfirst-class=0
  2000. Pspecial-delivery=100
  2001. Pjunk=-100
  2002.  
  2003. #########################
  2004. #     Trusted users     #
  2005. #########################
  2006.  
  2007. Troot
  2008. Tdaemon
  2009. Tuucp
  2010. Tnetwork
  2011.  
  2012. #############################
  2013. #     Format of headers     #
  2014. #############################
  2015.  
  2016. #H?P?Return-Path: <$g>
  2017. HReceived: $?sfrom $s 
  2018.     $.by $j ($v/$V)
  2019.     id $i; $b
  2020. H?D?Resent-Date: $a
  2021. H?D?Date: $a
  2022. H?F?Resent-From: $q
  2023. H?F?From: $q
  2024. H?x?Full-Name: $x
  2025. HSubject:
  2026. # HPosted-Date: $a
  2027. # H?l?Received-Date: $b
  2028. H?M?Resent-Message-Id: <$t.$i@$j>
  2029. H?M?Message-Id: <$t.$i@$j>
  2030.  
  2031. ############################################################
  2032. #
  2033. #        REWRITING RULES
  2034. #
  2035.  
  2036.  
  2037. ###########################
  2038. #              #
  2039. #  Name Canonicalization  #
  2040. #              #
  2041. ###########################
  2042. S3
  2043.  
  2044. # basic textual canonicalization
  2045. R<>            $@@                turn into magic token
  2046. R$*<$+>$*        $2                basic RFC821/822 parsing
  2047. R$+ at $+        $1@$2                "at" -> "@" for RFC 822
  2048. R$*<$*>$*        $1$2$3                in case recursive
  2049.  
  2050. # handle route-addr <@a,@b,@c:user@d> 
  2051. R@$+,$+            @$1:$2                change all "," to ":"
  2052. R@$+:$+            $@<@$1>:$2            handle <route-addr>
  2053. R$+:$*;@$+        $@$1:$2;@$3            list syntax
  2054.  
  2055. # Rewrite address into a domain-based address.  Any special mock domain names 
  2056. # (like UUX) should be defined on the CT line and removed (if necessary) 
  2057. # in S4.  You can use them in S0 for designated transport mechanisms.
  2058.  
  2059. # Delimiters with precedence over @.  Add yours here.
  2060.  
  2061. # The @ delimiter.  Leave this alone.
  2062. R$+@$+            $:$1<@$2>            focus on domain
  2063. R$+<$+@$+>        $1$2<@$3>            move gaze right
  2064. R$+<@$+>        $@$1<@$2>            already canonical
  2065.  
  2066. # Delimiters with precedence below @.  Add yours here.
  2067. R$+^$+            $1!$2                convert ^ to !
  2068. R$-!$+            $@$2<@$1.UUX>            resolve uucp names
  2069. R$+.!$+            $@$2<@$1>            domain.!host
  2070. R$+!$+            $@$2<@$1>            domain!host
  2071.  
  2072. # % is a low precedence @.
  2073. R$*%$*            $@$>3$1@$2            %->@ and retry
  2074.  
  2075. ############################################################
  2076. #
  2077. #            RULESET ZERO PREAMBLE
  2078. #
  2079. ############################################################
  2080.  
  2081. S0
  2082.  
  2083. # first make canonical
  2084. R$*<$*>$*        $1$2$3                defocus
  2085. R$+            $:$>3$1                make canonical
  2086.  
  2087. # handle special cases.....
  2088. R@            $#local$:MAILER-DAEMON        handle <> form
  2089. R$*<@[$+]>$*        $#ether$@[$2]$:$1@[$2]$3    numeric internet spec
  2090.  
  2091. # strip local stuff
  2092. R$*<@$-.$w.$D>$*    $1<@$2>$3            thishost.mydom
  2093. CF_GATEWAYR$*<@$-.$D>$*    $1<@$2>$3            mydom
  2094. R$*<@$-.$w.$=D>$*    $1<@$2>$4            thishost.anydom
  2095. R$*<@$-.$w.$A>$*    $1<@$2>$3            thishost.anotherdom
  2096. R$*<@$-.$A>$*        $1<@$2>$3            anotherdom
  2097. R$*<@$-.$w.$=T>$*    $1<@$2>$4            thishost.mockdom
  2098. CF_GATEWAYR$*<$*$w>$*    $1<$2>$3            thishost
  2099. R$*<$*.>$*        $1<$2>$3            drop trailing dot
  2100. R<@>:$+            $@$>0$1                strip null route, retry
  2101. R$+<@>            $@$>0$1                strip null addr, retry
  2102.  
  2103.  
  2104. ###############################################
  2105. #    Machine dependent part of ruleset zero   #
  2106. ###############################################
  2107.  
  2108. # Preemption: for a host on a known link turn the domain spec into a
  2109. # mock domain indicating the link.  One set of these rules for each of 
  2110. # the F classes listed in the local configuration options.
  2111.  
  2112. R$*<$*$=E.$D>$*            $:$1<$2$3.ETHER>$4    etherhost.mydomain
  2113. R$*<$*$=E.$=D>$*        $:$1<$2$3.ETHER>$5    etherhost.anydomain
  2114. R$*<$*$=E.$A>$*            $:$1<$2$3.ETHER>$4    etherhost.anotherdomain
  2115. R$*<$*$=E.$=T>$*        $:$1<$2$3.ETHER>$5    etherhost.mock-domain
  2116. R$*<$*$=E>$*            $:$1<$2$3.ETHER>$4    etherhost
  2117.  
  2118. # Designated delivery: use the indicated transport mechanism.  One of
  2119. # these rules for each of the mock domains defined in $=T.  You can
  2120. # remove these if you just want general disposition.  HINTS.
  2121.  
  2122. # Designated delivery:
  2123. R$*<@$=U.UUX>$*        $#uux$@$2$:$1$3            known uucphost
  2124. R$*<@$=E$+.ETHER>$*    $#ether$@$2$:$1@$2$4        known etherhost
  2125. R$*<@$+.ETHER>$*    $#ether$@$2$:$1@$2$3        etherhost
  2126.  
  2127. # throw out mock domain name now
  2128. R$*<$*.$=T>$*        $1<$2>$4
  2129.  
  2130. # General disposition of remote mail (comment out all but one).  You
  2131. # might add to this list, if you have other "smarter" mailers.  HINTS.
  2132.  
  2133. R$*<@$->:$+        $#uux$@$2$:$1$3            forward to $2
  2134. R$*<@$*>$*        $#uux$@$2$:$1$3            hand to uucp
  2135. #R$*<@$*>$*        $#uux$@$R$:$1@$2$3        hand to uucp relay
  2136. #R$*<@$*>$*        $#ether$@$R$:$1@$2$3        hand to ether relay
  2137. #R$*<$*>$*        $#error$:unknown address $1$2$3    don't hand anywhere
  2138.  
  2139. # local delivery
  2140. R$+            $#local$:$1            user
  2141.  
  2142. ############################################################
  2143. #
  2144. #         Local and Program Mailer specification
  2145. #
  2146. ############################################################
  2147.  
  2148. CF_SVMAILMlocal, P=CF_LOCALMAIL, F=lsDFMhumSU, S=10, R=20, A=rmail $u
  2149. CF_BSMAILMlocal, P=CF_LOCALMAIL, F=rlsDFMmn, S=10, R=20, A=mail -d $u
  2150. Mprog,    P=/bin/sh,   F=lsDFMe,   S=10, R=20, A=sh -c $u
  2151.  
  2152. S10
  2153. R@            MAILER-DAEMON    errors to mailer-daemon
  2154. CF_HIDDENHOSTSR$+<@$+.$j>$*        $1<@$j>$3    hide anydom.$j under $j
  2155.  
  2156. S20
  2157.  
  2158. ############################################################
  2159. #
  2160. #            UUCP Mailer specification
  2161. #
  2162. ############################################################
  2163.  
  2164. Muux,    P=/bin/smail, F=sDFMhum, S=14, R=24, M=100000,
  2165.     A=smail -vH$j $h!$u
  2166.  
  2167. S14
  2168. R$+<@$=E>        $1            user@etherhost -> user
  2169. R$*<@$+>$*        $@$1<@$2>$3        already ok
  2170. CF_HIDDENHOSTSR$+<@$+.$j>$*        $1<@$j>$3        hide anydom.$j under $j
  2171. R$+            $@$1<@$j>        add our full address
  2172.  
  2173. S24
  2174.  
  2175. ############################################################
  2176. #
  2177. #            SMTP ethernet mailer
  2178. #
  2179. ############################################################
  2180.  
  2181. Mether,    P=[IPC], F=msDFMuCXP, S=11, R=21, A=IPC $h
  2182.  
  2183. S11
  2184. R$*<@$+>$*        $@$1<@$2>$3        already ok
  2185. R$+            $@$1<@$w>        add our hostname
  2186.  
  2187. S21
  2188.  
  2189. #################################
  2190. #  Final Output Post-rewriting  #
  2191. #################################
  2192.  
  2193. # This rewrites the internal $=T mock domains into their external form.
  2194. # The default is to replace the mock domain name with $D.
  2195. # The last two lines are stock.
  2196.  
  2197. S4
  2198. R@            $@                handle <> error addr
  2199. R$+<@$-.UUX>        $2!$1                u@host.UUX => host!u
  2200. R$*<$*$=T>$*        $:$1<$2$D>$4            change local info
  2201. R$*<$+>$*        $1$2$3                defocus
  2202. R@$+:$+:$+        @$1,$2:$3            <route-addr> canonical
  2203. //E*O*F template.cf//
  2204.  
  2205. exit 0
  2206.