[net.sources] pathalias

honey@down.FUN (code 101) (01/21/85)

# To unbundle, sh this file
sed 's/.//' >README <<'//GO.SYSIN DD README'
-From down!honey Mon Jan 21 11:52:45 EST 1985
-To: whom it may concern
-Subject: new pathalias instructions
-
-cat CHANGES
-edit config.h
-edit Makefile
-	peter
//GO.SYSIN DD README
sed 's/.//' >CHANGES <<'//GO.SYSIN DD CHANGES'
-"Dead nets" for nets that require gateways.  See man page.
-By popular request, no ! in dbm output file.
-Network character must be one of !@%: -- dot is dead.
-Private hosts.  (Undocumented, but see lex.l if you're interested.  Goal
-	is to support host name collisions.))
-Discourage mixing of left- (@) and right-associative (!) operators.  
-Magic @ <--> % rule in paths involving multiple @'s.
-
-Use cheapest among duplicate links.
-Pure directed graph model.
-Reverse the sense of the -c (cost) flag.
-Don't list duplicate links -- they're normal.
-No network names in the output.
//GO.SYSIN DD CHANGES
sed 's/.//' >pathalias.1 <<'//GO.SYSIN DD pathalias.1'
-.TH PATHALIAS 1 
-.SH NAME
-pathalias \- compute shortest paths
-.SH SYNOPSIS
-.B pathalias
-[
-.B \-vcibp
-] [
-.B \-l
-host] [
-.B \-d
-link] [
-.ig
-.\" the -g option is for pathparse.  it's not really used by pathalias.
-file] [
-..
-.B \-P
-file] [inputfiles ...]
-.SH DESCRIPTION
-.I Pathalias
-computes the shortest paths and corresponding routes from one
-host to all other known, reachable hosts.
-\fIPathalias\fP expects as input a sequence of host-to-host connectivity
-information, with
-a host name in column 1, followed by white space, followed by
-a comma-separated list of links (also host names),
-denoting a connection from the host to the links.
-Connections are assumed to be unidirectional.
-A link-name may be preceded or followed by a network character to use
-in the path name.
-Valid network characters are '!', '@', ':', and '%'.
-The link-name (and network character, if present) may be
-followed by a ``cost'' in parentheses.
-.PP
-For example,
-.RS
-.nf
-down	princeton!(DEDICATED)
-princeton	topaz!(DEMAND+LOW)
-topaz	@rutgers(LOCAL)
-.fi
-.RE
-Costs may be arbitrary
-arithmetic expressions involving numbers, parentheses, '+', '\-', '*',
-and '/'.  Several symbolic numbers are
-defined, as follows:
-.PP
-.RS
-.nf
-.ta 10m 20m
-LOCAL	25	(local-area network connection)
-DEDICATED	95	(high speed dedicated link)
-DIRECT	200	(local call)
-DEMAND	300	(normal call)
-HOURLY	500	(hourly poll)
-EVENING	1800	(time restricted call)
-DAILY	5000	(daily poll)
-WEEKLY	30000	(irregular poll)
-.fi
-.RE
-.PP
-In addition,
-DEAD is a very large number (effectively infinite),
-and HIGH and LOW are \-5 and +5 respectively,
-for baud-rate or quality bonuses/penalties.
-.PP
-The numbers are intended to represent frequency
-of connection, which seems to be far more important than baud
-rates for this type of traffic.  There is an assumed
-high overhead for each hop; thus, e.g., HOURLY is far more than
-DAILY / 24.
-.PP
-Aliases may be indicated by including lines of the form
-.RS
-name = alias [ , alias...]
-.RE
-The primary name is used in the output.
-.PP
-Fully connected networks, such as the ARPANET or a LAN,
-are indicated by
-.RS
-net = {host, host, ...}
-.RE
-The host-list may be preceded or followed by a routing
-character, and may be followed by a cost:
-.RS
-.nf
-PrincetonCable = {up, down, yoyo, flakey, quirky, princeton, panic}!(LOCAL)
-ARPA = @{sri-unix, mit-ai, su-score}(DEDICATED)
-.fi
-.RE
-.PP
-Anything following # on an input line is ignored.  A line that begins with white
-space is taken as a continuation of the previous line.
-.PP
-The output, which appears on the standard output,
-is a list of host\-route pairs,
-where route is a string appropriate for use with
-\fIprintf\fP(3), e.g.
-.RS
-.nf
-.ta 10m 20m
-rutgers	princeton!topaz!%s@rutgers
-.fi
-.RE
-The ``%s'' in the route string should be replaced by the
-user name at the destination host.
-(This task is normally performed by a mailer.)
-.PP
-The name of a network is never used in
-expansions; thus, in the above example, sri-unix's path to
-mit-ai would be '%s@mit-ai', not '%s@ARPA@mit-ai'.
-.PP
-Options:
-.TP 6
-.B  \-i
-Map all host names to lower case.
-.TP 6
-.B  \-b
-Create a \fIdbm\fP(3) database as output.
-.TP 6
-.B  \-p
-Print output on stdout even if \-b is specified.
-.TP 6
-.B  \-c
-Print the costs of paths.
-.TP 6
-.B  \-v
-Report some statistics on stderr.
-.ig
-.\" the -g option is for pathparse.  it's not really used by pathalias.
-.TP 6
-.BR \-g " file\^"
-Dump the edges of the graph into the named file.
-..
-.TP 6
-.BR  \-l " host\^"
-Use host as local host name.
-.TP 6
-.BR  \-P " file\^"
-Use ``file'' as the name of the \fIdbm(3)\fP database.
-The database key is host name, the stored
-value is a (null-terminated) path.
-.TP 6
-.BR  \-d " link\^"
-Declares a dead link, host, or network.
-If link is of the form host1!host2, the link from host1 to host2
-is treated as an extremely high cost (i.e., dead) link.
-If link is a single host name, that
-host is treated as dead and will be used as an intermediate host of
-last resort on any path.
-If link is a network name, the network requires a gateway.
-.PP
-\fBGateways.\fP
-Normally, a network is represented by a pseudo-host with bidirectional
-links to network members.
-The links from pseudo-host to the members have the weight given in
-the input (or the default cost), while
-the links from the members to the pseudo-host
-have zero cost.
-Networks that are declared dead on the command line show these
-latter weights as very expensive links,
-effectively prohibiting paths within the network.
-In this case,
-the input should also show a link from some member(s) to the network;
-these hosts will act as gateways for the network.
-E.g., if CSNET is declared dead on the command line (with
-the -d flag) and the input contains
-.RS
-.nf
-CSNET = {...}
-csnet-relay	CSNET
-.fi
-.RE
-then routes to CSNET hosts will use csnet-relay as a gateway,
-rather than some other csnet host that may not
-be able to act as a gateway.
-.SH FILES
-.ta \w'/usr/local/lib/palias.{dir,pag}     'u
-/usr/local/lib/palias.{dir,pag}	default dbm output
-.SH COMPILE-TIME
-Edit config.h to accommodate \s-2UNIX\s0 variants.
-.SH AUTHORS
-Steve Bellovin (ulysses!smb)
-.br
-Peter Honeyman (princeton!honey)
//GO.SYSIN DD pathalias.1
sed 's/.//' >Makefile <<'//GO.SYSIN DD Makefile'
-# pathalias -- by steve bellovin, as told to peter honeyman
-
-# if you don't have -ldbm, edit config.h and edit the next line
-LIBE = -ll -ldbm
-
-CC = cc -g
-CFLAGS =
-LDFLAGS =
-YFLAGS = -d
-OBJ = addlink.o addnode.o gethostnam.o lex.o local.o main.o mapit.o mem.o parse.o
-HDRS = def.h config.h
-SRC = addlink.c addnode.c gethostnam.c lex.l local.c main.c mapit.c mem.c parse.y
-CSRC = addlink.c addnode.c gethostnam.c lex.c local.c main.c mapit.c mem.c parse.c
-
-pathalias: $(OBJ)
-	$(CC) $(LDFLAGS) $(OBJ) $(LIBE) -o pathalias
-
-
-tags: $(SRC) $(HDRS)
-	ctags -w $(HDRS) $(SRC)
-
-bundle:
-	@bundle README CHANGES pathalias.1 Makefile ${HDRS} ${SRC}
-
-$(OBJ):	def.h
-
-def.h: config.h
-	touch def.h
-#	get -s sccs/s.def.h
-
-parse.c: parse.y def.h
-	$(YACC) $(YFLAGS) parse.y
-	mv y.tab.c parse.c
-
-lex.o:	parse.c lex.c
-
-lex.c: def.h lex.l
-	lex lex.l
-	sed "s/define YYLMAX 200/define YYLMAX 512/" lex.yy.c >lex.c
-	rm -f lex.yy.c
-
-lint:	$(CSRC)
-	lint $(CFLAGS) $(CSRC)
-
-clean:
-	rm -f *.o pa y.tab.c y.tab.h lex.c parse.c core
-
-# the remainder is site specific -- here's how i do it
-
-LOCAL = down
-NEIGHBORS = yoyo tilt up quirky flakey
-SITES = ${LOCAL} ${NEIGHBORS}
-PATHFILES = paths/[^.]* paths.sites/[^.]* paths.bell/[^.]* path.map/[^.]*
-DEAD = -d harpo -d zeppo -d chico -d gummo -d tucc -d fortune!analog -d CSNET -d BITNET -d ARPANET -d purdue -d pur-ee -d uiucdcs!uokmet -d hogpc
-# EDGES = -g /usr/local/lib/mail/edges
-ARGS = -ci $(NODES) $(DEAD)
-
-paths:	${SITES}
-
-${LOCAL}:	paths/princeton
-	pathalias -v ${ARGS} -l $@ $(EDGES) $(PATHFILES) > $@.new 2>ERRORS
-	cut -f2- $@.new | sort >$@
-#	rm $@.new
-
-# NEIGHBOR hosts have exactly the same links as LOCAL
-# turn
-#	down	%s
-#	up	up!%s
-# into
-#	up	%s
-#	down	down!%s
-${NEIGHBORS}:	${LOCAL}.new
-	sed								\
-	    -e "s/	${LOCAL}	%s$$/	$@	%s/"		\
-	    -e "s/	$@	$@!%s$$/	${LOCAL}	${LOCAL}!%s/"	\
-	${LOCAL}.new > $@
-	
-sendit: paths
-	for i in $(NEIGHBORS); do\
-		uucp -ga $$i $$i!/usr/local/lib/pathaliases;\
-		uux -z -gb -a$$USER $$i!newaliases;\
-	done
-	touch sendit
-
-cat:
-	cat $(PATHFILES) > CAT
-
-# reorder the output for princeton/sendmail/uubang
-princeton:
-	pathalias ${ARGS} -l $@ $(PATHFILES)> $@.new 2>ERRORS
-	sed -e 's/\([^	]*\)	\([^	]*\)	\([^	]*\)/\2	\1	\3/' $@.new > $@
-	rm $@.new
-
-edges:	
-	pathalias -ib -l princeton -P palias -g edges $(PATHFILES) > edges 
//GO.SYSIN DD Makefile
sed 's/.//' >def.h <<'//GO.SYSIN DD def.h'
-/* pathalias -- by steve bellovin, as told to peter honeyman */
-#ifndef lint
-static char	*h_sccsid = "@(#)def.h	6.1 (down!honey) 85/01/21";
-#endif lint
-
-#include <stdio.h>
-#include <ctype.h>
-#include "config.h"
-
-typedef	long Cost;
-typedef struct node node;
-typedef struct link link;
-
-#ifdef MYMALLOC
-#define malloc mymalloc
-#define free myfree
-char	*sbrk();
-
-#ifdef ALIGN
-
-#if ALIGN == 0
-#undef ALIGN
-#endif ALIGN == 0
-
-#endif ALIGN
-
-#ifndef ALIGN
-#define memget sbrk
-#else ALIGN
-char	*memget();
-#endif ALIGN
-
-#endif MYMALLOC
-
-#ifdef ATTSV
-#ifndef UNAME
-#define UNAME
-#endif
-#define index strchr
-#define rindex strrchr
-#endif ATTSV
-
-#define STATIC /* static */	/* when i'm done profiling ... */
-
-#ifdef lint
-#define vprintf fprintf
-#else !lint -- this gives null effect warning
-/* because it's there ... */
-#define vprintf		!Vflag ? 0 : fprintf
-#endif lint
-
-#define	isnetc(c)	((c)=='!' || (c)=='.' || (c)==':' || (c)=='^' || \
-	(c)=='@' || (c)=='%')
-
-#define dirbits(c)	(c)
-
-#define	NAME(x)		((x)->n_alias ? (x)->n_alias->n_name : (x)->n_name)
-
-/* flags for n_flag */
-#define ISPRIVATE 0x001	/* this node invisible outside its definition file */
-#define DEHASH	  0x002	/* removed from hash table yet? */
-#define ATSIGN	  0x004	/* seen an at sign?  used for magic @/% rules */
-#define MAPPED	  0x008	/* done mapping this node */
-#define	NDEAD	  0x010	/* node is dead */
-#define HASLEFT	  0x020	/* route has a left side net character */
-#define HASRIGHT  0x040	/* route has a right side net character */
-#define	NNET	  0x080	/* node is a network name */
-#define INDFS	  0x100	/* used when removing net cycles */
-#define DUMP	  0x200	/* we have dumped this net's edges */
-
-struct node {
-	char	*n_name;	/* host name */
-	link	*n_link;	/* head of adjacency list */
-	node	*n_alias;	/* real node (when this node is an alias) */
-	node	*n_aliaslink;	/* other aliases for this node */
-	node	*n_private;	/* other private nodes in this file */
-	node	*n_root;	/* root of net cycle */
-	char	*n_path;	/* path to this host */
-	Cost	n_cost;		/* cost to this host */
-	short	n_tloc;		/* back ptr to heap/hash table */
-	short	n_flag;		/* see manifests above */
-};
-
-#define	DEFNET	'!'			/* default network character */
-#define	DEFDIR	LLEFT			/* host on left in default net */
-#define	DEFCOST	((Cost) 4000)		/* default cost of a link */
-#define	INF	((Cost) 30000000)	/* infinitely expensive link */
-
-#define NETDIR(l)	((l)->l_flag & LDIR)
-#define NETCHAR(l)	(Netchars[(l)->l_flag & LNETCHARS])
-
-/* data structure for adjacency list representation */
-/* flags for l_dir */
-
-/*
- * there's an ugly dependency between these manifests and the string
- * Netchars = "!.:^@%", defined in main.c
- * this saves 2 bytes per link (of which there are often > 20000)
- */
-#define LNETCHARS	0x3
-#define LBANG		0x0
-#define LCOLON		0x1
-#define LAT		0x2
-#define LPERCENT	0x3
-
-#define LDIR	0x8	/* 0 for left, 1 for right */
-#define LRIGHT	0x0	/* user@host style */
-#define LLEFT	0x8	/* host!user style */
-
-#define LDEAD	0x10	/* this link is dead */
-
-struct link {
-	link	*l_next;	/* rest of adjacency list */
-	node	*l_to;		/* adjacent node */
-	Cost	l_cost;		/* edge cost */
-	char	l_flag;		/* right/left syntax */
-	char	l_lnet;		/* network number ??? */
-};
-
-node	*addnode();
-link	*addlink();
-link	*lmerge();
-char	*strsave();
-char	*local();
-link	*newlink();
-node	*newnode();
-node	**newtable();
-void	strclear();
-void	setpath();
-
-long	atol();
-char	*malloc();
-char	*index();
-char	*rindex();
-FILE	*popen();
-char	*strcpy();
-
-extern node	*Home;
-extern char	*Cfile;
-extern int	Fcnt;
-extern int	Netid;
-extern char	**Ifiles;
-extern char	*ProgName;
-extern int	Lineno;
-extern node	**Table;
-extern int	Tabsize;
-extern char	*Netchars;
-extern int	Vflag;
-extern int	Cflag;
-extern int	Bflag;
-extern int	Pflag;
-extern int	Iflag;
-extern int	Ncount;
-extern int	Lcount;
-extern char	*Pathout;
-extern char	*Graphout;
-extern int	Netid;
-extern node	*Private;
//GO.SYSIN DD def.h
sed 's/.//' >config.h <<'//GO.SYSIN DD config.h'
-/* pathalias -- by steve bellovin, as told to peter honeyman */
-#ifndef lint
-static char	*c_sccsid = "@(#)config.h	6.1 (down!honey) 85/01/21";
-#endif lint
-
-#define DBM			/* include code to generate dbm(3) database */
-
-/* #define ATTSV		/* System III or System V */
-
-/* #define UNAME		/* have uname() */
-
-/* #define GETHOSTNAME		/* have gethostname() */
-
-#define	ALIASDB	"/usr/local/lib/palias"	/* default dbm output */
-
-/*
- * after much profiling, i finally found a good malloc/free
- * remove the next line if you disagree
- */
-#define MYMALLOC	/**/
-
-/*
- * how many trailing 0's needed in an pointer?
- * i am told that 68000 based systems want ALIGN to be 1.
- */
-/* #define ALIGN 1 /* */
//GO.SYSIN DD config.h
sed 's/.//' >addlink.c <<'//GO.SYSIN DD addlink.c'
-/* pathalias -- by steve bellovin, as told to peter honeyman */
-#ifndef lint
-static char	*sccsid = "@(#)addlink.c	6.1 (down!honey) 85/01/21";
-#endif lint
-
-#include "def.h"
-link	*
-addlink(from, to, cost, netchar, netdir)
-node	*from;
-register node	*to;
-Cost	cost;
-char	netchar;
-char	netdir;
-{
-	register link	*l, *prev = 0;
-
-	/* link chains are sorted by host struct address, largest to smallest */
-	for (l = from->n_link; l; l = l->l_next) {
-		if (to >= l->l_to)
-			break;
-		prev = l;
-	}
-	if (l && (to == l->l_to)) {
-		/*
-		 * use new cost if cheaper.
-		 * exception: if the existing link is a zero
-		 * cost link to a dead network, use this cost.
-		 */
-		if ((cost < l->l_cost)
-		 || (l->l_cost == 0
-		  && (to->n_flag & (NNET | NDEAD)) == (NNET | NDEAD))) {
-			l->l_cost = cost;
-			l->l_flag &= ~(LNETCHARS|LDIR);
-			l->l_flag |= netbits(netchar) | dirbits(netdir);
-		}
-		return(l);
-	}
-
-	l = newlink();
-
-	if (prev) {
-		l->l_next = prev->l_next;
-		prev->l_next = l;
-	} else {
-		l->l_next = from->n_link;
-		from->n_link = l;
-	}
-
-	l->l_to = to;
-	l->l_cost = cost;
-	if (netchar == 0)
-		netchar = DEFNET;
-	l->l_flag |= netbits(netchar) | dirbits(netdir);
-
-	return(l);
-}
-
-deadlink(s) 
-char	*s;
-{
-	char	*t, c;
-	link	*l;
-
-	for (t = s; !isnetc(*t); t++)
-		if (*t == 0) 
-			break;
-	if ((c = *t) != 0) {
-		*t = 0;
-		l = addlink(addnode(s, 0), addnode(t + 1, 0), INF / 2, c, DEFDIR);
-		l->l_flag |= LDEAD;
-	} else 
-		addnode(s, 0)->n_flag |= NDEAD;
-}
-
-#ifdef	SHOWLINK
-showlink(n) 
-register node *n;
-{
-	register link *l;
-
-	fprintf(stderr, "%s\t", NAME(n));
-	for (l = n->n_link; l; l = l->l_next)
-		fputs(NAME(l->l_to), stderr);
-	putc('\n', stderr);
-}
-#endif SHOWLINK
-
-netbits(c)
-char	c;
-{
-	char	*nptr;
-
-	if ((nptr = index(Netchars, c)) != 0)
-		return(nptr - Netchars);
-	fprintf(stderr, "%s: invalid network character: %c\n", ProgName, c);
-	badmagic(1);
-	/*NOTREACHED*/
-}
//GO.SYSIN DD addlink.c
sed 's/.//' >addnode.c <<'//GO.SYSIN DD addnode.c'
-/* pathalias -- by steve bellovin, as told to peter honeyman */
-#ifndef lint
-static char	*sccsid = "@(#)addnode.c	6.1 (down!honey) 85/01/21";
-#endif lint
-
-#include "def.h"
-
-void	lowercase();
-node	*isprivate();
-
-/*
- * these numbers are chosen because:
- *	-> they are prime,
- *	-> they are monotonic increasing,
- *	-> each is a tad smaller than a multiple of 1024.
- * the first point yields good hash functions, the second is used for the
- * standard re-hashing implementation of open addressing, and the third
- * optimizes for quirks in some mallocs i have seen.
- */
-static int Primes[]	= {
-	1021, 2039, 3067, 4093, 5113, 6133, 7159, 8179, 9209,
-	10223, 11261, 12281, 13309, 14327, 15349, 16381, 0
-};
-static int	Tabindex = -1;
-int	Tabsize;
-node	**Table;
-
-node	*
-addnode(name, privatenode)
-char	*name;
-{
-	int	i;
-	register node	*n;
-
-	if (Iflag)
-		lowercase(name);
-
-	/* is it a private host */
-	n = isprivate(name);
-	if (n != 0) {
-		while (n->n_alias)
-			n = n->n_alias;
-		return(n);
-	}
-
-	i = hash(name, privatenode);
-	if (Table[i] != 0) {
-		n = Table[i];
-		while (n->n_alias)
-			n = n->n_alias;
-		return(n);
-	}
-
-	n = newnode();
-	n->n_name = strsave(name);
-	Table[i] = n;
-	n->n_tloc = i;	/* essentially a back link to the table */
-
-	return(n);
-}
-
-alias(parent, child) 
-node	*parent;	/* real node */
-node	*child;		/* alias node */
-{
-	node	*root;		/* root of this alias tree */
-	if (parent == child) {
-		char	buf[BUFSIZ];
-
-		sprintf(buf, "warning: alias redeclaration: %s = %s",
-			parent->n_name, parent->n_name);
-		yyerror(buf);
-		return;		/* caused by redeclaration of alias */
-	}
-
-	/* avoid alias loops, force many-to-one */
-	/* can't happen -- wish it could ... */
-	if (parent->n_alias || child->n_alias) {
-		yyerror("can't nest aliases");
-		return;
-	}
-
-	/* merge links from parent(s) to root, point parent at root */
-	for (root = parent->n_alias; root; root = root->n_alias) {
-		root->n_link = lmerge(root->n_link, parent->n_link);
-		parent->n_link = 0;
-		parent = root;
-	}
-
-	/* merge child links into parent (now root) */
-	parent->n_link = lmerge(parent->n_link, child->n_link);
-
-	/* set up the alias pointers */
-	child->n_alias = parent;
-	child->n_aliaslink = parent->n_aliaslink;
-	parent->n_aliaslink = child;
-}
-
-/* double hashing */
-#define HASH1(n)	((n) % Tabsize);
-#define HASH2(n)	(((n) % (Tabsize - 2)) + 1)
-
-/*
- * at 75% full, probes per access is about 2.
- */
-#define HIGHWATER	75
-#define LOWWATER	50
-#define isfull(n, size)	((n) > (((size) * HIGHWATER) / 100))
-#define isempty(n, size)	((n) < (((size) * LOWWATER) / 100))
-
-STATIC int
-hash(n, privatenode)
-register char	*n;
-{
-	register int	probe, hash2;
-
-	if (Tabindex < 0) {			/* first time */
-		Tabindex = 0;
-		Tabsize = Primes[0];
-		Table = newtable(Tabsize);
-	} else if (isfull(Ncount, Tabsize)) {	/* too full -- rehash */
-		register node	**oldTable, **optr;
-
-		hashanalyze();
-		optr = Table + Tabsize - 1;	/* ptr to last */
-		oldTable = Table;
-
-		do
-			Tabsize = Primes[++Tabindex];
-		while (!isempty(Ncount, Tabsize))
-			;
-		vprintf(stderr, "rehash into %d\n", Tabsize);
-		if (Tabsize == 0) {
-			fprintf(stderr, "%s: > %d hosts\n", ProgName,
-							Primes[Tabindex-1]);
-			badmagic(1);
-		}
-		Table = newtable(Tabsize);
-
-		do {
-			if (*optr == 0)
-				continue;
-			probe = hash((*optr)->n_name,
-					(*optr)->n_flag & ISPRIVATE);
-			if (Table[probe] != 0) {
-				fprintf(stderr, "%s: rehash error\n", ProgName);
-				badmagic(1);
-			}
-			Table[probe] = *optr;
-			(*optr)->n_tloc = probe;
-		} while (optr-- > oldTable);
-		free((char *) oldTable);
-	}
-				
-	probe = fold(n);
-	/* don't change the order of the next two lines */
-	hash2 = HASH2(probe);
-	probe = HASH1(probe);
-	/* thank you! */
-
-	/*
-	 * probe the hash table until we find either
-	 *  (1) an empty slot, or
-	 *  (2) this host name,
-	 *      unless we require a fresh slot (privatenode != 0)
-	 */
-	while ((Table[probe] != 0)
-	    && ((privatenode != 0) || (strcmp(Table[probe]->n_name, n) != 0))) {
-		probe -= hash2;
-		if (probe < 0)
-			probe += Tabsize;
-	}
-	return(probe);
-}
-
-STATIC
-fold(s)
-register char	*s;
-{
-	register	sum = 0;
-
-	while (*s) {
-		sum <<= 2;
-		sum += *s++;
-	}
-	if (sum < 0) 
-		sum = -sum;
-	return(sum);
-}
-
-/* merge the l2 list into the l1 list */
-link	*
-lmerge(l1, l2)
-link	*l1, *l2;
-{
-	link	*rval, *ltmp;
-
-	if (l1 == 0)
-		return(l2);
-
-	if (l2 == 0)
-		return(l1);
-
-	if (l1->l_to > l2->l_to) {
-		ltmp = rval = l1;
-		l1 = l1->l_next;
-	} else if (l1->l_to < l2->l_to) {
-		ltmp = rval = l2;
-		l2 = l2->l_next;
-	} else if (l1->l_cost <= l2->l_cost) {
-		ltmp = rval = l1;
-		l1 = l1->l_next;
-		free((char *) l2);
-		l2 = l2->l_next;
-	} else {
-		ltmp = rval = l2;
-		l2 = l2->l_next;
-		free((char *) l1);
-		l1 = l1->l_next;
-	}
-
-	while (l1 && l2) {
-		if (l1->l_to > l2->l_to) {
-			ltmp->l_next = l1;
-			ltmp = l1;
-			l1 = l1->l_next;
-		} else if (l1->l_to < l2->l_to) {
-			ltmp->l_next = l2;
-			ltmp = l2;
-			l2 = l2->l_next;
-		} else if (l1->l_cost <= l2->l_cost) {	/* use cheaper link */
-			ltmp->l_next = l1;
-			ltmp = l1;
-			l1 = l1->l_next;
-			free((char *) l2);
-			l2 = l2->l_next;
-		} else {
-			ltmp->l_next = l2;
-			ltmp = l2;
-			l2 = l2->l_next;
-			free((char *) l1);
-			l1 = l1->l_next;
-		}
-	}
-	if (l1)
-		ltmp->l_next = l1;
-	else
-		ltmp->l_next = l2;
-
-	return(rval);
-}
-
-hashanalyze()
-{
-	int	probe, hash2, count, i, collision[5];
-	int	longest = 0, total = 0, slots = 0;
-	int	nslots = sizeof(collision)/sizeof(collision[0]);
-
-	if (!Vflag)
-		return;
-
-	strclear((char *) collision, sizeof(collision));
-	for (i = 0; i < Tabsize; i++) {
-		if (Table[i] == 0)
-			continue;
-		/* private hosts too hard to account for ... */
-		if (index(Table[i]->n_name, '!'))
-			continue;
-		count = 1;
-		probe = fold(Table[i]->n_name);
-		/* don't change the order of the next two lines */
-		hash2 = HASH2(probe);
-		probe = HASH1(probe);
-		/* thank you! */
-		while (Table[probe] != 0
-		    && strcmp(Table[probe]->n_name, Table[i]->n_name) != 0) {
-			count++;
-			probe -= hash2;
-			if (probe < 0)
-				probe += Tabsize;
-		}
-		if (Table[probe] == 0) {
-			fprintf(stderr, "%s: impossible hash error for %s\n",
-					ProgName, Table[i]->n_name);
-			continue;
-		}
-		
-		total += count;
-		slots++;
-		if (count > longest)
-			longest = count;
-		if (count >= nslots)
-			count = 0;
-		collision[count]++;
-	}
-	for (i = 1; i < nslots; i++)
-		if (collision[i])
-			fprintf(stderr, "%d chains: %d (%d%%)\n",
-				i, collision[i], (collision[i] * 100)/ slots);
-		if (collision[0])
-			fprintf(stderr, "> %d chains: %d (%d%%)\n",
-				nslots - 1, collision[0],
-				(collision[0] * 100)/ slots);
-	fprintf(stderr, "%2.2f probes per access, longest chain: %d\n",
-		(double) total / slots, longest);
-}
-
-STATIC void
-lowercase(s)
-char *s;
-{
-	do
-		*s = isupper(*s) ? tolower(*s) : *s;
-	while (*s++);
-}
-
-STATIC node	*
-isprivate(name)
-char	*name;
-{
-	node	*n;
-
-	for (n = Private; n != 0; n = n->n_private)
-		if (strcmp(name, n->n_name) == 0)
-			return(n);
-	return(0);
-}
-
-fixprivate()
-{
-	node	*n;
-	char	buf[BUFSIZ];
-
-	for (n = Private; n != 0; n = n->n_private) {
-		sprintf(buf, "%s!%s", n->n_name, Cfile);
-
-		/*
-		 * can't handle repeated input file containing
-		 * private definitions.
-		 * continue anyway, generating duplicate output.
-		 */
-		if (Table[hash(buf, 0)] != 0)
-			fprintf(stderr, "%s: input file %s used twice\n",
-				ProgName, Cfile);
-
-		free(n->n_name);
-		n->n_name = strsave(buf);
-	}
-	Private = 0;
-}
//GO.SYSIN DD addnode.c
sed 's/.//' >gethostnam.c <<'//GO.SYSIN DD gethostnam.c'
-#ifndef lint
-static char	*sccsid = "@(#)gethostnam.c	6.1 (down!honey) 85/01/21";
-#endif lint
-
-#ifndef GETHOSTNAME
-#include <stdio.h>
-
-void
-gethostname(name, len)
-char	*name;
-{
-	FILE	*whoami, *fopen(), *popen();
-	char	*ptr, *index();
-
-	*name = '\0';
-
-	/* try /etc/whoami */
-	if ((whoami = fopen("/etc/whoami", "r")) != 0) {
-		(void) fgets(name, len, whoami);
-		(void) fclose(whoami);
-		if ((ptr = index(name, '\n')) != 0)
-			*ptr = '\0';
-	}
-	if (*name)
-		return;
-
-	/* try /usr/include/whoami.h */
-	if ((whoami = fopen("/usr/include/whoami.h", "r")) != 0) {
-		while (!feof(whoami)) {
-			char	buf[100];
-
-			if (fgets(buf, 100, whoami) == 0)
-				break;
-			if (sscanf(buf, "#define sysname \"%[^\"]\"", name))
-				break;
-		}
-		(void) fclose(whoami);
-		if (*name)
-			return;
-	}
-
-	/* ask uucp */
-	if ((whoami = popen("uuname -l", "r")) != 0) {
-		(void) fgets(name, len, whoami);
-		(void) pclose(whoami);
-		if ((ptr = index(name, '\n')) != 0)
-			*ptr = '\0';
-	}
-	if (*name)
-		return;
-	
-	/* aw hell, i give up!  is this a real unix? */
-	return;
-}
-#endif GETHOSTNAME
//GO.SYSIN DD gethostnam.c
sed 's/.//' >lex.l <<'//GO.SYSIN DD lex.l'
-%{
-/* pathalias -- by steve bellovin, as told to peter honeyman */
-#ifndef lint
-static char	*sccsid = "@(#)lex.l	6.1 (down!honey) 85/01/21";
-#endif lint
-
-#include "def.h"
-#include "y.tab.h"
-
-extern	YYSTYPE yylval;
-
-static costing = 0;
-static private = 0;
-static struct ctable {
-	char *cname;
-	Cost cval;
-} ctable[] = {
-	/*
-	 * this list is searched sequentially (with strcmps!).
-	 * it is too long.
-	 */
-	{"DEMAND", 300},
-	{"DAILY", 5000},
-	{"DIRECT", 200},
-	{"DEDICATED", 95},
-	{"DIAL", 300},
-	{"LOCAL", 25},
-	{"HOURLY", 500},
-	{"EVENING", 1800},
-	{"WEEKLY", 30000},
-	{"ARPA", 100},
-	{"HIGH", -5},	/* baud rate bonus */
-	{"LOW", 5},	/* baud rate penalty */
-	{"DEAD", INF/2},
-	{"POLLED", 5000},
-	{"A", 300},
-	{"B", 500},
-	{"C", 1800},
-	{"D", 5000},
-	{"E", 30000},
-	{"F", INF/2},
-	{"DED", 95},
-	{"DIALED", 300},
-	0
-};
-
-%}
-
-WS	[ \t]+
-NET	[!:@%]
-ALPHA	[a-zA-Z_0-9]
-SALPHA	[-+a-zA-Z_0-9]
-
-%%
-"#".*\n{WS}	{Lineno++;}
-"#".*\n		{Lineno++; return(NL);}
-{WS}		;
-^"private"{WS}"{" {
-			private++;
-			return(PRIVATE);
-		}
-^{SALPHA}+	{
-			yylval.y_node = addnode(yytext, private);
-			return(HOST);
-		}
-[0-9]+		{
-			if (costing) {
-				yylval.y_cost = (Cost) atol(yytext);
-				return(COST);
-			}
-			REJECT;
-		}
-\n{WS}		{Lineno++;}
-\n		{costing = 0; Lineno++; return(NL);}
-{NET}		{
-			yylval.y_ind = yytext[0];
-			return(NET);
-		}
-\'.\'		{
-			yylval.y_ind = yytext[1];
-			return(NET);
-		}
-{ALPHA}+	{
-			register struct ctable *ct;
-			char c, errbuf[128];
-
-			c = input(); unput(c);
-			if (costing) {
-				for (ct = ctable; ct->cname; ct++)
-					if (strcmp(ct->cname, yytext) == 0) {
-						yylval.y_cost = ct->cval;
-						return(COST);
-					}
-				sprintf(errbuf, "unknown cost (%s), using default cost", yytext);
-				yyerror(errbuf);
-				yylval.y_cost = DEFCOST;
-				return(COST);
-			} else if (c=='-' || c=='+')
-				yymore();
-			else {
-				yylval.y_node = addnode(yytext, private);
-				return(SITE);
-			}
-		}
-\"[^"]*		{
-			if (yytext[yyleng-1] == '\\')
-				yymore();
-			else {
-				yylval.y_node = addnode(yytext+1, private);
-				input();
-				return(SITE);
-			}
-		}
-
-"{"				{
-					costing = 0;
-					yylval.y_s.ys_ind = '\0';
-					yylval.y_s.ys_dir = DEFDIR;
-					return(LNET);
-				}
-{NET}"{"			{
-					costing = 0;
-					yylval.y_s.ys_ind = yytext[0];
-					yylval.y_s.ys_dir = LRIGHT;
-					return(LNET);
-				}
-"}"				{
-					private = costing = 0;
-					yylval.y_s.ys_ind = '\0';
-					yylval.y_s.ys_dir = DEFDIR;
-					return(RBRACE);
-				}
-"}"{NET}			{
-					private = costing = 0;
-					yylval.y_s.ys_ind = yytext[1];
-					yylval.y_s.ys_dir = LLEFT;
-					return(RBRACE);
-				}
-
-"("				{costing++; return(LPAREN);}
-")"				{costing--; return(RPAREN);}
-","				{costing = 0; return(COMMA);}
-"="				{costing = 0; return(EQUALS);}
-"+"				{if (yyleng > 1) yymore(); else return(PLUS);}
-"-"				{if (yyleng > 1) yymore(); else return(MINUS);}
-"*"				{return(TIMES);}
-"/"				{return(DIVIDE);}
-.				{return(yytext[0]);}
-%%
-yywrap()
-{
-	char	errbuf[100];
-
-	fixprivate();	/* munge private host definitions */
-
-	if (Ifiles == 0) 
-		return(1);
-
-	fclose(stdin);
-	while (*Ifiles) {
-		Lineno = 1;
-		Fcnt++;
-		if (fopen((Cfile = *Ifiles++), "r"))
-			return(0);
-		sprintf(errbuf, "%s: %s", ProgName, Cfile);
-		perror(errbuf);
-	}
-	return(1);
-}
//GO.SYSIN DD lex.l
sed 's/.//' >local.c <<'//GO.SYSIN DD local.c'
-/* pathalias -- by steve bellovin, as told to peter honeyman */
-#ifndef lint
-static char	*sccsid = "@(#)local.c	6.1 (down!honey) 85/01/21";
-#endif lint
-
-#include <stdio.h>
-#include "config.h"
-
-#ifdef	UNAME
-#include <sys/utsname.h>
-struct utsname utsname;
-#endif	UNAME
-
-char	*
-local()
-{
-#ifdef	UNAME
-	uname(&utsname);
-	return(utsname.nodename);
-#else !UNAME
-	static char lname[64];
-	void	gethostname();
-
-	gethostname(lname, sizeof(lname));
-	return(lname);
-#endif	UNAME
-}
//GO.SYSIN DD local.c
sed 's/.//' >main.c <<'//GO.SYSIN DD main.c'
-/* pathalias -- by steve bellovin, as told to peter honeyman */
-#ifndef lint
-static char	*sccsid = "@(#)main.c	6.1 (down!honey) 85/01/21";
-#endif lint
-
-#include "def.h"
-
-node	*Home;
-int	Fcnt = -1;
-char	*Cfile;
-char	**Ifiles;
-char	*ProgName;
-int	Vflag;
-int	Cflag;
-int	Bflag;
-int	Pflag;
-int	Iflag;
-int	Lineno = 1;
-char	*Netchars = "!:@%";	/* sparse, but sufficient */
-int	Ncount;
-int	Lcount;
-char	*Pathout = ALIASDB;
-char	*Graphout = 0;
-int	Netid;
-node	*Private = 0;	/* list of private nodes in this file */
-
-main(argc, argv) 
-int	argc; 
-char	*argv[];
-{
-	char	*locname = 0, *pptr;
-
-#ifdef lint
-	argc = argc;
-#endif lint
-
-	ProgName = argv[0];
-	while (*++argv && **argv == '-') {
-		(*argv)++;
-		switch(**argv) {
-
-		case 'l':	/* local name */
-			locname = *++argv;
-			if (!*locname)  {
-				fprintf(stderr, "%s: -l requires host name\n",
-					ProgName);
-				exit(1);
-			}
-			break;
-
-		case 'd':	/* dead host or link */
-			if (!*++argv) {
-				fprintf(stderr, "%s: -d requires host name\n",
-					ProgName);
-				exit(1);
-			}
-			deadlink(*argv);
-			break;
-
-		case 'P':	/* dbm output file */
-			Pathout = *++argv;
-			if (!*Pathout)  {
-				fprintf(stderr, "%s: -P requires output file name\n",
-					ProgName);
-				exit(1);
-			}
-			if ((pptr = rindex(Pathout, '/')) != 0)
-				pptr++;
-			else
-				pptr = Pathout;
-			if (strlen(pptr) > 10) {
-				pptr[10] = 0;
-				fprintf(stderr, "%s: using %s for db output\n",
-					ProgName, Pathout);
-			}
-			break;
-
-		case 'g':	/* graph output file */
-			Graphout = *++argv;
-			if (!*Graphout)  {
-				fprintf(stderr, "%s: -g requires output file name\n",
-					ProgName);
-				exit(1);
-			}
-			break;
-
-		case 0:
-			break;	/* ignore naked '-' */
-
-		default:
-			while (**argv) switch (*((*argv)++)) {
-			
-			case 'v':	/* verbose stderr, somewhat boring */
-				Vflag++;
-				break;
-
-			case 'c':	/* print cost info */
-				Cflag++;
-				break;
-
-			case 'i':	/* ignore case */
-				Iflag++;
-				break;
-
-			case 'b':	/* make a dbm database */
-#ifdef DBM
-				Bflag++;
-#else !DBM
-				fprintf(stderr, "%s: not compiled for dbm (warning)\n",
-					ProgName);
-#endif DBM
-				break;
-
-			case 'p':	/* print, even if -b */
-				Pflag++;
-				break;
-
-			default:
-				fprintf(stderr, "%s: %s: unknown flag\n", ProgName,
-					*argv);
-				exit(1);
-			}
-		}
-	}
-
-	Fcnt++;
-	if (*argv) {
-		Ifiles = argv;
-		freopen("/dev/null", "r", stdin);
-	}
-
-	if (!locname) 
-		locname = local();
-	if (*locname == 0) {
-		locname = "lostinspace";
-		fprintf(stderr, "%s: using \"%s\" for local name\n",
-				ProgName, locname);
-	}
-
-	Home = addnode(locname, 0);	/* add home node */
-	Home->n_cost = 0;		/* doesn't cost to get here */
-
-	yyparse();			/* read in link info */
-
-	hashanalyze();
-
-	while (Home->n_alias) 
-		Home = Home->n_alias;	/* bad practice, but conceivable */
-
-	mapit();			/* compute shortest paths */
-
-#ifdef	SHOWLINK
-	showall();
-#endif	SHOWLINK
-
-	exit(0);
-}
-
-badmagic(n)
-{
-#ifdef DEBUG
-	abort();
-#else !DEBUG
-	exit(n);
-#endif DEBUG
-}
//GO.SYSIN DD main.c
sed 's/.//' >mapit.c <<'//GO.SYSIN DD mapit.c'
-/* pathalias -- by steve bellovin, as told to peter honeyman */
-#ifndef lint
-static char	*sccsid = "@(#)mapit.c	6.1 (down!honey) 85/01/21";
-#endif lint
-
-#include "def.h"
-
-void	reheap(), insert(), setpath(), pack(), swap();
-node	*min_node();
-
-static int	Hashpart, Nheap;
-
-#ifdef DBM
-typedef struct {char *dptr; int dsize;} datum;
-#endif DBM
-
-mapit()
-{
-	node *n, *next;
-	link *l;
-	Cost	cost;
-#ifdef	DBM
-	char alif[200];
-#endif
-	char	*sbrk();
-
-	vprintf(stderr, "%d vertices, %d edges\n", Ncount, Lcount);
-	vprintf(stderr, "break is %d after parsing\n", sbrk(0));
-	
-#ifdef DBM
-	if (Bflag) {
-		sprintf(alif, "%s.dir", Pathout);
-		if (close(creat(alif,0644)) < 0) {
-			fprintf(stderr, "%s: ", ProgName);
-			perror(alif);
-			Bflag = 0;	/* print to stdout */
-		}
-		sprintf(alif, "%s.pag", Pathout);
-		if (close(creat(alif,0644)) < 0) {
-			fprintf(stderr, "%s: ", ProgName);
-			perror(alif);
-			Bflag = 0;	/* print to stdout */
-		}
-		if (Bflag)
-			dbminit(Pathout);
-	}
-#endif
-	/* use the hash Table for the heap */
-	/* TODO: coalesce the following functions into a single one */
-	pack();		/* remove holes in the Table */
-	rename();	/* restore private names to standard form */
-	amerge();	/* merge all alias links once and for all */
-	if (Graphout && *Graphout)	/* dump the edge list */
-		dumpgraph();
-
-	dehash(Home);
-	Home->n_path = strsave("%s");
-	insert(Home);
-
-	while ((n = min_node()) != 0) {
-		printit(n);
-		for (l = n->n_link; l != 0; l = l->l_next) {
-			next = l->l_to;
-			while (next->n_alias)
-				next = next->n_alias;
-			if (next->n_flag & MAPPED)
-				continue;
-			dehash(next);
-			cost = n->n_cost + l->l_cost;
-			/*
-			 * heuristics:
-			 *    charge for getting out of a dead host.
-			 *    charge for getting in to a dead net
-			 *         unless the link cost is non-zero (gateway).
-			 *    charge for a dead link.
-			 *    discourage mixing of left and right syntax.
-			 */
-			if ((n->n_flag & (NNET | NDEAD)) == NDEAD)
-				cost += INF/2;	/* dead host */
-			if (((next->n_flag & (NNET | NDEAD)) == (NNET | NDEAD))
-			 && (l->l_cost == 0))
-				cost += INF/2;	/* dead net */
-			if (l->l_flag & LDEAD)
-				cost += INF/2;	/* dead link */
-			if ((n->n_flag & HASLEFT) && (NETDIR(l) == LRIGHT))
-				cost += DEFCOST;	/* mix */
-			if ((n->n_flag & HASRIGHT) && (NETDIR(l) == LLEFT))
-				cost += DEFCOST;	/* mix */
-
-			if (next->n_cost == 0) {
-				next->n_cost = cost;
-				insert(next);
-			} else if (cost < next->n_cost) {
-				next->n_cost = cost;
-				reheap(next);
-			} else
-				continue;
-
-			setpath(next, n, NETCHAR(l), NETDIR(l));
-
-			free((char *) l);	
-		}
-		free((char *) n->n_path);
-		free((char *) n->n_name);
-		for (next = n->n_aliaslink; next; next = next->n_aliaslink) {
-			/* expunge aliases */
-			dehash(next);
-			Table[next->n_tloc] = 0;
-			next->n_tloc = 0;
-			free((char *) next->n_name);
-		}
-	}
-	vprintf(stderr, "break is %d at after mapping\n", sbrk(0));
-
-	if (Nheap != 0) {
-		fprintf(stderr, "%s: null entry found in heap\n", ProgName);
-		badmagic(1);
-	}
-
-	if (Hashpart < Tabsize) {
-		fprintf(stderr, "You can't get there from here:\n");
-		while (Hashpart < Tabsize) {
-			n = Table[Hashpart++];
-			if (n->n_alias)
-				continue;	/* primary hosts only */
-			fprintf(stderr, "\t%s", n->n_name);
-			if (n->n_aliaslink) {
-				fprintf(stderr, " (alias %s", n->n_aliaslink->n_name);
-				n = n->n_aliaslink;
-				while (n = n->n_aliaslink)
-					fprintf(stderr,  ", %s", n->n_name);
-				putc(')', stderr);
-			}
-			putc('\n', stderr);
-		}
-	}
-}
-
-/*
- * heap implementation of priority queue.
- */
-
-STATIC void
-insert(n)
-node	*n;
-{
-	int	i, parent;
-
-	Table[n->n_tloc] = 0;
-	if (Table[Nheap+1] != 0) {
-		fprintf(stderr, "%s: heap error in insert\n", ProgName);
-		badmagic(1);
-	}
-	if (Nheap++ == 0) {
-		Table[1] = n;
-		n->n_tloc = 1;
-		return;
-	}
-
-	/* insert at the end and percolate up */
-	Table[Nheap] = n;
-	n->n_tloc = Nheap;
-	for (i = Nheap; i > 1; i = parent) {
-		if (Table[i] == 0) {
-			fprintf(stderr, "%s: heap error in insert\n", ProgName);
-			badmagic(1);
-		}
-		parent = i / 2;
-		if (Table[i]->n_cost < Table[parent]->n_cost)
-			swap(i, parent);
-	}
-	return;
-}
-
-STATIC node	*
-min_node()
-{
-	node	*rval;
-	int	i;
-
-	if (Nheap == 0)
-		return(0);
-
-	rval = Table[1];	/* return this one */
-			
-	/* move last entry into root, percolate down */
-	Table[1] = Table[Nheap];
-	Table[1]->n_tloc = 1;
-	Table[Nheap] = 0;
-	if (--Nheap == 0)
-		return(rval);
-
-	i = 1;
-	for (;;) {
-		/* swap with smaller child  (if larger than same) */
-		int	child;
-
-		child = i * 2;
-		if (child > Nheap)
-			break;
-		if (child + 1 < Nheap) 		/* right child exists? */
-			if (Table[child]->n_cost > Table[child+1]->n_cost)
-				child++;
-			
-		if (Table[i]->n_cost > Table[child]->n_cost)
-			swap(i, child);
-		i = child;
-	}
-
-	return(rval);
-}
-
-STATIC void
-swap(i, j)
-{
-	node	*temp;
-
-	temp = Table[i];
-	Table[i] = Table[j];
-	Table[j] = temp;
-	Table[j]->n_tloc = j;
-	Table[i]->n_tloc = i;
-}
-
-
-/* "percolate" node n up the heap by exchanging with the parent */
-STATIC void
-reheap(n)
-node	*n;
-{
-	int	loc, parent;
-	Cost	cost;
-
-	cost = n->n_cost;
-	for (loc = n->n_tloc; loc != 1; loc = parent) {
-		parent = loc / 2;
-		if (cost >= Table[parent]->n_cost)
-			return;
-		swap(loc, parent);
-	}
-}
-
-STATIC void
-setpath(n, prev, netchar, netdir) 
-node	*n, *prev;
-char	netchar, netdir;
-{
-	char	pathbuf[BUFSIZ], hostbuf[BUFSIZ], *name, *hptr;
-
-	/* undo settings from earlier calls */
-	if (n->n_path)
-		free((char *) n->n_path);
-
-	if (prev->n_flag & ATSIGN)
-		n->n_flag |= ATSIGN;
-	else
-		n->n_flag &= ~ATSIGN;
-
-	if (prev->n_flag & HASLEFT)
-		n->n_flag |= HASLEFT;
-	else
-		n->n_flag &= ~HASLEFT;
-
-	if (prev->n_flag & HASRIGHT)
-		n->n_flag |= HASRIGHT;
-	else
-		n->n_flag &= ~HASRIGHT;
-
-	if (n->n_flag & NNET) {
-		n->n_path = strsave(prev->n_path);
-		return;
-	}
-
-	name = NAME(n);
-
-	/* do it by hand instead of sprintf-ing -- foo on '%' */
-	if (netdir == LLEFT) {
-		/* e.g., host!%s */
-		n->n_flag |= HASLEFT;
-		strcpy(hostbuf, name);
-		hptr = hostbuf + strlen(hostbuf);
-		*hptr++ = netchar;
-		if (netchar == '%')
-			*hptr++ = netchar;
-		*hptr++ = '%';
-		*hptr++ = 's';
-		*hptr = 0;
-	} else {
-		/* e.g., %s@host, but watch out for the magic @-% conversion */
-		n->n_flag |= HASRIGHT;
-		if (netchar == '@') {
-			n->n_flag |= ATSIGN;
-			if (prev->n_flag & ATSIGN)
-				netchar = '%';	/* shazam?  shaman? */
-		}
-		hptr = hostbuf;
-		*hptr++ = '%';
-		*hptr++ = 's';
-		*hptr++ = netchar;
-		if (netchar == '%')
-			*hptr++ = netchar;
-		strcpy(hptr, name);
-	}
-	/* this would be an sprintf were it not for the %'s.  feh. */
-	pathprintf(pathbuf, prev->n_path, hostbuf);
-	n->n_path = strsave(pathbuf);
-}
-
-
-dehash(n)
-node	*n;
-{
-	if (n->n_flag & DEHASH)
-		return;
-	Table[Hashpart]->n_tloc = n->n_tloc;
-	Table[n->n_tloc] = Table[Hashpart];
-	Table[Hashpart] = n;
-	n->n_flag |= DEHASH;
-	n->n_tloc = Hashpart++;
-}
-
-STATIC void
-pack()
-{
-	int	hole, next;
-
-	/* find first "hole " */
-	for (hole = Tabsize - 1; hole >= 0 && Table[hole] != 0; --hole)
-		;
-
-	/* repeatedly move next filled entry into last hole */
-	for (next = hole - 1; next >= 0; --next) {
-		if (Table[next] != 0) {
-			Table[hole] = Table[next];
-			Table[hole]->n_tloc = hole;
-			Table[next] = 0;
-			while (Table[--hole] != 0)	/* find next hole */
-				;
-		}
-	}
-	Hashpart = hole + 1;
-}
-
-#ifdef DBM
-wdb(name, path)
-char *name, *path;
-{
-	datum dbkey, dbpath;
-
-	dbkey.dptr = name;
-	dbkey.dsize = strlen(name)+1;
-	dbpath.dptr = path;
-	dbpath.dsize = strlen(path)+1;
-	if (store(dbkey, dbpath))
-		fprintf(stderr, "%s: dbm error at %s->%s\n",
-						ProgName, name, path);
-}
-#endif DBM
-
-pathprintf(buf, path, host)
-char	*buf, *path, *host;
-{
-	for ( ; *buf = *path; path++) {
-		if (*path == '%') {
-			switch(path[1]) {
-			case 's':
-				strcpy(buf, host);
-				buf += strlen(buf);
-				path++;
-				break;
-			case '%':
-				*++buf = *++path;
-				break;
-			}
-		} else
-			buf++;
-	}
-}
-
-amerge()
-{
-	node	*n, *a;
-	int	i;
-
-	for (i = Hashpart; i < Tabsize; i++) {
-		n = Table[i];
-		if (n == 0)	/* impossible, but ... */
-			continue;
-		for (a = n->n_alias; a; a = a->n_alias) {
-			a->n_link = lmerge(a->n_link, n->n_link);
-			n->n_link = 0;
-			n = a;
-		}
-	}
-}
-
-printit(n)
-node	*n;
-{
-	char	*path = n->n_path;
-	Cost	cost = n->n_cost;
-
-	for ( ; n; n = n->n_aliaslink) {
-		n->n_flag |= MAPPED;
-		if (n->n_flag & NNET)
-			continue;
-#ifdef DBM
-		if (Bflag)
-			wdb(n->n_name, path);
-		if (Pflag || !Bflag)
-#endif
-		{
-			if (Cflag)
-				printf("%ld\t", (long) cost);
-			printf("%s\t%s\n", n->n_name, path);
-		}
-	}
-}
-
-static FILE	*estream;
-
-dumpgraph()
-{
-	int	i;
-	long	seekstart, seekend;
-	node	*n;
-	char	edges[256], blocks[256], command[256];
-	FILE	*bstream, *fopen(), *popen();
-
-	untangle();
-	sprintf(edges, "%s.e", Graphout);
-	sprintf(blocks, "%s.b", Graphout);
-	if ((estream = fopen(edges, "w")) == NULL) {
-		fprintf(stderr, "%s: ", ProgName);
-		perror(edges);
-		return;
-	}
-	sprintf(command, "sort -o %s", blocks);
-	if ((bstream = popen(command, "w")) == NULL) {
-		fprintf(stderr, "%s: ", ProgName);
-		perror(command);
-		fclose(bstream);
-		return;
-	}
-
-	seekstart = 0;
-	for (i = Hashpart; i < Tabsize; i++) {
-		n = Table[i];
-		if (n == 0)
-			continue;	/* impossible, but ... */
-		if (n->n_alias)
-			continue;
-		/* a minor optimization ... */
-		if (n->n_link == 0)
-			continue;
-		/* special treatment for nets */
-		if ((n->n_flag & NNET) && n->n_root != n)
-			continue;
-		fprintf(bstream, "%s\t%d", n->n_name, seekstart);
-		fprintf(estream, "!%s\n", n->n_name);
-		dumplist(n);
-		seekend = ftell(estream);
-		fprintf(bstream, "\t%d\n", seekend - seekstart);
-		seekstart = seekend;
-	}
-	fclose(estream);
-	pclose(bstream);
-}
-
-dumplist(n)
-node	*n;
-{
-	node	*nxt, *r0, *r1;
-	link	*l;
-
-	if ((n->n_flag & (DUMP | NNET)) == (DUMP | NNET))
-		return;
-	if (n->n_flag & NNET) {
-		n->n_flag |= DUMP;
-		/* get to root of n */
-		for (r0 = n->n_root; r0 && r0 != r0->n_root; r0 = r0->n_root)
-			;
-	}
-	for (l = n->n_link ; l; l = l->l_next) {
-		nxt = l->l_to;
-		while (nxt->n_alias)
-			nxt = nxt->n_alias;
-		if (n == nxt)
-			continue;
-		if (nxt->n_flag & NNET) {
-			/* get to root of nxt */
-			for (r1 = nxt->n_root;
-			    r1 && r1 != r1->n_root;
-				r1 = r1->n_root)
-				    ;
-			/* are nxt and n nets on a common cycle? */
-			if ((n->n_flag & NNET) && r0 == r1) {
-				dumplist(nxt);
-				continue;
-			}
-
-			putc('#', estream);
-			fputs(r1->n_name, estream);
-		} else
-			fputs(nxt->n_name, estream);
-		putc('\n', estream);
-	}
-}
-
-rename()
-{
-	char	*bang;
-	node	*n;
-	int	i;
-
-	for (i = Hashpart; i < Tabsize; i++) {
-		n = Table[i];
-		if (n == 0 || (n->n_flag & ISPRIVATE) == 0)
-			continue;
-		if ((bang = index(n->n_name, '!')) == 0)
-			fprintf(stderr,
-				"%s: internal error on private host %s\n",
-					ProgName, n->n_name);
-			else
-				*bang = 0;
-	}
-}
-
-/*
- * remove cycles in net definitions. 
- *
- * strategy:  well, let's see, we've used a priority queue,
- * a heap, several hash strategies, binary search, bipartite
- * matching ... what's left?
- *
- * depth-first search, of course!  for each net, run
- * dfs on its neighbors (nets only).  if we return to
- * a visited node, that's a net cycle.  mark the cycle with
- * a pointer in the n_root field (which gets us closer to
- * the root of this portion of the dfs tree).
- */
-untangle()
-{
-	int	i;
-	node	*n;
-
-	for (i = Hashpart; i < Tabsize; i++) {
-		n = Table[i];
-		if (n == 0 || (n->n_flag & NNET) == 0 || n->n_root)
-			continue;
-		dfs(n);
-	}
-}
-
-dfs(n)
-node	*n;
-{
-	link	*l;
-	node	*next;
-
-	n->n_flag |= INDFS;
-	n->n_root = n;
-	for (l = n->n_link; l; l = l->l_next) {
-		next = l->l_to;
-		if ((next->n_flag & NNET) == 0)
-			continue;
-		if ((next->n_flag & INDFS) == 0) {
-			dfs(next);
-			if (next->n_root != next)
-				n->n_root = next->n_root;
-		} else
-			n->n_root = next->n_root;
-	}
-	n->n_flag &= ~INDFS;
-}
//GO.SYSIN DD mapit.c
sed 's/.//' >mem.c <<'//GO.SYSIN DD mem.c'
-/* pathalias -- by steve bellovin, as told to peter honeyman */
-#ifndef lint
-static char	*sccsid = "@(#)mem.c	6.1 (down!honey) 85/01/21";
-#endif lint
-
-#include "def.h"
-
-link	*
-newlink()
-{
-	link	*rval;
-
-	if ((rval = (link * ) malloc(sizeof(link))) == 0)
-		nomem();
-	strclear((char *) rval, sizeof(link));	/* fresh as a daisy */
-	Lcount++;
-	return(rval);
-}
-
-node	*
-newnode()
-{
-	node	*rval;
-
-	if ((rval = (node * ) malloc(sizeof(node))) == 0)
-		nomem();
-	strclear((char *) rval, sizeof(node));	/* fresh as a daisy */
-	Ncount++;
-	return(rval);
-}
-
-char	*
-strsave(s)
-char	*s;
-{
-	char *r;
-
-	if ((r = malloc(strlen(s) + 1)) == 0)
-		nomem();
-	(void) strcpy(r, s);
-	return(r);
-}
-
-void
-strclear(dst, len)
-char *dst;
-int len;
-{
-#ifdef lint
-	dst = dst;
-	len = len;
-#endif lint
-
-#ifdef vax
-	asm("movc5 $0,*4(ap),$0,8(ap),*4(ap)");
-#else !vax
-	while (--len >= 0)
-		*dst++ = 0;
-#endif vax
-}
-
-node	**
-newtable(size)
-int	size;
-{
-	node	**rval;
-
-	if ((rval = (node **) malloc(size * sizeof(*rval))) == 0) 
-		nomem();
-	strclear((char *) rval, size * sizeof(*rval));
-	return(rval);
-}
-
-nomem()
-{
-	fprintf(stderr, "%s: Out of memory\n", ProgName);
-	badmagic(1);
-}
-
-#ifdef MYMALLOC
-char	*
-mymalloc(n)
-register int	n;
-{
-	static int	size;
-	static char	*mem;
-	register char	*rval;
-
-	if (n > BUFSIZ)
-		rval = memget(n);
-	else {
-#ifdef ALIGN
-		int adjustment;
-
-		adjustment = align(mem);
-		mem += adjustment;
-		size -= adjustment;
-#endif ALIGN
-		if (n > size) {
-			mem = memget(BUFSIZ);
-			size = BUFSIZ;
-		}
-		rval = mem;
-		mem += n;
-		size -= n;
-	}
-	return(rval);
-}
-
-myfree(s)
-char	*s;
-{
-#ifdef lint
-	s = s;
-#endif lint
-}
-
-#ifdef ALIGN
-char	*
-memget(n)
-int	n;
-{
-	char	*rval;
-	int	abits;	/* alignment bits */
-	int	adjustment = 0;
-
-	adjustment = align(sbrk(0));
-	rval = sbrk(n + adjustment);
-	if (rval <= 0)
-		return(0);
-	return(rval + adjustment);
-}
-
-align(n)
-char	*n;
-{
-	int	abits;	/* alignment bits */
-	int	adjustment = 0;
-	int	foo;
-
-	abits = (long) n & ~(0xff << ALIGN) & 0xff;
-	if (abits != 0)
-		adjustment = (1 << ALIGN) - abits;
-	return(adjustment);
-}
-#endif ALIGN
-
-#endif MYMALLOC
//GO.SYSIN DD mem.c
sed 's/.//' >parse.y <<'//GO.SYSIN DD parse.y'
-%{
-/* pathalias -- by steve bellovin, as told to peter honeyman */
-#ifndef lint
-static char	*sccsid = "@(#)parse.y	6.1 (down!honey) 85/01/21";
-#endif lint
-
-#include "def.h"
-
-%}
-
-%union {
-	node *y_node;
-	Cost	y_cost;
-	char	y_ind;
-	struct y_s {
-		node *ys_node;
-		Cost ys_cost;
-		char ys_ind;
-		char ys_dir;
-	} y_s;
-}
-
-%type <y_s> site sitenet lnetl
-%type <y_node> links aliases plist
-%type <y_cost> cost
-
-%token <y_node>	HOST SITE
-%token <y_cost>	COST
-%token <y_ind>	NET
-%token <y_s>	LNET RBRACE
-%token LPAREN RPAREN COMMA EQUALS NL PRIVATE
-
-%left	PLUS MINUS
-%left	TIMES DIVIDE
-
-%%
-map	:	/* empty */
-	|	map NL
-	|	map links NL
-	|	map aliases NL
-	|	map lnet NL
-	|	map private NL
-	|	error NL
-	;
-
-private	:	PRIVATE plist RBRACE =
-		{
-			if ($3.ys_ind != 0)
-				yyerror("cost ignored on private definition (warning)\n");
-			Private = $2;
-		}
-	;
-
-plist	:	SITE =
-		{
-			if (($1->n_flag & ISPRIVATE) != 0) {
-				/* we can live with this */
-				yyerror("warning: redefinition of private node ");
-				fprintf(stderr, "%s\n", $1->n_name);
-			}
-			$1->n_flag |= ISPRIVATE;
-		}
-	|	plist COMMA SITE =
-		{
-			if (($3->n_flag & ISPRIVATE) != 0) {
-				/* we can live with this */
-				yyerror("warning: redefinition of private node ");
-				fprintf(stderr, "%s\n", $3->n_name);
-			}
-			$3->n_private = $1;
-			$3->n_flag |= ISPRIVATE;
-			$$ = $3;
-		}
-	;
-		
-lnet	:	lnetl RBRACE =
-		{
-			fixnet($1.ys_node, &$1, &$2, DEFCOST, Netid);
-		}
-	|	lnetl RBRACE LPAREN cost RPAREN =
-		{
-			fixnet($1.ys_node, &$1, &$2, $4, Netid);
-		}
-	;
-
-lnetl	:	HOST EQUALS LNET SITE =
-		{
-#ifdef notdef
-			/* this doesn't work.  should it? */
-			if ($1->n_flag & NNET) {
-				yyerror("redefinition of network: ");
-				fprintf(stderr, "%s\n", $1->n_name);
-				YYERROR;
-			}
-			if ($1->n_link) {
-				yyerror("host/network conflict: ");
-				fprintf(stderr, "%s\n", $1->n_name);
-				YYERROR;
-			}
-#endif notdef
-			Netid++;
-			$1->n_flag |= NNET;
-			/*
-			 * set up 0 cost network -> member now.
-			 * later, in fixnet(), we will adjust the
-			 * cost and add a 0 cost member -> network
-			 */
-			addlink($1, $4, (Cost) 0, $3.ys_ind,
-				$3.ys_dir)->l_lnet = Netid;
-			$3.ys_node = $1;
-			$$ = $3;
-		}
-	|	lnetl COMMA SITE =
-		{
-			/* see comment above */
-			addlink($1.ys_node, $3, (Cost) 0, $1.ys_ind,
-				$1.ys_dir)->l_lnet=Netid;
-		}
-	;
-
-aliases	:	HOST EQUALS SITE =
-		{
-			alias($1, $3);
-		}
-	|	aliases COMMA SITE =
-		{
-			alias($1, $3);
-		}
-	;
-
-links	:	HOST site =
-		{
-#ifdef notdef
-			/* this doesn't work.  should it? */
-			if ($1->n_flag & NNET) {
-				yyerror("host/network conflict\n");
-				YYERROR;
-			}
-#endif notdef
-			addlink($1, $2.ys_node, $2.ys_cost, $2.ys_ind, $2.ys_dir);
-		}
-	|	links COMMA site =
-		{
-			addlink($1, $3.ys_node, $3.ys_cost, $3.ys_ind, $3.ys_dir);
-		}
-	;
-
-site	:	sitenet =
-		{
-			$$.ys_cost = DEFCOST;
-		}
-	|	sitenet LPAREN cost RPAREN =
-		{
-			$$.ys_cost =$3;
-		}
-	;
-
-sitenet	:	NET SITE =
-		{
-			$$.ys_node = $2;
-			$$.ys_ind = $1;
-			$$.ys_dir = LRIGHT;
-		}
-	|	SITE NET =
-		{
-			$$.ys_node = $1;
-			$$.ys_ind = $2;
-			$$.ys_dir = LLEFT;
-		}
-	|	SITE =
-		{
-			$$.ys_node=$1;
-			$$.ys_ind=DEFNET;
-			$$.ys_dir=DEFDIR;
-		}
-	;
-
-cost	:	COST
-	|	LPAREN cost RPAREN =
-		{
-			$$ = $2;
-		}
-	|	cost PLUS cost =
-		{
-			$$ = $1 + $3;
-		}
-	|	cost MINUS cost =
-		{
-			$$ = $1 - $3;
-		}
-	|	cost TIMES cost =
-		{
-			$$ = $1 * $3;
-		}
-	|	cost DIVIDE cost =
-		{
-			if ($3 == 0)
-				yyerror("zero term in divison\n");
-			else
-				$$ = $1 / $3;
-		}
-	;
-
-%%
-
-yyerror(s) char *s;
-{
-	/* a concession to ucb's error(1) */
-	if (Cfile)
-		fprintf(stderr, "\"%s\", ", Cfile);
-	else
-		fprintf(stderr, "%s: ", ProgName);
-	fprintf(stderr, "line %d: %s\n", Lineno, s);
-}
-
-fixnet(n, yl, yr, cost, netid)
-node	*n;
-YYSTYPE	*yl, *yr;
-Cost	cost;
-int	netid;
-{
-	link	*l;
-	char	netdir;
-	char	netchar;
-
-	if (yl->y_s.ys_ind && yr->y_s.ys_ind) {
-		yyerror("two net indicators\n");
-		netchar = DEFNET;
-		netdir = DEFDIR;
-	} else if (yl->y_s.ys_ind) {
-		netchar = yl->y_s.ys_ind;
-		netdir = yl->y_s.ys_dir;
-	} else if (yr->y_s.ys_ind) {
-		netchar = yr->y_s.ys_ind;
-		netdir = yr->y_s.ys_dir;
-	} else {
-		netchar = DEFNET;
-		netdir = DEFDIR;
-	}
-
-	for (l = n->n_link; l; l = l->l_next)
-		if (l->l_lnet == netid) {
-			l->l_flag &= ~(LNETCHARS|LDIR);
-			l->l_flag |= netbits(netchar) | dirbits(netdir);
-			l->l_cost = cost;
-			(void) addlink(l->l_to, n, (Cost) 0, netchar, netdir);
-		}
-}
//GO.SYSIN DD parse.y
exit