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