v22i110: Pathalias, version 10, Part02/03
Rich Salz
rsalz at uunet.uu.net
Fri Jun 8 23:33:02 AEST 1990
Submitted-by: peter honeyman <honey at citi.umich.edu>
Posting-number: Volume 22, Issue 110
Archive-name: pathalias10/part02
#! /bin/sh
# This is a shell archive. Remove anything before this line, then feed it
# into a shell via "sh file" or similar. To overwrite existing files,
# type "sh file -c".
# The tool that generated this appeared in the comp.sources.unix newsgroup;
# send mail to comp-sources-unix at uunet.uu.net if you want that tool.
# Contents: addlink.c addnode.c arpa-privates mapaux.c parse.y
# printit.c
# Wrapped by rsalz at litchi.bbn.com on Fri Jun 8 09:25:21 1990
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
echo If this archive is complete, you will see the following message:
echo ' "shar: End of archive 2 (of 3)."'
if test -f 'addlink.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'addlink.c'\"
else
echo shar: Extracting \"'addlink.c'\" \(6001 characters\)
sed "s/^X//" >'addlink.c' <<'END_OF_FILE'
X/* pathalias -- by steve bellovin, as told to peter honeyman */
X#ifndef lint
Xstatic char *sccsid = "@(#)addlink.c 9.7 88/06/10";
X#endif /* lint */
X
X#include "def.h"
X
X/* exports */
Xextern link *addlink();
Xextern void deadlink(), atrace(), freelink();
Xextern int tracelink(), maptrace();
Xchar *Netchars = "!:@%"; /* sparse, but sufficient */
Xlong Lcount; /* how many edges? */
X
X/* imports */
Xextern int Tflag, Dflag;
Xextern link *newlink();
Xextern node *addnode();
Xextern void yyerror(), die();
Xextern int strcmp(), strlen();
X
X/* privates */
XSTATIC void netbits(), ltrace(), ltrprint();
Xstatic link *Trace[NTRACE];
Xstatic int Tracecount;
X
X#define EQ(n1, n2) (strcmp((n1)->n_name, (n2)->n_name) == 0)
X#define LTRACE if (Tflag) ltrace
X
Xlink *
Xaddlink(from, to, cost, netchar, netdir)
X node *from;
X register node *to;
X Cost cost;
X char netchar, netdir;
X{ register link *l, *prev = 0;
X
X LTRACE(from, to, cost, netchar, netdir, "");
X /*
X * maintain uniqueness for dead links (only).
X */
X for (l = from->n_link; l; l = l->l_next) {
X if (!DEADLINK(l))
X break;
X if (to == l->l_to) {
X /* what the hell, use cheaper dead cost */
X if (cost < l->l_cost) {
X l->l_cost = cost;
X netbits(l, netchar, netdir);
X }
X return l;
X }
X prev = l;
X }
X
X
X /* allocate and link in the new link struct */
X l = newlink();
X if (cost != INF) /* ignore back links */
X Lcount++;
X if (prev) {
X l->l_next = prev->l_next;
X prev->l_next = l;
X } else {
X l->l_next = from->n_link;
X from->n_link = l;
X }
X
X l->l_to = to;
X /* add penalty */
X if ((l->l_cost = cost + from->n_cost) < 0) {
X char buf[100];
X
X l->l_flag |= LDEAD;
X sprintf(buf, "link to %s ignored with negative cost", to->n_name);
X yyerror(buf);
X }
X if (netchar == 0) {
X netchar = DEFNET;
X netdir = DEFDIR;
X }
X netbits(l, netchar, netdir);
X if (Dflag && ISADOMAIN(from))
X l->l_flag |= LTERMINAL;
X
X return l;
X}
X
Xvoid
Xdeadlink(nleft, nright)
X node *nleft, *nright;
X{ link *l, *lhold = 0, *lprev, *lnext;
X
X /* DEAD host */
X if (nright == 0) {
X nleft->n_flag |= NDEAD; /* DEAD host */
X return;
X }
X
X /* DEAD link */
X
X /* grab <nleft, nright> instances at head of nleft adjacency list */
X while ((l = nleft->n_link) != 0 && l->l_to == nright) {
X nleft->n_link = l->l_next; /* disconnect */
X l->l_next = lhold; /* terminate */
X lhold = l; /* add to lhold */
X }
X
X /* move remaining <nleft, nright> instances */
X for (lprev = nleft->n_link; lprev && lprev->l_next; lprev = lprev->l_next) {
X if (lprev->l_next->l_to == nright) {
X l = lprev->l_next;
X lprev->l_next = l->l_next; /* disconnect */
X l->l_next = lhold; /* terminate */
X lhold = l;
X }
X }
X
X /* check for emptiness */
X if (lhold == 0) {
X addlink(nleft, nright, INF / 2, DEFNET, DEFDIR)->l_flag |= LDEAD;
X return;
X }
X
X /* reinsert deleted edges as DEAD links */
X for (l = lhold; l; l = lnext) {
X lnext = l->l_next;
X addlink(nleft, nright, l->l_cost, NETCHAR(l), NETDIR(l))->l_flag |= LDEAD;
X freelink(l);
X }
X}
X
XSTATIC void
Xnetbits(l, netchar, netdir)
X register link *l;
X char netchar, netdir;
X{
X l->l_flag &= ~LDIR;
X l->l_flag |= netdir;
X l->l_netop = netchar;
X}
X
Xint
Xtracelink(arg)
X char *arg;
X{ char *bang;
X link *l;
X
X if (Tracecount >= NTRACE)
X return -1;
X l = newlink();
X bang = index(arg, '!');
X if (bang) {
X *bang = 0;
X l->l_to = addnode(bang+1);
X } else
X l->l_to = 0;
X
X l->l_from = addnode(arg);
X Trace[Tracecount++] = l;
X return 0;
X}
X
X/*
X * the obvious choice for testing equality is to compare struct
X * addresses, but that misses private nodes, so we use strcmp().
X */
X
XSTATIC void
Xltrace(from, to, cost, netchar, netdir, message)
X node *from, *to;
X Cost cost;
X char netchar, netdir, *message;
X{ link *l;
X int i;
X
X for (i = 0; i < Tracecount; i++) {
X l = Trace[i];
X /* overkill, but you asked for it! */
X if (l->l_to == 0) {
X if (EQ(from, l->l_from) || EQ(to, l->l_from))
X break;
X } else if (EQ(from, l->l_from) && EQ(to, l->l_to))
X break;
X else if (EQ(from, l->l_to) && EQ(to, l->l_from))
X break; /* potential dead backlink */
X }
X if (i < Tracecount)
X ltrprint(from, to, cost, netchar, netdir, message);
X}
X
X/* print a trace item */
XSTATIC void
Xltrprint(from, to, cost, netchar, netdir, message)
X node *from, *to;
X Cost cost;
X char netchar, netdir, *message;
X{ char buf[256], *bptr = buf;
X
X strcpy(bptr, from->n_name);
X bptr += strlen(bptr);
X *bptr++ = ' ';
X if (netdir == LRIGHT) /* @% */
X *bptr++ = netchar;
X strcpy(bptr, to->n_name);
X bptr += strlen(bptr);
X if (netdir == LLEFT) /* !: */
X *bptr++ = netchar;
X sprintf(bptr, "(%ld) %s", cost, message);
X yyerror(buf);
X}
X
Xvoid
Xatrace(n1, n2)
X node *n1, *n2;
X{ link *l;
X int i;
X char buf[256];
X
X for (i = 0; i < Tracecount; i++) {
X l = Trace[i];
X if (l->l_to == 0 && ((node *) l->l_from == n1 || (node *) l->l_from == n2)) {
X sprintf(buf, "%s = %s", n1->n_name, n2->n_name);
X yyerror(buf);
X return;
X }
X }
X}
X
Xint
Xmaptrace(from, to)
X register node *from, *to;
X{ register link *l;
X register int i;
X
X for (i = 0; i < Tracecount; i++) {
X l = Trace[i];
X if (l->l_to == 0) {
X if (EQ(from, l->l_from) || EQ(to, l->l_from))
X return 1;
X } else if (EQ(from, l->l_from) && EQ(to, l->l_to))
X return 1;
X }
X return 0;
X}
X
Xvoid
Xdeletelink(from, to)
X node *from;
X node *to;
X{ register link *l, *lnext;
X
X l = from->n_link;
X
X /* delete all neighbors of from */
X if (to == 0) {
X while (l) {
X LTRACE(from, l->l_to, l->l_cost, NETCHAR(l), NETDIR(l), "DELETED");
X lnext = l->l_next;
X freelink(l);
X l = lnext;
X }
X from->n_link = 0;
X return;
X }
X
X /* delete from head of list */
X while (l && EQ(to, l->l_to)) {
X LTRACE(from, to, l->l_cost, NETCHAR(l), NETDIR(l), "DELETED");
X lnext = l->l_next;
X freelink(l);
X l = from->n_link = lnext;
X }
X
X /* delete from interior of list */
X if (l == 0)
X return;
X for (lnext = l->l_next; lnext; lnext = l->l_next) {
X if (EQ(to, lnext->l_to)) {
X LTRACE(from, to, l->l_cost, NETCHAR(l), NETDIR(l), "DELETED");
X l->l_next = lnext->l_next;
X freelink(lnext);
X /* continue processing this link */
X } else
X l = lnext; /* next link */
X }
X}
END_OF_FILE
if test 6001 -ne `wc -c <'addlink.c'`; then
echo shar: \"'addlink.c'\" unpacked with wrong size!
fi
# end of 'addlink.c'
fi
if test -f 'addnode.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'addnode.c'\"
else
echo shar: Extracting \"'addnode.c'\" \(8979 characters\)
sed "s/^X//" >'addnode.c' <<'END_OF_FILE'
X/* pathalias -- by steve bellovin, as told to peter honeyman */
X#ifndef lint
Xstatic char *sccsid = "@(#)addnode.c 9.6 89/05/05";
X#endif
X
X#include "def.h"
X
X#define EQ(n, s) (*(n)->n_name == *(s) && strcmp((n)->n_name, (s)) == 0)
X
X/* exports */
Xnode *addnode(), *addprivate();
Xvoid alias(), hashanalyze(), fixprivate();
Xnode **Table; /* hash table ^ priority queue */
Xlong Tabsize; /* size of Table */
X
X/* imports */
Xextern link *addlink();
Xextern node *newnode(), **newtable();
Xextern char *strsave();
Xextern int Iflag, Tflag, Vflag;
Xextern node **Table;
Xextern long Ncount, Tabsize;
Xextern char **Argv;
Xextern void atrace(), die(), freetable();
Xextern int strcmp();
X
X/* privates */
XSTATIC void crcinit(), rehash(), lowercase();
XSTATIC long fold();
XSTATIC long hash();
XSTATIC node *isprivate();
Xstatic node *Private; /* list of private nodes in current input file */
X/*
X * these numbers are chosen because:
X * -> they are prime,
X * -> they are monotonic increasing,
X * -> each is a tad smaller than a multiple of 1024,
X * -> they form a fibonacci sequence (almost).
X * the first point yields good hash functions, the second is used for the
X * standard re-hashing implementation of open addressing, the third
X * optimizes for quirks in some mallocs i have seen, and the fourth simply
X * appeals to me.
X */
Xstatic long Primes[] = {
X 1021, 2039, 3067, 5113, 8179, 13309, 21499, 34807, 56311, 0
X};
X
Xstatic int Tabindex;
Xstatic long Tab128; /* Tabsize * 128 */
X
Xnode *
Xaddnode(name)
X register char *name;
X{ register long i;
X register node *n;
X
X if (Iflag)
X lowercase(name);
X
X /* is it a private host? */
X n = isprivate(name);
X if (n)
X return n;
X
X i = hash(name, 0);
X if (Table[i])
X return Table[i];
X
X n = newnode();
X n->n_name = strsave(name);
X Table[i] = n;
X n->n_tloc = i; /* essentially a back link to the table */
X
X return n;
X}
X
Xvoid
Xalias(n1, n2)
X node *n1, *n2;
X{
X link *l;
X
X if (ISADOMAIN(n1) && ISADOMAIN(n2)) {
X fprintf(stderr, "%s: domain alias %s = %s is illegal\n", Argv[0], n1->n_name, n2->n_name);
X return;
X }
X l = addlink(n1, n2, (Cost) 0, DEFNET, DEFDIR);
X l->l_flag |= LALIAS;
X l = addlink(n2, n1, (Cost) 0, DEFNET, DEFDIR);
X l->l_flag |= LALIAS;
X if (Tflag)
X atrace(n1, n2);
X}
X
X/*
X * fold a string into a long int. 31 bit crc (from andrew appel).
X * the crc table is computed at run time by crcinit() -- we could
X * precompute, but it takes 1 clock tick on a 750.
X *
X * This fast table calculation works only if POLY is a prime polynomial
X * in the field of integers modulo 2. Since the coefficients of a
X * 32-bit polynomail won't fit in a 32-bit word, the high-order bit is
X * implicit. IT MUST ALSO BE THE CASE that the coefficients of orders
X * 31 down to 25 are zero. Happily, we have candidates, from
X * E. J. Watson, "Primitive Polynomials (Mod 2)", Math. Comp. 16 (1962):
X * x^32 + x^7 + x^5 + x^3 + x^2 + x^1 + x^0
X * x^31 + x^3 + x^0
X *
X * We reverse the bits to get:
X * 111101010000000000000000000000001 but drop the last 1
X * f 5 0 0 0 0 0 0
X * 010010000000000000000000000000001 ditto, for 31-bit crc
X * 4 8 0 0 0 0 0 0
X */
X
X#define POLY32 0xf5000000 /* 32-bit polynomial */
X#define POLY31 0x48000000 /* 31-bit polynomial */
X#define POLY POLY31 /* use 31-bit to avoid sign problems */
X
Xstatic long CrcTable[128];
X
XSTATIC void
Xcrcinit()
X{ register int i,j;
X register long sum;
X
X for (i = 0; i < 128; i++) {
X sum = 0;
X for (j = 7-1; j >= 0; --j)
X if (i & (1 << j))
X sum ^= POLY >> j;
X CrcTable[i] = sum;
X }
X}
X
XSTATIC long
Xfold(s)
X register char *s;
X{ register long sum = 0;
X register int c;
X
X while ((c = *s++) != 0)
X sum = (sum >> 7) ^ CrcTable[(sum ^ c) & 0x7f];
X return sum;
X}
X
X
X#define HASH1(n) ((n) % Tabsize);
X#define HASH2(n) (Tabsize - 2 - ((n) % (Tabsize-2))) /* sedgewick */
X
X/*
X * when alpha is 0.79, there should be 2 probes per access (gonnet).
X * use long constant to force promotion. Tab128 biases HIGHWATER by
X * 128/100 for reduction in strength in isfull().
X */
X#define HIGHWATER 79L
X#define isfull(n) ((n) * 128 >= Tab128)
X
XSTATIC long
Xhash(name, unique)
X char *name;
X int unique;
X{ register long probe;
X register long hash2;
X register node *n;
X
X if (isfull(Ncount)) {
X if (Tabsize == 0) { /* first time */
X crcinit();
X Tabindex = 0;
X Tabsize = Primes[0];
X Table = newtable(Tabsize);
X Tab128 = (HIGHWATER * Tabsize * 128L)/100L;
X } else
X rehash(); /* more, more! */
X }
X
X probe = fold(name);
X hash2 = HASH2(probe);
X probe = HASH1(probe);
X
X /*
X * probe the hash table.
X * if unique is set, we require a fresh slot.
X * otherwise, use double hashing to find either
X * (1) an empty slot, or
X * (2) a non-private copy of this host name
X *
X * this is an "inner loop."
X */
X while ((n = Table[probe]) != 0) {
X if (EQ(n, name) && !(n->n_flag & ISPRIVATE) && !unique)
X return probe; /* this is it! */
X
X probe -= hash2; /* double hashing */
X if (probe < 0)
X probe += Tabsize;
X }
X return probe; /* brand new */
X}
X
XSTATIC void
Xrehash()
X{ register node **otable, **optr;
X register long probe;
X long osize;
X
X#ifdef DEBUG
X hashanalyze();
X#endif
X optr = Table + Tabsize - 1; /* ptr to last */
X otable = Table;
X osize = Tabsize;
X Tabsize = Primes[++Tabindex];
X if (Tabsize == 0)
X die("too many hosts"); /* need more prime numbers */
X vprintf(stderr, "rehash into %d\n", Tabsize);
X Table = newtable(Tabsize);
X Tab128 = (HIGHWATER * Tabsize * 128L)/100L;
X
X do {
X if (*optr == 0)
X continue; /* empty slot in old table */
X probe = hash((*optr)->n_name,
X ((*optr)->n_flag & ISPRIVATE) != 0);
X if (Table[probe] != 0)
X die("rehash error");
X Table[probe] = *optr;
X (*optr)->n_tloc = probe;
X } while (optr-- > otable);
X freetable(otable, osize);
X}
X
Xvoid
Xhashanalyze()
X#if 0
X{ long probe, hash2;
X int count, i, collision[8];
X int longest = 0, total = 0, slots = 0, longprobe = 0;
X int nslots = sizeof(collision)/sizeof(collision[0]);
X
X if (!Vflag)
X return;
X
X strclear((char *) collision, sizeof(collision));
X for (i = 0; i < Tabsize; i++) {
X if (Table[i] == 0)
X continue;
X /* private hosts too hard to account for ... */
X if (Table[i]->n_flag & ISPRIVATE)
X continue;
X count = 1;
X probe = fold(Table[i]->n_name);
X /* don't change the order of the next two lines */
X hash2 = HASH2(probe);
X probe = HASH1(probe);
X /* thank you! */
X while (Table[probe] != 0
X && strcmp(Table[probe]->n_name, Table[i]->n_name) != 0) {
X count++;
X probe -= hash2;
X if (probe < 0)
X probe += Tabsize;
X }
X if (Table[probe] == 0)
X die("impossible hash error");
X
X total += count;
X slots++;
X if (count > longest) {
X longest = count;
X longprobe = i;
X }
X if (count >= nslots)
X count = 0;
X collision[count]++;
X }
X for (i = 1; i < nslots; i++)
X if (collision[i])
X fprintf(stderr, "%d chains: %d (%ld%%)\n",
X i, collision[i], (collision[i] * 100L)/ slots);
X if (collision[0])
X fprintf(stderr, "> %d chains: %d (%ld%%)\n",
X nslots - 1, collision[0],
X (collision[0] * 100L)/ slots);
X fprintf(stderr, "%2.2f probes per access, longest chain: %d, %s\n",
X (double) total / slots, longest, Table[longprobe]->n_name);
X if (Vflag < 2)
X return;
X probe = fold(Table[longprobe]->n_name);
X hash2 = HASH2(probe);
X probe = HASH1(probe);
X while (Table[probe] != 0
X && strcmp(Table[probe]->n_name, Table[longprobe]->n_name) != 0) {
X fprintf(stderr, "%5d %s\n", probe, Table[probe]->n_name);
X probe -= hash2;
X if (probe < 0)
X probe += Tabsize;
X }
X fprintf(stderr, "%5d %s\n", probe, Table[probe]->n_name);
X
X}
X#else
X{
X /* the hash algorithms are perfect -- leave them alone */
X}
X#endif
X
X/* convert to lower case in place */
XSTATIC void
Xlowercase(s)
X register char *s;
X{
X do {
X if (isupper(*s))
X *s -= 'A' - 'a'; /* ASCII */
X } while (*s++);
X}
X
X/*
X * this might need change if privates catch on
X */
XSTATIC node *
Xisprivate(name)
X register char *name;
X{ register node *n;
X
X for (n = Private; n != 0; n = n->n_private)
X if (strcmp(name, n->n_name) == 0)
X return n;
X return 0;
X}
X
X/* Add a private node so private that nobody can find it. */
Xnode *
Xaddhidden(name)
X register char *name;
X{ register node *n;
X register int i;
X if (Iflag)
X lowercase(name);
X
X n = newnode();
X n->n_name = strsave(name);
X n->n_flag = ISPRIVATE;
X i = hash(n->n_name, 1);
X if (Table[i] != 0)
X die("impossible hidden node error");
X Table[i] = n;
X n->n_tloc = i;
X n->n_private = 0;
X return n;
X}
X
Xvoid
Xfixprivate()
X{ register node *n, *next;
X register long i;
X
X for (n = Private; n != 0; n = next) {
X n->n_flag |= ISPRIVATE; /* overkill, but safe */
X i = hash(n->n_name, 1);
X if (Table[i] != 0)
X die("impossible private node error");
X
X Table[i] = n;
X n->n_tloc = i; /* essentially a back link to the table */
X next = n->n_private;
X n->n_private = 0; /* clear for later use */
X }
X Private = 0;
X}
X
Xnode *
Xaddprivate(name)
X register char *name;
X{ register node *n;
X
X if (Iflag)
X lowercase(name);
X if ((n = isprivate(name)) != 0)
X return n;
X
X n = newnode();
X n->n_name = strsave(name);
X n->n_private = Private;
X Private = n;
X return n;
X}
END_OF_FILE
if test 8979 -ne `wc -c <'addnode.c'`; then
echo shar: \"'addnode.c'\" unpacked with wrong size!
fi
# end of 'addnode.c'
fi
if test -f 'arpa-privates' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'arpa-privates'\"
else
echo shar: Extracting \"'arpa-privates'\" \(7927 characters\)
sed "s/^X//" >'arpa-privates' <<'END_OF_FILE'
X#################################################################
X# arpa-privates file for arpatxt/pathalias #
X# #
X# updated from hosts.txt ver. 750 and the #
X# UUCP Project map data as of 17-Jun-88 #
X#################################################################
X# "master" file is available for anonymous ftp at: #
X# swan.ulowell.edu:~ftp/hosts/arpa-privates #
X# citi.umich.edu:~ftp/pub/honey/arpa-privates #
X# #
X# Send updates to postmaster at one of above sites. #
X#################################################################
X# format: #
X# host map.file (for registered UUCP hosts) #
X# host [map.file] (for unregistered UUCP hosts) #
X# Everything after white space is ignored, and is #
X# primarily intended to keep the file easier to update. #
X# Order does not matter, but case does. #
X#################################################################
Xa usa.ca
Xaardvark usa.or
Xabbott usa.ca
Xac1 [usa.ca] nsc
Xac6 [usa.ca] cerebus, esl
Xachilles [att]
Xacorn gbr
Xadam swe
Xadams swe
Xadmin usa.ca
Xalamo usa.tx
Xalex usa.va
Xalf [usa.az] ellymae
Xalgedi [usa.wa] pilchuck
Xalien usa.ca
Xalpha usa.in
Xaltair [usa.tx] juniper
Xamc usa.wa
Xamos [usa.ca] suntan
Xandy [att]
Xantares usa.nj
Xanubis usa.il
Xapollo usa.ma
Xaqua usa.ma
Xarc usa.ca
Xares swe
Xargon usa.nj
Xargus usa.nj
Xariadne grc
Xariel [usa.oh] mtune-isn
Xaris grc
Xarthur [usa.mo] wuphys
Xasgard usa.or
Xastro [usa.tx] milano
Xathena [usa.ca] daisy
Xatlas [att]
Xatt
Xb21 deu
Xbacchus usa.nc
Xbert usa.ca
Xbezier [usa.oh] bgsuvax
Xblue jpn
Xbluto [usa.tx] im4u
Xbobcat [usa.ca] vortex
Xboojum [att]
Xboole [att]
Xbosco [esp]
Xbounty [usa.az] ellymae
Xbourbaki usa.il
Xbridge [usa.il] richp1
Xbugs [usa.ca] cuschico
Xbull usa.ca
Xcac usa.ma
Xcad dmk (ibt)
Xcalico usa.ny
Xcallisto usa.in
Xcalvin [usa.ca] ucdavis
Xcantor [usa.il] gargoyle, luccpud
Xcarl swe
Xcarmel [usa.az] verde
Xcarrara [usa.ma] talcott
Xcasper usa.or
Xcastor [att]
Xccb [kor] kaist
Xccd usa.fl (pd1)
Xccs [usa.tx] convex
Xcerberus usa.ca
Xchaos usa.ok
Xcheetah usa.oh
Xchem usa.ca
Xcheops [usa.ca] esl
Xchip usa.ca
Xchiron usa.ny
Xchopin [att]
Xcims1 usa.ga
Xcip ita
Xcirce [att]
Xclara usa.ny
Xclover usa.ca
Xcls [usa.nh] sii
Xclutx [usa.fl] gould
Xcmr usa.fl
Xcogito [att]
Xcognac usa.pa
Xcolby usa.me
Xcondor usa.ma
Xcookie usa.ne
Xcoral usa.ca
Xcortex [usa.tx] CNLNET/soma
Xcottage gbr
Xcrash usa.ca
Xcs1 usa.ca
Xcsab [usa.va] xanth, [usa.il] uiucdcs
Xcsc can.on
Xcsd1 [usa.ny] cmcl2
Xcsd2 [usa.ny] cmcl2
Xcssun [usa.ny] albanycs
Xcsun1 usa.ga
Xcsun2 usa.ga
Xcti usa.ca
Xcurie usa.tx
Xcygnus usa.ny
Xdalek usa.ca
Xdali [esp] goya
Xdarwin can.on
Xdavid usa.oh
Xdcn1 [usa.ca] scgvaxd
Xdeimos [usa.oh] codas
Xdelphi ita
Xdeneb [can.bc] ubc-cs
Xdescartes [usa.ca] nosc
Xdevvax usa.ny (until Larry fixes news path on jpl-devvax)
Xdewey [usa.ca] hpda
Xdipl usa.ca
Xdisc [usa.ca] ucdavis
Xdorothy usa.ca
Xdraco [usa.tx] petro
Xea usa.ok
Xeagle [usa.ca] ames
Xearth [att]
Xeast fra
Xecn nld
Xed gbr
Xedam [att]
Xedith [usa.oh] mtune
Xeli usa.dc
Xelse jpn
Xelvira [usa.dc] sundc
Xemily [usa.nj] althea
Xems usa.mn
Xernie usa.ca
Xescher usa.ca
Xetl [usa.va] potomac
Xeunice usa.fl
Xeuropa usa.ri
Xevans [usa.ca] ucbvax
Xeve [usa.ny] clara
Xewok [usa.nc] suntri
Xfalcon [usa.nc] suntri
Xfaraday usa.ny
Xfaust usa.ma
Xfenway usa.ga
Xfergvax [usa.ne] upba
Xfisher usa.nj
Xflight [usa.or] argent
Xfluke usa.wa
Xfoobar usa.or
Xforest [usa.tx] hal6000
Xforty2 che
Xfred usa.co
Xfrisbee usa.co
Xfrog usa.ma
Xgaia usa.co
Xgalaxy usa.nj
Xgamma [usa.oh] codas
Xgandalf can.on
Xgarfield can.nf
Xgateway [usa.ut] pedro
Xgemini usa.ca
Xgeorge usa.tx
Xgilbert [usa.wa] pilchuck
Xgizmo [usa.ca] sun
Xgodot usa.nc
Xgodzilla [att]
Xgolem usa.ca
Xgort [usa.ok] romed
Xgould usa.fl
Xgranite [usa.nh] decvax
Xgreen [usa.md] jhunix
Xgrendel [usa.oh] mtune
Xgrinch usa.ca
Xgroucho [att]
Xgrumpy [usa.oh] codas
Xgull usa.tx
Xhal usa.oh
Xhamster [usa.ca] qantel
Xhappy usa.ca
Xhawk [usa.ca] nosc
Xhector [att]
Xhelios can.on
Xhermes [att]
Xhollywood [usa.ca] fortune
Xhottub usa.ca
Xhq sgp
Xhub [usa.ca] comdesign
Xhugo usa.va
Xhydra usa.nj
Xhydro [usa.ca] csustan
Xibd [att]
Xibis usa.tx
Xicarus [usa.ri] brunix
Xice usa.wi
Ximagen usa.ca
Xindra [usa.oh] codas
Xintrepid usa.ar
Xio [usa.oh] mtune
Xipac [usa.az] noao, [usa.ca] csula-ps
Xircam fra
Xiris usa.ri
Xisi usa.ca
Xisis usa.co
Xisland usa.ca
Xjack usa.ca
Xjanus usa.ca
Xjhereg [usa.mn] bungia
Xjuniper usa.tx
Xkaos usa.ma
Xkiwi bel
Xkontiki dmk
Xkronos grc
Xlafite [usa.nh] decvax
Xlassen usa.ca
Xlaura deu
Xleg [fra] geocub
Xlego dmk
Xleopard [att]
Xlilac kor
Xlinus usa.ma
Xlion [att]
Xlola [usa.oh] codas
Xlono usa.ca
Xlynx usa.ca
Xmacom1 usa.md
Xmagic [usa.ca] idi
Xmanatee usa.fl
Xmanta usa.pa
Xmarge usa.ca
Xmars usa.nj
Xmaui usa.va
Xmax [att]
Xmaxwell usa.mo
Xmcl can.sk
Xmcs usa.md
Xmedusa usa.nj
Xmegalon deu
Xmercury [usa.ma] interlan
Xmerlin [usa.ma] masscomp
Xmickey usa.ca
Xmimas nld
Xminnie usa.co
Xmiranda [usa.oh] mtune
Xmirage gbr
Xmoe [usa.nv] jimi
Xmojave usa.ca
Xmoses [usa.mi] umich
Xmouse usa.de
Xmozart usa.ny
Xmruxd [att]
Xms can.on
Xmycroft [usa.ca] hplabs
Xmyrddin [usa.ca] amdahl-bartender
Xnetman [att]
Xnewton [can.bc] ubc-cs
Xnexus usa.dc
Xnirvana usa.va
Xnoether [usa.ny] mozart
Xnova usa.ok
Xoac [att]
Xnps [usa.il] cerl
Xnyquiest [att]
Xoahu [usa.nj] hjuxa
Xoak [usa.ct] clunker
Xoasis usa.ca (precautionary. llnl clashes with oasis.sait.ko.kr)
Xocean [usa.ca] ucsbcsl
Xodin [att]
Xopus [att]
Xorbit usa.mn
Xorca [usa.az] ellymae
Xorcas usa.wa
Xoregon usa.or {believe it or not}
Xorion [att]
Xorville usa.ny
Xoscar [usa.oh] bcd-dyn
Xosiris usa.md
Xoz usa.wa
Xpallas usa.il
Xpandora [usa.ma] harv-net
Xpegasus [att]
Xpercival usa.or
Xphobos usa.vt
Xphoebus gbr
Xphoenix [att]
Xphysics [usa.ny] ccnysci
Xpicasso [esp] goya
Xpilchuck usa.wa
Xpioneer usa.md
Xpixar usa.ca
Xplasma usa.ca
Xplato usa.ca
Xpluto usa.ny
Xpokey [usa.va] men2a
Xpolaris [usa.wa] camco
Xpollux usa.tx
Xpostel nld
Xpresto usa.md
Xpriam [che] cernvax
Xprime usa.ma
Xprism usa.nj
Xprodigal usa.pa
Xprometheus usa.md
Xpsc usa.md
Xpsych [aus]
Xpsyche usa.nc
Xpuppy usa.ny
Xqat [usa.tx] techsup
Xquark [usa.ca] csuchico
Xra [can.bc] ubc-cs
Xrainier swe
Xralph usa.la
Xrdm usa.ga
Xreason usa.ny
Xrebel usa.ga
Xred jpn
Xredwood [usa.ca] amdcad
Xridge usa.ca
Xrobin [usa.oh] bgsuvax [usa.ma] linus
Xrodan usa.or
Xrome usa.ok
Xrosetta [usa.tx] rice
Xrover [usa.az] ellymae
Xrsch [usa.ma] harvard
Xsable [usa.ca] pyramid
Xsabre [usa.oh] codas
Xsal swe
Xsam usa.il
Xsandy [usa.tx] woton
Xsas [usa.nc] rti
Xsaturn [kor] ketri
Xscarecrow [usa.pa] lehi3b15
Xscooter usa.ca
Xselect nld
Xservice gbr
Xshamash usa.mn
Xshaw [att]
Xshockeye usa.pa
Xshrike [usa.tx] MBIRNET
Xshrimp usa.tx
Xsierra usa.ca
Xsimon usa.il
Xsirius [usa.nh] dartvax
Xsmith [can.ab] edm
Xsnark usa.pa
Xsnucom kor
Xsol usa.nh
Xsolar usa.nm
Xsoleil usa.nj
Xspam usa.nj
Xsparky [usa.oh] codas
Xsphinx usa.il
Xspike usa.la
Xspock usa.ct
Xsri aus.qld
Xssi usa.wi
Xstar [usa.oh] codas
Xstars [can.ns] dalcs
Xstuart [usa.md] prometheus
Xstymie [usa.ma] harvard
Xsuna [usa.mn] mscunx
Xsunburn usa.az
Xsunrise usa.nj
Xsunspot usa.nm
Xsuntan usa.ca
Xsunup usa.wa
Xsuper usa.md
Xsvc [usa.md] epiwrl
Xswamp [usa.ca] amdahl
Xswan usa.tx
Xtaurus isr
Xte gbr
Xterminus [att]
Xthermo [usa.nv] stride1
Xthor dmk
Xthunder can.on
Xtiger usa.nj
Xtinman usa.ca
Xtitan usa.ca
Xtrantor usa.ca
Xtut fin
Xubvax usa.ca
Xunh usa.nh
Xunix usa.wa
Xusafa [usa.co] winfree, [usa.fl] gould, [usa.nh] trixie
Xvalhalla [usa.mi] edsr
Xvax2 [usa.md] elsie
Xvector usa.tx
Xvice [usa.or] enky, budda, loop
Xvideo [att]
Xvilya [att]
Xviper [usa.mn] bungia, mmm, pwcs, quest
Xvista usa.ca
Xvlsi1 [usa.ut] byuopus
Xvlsi2 [usa.ut] byuopus
Xvlsi3 [usa.ut] byuopus
Xvolt usa.ca
Xvoodoo usa.wa
Xwang usa.ma
Xwayback [att]
Xwombat usa.ca
Xwotan usa.ca
Xxyzzy usa.nc
Xyoda usa.co (UCARNET)
Xyogi [usa.nj] bellcore-micom, pyrnj
Xz usa.ca
Xzap can.qc
Xzaphod can.sk
Xzeta [usa.md] cp1
Xzeus can.bc
Xzip usa.oh
Xzorac can.on
END_OF_FILE
if test 7927 -ne `wc -c <'arpa-privates'`; then
echo shar: \"'arpa-privates'\" unpacked with wrong size!
fi
# end of 'arpa-privates'
fi
if test -f 'mapaux.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'mapaux.c'\"
else
echo shar: Extracting \"'mapaux.c'\" \(8512 characters\)
sed "s/^X//" >'mapaux.c' <<'END_OF_FILE'
X/* pathalias -- by steve bellovin, as told to peter honeyman */
X#ifndef lint
Xstatic char *sccsid = "@(#)mapaux.c 9.4 89/03/01";
X#endif /* lint */
X
X#include "def.h"
X
X/* imports */
Xextern long Nheap, Hashpart, Tabsize, NumNcopy, Nlink, NumLcopy;
Xextern node **Table, *Home;
Xextern char *Graphout, *Linkout, *Netchars, **Argv;
Xextern int Vflag;
Xextern void freelink(), die();
Xextern long pack();
Xextern link *newlink();
Xextern node *newnode();
Xextern char *strsave();
Xextern int strcmp(), strlen();
X
X/* exports */
Xextern long pack();
Xextern void resetnodes(), dumpgraph(), showlinks(), terminalnet();
Xextern int tiebreaker();
Xextern node *ncopy();
X
X/* privates */
Xstatic FILE *Gstream; /* for dumping graph */
XSTATIC void dumpnode(), untangle(), dfs();
XSTATIC int height();
XSTATIC link *lcopy();
X
X
X/*
X * slide everything from Table[low] to Table[high]
X * up toward the high end. make room! make room!
X */
Xlong
Xpack(low, high)
X long low, high;
X{ long hole, next;
X
X /* find first "hole " */
X for (hole = high; hole >= low && Table[hole] != 0; --hole)
X ;
X
X /* repeatedly move next filled entry into last hole */
X for (next = hole - 1; next >= low; --next) {
X if (Table[next] != 0) {
X Table[hole] = Table[next];
X Table[hole]->n_tloc = hole;
X Table[next] = 0;
X while (Table[--hole] != 0) /* find next hole */
X ;
X }
X }
X return hole + 1;
X}
X
Xvoid
Xresetnodes()
X{ register long i;
X register node *n;
X
X for (i = Hashpart; i < Tabsize; i++)
X if ((n = Table[i]) != 0) {
X n->n_cost = (Cost) 0;
X n->n_flag &= ~(NALIAS|ATSIGN|MAPPED|HASLEFT|HASRIGHT|NTERMINAL);
X n->n_copy = n;
X }
X
X Home->n_cost = (Cost) 0;
X Home->n_flag &= ~(NALIAS|ATSIGN|MAPPED|HASLEFT|HASRIGHT|NTERMINAL);
X Home->n_copy = Home;
X}
X
Xvoid
Xdumpgraph()
X{ register long i;
X register node *n;
X
X if ((Gstream = fopen(Graphout, "w")) == NULL) {
X fprintf(stderr, "%s: ", Argv[0]);
X perror(Graphout);
X return;
X }
X
X untangle(); /* untangle net cycles for proper output */
X
X for (i = Hashpart; i < Tabsize; i++) {
X n = Table[i];
X if (n == 0)
X continue; /* impossible, but ... */
X /* a minor optimization ... */
X if (n->n_link == 0)
X continue;
X /* pathparse doesn't need these */
X if (n->n_flag & NNET)
X continue;
X dumpnode(n);
X }
X}
X
XSTATIC void
Xdumpnode(from)
X register node *from;
X{ register node *to;
X register link *l;
X link *lnet = 0, *ll, *lnext;
X
X for (l = from->n_link ; l; l = l->l_next) {
X to = l->l_to;
X if (from == to)
X continue; /* oops -- it's me! */
X
X if ((to->n_flag & NNET) == 0) {
X /* host -> host -- print host>host */
X if (l->l_cost == INF)
X continue; /* phoney link */
X fputs(from->n_name, Gstream);
X putc('>', Gstream);
X fputs(to->n_name, Gstream);
X putc('\n', Gstream);
X } else {
X /*
X * host -> net -- just cache it for now.
X * first check for dups. (quadratic, but
X * n is small here.)
X */
X while (to->n_root && to != to->n_root)
X to = to->n_root;
X for (ll = lnet; ll; ll = ll->l_next)
X if (strcmp(ll->l_to->n_name, to->n_name) == 0)
X break;
X if (ll)
X continue; /* dup */
X ll = newlink();
X ll->l_next = lnet;
X ll->l_to = to;
X lnet = ll;
X }
X }
X
X /* dump nets */
X if (lnet) {
X /* nets -- print host@\tnet,net, ... */
X fputs(from->n_name, Gstream);
X putc('@', Gstream);
X putc('\t', Gstream);
X for (ll = lnet; ll; ll = lnext) {
X lnext = ll->l_next;
X fputs(ll->l_to->n_name, Gstream);
X if (lnext)
X fputc(',', Gstream);
X freelink(ll);
X }
X putc('\n', Gstream);
X }
X}
X
X/*
X * remove cycles in net definitions.
X *
X * depth-first search
X *
X * for each net, run dfs on its neighbors (nets only). if we return to
X * a visited node, that's a net cycle. mark the cycle with a pointer
X * in the n_root field (which gets us closer to the root of this
X * portion of the dfs tree).
X */
XSTATIC void
Xuntangle()
X{ register long i;
X register node *n;
X
X for (i = Hashpart; i < Tabsize; i++) {
X n = Table[i];
X if (n == 0 || (n->n_flag & NNET) == 0 || n->n_root)
X continue;
X dfs(n);
X }
X}
X
XSTATIC void
Xdfs(n)
X register node *n;
X{ register link *l;
X register node *next;
X
X n->n_flag |= INDFS;
X n->n_root = n;
X for (l = n->n_link; l; l = l->l_next) {
X next = l->l_to;
X if ((next->n_flag & NNET) == 0)
X continue;
X if ((next->n_flag & INDFS) == 0) {
X dfs(next);
X if (next->n_root != next)
X n->n_root = next->n_root;
X } else
X n->n_root = next->n_root;
X }
X n->n_flag &= ~INDFS;
X}
X
Xvoid
Xshowlinks()
X{ register link *l;
X register node *n;
X register long i;
X FILE *estream;
X
X if ((estream = fopen(Linkout, "w")) == 0)
X return;
X
X for (i = Hashpart; i < Tabsize; i++) {
X n = Table[i];
X if (n == 0 || n->n_link == 0)
X continue;
X for (l = n->n_link; l; l = l->l_next) {
X fputs(n->n_name, estream);
X putc('\t', estream);
X if (NETDIR(l) == LRIGHT)
X putc(NETCHAR(l), estream);
X fputs(l->l_to->n_name, estream);
X if (NETDIR(l) == LLEFT)
X putc(NETCHAR(l), estream);
X fprintf(estream, "(%d)\n", l->l_cost);
X }
X }
X (void) fclose(estream);
X}
X
X/*
X * n is node in heap, newp is candidate for new parent.
X * choose between newp and n->n_parent for parent.
X * return 0 to use newp, non-zero o.w.
X */
X#define NEWP 0
X#define OLDP 1
Xint
Xtiebreaker(n, newp)
X node *n;
X register node *newp;
X{ register char *opname, *npname, *name;
X register node *oldp;
X int metric;
X
X oldp = n->n_parent;
X
X /* given the choice, avoid gatewayed nets */
X if (GATEWAYED(newp) && !GATEWAYED(oldp))
X return OLDP;
X if (!GATEWAYED(newp) && GATEWAYED(oldp))
X return NEWP;
X
X /* look at real parents, not nets */
X while ((oldp->n_flag & NNET) && oldp->n_parent)
X oldp = oldp->n_parent;
X while ((newp->n_flag & NNET) && newp->n_parent)
X newp = newp->n_parent;
X
X /* use fewer hops, if possible */
X metric = height(oldp) - height(newp);
X if (metric < 0)
X return OLDP;
X if (metric > 0)
X return NEWP;
X
X /*
X * compare names
X */
X opname = oldp->n_name;
X npname = newp->n_name;
X name = n->n_name;
X
X /* use longest common prefix with parent */
X while (*opname == *name && *npname == *name && *name) {
X opname++;
X npname++;
X name++;
X }
X if (*opname == *name)
X return OLDP;
X if (*npname == *name)
X return NEWP;
X
X /* use shorter host name */
X metric = strlen(opname) - strlen(npname);
X if (metric < 0)
X return OLDP;
X if (metric > 0)
X return NEWP;
X
X /* use larger lexicographically */
X metric = strcmp(opname, npname);
X if (metric < 0)
X return NEWP;
X return OLDP;
X}
X
XSTATIC int
Xheight(n)
X register node *n;
X{ register int i = 0;
X
X if (n == 0)
X return 0;
X while ((n = n->n_parent) != 0)
X if (ISADOMAIN(n) || !(n->n_flag & NNET))
X i++;
X return i;
X}
X
X/*
X * return a copy of n ( == l->l_to). we rely on n and its copy
X * pointing to the same name string, which is kludgey, but works
X * because the name is non-volatile.
X */
X
X#define REUSABLE(n, l) (((n)->n_flag & NTERMINAL) == 0 \
X && ((n)->n_copy->n_flag & NTERMINAL) \
X && !((n)->n_copy->n_flag & NALIAS) \
X && !((l)->l_flag & LALIAS))
Xnode *
Xncopy(parent, l)
X register node *parent;
X register link *l;
X{ register node *n, *ncp;
X
X#ifdef DEBUG
X if (Vflag > 1)
X vprintf(stderr, "<%s> <- %s\n", l->l_to->n_name, parent->n_name);
X#endif
X n = l->l_to;
X if (REUSABLE(n, l)) {
X Nlink++;
X return n->n_copy; /* re-use */
X }
X NumNcopy++;
X l->l_to = ncp = newnode();
X ncp->n_name = n->n_name; /* nonvolatile */
X ncp->n_tloc = --Hashpart; /* better not be > 20% of total ... */
X if (Hashpart == Nheap)
X die("too many terminal links");
X Table[Hashpart] = ncp;
X ncp->n_copy = n->n_copy; /* circular list */
X n->n_copy = ncp;
X ncp->n_link = lcopy(parent, n);
X ncp->n_flag = (n->n_flag & ~(NALIAS|ATSIGN|MAPPED|HASLEFT|HASRIGHT)) | NTERMINAL;
X return ncp;
X}
X
X/*
X * copy l, but don't include any links to parent.
X *
X * this is a little messier than it should be, because
X * of the funny test for ancestry, and because it wants
X * to be recursive, but the recursion might be very deep
X * (for a long link list), so it's done iteratively.
X */
XSTATIC link *
Xlcopy(parent, n)
X register node *parent, *n;
X{ register link *l, *lcp;
X link *first = 0, *last = 0;
X
X for (l = n->n_link; l != 0; l = l->l_next) {
X /* avoid vestigial descendants */
X if ((l->l_to->n_flag & MAPPED) != 0
X || ALTEREGO(l->l_to, parent))
X continue;
X#ifdef DEBUG
X if (Vflag > 1)
X vprintf(stderr, "\t-> %s\n", l->l_to->n_name);
X#endif
X NumLcopy++;
X lcp = newlink();
X *lcp = *l; /* struct copy */
X lcp->l_flag &= ~LTREE;
X if (ISANET(n))
X lcp->l_flag |= LTERMINAL;
X
X if (first == 0) {
X first = last = lcp;
X } else {
X last->l_next = lcp;
X last = lcp;
X }
X }
X if (last)
X last->l_next = 0;
X return first;
X}
END_OF_FILE
if test 8512 -ne `wc -c <'mapaux.c'`; then
echo shar: \"'mapaux.c'\" unpacked with wrong size!
fi
# end of 'mapaux.c'
fi
if test -f 'parse.y' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'parse.y'\"
else
echo shar: Extracting \"'parse.y'\" \(10671 characters\)
sed "s/^X//" >'parse.y' <<'END_OF_FILE'
X%{
X/* pathalias -- by steve bellovin, as told to peter honeyman */
X#ifndef lint
Xstatic char *sccsid = "@(#)parse.y 9.10 88/09/07";
X#endif /* lint */
X
X#include "def.h"
X
X/* scanner states (yylex, parse) */
X#define OTHER 0
X#define COSTING 1
X#define NEWLINE 2
X#define FILENAME 3
X
X/* exports */
Xlong Tcount;
Xextern void yyerror();
X
X/* imports */
Xextern node *addnode(), *addprivate();
Xextern void fixprivate(), alias(), deadlink(), deletelink();
Xextern link *addlink();
Xextern int strcmp();
Xextern char *strsave();
Xextern int optind;
Xextern char *Cfile, *Netchars, **Argv;
Xextern int Lineno, Argc;
X
X/* privates */
XSTATIC void fixnet(), adjust();
XSTATIC int yylex(), yywrap(), getword();
Xstatic int Scanstate = NEWLINE; /* scanner (yylex) state */
X
X/* flags for ys_flags */
X#define TERMINAL 1
X%}
X
X%union {
X node *y_node;
X Cost y_cost;
X char y_net;
X char *y_name;
X struct {
X node *ys_node;
X Cost ys_cost;
X short ys_flag;
X char ys_net;
X char ys_dir;
X } y_s;
X}
X
X%type <y_s> site asite
X%type <y_node> links aliases plist network nlist host nhost
X%type <y_node> usite delem dlist
X%type <y_cost> cost cexpr
X
X%token <y_name> SITE HOST STRING
X%token <y_cost> COST
X%token <y_net> NET
X%token EOL PRIVATE DEAD DELETE FILETOK ADJUST
X
X%left '+' '-'
X%left '*' '/'
X
X%%
Xmap : /* empty */
X | map EOL
X | map links EOL
X | map aliases EOL
X | map network EOL
X | map private EOL
X | map dead EOL
X | map delete EOL
X | map file EOL
X | map adjust EOL
X | error EOL
X ;
X
Xlinks : host site cost {
X struct link *l;
X
X l = addlink($1, $2.ys_node, $3, $2.ys_net, $2.ys_dir);
X if (GATEWAYED($2.ys_node))
X l->l_flag |= LGATEWAY;
X if ($2.ys_flag & TERMINAL)
X l->l_flag |= LTERMINAL;
X }
X | links ',' site cost {
X struct link *l;
X
X l = addlink($1, $3.ys_node, $4, $3.ys_net, $3.ys_dir);
X if (GATEWAYED($3.ys_node))
X l->l_flag |= LGATEWAY;
X if ($3.ys_flag & TERMINAL)
X l->l_flag |= LTERMINAL;
X }
X | links ',' /* benign error */
X ;
X
Xhost : HOST {$$ = addnode($1);}
X | PRIVATE {$$ = addnode("private");}
X | DEAD {$$ = addnode("dead");}
X | DELETE {$$ = addnode("delete");}
X | FILETOK {$$ = addnode("file");}
X | ADJUST {$$ = addnode("adjust");}
X ;
X
Xsite : asite {
X $$ = $1;
X $$.ys_net = DEFNET;
X $$.ys_dir = DEFDIR;
X }
X | NET asite {
X $$ = $2;
X $$.ys_net = $1;
X $$.ys_dir = LRIGHT;
X }
X | asite NET {
X $$ = $1;
X $$.ys_net = $2;
X $$.ys_dir = LLEFT;
X }
X ;
X
Xasite : SITE {
X $$.ys_node = addnode($1);
X $$.ys_flag = 0;
X }
X | '<' SITE '>' {
X Tcount++;
X $$.ys_node = addnode($2);
X $$.ys_flag = TERMINAL;
X }
X ;
X
Xaliases : host '=' SITE {alias($1, addnode($3));}
X | aliases ',' SITE {alias($1, addnode($3));}
X | aliases ',' /* benign error */
X ;
X
Xnetwork : nhost '{' nlist '}' cost {fixnet($1, $3, $5, DEFNET, DEFDIR);}
X | nhost NET '{' nlist '}' cost {fixnet($1, $4, $6, $2, LRIGHT);}
X | nhost '{' nlist '}' NET cost {fixnet($1, $3, $6, $5, LLEFT);}
X ;
X
Xnhost : '=' {$$ = 0; /* anonymous net */}
X | host '=' {$$ = $1; /* named net */}
X ;
X
Xnlist : SITE {$$ = addnode($1);}
X | nlist ',' SITE {
X node *n;
X
X n = addnode($3);
X if (n->n_net == 0) {
X n->n_net = $1;
X $$ = n;
X }
X }
X | nlist ',' /* benign error */
X ;
X
Xprivate : PRIVATE '{' plist '}' /* list of privates */
X | PRIVATE '{' '}' {fixprivate();} /* end scope of privates */
X ;
X
Xplist : SITE {addprivate($1)->n_flag |= ISPRIVATE;}
X | plist ',' SITE {addprivate($3)->n_flag |= ISPRIVATE;}
X | plist ',' /* benign error */
X ;
X
Xdead : DEAD '{' dlist '}';
X
Xdlist : delem
X | dlist ',' delem
X | dlist ',' /* benign error */
X ;
X
Xdelem : SITE {deadlink(addnode($1), (node *) 0);}
X | usite NET usite {deadlink($1, $3);}
X ;
X
Xusite : SITE {$$ = addnode($1);} ; /* necessary unit production */
X
Xdelete : DELETE '{' dellist '}';
X
Xdellist : delelem
X | dellist ',' delelem
X | dellist ',' /* benign error */
X ;
X
Xdelelem : SITE {
X node *n;
X
X n = addnode($1);
X deletelink(n, (node *) 0);
X n->n_flag |= ISPRIVATE;
X }
X | usite NET usite {deletelink($1, $3);}
X ;
X
Xfile : FILETOK '{' {Scanstate = FILENAME;} STRING {Scanstate = OTHER;} '}' {
X Lineno = 0;
X Cfile = strsave($4);
X }
X
Xadjust : ADJUST '{' adjlist '}' ;
X
Xadjlist : adjelem
X | adjlist ',' adjelem
X | adjlist ',' /* benign error */
X ;
X
Xadjelem : usite cost {adjust($1, $2);} ;
X
Xcost : {$$ = DEFCOST; /* empty -- cost is always optional */}
X | '(' {Scanstate = COSTING;} cexpr {Scanstate = OTHER;} ')'
X {$$ = $3;}
X ;
X
Xcexpr : COST
X | '-' cexpr {$$ = -$2;}
X | '(' cexpr ')' {$$ = $2;}
X | cexpr '+' cexpr {$$ = $1 + $3;}
X | cexpr '-' cexpr {$$ = $1 - $3;}
X | cexpr '*' cexpr {$$ = $1 * $3;}
X | cexpr '/' cexpr {
X if ($3 == 0)
X yyerror("zero divisor\n");
X else
X $$ = $1 / $3;
X }
X ;
X%%
X
Xvoid
X#ifdef YYDEBUG
X/*VARARGS1*/
Xyyerror(fmt, arg)
X char *fmt, *arg;
X#else
Xyyerror(s)
X char *s;
X#endif
X{
X /* a concession to bsd error(1) */
X fprintf(stderr, "\"%s\", ", Cfile);
X#ifdef YYDEBUG
X fprintf(stderr, "line %d: ", Lineno);
X fprintf(stderr, fmt, arg);
X putc('\n', stderr);
X#else
X fprintf(stderr, "line %d: %s\n", Lineno, s);
X#endif
X}
X
X/*
X * patch in the costs of getting on/off the network.
X *
X * for each network member on netlist, add links:
X * network -> member cost = 0;
X * member -> network cost = parameter.
X *
X * if network and member both require gateways, assume network
X * is a gateway to member (but not v.v., to avoid such travesties
X * as topaz!seismo.css.gov.edu.rutgers).
X *
X * note that members can have varying costs to a network, by suitable
X * multiple declarations. this is a feechur, albeit a useless one.
X */
XSTATIC void
Xfixnet(network, nlist, cost, netchar, netdir)
X register node *network;
X node *nlist;
X Cost cost;
X char netchar, netdir;
X{ register node *member, *nextnet;
X link *l;
X static int netanon = 0;
X char anon[25];
X
X if (network == 0) {
X sprintf(anon, "[unnamed net %d]", netanon++);
X network = addnode(anon);
X }
X network->n_flag |= NNET;
X
X /* insert the links */
X for (member = nlist ; member; member = nextnet) {
X
X /* network -> member, cost is 0 */
X l = addlink(network, member, (Cost) 0, netchar, netdir);
X if (GATEWAYED(network) && GATEWAYED(member))
X l->l_flag |= LGATEWAY;
X
X /* member -> network, cost is parameter */
X /* never ever ever crawl up from a domain*/
X if (!ISADOMAIN(network))
X (void) addlink(member, network, cost, netchar, netdir);
X
X nextnet = member->n_net;
X member->n_net = 0; /* clear for later use */
X }
X}
X
X/* scanner */
X
X#define QUOTE '"'
X#define STR_EQ(s1, s2) (s1[2] == s2[2] && strcmp(s1, s2) == 0)
X#define NLRETURN() {Scanstate = NEWLINE; return EOL;}
X
Xstatic struct ctable {
X char *cname;
X Cost cval;
X} ctable[] = {
X /* ordered by frequency of appearance in a "typical" dataset */
X {"DIRECT", 200},
X {"DEMAND", 300},
X {"DAILY", 5000},
X {"HOURLY", 500},
X {"DEDICATED", 100},
X {"EVENING", 2000},
X {"LOCAL", 25},
X {"LOW", 5}, /* baud rate, quality penalty */
X {"DEAD", MILLION},
X {"POLLED", 5000},
X {"WEEKLY", 30000},
X {"HIGH", -5}, /* baud rate, quality bonus */
X {"FAST", -80}, /* high speed (>= 9.6 kbps) modem */
X /* deprecated */
X {"ARPA", 100},
X {"DIALED", 300},
X {0, 0}
X};
X
XSTATIC int
Xyylex()
X{ static char retbuf[128]; /* for return to yacc part */
X register int c;
X register char *buf = retbuf;
X register struct ctable *ct;
X register Cost cost;
X char errbuf[128];
X
X if (feof(stdin) && yywrap())
X return EOF;
X
X /* count lines, skip over space and comments */
X if ((c = getchar()) == EOF)
X NLRETURN();
X
Xcontinuation:
X while (c == ' ' || c == '\t')
X if ((c = getchar()) == EOF)
X NLRETURN();
X
X if (c == '#')
X while ((c = getchar()) != '\n')
X if (c == EOF)
X NLRETURN();
X
X /* scan token */
X if (c == '\n') {
X Lineno++;
X if ((c = getchar()) != EOF) {
X if (c == ' ' || c == '\t')
X goto continuation;
X ungetc(c, stdin);
X }
X NLRETURN();
X }
X
X switch(Scanstate) {
X case COSTING:
X if (isdigit(c)) {
X cost = c - '0';
X for (c = getchar(); isdigit(c); c = getchar())
X cost = (cost * 10) + c - '0';
X ungetc(c, stdin);
X yylval.y_cost = cost;
X return COST;
X }
X
X if (getword(buf, c) == 0) {
X for (ct = ctable; ct->cname; ct++)
X if (STR_EQ(buf, ct->cname)) {
X yylval.y_cost = ct->cval;
X return COST;
X }
X sprintf(errbuf, "unknown cost (%s), using default", buf);
X yyerror(errbuf);
X yylval.y_cost = DEFCOST;
X return COST;
X }
X
X return c; /* pass the buck */
X
X case NEWLINE:
X Scanstate = OTHER;
X if (getword(buf, c) != 0)
X return c;
X /*
X * special purpose tokens.
X *
X * the "switch" serves the dual-purpose of recognizing
X * unquoted tokens only.
X */
X switch(c) {
X case 'p':
X if (STR_EQ(buf, "private"))
X return PRIVATE;
X break;
X case 'd':
X if (STR_EQ(buf, "dead"))
X return DEAD;
X if (STR_EQ(buf, "delete"))
X return DELETE;
X break;
X case 'f':
X if (STR_EQ(buf, "file"))
X return FILETOK;
X break;
X case 'a':
X if (STR_EQ(buf, "adjust"))
X return ADJUST;
X break;
X }
X
X yylval.y_name = buf;
X return HOST;
X
X case FILENAME:
X while (c != EOF && isprint(c)) {
X if (c == ' ' || c == '\t' || c == '\n' || c == '}')
X break;
X *buf++ = c;
X c = getchar();
X }
X if (c != EOF)
X ungetc(c, stdin);
X *buf = 0;
X yylval.y_name = retbuf;
X return STRING;
X }
X
X if (getword(buf, c) == 0) {
X yylval.y_name = buf;
X return SITE;
X }
X
X if (index(Netchars, c)) {
X yylval.y_net = c;
X return NET;
X }
X
X return c;
X}
X
X/*
X * fill str with the next word in [0-9A-Za-z][-._0-9A-Za-z]+ or a quoted
X * string that contains no newline. return -1 on failure or EOF, 0 o.w.
X */
XSTATIC int
Xgetword(str, c)
X register char *str;
X register int c;
X{
X if (c == QUOTE) {
X while ((c = getchar()) != QUOTE) {
X if (c == '\n') {
X yyerror("newline in quoted string\n");
X ungetc(c, stdin);
X return -1;
X }
X if (c == EOF) {
X yyerror("EOF in quoted string\n");
X return -1;
X }
X *str++ = c;
X }
X *str = 0;
X return 0;
X }
X
X /* host name must start with alphanumeric or `.' */
X if (!isalnum(c) && c != '.')
X return -1;
X
Xyymore:
X do {
X *str++ = c;
X c = getchar();
X } while (isalnum(c) || c == '.' || c == '_');
X
X if (c == '-' && Scanstate != COSTING)
X goto yymore;
X
X ungetc(c, stdin);
X *str = 0;
X return 0;
X}
X
XSTATIC int
Xyywrap()
X{ char errbuf[100];
X
X fixprivate(); /* munge private host definitions */
X Lineno = 1;
X while (optind < Argc) {
X if (freopen((Cfile = Argv[optind++]), "r", stdin) != 0)
X return 0;
X sprintf(errbuf, "%s: %s", Argv[0], Cfile);
X perror(errbuf);
X }
X freopen("/dev/null", "r", stdin);
X return -1;
X}
X
XSTATIC void
Xadjust(n, cost)
X node *n;
X Cost cost;
X{ link *l;
X
X n->n_cost += cost; /* cumulative */
X
X /* hit existing links */
X for (l = n->n_link; l; l = l->l_next) {
X if ((l->l_cost += cost) < 0) {
X char buf[100];
X
X l->l_flag |= LDEAD;
X sprintf(buf, "link to %s deleted with negative cost",
X l->l_to->n_name);
X yyerror(buf);
X }
X }
X}
END_OF_FILE
if test 10671 -ne `wc -c <'parse.y'`; then
echo shar: \"'parse.y'\" unpacked with wrong size!
fi
# end of 'parse.y'
fi
if test -f 'printit.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'printit.c'\"
else
echo shar: Extracting \"'printit.c'\" \(6907 characters\)
sed "s/^X//" >'printit.c' <<'END_OF_FILE'
X/* pathalias -- by steve bellovin, as told to peter honeyman */
X#ifndef lint
Xstatic char *sccsid = "@(#)printit.c 9.4 89/02/07";
X#endif
X
X#include "def.h"
X
X/*
X * print the routes by traversing the shortest path tree in preorder.
X * use lots of char bufs -- profiling indicates this costs about 5 kbytes
X */
X
X/* exports */
Xextern void printit();
X
X/* imports */
Xextern int Cflag, Vflag, Dflag, Fflag;
Xextern node *Home;
Xextern char *Netchars;
Xextern void die();
Xextern int strlen();
X
X/* privates */
Xstatic link *Ancestor; /* for -f option */
XSTATIC void preorder(), setpath(), printhost(), printdomain();
XSTATIC char *hostpath();
XSTATIC int printable();
X
X/* in practice, even the longest paths are < 100 bytes */
X#define PATHSIZE 512
X
Xvoid
Xprintit()
X{ link *l;
X char pbuf[PATHSIZE];
X
X /* print home */
X if (Cflag)
X printf("%ld\t", (long) Home->n_cost);
X printf("%s\t%%s\n", Home->n_name);
X
X strcpy(pbuf, "%s");
X for (l = Home->n_link; l; l = l->l_next) {
X if (l->l_flag & LTREE) {
X l->l_flag &= ~LTREE;
X Ancestor = l;
X preorder(l, pbuf);
X strcpy(pbuf, "%s");
X }
X }
X fflush(stdout);
X fflush(stderr);
X}
X
X/*
X * preorder traversal of shortest path tree.
X */
XSTATIC void
Xpreorder(l, ppath)
X register link *l;
X char *ppath;
X{ register node *n;
X node *ncp; /* circular copy list */
X Cost cost;
X char npath[PATHSIZE];
X short p_dir; /* DIR bits of parent (for nets) */
X char p_op; /* net op of parent (for nets) */
X
X setpath(l, ppath, npath);
X n = l->l_to;
X if (printable(n)) {
X if (Fflag)
X cost = Ancestor->l_to->n_cost;
X else
X cost = n->n_cost;
X if (ISADOMAIN(n))
X printdomain(n, npath, cost);
X else if (!(n->n_flag & NNET)) {
X printhost(n, npath, cost);
X }
X n->n_flag |= PRINTED;
X for (ncp = n->n_copy; ncp != n; ncp = ncp->n_copy)
X ncp->n_flag |= PRINTED;
X }
X
X /* prepare routing bits for domain members */
X p_dir = l->l_flag & LDIR;
X p_op = l->l_netop;
X
X /* recursion */
X for (l = n->n_link; l; l = l->l_next) {
X if (!(l->l_flag & LTREE))
X continue;
X /* network member inherits the routing syntax of its gateway */
X if (ISANET(n)) {
X l->l_flag = (l->l_flag & ~LDIR) | p_dir;
X l->l_netop = p_op;
X }
X l->l_flag &= ~LTREE;
X preorder(l, npath);
X }
X}
X
XSTATIC int
Xprintable(n)
X register node *n;
X{ node *ncp;
X link *l;
X
X if (n->n_flag & PRINTED)
X return 0;
X
X /* is there a cheaper copy? */
X for (ncp = n->n_copy; n != ncp; ncp = ncp->n_copy) {
X if (!(ncp->n_flag & MAPPED))
X continue; /* unmapped copy */
X
X if (n->n_cost > ncp->n_cost)
X return 0; /* cheaper copy */
X
X if (n->n_cost == ncp->n_cost && !(ncp->n_flag & NTERMINAL))
X return 0; /* synthetic copy */
X }
X
X /* will a domain route suffice? */
X if (Dflag && !ISANET(n) && ISADOMAIN(n->n_parent)) {
X /*
X * are there any interesting links? a link
X * is interesting if it doesn't point back
X * to the parent, and is not an alias.
X */
X
X /* check n */
X for (l = n->n_link; l; l = l->l_next) {
X if (l->l_to == n->n_parent)
X continue;
X if (!(l->l_flag & LALIAS))
X return 1;
X }
X
X /* check copies of n */
X for (ncp = n->n_copy; ncp != n; ncp = ncp->n_copy) {
X for (l = ncp->n_link; l; l = l->l_next) {
X if (l->l_to == n->n_parent)
X continue;
X if (!(l->l_flag & LALIAS))
X return 1;
X }
X }
X
X /* domain route suffices */
X return 0;
X }
X return 1;
X}
X
XSTATIC void
Xsetpath(l, ppath, npath)
X link *l;
X register char *ppath, *npath;
X{ register node *next, *parent;
X char netchar;
X
X next = l->l_to;
X parent = next->n_parent;
X netchar = NETCHAR(l);
X
X /* for magic @->% conversion */
X if (parent->n_flag & ATSIGN)
X next->n_flag |= ATSIGN;
X
X /*
X * i've noticed that distant gateways to domains frequently get
X * ...!gateway!user at dom.ain wrong. ...!gateway!user%dom.ain
X * seems to work, so if next is a domain and the parent is
X * not the local host, force a magic %->@ conversion. in this
X * context, "parent" is the nearest ancestor that is not a net.
X */
X while (ISANET(parent))
X parent = parent->n_parent;
X if (ISADOMAIN(next) && parent != Home)
X next->n_flag |= ATSIGN;
X
X /*
X * special handling for nets (including domains) and aliases.
X * part of the trick is to treat aliases to domains as 0 cost
X * links. (the author believes they should be declared as such
X * in the input, but the world disagrees).
X */
X if (ISANET(next) || ((l->l_flag & LALIAS) && !ISADOMAIN(parent))) {
X strcpy(npath, ppath);
X return;
X }
X
X if (netchar == '@')
X if (next->n_flag & ATSIGN)
X netchar = '%'; /* shazam? shaman? */
X else
X next->n_flag |= ATSIGN;
X
X /* remainder should be a sprintf -- foo on '%' as an operator */
X for ( ; (*npath = *ppath) != 0; ppath++) {
X if (*ppath == '%') {
X switch(ppath[1]) {
X case 's':
X ppath++;
X npath = hostpath(npath, l, netchar);
X break;
X
X case '%':
X *++npath = *++ppath;
X npath++;
X break;
X
X default:
X die("unknown escape in setpath");
X break;
X }
X } else
X npath++;
X }
X}
X
XSTATIC char *
Xhostpath(path, l, netchar)
X register char *path;
X register link *l;
X char netchar;
X{ register node *prev;
X
X prev = l->l_to->n_parent;
X if (NETDIR(l) == LLEFT) {
X /* host!%s */
X strcpy(path, l->l_to->n_name);
X path += strlen(path);
X while (ISADOMAIN(prev)) {
X strcpy(path, prev->n_name);
X path += strlen(path);
X prev = prev->n_parent;
X }
X *path++ = netchar;
X if (netchar == '%')
X *path++ = '%';
X *path++ = '%';
X *path++ = 's';
X } else {
X /* %s at host */
X *path++ = '%';
X *path++ = 's';
X *path++ = netchar;
X if (netchar == '%')
X *path++ = '%';
X strcpy(path, l->l_to->n_name);
X path += strlen(path);
X while (ISADOMAIN(prev)) {
X strcpy(path, prev->n_name);
X path += strlen(path);
X prev = prev->n_parent;
X }
X }
X return path;
X}
X
XSTATIC void
Xprinthost(n, path, cost)
X register node *n;
X char *path;
X Cost cost;
X{
X if (n->n_flag & PRINTED)
X die("printhost called twice");
X n->n_flag |= PRINTED;
X /* skip private hosts */
X if ((n->n_flag & ISPRIVATE) == 0) {
X if (Cflag)
X printf("%ld\t", (long) cost);
X fputs(n->n_name, stdout);
X putchar('\t');
X puts(path);
X }
X}
X
XSTATIC void
Xprintdomain(n, path, cost)
X register node *n;
X char *path;
X Cost cost;
X{ node *p;
X
X if (n->n_flag & PRINTED)
X die("printdomain called twice");
X n->n_flag |= PRINTED;
X
X /*
X * print a route for dom.ain if it is a top-level domain, unless
X * it is private.
X *
X * print a route for sub.dom.ain only if all its ancestor dom.ains
X * are private and sub.dom.ain is not private.
X */
X if (!ISADOMAIN(n->n_parent)) {
X /* top-level domain */
X if (n->n_flag & ISPRIVATE) {
X vprintf(stderr, "ignoring private top-level domain %s\n", n->n_name);
X return;
X }
X } else {
X /* subdomain */
X for (p = n->n_parent; ISADOMAIN(p); p = p->n_parent)
X if (!(p->n_flag & ISPRIVATE))
X return;
X if (n->n_flag & ISPRIVATE)
X return;
X }
X
X /* print it (at last!) */
X if (Cflag)
X printf("%ld\t", (long) cost);
X do {
X fputs(n->n_name, stdout);
X n = n->n_parent;
X } while (ISADOMAIN(n));
X putchar('\t');
X puts(path);
X}
END_OF_FILE
if test 6907 -ne `wc -c <'printit.c'`; then
echo shar: \"'printit.c'\" unpacked with wrong size!
fi
# end of 'printit.c'
fi
echo shar: End of archive 2 \(of 3\).
cp /dev/null ark2isdone
MISSING=""
for I in 1 2 3 ; do
if test ! -f ark${I}isdone ; then
MISSING="${MISSING} ${I}"
fi
done
if test "${MISSING}" = "" ; then
echo You have unpacked all 3 archives.
rm -f ark[1-9]isdone
else
echo You still must unpack the following archives:
echo " " ${MISSING}
fi
exit 0
exit 0 # Just in case...
--
Please send comp.sources.unix-related mail to rsalz at uunet.uu.net.
Use a domain-based address or give alternate paths, or you may lose out.
More information about the Comp.sources.unix
mailing list