[net.notes] Router/buildtable.c wastes space

mclure@sri-unix (09/15/82)

#N:sri-unix:1000021:000:532
sri-unix!mclure    Sep 15 14:47:00 1982

Has anyone hacked Router/buildtable.c so that it will work properly on
11's?  All I get now is a segmentation error.  One problem is that the
number of uucp sites is growing and compiling buildtable.c with -i
yields the 'very large data structure' error but does not avoid the
core dump.  It would seem that the fixed way of allocation for the
struct site_f eats a lot of space unnecessarily.  It should probably
just have char pointers and malloc the strings so that it doesn't waste
so much space.  Anyone done this yet?

	Stuart

mclure@sri-unix (09/17/82)

#R:sri-unix:1000021:sri-unix:1000022:000:6626
sri-unix!mclure    Sep 16 21:47:00 1982

Here's a copy of Router/buildtable.c which we have modified so that it
can work with much larger uucpnet maps.  Formerly, it blew up in
various unpleasant ways on 11's and the increasing size of the net map.
The sites struct has been changed to use pointers to strings rather
than allocating full fixed arrays which eats up space quickly.  Also,
it discards "(null)" paths produced by buildlink as being unreachable
sites.  In these cases, getpath returns the normal error code.  It
finally works for the latest map I have (314 sites).  You might want to
increase PATHLEN if you are in a particularly distant portion of the
universe.

	Stuart

#include <stdio.h>
/*
 *	format.c
 *
 *	This program takes a file of the form:
 *	site	intermediary1<token>intermediary2<token>...<token>site
 *
 *	and produces a file of the form:
 *	site	complete address to this site with embedded %s for user.
 *
 *	Addressing convention is one of the following:
 *
 *	@	Arpa address format (user@site)
 *	!	Uucp address format (site!user)
 *	:	Berknet address	(site:user)
 *	.	"dot" addressing, don't know the real name
 *			(user.site)
 *
 *
 *	Original Coding:
 *			Ray Essick		June 14, 1982
 */

#define	NOSITE	'N'		/* no site, simple formatting */
#define	ARPA	'@'		/* address format identifiers */
#define	UUCP	'!'
#define	BERK	':'
#define	DOT	'.'
#define	DFLTSCHEME	'!'
#define	LOCALSCHEME	'!'

#define	SITES	350		/* max sites we can handle */
#define	PATHLEN	128
#define	SYSNAME	20

struct site_f
{				/* structure for a site's information */
    char   *s_name;		/* name of system */
    char   *s_rawpath;		/* path to there */
    char   *s_fmtpath;		/* formatted path */
    int     s_scheme;		/* site's addr scheme */
};

struct site_f   site[SITES];	/* set up tables */
int     nsites;			/* number of active sites in the table */
char   *map,
       *memp,
       *links,
       *malloc ();

main (argc, argv)
char  **argv;
{
    FILE * fp;			/* for reading the files */

    if (argc != 3)		/* fixed format */
    {
	fprintf (stdout, "Usage: %s paths map\n", argv[0]);
	exit (1);
    }
    links = argv[1];
    map = argv[2];
    if (getsites () < 0)
	exit (1);		/* read in the site list */
    format ();			/* formats the tables */
    dumpem ();			/* dump out the formatted tables */
}

