|
|
DataMuseum.dkPresents historical artifacts from the history of: DKUUG/EUUG Conference tapes |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about DKUUG/EUUG Conference tapes Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - downloadIndex: T p
Length: 5860 (0x16e4)
Types: TextFile
Names: »printit.c«
└─⟦a0efdde77⟧ Bits:30001252 EUUGD11 Tape, 1987 Spring Conference Helsinki
└─⟦this⟧ »EUUGD11/euug-87hel/sec8/pathalias/printit.c«
/* pathalias -- by steve bellovin, as told to peter honeyman */
#ifndef lint
static char *sccsid = "@(#)printit.c 8.7 (down!honey) 86/09/19";
#endif
#include "def.h"
/*
* print the routes by traversing the shortest path tree in preorder.
* use lots of char bufs -- profiling indicates this costs about 5 kbytes
*/
/* exports */
extern void printit();
/* imports */
extern int Cflag, Dflag, Vflag;
extern node *Home;
extern char *Netchars;
extern void die();
/* privates */
static int Phase;
STATIC void preorder(), setpath(), printhost(), printdomain();
STATIC char *hostpath();
/* in practice, even the longest paths are < 100 bytes */
#define PATHSIZE 512
void
printit(phase)
{ link *l;
char pbuf[PATHSIZE];
Phase = phase;
if (Dflag || Phase == NODOMAINS) {
/* print home */
if (Cflag)
printf("%ld\t", (long) Home->n_cost);
printf("%s\t%%s\n", Home->n_name);
}
strcpy(pbuf, "%s");
for (l = Home->n_link; l; l = l->l_next) {
if (l->l_flag & LTREE) {
preorder(l, pbuf, 0);
l->l_flag &= ~LTREE;
strcpy(pbuf, "%s");
}
}
fflush(stdout);
fflush(stderr);
}
/*
* preorder traversal of shortest path tree.
*/
STATIC void
preorder(l, ppath, domparent)
register link *l;
char *ppath;
int domparent; /* parent is a domain or domain member */
{ register node *n;
char npath[PATHSIZE];
int print, ldirbits;
short savelflag;
setpath(l, ppath, npath);
n = l->l_to;
if (!Dflag && Phase == DOMAINS) {
/*
* print if
* n is a domain
* parent is a domain
* parent is a domain member and n is its alias
*/
if (ISADOMAIN(n))
print = 1;
else if (domparent)
print = (ISADOMAIN(n->n_parent) || l->l_flag & LALIAS);
else
print = 0;
} else
print = !(n->n_flag & PRINTED);
if (print) {
if (ISADOMAIN(n))
printdomain(n, npath, n->n_cost);
else if (!(n->n_flag & NNET)) {
printhost(n, npath, n->n_cost);
}
}
/* prepare routing bits for domain members */
ldirbits = (l->l_flag & (LNETCHARS|LDIR));
for (l = n->n_link; l; l = l->l_next) {
if (l->l_flag & LTREE) {
/*
* domain members inherit the routing syntax
* of the domain gateway
*/
savelflag = l->l_flag;
if (ISANET(n)) {
l->l_flag &= ~(LNETCHARS|LDIR);
l->l_flag |= ldirbits;
}
preorder(l, npath, print);
l->l_flag = savelflag & ~LTREE;
}
}
}
STATIC void
setpath(l, ppath, npath)
link *l;
register char *ppath, *npath;
{
register node *next, *parent;
char netchar;
next = l->l_to;
parent = next->n_parent;
netchar = NETCHAR(l);
/* for magic @->% conversion */
if (parent->n_flag & ATSIGN)
next->n_flag |= ATSIGN;
/*
* i've noticed that distant gateways to domains frequently get
* ...!gateway!user@dom.ain wrong. ...!gateway!user%dom.ain
* seems to work, so if next is a domain and the parent is
* not the local host, force a magic %->@ conversion.
*/
if (ISADOMAIN(next) && parent != Home)
next->n_flag |= ATSIGN;
/*
* special handling for nets (including domains) and aliases.
* part of the trick is to treat aliases to domains as 0 cost
* links. (the author believes they should be declared as such
* in the input, but the world disagrees).
*/
if (ISANET(next) || ((l->l_flag & LALIAS) && !ISADOMAIN(parent))) {
strcpy(npath, ppath);
return;
}
if (netchar == '@')
if (next->n_flag & ATSIGN)
netchar = '%'; /* shazam? shaman? */
else
next->n_flag |= ATSIGN;
/* remainder should be a sprintf -- foo on '%' as an operator */
for ( ; *npath = *ppath; ppath++) {
if (*ppath == '%') {
switch(ppath[1]) {
case 's':
ppath++;
npath = hostpath(npath, l, netchar);
break;
case '%':
*++npath = *++ppath;
npath++;
break;
default:
die("unknown escape in setpath");
break;
}
} else
npath++;
}
}
STATIC char *
hostpath(path, l, netchar)
register char *path;
register link *l;
char netchar;
{ register node *prev;
prev = l->l_to->n_parent;
if (NETDIR(l) == LLEFT) {
/* host!user */
strcpy(path, l->l_to->n_name);
path += strlen(path);
while (ISADOMAIN(prev)) {
strcpy(path, prev->n_name);
path += strlen(path);
prev = prev->n_parent;
}
*path++ = netchar;
if (netchar == '%')
*path++ = '%';
*path++ = '%';
*path++ = 's';
} else {
/* %s@host */
*path++ = '%';
*path++ = 's';
*path++ = netchar;
if (netchar == '%')
*path++ = '%';
strcpy(path, l->l_to->n_name);
path += strlen(path);
while (ISADOMAIN(prev)) {
strcpy(path, prev->n_name);
path += strlen(path);
prev = prev->n_parent;
}
}
return(path);
}
STATIC void
printhost(n, path, cost)
register node *n;
char *path;
Cost cost;
{
if (n->n_flag & PRINTED)
die("printhost called twice");
n->n_flag |= PRINTED;
/* skip private hosts */
if ((n->n_flag & ISPRIVATE) == 0) {
if (Cflag)
printf("%ld\t", (long) cost);
fputs(n->n_name, stdout);
putchar('\t');
puts(path);
}
}
STATIC void
printdomain(n, path, cost)
register node *n;
char *path;
Cost cost;
{ node *p;
if (n->n_flag & PRINTED)
die("printdomain called twice");
n->n_flag |= PRINTED;
/*
* don't print private top-level domains or subdomains
* of a nonprivate domain ancestor. i can't believe either
* of these would ever really happen.
*/
if (!ISADOMAIN(n->n_parent)) { /* top-level domain */
if (n->n_flag & ISPRIVATE) {
vprintf(stderr, "ignoring private top-level domain %s\n", n->n_name);
return;
}
} else { /* subdomain */
/* ignore private subdomain */
if (n->n_flag & ISPRIVATE)
return;
/* ignore subdomain of non-private domain ancestor */
for (p = n->n_parent; ISADOMAIN(p); p = p->n_parent)
if (!(p->n_flag & ISPRIVATE))
return;
}
/* print it (at last!) */
if (Cflag)
printf("%ld\t", (long) cost);
do {
fputs(n->n_name, stdout);
n = n->n_parent;
} while (ISADOMAIN(n));
putchar('\t');
puts(path);
}