[net.sources] Pathalias Sources

bbanerje@sjuvax.UUCP (12/17/83)

Following are the sources for Pathalias.  Expand the script with
/bin/sh in an EMPTY directory.  Pathalias was written by Steve
Bellovin (ulysses!smb).  This distribution came to me courtesy of
Bill Sebok (astrovax!wls).  To get maximum utility out of this, install
Bill's modifications to readnews and vnews.

Enjoy!
---------------- Cut here and feed to /bin/sh -----------------
: Run this shell script with "sh" not "csh"
PATH=:/bin:/usr/bin:/usr/ucb
export PATH
all=FALSE
if [ $1x = -ax ]; then
	all=TRUE
fi
/bin/echo 'Extracting README'
sed 's/^X//' <<'//go.sysin dd *' >README
This directory contains the sources of Pathalias, as well as a 
various auxiliary scripts necessary to get the most out of them.
You should do the following.

	1)  Transfer the Usenet Maps posted every month to the 'sites'
	    directory.

	2)  If you have the information posted periodically by 
	  parsec!kolstad, this should be placed in the directory
	   paths/paths.misc.  If you don't have access
	   to this information, doesn't matter.

	3)  The directory paths/paths.sites should contain the following:
	    One or more files, containing lines such as the following :
#
# Saint Joseph's University
#
sjuvax allegra(2*DEMAND), astrovax(2*DEMAND), bpa(DEMAND), 
	burdvax(DEMAND-20)
#
# allegra and astrovax get penalised because they're non local.  Burdvax
# gets a bonus because they give us our news feed.

This is very similar to the information being posted to net.adm.site.
You can hand edit this information in.  Be sure to include an entry for
your own site.  In practice it is most convenient to have this information
in separate files; one for each site.  The lines started with # are, of
course, comments. (Above is our up-to-date entry).  Look at the 'siteform"
script, and the README file in sources for more info on the allowed 
costs of the connections.

Now, execute the shell script paths/paths.std/run .  Then run the
shell script /paths/paths.misc/run with parsec!kolstad's data as its
sole argument.  If you dont have this data, forget it.
The next step is to compile the pathalias sources.  After this is
done, and the pathalias binary is installed in its appropriate directory,
do the following :
edit the script paths/run replacing sjuvax by your sitename.  Now run
the script.  This should update your database, placing the info in
X/usr/lib/uucp/alpath.*  .  The sources directory also has a program
called uupath.c .  This allows you to find the shortest path to a given
site very easily.

Pathalias was written by Steve Bellovin (ulysses!smb).  Uupath was 
written by Bill Sebok (astrovax!wls).  They are in the public domain.
Please give the authors credit if you pass these one.

I also have some modifications to delivermai, so that it uses the
routing information to expand a netmail address automatically.  Since
delivermail probably won't be with us much longer, I'm not including it.

I didn't include the information for paths/paths.sites and 
paths/paths.misc/paths.kolstad because together they come to well over
300 K bytes, and I'm not sure how up to date they are.  If you want 
them anyhow, send me mail.  You'll have to pay for the phone call
(via uucp).  If net.adm.site works out, this won't be necessary.

	Binayak Banerjee
{allegra | astrovax | bpa | burdvax}!sjuvax!bbanerje
//go.sysin dd *
made=TRUE
if [ $made = TRUE ]; then
	/bin/chmod 644 README
	/bin/echo -n '	'; /bin/ls -ld README
fi
/bin/echo 'Making directory "paths"'
mkdir paths
/bin/echo 'Making directory "paths/paths.misc"'
mkdir paths/paths.misc
/bin/echo 'Decoding paths/paths.misc/paths.kolstad'
uudecode << '//go.sysin dd *'
begin 644 paths/paths.misc/paths.kolstad
 
end
//go.sysin dd *
made=TRUE
if [ $made = TRUE ]; then
	/bin/chmod 644 paths/paths.misc/paths.kolstad
	/bin/echo -n '	'; /bin/ls -ld paths/paths.misc/paths.kolstad
fi
/bin/echo 'Extracting paths/paths.misc/run'
sed 's/^X//' <<'//go.sysin dd *' >paths/paths.misc/run
#! /bin/sh
# Usage:	run input
# This script is useful for processing the list of connections supplied by
# linus!kolstad . Entries in this list contain a site name starting in the
# first column, followed by a site it talks to in the second column.  This list
# is usually given in "upper-triangular" form, meaning that all connections are
# given once but assumed to be two-way.  The first-part of the script doubles
# the entries to create an file for input to pathalias.  For all entries (a b)
# it generates two lines (a b) and (b a).
# The second part of the script collects together all lines with the same
# first column (i.e. all that sites that a given site talks to).
#  Remove all comments from the input before processing (all lines beginning
# with # ).  You can edit them back in afterwards (hopefully this won't be
# necessary someday).
T=/tmp/do$$
awk -f util/doubler.awk < $1 > $T
sort -u $T > paths.kolstad
rm $T
awk -f util/makemap.awk paths.kolstad > ../../mailroutes
//go.sysin dd *
made=TRUE
if [ $made = TRUE ]; then
	/bin/chmod 755 paths/paths.misc/run
	/bin/echo -n '	'; /bin/ls -ld paths/paths.misc/run
fi
/bin/echo 'Making directory "paths/paths.misc/util"'
mkdir paths/paths.misc/util
/bin/echo 'Extracting paths/paths.misc/util/doubler.awk'
sed 's/^X//' <<'//go.sysin dd *' >paths/paths.misc/util/doubler.awk
# this file takes a set of records of form "a b" and
# outputs two records for each one:  "a b" and "b a"
#
BEGIN { FS = " " }
$1 != $2  {print $1 " " $2; print $2 " " $1}
//go.sysin dd *
made=TRUE
if [ $made = TRUE ]; then
	/bin/chmod 644 paths/paths.misc/util/doubler.awk
	/bin/echo -n '	'; /bin/ls -ld paths/paths.misc/util/doubler.awk
fi
/bin/echo 'Extracting paths/paths.misc/util/makemap.awk'
sed 's/^X//' <<'//go.sysin dd *' >paths/paths.misc/util/makemap.awk
# given a long set of sorted pairs of connectivities:
#  a b  / a c / d e / d f
# this gives:  a <tab> b c
#              d <tab> e f \
#	       <tab  > g h   [continued line]
#
NR == 1 {src = $1; line = $1 "	"; n = 0}
$1 == src {if(n>8){print line " \\"; line = "	" $2; n = 1} else {line = line " " $2; n++}}
$1 != src {print line; src = $1; line = $1 "	" $2; n = 0}
END {print line}
//go.sysin dd *
made=TRUE
if [ $made = TRUE ]; then
	/bin/chmod 644 paths/paths.misc/util/makemap.awk
	/bin/echo -n '	'; /bin/ls -ld paths/paths.misc/util/makemap.awk
fi
made=TRUE
if [ $made = TRUE ]; then
	/bin/chmod 755 paths/paths.misc/util
	/bin/echo -n '	'; /bin/ls -ld paths/paths.misc/util
