DataMuseum.dk

Presents historical artifacts from the history of:

DKUUG/EUUG Conference tapes

This is an automatic "excavation" of a thematic subset of
artifacts from Datamuseum.dk's BitArchive.

See our Wiki for more about DKUUG/EUUG Conference tapes

Excavated with: AutoArchaeologist - Free & Open Source Software.


top - download
Index: ┃ T p

⟦045d8a31a⟧ TextFile

    Length: 5860 (0x16e4)
    Types: TextFile
    Names: »printit.c«

Derivation

└─⟦a0efdde77⟧ Bits:30001252 EUUGD11 Tape, 1987 Spring Conference Helsinki
    └─ ⟦this⟧ »EUUGD11/euug-87hel/sec8/pathalias/printit.c« 

TextFile

/* 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);
}