1: #ifndef lint
   2: static char *sccsid = "@(#)arpatxt.c	9.1 87/10/04";
   3: #endif
   4: 
   5: /*
   6:  * convert hosts.txt into pathalias format.
   7:  *
   8:  * alias rule: "host.dom.ain,nickname.arpa,..." -> host = nickname, ...
   9:  */
  10: 
  11: /* remove the next line for standard or research unix */
  12: #define BSD
  13: 
  14: #ifdef BSD
  15: #define strchr index
  16: #endif /* BSD */
  17: 
  18: #include <stdio.h>
  19: #include <ctype.h>
  20: 
  21: typedef struct node node;
  22: 
  23: struct node {
  24:     node *child;    /* subdomain or member host */
  25:     node *parent;   /* parent domain */
  26:     node *next; /* sibling in domain tree or host list */
  27:     char *name;
  28:     node *alias;
  29:     node *bucket;
  30:     node *gateway;
  31:     int  flag;
  32: };
  33: 
  34: node *Top;
  35: int Atflag;
  36: int Fflag, Iflag;
  37: char *DotArpa = ".ARPA";
  38: char Fname[256], *Fstart;
  39: 
  40: node *newnode(), *find();
  41: char *strsave(), *lowercase();
  42: void crcinit();
  43: long fold();
  44: FILE *mkfile();
  45: 
  46: extern char *malloc(), *strchr(), *calloc(), *gets(), *strcpy(), *fgets();
  47: extern FILE *fopen();
  48: 
  49: #define ISADOMAIN(n) ((n) && *((n)->name) == '.')
  50: 
  51: /* for node.flag */
  52: #define COLLISION 1
  53: 
  54: /* for formatprint() */
  55: #define PRIVATE     0
  56: #define HOSTS       1
  57: #define SUBDOMAINS  2
  58: 
  59: /* for usage() */
  60: #define USAGE "usage: %s [-i@] [-g gateway] [-p privatefile] [-f | -d directory] [file ...]\n"
  61: 
  62: main(argc, argv)
  63:     char **argv;
  64: {   int c;
  65:     char *progname;
  66:     extern char *optarg;
  67:     extern int optind;
  68: 
  69:     if ((progname = strchr(argv[0], '/')) != 0)
  70:         progname++;
  71:     else
  72:         progname = argv[0];
  73:     crcinit();
  74: 
  75:     Top = newnode();    /* needed for adding gateways */
  76:     while ((c = getopt(argc, argv, "d:fg:ip:@")) != EOF)
  77:         switch(c) {
  78:         case 'd':
  79:             strcpy(Fname, optarg);
  80:             break;
  81:         case 'f':   /* filter mode -- write on stdout */
  82:             Fflag++;
  83:             break;
  84:         case 'g':
  85:             gateway(optarg);
  86:             break;
  87:         case 'i':
  88:             Iflag++;
  89:             break;
  90:         case 'p':
  91:             readprivates(optarg);
  92:             break;
  93:         case '@':
  94:             Atflag++;
  95:             break;
  96:         default:
  97:             usage(progname);
  98:         }
  99: 
 100:     if (Fflag && *Fname)
 101:         usage(progname);
 102:     if (Iflag)
 103:         (void) lowercase(DotArpa);
 104:     if (Top->gateway == 0)
 105:         fprintf(stderr, "%s: warning: no gateway to top level domains\n", progname);
 106: 
 107:     Fstart = Fname + strlen(Fname);
 108:     if (Fstart != Fname) {
 109:         *Fstart++ = '/';
 110:         *Fstart = 0;
 111:     }
 112:     /* should do the mkdir here instead of the shell script ...*/
 113: 
 114:     Top->name = "internet";
 115:     if (optind == argc)
 116:         scan();
 117:     else for ( ; optind < argc; optind++) {
 118:         if (freopen(argv[optind], "r", stdin) == 0) {
 119:             perror(argv[optind]);
 120:             continue;
 121:         }
 122:         scan();
 123:     }
 124:     merge();
 125:     dump(Top);
 126:     return 0;
 127: }
 128: 
 129: scan()
 130: {   static first;
 131:     char buf0[BUFSIZ], buf1[BUFSIZ], buf2[BUFSIZ];
 132: 
 133:     if (first++ == 0)
 134:         (void) re_comp("^HOST.*SMTP");
 135:     while (gets(buf0) != 0) {
 136:         if (re_exec(buf0) == 0)
 137:             continue;
 138:         if (sscanf(buf0, "HOST : %[^:] : %[^: ]", buf1, buf2) != 2)
 139:             continue;
 140:         if (Iflag)
 141:             (void) lowercase(buf2);
 142:         insert(buf2);
 143:     }
 144: }
 145: /*
 146:  * format of private file:
 147:  *	one per line, optionally followed by white space and comments
 148:  *	line starting with # is comment
 149:  */
 150: readprivates(pfile)
 151:     char *pfile;
 152: {   FILE *f;
 153:     node *n;
 154:     char buf[BUFSIZ], *bptr;
 155: 
 156:     if ((f = fopen(pfile, "r")) == 0) {
 157:         perror(pfile);
 158:         return;
 159:     }
 160:     while (fgets(buf, BUFSIZ, f) != 0) {
 161:         if (*buf == '#')
 162:             continue;
 163:         if ((bptr = strchr(buf, ' ')) != 0)
 164:             *bptr = 0;
 165:         if ((bptr = strchr(buf, '\t')) != 0)
 166:             *bptr = 0;
 167:         if (*buf == 0)
 168:             continue;
 169:         n = newnode();
 170:         n->name = strsave(buf);
 171:         hash(n);
 172:     }
 173:     (void) fclose(f);
 174: }
 175: usage(progname)
 176:     char *progname;
 177: {
 178:     fprintf(stderr, USAGE, progname);
 179:     exit(1);
 180: }
 181: dumpgateways(ndom, f)
 182:     node *ndom;
 183:     FILE *f;
 184: {   node *n;
 185: 
 186:     for (n = ndom->gateway; n; n = n->next) {
 187:         fprintf(f, "%s ", n->name);
 188:         if (Atflag)
 189:             putc('@', f);
 190:         fprintf(f, "%s(%s)\t# gateway\n", ndom->name,
 191:                 ndom == Top ? "DEDICATED" : "LOCAL");
 192:     }
 193: }
 194: 
 195: gateway(buf)
 196:     char *buf;
 197: {   node *n, *dom;
 198:     char *dot;
 199: 
 200:     dot = strchr(buf, '.');
 201:     if (dot) {
 202:         dom = find(dot);
 203:         *dot = 0;
 204:     } else
 205:         dom = Top;
 206: 
 207:     n = newnode();
 208:     n->name = strsave(buf);
 209:     n->next = dom->gateway;
 210:     dom->gateway = n;
 211: }
 212: 
 213: insert(buf)
 214:     char *buf;
 215: {   char host[BUFSIZ], *hptr, *dot;
 216:     node *n;
 217: 
 218:     for (hptr = host; *hptr = *buf++; hptr++)
 219:         if (*hptr == ',')
 220:             break;
 221: 
 222:     if (*hptr == ',')
 223:         *hptr = 0;
 224:     else
 225:         buf = 0;    /* no aliases */
 226: 
 227:     if ((dot = strchr(host, '.')) == 0)
 228:         abort();    /* can't happen */
 229: 
 230:     if (strcmp(dot, DotArpa) == 0)
 231:         buf = 0;        /* no aliases */
 232: 
 233:     n = find(dot);
 234:     *dot = 0;
 235: 
 236:     addchild(n, host, buf);
 237: }
 238: 
 239: node *
 240: find(domain)
 241:     char *domain;
 242: {   char *dot;
 243:     node *parent, *child;
 244: 
 245:     if (domain == 0)
 246:         return Top;
 247:     if ((dot = strchr(domain+1, '.')) != 0) {
 248:         parent = find(dot);
 249:         *dot = 0;
 250:     } else
 251:         parent = Top;
 252: 
 253:     for (child = parent->child; child; child = child->next)
 254:         if (strcmp(domain, child->name) == 0)
 255:             break;
 256:     if (child == 0) {
 257:         child = newnode();
 258:         child->next = parent->child;
 259:         parent->child = child;
 260:         child->parent = parent;
 261:         child->name = strsave(domain);
 262:     }
 263:     return child;
 264: }
 265: 
 266: node *
 267: newnode()
 268: {
 269:     node *n;
 270: 
 271:     if ((n = (node *) calloc(1, sizeof(node))) == 0)
 272:         abort();
 273:     return n;
 274: }
 275: 
 276: char *
 277: strsave(buf)
 278:     char *buf;
 279: {   char *mstr;
 280: 
 281:     if ((mstr = malloc(strlen(buf)+1)) == 0)
 282:         abort();
 283:     strcpy(mstr, buf);
 284:     return mstr;
 285: }
 286: 
 287: addchild(n, host, aliases)
 288:     node *n;
 289:     char *host, *aliases;
 290: {   node *child;
 291: 
 292:     /* check for dups?  nah! */
 293:     child = newnode();
 294:     child->name = strsave(host);
 295:     child->parent = n;
 296:     child->next = n->child;
 297:     makealiases(child, aliases);
 298:     n->child = child;
 299: }
 300: 
 301: /* yer basic tree walk */
 302: dump(n)
 303:     node *n;
 304: {   node *child;
 305:     FILE *f;
 306:     int hadprivates = 0;
 307: 
 308:     if (n->child == 0)
 309:         return;
 310: 
 311:     f = mkfile(n);
 312: 
 313:     if (n != Top && ! ISADOMAIN(n))
 314:         abort();
 315: 
 316:     hadprivates = domprint(n, f);
 317:     dumpgateways(n, f);
 318:     if (hadprivates || n == Top)
 319:         fputs("private {}\n", f);   /* end scope of privates */
 320:     if (!Fflag)
 321:         (void) fclose(f);
 322:     else
 323:         putc('\n', f);
 324:     for (child = n->child; child; child = child->next)
 325:         dump(child);
 326: }
 327: 
 328: qcmp(a, b)
 329:     node **a, **b;
 330: {
 331:     return strcmp((*a)->name, (*b)->name);
 332: }
 333: 
 334: domprint(n, f)
 335:     node *n;
 336:     FILE *f;
 337: {   node *table[10240], *child, *alias;
 338:     char *cost = 0;
 339:     int nelem, i, rval = 0;
 340: 
 341:     /* dump private definitions */
 342:     /* sort hosts and aliases in table */
 343:     i = 0;
 344:     for (child = n->child; child; child = child->next) {
 345:         table[i++] = child;
 346:         for (alias = child->alias; alias; alias = alias->next)
 347:             table[i++] = alias;
 348:     }
 349: 
 350:     qsort((char *) table, i, sizeof(table[0]), qcmp);
 351:     formatprint(f, table, i, PRIVATE, "private", cost);
 352: 
 353:     /* rval == 0 IFF no privates */
 354:     while (i-- > 0)
 355:         if (table[i]->flag & COLLISION) {
 356:             rval = 1;
 357:             break;
 358:         }
 359: 
 360:     /* dump domains and aliases */
 361:     /* sort hosts (only) in table */
 362:     i = 0;
 363:     for (child = n->child; child; child = child->next)
 364:         table[i++] = child;
 365:     qsort((char *) table, i, sizeof(table[0]), qcmp);
 366: 
 367:     /* cost is DEDICATED for hosts in top-level domains, LOCAL o.w. */
 368:     if (n->parent == Top && strchr(n->name + 1, '.') == 0)
 369:         cost = "DEDICATED";
 370:     else
 371:         cost = "LOCAL";
 372:     formatprint(f, table, i, HOSTS, n->name, cost);
 373: 
 374:     formatprint(f, table, i, SUBDOMAINS, n->name, "0");
 375: 
 376:     /* dump aliases */
 377:     nelem = i;
 378:     for (i = 0; i < nelem; i++) {
 379:         if ((alias = table[i]->alias) == 0)
 380:             continue;
 381:         fprintf(f, "%s = %s", table[i]->name, alias->name);
 382:         for (alias = alias->next; alias; alias = alias->next)
 383:             fprintf(f, ", %s", alias->name);
 384:         putc('\n', f);
 385:     }
 386: 
 387:     return rval;
 388: }
 389: 
 390: /* for debugging */
 391: dtable(comment, table, nelem)
 392:     char *comment;
 393:     node **table;
 394: {   int i;
 395: 
 396:     fprintf(stderr, "\n%s\n", comment);
 397:     for (i = 0; i < nelem; i++)
 398:         fprintf(stderr, "%3d\t%s\n", i, table[i]->name);
 399: }
 400: 
 401: formatprint(f, table, nelem, type, lhs, cost)
 402:     FILE *f;
 403:     node **table;
 404:     char *lhs, *cost;
 405: {   int i, didprint;
 406:     char buf[128], *bptr;
 407: 
 408:     sprintf(buf, "%s%s{" /*}*/, lhs, type == PRIVATE ? " " : " = ");
 409:     bptr = buf + strlen(buf);
 410: 
 411:     didprint = 0;
 412:     for (i = 0; i < nelem; i++) {
 413:         if (type == PRIVATE && ! (table[i]->flag & COLLISION))
 414:             continue;
 415:         else if (type == HOSTS && ISADOMAIN(table[i]) )
 416:             continue;
 417:         else if (type == SUBDOMAINS && ! ISADOMAIN(table[i]) )
 418:             continue;
 419: 
 420:         if ((bptr - buf) + strlen(table[i]->name) > 69) {
 421:             *bptr = 0;
 422:             fprintf(f, "%s\n ", buf);   /* continuation */
 423:             bptr = buf;
 424:         }
 425:         sprintf(bptr, "%s, ", table[i]->name);
 426:         bptr += strlen(bptr);
 427:         didprint++;
 428:     }
 429:     *bptr = 0;
 430: 
 431:     if ( ! didprint )
 432:         return;
 433: 
 434:     fprintf(f, /*{*/ "%s}", buf);
 435:     if (type != PRIVATE)
 436:         fprintf(f, "(%s)", cost);
 437:     putc('\n', f);
 438: }
 439: 
 440: FILE *
 441: mkfile(n)
 442:     node *n;
 443: {   node *parent;
 444:     char *bptr;
 445:     FILE *f;
 446: 
 447:     /* build up the domain name in Fname[] */
 448:     bptr = Fstart;
 449:     if (n == Top)
 450:         strcpy(bptr, n->name);
 451:     else {
 452:         strcpy(bptr, n->name + 1);  /* skip leading dot */
 453:         bptr = bptr + strlen(bptr);
 454:         parent = n->parent;
 455:         while (ISADOMAIN(parent)) {
 456:             strcpy(bptr, parent->name);
 457:             bptr += strlen(bptr);
 458:             parent = parent->parent;
 459:         }
 460:         *bptr = 0;
 461:     }
 462: 
 463:     /* get a stream descriptor */
 464:     if (Fflag) {
 465:         printf("# %s\n", Fstart);
 466:         f = stdout;
 467:     } else {
 468: #ifndef BSD
 469:         Fstart[14] = 0;
 470: #endif
 471:         if ((f = fopen(Fname, "w")) == 0) {
 472:             perror(Fname);
 473:             exit(1);
 474:         }
 475:     }
 476:     if (n == Top)
 477:         fprintf(f, "private {%s}\ndead {%s}\n", Top->name, Top->name);
 478:     return f;
 479: }
 480: 
 481: /* map to lower case in place.  return parameter for convenience */
 482: char *
 483: lowercase(buf)
 484:     char *buf;
 485: {   char *str;
 486: 
 487:     for (str = buf ; *str; str++)
 488:         if (isupper(*str))
 489:             *str -= 'A' - 'a';
 490:     return buf;
 491: }
 492: 
 493: /* get the interesting aliases, attach to n->alias */
 494: makealiases(n, line)
 495:     node *n;
 496:     char *line;
 497: {   char *next, *dot;
 498:     node *a;
 499: 
 500:     if (line == 0 || *line == 0)
 501:         return;
 502: 
 503:     for ( ; line; line = next) {
 504:         next = strchr(line, ',');
 505:         if (next)
 506:             *next++ = 0;
 507:         if ((dot = strchr(line, '.')) == 0)
 508:             continue;
 509:         if (strcmp(dot, DotArpa) != 0)
 510:             continue;
 511:         *dot = 0;
 512: 
 513:         if (strcmp(n->name, line) == 0)
 514:             continue;
 515: 
 516:         a = newnode();
 517:         a->name = strsave(line);
 518:         a->next = n->alias;
 519:         n->alias = a;
 520:     }
 521: }
 522: 
 523: #define NHASH 13309
 524: node *htable[NHASH];
 525: 
 526: merge()
 527: {   node *n;
 528: 
 529:     setuniqflag(Top);
 530:     for (n = Top->child; n; n = n->next) {
 531:         if (n->flag & COLLISION) {
 532:             fprintf(stderr, "illegal subdomain: %s\n", n->name);
 533:             abort();
 534:         }
 535:         promote(n);
 536:     }
 537: }
 538: 
 539: /*
 540:  * for domains like cc.umich.edu and cc.berkeley.edu, it's inaccurate
 541:  * to describe cc as a member of umich.edu or berkeley.edu.  (i.e., the
 542:  * lousy scoping rules for privates don't permit a clean syntax.)  so.
 543:  *
 544:  * to prevent confusion, tack on to any such domain name its parent domain
 545:  * and promote it in the tree.  e.g., make cc.umich and cc.berkeley
 546:  * subdomains of edu.
 547:  */
 548: 
 549: promote(parent)
 550:     node *parent;
 551: {   node *prev, *child, *next;
 552:     char buf[BUFSIZ];
 553: 
 554:     prev = 0;
 555:     for (child = parent->child; child; child = next) {
 556:         next = child->next;
 557:         if (!ISADOMAIN(child)) {
 558:             prev = child;
 559:             continue;
 560:         }
 561:         if ((child->flag & COLLISION) || child->gateway) {
 562:             /*
 563: 			 * dup domain name or gateway found.  don't bump
 564: 			 * prev: this node is moving up the tree.
 565: 			 */
 566: 
 567:             /* qualify child domain name */
 568:             sprintf(buf, "%s%s", child->name, parent->name);
 569:             cfree(child->name);
 570:             child->name = strsave(buf);
 571: 
 572:             /* unlink child out of sibling chain */
 573:             if (prev)
 574:                 prev->next = child->next;
 575:             else
 576:                 parent->child = child->next;
 577: 
 578:             /* link child in as peer of parent */
 579:             child->next = parent->next;
 580:             parent->next = child;
 581:             child->parent = parent->parent;
 582: 
 583:             /*
 584: 			 * reset collision flag; may promote again on
 585: 			 * return to caller.
 586: 			 */
 587:             child->flag &= ~COLLISION;
 588:             hash(child);
 589:         } else {
 590:             /* this domain is uninteresting (so bump prev) */
 591:             promote(child);
 592:             prev = child;
 593:         }
 594:     }
 595: 
 596: }
 597: 
 598: setuniqflag(n)
 599:     node *n;
 600: {   node *child, *alias;
 601: 
 602:     /* mark this node in the hash table */
 603:     hash(n);
 604:     /* mark the aliases of this node */
 605:     for (alias = n->alias; alias; alias = alias->next)
 606:         hash(alias);
 607:     /* recursively mark this node's children */
 608:     for (child = n->child; child; child = child->next)
 609:         setuniqflag(child);
 610: }
 611: 
 612: hash(n)
 613:     node *n;
 614: {   node **bucket, *b;
 615: 
 616:     bucket = &htable[fold(n->name) % NHASH];
 617:     for (b = *bucket; b; b = b->bucket) {
 618:         if (strcmp(n->name, b->name) == 0) {
 619:             b->flag |= COLLISION;
 620:             n->flag |= COLLISION;
 621:             return;
 622:         }
 623:     }
 624:     n->bucket = *bucket;
 625:     *bucket = n;
 626: }
 627: 
 628: /* stolen from pathalias:addnode.c, q.v. */
 629: #define POLY    0x48000000      /* 31-bit polynomial */
 630: long CrcTable[128];
 631: 
 632: void
 633: crcinit()
 634: {   register int i,j;
 635:     register long sum;
 636: 
 637:     for (i = 0; i < 128; i++) {
 638:         sum = 0;
 639:         for (j = 7-1; j >= 0; --j)
 640:             if (i & (1 << j))
 641:                 sum ^= POLY >> j;
 642:         CrcTable[i] = sum;
 643:     }
 644: }
 645: 
 646: long
 647: fold(s)
 648:     register char *s;
 649: {   register long sum = 0;
 650:     register int c;
 651: 
 652:     while (c = *s++)
 653:         sum = (sum >> 7) ^ CrcTable[(sum ^ c) & 0x7f];
 654:     return sum;
 655: }

