|
|
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 a
Length: 12969 (0x32a9)
Types: TextFile
Names: »arpatxt.c«
└─⟦9ae75bfbd⟧ Bits:30007242 EUUGD3: Starter Kit
└─⟦2fafebccf⟧ »EurOpenD3/mail/smail3.1.19.tar.Z«
└─⟦bcd2bc73f⟧
└─⟦this⟧ »pd/pathalias/arpatxt.c«
#ifndef lint
static char *sccsid = "@(#)arpatxt.c 9.1 87/10/04";
#endif
/*
* convert hosts.txt into pathalias format.
*
* alias rule: "host.dom.ain,nickname.arpa,..." -> host = nickname, ...
*/
#define IS_ARPATXT
#include <ctype.h>
#include "config.h"
#include <stdio.h>
typedef struct node node;
struct node {
node *child; /* subdomain or member host */
node *parent; /* parent domain */
node *next; /* sibling in domain tree or host list */
char *name;
node *alias;
node *bucket;
node *gateway;
int flag;
};
node *Top;
int Atflag;
int Fflag, Iflag;
char *DotArpa = ".ARPA";
char Fname[256], *Fstart;
node *newnode(), *find();
char *strsave(), *lowercase();
void crcinit();
long fold();
FILE *mkfile();
extern char *malloc(), *index(), *calloc(), *gets(), *strcpy(), *fgets();
extern FILE *fopen();
#define ISADOMAIN(n) ((n) && *((n)->name) == '.')
/* for node.flag */
#define COLLISION 1
/* for formatprint() */
#define PRIVATE 0
#define HOSTS 1
#define SUBDOMAINS 2
/* for usage() */
#define USAGE "usage: %s [-i@] [-g gateway] [-p privatefile] [-f | -d directory] [file ...]\n"
main(argc, argv)
char **argv;
{ int c;
char *progname;
extern char *optarg;
extern int optind;
if ((progname = index(argv[0], '/')) != 0)
progname++;
else
progname = argv[0];
crcinit();
Top = newnode(); /* needed for adding gateways */
while ((c = getopt(argc, argv, "d:fg:ip:@")) != EOF)
switch(c) {
case 'd':
strcpy(Fname, optarg);
break;
case 'f': /* filter mode -- write on stdout */
Fflag++;
break;
case 'g':
gateway(optarg);
break;
case 'i':
Iflag++;
break;
case 'p':
readprivates(optarg);
break;
case '@':
Atflag++;
break;
default:
usage(progname);
}
if (Fflag && *Fname)
usage(progname);
if (Iflag)
(void) lowercase(DotArpa);
if (Top->gateway == 0)
fprintf(stderr, "%s: warning: no gateway to top level domains\n", progname);
Fstart = Fname + strlen(Fname);
if (Fstart != Fname) {
*Fstart++ = '/';
*Fstart = 0;
}
/* should do the mkdir here instead of the shell script ...*/
Top->name = "internet";
if (optind == argc)
scan();
else for ( ; optind < argc; optind++) {
if (freopen(argv[optind], "r", stdin) == 0) {
perror(argv[optind]);
continue;
}
scan();
}
merge();
dump(Top);
return 0;
}
scan()
{ static first;
char buf0[BUFSIZ], buf1[BUFSIZ], buf2[BUFSIZ];
#ifdef SYSV_REGCMP
char *re; /* regular expression */
char *regcmp(); /* compile a regular expression */
char *regex(); /* returns 0 if pattern doesn't match */
if (first++ == 0)
re = regcmp("^HOST.*SMTP", 0);
if (re == 0) {
abort();
}
while (gets(buf0) != 0) {
if (regex(re, buf0) == 0)
continue;
if (sscanf(buf0, "HOST : %[^:] : %[^: ]", buf1, buf2) != 2)
continue;
if (Iflag)
(void) lowercase(buf2);
insert(buf2);
}
#else /* SYSV_REGCMP */
if (first++ == 0)
(void) re_comp("^HOST.*SMTP");
while (gets(buf0) != 0) {
if (re_exec(buf0) == 0)
continue;
if (sscanf(buf0, "HOST : %[^:] : %[^: ]", buf1, buf2) != 2)
continue;
if (Iflag)
(void) lowercase(buf2);
insert(buf2);
}
#endif /* SYSV_REGCMP */
}
/*
* format of private file:
* one per line, optionally followed by white space and comments
* line starting with # is comment
*/
readprivates(pfile)
char *pfile;
{ FILE *f;
node *n;
char buf[BUFSIZ], *bptr;
if ((f = fopen(pfile, "r")) == 0) {
perror(pfile);
return;
}
while (fgets(buf, BUFSIZ, f) != 0) {
if (*buf == '#')
continue;
if ((bptr = index(buf, ' ')) != 0)
*bptr = 0;
if ((bptr = index(buf, '\t')) != 0)
*bptr = 0;
if (*buf == 0)
continue;
n = newnode();
n->name = strsave(buf);
hash(n);
}
(void) fclose(f);
}
usage(progname)
char *progname;
{
fprintf(stderr, USAGE, progname);
exit(1);
}
dumpgateways(ndom, f)
node *ndom;
FILE *f;
{ node *n;
for (n = ndom->gateway; n; n = n->next) {
fprintf(f, "%s ", n->name);
if (Atflag)
putc('@', f);
fprintf(f, "%s(%s)\t# gateway\n", ndom->name,
ndom == Top ? "DEDICATED" : "LOCAL");
}
}
gateway(buf)
char *buf;
{ node *n, *dom;
char *dot;
dot = index(buf, '.');
if (dot) {
dom = find(dot);
*dot = 0;
} else
dom = Top;
n = newnode();
n->name = strsave(buf);
n->next = dom->gateway;
dom->gateway = n;
}
insert(buf)
char *buf;
{ char host[BUFSIZ], *hptr, *dot;
node *n;
for (hptr = host; *hptr = *buf++; hptr++)
if (*hptr == ',')
break;
if (*hptr == ',')
*hptr = 0;
else
buf = 0; /* no aliases */
if ((dot = index(host, '.')) == 0)
abort(); /* can't happen */
if (strcmp(dot, DotArpa) == 0)
buf = 0; /* no aliases */
n = find(dot);
*dot = 0;
addchild(n, host, buf);
}
node *
find(domain)
char *domain;
{ char *dot;
node *parent, *child;
if (domain == 0)
return Top;
if ((dot = index(domain+1, '.')) != 0) {
parent = find(dot);
*dot = 0;
} else
parent = Top;
for (child = parent->child; child; child = child->next)
if (strcmp(domain, child->name) == 0)
break;
if (child == 0) {
child = newnode();
child->next = parent->child;
parent->child = child;
child->parent = parent;
child->name = strsave(domain);
}
return child;
}
node *
newnode()
{
node *n;
if ((n = (node *) calloc(1, sizeof(node))) == 0)
abort();
return n;
}
char *
strsave(buf)
char *buf;
{ char *mstr;
if ((mstr = malloc(strlen(buf)+1)) == 0)
abort();
strcpy(mstr, buf);
return mstr;
}
addchild(n, host, aliases)
node *n;
char *host, *aliases;
{ node *child;
/* check for dups? nah! */
child = newnode();
child->name = strsave(host);
child->parent = n;
child->next = n->child;
makealiases(child, aliases);
n->child = child;
}
/* yer basic tree walk */
dump(n)
node *n;
{ node *child;
FILE *f;
int hadprivates = 0;
if (n->child == 0)
return;
f = mkfile(n);
if (n != Top && ! ISADOMAIN(n))
abort();
hadprivates = domprint(n, f);
dumpgateways(n, f);
if (hadprivates || n == Top)
fputs("private {}\n", f); /* end scope of privates */
if (!Fflag)
(void) fclose(f);
else
putc('\n', f);
for (child = n->child; child; child = child->next)
dump(child);
}
qcmp(a, b)
node **a, **b;
{
return strcmp((*a)->name, (*b)->name);
}
domprint(n, f)
node *n;
FILE *f;
{ node **table, *child, *alias;
char *cost = 0;
int nelem, i, rval = 0;
/*
* some systems can't hack a large stack, so malloc table
*
* was node *table[10240];
*/
table = (node **)malloc(10240*sizeof(node));
if (table == NULL) {
fprintf(stderr, "malloc failed in domprint\n");
abort();
}
/* dump private definitions */
/* sort hosts and aliases in table */
i = 0;
for (child = n->child; child; child = child->next) {
table[i++] = child;
for (alias = child->alias; alias; alias = alias->next)
table[i++] = alias;
}
qsort((char *) table, i, sizeof(table[0]), qcmp);
formatprint(f, table, i, PRIVATE, "private", cost);
/* rval == 0 IFF no privates */
while (i-- > 0)
if (table[i]->flag & COLLISION) {
rval = 1;
break;
}
/* dump domains and aliases */
/* sort hosts (only) in table */
i = 0;
for (child = n->child; child; child = child->next)
table[i++] = child;
qsort((char *) table, i, sizeof(table[0]), qcmp);
/* cost is DEDICATED for hosts in top-level domains, LOCAL o.w. */
if (n->parent == Top && index(n->name + 1, '.') == 0)
cost = "DEDICATED";
else
cost = "LOCAL";
formatprint(f, table, i, HOSTS, n->name, cost);
formatprint(f, table, i, SUBDOMAINS, n->name, "0");
/* dump aliases */
nelem = i;
for (i = 0; i < nelem; i++) {
if ((alias = table[i]->alias) == 0)
continue;
fprintf(f, "%s = %s", table[i]->name, alias->name);
for (alias = alias->next; alias; alias = alias->next)
fprintf(f, ", %s", alias->name);
putc('\n', f);
}
free(table);
return rval;
}
/* for debugging */
dtable(comment, table, nelem)
char *comment;
node **table;
{ int i;
fprintf(stderr, "\n%s\n", comment);
for (i = 0; i < nelem; i++)
fprintf(stderr, "%3d\t%s\n", i, table[i]->name);
}
formatprint(f, table, nelem, type, lhs, cost)
FILE *f;
node **table;
char *lhs, *cost;
{ int i, didprint;
char buf[128], *bptr;
sprintf(buf, "%s%s{" /*}*/, lhs, type == PRIVATE ? " " : " = ");
bptr = buf + strlen(buf);
didprint = 0;
for (i = 0; i < nelem; i++) {
if (type == PRIVATE && ! (table[i]->flag & COLLISION))
continue;
else if (type == HOSTS && ISADOMAIN(table[i]) )
continue;
else if (type == SUBDOMAINS && ! ISADOMAIN(table[i]) )
continue;
if ((bptr - buf) + strlen(table[i]->name) > 69) {
*bptr = 0;
fprintf(f, "%s\n ", buf); /* continuation */
bptr = buf;
}
sprintf(bptr, "%s, ", table[i]->name);
bptr += strlen(bptr);
didprint++;
}
*bptr = 0;
if ( ! didprint )
return;
fprintf(f, /*{*/ "%s}", buf);
if (type != PRIVATE)
fprintf(f, "(%s)", cost);
putc('\n', f);
}
FILE *
mkfile(n)
node *n;
{ node *parent;
char *bptr;
FILE *f;
/* build up the domain name in Fname[] */
bptr = Fstart;
if (n == Top)
strcpy(bptr, n->name);
else {
strcpy(bptr, n->name + 1); /* skip leading dot */
bptr = bptr + strlen(bptr);
parent = n->parent;
while (ISADOMAIN(parent)) {
strcpy(bptr, parent->name);
bptr += strlen(bptr);
parent = parent->parent;
}
*bptr = 0;
}
/* get a stream descriptor */
if (Fflag) {
printf("# %s\n", Fstart);
f = stdout;
} else {
#ifndef BSD
Fstart[14] = 0;
#endif
if ((f = fopen(Fname, "w")) == 0) {
perror(Fname);
exit(1);
}
}
if (n == Top)
fprintf(f, "private {%s}\ndead {%s}\n", Top->name, Top->name);
return f;
}
/* map to lower case in place. return parameter for convenience */
char *
lowercase(buf)
char *buf;
{ char *str;
for (str = buf ; *str; str++)
if (isupper(*str))
*str -= 'A' - 'a';
return buf;
}
/* get the interesting aliases, attach to n->alias */
makealiases(n, line)
node *n;
char *line;
{ char *next, *dot;
node *a;
if (line == 0 || *line == 0)
return;
for ( ; line; line = next) {
next = index(line, ',');
if (next)
*next++ = 0;
if ((dot = index(line, '.')) == 0)
continue;
if (strcmp(dot, DotArpa) != 0)
continue;
*dot = 0;
if (strcmp(n->name, line) == 0)
continue;
a = newnode();
a->name = strsave(line);
a->next = n->alias;
n->alias = a;
}
}
#define NHASH 13309
node *htable[NHASH];
merge()
{ node *n;
setuniqflag(Top);
for (n = Top->child; n; n = n->next) {
if (n->flag & COLLISION) {
fprintf(stderr, "illegal subdomain: %s\n", n->name);
abort();
}
promote(n);
}
}
/*
* for domains like cc.umich.edu and cc.berkeley.edu, it's inaccurate
* to describe cc as a member of umich.edu or berkeley.edu. (i.e., the
* lousy scoping rules for privates don't permit a clean syntax.) so.
*
* to prevent confusion, tack on to any such domain name its parent domain
* and promote it in the tree. e.g., make cc.umich and cc.berkeley
* subdomains of edu.
*/
promote(parent)
node *parent;
{ node *prev, *child, *next;
char buf[BUFSIZ];
prev = 0;
for (child = parent->child; child; child = next) {
next = child->next;
if (!ISADOMAIN(child)) {
prev = child;
continue;
}
if ((child->flag & COLLISION) || child->gateway) {
/*
* dup domain name or gateway found. don't bump
* prev: this node is moving up the tree.
*/
/* qualify child domain name */
sprintf(buf, "%s%s", child->name, parent->name);
cfree(child->name);
child->name = strsave(buf);
/* unlink child out of sibling chain */
if (prev)
prev->next = child->next;
else
parent->child = child->next;
/* link child in as peer of parent */
child->next = parent->next;
parent->next = child;
child->parent = parent->parent;
/*
* reset collision flag; may promote again on
* return to caller.
*/
child->flag &= ~COLLISION;
hash(child);
} else {
/* this domain is uninteresting (so bump prev) */
promote(child);
prev = child;
}
}
}
setuniqflag(n)
node *n;
{ node *child, *alias;
/* mark this node in the hash table */
hash(n);
/* mark the aliases of this node */
for (alias = n->alias; alias; alias = alias->next)
hash(alias);
/* recursively mark this node's children */
for (child = n->child; child; child = child->next)
setuniqflag(child);
}
hash(n)
node *n;
{ node **bucket, *b;
bucket = &htable[fold(n->name) % NHASH];
for (b = *bucket; b; b = b->bucket) {
if (strcmp(n->name, b->name) == 0) {
b->flag |= COLLISION;
n->flag |= COLLISION;
return;
}
}
n->bucket = *bucket;
*bucket = n;
}
/* stolen from pathalias:addnode.c, q.v. */
#define POLY 0x48000000 /* 31-bit polynomial */
long CrcTable[128];
void
crcinit()
{ register int i,j;
register long sum;
for (i = 0; i < 128; i++) {
sum = 0;
for (j = 7-1; j >= 0; --j)
if (i & (1 << j))
sum ^= POLY >> j;
CrcTable[i] = sum;
}
}
long
fold(s)
register char *s;
{ register long sum = 0;
register int c;
while (c = *s++)
sum = (sum >> 7) ^ CrcTable[(sum ^ c) & 0x7f];
return sum;
}