[net.sources] nmail.c C source pgm for Network Mail Router

tim (06/18/82)

/*
 *
 * TITLE       : nmail
 *
 * PURPOSE     : To pre-process network addresses finding the shortest
 *                  path through the network
 *
 * PROGRAMMER  : Timothy W. Curry at University of Central Florida
 *
 * DATE        : April 7, 1982
 *
 * ENTRY PTS.  : main
 *
 * PARAMETERS  : addresses of the form: name or site!name or name@arpa_site
 *
 */

/* include the headers to work with standard I/O; isdigit; nmailer defines */

#include <stdio.h>
#include <ctype.h>

#include "nmail.h"

main(argc,argv)
int   argc;
char *argv[];
{  /*
    * Variable Usage:
    * 	net - the input file descriptor name for the network topology file
    *	site_name - a storage buffer to hold the name of a site
    *	plen,psrc,pdest - pointer variables used to build the list of site
    *		names. plen holds the length of the site name; psrc holds
    *		the current character position in the source buffer; pdest
    *		in the destination buffer
    *	dest - holds the name of the site we are trying to reach
    *	addr - holds both the name of the destination site and name of the
    *		user to receive the message
    *	i,k,j,l,m,n - integer counters
    *	ppos - keeps track of the current character position in paths
    *	ptr - index into the list of site links
    *	used - an array to hold the sites already visited while finding
    *		the shortest path
    *	pstk - the stack onto which the breadth first search places values
    */

   FILE *net,*fopen();
   char site_name[SITENAMELEN];
   char *plen,*psrc,*pdest;
   char paths[256],dest[14],addr[30];
   int  i,j,k,l,m,n,ppos;
   short int *ptr,used[MAXSITES],pstk[MAXSITES][2];

   if (argc == 1)
   {  fprintf(stderr,"nmail: no addresses given.\n");
      nmailusage();
   }

   if ((net = fopen(NETFILE,"r")) == NULL)
   {  fprintf(stderr,"nmail: can't open network configuration file.\n");
      exit(1);
   }

   /* the SITES buffer will consist of a byte with the length of
	the site name in it followed by the site name		*/

   *SITES = '\0';
   pdest = SITES;
   for (NUMSITES=1; ; NUMSITES++)
   {  if ((pdest-SITES+SITENAMELEN) > SITEBUFSZ)
      {  fprintf(stderr,"SITES buffer overflowed\n");
         exit(1);
      }
      fscanf(net,"%s",site_name);
      if (isdigit(*site_name)) break;
      for (plen=pdest,psrc=site_name; *++pdest = *psrc++; (*plen)++);
   }

   /* LINKS will be an array of numbers indicating which sites are connected
	to which.  LINDEX is used to index into the LINKS array.	    */

   LINKS[1] = (short int) atoi(site_name);
   LINDEX[1] = &LINKS[1];
   for (i=2,j=1; i<=NUMSITES+1 ; i++)
   {   while (LINKS[j] != 0)
       {  fscanf(net,"%d",&k);
	  j++;
          LINKS[j] = (short int) k;
       }
       LINDEX[i] = &LINKS[j];
       j--;
   }

   /* the last number was the value for the local site */

   Local = LINKS[j];

   /* initialize the buffer to mail */

   strcpy(paths,"mail ");
   ppos = 5;
   for (i=1; i<argc ;i++)
   {  addr[0] = '\0';

      /* if its a local address, then no need to process it */

      if (!(index(argv[i],'@')) && !(index(argv[i],'!')))
      {  strcat(paths,argv[i]);
	 strcat(paths," ");
	 ppos += strlen(argv[i]) + 1;
      }

      /* otherwise a path must be found ! */

      else
      {  if (index(argv[i],'@') && !(index(argv[i],'!'))) strcpy(addr,ARPA);
         strcat(addr,argv[i]);
         strcat(addr," ");

	 /* set dest = name of destination site */

         for (j=0; addr[j] != '!' ;j++)
         {  dest[j] = addr[j];
	    dest[j+1] = '\0';
	    if (dest[j] == '\0')
	    {  fprintf(stderr,"nmail: improperly formed address.\n");
	       nmailusage();
	    }
         }

	 /* find the numeric index of dest for LINDEX to use */

         for (j=0,k=1,m = strlen(dest); k<NUMSITES ;k++)
         {  l = SITES[j];
	    if (l == m)
	    {  for (j++,l+=j,n=0; j<l ; j++,n++)
	          if (SITES[j] != dest[n]) break;
	       if (j == l) break;
	       j = l;
	    }
	    else j += l + 1;
         }
         if (k == NUMSITES)
         {  fprintf(stderr,"nmail: site %s is not in the network.\n",dest);
	    exit(1);
         }

	 /* do a breadth first search to find a path from source to sink */

	 if (k != Local)
         {  for (j=0,l=1,m=0,used[0] = k; k!=Local ;k=pstk[m++][1])
            {  for (ptr=LINDEX[k]; ptr<LINDEX[k+1] ;ptr++)
	       {  for (n=0; n<l ;n++) if (used[n] == *ptr) break;
	          if (n==l)
	          {  used[l] = *ptr;
	             l++;
	             pstk[j][0] = k;
	             pstk[j][1] = *ptr;
	             j++;
	          }
	       }
            }

	 /* convert the numeric site values to thier character names
		and place them in the paths buffer			*/

            k = pstk[m-1][0];
            while (k != pstk[0][0])
            {  for (j=0,l=0; j<k-1 ;j++) l += SITES[l] + 1;
	       n = SITES[l];
	       for (j=0,l++; j<n ;j++,l++,ppos++) paths[ppos] = SITES[l];
	       paths[ppos++] = '!';
	       for ( ; pstk[m][1] != k ;m--);
	       k = pstk[m][0];
            }
	    paths[ppos] = '\0';
         }

         strcat(paths,addr);
         ppos += strlen(addr);
      }
   }

   /* when all the paths are resolved, pass control over to mail */

   printf("%s\n",paths);
   execl("/usr/ucb/mail","mail",paths,0);
}

nmailusage()
{  fprintf(stderr,"usage: nmail addr {addr} \nWhere addr = site!name for ");
   fprintf(stderr,"uucp-address or name@site for ARPANET-address.\n");
   exit(1);
}