Defined functions

addchild defined in line 287; used 1 times
crcinit defined in line 632; used 2 times
domprint defined in line 334; used 1 times
dtable defined in line 391; never used
dump defined in line 302; used 2 times
dumpgateways defined in line 181; used 1 times
find defined in line 239; used 4 times
fold defined in line 646; used 2 times
formatprint defined in line 401; used 3 times
gateway defined in line 195; used 7 times
hash defined in line 612; used 4 times
insert defined in line 213; used 1 times
lowercase defined in line 482; used 3 times
main defined in line 62; never used
makealiases defined in line 494; used 1 times
merge defined in line 526; used 1 times
mkfile defined in line 440; used 2 times
newnode defined in line 266; used 7 times
promote defined in line 549; used 2 times
qcmp defined in line 328; used 2 times
readprivates defined in line 150; used 1 times
  • in line 91
scan defined in line 129; used 2 times
setuniqflag defined in line 598; used 2 times
strsave defined in line 276; used 7 times
usage defined in line 175; used 2 times

Defined variables

Atflag defined in line 35; used 2 times
CrcTable defined in line 630; used 2 times
DotArpa defined in line 37; used 3 times
Fflag defined in line 36; used 5 times
Fname defined in line 38; used 7 times
Fstart defined in line 38; used 7 times
Iflag defined in line 36; used 6 times
Top defined in line 34; used 17 times
htable defined in line 524; used 1 times
sccsid defined in line 2; never used

Defined struct's

node defined in line 23; used 1 times
  • in line 21

Defined typedef's

node defined in line 21; used 40 times

Defined macros

BSD defined in line 12; used 2 times
COLLISION defined in line 52; used 7 times
HOSTS defined in line 56; used 2 times
ISADOMAIN defined in line 49; used 5 times
NHASH defined in line 523; used 2 times
POLY defined in line 629; used 1 times
PRIVATE defined in line 55; used 4 times
SUBDOMAINS defined in line 57; used 2 times
USAGE defined in line 60; used 1 times
strchr defined in line 15; used 10 times
Last modified: 1987-11-29
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 41170
Valid CSS Valid XHTML 1.0 Strict