fi
made=TRUE
if [ $made = TRUE ]; then
	/bin/chmod 755 paths/paths.misc
	/bin/echo -n '	'; /bin/ls -ld paths/paths.misc
fi
/bin/echo 'Making directory "paths/paths.sites"'
mkdir paths/paths.sites
made=TRUE
if [ $made = TRUE ]; then
	/bin/chmod 755 paths/paths.sites
	/bin/echo -n '	'; /bin/ls -ld paths/paths.sites
fi
/bin/echo 'Making directory "paths/paths.std"'
mkdir paths/paths.std
/bin/echo 'Extracting paths/paths.std/run'
sed 's/^X//' <<'//go.sysin dd *' >paths/paths.std/run
#! /bin/sh
# this is a script for extracting path information form Mark and Karen
# Horton's Usenet Map
T=/tmp/mp$$
trap "/bin/rm -f $T;exit" 0 1 2 3 15
#cat use.map/* > $T
( cd ../../sites ; cat *.* > $T )
echo -n "# Usenet map extracted on " > path.usenet
date >> path.usenet
awk -f usenet.awk <$T >> path.usenet
echo -n "# Uucp map extracted from usenet map on " > path.uucp
date >> path.uucp
awk -f uucp.awk <$T >> path.uucp
//go.sysin dd *
made=TRUE
if [ $made = TRUE ]; then
	/bin/chmod 755 paths/paths.std/run
	/bin/echo -n '	'; /bin/ls -ld paths/paths.std/run
fi
/bin/echo 'Extracting paths/paths.std/usenet.awk'
sed 's/^X//' <<'//go.sysin dd *' >paths/paths.std/usenet.awk
BEGIN	{
		site = "";
		contline = 0;
	}
X/^$/	{ site = ""; }
X/^Name:/ {
		if (NF > 1) {
			site = $2;
			if (site ~ /,$/)
				site = substr(site, 1, length(site)-1);
		}
		next;
	}
X/^News:/ {
		if (NF > 1 && site != "") {
			printf "%s\t%s", site, $2;
			for (i = 3; i<=NF; i++)
				printf ", %s", $(i);
			printf "\n";
			contline = 1;
			next;
		}
	}
X/^	/ {
		if (conline != 0 && site != "") {
			printf "\t%s", $1;
			for (i = 2; i<=NF; i++)
				printf ", %s", $(i);
			printf "\n";
			next;
		}
	}
X/^*/	{ contline = 0; }
//go.sysin dd *
made=TRUE
if [ $made = TRUE ]; then
	/bin/chmod 644 paths/paths.std/usenet.awk
	/bin/echo -n '	'; /bin/ls -ld paths/paths.std/usenet.awk
fi
/bin/echo 'Extracting paths/paths.std/uucp.awk'
sed 's/^X//' <<'//go.sysin dd *' >paths/paths.std/uucp.awk
BEGIN	{
		site = "";
		contline = 0;
	}
X/^$/	{ site = ""; }
X/^Name:/ {
		if (NF > 1) {
			site = $2;
			if (site ~ /,$/) {
				site = substr(site, 1, length(site)-1);
				printf "%s\t= %s", site, $3;
				for (i = 4; i<=NF; i++)
					printf ", %s", $(i);
				printf "\n";
			}
		}
		next;
	}
X/^Mail:/ {
		if (NF > 1 && site != "") {
			printf "%s\t%s", site, $2;
			for (i = 3; i<=NF; i++)
				printf ", %s", $(i);
			contline = 1;
			next;
		}
	}
X/^	/ {	if(site != "" && contline != 0) {
			printf ",\n\t%s", $1;
			for (i = 2; i<=NF; i++)
				printf ", %s", $(i);
			next;
		}
	}
X/^./	{
		if(contline != 0)
			printf "\n";
		contline = 0;
	}
//go.sysin dd *
made=TRUE
if [ $made = TRUE ]; then
	/bin/chmod 644 paths/paths.std/uucp.awk
	/bin/echo -n '	'; /bin/ls -ld paths/paths.std/uucp.awk
fi
made=TRUE
if [ $made = TRUE ]; then
	/bin/chmod 755 paths/paths.std
	/bin/echo -n '	'; /bin/ls -ld paths/paths.std
