home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / unix / volume8 / uumail4 / part02 < prev    next >
Encoding:
Internet Message Format  |  1987-02-04  |  49.3 KB

  1. Subject:  v08i034:  Uumail release 4.2, Part02/04
  2. Newsgroups: mod.sources
  3. Approved: mirror!rs
  4.  
  5. Submitted by: sob@soma.BCM.TMC.EDU (Stan Barber)
  6. Mod.sources: Volume 8, Issue 34
  7. Archive-name: uumail4/Part02
  8.  
  9. [  IMPORTANT NOTE:  This version superceeds the recent net.sources posting
  10.    because it also inclues the Patch#1.  An earlier version of Uumail
  11.    was next in the backlog, hence this "rapid" posting.  --r$  ]
  12.  
  13. #! /bin/sh
  14.  
  15. # Make a new directory for the uumail sources, cd to it, 
  16. # and run kits 1 thru 4 through sh. 
  17. # When all 4 kits have been run, read README.
  18.  
  19. echo "This is uumail kit 2 (of 4).  If kit 2 is complete, the line"
  20. echo '"'"End of kit 2 (of 4)"'" will echo at the end.'
  21. echo ""
  22. export PATH || (echo "You didn't use sh, you clunch." ; kill $$)
  23. echo Extracting uumail.c
  24. cat >uumail.c <<'!STUFFY!FUNK!'
  25. /*
  26.  *  U U M A I L
  27.  *  This program when invoked in the form:
  28.  *  uumail host!user will consult the local usemap for
  29.  *  the proper routing.
  30.  * 
  31.  *  If it finds it, it will invoke the proper uux call
  32.  *  to send the mail.
  33.  *  Otherwise it aborts with an error 68 (host unknown)
  34. ***************************************************************************
  35. This work in its current form is Copyright 1986 Stan Barber
  36. with the exception of resolve, gethostname and the original getpath which
  37. as far as I know are in the Public Domain. This software may be distributed
  38. freely as long as no profit is made from such distribution and this notice
  39. is reproducted in whole.
  40. ***************************************************************************
  41. This software is provided on an "as is" basis with no guarantee of 
  42. usefulness or correctness of operation for any purpose, intended or
  43. otherwise. The author is in no way liable for this software's performance
  44. or any damage it may cause to any data of any kind anywhere.
  45. ***************************************************************************
  46.  * $Log:    uumail.c,v $
  47.  * Revision 4.2  87/02/02  15:43:50  sob
  48.  * Added fix for lost line at the beginning of the message problems
  49.  * 
  50.  * Revision 4.1  86/12/15  13:14:44  sob
  51.  * Added attempted fix for null userid in from line on some system V machines.
  52.  * 
  53.  * Revision 4.0  86/11/17  16:02:36  sob
  54.  * Release version 4.0 -- uumail
  55.  * 
  56.  * Revision 3.16  86/10/28  23:26:05  sob
  57.  * installed header bug fix from steve@jplgodo
  58.  * 
  59.  * Revision 3.15  86/10/20  15:05:52  sob
  60.  * Ready for beta test
  61.  * 
  62.  * Revision 3.14  86/10/20  13:24:02  sob
  63.  * Additions to correctly deal with KNOWNHOST
  64.  * 
  65.  * Revision 3.13  86/10/10  18:25:03  sob
  66.  * Now deals with all forms of addresses correctly... close to beta release now
  67.  * 
  68.  * Revision 3.12  86/10/07  13:22:23  sob
  69.  * Made more changes to be compatilble with new Configure script
  70.  * 
  71.  * Revision 3.11  86/10/07  01:07:33  sob
  72.  * Correction for LOG definition
  73.  * 
  74.  * Revision 3.10  86/10/07  01:02:19  sob
  75.  * Altered to work correctly with new Configure script
  76.  * 
  77.  * Revision 3.9  86/10/06  15:03:04  sob
  78.  * Fixed another problem with getting neighbors in getpath.
  79.  * 
  80.  * Revision 3.8  86/10/01  15:52:08  sob
  81.  * Reveresed sense of nghborflag to make it work right.
  82.  * 
  83.  * Revision 3.7  86/09/22  17:52:36  sob
  84.  * This version appears to work when using and not using resolve.
  85.  * Now to alpha test
  86.  * 
  87.  * Revision 3.6  86/09/22  15:58:19  sob
  88.  * This version works correctly with resolve in the compilation. Now
  89.  * to check the other alternatives.
  90.  * Stan
  91.  * 
  92.  * Revision 3.5  86/09/22  12:44:24  sob
  93.  * Added KNOWNHOST definition to allow a place to punt unresolved mail.
  94.  * Hopefully this will help sites with small databases
  95.  * 
  96.  * Revision 3.4  86/09/02  23:32:14  sob
  97.  * Now works with resolve... need to clean up for release.
  98.  * Stan
  99.  * 
  100.  * Revision 3.3  86/08/18  14:13:16  sob
  101.  * checkpoint
  102.  * 
  103.  * Revision 3.2  86/07/11  17:59:19  sob
  104.  * This version now adapted to work with the uumail package.
  105.  * Thanks to Mark and the UUCP project for their work on smail!
  106.  * Stan
  107.  * 
  108.  * Revision 3.1  86/05/27  15:01:27  sob
  109.  * Added modification suggested by tp@ndm20.UUCP to allow user 
  110.  * to specify if uuname will be used to determine uucp neighbors.
  111.  * Stan Barber
  112.  * 
  113.  * Revision 3.0  86/03/14  12:05:00  sob
  114.  * Release of 3/15/86 --- 3rd Release
  115.  * 
  116.  * Revision 2.20  86/03/14  11:57:46  sob
  117.  * 
  118.  * 
  119.  * Revision 2.19  86/03/11  11:29:11  sob
  120.  * Added Copyright Notice
  121.  * 
  122.  * Revision 2.18  86/03/04  18:20:40  sob
  123.  * Fixed some problems with local vs. non-local mail.
  124.  * 
  125.  * Revision 2.17  86/02/26  03:06:47  sob
  126.  * Added error checking for a null name.
  127.  * 
  128.  * Revision 2.16  86/02/23  23:49:40  sob
  129.  * 
  130.  * 
  131.  * Revision 2.15  86/02/23  23:19:09  sob
  132.  * This version will hopefully work with the new pipeoutput option from 
  133.  * aliasing.
  134.  * Stan
  135.  * 
  136.  * Revision 2.14  86/02/18  02:56:38  sob
  137.  * Correct pointer problem with linked list.
  138.  * Stan
  139.  * 
  140.  * Revision 2.13  86/02/17  18:43:37  sob
  141.  * Updated with linked list for addresses. This will allow aliasing which
  142.  * will be added next.
  143.  * Stan
  144.  * 
  145.  * Revision 2.12  86/02/17  17:33:12  sob
  146.  * This update incorporates changes to the command line flags to
  147.  * conform more with the syntax of sendmail.
  148.  * Stan
  149.  * 
  150.  * Revision 2.11  86/02/07  16:06:16  sob
  151.  * Altered the code to always unlink the temporary letter file when
  152.  * DEBUG is NOT defined.
  153.  * Stan
  154.  * 
  155.  * Revision 2.10  85/12/26  16:50:23  sob
  156.  * Added fixes to allow uupath myhostname to work correctly.
  157.  * Stan
  158.  * 
  159.  * Revision 2.9  85/12/10  20:36:01  sob
  160.  * Added new return flag from getpath EX_TEMPFAIL to signal that the
  161.  * path database is currently being updated.
  162.  * 
  163.  * Revision 2.8  85/12/02  16:51:39  sob
  164.  * Added a fix to cope with percents in addresses returned by opath.
  165.  * Thank to steve@umd-cs.UUCP for the bug report.
  166.  * 
  167.  * Revision 2.7  85/11/18  12:36:48  sob
  168.  * Added the -h option to cause uumail NOT to add a From_ line.
  169.  * 
  170.  * Revision 2.6  85/11/14  20:20:06  sob
  171.  * Added #ifdef DEBUG to allow compiliation with out DEBUG installed
  172.  * 
  173.  * Revision 2.5  85/11/14  20:14:11  sob
  174.  * Another little buggie in the log format...sheesh.
  175.  * 
  176.  * Revision 2.4  85/11/13  15:53:18  sob
  177.  * Reformated the log file a little bit.
  178.  * 
  179.  * Revision 2.3  85/11/08  03:03:51  sob
  180.  * This is the release version.
  181.  * 
  182.  * 
  183.  * Revision 2.2  85/09/30  02:51:18  sob
  184.  * This version uses opath when defined during compile time.
  185.  * With a bit of cleaning up, this is a release version.
  186.  * 
  187.  * Revision 2.1  85/09/30  02:46:06  sob
  188.  * *** empty log message ***
  189.  * 
  190.  * Revision 2.0  85/09/09  18:22:56  UUCP
  191.  * *** empty log message ***
  192.  * 
  193.  * Revision 2.0  85/09/09  18:22:56  UUCP
  194.  * Added flags to conform with sendmail. Also updated the flags it could send
  195.  * to uux to conform with 4.3 uux command.
  196.  * Will add name resolution and header checking.
  197.  * Also will allow multiple addresses per line.
  198.  * 
  199.  * Revision 1.7  85/08/03  00:49:14  UUCP
  200.  * Cleaned up with lint.
  201.  * Stan Barber
  202.  * 
  203.  * Revision 1.6  85/07/11  19:30:00  sob
  204.  * changed PATHSIZE to PATHSIZ to conform with uupath
  205.  * 
  206.  * Revision 1.5  85/07/11  18:08:13  sob
  207.  * This one works both as uumail and uupath!
  208.  * Stan
  209.  * 
  210.  * Revision 1.4  85/07/10  18:35:05  sob
  211.  * moved DBM to getpath
  212.  * Stan Barber
  213.  * 
  214.  * Revision 1.3  85/07/09  01:28:14  sob
  215.  * First attempt to integrate uupath
  216.  * Not successful. Changed PATHALIAS define
  217.  * to DBM... will ultimately alter getpath as well
  218.  * added gethostname call to fill in for local host.
  219.  * 
  220.  * Revision 1.2  85/07/08  05:29:16  sob
  221.  * This one works with pathalias database...
  222.  * need to modify to substitue for uupath.
  223.  * Stan
  224.  * 
  225.  * Revision 1.1  85/07/08  03:11:10  sob
  226.  * Initial revision
  227.  * 
  228.  */
  229. #define _DEFINE
  230.  
  231. #include "uuconf.h"
  232. #include "patchlevel.h"
  233.  
  234. EXTERN bool uupath;
  235. extern int      errno;
  236. extern struct passwd *getpwuid();
  237. extern FILE    *popen();
  238. extern char     *ctime();
  239. extern char    *getlogin();
  240. extern char    *index();
  241. extern char    *rindex();
  242. extern char    *malloc();
  243. extern char     *getenv();
  244. extern char     *Alias();
  245. extern bool    nghborflag;
  246. EXTERN char    progname[12];
  247. EXTERN char  *paths;
  248. char * bangpath[BUFSIZ];
  249. char templet[64];
  250. struct mailname addrlist;    /* list of addresses */
  251. int local;
  252.  
  253.  
  254. main(argc, argv)
  255.     char **argv;
  256. {
  257.     FILE *out, *tmpf;    /* output to uux, temp file */
  258.  
  259.     char sender[512];    /* accumulated path of sender */
  260.     char user[NAMESIZ];
  261.     char cmd[2000];
  262.     char **av;
  263.     int i,
  264.             error = 0,
  265.             hopcount = 30;
  266.         
  267.         char c,
  268.            grade = 'C',
  269.        *path,            /* uupath to the system */
  270.            *p, *q, *r,            /* tmp pointer to argv's */
  271.        *FullName;
  272.        bool GrabTo,safecf,NoAlias,startuux,noheader,metoo;
  273.        extern intsig();
  274.        struct mailname *lp;
  275.        int form;
  276.  
  277.     if (signal(SIGINT, SIG_IGN) != SIG_IGN)
  278.         (void) signal(SIGINT, intsig);
  279.     if (signal(SIGHUP, SIG_IGN) != SIG_IGN)
  280.         (void) signal(SIGHUP, intsig);
  281.     (void) signal(SIGTERM, intsig);
  282.     (void) signal(SIGPIPE, SIG_IGN);
  283.     /* initialize Boolean Values */
  284.     startuux = safecf = TRUE;
  285.     metoo=GrabTo=NoAlias=noheader = FALSE;
  286.  
  287.     for (i = 3; i < 20; i++)
  288.         (void) close(i);
  289.     errno = 0;
  290.     nghborflag = TRUE;    /* use uuname if possible */
  291.     gethostname(Myname,32);
  292.     paths=DATABASE;
  293. #ifdef LOG
  294.     logfile=LOGFILE;
  295. #endif
  296.     FullName=getenv("NAME");
  297.     argv[argc] = NULL;
  298.     av = argv;
  299.     p = rindex(*av, '/');
  300.     if (p++ == NULL)
  301.         p = *av;
  302.     strcpy(progname ,p);
  303.     if(strcmp(p,"uupath") == 0)
  304.         uupath = TRUE;
  305.     while ((p = *++av) != NULL && p[0] == '-')
  306.     {
  307.         switch (p[1])
  308.         {
  309.  
  310.           case 'g':   /* set grade */
  311.             grade = p[2];
  312.             break;
  313.     
  314. # ifdef DEBUG
  315.           case 'd':    /* debug */
  316.             Debug= atoi(&p[2]);
  317.             if (Debug == 0) Debug = 1;
  318.             setbuf(stdout, (char *) NULL);
  319.             (void) printf("Version %s\n", Version);
  320.             break;
  321. # endif DEBUG
  322.  
  323.           case 'f':    /* from address */
  324.           case 'r':    /* obsolete -f flag */
  325.             p += 2;
  326.             if (*p == '\0' && ((p = *++av) == NULL || *p == '-'))
  327.             {
  328.                 p = *++av;
  329.                 if (p == NULL || *p == '-')
  330.                 {
  331.                     syserr("No \"from\" person");
  332.                     av--;
  333.                     break;
  334.                 }
  335.             }
  336.             if (from != NULL)
  337.             {
  338.                 syserr("More than one \"from\" person");
  339.                 break;
  340.             }
  341.             from = p;
  342.             break;
  343.  
  344.           case 'F':    /* set full name */
  345.             p += 2;
  346.             if (*p == '\0' && ((p = *++av) == NULL || *p == '-'))
  347.             {
  348.                 syserr("Bad -F flag");
  349.                 av--;
  350.                 break;
  351.             }
  352.             FullName = p;
  353.             break;
  354.  
  355.           case 'w':    /* just print the path */
  356.             uupath = TRUE;
  357.             break;
  358.           case 'h':    /* don't add a From line */
  359.             noheader = TRUE;
  360.             break;
  361.           case 'N':    /* don't use uuname to get neighbors */
  362.             nghborflag = FALSE;
  363.             break;
  364.           case 'n':     /* don't alias any addresses */
  365.             NoAlias = TRUE;
  366.             break;
  367.           case 't':    /* read Header for addresses */
  368.             GrabTo = TRUE;
  369.                 break;
  370.           case 'o':    /* sendmail-like options flag */
  371.             switch(p[2]){
  372.                 case 'm': /* send this message to the sender*/
  373.                     metoo=TRUE;
  374.                     break;
  375.                 case 'c': /* don't connect to expensive
  376.                         mailer, or don't start uux*/
  377.                     startuux = FALSE;
  378.                     break;
  379.                 }
  380.             break;
  381.           case 'b':    /* sendmail-like operation mode flag */
  382.             switch(p[2]){
  383.                 case MD_DELIVER: /* deliver the mail */
  384.                     uupath = FALSE;
  385.                     break;
  386.                 case MD_VERIFY: /* verify an address */
  387.                     uupath = TRUE;
  388.                     break;
  389.                 default:
  390.                     (void) fprintf(stderr,
  391.                     "%s: mode %c not supported\n",
  392.                             progname,p[2]);
  393.                     exit(EX_USAGE);
  394.                 }
  395.             break;
  396.             }
  397.     
  398.         }
  399.  
  400.     handle = JUSTUUCP;    /* default handling is just uucp */
  401.     if(*av==NULL && GrabTo!= TRUE)
  402.     {
  403.         (void) fprintf(stderr,"Usage: %s [flags] address\n",progname);
  404.         exit(EX_USAGE);
  405.     }
  406.  
  407.  
  408. #ifndef NOALIAS
  409.     if (AliasFile == NULL) AliasFile = ALIASFILE;
  410. #endif
  411.  
  412. /* get login name of the sender... use environment variables if possible */
  413.  
  414.     if(from==NULL || strlen(from) == 0){
  415.         if (((from = getenv("LOGNAME")) == NULL) || (strlen(from) == 0))
  416.             from = getenv("USER");
  417.         if ((from == NULL) || (strlen(from) == 0))
  418.             from = getlogin();
  419.         if ((from == NULL) || (strlen(from) == 0))
  420.             from = getpwuid(geteuid())->pw_name;
  421.     }
  422.  
  423. /* if from is still null, set it equal to UUMAIL daemon -- kluge! */
  424.  
  425. if (from == NULL) from = MAILERDAEMON;
  426.  
  427. /* If this is not uupath, then there must be a letter */
  428.  
  429. if (!uupath)
  430. {    
  431. #ifdef DEBUG
  432.     if (Debug) (void) printf("Mail from %s\n",from);
  433. #endif
  434.     /*
  435.      * Make temporary file for letter
  436.      * (I wish ACCESS(2) would take care of this better !!)
  437.      */
  438.     if ((p=getenv("HOME"))== NULL)
  439.         p="/tmp";
  440.     sprintf(&templet[0],"%s/.uumXXXXXX",p);
  441.     mktemp(templet);
  442.     unlink(templet);
  443.     if ((i=open(templet,2)) < 0)
  444.         {
  445.             p="/tmp";
  446.     
  447.             sprintf(&templet[0],"%s/.uumXXXXXX",p);
  448.             mktemp(templet);
  449.             unlink(templet);
  450.         }
  451.     else
  452.         {
  453.             close(i);
  454.             unlink(templet);
  455.         }
  456. #ifdef DEBUG
  457.     if (Debug>2) (void) fprintf(stderr,"Temp file is %s\n",templet);
  458. #endif
  459.     if((tmpf = fopen(templet, "w")) == NULL){
  460.         (void) fprintf(stderr, "%s : can't open %s for writing\n", progname,templet);
  461.         fclose(stdin);
  462.         exit(EX_CANTCREAT);
  463.  
  464.         }
  465.     while(fgets(lbuf,sizeof lbuf,stdin))
  466.         fputs(lbuf,tmpf);
  467.     (void) fclose(tmpf);
  468.     (void) fclose(stdin);
  469. /* file now saved */
  470.     if((tmpf = fopen(templet, "r")) == NULL){
  471.         (void) fprintf(stderr, "%s : can't open %s for reading\n", progname,templet);
  472.         unlink(templet);
  473.         exit(EX_OSERR);
  474.     }
  475.     
  476. }    
  477.     (void) strcpy(sender, "");
  478.  
  479.     path = malloc(PATHSIZ);
  480.  
  481. /* build address list */
  482.  
  483.  
  484.     while (*av != NULL && *av != NULL)
  485.         add(*av++,&addrlist);
  486.  
  487.     if(metoo)   add(from,&addrlist); /* add me to the list too */
  488.  
  489.     if(!NoAlias) alias();        /* do aliasing if not turned off */
  490. #ifndef NOALIAS                /* process forwarding files */
  491.     for (lp = addrlist.m_next;lp;lp = lp->m_next) forward(lp->m_name);
  492. #endif
  493.  
  494.     for (lp = addrlist.m_next;lp;lp = lp->m_next) /* mail it out */
  495.     {
  496.  
  497.     if(strlen(lp->m_name) == 0) continue;
  498.  
  499.     local = 0;
  500.  
  501.     q = p = lp->m_name;
  502.     
  503.     
  504. /* this is uupath command */    
  505.     if (uupath) 
  506.     {
  507.         if ((error = getpath (p, path,paths)) != EX_OK)
  508.             patherror(error,p);
  509.         if (strcmp(path,"%s") == 0) local = 1;
  510.     }
  511. #ifdef RESOLVE
  512.     else 
  513.     {
  514.     /* check for pipe to another program output here */
  515.         if (lp->m_pipe == TRUE){
  516.                 strcat(cmd,lp->m_name);
  517.                 goto pipeout;
  518.     }
  519.  r = malloc(PATHSIZ);
  520.  strcpy(r,p);
  521.  if (index(p,'@') != NULL) handle = ALL;
  522. /* try one */
  523.     form = resolve(p,path,user);
  524.     if ( (form == LOCAL && path[0] == '\0') 
  525.         || form == ERROR || form == ROUTE || form == DOMAIN){
  526.         if (user[0] != '\0') strcpy(p,user);
  527.         path[0] = user[0] = '\0';
  528. /* try two */
  529.             if (index(p,'@') != NULL) handle = ALL;
  530.         form = resolve(p,path,user);
  531.     }
  532. /* we could punt at this point, but let's forward it to a known
  533.    host that might be able to resolve it */
  534.  
  535. #ifdef KNOWNHOST /* ugly... alternate suggestions welcome */
  536.     if ( (exitstat || form == ERROR)
  537.      && (index(r,'@') != NULL || index(r,'!') != NULL) ){
  538.         strcpy(p,KNOWNHOST);
  539.         strcat(p,"!");
  540.         strcat(p,r);
  541.         user[0] = '\0';
  542.         form = resolve(p,path,user);
  543.     }
  544. #endif
  545.  
  546. #ifdef DEBUG
  547.     if ((Debug > 1) && (!exitstat)) 
  548.         (void) fprintf(stderr,"resolve returns %s!%s\n",path,user);
  549. #endif
  550.  
  551.     if (exitstat || form == ERROR )
  552.              /* no match in pathalias database */
  553.     {
  554.         deadletter(tmpf,local,exitstat,p);
  555.         unlink(templet);
  556.         exit(exitstat);
  557.     }
  558.    
  559.  
  560.    if (form == LOCAL)
  561.     {
  562.         strcpy(path,Myname);
  563.         local = 1;
  564.     }
  565.     } /* end of else uupath */
  566. #else
  567.     else
  568.     {
  569.            p = index(q,'!');
  570.            if (p == NULL) local++;
  571.            else *p = '\0';
  572.            if(!local){
  573.             if ((error = getpath (q,path,paths)) != EX_OK)
  574.                 patherror(error,q);
  575.             if (*path != '\0' && index(path,'!')) 
  576.                     *(rindex(path,'!')+1) = '\0';
  577.                  p++;
  578.                 strcat(path,p);
  579.                 p = index(path,'!');
  580.                 if (p != NULL) {
  581.                 *p = '\0';
  582.                     p++;
  583.                 strcpy(user,p);
  584.              }
  585.             else
  586.             {
  587.                 strcpy(user,path);
  588.                 local++;
  589.             }
  590.         }
  591.     }
  592. #endif
  593.  
  594. #ifdef DEBUG
  595.        if(Debug>3)
  596.         (void) fprintf(stderr,
  597.             "p = %s path = %s user = %s\n",p, path,user);
  598. #endif
  599.  
  600.     if (uupath)
  601.         {
  602.             if (*path != '\0') *(rindex(path,'!')+1) = '\0';
  603.             (void) printf("Path to %s:  %susername\n",
  604.                             lp->m_name,path);
  605.             continue;
  606.         }
  607.     else
  608.         {
  609.             if (local)
  610.                 (void) sprintf(cmd, LOCALMAIL, user);
  611.             else {
  612.                 (void) sprintf(cmd,"%s - ",REALUUX);
  613.             if (!startuux)
  614.                 strcat(cmd,"-r");
  615. #ifndef NORETURN
  616.             if (from)
  617.                 {
  618.                     strcat(cmd," -a");
  619.                     strcat(cmd,from);
  620.                 }
  621. #endif
  622. #ifndef NOGRADE
  623.             if (grade)
  624.                 {
  625.                     char work[10];
  626.                     (void) sprintf(work," -g%c",grade);
  627.                     strcat(cmd,work);
  628.                 }
  629. #endif        
  630.             if (index(user, '!'))
  631.                 {
  632.                     char work[100];
  633.                     (void)sprintf(work,
  634.                      " %s!rmail \\(%s\\)",path,user);
  635.                     strcat(cmd,work);
  636.                 }
  637.             else
  638.                 {
  639.                     char work[100];
  640.                     (void) sprintf(work, " %s!rmail %s",
  641.                     path,user);
  642.                     strcat(cmd,work);
  643.                 }
  644.             }
  645. pipeout:
  646. #ifdef DEBUG
  647.     if (Debug) (void) fprintf(stderr,"Command is %s\n",cmd);
  648. #endif
  649.         rewind(tmpf);
  650. #ifdef DEBUG
  651.         if (Debug)
  652.             out = fopen("UUMAIL.TEST","w");
  653.         else
  654. #endif
  655.             out = popen(cmd, "w");
  656. /*        fputs(lbuf, out); */
  657. /* reprocess header ? */
  658.         if (!noheader) Putfrom(tmpf,out);
  659.         while (fgets(lbuf, sizeof lbuf, tmpf))
  660.             fputs(lbuf, out);
  661.  
  662. /* may not be needed */
  663.         if (local!=0)
  664.             (void) fprintf(out,"\n.\n");
  665.  
  666. #ifdef DEBUG
  667.         if (Debug)
  668.             i = fclose(out);
  669.         else
  670. #endif
  671.             i = pclose(out);
  672.         if ((i & 0377) != 0)
  673.             {
  674.                 (void) fprintf(stderr, "pclose: status 0%o\n", i);
  675.                 deadletter(tmpf,local,EX_OSERR);
  676. #ifdef DEBUG
  677.                 if (Debug <3)
  678. #endif
  679.                          unlink(templet);
  680.                 exit(EX_OSERR);
  681.             }
  682. #ifdef LOG
  683.         maillog(cmd);
  684. #endif
  685.        }
  686.     }
  687. #ifdef DEBUG
  688.     if (Debug <3)
  689. #endif
  690.                 unlink(templet);
  691. exit(EX_OK);
  692. }
  693.  
  694. /* print an error message on stderr */
  695.  
  696. syserr(string)
  697. char * string;
  698. {
  699.     (void) fprintf(stderr,"%s\n",string);
  700. }
  701.  
  702. /* make a unix type From line and send it out the stream */
  703. /* based on smail code (rline subroutine )  to be compatible with RFC 976 */
  704.  
  705. Putfrom(into,outto)
  706. FILE *into, *outto;
  707. {
  708.     char    *asctime();
  709.     struct    tm *bp, *localtime();
  710.     char    *tp, *zp,*c;
  711.     int    parts,fromflag=0;
  712.     char     *partv[16];
  713.     char buf[BUFSIZ], addr[PATHSIZ], domain[PATHSIZ], user[NAMESIZ];
  714.     int form;
  715.     extern build();
  716.     long iop, offset;
  717.     (void) strcpy( bangpath,"");  /* zero bang path */
  718.     /* code from smail follows  (Thanks Mark!) */
  719.     for( ;; )
  720.     {
  721.         offset=ftell(into); /* get current position in file */
  722.         if ( fgets( buf, sizeof(buf), into )==NULL )
  723.             break;
  724.         if ( strncmp( "From ", buf, 5 ) 
  725.             && strncmp( ">From ", buf, 6 ) )
  726.             break;
  727. /*
  728. **  Crack the line apart using ssplit.
  729. */
  730.         if( c = index( buf, '\n' ) );
  731.             *c = '\0';
  732.  
  733.          parts = ssplit( buf, ' ', partv );
  734. /*
  735. **  Tack host! onto the bangpath argument if "remote from host" is present.
  736. */
  737.  
  738.         if ( parts > 3 
  739.             && !strncmp( "remote from ", partv[parts-3], 12 ) )
  740.         {
  741.             (void) strcat( bangpath, partv[parts-1] );
  742.             (void) strcat( bangpath, "!" );
  743.         } 
  744. /*
  745. **  Stuff user name into addr, overwriting the user name from previous 
  746. **  From_ lines, since only the last one counts.  Then rewrite user@host 
  747. **  into host!user, since @'s don't belong in the From_ argument.
  748. */
  749.         (void) strncpy( addr, partv[1], partv[2]-partv[1]-1 ); 
  750.         addr[partv[2]-partv[1]-1] = '\0';    /* ugh */
  751.  
  752.         (void) parse( addr, domain, user );
  753.         if(*domain == '\0') {
  754.             form= LOCAL;
  755.         } else {
  756.             form = UUCP;
  757.         }
  758.  
  759.         build( domain, user, form, addr );
  760.  
  761.     }
  762. /*
  763. **  Now tack the user name onto the from argument.
  764. */
  765.     (void) strcat( bangpath, addr );
  766. /*
  767. **  If we still have no from argument, we have junk headers.
  768. **  We use the from name determined at startup time.
  769. */
  770.     if (bangpath[0] == '\0') strcpy(bangpath,from);
  771.  
  772. /*
  773.  * Format time
  774.  */
  775.     time(&iop);
  776.     bp = localtime(&iop);
  777.     tp = asctime(bp);
  778. /*    zp = tzname[bp->tm_isdst];*/
  779.  
  780. /*    sprintf(buf, "%s%s %.16s %.3s %.5s", from, tp, zp, tp+20);*/
  781.      (void) sprintf(buf, "From %s %.16s %.4s", bangpath, tp, tp+20); 
  782.  
  783.     if (local == 0){
  784.             strcat(buf," remote from ");
  785.             strcat(buf,Myname);
  786.            }
  787.  
  788.     strcat(buf,"\n");
  789.     /* if there is no output file (no headers), exit */
  790.     if (outto == NULL) return;
  791.     (void) write(outto->_file,buf,strlen(buf));
  792.     /* now reset the input file to the beginning of the header
  793.      * following the "From " lines
  794.      */
  795.     (void) fseek(into,offset,0);
  796.     (void) fflush(outto);
  797.  
  798. }
  799.  
  800. /* end of code derived from smail */
  801.  
  802.  
  803. /* go here on a signal we want to catch */
  804. intsig()
  805. {
  806.     unlink(templet);
  807.     exit(EX_OK);
  808. }
  809.  
  810. /* put command strings in the logfile */
  811.  
  812. #ifdef LOG
  813.  
  814. maillog(command)
  815. char * command;
  816. {
  817.     FILE *f;
  818.     char atime[24];
  819.     long clock;
  820.     time (&clock);
  821.     strncpy(atime,ctime(&clock),24);
  822.  
  823.     if ((f=fopen(logfile,"a")) != NULL)
  824.         {
  825.             (void) fprintf(f,"%s: %s - %s\n",progname,atime,command);
  826.             fclose(f);
  827.         }
  828. }
  829.  
  830. #endif
  831.  
  832. /* print a path error and exit */
  833. patherror(error,name)
  834. int error;
  835. char * name;
  836. {
  837.     switch(error){
  838.         case EX_NOHOST:
  839.         (void) fprintf(stderr,"System %s not found in network map.\n",
  840.                          name);
  841.             break;
  842.         case EX_NOINPUT:
  843.              (void) fprintf(stderr,
  844.                 "Database %s could not be opened.\n",paths);
  845.             break;
  846.         case EX_TEMPFAIL:
  847.              (void) fprintf(stderr,
  848.         "Database %s is being updated.\nTry again later.\n",paths);
  849.             break;
  850.         }
  851.     exit(EX_NOHOST);
  852. }
  853. !STUFFY!FUNK!
  854. echo Extracting getpath.c
  855. cat >getpath.c <<'!STUFFY!FUNK!'
  856. /*
  857.  * Name: getpath -- return the full usenet path of the given name
  858.  *
  859.  * Paramaters: sysname (input) -- The system name to be expanded
  860.  *           pathname (output)  The usenet path of the given system name
  861.  *           pathfile (input) the file to search for the system name
  862.  *
  863.  * Returns: EX_OK     -- path found
  864.  *        EX_NOHOST -- path not found
  865.  *        EX_NOINPUT-- unable to open usemap
  866.  *          EX_TEMPFAIL -- database being rebuilt
  867.  *
  868.  * Original Version Author: J. Donnelly   3/82
  869.  *
  870.  */
  871.  
  872. /*    IF YOU ARE USING A DBM DATABASE, READ THIS!
  873.  *    If the special sentinel value of @@@ is not present in the
  874.  *    database, then it is assumed that the database is being
  875.  *    rebuilt and the requesting process is blocked for TIMEOUT
  876.  *    (default = 180) seconds.  If, after 5 such blocks, the
  877.  *    sentinel is not present, the error code EX_TEMPFAIL is returned.
  878.  *    The same is true if the dbm files cannot be initialized.
  879.  */
  880.  
  881. /***************************************************************************
  882. This work in its current form is Copyright 1986 Stan Barber
  883. with the exception of opath, gethostname and the original getpath which
  884. as far as I know are in the Public Domain. This software may be distributed
  885. freely as long as no profit is made from such distribution and this notice
  886. is reproducted in whole.
  887. ***************************************************************************
  888. This software is provided on an "as is" basis with no guarantee of 
  889. usefulness or correctness of operation for any purpose, intended or
  890. otherwise. The author is in no way liable for this software's performance
  891. or any damage it may cause to any data of any kind anywhere.
  892. ***************************************************************************/
  893. /* 22-jun-83 Sheppard
  894.  * modified to rewind path file (if open), rather than open again
  895.  *
  896.  * $Log:    getpath.c,v $
  897.  * Revision 4.0  86/11/17  16:02:15  sob
  898.  * Release version 4.0 -- uumail
  899.  * 
  900.  * Revision 3.11  86/11/06  01:59:48  sob
  901.  * Altered DBM to UUDBM to avoid possible conflicts under 4.3 BSD
  902.  * Thanks to page@ulowell for the report
  903.  * 
  904.  * Revision 3.10  86/10/20  15:05:14  sob
  905.  * Ready for beta test
  906.  * 
  907.  * Revision 3.9  86/10/20  13:23:36  sob
  908.  * Revisions to work more correctly in SORTED and nonSORTED databases
  909.  * 
  910.  * Revision 3.7  86/10/10  18:24:16  sob
  911.  * Moved dbm.h include here from uuconf.h
  912.  * 
  913.  * Revision 3.6  86/10/06  15:03:23  sob
  914.  * Fixed another problem with getting neighbors in getpath.
  915.  * 
  916.  * Revision 3.5  86/10/01  15:49:15  sob
  917.  * Revisions to deal with problems arrising from the neighbors array.
  918.  * Still not completely solved.
  919.  * 
  920.  * Revision 3.4  86/07/11  17:58:07  sob
  921.  * Fixed the alternate case conversion to work right.
  922.  * Stan
  923.  * 
  924.  * Revision 3.3  86/07/10  15:29:21  sob
  925.  * Added modifications that allow getpath to work with hosts that have
  926.  * names that are all uppercase or all lowercase.
  927.  * Stan
  928.  * 
  929.  * Revision 3.2  86/07/06  17:39:57  sob
  930.  * Added changes provided to dynamically allocate enough space for
  931.  * neighbors array. Thanks to rct for the help.
  932.  * Stan
  933.  * 
  934.  * Revision 3.0  86/03/14  12:04:46  sob
  935.  * Release of 3/15/86 --- 3rd Release
  936.  * 
  937.  * Revision 1.19  86/03/14  11:57:23  sob
  938.  * updated copyright
  939.  * 
  940.  * Revision 1.18  86/03/11  11:28:58  sob
  941.  * Added Copyright Notice
  942.  * 
  943.  * Revision 1.17  86/03/03  17:16:59  sob
  944.  * Added fixes provided by desint!geoff.
  945.  * Stan
  946.  * 
  947.  * Revision 1.16  86/02/24  12:45:36  sob
  948.  * Bug fix in scanning the list from uuname.
  949.  * Stan
  950.  * 
  951.  * Revision 1.15  86/02/23  23:01:53  sob
  952.  * This version will use data from the uuname command as well as
  953.  * data from the database
  954.  * 
  955.  * Revision 1.14  85/12/13  15:23:21  sob
  956.  * Added patches from umd-cs!steve
  957.  * 
  958.  * Revision 1.13  85/12/10  20:36:58  sob
  959.  * Added modifications suggested in gatech's version of uumail.
  960.  * Now, the DBM version of the database needs to have a SENTINAL in it
  961.  * to indicate that the DATABASE is not being updated. Also added similiar
  962.  * indicators to the non-DBM version to compare modification times and act
  963.  * accordingly. 
  964.  * 
  965.  * Revision 1.12  85/12/02  15:48:39  sob
  966.  * Combined speed hacks and old way of reading database and
  967.  * added compile flag SORTED. If database is SORTED and not DBM, use
  968.  * -DSORTED in CFLAGS to make it fast. If database is not sorted
  969.  * DO NOT use this flag.
  970.  * 
  971.  * Revision 1.11  85/11/24  15:03:41  sob
  972.  * Added changes suggested by regina!mark
  973.  * 
  974.  * Revision 1.10  85/11/24  04:21:45  sob
  975.  * Added efficiency hacks supplied by meccts!asby (Shane P. McCarron)
  976.  * 
  977.  * Revision 1.9  85/11/14  20:21:49  sob
  978.  * Added #ifdef DEBUG to allow compilation without DEBUG
  979.  * 
  980.  * Revision 1.8  85/11/08  03:04:49  sob
  981.  * release version
  982.  * 
  983.  * Revision 1.7  85/09/30  02:47:40  sob
  984.  * Altered to use path filename from global variable.
  985.  * 
  986.  * Revision 1.6  85/08/03  00:48:57  UUCP
  987.  * Cleaned up with lint.
  988.  * Stan Barber
  989.  * 
  990.  * Revision 1.5  85/07/19  17:45:13  UUCP
  991.  * Added \t as a valid seperation character for the database
  992.  * in the non DBM case. This is what pathalias uses.
  993.  * 
  994.  * Revision 1.4  85/07/19  16:44:07  UUCP
  995.  * revised to return proper things in accordance with sysexits
  996.  * Stan
  997.  * 
  998.  * Revision 1.3  85/07/11  19:30:31  sob
  999.  * added "uuconf.h" include file and deleted duplicated information
  1000.  * 
  1001.  * Revision 1.2  85/07/10  18:30:59  sob
  1002.  * updated to add DBM capabilities
  1003.  * Stan Barber, Baylor College of Medicine
  1004.  * 
  1005.  * Revision 1.1  85/07/10  18:03:28  sob
  1006.  * Initial revision
  1007.  * 
  1008.  */
  1009.  
  1010. #include    "uuconf.h"
  1011. #ifdef UUDBM
  1012. #include <dbm.h>
  1013. #else
  1014. #include <sys/types.h>
  1015. #include <sys/stat.h>
  1016. #endif
  1017.  
  1018. static char rcsid[] = "$Header: getpath.c,v 4.0 86/11/17 16:02:15 sob Exp $";
  1019. extern char * index();
  1020.  
  1021. extern FILE * fopen (), *popen();
  1022. FILE * in;
  1023. bool nghborflag,gotneighbors;
  1024. char **neighbors, *n_array;    /* rct */
  1025.  
  1026. int getpath (sysname, pathname, pathfile)
  1027. char   *sysname, *pathname,*pathfile;
  1028. {
  1029.     int indx,x;
  1030.     char ACsysname[NAMESIZ];            /* alternate case sysname */
  1031. #ifdef UUDBM
  1032.     datum lhs,rhs;
  1033. #else
  1034.     struct stat st;
  1035.         time_t modtime;
  1036.     char name[NAMESIZ];
  1037. #ifdef SORTED
  1038.     int scomp();
  1039.  
  1040.     long lo,hi;
  1041.     long cur;
  1042.     long last;
  1043.     static char buf[256];
  1044. #else
  1045.     char    * p, * q, t;
  1046. #endif
  1047. #endif
  1048.  
  1049.  
  1050. /* build sysname in the alternate case to conform to methods in SMAIL */
  1051.     if (*(sysname) == '.' || isupper(*sysname)) /* a kludge */
  1052.         {
  1053.             for (x=0;x<strlen(sysname);x++)
  1054.                 ACsysname[x] = tolower(*(sysname+x));
  1055.         }
  1056.     else
  1057.         {
  1058.             for (x=0;x<strlen(sysname);x++)
  1059.                 ACsysname[x] = toupper(*(sysname+x));
  1060.         }
  1061.  
  1062.     if (x < NAMESIZ) ACsysname[x] = '\0';
  1063. /* end case switch */
  1064. #ifdef DEBUG
  1065. if (Debug>2) (void) fprintf
  1066.     (stderr,"getpath: Sysname = %s, Alternate = %s, Pathfile = %s\n",
  1067.                         sysname,ACsysname,paths);
  1068. #endif
  1069.     if(nghborflag == TRUE)
  1070.     {
  1071.     if (gotneighbors != TRUE) getneighbors();
  1072.     indx = 0;
  1073. /* is it a neighbor? */
  1074.     while(neighbors[indx] != NULL && *(neighbors[indx]) != '\0'){
  1075.         if(!strcmp(sysname, neighbors[indx]) 
  1076.             || !strcmp(ACsysname,neighbors[indx])){
  1077.                 strcpy(pathname, neighbors[indx]);
  1078.                 strcat(pathname, "!%s");
  1079.                 return(EX_OK);
  1080.             }
  1081.             indx++;
  1082.         }
  1083.     }
  1084. /* not a neighbor, let's look in the database */
  1085. #ifdef UUDBM
  1086.     for (indx = 0; indx < 5; indx++)
  1087.     {
  1088.     if ((x = dbminit (pathfile)) >= 0)
  1089.         break;
  1090.     
  1091. #ifdef DEBUG
  1092.     if (Debug>2)
  1093.         (void) fprintf (stderr, "Database unavailable.  Sleeping.\n");
  1094. #endif
  1095.     sleep (TIMEOUT);
  1096.     }
  1097.  
  1098.     if (x < 0)
  1099.     return(EX_OSFILE);
  1100.  
  1101.     lhs.dptr = SENTINEL;
  1102.     lhs.dsize = strlen (SENTINEL) + 1;
  1103.     for (indx = 0; indx < 5; indx++)
  1104.     {
  1105.     rhs = fetch (lhs);
  1106.     if (rhs.dsize > 0)
  1107.         break;
  1108.     
  1109. #ifdef DEBUG
  1110.     if (Debug>2)
  1111.         (void) fprintf (stderr, "Database incomplete.  Sleeping.\n");
  1112. #endif
  1113.     sleep (TIMEOUT);
  1114.     }
  1115.     if (rhs.dsize <= 0)
  1116.     return(EX_TEMPFAIL);
  1117.  
  1118.         lhs.dptr = sysname;
  1119.     lhs.dsize = strlen(sysname)+1;
  1120.     rhs = fetch(lhs);
  1121.     if (rhs.dptr == NULL){        /* try other case */
  1122.         lhs.dptr=ACsysname;
  1123.         rhs = fetch(lhs);
  1124.         if (rhs.dptr == NULL) return(EX_NOHOST); /* no name found */
  1125.     }
  1126.     strcpy(pathname,rhs.dptr);
  1127.         return(EX_OK);            /* system name found */
  1128.  
  1129. #else
  1130. if (in == NULL) 
  1131.     {
  1132.     for (indx = 0; indx < 5; indx++)
  1133.         {
  1134.         if ((in = fopen(pathfile, "r")) != NULL)
  1135.             break;
  1136.     
  1137. #ifdef DEBUG
  1138.         if (Debug>2)
  1139.             (void) fprintf (stderr, "Database unavailable.  Sleeping.\n");
  1140. #endif
  1141.         sleep (TIMEOUT);
  1142.         }
  1143.     if (in == NULL)
  1144.     return(EX_OSFILE);
  1145.     }
  1146.     else
  1147.     rewind(in);
  1148.     indx = 0;
  1149.     strcpy(name,sysname);
  1150. restart:
  1151.     indx++;
  1152.     if (indx > 5) return(EX_TEMPFAIL);
  1153.     stat(pathfile, &st);
  1154.     modtime=st.st_mtime; /* original last modification time */
  1155.  
  1156. #ifdef SORTED
  1157.     lo = 0;
  1158.     hi = st.st_size;
  1159.     last = 0;
  1160.     cur = hi >> 1;
  1161.  
  1162.     while (cur > lo && cur < hi)
  1163.     {
  1164.         stat(pathfile,&st);
  1165.         if (st.st_mtime > modtime) goto restart;
  1166.         (void)fseek(in, cur, 0);
  1167.         if (fgets(buf, sizeof(buf), in)== NULL) return(EX_TEMPFAIL);
  1168.         cur = ftell(in);
  1169.         if (fgets(buf, sizeof(buf), in) == NULL) return(EX_TEMPFAIL);
  1170.  
  1171. #ifdef    DEBUG
  1172.     if (Debug > 4)
  1173.         (void) printf("Found site %s\n", buf);
  1174. #endif
  1175.         if (scomp(name, buf) < 0) hi = cur;
  1176.         else
  1177.         if (scomp(name, buf) > 0) lo = cur;
  1178.         else
  1179.         {
  1180.             buf[strlen(buf)-1] = '\0';
  1181.             strcpy(pathname, (char *)index(buf, '\t') + 1);
  1182.             return(EX_OK);
  1183.         }
  1184.         cur = lo + ((hi - lo)>>1);
  1185.         if (last == cur) 
  1186.         {
  1187.             (void)fseek(in, lo, 0);
  1188.             do
  1189.             {
  1190.                 if (fgets(buf, sizeof(buf), in) == NULL)
  1191.                         return(EX_TEMPFAIL);
  1192.                 lo = ftell(in);
  1193.                 if (scomp(name, buf) == 0 )
  1194.                 {
  1195.                     buf[strlen(buf)-1] = '\0';
  1196.                     strcpy(pathname, (char *)index(buf, '\t') + 1);
  1197.                     return(EX_OK);
  1198.                 }
  1199.             } while (lo <= hi);
  1200.             break;
  1201.         } /* end if */
  1202.         last = cur;
  1203.     } /* end while */
  1204.     if (!strcmp(name,ACsysname)) return(EX_NOHOST);
  1205.     else {
  1206.         strcpy(name,ACsysname);
  1207.         goto restart;
  1208.     }
  1209. #else
  1210.     p = (char *) malloc(NAMESIZ);
  1211.     if (p == NULL) return(EX_OSERR);     /* can't get space */
  1212.     q = p;
  1213.     for (;;)
  1214.     {
  1215.     p = q;
  1216.     while ((t = getc(in)) != EOF && (*p++ = t) != ' ' && t != '\t');
  1217.                      /* read the system name */
  1218.         stat(pathfile,&st);
  1219.         if (st.st_mtime > modtime) goto restart;        
  1220.                     /* database update in progress */
  1221.     if( t == EOF ) return(EX_NOHOST);
  1222.     *--p = '\0';            /* set end of string */
  1223.     p = q;
  1224. #ifdef DEBUG
  1225.     if (Debug>4) (void) printf("Found %s\n",p);
  1226. #endif
  1227.     if (!strcmp (p,name) || !strcmp(p,ACsysname))break;
  1228.     while (((t = getc (in)) !=EOF && t != '\n'));    /* skip this path */
  1229.     }
  1230.     p = pathname;            /* save start loc of pathname */
  1231.     while ((*pathname++ = getc (in)) != '\n' && *(pathname-1) != EOF);
  1232.     *--pathname = '\0';
  1233.     pathname = p;
  1234.     return(EX_OK);            /* system name found */
  1235.  
  1236. #endif
  1237. #endif
  1238. }
  1239.  
  1240. #ifdef    SORTED
  1241. #define MAPTAB(c) ((c=='\t')?'\0':c)
  1242.  
  1243. int scomp(a,b)
  1244. char *a,*b;
  1245. {
  1246. int r;
  1247.     while (!(r=(MAPTAB(*a)-MAPTAB(*b))) && *a && *b && *a!='\t' && *b!='\t')
  1248.     {
  1249.            a++; b++;
  1250.     }
  1251.     return(r);
  1252. }
  1253. #endif
  1254.  
  1255. getneighbors()
  1256. {
  1257.     FILE *ppntr;
  1258.     char * ptr;
  1259.     int x = 0;
  1260.     char n_neigh[16], *calloc();    /* rct */
  1261.     int nelem = 0;            /* rct */
  1262.  
  1263.     gotneighbors = TRUE;
  1264.  
  1265.     /*
  1266.     *  Let's get the number of neighbors we have.
  1267.     *
  1268.     *  Beginning of added code.    --rct
  1269.     */
  1270.  
  1271.     if((ppntr = popen("uuname | wc -l", "r")) != NULL){
  1272. #ifdef DEBUG
  1273.         if(Debug > 2)
  1274.             (void)fprintf(stderr, "Starting uuname | wc -l\n");
  1275. #endif
  1276.     }
  1277.     else{
  1278.         (void)fprintf(stderr, "Error: popen\(\"uuname | wc -l\"\)\n");
  1279.         exit(1);
  1280.     }
  1281.     if((fgets(n_neigh, sizeof(n_neigh), ppntr)) != (char *)0){
  1282.         if((ptr = index(n_neigh, '\n')) != (char *)0)
  1283.             *ptr = '\0';
  1284.     }
  1285.     else{
  1286.         (void)fprintf(stderr, "Error: fgets\(n_neigh\)\n");
  1287.         exit(2);
  1288.     }
  1289. #ifdef DEBUG
  1290.     if (Debug > 2)
  1291.         (void)fprintf(stderr, "n_neigh = %s\n", n_neigh);
  1292. #endif
  1293.     (void)pclose(ppntr);
  1294.  
  1295.     /*
  1296.     *  Allocate storage for neighbors based on n_neigh.
  1297.     *  Assumption being made here is that no system has a name
  1298.     *  longer than 14 characters.  If this assumption ever turns
  1299.     *  out to be wrong, lots of other code will break before this
  1300.     *  does!    --rct
  1301.     */
  1302.  
  1303.     nelem = atoi(n_neigh) + 2;
  1304.  
  1305.     if(((neighbors = (char **)calloc((unsigned)nelem,
  1306.         sizeof(char **))) == (char **)0) ||
  1307.         ((n_array = calloc((unsigned)nelem, 15)) == (char *)0)){
  1308.         (void)fprintf(stderr, "Error: getneighbors\(\): calloc\(\)\n");
  1309.         exit(3);
  1310.     }
  1311.  
  1312.     /*
  1313.     *  Set up pointers.
  1314.     */
  1315.  
  1316.     for(x = 0; x < nelem; x++)
  1317.         neighbors[x] = &n_array[x * 15];
  1318.  
  1319.     /*
  1320.     *  Now, let's read them in!
  1321.     *
  1322.     *  End of added code.    --rct
  1323.     */
  1324.  
  1325.     if ((ppntr = popen("uuname", "r")) != NULL) {
  1326. #ifdef DEBUG
  1327.         if (Debug>2)
  1328.             (void)fprintf(stderr, "Starting uuname\n");
  1329. #endif
  1330.         x = 0;
  1331.         while((fgets(neighbors[x], 15, ppntr)) != NULL){
  1332.             if ((ptr = index(neighbors[x], '\n')) != NULL)
  1333.                 *ptr = '\0';
  1334. #ifdef DEBUG
  1335.             if (Debug>4)
  1336.                 (void) fprintf(stderr, "Neighbor # %d: %s\n",
  1337.                     x + 1, neighbors[x]);
  1338. #endif
  1339.             x++;
  1340.         }    
  1341.         (void) pclose(ppntr);
  1342.     }
  1343.     strcpy(neighbors[x], Myname);
  1344. }
  1345.  
  1346.  
  1347.  
  1348. !STUFFY!FUNK!
  1349. echo Extracting resolve.c
  1350. cat >resolve.c <<'!STUFFY!FUNK!'
  1351. /*
  1352. **
  1353. **  Resolve.c
  1354. **
  1355. **  Routes then resolves addresses into UUCP or LOCAL.
  1356. **
  1357. */
  1358. #ifndef lint
  1359. static char     *sccsid="@(#)$Header: resolve.c,v 4.0 86/11/17 16:02:28 sob Exp $";
  1360. #endif
  1361.  
  1362. #include    <ctype.h>
  1363. #include    <stdio.h>
  1364. #include    "uuconf.h"
  1365.  
  1366.  
  1367.  
  1368. /*
  1369. **
  1370. **  rsvp(): how to resolve addresses.
  1371. **
  1372. **  After parsing an address into <form>, the resolved form will be
  1373. **  rsvp( form ).  If == ROUTE, we route the parsed address and parse again.
  1374. **
  1375. */
  1376.  
  1377. # define rsvp(a) table[(int)a-1][handle-1]
  1378.  
  1379. int table[5][3] = {
  1380. /*    all        uucponly    none */
  1381. {     ERROR,         ERROR,         ERROR },     /* error */
  1382. {     LOCAL,         LOCAL,         LOCAL },     /* local */
  1383. {     ROUTE,         LOCAL,         LOCAL },     /* domain */
  1384. {     UUCP,         UUCP,         LOCAL },     /* uucp */
  1385. {    ERROR,         ERROR,         ERROR }};    /* route */
  1386.  
  1387.  
  1388. /*
  1389. **  NOTE: in this module <domainv> replaces <hostv>. <domainv> contains 
  1390. **  the domain part of each address, though by the time it leaves here it 
  1391. **  can only be a host name.
  1392. */
  1393.  
  1394.  
  1395. /*
  1396. **
  1397. **  resolve(): resolve addresses to <host, user, form>.
  1398. **
  1399. **  This is a gnarly piece of code, but it does it all.  Each section 
  1400. **  is documented.
  1401. **
  1402. */
  1403.  
  1404. resolve( address, domain, user )
  1405. char *address;                /* the input address     */
  1406. char *domain;                /* the returned domain     */
  1407. char *user;                /* the returned user     */
  1408. {
  1409.     int form;        /* the returned form    */ 
  1410.     int parts;            /* to ssplit addresses    */
  1411.     char *partv[PATHSIZ];        /* "  "      "        */
  1412.      char temp[PATHSIZ];        /* "  "      "        */
  1413.     int i;
  1414.         
  1415.  
  1416. /*
  1417. **  If we set REROUTE and are prepared to deliver UUCP mail, we split the 
  1418. **  address apart at !'s and try to resolve successively larger righthand 
  1419. **  substrings until we succeed.  Regularly, we just resolve the whole thing 
  1420. **  once.
  1421. */
  1422.     if ( rsvp( UUCP ) == UUCP )
  1423.         parts = ssplit( address, '!', partv );
  1424.     else
  1425.         parts = 1, partv[0] = address;
  1426. /*
  1427. **  This for( i ) loop selects successively larger righthand substrings 
  1428. **  for BULLYing, see above. 
  1429. */
  1430.     for( i = parts - 1; i >= 0; i-- )
  1431.     {
  1432. /*
  1433. **  Parse the address.  If we are BULLYing and our substring parses to 
  1434. **  the LOCAL address, we skip to the next larger.
  1435. */
  1436.         (void) strcpy( temp, partv[i] );
  1437.         form = parse( temp, domain, user );
  1438. #ifdef DEBUG
  1439.     if (Debug>2) 
  1440.     printf("resolve: parse address '%s' = %s @ %s (%d)\n",temp,user,domain,form);
  1441. #endif
  1442.         if ( i && form == LOCAL )
  1443.             continue;
  1444. /*
  1445. **  Routing is next step, so we break out if we don't have a UUCP form (if 
  1446. **  we are set to route ALWAYS or REROUTE) or a ROUTE form.
  1447. */
  1448.         if ( rsvp( form ) != ROUTE && 
  1449.             ( rsvp( form ) != UUCP ) )
  1450.                 break;
  1451. /*
  1452. **  Apply router.  If BULLYing and routing failed, try next larger substring.
  1453. */
  1454.         if ( route( form, domain, user, temp ) )
  1455.             continue;
  1456. /*
  1457. **  After routing, reparse and resolve.
  1458. */
  1459.         form = parse( temp, domain, user );
  1460. #ifdef DEBUG
  1461. if (Debug>2)printf("resolve: parse route '%s' = %s @ %s (%d)\n",temp,user,domain,form);
  1462. #endif
  1463.         break;
  1464.     }
  1465. /*
  1466. **  For LOCAL mail in non-local format, we rewrite the full address into 
  1467. **  <user> and leave <domain> blank.
  1468. */
  1469.     if ( rsvp( form ) == LOCAL && form != LOCAL )
  1470.     {
  1471.         build( domain, user, form, temp );
  1472.         (void) strcpy( user, temp );
  1473.         (void) strcpy( domain, "" );
  1474.         form = LOCAL;
  1475.     }
  1476. /*
  1477. **  If we were supposed to route and address but failed (form == ERROR), 
  1478. **  or after routing once we are left with an address that still needs to
  1479. **  be routed (rsvp( form ) == ROUTE), complain.  It is possible that we 
  1480. **  may want to resolve this address more than once (if the routing tables
  1481. **  return a domain-style address), but most likely this address partially 
  1482. **  resolved to this host.
  1483. */
  1484.     if ( form == ERROR || rsvp( form ) == ROUTE )
  1485.     {
  1486.         exitstat = EX_NOHOST;
  1487. #ifdef DEBUG
  1488.      if (Debug) printf( "%s...couldn't resolve %s.\n", address, domain );
  1489. #endif
  1490.         form = ERROR;
  1491.     }
  1492.     return ( form );
  1493. }
  1494.  
  1495.  
  1496. /*
  1497. **
  1498. ** parse(): parse <address> into <domain, user, form>.
  1499. **
  1500. **     input        form
  1501. **    -----        ----
  1502. **    user        LOCAL
  1503. **    domain!user    DOMAIN
  1504. **    user@domain    DOMAIN
  1505. **    @domain,address    LOCAL    (just for sendmail)
  1506. **    host!address    UUCP
  1507. **
  1508. */
  1509.  
  1510. parse( address, domain, user )
  1511. char *address;        /* input address     */
  1512. char *domain;        /* output domain     */
  1513. char *user;        /* output user         */
  1514. {
  1515.     int parts;
  1516.     char *partv[PATHSIZ];                /* to crack address */
  1517.  
  1518. /*
  1519. **  If this is route address form @hosta,@hostb:user@hostd, break for
  1520. **  LOCAL since only sendmail would want to eat it.
  1521. */
  1522.     if ( *address == '@' )
  1523.         goto local;
  1524. /*
  1525. **  Try splitting at !. If it works, see if the piece before the ! has
  1526. **  a . in it (domain!user, form DOMAIN) or not (host!user, form UUCP).
  1527. */
  1528.     if ( ssplit( address, '!', partv ) > 1 )
  1529.     {
  1530.         (void) strcpy( user, partv[1] );
  1531.         (void) strncpy( domain, partv[0], partv[1]-partv[0]-1 );
  1532.         domain[partv[1]-partv[0]-1] = '\0';
  1533.         if( ( parts = ssplit( domain, '.', partv ) ) < 2 )
  1534.             return( UUCP );
  1535.         if( partv[parts-1][0] == '\0' )    
  1536.             partv[parts-1][-1] = '\0'; /* strip trailing . */
  1537.         return ( DOMAIN );
  1538.     }
  1539. /*
  1540. **  Try splitting at @.  If it work, this is user@domain, form DOMAIN.
  1541. **  Prefer the righthand @ in a@b@c.
  1542. */
  1543.     if ( ( parts = ssplit( address, '@', partv ) ) >= 2 )
  1544.     {
  1545.         (void) strcpy( domain, partv[parts-1] );
  1546.         (void) strncpy( user, partv[0], partv[parts-1]-partv[0]-1 );
  1547.         user[partv[parts-1]-partv[0]-1] = '\0';
  1548.         return ( DOMAIN );
  1549.     } 
  1550. /* 
  1551. **  Done trying.  This must be just a user name, form LOCAL.
  1552. */
  1553. local:
  1554.     (void) strcpy( user, address );
  1555.     (void) strcpy( domain, "" );
  1556.     return( LOCAL );                /* user */
  1557. }
  1558.  
  1559.  
  1560. /*
  1561. **
  1562. **  route(): route domain, plug in user.
  1563. **
  1564. **  Less complicated than it looks.  Each section is documented.
  1565. **
  1566. */
  1567.  
  1568. route( form, domain, user, result )
  1569. int form;            /* domain is UUCP host? */
  1570. char *domain;            /* domain or host name     */
  1571. char *user;            /* user name         */
  1572. char *result;            /* output route     */
  1573. {
  1574.     int    domains, step;            /* to split domain    */
  1575.     char    *domainv[MAXDOMS];        /* "  "     "        */
  1576.     char    temp[PATHSIZ], path[PATHSIZ];
  1577.  
  1578. /*
  1579. **  Fully qualify the domain, and then strip the last (top level domain) 
  1580. **  component off, so that we look it up separately.
  1581. */
  1582.     (void) strcpy( temp, ".");
  1583.     (void) strcat( temp, domain );
  1584.  
  1585.     domains = ssplit( temp+1, '.', domainv );
  1586.     /* If the domain ends in .UUCP, trim that off. */
  1587.     if ( domains && isuucp(domainv[domains-1]))
  1588.         domainv[domains-1][-1] = '\0';
  1589. /*
  1590. **  Try to get the path for successive components of the domain.  
  1591. **  Example for osgd.cb.att.uucp:
  1592. **    osgd.cb.att
  1593. **    cb.att
  1594. **    att
  1595. **    uucp ( remember stripping top level? )
  1596. **  Returns with error if we find no path.
  1597. */
  1598.     step = 0;
  1599.     while ( step<domains && getpath( domainv[step]-1, path,paths )
  1600.                              /* w/dot */
  1601.                  && getpath( domainv[step]  , path, paths) )
  1602.                             /* no dot */
  1603.         step++;
  1604.     if ( step == domains )
  1605.     {
  1606. #ifdef DEBUG
  1607.     if(Debug>2) printf( "resolve: getpath '%s' failed\n", domain );
  1608. #endif
  1609.         exitstat = EX_NOHOST;
  1610.         return( exitstat );
  1611.     }
  1612. #ifdef DEBUG
  1613.     if(Debug>2)printf("resolve: getpath '%s' (%s) = %s\n",domain,domainv[step],path);
  1614. #endif
  1615. /*
  1616. **  If we matched on the entire domain name, this address is fully resolved, 
  1617. **  and we plug <user> into it.  If we matched on only part of the domain 
  1618. **  name, we plug <domain>!<user> in.  
  1619. */
  1620.     build( domain, user, step ? UUCP:LOCAL, temp+1 );
  1621.     (void) sprintf( result, path, temp+1 );
  1622.     exitstat=EX_OK;
  1623.     return( exitstat );
  1624. }
  1625.  
  1626. /*
  1627.  * Return 1 iff the string is "UUCP" (ignore case).
  1628.  */
  1629. isuucp(str)
  1630. char *str;
  1631. {
  1632.     if (islower(*str) != 'u') return 0;
  1633.     ++str;
  1634.     if (islower(*str) != 'u') return 0;
  1635.     ++str;
  1636.     if (islower(*str) != 'c') return 0;
  1637.     ++str;
  1638.     if (islower(*str) != 'p') return 0;
  1639.     ++str;
  1640.     if (*str != '\0') return 0;
  1641.     return 1;
  1642. }
  1643.  
  1644. /*
  1645. **
  1646. ** qualifydomain(): turn domain into full domain name.
  1647. **
  1648. ** Best explained by examples, if hostdomain = a.b.c.UUCP
  1649. **    host.domain.UUCP -> host.domain.UUCP
  1650. **    host.b -> host.b.c.UUCP
  1651. **    host.x -> host.x.UUCP
  1652. **
  1653. */
  1654.  
  1655. /* qualifydomain():
  1656.  * Taken out 3/21/86 by MRH - if hostdomain is, say. a.b.c.COM,
  1657.  * and domain is x.UUCP, it turns it into x.UUCP.COM and then
  1658.  * barfs on it.  I don't see a way to handle PQN's this easily.
  1659.  */
  1660.  
  1661. build( domain, user, form, result )
  1662. char *domain;
  1663. char *user;
  1664. int form;
  1665. char *result;
  1666. {
  1667.     switch( form )
  1668.     {
  1669.     case LOCAL:
  1670.         (void) sprintf( result, "%s", user ); 
  1671.         break;
  1672.     case UUCP:
  1673.         (void) sprintf( result, "%s!%s", domain, user );
  1674.         break;
  1675.     case DOMAIN:
  1676.         (void) sprintf( result, "%s@%s", user, domain );
  1677.         break;
  1678.     }
  1679. }
  1680.  
  1681.  
  1682.  
  1683. /*
  1684. **  ssplit(): split a line into array pointers.
  1685. **
  1686. **  Each pointer wordv[i] points to the first character after the i'th 
  1687. **  occurence of c in buf.  Note that each wordv[i] includes wordv[i+1].
  1688. **
  1689. */
  1690.  
  1691. ssplit( buf, c, ptr )
  1692. register char *buf;        /* line to split up         */
  1693. char c;                /* character to split on    */
  1694. char **ptr;            /* the resultant vector        */
  1695. {
  1696.         int count = 0;
  1697.         int wasword = 0;
  1698.  
  1699.         for( ; *buf; buf++ )
  1700.         {
  1701.         if ( !wasword )
  1702.             count++, *ptr++ = buf;
  1703.         wasword = ( c != *buf );
  1704.         }
  1705.     if ( !wasword )
  1706.         count++, *ptr++ = buf;
  1707.         *ptr = NULL;
  1708.         return( count );
  1709. }
  1710.  
  1711. !STUFFY!FUNK!
  1712. echo Extracting aliascheck.c
  1713. cat >aliascheck.c <<'!STUFFY!FUNK!'
  1714. #ifndef lint
  1715. static char * rcsid="$Header: aliascheck.c,v 4.0 86/11/17 16:02:05 sob Exp $";
  1716. #endif
  1717. /***************************************************************************
  1718. This work in its current form is Copyright 1986 Stan Barber
  1719. with the exception of resolve, gethostname and the original getpath which
  1720. as far as I know are in the Public Domain. This software may be distributed
  1721. freely as long as no profit is made from such distribution and this notice
  1722. is reproducted in whole.
  1723. ***************************************************************************
  1724. This software is provided on an "as is" basis with no guarantee of 
  1725. usefulness or correctness of operation for any purpose, intended or
  1726. otherwise. The author is in no way liable for this software's performance
  1727. or any damage it may cause to any data of any kind anywhere.
  1728. ***************************************************************************/
  1729. /* This program based in part on the aliascheck program from MH Version 1.7 */
  1730. #include "uuconf.h"
  1731. #include <grp.h>
  1732. #include <sys/param.h>
  1733.  
  1734. #ifdef LIBNDIR
  1735. #include <ndir.h>
  1736. #else
  1737. #ifdef USENDIR
  1738. #include "ndir.h"
  1739. #else
  1740. #include <dir.h>
  1741. #endif
  1742. #endif
  1743.  
  1744. char    *AliasFile =    ALIASFILE;
  1745. char    *Password  =    "/etc/passwd";
  1746. char    *MailDir   =    MAILFILE;
  1747.  
  1748. char *termptr;
  1749.  
  1750. struct  mailname {
  1751.     struct mailname *m_next;
  1752.     char            *m_name;
  1753.     int              m_seen;
  1754. }  users, bad;
  1755.  
  1756. char *getcpy(str)
  1757. {
  1758.     register char *cp;
  1759.  
  1760.     cp = (char *) malloc(strlen(str) + 1);
  1761.     strcpy(cp, str);
  1762.     return(cp);
  1763. }
  1764. uleq(c1, c2)
  1765. register char *c1, *c2;
  1766. {
  1767.     register int c;
  1768.  
  1769.     while(c = *c1++)
  1770.         if((c|040) != (*c2|040))
  1771.             return(0);
  1772.         else
  1773.             c2++;
  1774.     return(*c2 == 0);
  1775. }
  1776.  
  1777. char *parse(ptr, buf)
  1778. register char *ptr;
  1779. char *buf;
  1780. {
  1781.     register char *cp;
  1782.  
  1783.     cp = buf;
  1784.     while(isspace(*ptr) || *ptr == ',' || *ptr == ':')
  1785.         ptr++;
  1786.     while(isalnum(*ptr) || *ptr == '/' || *ptr == '-' || *ptr == '.')
  1787.         *cp++ = *ptr++;
  1788.     if(cp == buf) {
  1789.         switch(*ptr) {
  1790.         case '<':
  1791.         case '*':
  1792.         case '=':
  1793.             *cp++ = *ptr++;
  1794.         }
  1795.     }
  1796.     *cp = 0;
  1797.     if(cp == buf)
  1798.         return 0;
  1799.     termptr = ptr;
  1800.     return buf;
  1801. }
  1802.  
  1803.  
  1804. char   *mail = 0;
  1805. FILE   *out;
  1806. int     donecd = 0;
  1807.  
  1808. main(argc, argv)
  1809.     int argc;
  1810.     char *argv[];
  1811. {
  1812.     register char *cp, *pp, **cpp;
  1813.     register struct mailname *lp;
  1814.     register struct group *gp;
  1815.     struct direct *dir;
  1816.     DIR *dirp;
  1817.     char line[256], pbuf[64];
  1818.     FILE *a;
  1819.  
  1820.     if(argc == 3 && strcmp(argv[1], "-mail") == 0)
  1821.         mail = argv[2];
  1822.     if(!mail)
  1823.         out = stdout;
  1824.     if((a = fopen(Password, "r")) == NULL) {
  1825.         om();
  1826.         fprintf(out, "Can't open password file ");
  1827.         perror(Password);
  1828.         exit(1);
  1829.     }
  1830.     while(fgets(line, sizeof line, a)) {
  1831.         if(line[0] == '\n' || line[0] == ';')
  1832.             continue;
  1833.         cp = parse(line, pbuf);
  1834.         add(cp, &users);
  1835.     }
  1836.     fclose(a);
  1837.     if((a = fopen(AliasFile, "r")) == NULL) {
  1838.         om();
  1839.         fprintf(out, "Can't open alias file: %s\n", AliasFile);
  1840.         donecd = 1;
  1841.     } else {
  1842.         while(fgets(line, sizeof line, a)) {
  1843.             if(line[0] == '\n' || line[0] == ';')
  1844.                 continue;
  1845.             cp = parse(line, pbuf);
  1846.             if(check(cp, 0)) {
  1847.                 add(line, &bad);
  1848.                 donecd = 1;
  1849.             }
  1850.         }
  1851.         fclose(a);
  1852.         if(donecd < 1) {
  1853.             if(out)
  1854.                 fprintf(out, "No Alias Inconsistencies.\n");
  1855.         } else {
  1856.             om();
  1857.             fprintf(out, "%s :: %s Collisions:\n",
  1858.                 Password, AliasFile);
  1859.             fprintf(out, "Colliding alias lines:\n");
  1860.             for(lp = bad.m_next; lp; lp = lp->m_next)
  1861.                 fprintf(out, "%s", lp->m_name);
  1862.             donecd = 1;
  1863.         }
  1864.     }
  1865.     while(gp = getgrent()) {
  1866.         for(cpp = gp->gr_mem; *cpp; cpp++)
  1867.             if(!check(*cpp, 1)) {
  1868.                 om();
  1869.                 fprintf(out, "Group: %s--User: %s not in /etc/passwd\n",
  1870.                     gp->gr_name, *cpp);
  1871.                 donecd = 2;
  1872.             }
  1873.     }
  1874.     if(donecd < 2 && out)
  1875.         fprintf(out, "No extraneous group entries.\n");
  1876. #ifdef RAND
  1877.     for(lp = users.m_next; lp; lp = lp->m_next)
  1878.         if(lp->m_seen == 0) {
  1879.             om();
  1880.             fprintf(out, "User: %s not in a group.\n", lp->m_name);
  1881.             donecd = 3;
  1882.         }
  1883.     if(donecd < 3 && out)
  1884.         fprintf(out, "No Users not in any group.\n");
  1885. #endif
  1886.     if ((dirp = opendir(MailDir)) == 0) {
  1887.         om();
  1888.         fprintf(out, "Can't open mail directory: %s\n", MailDir);
  1889.         donecd = 4;
  1890.     } else {
  1891.         (void) readdir(dirp);        /* skip . */
  1892.         (void) readdir(dirp);        /* skip .. */
  1893.         while (dir = readdir(dirp)) {
  1894.             if (!check(dir->d_name, 0)) {
  1895.                 om();
  1896.                 fprintf(out, "Mail drop: %s--Nonexistent user.\n",
  1897.                     dir->d_name);
  1898.                 donecd = 4;
  1899.             }
  1900.         }
  1901.         closedir(dirp);
  1902.     }
  1903.     if(donecd < 4 && out)
  1904.         fprintf(out, "No Extra mail drops.\n");
  1905.  
  1906.     exit(donecd);
  1907. }
  1908.  
  1909.  
  1910. add(name, list)
  1911. char *name;
  1912. struct mailname *list;
  1913. {
  1914.     register struct mailname *mp;
  1915.     char *getcpy();
  1916.  
  1917.     for(mp = list; mp->m_next; mp = mp->m_next)
  1918.         ;
  1919.     mp->m_next = (struct mailname *) malloc(sizeof *mp->m_next);
  1920.     mp = mp->m_next;
  1921.     mp->m_next = 0;
  1922.     mp->m_name = getcpy(name);
  1923. }
  1924.  
  1925. check(name, mark)
  1926.     char *name;
  1927.     int mark;
  1928. {
  1929.     register struct mailname *mp;
  1930.  
  1931.     for(mp = users.m_next; mp; mp = mp->m_next)
  1932.         if(uleq(name, mp->m_name)) {
  1933.             if(mark)
  1934.                 mp->m_seen = 1;
  1935.             return 1;
  1936.         }
  1937.     return 0;
  1938. }
  1939.  
  1940.  
  1941. om()
  1942. {
  1943.     int pipes[2], child;
  1944.  
  1945.     if(out)
  1946.         return;
  1947.     if(mail) {
  1948.         pipe(pipes);
  1949.         out = fdopen(pipes[1], "w");
  1950.         if((child = fork()) == -1) {
  1951.             fprintf(stderr, "Aliascheck: no forks!\n");
  1952.             exit(1);
  1953.         }
  1954.         if(child == 0) {
  1955.             close(pipes[1]);
  1956.             close(0);
  1957.             dup(pipes[0]);
  1958.             close(pipes[0]);
  1959.             execl("/bin/mail", "mail", mail, 0);
  1960.             execl("/usr/bin/mail", "mail", mail, 0);
  1961.             execl("/bin/bellmail", "mail", mail,0);
  1962.             perror("mail");
  1963.             exit(1);
  1964.         }
  1965.         fprintf(out, "Aliascheck: ");
  1966.     }
  1967. }
  1968.  
  1969. #ifdef USENDIR
  1970. #include "ndir.c"
  1971. #endif
  1972. !STUFFY!FUNK!
  1973. echo Extracting MANIFEST
  1974. cat >MANIFEST <<'!STUFFY!FUNK!'
  1975. After all the uumail kits are run you should have the following files:
  1976.  
  1977. Filename    Kit Description
  1978. --------    --- -----------
  1979. Alias.Design     3  How the aliasing mechanism works.
  1980. Binary.Only      3  How to use uumail at a site with a Binary Only license.
  1981. Configure        1  A shell script that deals with system dependancies.
  1982. MANIFEST         2  This list of files.
  1983. Makefile.SH      3  The makefile builder.
  1984. README           1  READ THIS FIRST!
  1985. SYNOPSIS.txt     3  General features of uumail (for mod.sources)
  1986. Sendmail         3  How to use uumail with Sendmail.
  1987. address.1.SH     3  Manual Page builder for address
  1988. address.c        3  address program file
  1989. alias.c          3  The aliasing subroutines based on the ideas in MH.
  1990. aliascheck.c     2  A program to check the format of alias files.
  1991. deadletter.c     3  The subroutine that deals with returning mail that fails.
  1992. gethostnam.c     3  The subroutine that returns the name of the local host.
  1993. getpath.c        2  The paths database search subroutine.
  1994. kitleader        4  Shell script to produce front of kit. (SYSTEM DEPENDANT)
  1995. kitlists.c       3  Kit packer (SYSTEM DEPENDANT)
  1996. kittrailer       4  Shell script to product end of kit. (SYSTEM DEPENDANT)
  1997. makedepend.SH    3  Shell script to generate make dependancies.
  1998. makekit          3  Shell script to make a kit file
  1999. manifake         1  Shell script to make MANIFEST.new file.
  2000. manimake         3  Shell script to make MANIFEST file.
  2001. ndir.c           3  Source file for Berkeley directory subroutine simulation
  2002. ndir.h           3  Include file for Berkeley directory subroutine simulation
  2003. palias           3  Sample paths database file.
  2004. patchlevel.h     3  Patch level and version header file
  2005. resolve.c        2  The path resolving subroutine.
  2006. rmail.c          3  rmail replacement to call uumail.
  2007. uumail.8.SH      3  The manual page builder for uumail.8.
  2008. uumail.c         2  The main program for uumail/uupath.
  2009. uux.c            3  uux replacement for Binary Only sites.
  2010. !STUFFY!FUNK!
  2011. echo ""
  2012. echo "End of kit 2 (of 4)"
  2013. cat /dev/null >kit2isdone
  2014. config=true
  2015. for iskit in 1               2               3               4               ; do
  2016.     if test -f kit${iskit}isdone; then
  2017.     echo "You have run kit ${iskit}."
  2018.     else
  2019.     echo "You still need to run kit ${iskit}."
  2020.     config=false
  2021.     fi
  2022. done
  2023. case $config in
  2024.     true)
  2025.     echo "You have run all your kits.  Please read README and then type Configure."
  2026.     chmod 755 Configure
  2027.     ;;
  2028. esac
  2029. : I do not append .signature, but someone might mail this.
  2030. exit
  2031.  
  2032.