getsites ()
{
    FILE * fp;
    char    asite[SYSNAME];	/* hold system name */
    char    rawpath[PATHLEN];	/* and the raw path */
    int     c;			/* scratch character */
    int     i;

    nsites = 0;			/* empty table */
    if ((fp = fopen (links, "r")) == NULL)
	return - 1;

    while (1)
    {
	asite[0] = rawpath[0] = '\0';/* init the paths */
	i = 0;
	while ((c = getc (fp)) != ' ' && c != '\t' && c != '\n')
	    if (i < SYSNAME)
		asite[i++] = c;
	asite[i++] = '\0';	/* null terminate */
	if (c == '\n')
	    goto process;	/* no links, must be our local site! */

	while ((c = getc (fp)) == ' ' || c == '\t');/* skip white space */
	if (c == '\n')
	    goto process;	/* null links */

	rawpath[0] = c;		/* insert first character */
	i = 1;
	while ((c = getc (fp)) != ' ' && c != '\t' && c != '\n')
	    if (i < PATHLEN)
		rawpath[i++] = c;
	    else
	    {
		fprintf (stdout, "Site %s: path too long, ignored\n", site);
		asite[0] = '\0';
		while (getc (fp) != '\n');
		break;
	    }
	rawpath[i++] = '\0';	/* null terminate */
process: 			/* process the stuff */
	if (asite[0] && (strcmp (rawpath, "(null)") != 0))
	{			/* if we got a valid site */
	    printf ("%d\n", nsites);
	    if ((memp = malloc (strlen (asite) + 1)) != NULL)
	    {
		site[nsites].s_name = memp;
		strcpy (memp, asite);
	    }
	    else
	    {
		fprintf (stdout, "No memory left!\n");
		exit (1);
	    }
	    if ((memp = malloc (strlen (rawpath) + 1)) != NULL)
	    {
		site[nsites].s_rawpath = memp;
		strcpy (memp, rawpath);
	    }
	    else
	    {
		fprintf (stdout, "No memory left!\n");
		exit (1);
	    }
	    site[nsites].s_fmtpath = '\0';
	    site[nsites].s_scheme = DFLTSCHEME;
	    if (++nsites == SITES)
	    {
		fprintf (stdout, "Too many sites, change SITES constant\n");
		exit (1);
	    }
	}
	if ((c = getc (fp)) == EOF)
	    break;
	else
	    ungetc (c, fp);
    }
    fclose (fp);		/* return the file descriptor */
}

/*
 *	dumpem
 *
 *	dump out the formatted tables 
 */
dumpem ()
{
    FILE * fp;
    int     i;

    if ((fp = fopen (map, "w")) == NULL)
    {
	fprintf (stdout, "Failed while writing\n");
	exit (1);
    }

    for (i = 0; i < nsites; i++)
	fprintf (fp, "%s\t%s\n", site[i].s_name, site[i].s_fmtpath);

    fclose (fp);
}
/*
 *	format()
 *
 *	using the information contained in the tables, go figure out
 *	a formatted path with the appropriate addressing information
 *	in it.
 */
format ()
{
    int     i;
    char    apath[PATHLEN],
            tempfmt[PATHLEN];
    char   *p,
           *q;

    for (i = 0; i < nsites; i++)
    {
	parse (LOCALSCHEME, site[i].s_rawpath, tempfmt);
	if ((memp = malloc (strlen (tempfmt) + 1)) != NULL)
	{
	    site[i].s_fmtpath = memp;
	    strcpy (memp, tempfmt);
	}
	else
	{
	    fprintf (stderr, "No more memory in format!\n");
	    exit (1);
	}
    }
}
/*
 *	parse(scheme,user, buffer)
 *
 *	arranges a string in the buffer with the correct addressing
 *	to reach "user" using "scheme" for the first hop
 *	and recursing to get the other hops 
 */
parse (scheme, user, buffer)
char   *user;
char    buffer[PATHLEN];
{
    char   *p,
           *q,
           *r;
    char   *tosite;
    char   *touser;
    int     i,
            done,
            j,
            k;
    int     nscheme;
    char    tmpbuf[PATHLEN];


    if (user == NULL || *user == '\0')
    {
	sprintf (buffer, "%s", "%s");/* simple format */
	return;
    }

    p = user;			/* parse site!user */
    while (*p != '\0' && *p != UUCP && *p != BERK &&
	    *p != DOT && *p != ARPA)
	p++;			/* skip site */
    if (*p == '\0')
    {
	p = NULL;
    }
    else
    {
	nscheme = *p;		/* mark the scheme */
	*p = '\0';
	p++;
    }

    parse (nscheme, p, tmpbuf);	/* recurse */
    touser = tmpbuf;		/* point at the user */
    tosite = user;		/* and the destination site */
    if (tosite == NULL || *tosite == '\0')
	scheme = NOSITE;
    switch (scheme)
    {
	case NOSITE: 
	    sprintf (buffer, "%s", touser);
	    break;
	case ARPA: 
	    sprintf (buffer, "%s@%s", touser, tosite);
	    break;

	case UUCP: 
	    sprintf (buffer, "%s!%s", tosite, touser);
	    break;

	case BERK: 
	    sprintf (buffer, "%s:%s", tosite, touser);
	    break;

	case DOT: 
	    sprintf (buffer, "%s.%s", touser, tosite);
	    break;

	default: 
	    fprintf (stdout, "Invalid addr mode: %c\n", scheme);
	    exit (1);
    }

}