fi
/bin/echo 'Extracting paths/run'
sed 's/^X//' <<'//go.sysin dd *' >paths/run
#! /bin/sh 
# run this shell script in this directory to update your mail database
SITE=sjuvax
T=/tmp/pa$$
trap "rm -f $T; exit" 0 1 2 3 15
cat paths.sites/* > $T
pathalias -p -b -w -l${SITE} \
	$T \
	paths.std/path.uucp \
	paths.std/path.usenet \
	paths.misc/paths.kolstad \
 > alpath 2>unreach
( echo -n '# Routes Generated on' ; date ; \
  echo '# Cost	Site		Address' ; \
  sort +1 alpath ) >../Mailroutes
( echo "	uucp"; echo "#sites	hops" ;\
	sed 's/[^!]//g' < alpath | sort | uniq -c ) >results
//go.sysin dd *
made=TRUE
if [ $made = TRUE ]; then
	/bin/chmod 755 paths/run
	/bin/echo -n '	'; /bin/ls -ld paths/run
fi
made=TRUE
if [ $made = TRUE ]; then
	/bin/chmod 755 paths
	/bin/echo -n '	'; /bin/ls -ld paths
fi
/bin/echo 'Making directory "sites"'
mkdir sites
made=TRUE
if [ $made = TRUE ]; then
	/bin/chmod 755 sites
	/bin/echo -n '	'; /bin/ls -ld sites
fi
/bin/echo 'Making directory "sources"'
mkdir sources
/bin/echo 'Extracting sources/Makefile'
sed 's/^X//' <<'//go.sysin dd *' >sources/Makefile
#	Makefile for smb's pathalias program
# Define DBM to include data base stuff
# Define NETMAIL to make data base for netmail (delivermail)
BINDIR = /usr/lib/uucp
CFLAGS = -O -DDBM -DNETMAIL
LDFLAGS = -z
LIBE = -ll -ldbm
YFLAGS = -d
LPR = lpr
OBJ = addhop.o addlink.o addnode.o alias.o dumpmap.o lex.o \
	local.o main.o makelink.o mapit.o parse.o setcost.o strings.o
SRC = def.h config.h addhop.c addlink.c addnode.c alias.c dumpmap.c lex.l \
	local.c main.c makelink.c mapit.c parse.y setcost.c strings.c
LSRC = addhop.c addlink.c addnode.c alias.c dumpmap.c lex.c \
	local.c main.c makelink.c mapit.c parse.c setcost.c strings.c
TARFILE = /usr/spool/uucppublic/pathalias.tar
TAR = README Makefile \
	addlink.c addnode.c alias.c def.h dumpmap.c lex.l local.c \
	main.c makelink.c mapit.c parse.y setcost.c strings.c \
	path.local path.misc path.usenet path.vdh path.test paths/* \
	package modguide

all: pathalias

pathalias: $(OBJ)
	$(CC) $(LDFLAGS) $(OBJ) $(LIBE) -o pathalias

$(OBJ):	def.h config.h

parse.c: parse.y
	$(YACC) $(YFLAGS) parse.y
	mv y.tab.c parse.c

lex.o:	parse.c lex.c

print:
	pr $(SRC) | $(LPR)

namelist:
	@echo $(SRC)

lint:	$(LSRC)
	lint -hp $(LSRC)

install:	all
	install -s pathalias $(BINDIR)

clean:
	rm -f *.o pathalias pa y.tab.c y.tab.h lex.c parse.c core

tar:
	tar cf $(TARFILE) $(TAR)

export:
	@echo "mkdir paths"
	@package $(TAR)
	@echo "chmod +x package"

dbexport:
	@package path.local path.misc path.usenet path.vdh path.test paths/*

test:	local simple dead ucbvax dupl twoway arpa vdh

local:	pathalias
	@echo "local nodes only"
	pathalias -ldopey path.test

simple:	pathalias
	@echo "simple test"
	pathalias -ldopey path.test path.misc

dead:	pathalias
	@echo "same as 'simple', without unc/mcnc link"
	pathalias -ldopey -dunc!mcnc path.test path.misc

ucbvax:	pathalias
	@echo "same as 'simple', but from ucbvax's viewpoint"
	pathalias -lucbvax path.test path.misc

arpa:	pathalias
	@echo "same as 'simple', but from mit-ai's viewpoint"
	pathalias -lmit-ai path.test path.misc

dupl:	pathalias
	@echo "same as 'simple', but with duplicates listed"
	pathalias -ldopey -a path.test path.misc

twoway:	pathalias
	@echo "from web40"
	pathalias -lweb40 path.test path.misc
	@echo "from web40 with two-way links defaulted"
	pathalias -lweb40 -o path.test path.misc

vdh:	pathalias
	@echo "show varying-quality network connections"
	pathalias -ldopey path.vdh

big:	pathalias
	@echo "Use Mark's Usenet map"
	pathalias -ldopey paths/* path.misc path.usenet
//go.sysin dd *
made=TRUE
if [ $made = TRUE ]; then
	/bin/chmod 644 sources/Makefile
	/bin/echo -n '	'; /bin/ls -ld sources/Makefile
fi
/bin/echo 'Extracting sources/README'
sed 's/^X//' <<'//go.sysin dd *' >sources/README
Parameters:

	-a	list all duplicate entries, not just those in the same file
	-c	supress cost output
	-w	supress warnings
	-o	treat links as two-way
	-b	create data base /usr/lib/uucp/alpath
	-p	   print even if making database	(MITRE sch)
	-dsite	mark the site dead, and do not use any links to or from it
	-dsiteA!siteB	mark the link from 'siteA' to 'siteB' dead
	-lsite	Give the view of the world from 'site'
	0 or more map files (if 0, the standard input is used)

Output:  a list of unreachable sites (on stderr), and a set of 3-tuples:
		cost name path

	A %s in the output string is where the userid should be
	inserted.  Output is generated in dumpmap.c; change that
	routine to do something like generate a dbm database.  Or
	#define DBM and the code will magically appear....

Input:  A site in column 1, followed by white space, followed by
	a comma-separated list of links.  A link-name may be preceeded
	or followed by a network character to use in the path name,
	such as ':' for the Berknet or @ for the ARPAnet.  Any character
	may be used if it's enclosed in single quotes; the program will
	recognize '!', '@', ':', '.', '^', and '%' by itself.

	The link-name (and network character, if present) may be
	followed by a "cost" in parentheses.  Costs may be arbitrary
	arithmetic experssions involving numbers, parentheses, '+', '-'
	(and what hackwork was needed to allow '-' as a sitename
	character...), '*', and '/'.  Several symbolic numbers are
	defined, such as LOCAL for a high-speed local network,
	DEDICATED for lines used only for mail and news, POLLED for a
	system that is called (approximately) daily, etc.; see lex.l
	for the list.  The numbers are intended to represent frequency
	of connection, which seems to be far more important than baud
	rates for this type of traffic.  Note that there is an assumed
	high overhead for each hop; thus, HOURLY is far less than
	24*DAILY -- I spent a fair amount of time playing with the
	values to make the output appear right for systems I know
	about.  Add in HIGH (LOW) for baud-rate or quality bonuses
	(penalties).

	Links are not bidirectional unless coded both ways.

	Aliases may be indicated by including lines of the form

		name = alias [ , alias...]

	The primary name is used in all expansions.  Secondary names
	may not be referenced until after the alias declaration;
	following that, they are treated identically to the primary
	name.

	Fully connected networks, such as the ARPAnet or the BerkNet,
	are indicated by a line like

		net = {host, host, ...}

	The host-list may be preceeded or followed by a routing
	character, and the entire thing may be followed by a cost:

		ARPA = @{sri-unix, mit-ai}(ARPA+5)
		BerkNet = {c70, ucbvax, Cory}:(DEDICATED)

	The network name is treated as a host that has bidirectional
	links to each member host.  The cost from a member to the net
	pseudo-host is 0; the cost specified is used for the downlink
	to each member.  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'.  Clever
	things (or maybe kludges, depending on your perspective) can be
	done with multiple nets and gateways; see the BerkNet/ARPAnet
	interface in path.misc.  If different members of a network have
	differing connection costs to the net (say, different kinds of
	IMPs), fake subnets can be built and linked; see path.vdh.

	The network code often works in surprising ways (it was a
	last-minute add-on); it is very necessary to test a definition
	from all points of view.

	Lines beginning with # are ignored.  A line may be continued by
	starting the next line with white space.

Compile-time: If you have a program on your local system that will
	return the system name, change the definition of LNAME in the
	Makefile.  If you don't have such a program, delete the
	definition; <whoami.h> will be included instead.

Usage:  Typically,

		pathalias [tempfiles] localstuff paths/* distributed

	The localstuff (i.e., 'path.local') is used to provide a
	complete map of the local area, plus any special connections
	you are authorized to use for mail.  The directory is the
	collection of data people have mailed me.  The last file is the
	map that will be broadcast regularly over USENET.  Temporary
	files may be inserted to reflect transient conditions, such as
	a line being down.
//go.sysin dd *
made=TRUE
if [ $made = TRUE ]; then
	/bin/chmod 644 sources/README
	/bin/echo -n '	'; /bin/ls -ld sources/README
fi
/bin/echo 'Extracting sources/addhop.c'
sed 's/^X//' <<'//go.sysin dd *' >sources/addhop.c
static char Sccsid[] = "@(#)addhop.c	4.2";
#include "def.h"

static path *LL_path = NULL;
static path *L_path;
static int Q_path = QPATH;

static path *pathalloc()
{
	register path *qt;

	if (LL_path != NULL) {
		qt = LL_path;
		LL_path = qt->p_next;
		return(qt);
	}

	if (Q_path == QPATH) {
		Q_path = 0;
		L_path = (path *) malloc(sizeof(path[QPATH]));
		if (L_path == NULL) {
			fprintf(stderr, "Out of memory!\n");
			abort();
		}
	}
	return(&L_path[Q_path++]);
}

path *addhop(pt, n, dir, lind) path *pt; node *n; hdir dir; char lind;
{
	register path *qt, *rt;
	register hop *h;

	qt = pathdup(pt);
	if (qt == NULL || qt->p_cnt == QHOP) {
		rt = pathalloc();
		rt->p_next = qt;
		rt->p_cnt = 0;
		qt = rt;
	}
		
	h = &qt->p_hop[qt->p_cnt++];
	h->h_node = n;
	h->h_dir = dir;
	h->h_ind = lind;
	
	return(qt);
}

path *pathdup(pt) register path *pt;
{
	register path *qt, *rt;
	path temp;

	rt = &temp;
	for ( ; pt != NULL; pt = pt->p_next) {
		qt = pathalloc();
		*qt = *pt;
		rt->p_next = qt;
		rt = qt;
	}
	rt->p_next = NULL;
	return(temp.p_next);
}

pathfree(pt) register path *pt;
{
	register path *qt;

	if (pt == NULL) return;
	for (qt = pt; qt->p_next != NULL; qt = qt->p_next)
		;
	qt->p_next = LL_path;
	LL_path = pt;
}

char *pathname(pt) register path *pt;
{
	register hop *h;
	static char *nb = NULL, *nb2;
	char indbuf[5], *tnb;
	int j, nbl;
	register int i;

	if (nb == NULL) {
		nbl = QPATH*NAMELEN;
		nb = malloc(nbl+1);
		nb2 = malloc(nbl+1);
		if (nb == NULL || nb2 == NULL) {
			fprintf(stderr, "Out of memory\n");
			exit(1);
		}
	}
	strcpy(nb, "%s");
	for ( ; pt != NULL; pt = pt->p_next) {
		for (i = pt->p_cnt - 1; i >= 0; i--) {
			h = &pt->p_hop[i];
			if (h->h_ind == '%') strcpy(indbuf, "%%");
			else {
				indbuf[0] = h->h_ind;
				indbuf[1] = '\0';
			}
			j = strlen(NAME(h->h_node)) + strlen(indbuf) + strlen(nb);
			if (j > nbl) {
				nbl = (j/(QPATH*NAMELEN) + 1) * (QPATH*NAMELEN);
				free(nb);
				nb = realloc(nb, nbl+1);
				free(nb2);
				nb2 = realloc(nb2, nbl+1);
				if (nb == NULL || nb2 == NULL) {
					fprintf(stderr, "Out of memory\n");
					exit(1);
				}
			}
			if (h->h_dir == HLEFT)
				sprintf(nb2, "%s%s%s", NAME(h->h_node), indbuf, nb);
			else sprintf(nb2, "%s%s%s", nb, indbuf, NAME(h->h_node));

			tnb = nb; nb = nb2; nb2 = tnb;
		}
	}
	return(nb);
}
//go.sysin dd *
made=TRUE
if [ $made = TRUE ]; then
	/bin/chmod 644 sources/addhop.c
	/bin/echo -n '	'; /bin/ls -ld sources/addhop.c
fi
/bin/echo 'Extracting sources/addlink.c'
sed 's/^X//' <<'//go.sysin dd *' >sources/addlink.c
static char Sccsid[] = "@(#)addlink.c	4.1";
#include "def.h"

static link *L_link;
static int Q_link = QLINK;

link *addlink(n, nto, cost, lind, dir)
	register node *n, *nto;
	Cost cost;
	char lind;
	hdir dir;
{
	register link *l;

	if ((nto->n_flag&NDEAD) && cost <INF/2) cost += INF / 2;

	if ((l = isalink(n, nto)) != NULL) {
		if (l->l_fcnt == fcnt || dupl) {
			yyerror("duplicate link\n");
			fprintf(stderr, "\t%s\t%s%c(%ld)\n\t%s\t%s%c(%ld)\n",
			    n->n_name, nto->n_name, l->l_ind, (long) l->l_cost,
			    n->n_name, nto->n_name, lind, (long) cost);
		}
		return(l);
	}
	
	if (Q_link == QLINK) {
		Q_link = 0;
		L_link = (link *) malloc(sizeof (link [QLINK]));
		if (L_link == NULL) {
			fprintf(stderr, "Out of memory!\n");
			abort();
		}
	}
	l = &L_link[Q_link++];

	n->n_flag |= NREF;
	nto->n_flag |= NREF;
	l->l_next = n->n_link;
	n->n_link = l;
	l->l_cost = cost;
	l->l_ind = lind;
	l->l_dir = dir;
	l->l_to = nto;
	l->l_fcnt = fcnt;
	l->l_lnet = 0;
	return(l);
}

deadlink(s) char *s;
{
	register char *t;
	char c;

	for (t = s; !isnetc(*t); t++)
		if (!*t) break;
	if ((c = *t) != '\0') {
		*t = '\0';
		addlink(addnode(s), addnode(t+1), INF/2, c, DEFDIR);
	}
	else addnode(s)->n_flag |= NDEAD;
}

link *isalink(nfrom, nto) register node *nto, *nfrom;
{
	register link *l;

	for (l = nfrom->n_link; l != NULL; l = l->l_next)
		if (l->l_to == nto) return(l);

	return(0);
}

#ifdef	DEBUG
showlink(n) register node *n;
{
	register link *l;

	printf("%s\t", NAME(n));
	for (l = n->n_link; l != NULL; l = l->l_next)
		printf(" %s", NAME(l->l_to));
	putchar('\n');
}
#endif
//go.sysin dd *
made=TRUE
if [ $made = TRUE ]; then
	/bin/chmod 644 sources/addlink.c
	/bin/echo -n '	'; /bin/ls -ld sources/addlink.c
fi
/bin/echo 'Extracting sources/addnode.c'
sed 's/^X//' <<'//go.sysin dd *' >sources/addnode.c
static char Sccsid[] = "@(#)addnode.c	4.1";
#include "def.h"

static node *hashtab[NHASH];
#ifdef	HASHASTAT
static hashcnt[NHASH];
#endif

static hash(n) register char *n;
{
	register int h;

	h = 0;
	while (*n) h = (h<<2) ^ *n++;
	if (h < 0) h = -h;
	return(h%NHASH);
}

static node *L_node;
static int Q_node = QNODE;

node *addnode(name) char *name;
{
	int i;
	register node *n;

	i = hash(name);
	for (n = hashtab[i]; n != NULL; n = n->n_next)
		if (strcmp(name, n->n_name) == 0)
			return(n->n_alias ? n->n_alias : n);
	
	ncount++;

	if (Q_node == QNODE) {
		Q_node = 0;
		L_node = (node *) malloc(sizeof (node [QNODE]));
		if (L_node == NULL) {
			fprintf(stderr, "Out of memory!\n");
			abort();
		}
	}
	n = &L_node[Q_node++];

	n->n_next = hashtab[i];
	hashtab[i] = n;
	n->n_cost = INF;
	n->n_path = NULL;
	n->n_name = savestr(name);
	n->n_link = NULL;
	n->n_flag = 0;
	n->n_alias = NULL;
#ifdef	HASHASTAT
	hashcnt[i]++;
#endif
	return(n);
}

remove(i) register int i;
{
	node *t;

	if (i >= ncount) fprintf(stderr, "Internal error -- node %d not on list\n", i);
	t = all[i];
	all[i] = all[--ncount];
	all[ncount] = t;
}

linear()
{
	register int i, j;
	register node *n;

#ifdef	HASHASTAT
	for (i = 0; i < NHASH; i += 10) {
		for (j = i; j < NHASH && j < i+10; j++)
			fprintf(stderr, "%7d", hashcnt[j]);
		putc('\n', stderr);
	}
#endif
	all = (node **) malloc((ncount + 1) * sizeof (node *));
	if (all == NULL) {
		fprintf(stderr, "Out of memory!\n");
		abort();
	}

	j = 0;
	for (i = 0; i <NHASH; i++)
		for (n = hashtab[i]; n != NULL; n = n->n_next)
			all[j++] = n;
	all[j] = NULL;
}

#ifdef	DEBUG
showall()
{
	register int i;

	for (i = 0; i < ncount; i++)
		showlink(all[i]);
	printf("\n------------\n");
	while(all[i] != NULL)
		showlink(all[i++]);
}
#endif
//go.sysin dd *
made=TRUE
if [ $made = TRUE ]; then
	/bin/chmod 644 sources/addnode.c
	/bin/echo -n '	'; /bin/ls -ld sources/addnode.c
fi
/bin/echo 'Extracting sources/alias.c'
sed 's/^X//' <<'//go.sysin dd *' >sources/alias.c
static char Sccsid[] = "@(#)alias.c	4.1";
#include "def.h"

alias(n, na) register node *n, *na;
{
	if (n->n_alias != NULL || na->n_alias != NULL) {
		yyerror("can't nest aliases\n");
		return;
	}
	if (na->n_flag & NREF) {
		yyerror("alias name already referenced");
		return;
	}
	addlink(n, na, (Cost) 0, DEFNET, DEFDIR);
	addlink(na, n, (Cost) 0, DEFNET, DEFDIR);
	na->n_alias = n;
	na->n_flag = n->n_flag & ~NREF;
}
//go.sysin dd *
made=TRUE
if [ $made = TRUE ]; then
	/bin/chmod 644 sources/alias.c
	/bin/echo -n '	'; /bin/ls -ld sources/alias.c
fi
/bin/echo 'Extracting sources/config.h'
sed 's/^X//' <<'//go.sysin dd *' >sources/config.h
X/*	@(#)config.h	4.2	*/
X/*	Put local configuration options here */

X/* Define for USG systems */
#ifdef	USG
#define	UNAME		/* have USG UNIX 'uname' call */
#endif

X/* program to find local node name */
X/* otherwise use whoami.h */
#define	LNAME	"/usr/bin/uuname -l"

X/* Are you on ARPA?  (i.e., how much does ARPANET cost? */
#define HASARPA
//go.sysin dd *
made=TRUE
if [ $made = TRUE ]; then
	/bin/chmod 644 sources/config.h
	/bin/echo -n '	'; /bin/ls -ld sources/config.h
fi
/bin/echo 'Extracting sources/def.h'
sed 's/^X//' <<'//go.sysin dd *' >sources/def.h
X/* "@(#)def.h	4.2" */
#include <stdio.h>
#include "config.h"

#define	QLINK	128	/* Quanta of link structures to malloc at once */
#define	QNODE	64	/* Quanta of node structures to malloc at once */
#define	QPATH	64	/* Quanta of path structures to malloc at once */
#define	QHOP	8	/* Number of hops per path structure */
#define	NHASH	73	/* number of hash table indices */
#define	NAMELEN	16

#define	isnetc(c)	((c)=='!' || (c)=='.' || (c)==':' || (c)=='^' || \
	(c)=='@' || (c)=='%')
#define	NAME(x)		((x)->n_alias ? (x)->n_alias->n_name : (x)->n_name)

#define	DEFNET	'!'	/* default network character */
#define	DEFDIR	HLEFT	/* host on left in default net */
#define	DEFCOST	4000	/* default cost of a link */
#define	INF	((Cost) 30000000)	/* infinitely expensive link */

#define	PATHALIAS	"/usr/lib/uucp/alpath"	/* alias file */

typedef	long Cost;
typedef struct path path;
typedef struct hop hop;
typedef struct node node;
typedef struct link link;
typedef enum hdir hdir;

enum hdir {HNONE, HLEFT, HRIGHT}; /* Is host on left or right in address? */

struct hop {
	node	*h_node;
	hdir	h_dir;
	char	h_ind;
};

struct path {
	path	*p_next;
	int	p_cnt;
	hop	p_hop[QHOP];
};
	
struct node {
	node	*n_next;
	Cost	n_cost;
	path	*n_path;
	char	*n_name;
	link	*n_link;
	char	n_flag;
	node	*n_alias;
};

X/* flags for n_flag */
#define	NDEAD	0x01	/* Node dead */
#define	NREF	0x02	/* node has been referenced */
#define	NHOST	0x04	/* node is a real machine */
#define	NNET	0x08	/* node is a network name */

struct link {
	link	*l_next;
	node	*l_to;
	Cost	l_cost;
	char	l_ind;
	hdir	l_dir;
	char	l_fcnt;
	char	l_lnet;
};

node *addnode();
link *addlink();
link *isalink();
path *addhop();
path *pathdup();
char *savestr();
char *local();
char *pathname();

long atol();
char *malloc();
char *calloc();
char *realloc();

extern node **all;
extern node *home;
extern int ncount;
extern int lineno;
extern char *cfile;
extern int fcnt;
extern int netid;
extern char **ifiles;
extern int dupl;
extern char *cmdname;
extern int dbflag;
extern int prflag;
extern int oneflag;
extern int nwarnflag;
extern int ncostflag;
//go.sysin dd *
made=TRUE
if [ $made = TRUE ]; then
	/bin/chmod 644 sources/def.h
	/bin/echo -n '	'; /bin/ls -ld sources/def.h
fi
/bin/echo 'Extracting sources/dumpmap.c'
sed 's/^X//' <<'//go.sysin dd *' >sources/dumpmap.c
static char Sccsid[] = "@(#)dumpmap.c	4.1";
#include "def.h"

typedef struct {char *dptr; int dsize;} datum;

dumpmap()
{
	register node *n;
	register int i;
	register char *p;
#ifdef	DBM
	char alif[200];
#endif
	char *npath;

#ifdef DBM
	if (dbflag) {
		sprintf(alif, "%s.dir", PATHALIAS);
		close(creat(alif,0644));
		sprintf(alif, "%s.pag", PATHALIAS);
		close(creat(alif,0644));
		dbminit(PATHALIAS);
	}
#endif

	for (i = ncount; all[i] != NULL; i++)
		;
	for (i--; i >= ncount; i--) {
		n = all[i];
		npath = pathname(n->n_path);
#ifdef DBM
		if (dbflag) wdb(n, npath);
		if (prflag || !dbflag)
#endif
		{
			if (!ncostflag)
				printf("%ld\t", (long) n->n_cost);
			printf("%-13s\t%s\n", n->n_name, npath);
		}
	}
}

#ifdef DBM
static char *pbuf = NULL;
static int psize = -1;

wdb(n, npath) register node *n; char *npath;
{
	datum dbkey, dbpath;

	if (strlen(n->n_name)+2 > psize) {
		if (pbuf) free(pbuf);
		psize = 2 * (strlen(n->n_name)+2);
		pbuf = malloc(psize);
		if (pbuf == NULL) {
			fprintf(stderr, "Out of memory\n");
			abort();
		}
	}
#ifdef NETMAIL
	cpylwr(pbuf, n->n_name);
#else
	sprintf(pbuf, "%s%c", n->n_name, DEFNET);
#endif

	dbkey.dptr = pbuf;
	dbkey.dsize = strlen(pbuf)+1;
	dbpath.dptr = npath;
	dbpath.dsize = strlen(npath)+1;
	if (store(dbkey, dbpath))
		fprintf(stderr, "Cannot store %s->%s\n", n->n_name, npath);
}
#ifdef NETMAIL

#include <ctype.h>

static cpylwr(dst,src)
register char *dst, *src;
{
	while(*src) {
		*dst++ = isupper(*src) ? tolower(*src) : *src;
		src++;
	}
	*dst = '\0';
}
#endif
#endif
//go.sysin dd *
made=TRUE
if [ $made = TRUE ]; then
	/bin/chmod 644 sources/dumpmap.c
	/bin/echo -n '	'; /bin/ls -ld sources/dumpmap.c
fi
/bin/echo 'Extracting sources/lex.l'
sed 's/^X//' <<'//go.sysin dd *' >sources/lex.l
%{
static char Sccsid[] = "@(#)lex.l	4.1";
#include "def.h"
#include "y.tab.h"

int	lineno = 1;
extern	YYSTYPE yylval;

static costing = 0;
static struct ctable {
	char *cname;
	Cost cval;
} ctable[] = {
	{"LOCAL", 10},
#ifdef HASARPA
	{"ARPA", 100},
#else
	{"ARPA", 30000},
#endif
	{"DED", 95},
	{"DEDICATED", 95},
	{"DIRECT", 200},
	{"DEMAND", 300},
	{"DIAL", 300},
	{"DIALED", 300},
	{"HOURLY", 500},
	{"EVENING", 1800},
	{"POLLED", 5000},
	{"DAILY", 5000},
	{"WEEKLY", 30000},
	{"DEAD", INF/2},
	{"HIGH", -5},	/* baud rate bonus */
	{"LOW", 5},	/* baud rate penalty */
	NULL
};

%}

WS	[ \t]
NET	[!^.:@%]
ALPHA	[a-zA-Z_0-9]
SALPHA	[-+a-zA-Z_0-9]

%%
"#".*\n{WS}+	{lineno++;}
"#".*\n		{lineno++; return(NL);}
{WS}+		;
^{SALPHA}+	{
			yylval.y_node = addnode(yytext);
			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;
			c = input(); unput(c);
			if (costing) {
				for (ct = ctable; ct->cname != NULL; ct++)
					if (strcmp(ct->cname, yytext) == 0) {
						yylval.y_cost = ct->cval;
						return(COST);
					}
				yylval.y_node = addnode(yytext);
				return(SITE);
			}
			else if (c=='-' || c=='+') yymore();
			else {
				yylval.y_node = addnode(yytext);
				return(SITE);
			}
		}
\"[^"]*		{
			if (yytext[yyleng-1] == '\\')
				yymore();
			else {
				yylval.y_node = addnode(yytext+1);
				input();
				return(SITE);
			}
		}

"{"				{
					costing = 0;
					yylval.y_s.ys_ind = '\0';
					yylval.y_s.ys_dir = HNONE;
					return(LNET);
				}
{NET}"{"			{
					costing = 0;
					yylval.y_s.ys_ind = yytext[0];
					yylval.y_s.ys_dir = HRIGHT;
					return(LNET);
				}
"}"				{
					costing = 0;
					yylval.y_s.ys_ind = '\0';
					yylval.y_s.ys_dir = HNONE;
					return(RBRACE);
				}
"}"{NET}			{
					costing = 0;
					yylval.y_s.ys_ind = yytext[1];
					yylval.y_s.ys_dir = HLEFT;
					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);}
X.				{return(yytext[0]);}
%%
yywrap()
{
	FILE *in;
	char errbuf[100];

	if (ifiles == NULL) return(1);

	fclose(stdin);
	while (*ifiles) {
		lineno = 1;
		fcnt++;
		if (fopen((cfile = *ifiles++), "r") != NULL)
			return(0);
		sprintf(errbuf, "%s: %s", cmdname, cfile);
		perror(errbuf);
	}
	return(1);
}
//go.sysin dd *
made=TRUE
if [ $made = TRUE ]; then
	/bin/chmod 644 sources/lex.l
	/bin/echo -n '	'; /bin/ls -ld sources/lex.l
fi
/bin/echo 'Extracting sources/local.c'
sed 's/^X//' <<'//go.sysin dd *' >sources/local.c
static char Sccsid[] = "@(#)local.c	4.2";
#include "def.h"

#ifdef	UNAME
#include <sys/utsname.h>
struct utsname utsname;
#else
#ifndef	LNAME
#include <whoami.h>
#endif
#endif	UNAME

char *local()
{
#ifdef	UNAME
	uname(&utsname);
	return(utsname.nodename);
#else
#ifdef	LNAME
	FILE *popen(), *ln;
	static char lname[NAMELEN+3];
	int i;

	ln = popen(LNAME, "r");
	if (fgets(lname, sizeof lname, ln) == NULL) nosite();
	i = strlen(lname) - 1;
	if (lname[i] == '\n') lname[i] = 0;
	if (pclose(ln) || !*lname) nosite();
	return(lname);
#else
	return(sysname);
#endif
#endif	UNAME
}

#ifdef	LNAME
nosite()
{
	fprintf(stderr, "%s: cannot get local site name; use -l\n", cmdname);
}
#endif
//go.sysin dd *
made=TRUE
if [ $made = TRUE ]; then
	/bin/chmod 644 sources/local.c
	/bin/echo -n '	'; /bin/ls -ld sources/local.c
fi
/bin/echo 'Extracting sources/main.c'
sed 's/^X//' <<'//go.sysin dd *' >sources/main.c
static char Sccsid[] = "@(#)main.c	4.1";
#include "def.h"

char *locname;
node **all;
node *home;
int ncount;
int fcnt = -1;
char *cfile;
char **ifiles;
int dupl;
char *cmdname;
int dbflag;
int prflag;		/* sch - print output (even if db) */
int oneflag;
int nwarnflag;
int ncostflag;

main(argc, argv) int argc; char *argv[];
{
	cmdname = argv[0];
	while (*++argv && **argv == '-') {
		switch((*argv)[1]) {
			case 'l':
				locname = *argv+2;
				if (!*locname) usage();
				break;
			case 'd':
				if (!*(*argv+2)) usage();
				deadlink(*argv+2);
				break;
			case 'a':
				dupl++;
				break;
			case 'o':
				oneflag++;
				break;
			case 'c':
				ncostflag++;
				break;
			case 'w':
				nwarnflag++;
				break;
#ifdef	DBM
			case 'b':
				dbflag++;
				break;
			case 'p':
				prflag++;
				break;
#endif
			default:
				usage();
		}
	}

	fcnt++;
	if (*argv) {
		ifiles = argv;
		freopen("/dev/null", "r", stdin);
	}

	if (!locname) locname = local();

	home = addnode(locname);	/* add home node */
	if (home->n_alias) home = home->n_alias;
	home->n_cost = 0;		/* doesn't cost to get here */

	/* read in link info */
	makelink();

	mapit();

	dumpmap();
	exit(0);
}

usage()
{
	fprintf(stderr, "%s: usage: %s [-b] [-lsite] [-a] [-dnode!node]... [file...]\n", cmdname, cmdname);
	exit(1);
}
//go.sysin dd *
made=TRUE
if [ $made = TRUE ]; then
	/bin/chmod 644 sources/main.c
	/bin/echo -n '	'; /bin/ls -ld sources/main.c
fi
/bin/echo 'Extracting sources/makelink.c'
sed 's/^X//' <<'//go.sysin dd *' >sources/makelink.c
static char Sccsid[] = "@(#)makelink.c	4.1";
#include "def.h"

makelink()
{
	yyparse();

	linear();
	oneway();
}

oneway()
{
	static firsttime = 1;
	register node *n;
	register link *l;
	register int i;

	for (i = 0; i < ncount; i++) {
		n = all[i];
		for (l = n->n_link; l != NULL; l = l->l_next) {
			if (isalink(l->l_to, n) != NULL) continue;
			if (!nwarnflag) {
				if (firsttime) {
					firsttime = 0;
					fprintf(stderr, "Missing links:\n");
				}
				fprintf(stderr, "\t%s -> %s\n", NAME(l->l_to),
				    NAME(n));
			}
			if (oneflag)
				addlink(l->l_to, n, l->l_cost, l->l_ind, l->l_dir);
		}
	}
}
//go.sysin dd *
made=TRUE
if [ $made = TRUE ]; then
	/bin/chmod 644 sources/makelink.c
	/bin/echo -n '	'; /bin/ls -ld sources/makelink.c
fi
/bin/echo 'Extracting sources/mapit.c'
sed 's/^X//' <<'//go.sysin dd *' >sources/mapit.c
static char Sccsid[] = "@(#)mapit.c	4.1";
#include "def.h"

mapit()
{
	register int i, j;
	register node *n;
	register link *l;

	while (ncount > 0) {
		/* find closest node not mapped yet */
		j = 0; n = all[j];
		for (i = 1; i < ncount; i++)
			if (all[i]->n_cost < all[j]->n_cost) {
				j = i;
				n = all[j];
			}
		if (n->n_cost == INF) break;

		/* calculate the cost from this node to its neighbors */
		remove(j);
		for (l = n->n_link; l != NULL; l = l->l_next)
			setcost(n, l);
	}
	if (ncount != 0) {	/* exited early -- unreachable nodes */
		fprintf(stderr, "%s: You can't get there from here:\n", cmdname);
		for (i = 0; i < ncount; i++)
			fprintf(stderr, "\t%s\n", all[i]->n_name);
		putc('\n', stderr);
		fflush(stderr);
	}
}
//go.sysin dd *
made=TRUE
if [ $made = TRUE ]; then
	/bin/chmod 644 sources/mapit.c
	/bin/echo -n '	'; /bin/ls -ld sources/mapit.c
fi
/bin/echo 'Extracting sources/parse.y'
sed 's/^X//' <<'//go.sysin dd *' >sources/parse.y
%{
static char Sccsid[] = "@(#)parse.y	4.1";
#include "def.h"

int netid = 0;
%}

%union {
	node *y_node;
	Cost	y_cost;
	char	y_ind;
	struct {
		node *ys_node;
		char ys_ind;
		Cost ys_cost;
		hdir ys_dir;
	} y_s;
}

%type <y_s> site sitenet lnetl
%type <y_node> links aliases
%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

%left	PLUS MINUS
%left	TIMES DIVIDE

%%
map	:	/* empty */
	|	map NL
	|	map links NL
	|	map aliases NL
	|	map lnet NL
	|	error NL
	;

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 =
			{
				netid++;
X/*TEST
				if ($1->n_flag & NHOST) {
					yyerror("host/network conflict\n");
					YYERROR;
				}
*/
				$1->n_flag |= NNET;
				addlink($1, $4, (Cost) 0, $3.ys_ind,
				    $3.ys_dir)->l_lnet = netid;
				addlink($4, $1, (Cost) 0, $3.ys_ind,
				    $3.ys_dir)->l_lnet = netid;
				$3.ys_node = $1;
				$3.ys_cost = DEFCOST;
				$$ = $3;
			}
	|	lnetl COMMA SITE =
			{
				addlink($1.ys_node,$3,$1.ys_cost,
				    $1.ys_ind,$1.ys_dir)->l_lnet=netid;
				addlink($3,$1.ys_node,$1.ys_cost,
				    $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 =
			{
X/*TEST
				if ($1->n_flag & NNET) {
					yyerror("host/network conflict\n");
					YYERROR;
				}
*/
				$1->n_flag |= NHOST;
				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 = HRIGHT;}
	|	SITE NET =
			{$$.ys_node = $1; $$.ys_ind = $2; $$.ys_dir = HLEFT;}
	|	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;
{
	fprintf(stderr, "%s: ", cmdname);
	if (cfile) fprintf(stderr, "file %s, ", cfile);
	fprintf(stderr, "line %d: %s\n", lineno, s);
}

fixnet(n, yl, yr, c, netid)
	register node *n;
	YYSTYPE *yl, *yr;
	Cost c;
	int netid;
{
	register link *l, *lt;
	hdir d;
	char p;

	if (yl->y_s.ys_ind && yr->y_s.ys_ind) {
		yyerror("two net indicators\n");
		p = DEFNET;
		d = DEFDIR;
	}
	else if (yl->y_s.ys_ind) {
		p = yl->y_s.ys_ind;
		d = yl->y_s.ys_dir;
	}
	else if (yr->y_s.ys_ind) {
		p = yr->y_s.ys_ind;
		d = yr->y_s.ys_dir;
	}
	else {
		p = DEFNET;
		d = DEFDIR;
	}

	for (l = n->n_link; l != NULL; l = l->l_next) {
		if (l->l_lnet == netid) {
			if (l->l_cost < INF/2)
				l->l_cost = c;
			l->l_ind = p;
			l->l_dir = d;
			lt = isalink(l->l_to, n);
			if (lt == NULL) lt = addlink(l->l_to, n, c, p, d);
			if (l->l_cost < INF/2)
				lt->l_cost = 0;
			lt->l_ind = p;
			lt->l_dir = d;
		}
	}
}
//go.sysin dd *
made=TRUE
if [ $made = TRUE ]; then
	/bin/chmod 644 sources/parse.y
	/bin/echo -n '	'; /bin/ls -ld sources/parse.y
fi
/bin/echo 'Extracting sources/setcost.c'
sed 's/^X//' <<'//go.sysin dd *' >sources/setcost.c
static char Sccsid[] = "@(#)setcost.c	4.1";
#include "def.h"

setcost(n, l) register node *n; register link *l;
{
	register node *nto;
	Cost c;

	nto = l->l_to;
	if (n->n_cost >= INF/2 && l->l_cost >= INF/2) c = n->n_cost + INF/1000;
	else c = n->n_cost + l->l_cost;
	if (nto->n_cost < c) return;

	nto->n_cost = c;
	if (l->l_cost == 0 || (nto->n_flag&NNET))
		nto->n_path = pathdup(n->n_path);
	else {
		pathfree(nto->n_path);
		nto->n_path = addhop(n->n_path, nto, l->l_dir, l->l_ind);
	}
}
//go.sysin dd *
made=TRUE
if [ $made = TRUE ]; then
	/bin/chmod 644 sources/setcost.c
	/bin/echo -n '	'; /bin/ls -ld sources/setcost.c
fi
/bin/echo 'Extracting sources/strings.c'
sed 's/^X//' <<'//go.sysin dd *' >sources/strings.c
static char Sccsid[] = "@(#)strings.c	4.1";
#include "def.h"

char *savestr(s) char *s;
{
	char *r;

	if (strcmp(s, "%s")) {
		r = malloc(strlen(s) + 1);
		if (r == NULL) {
			fprintf(stderr, "Out of memory!\n");
			abort();
		}
		strcpy(r, s);
		return(r);
	}
	else return("%s");
}
//go.sysin dd *
made=TRUE
if [ $made = TRUE ]; then
	/bin/chmod 644 sources/strings.c
	/bin/echo -n '	'; /bin/ls -ld sources/strings.c
fi
/bin/echo 'Extracting sources/uupath.c'
sed 's/^X//' <<'//go.sysin dd *' >sources/uupath.c
X/* * * * uupath - look up path to computer in database * * * W.Sebok 11/4/83 */
X/* Compile with    cc -O -s -o uupath uupath.c -ldbm  */
#include <stdio.h>
#ifdef NULL
#undef NULL
#endif
#include <dbm.h>

#define ARCHIVE	"/usr/lib/uucp/alpath"
#define USAGE	"Usage: uupath site [ dbase ]\n"

main(argc,argv)
	int argc; char *argv[];
{
	char *fil;
	int ret;
	datum key, result;
	if (argc<2 && argc>3) {
	 	fprintf(stderr,USAGE);
		exit(1);
	}

	fil =  (argc == 3) ? argv[2] : ARCHIVE;
	key.dptr = argv[1];
	key.dsize = strlen(key.dptr) + 1 ;
	ret = dbminit(fil);
	if (ret != 0) {
		exit(1);
	}
	result = fetch(key);
	if (result.dptr != NULL) {
		if (strcmp("!%s",&result.dptr[result.dsize-4])==0) {
			result.dptr[result.dsize-4] = '\0';
		}
		printf("%s\n",result.dptr);
	} else {
		fprintf(stderr,"%s not found\n",argv[1]);
		exit(1);
	}
	exit(0);
}
//go.sysin dd *
made=TRUE
if [ $made = TRUE ]; then
	/bin/chmod 644 sources/uupath.c
	/bin/echo -n '	'; /bin/ls -ld sources/uupath.c
fi
made=TRUE
if [ $made = TRUE ]; then
	/bin/chmod 755 sources
	/bin/echo -n '	'; /bin/ls -ld sources
fi
-- 


				Binayak Banerjee
		{allegra | astrovax | bpa | burdvax}!sjuvax!bbanerje

honey@down.UUCP (01/21/84)

here are some minor mods i have made.  there's a variable that should
be declared a static.  i added a -n flag to request supression of
network names, so that only site names are put in the database.  i
increased the size of the site name buffer from 16 to 32 bytes;
bbn-minet-gateway is a site in my arpa list.  diff -c output follows.
	peter honeyman

*** addhop.c	Sat Jan 21 11:52:17 1984
--- ../../addhop.c	Fri Jun  3 13:56:16 1983
***************
*** 79,85
  	register hop *h;
  	static char *nb = NULL, *nb2;
  	char indbuf[5], *tnb;
! 	int j, nbl;
  	register int i;
  
  	if (nb == NULL) {

--- 79,86 -----
  	register hop *h;
  	static char *nb = NULL, *nb2;
  	char indbuf[5], *tnb;
! 	int j;
! 	static int nbl;
  	register int i;
  
  	if (nb == NULL) {
*** def.h	Sat Jan 21 11:52:29 1984
--- ../../def.h	Wed Jun  1 11:49:37 1983
***************
*** 7,13
  #define	QPATH	64	/* Quanta of path structures to malloc at once */
  #define	QHOP	8	/* Number of hops per path structure */
  #define	NHASH	73	/* number of hash table indices */
! #define	NAMELEN	16
  
  #define	isnetc(c)	((c)=='!' || (c)=='.' || (c)==':' || (c)=='^' || \
  	(c)=='@' || (c)=='%')

--- 7,13 -----
  #define	QPATH	64	/* Quanta of path structures to malloc at once */
  #define	QHOP	8	/* Number of hops per path structure */
  #define	NHASH	73	/* number of hash table indices */
! #define	NAMELEN	32	/* down!honey -- for **long**  arpa sites */
  
  #define	isnetc(c)	((c)=='!' || (c)=='.' || (c)==':' || (c)=='^' || \
  	(c)=='@' || (c)=='%')
***************
*** 96,98
  extern int oneflag;
  extern int nwarnflag;
  extern int ncostflag;

--- 95,98 -----
  extern int oneflag;
  extern int nwarnflag;
  extern int ncostflag;
+ extern int netflag;
*** main.c	Sat Jan 21 11:52:40 1984
--- ../../main.c	Sat Jan 21 12:18:18 1984
***************
*** 15,20
  int oneflag;
  int nwarnflag;
  int ncostflag;
  
  main(argc, argv) int argc; char *argv[];
  {

--- 15,21 -----
  int oneflag;
  int nwarnflag;
  int ncostflag;
+ int netflag;		/* down!honey -- don't print network names */
  
  main(argc, argv) int argc; char *argv[];
  {
***************
*** 40,45
  				break;
  			case 'w':
  				nwarnflag++;
  				break;
  #ifdef	DBM
  			case 'b':

--- 41,49 -----
  				break;
  			case 'w':
  				nwarnflag++;
+ 				break;
+ 			case 'n':
+ 				netflag++;
  				break;
  #ifdef	DBM
  			case 'b':
*** dumpmap.c	Sat Jan 21 11:52:32 1984
--- ../../dumpmap.c	Sat Jan 21 12:46:42 1984
***************
*** 27,32
  		;
  	for (i--; i >= ncount; i--) {
  		n = all[i];
  		npath = pathname(n->n_path);
  #ifdef DBM
  		if (dbflag) wdb(n, npath);

--- 27,34 -----
  		;
  	for (i--; i >= ncount; i--) {
  		n = all[i];
+ 		if (netflag && (n->n_flag & NNET))
+ 			continue;
  		npath = pathname(n->n_path);
  #ifdef DBM
  		if (dbflag) wdb(n, npath);