1: #
   2: 
   3: /*
   4:  * Mail -- a program for sending and receiving mail.
   5:  *
   6:  * Network name modification routines.
   7:  */
   8: 
   9: #include "rcv.h"
  10: #include "configdefs.h"
  11: #include <ctype.h>
  12: 
  13: static char *SccsId = "@(#)optim.c	2.8 3/2/83";
  14: 
  15: /*
  16:  * Map a name into the correct network "view" of the
  17:  * name.  This is done by prepending the name with the
  18:  * network address of the sender, then optimizing away
  19:  * nonsense.
  20:  */
  21: 
  22: char *
  23: netmap(name, from)
  24:     char name[], from[];
  25: {
  26:     char nbuf[BUFSIZ], ret[BUFSIZ];
  27:     register char *cp;
  28: 
  29:     if (strlen(from) == 0)
  30:         return(name);
  31:     if (any('@', name) || any('%', name))
  32:         return(savestr(arpafix(name, from)));
  33:     cp = revarpa(from);
  34:     if (cp == NOSTR)
  35:         return(name);
  36:     strcpy(nbuf, cp);
  37:     cp = &nbuf[strlen(nbuf) - 1];
  38:     while (!any(*cp, metanet) && cp > nbuf)
  39:         cp--;
  40:     if (cp == nbuf)
  41:         return(name);
  42:     *++cp = 0;
  43:     strcat(nbuf, revarpa(name));
  44:     optim(nbuf, ret);
  45:     cp = revarpa(ret);
  46:     if (!icequal(name, cp))
  47:         return(savestr(cp));
  48:     return(name);
  49: }
  50: 
  51: /*
  52:  * Rename the given network path to use
  53:  * the kinds of names that we would right here.
  54:  */
  55: 
  56: char *
  57: rename(str)
  58:     char str[];
  59: {
  60:     register char *cp, *cp2;
  61:     char buf[BUFSIZ], path[BUFSIZ];
  62:     register int c, host;
  63: 
  64:     strcpy(path, "");
  65:     for (;;) {
  66:         if ((c = *cp++) == 0)
  67:             break;
  68:         cp2 = buf;
  69:         while (!any(c, metanet) && c != 0) {
  70:             *cp2++ = c;
  71:             c = *cp++;
  72:         }
  73:         *cp2 = 0;
  74:         if (c == 0) {
  75:             strcat(path, buf);
  76:             break;
  77:         }
  78:         host = netlook(buf, ntype(c));
  79:         strcat(path, netname(host));
  80:         stradd(path, c);
  81:     }
  82:     if (strcmp(str, path) != 0)
  83:         return(savestr(path));
  84:     return(str);
  85: }
  86: 
  87: /*
  88:  * Turn a network machine name into a unique character
  89:  */
  90: netlook(machine, attnet)
  91:     char machine[];
  92: {
  93:     register struct netmach *np;
  94:     register char *cp, *cp2;
  95:     char nbuf[20];
  96: 
  97:     /*
  98: 	 * Make into lower case.
  99: 	 */
 100: 
 101:     for (cp = machine, cp2 = nbuf; *cp; *cp2++ = little(*cp++))
 102:         ;
 103:     *cp2 = 0;
 104: 
 105:     /*
 106: 	 * If a single letter machine, look through those first.
 107: 	 */
 108: 
 109:     if (strlen(nbuf) == 1)
 110:         for (np = netmach; np->nt_mid != 0; np++)
 111:             if (np->nt_mid == nbuf[0])
 112:                 return(nbuf[0]);
 113: 
 114:     /*
 115: 	 * Look for usual name
 116: 	 */
 117: 
 118:     for (np = netmach; np->nt_mid != 0; np++)
 119:         if (strcmp(np->nt_machine, nbuf) == 0)
 120:             return(np->nt_mid);
 121: 
 122:     /*
 123: 	 * Look in side hash table.
 124: 	 */
 125: 
 126:     return(mstash(nbuf, attnet));
 127: }
 128: 
 129: /*
 130:  * Make a little character.
 131:  */
 132: 
 133: little(c)
 134:     register int c;
 135: {
 136: 
 137:     if (c >= 'A' && c <= 'Z')
 138:         c += 'a' - 'A';
 139:     return(c);
 140: }
 141: 
 142: /*
 143:  * Turn a network unique character identifier into a network name.
 144:  */
 145: 
 146: char *
 147: netname(mid)
 148: {
 149:     register struct netmach *np;
 150:     char *mlook();
 151: 
 152:     if (mid & 0200)
 153:         return(mlook(mid));
 154:     for (np = netmach; np->nt_mid != 0; np++)
 155:         if (np->nt_mid == mid)
 156:             return(np->nt_machine);
 157:     return(NOSTR);
 158: }
 159: 
 160: /*
 161:  * Deal with arpa net addresses.  The way this is done is strange.
 162:  * In particular, if the destination arpa net host is not Berkeley,
 163:  * then the address is correct as stands.  Otherwise, we strip off
 164:  * the trailing @Berkeley, then cook up a phony person for it to
 165:  * be from and optimize the result.
 166:  */
 167: char *
 168: arpafix(name, from)
 169:     char name[];
 170:     char from[];
 171: {
 172:     register char *cp;
 173:     register int arpamach;
 174:     char newname[BUFSIZ];
 175:     char fake[5];
 176:     char fakepath[20];
 177: 
 178:     if (debug) {
 179:         fprintf(stderr, "arpafix(%s, %s)\n", name, from);
 180:     }
 181:     cp = rindex(name, '@');
 182:     if (cp == NOSTR)
 183:         cp = rindex(name, '%');
 184:     if (cp == NOSTR) {
 185:         fprintf(stderr, "Somethings amiss -- no @ or % in arpafix\n");
 186:         return(name);
 187:     }
 188:     cp++;
 189:     arpamach = netlook(cp, '@');
 190:     if (arpamach == 0) {
 191:         if (debug)
 192:             fprintf(stderr, "machine %s unknown, uses: %s\n", cp, name);
 193:         return(name);
 194:     }
 195:     if (((nettype(arpamach) & nettype(LOCAL)) & ~AN) == 0) {
 196:         if (debug)
 197:             fprintf(stderr, "machine %s known but remote, uses: %s\n",
 198:                 cp, name);
 199:         return(name);
 200:     }
 201:     strcpy(newname, name);
 202:     cp = rindex(newname, '@');
 203:     if (cp == NOSTR)
 204:         cp = rindex(newname, '%');
 205:     *cp = 0;
 206:     fake[0] = arpamach;
 207:     fake[1] = ':';
 208:     fake[2] = LOCAL;
 209:     fake[3] = ':';
 210:     fake[4] = 0;
 211:     prefer(fake);
 212:     strcpy(fakepath, netname(fake[0]));
 213:     stradd(fakepath, fake[1]);
 214:     strcat(fakepath, "daemon");
 215:     if (debug)
 216:         fprintf(stderr, "machine local, call netmap(%s, %s)\n",
 217:             newname, fakepath);
 218:     return(netmap(newname, fakepath));
 219: }
 220: 
 221: /*
 222:  * Take a network machine descriptor and find the types of connected
 223:  * nets and return it.
 224:  */
 225: 
 226: nettype(mid)
 227: {
 228:     register struct netmach *np;
 229: 
 230:     if (mid & 0200)
 231:         return(mtype(mid));
 232:     for (np = netmach; np->nt_mid != 0; np++)
 233:         if (np->nt_mid == mid)
 234:             return(np->nt_type);
 235:     return(0);
 236: }
 237: 
 238: /*
 239:  * Hashing routines to salt away machines seen scanning
 240:  * networks paths that we don't know about.
 241:  */
 242: 
 243: #define XHSIZE      19      /* Size of extra hash table */
 244: #define NXMID       (XHSIZE*3/4)    /* Max extra machines */
 245: 
 246: struct xtrahash {
 247:     char    *xh_name;       /* Name of machine */
 248:     short   xh_mid;         /* Machine ID */
 249:     short   xh_attnet;      /* Attached networks */
 250: } xtrahash[XHSIZE];
 251: 
 252: struct xtrahash *xtab[XHSIZE];      /* F: mid-->machine name */
 253: 
 254: short   midfree;            /* Next free machine id */
 255: 
 256: /*
 257:  * Initialize the extra host hash table.
 258:  * Called by sreset.
 259:  */
 260: 
 261: minit()
 262: {
 263:     register struct xtrahash *xp, **tp;
 264:     register int i;
 265: 
 266:     midfree = 0;
 267:     tp = &xtab[0];
 268:     for (xp = &xtrahash[0]; xp < &xtrahash[XHSIZE]; xp++) {
 269:         xp->xh_name = NOSTR;
 270:         xp->xh_mid = 0;
 271:         xp->xh_attnet = 0;
 272:         *tp++ = (struct xtrahash *) 0;
 273:     }
 274: }
 275: 
 276: /*
 277:  * Stash a net name in the extra host hash table.
 278:  * If a new entry is put in the hash table, deduce what
 279:  * net the machine is attached to from the net character.
 280:  *
 281:  * If the machine is already known, add the given attached
 282:  * net to those already known.
 283:  */
 284: 
 285: mstash(name, attnet)
 286:     char name[];
 287: {
 288:     register struct xtrahash *xp;
 289:     struct xtrahash *xlocate();
 290:     int x;
 291: 
 292:     xp = xlocate(name);
 293:     if (xp == (struct xtrahash *) 0) {
 294:         printf("Ran out of machine id spots\n");
 295:         return(0);
 296:     }
 297:     if (xp->xh_name == NOSTR) {
 298:         if (midfree >= XHSIZE) {
 299:             printf("Out of machine ids\n");
 300:             return(0);
 301:         }
 302:         xtab[midfree] = xp;
 303:         xp->xh_name = savestr(name);
 304:         xp->xh_mid = 0200 + midfree++;
 305:     }
 306:     x = ntype(attnet);
 307:     if (x == 0)
 308:         xp->xh_attnet |= SN;
 309:     else
 310:         xp->xh_attnet |= x;
 311:     return(xp->xh_mid);
 312: }
 313: 
 314: /*
 315:  * Search for the given name in the hash table
 316:  * and return the pointer to it if found, or to the first
 317:  * empty slot if not found.
 318:  *
 319:  * If no free slots can be found, return 0.
 320:  */
 321: 
 322: struct xtrahash *
 323: xlocate(name)
 324:     char name[];
 325: {
 326:     register int h, q, i;
 327:     register char *cp;
 328:     register struct xtrahash *xp;
 329: 
 330:     for (h = 0, cp = name; *cp; h = (h << 2) + *cp++)
 331:         ;
 332:     if (h < 0 && (h = -h) < 0)
 333:         h = 0;
 334:     h = h % XHSIZE;
 335:     cp = name;
 336:     for (i = 0, q = 0; q < XHSIZE; i++, q = i * i) {
 337:         xp = &xtrahash[(h + q) % XHSIZE];
 338:         if (xp->xh_name == NOSTR)
 339:             return(xp);
 340:         if (strcmp(cp, xp->xh_name) == 0)
 341:             return(xp);
 342:         if (h - q < 0)
 343:             q += XHSIZE;
 344:         xp = &xtrahash[(h - q) % XHSIZE];
 345:         if (xp->xh_name == NOSTR)
 346:             return(xp);
 347:         if (strcmp(cp, xp->xh_name) == 0)
 348:             return(xp);
 349:     }
 350:     return((struct xtrahash *) 0);
 351: }
 352: 
 353: /*
 354:  * Return the name from the extra host hash table corresponding
 355:  * to the passed machine id.
 356:  */
 357: 
 358: char *
 359: mlook(mid)
 360: {
 361:     register int m;
 362: 
 363:     if ((mid & 0200) == 0)
 364:         return(NOSTR);
 365:     m = mid & 0177;
 366:     if (m >= midfree) {
 367:         printf("Use made of undefined machine id\n");
 368:         return(NOSTR);
 369:     }
 370:     return(xtab[m]->xh_name);
 371: }
 372: 
 373: /*
 374:  * Return the bit mask of net's that the given extra host machine
 375:  * id has so far.
 376:  */
 377: 
 378: mtype(mid)
 379: {
 380:     register int m;
 381: 
 382:     if ((mid & 0200) == 0)
 383:         return(0);
 384:     m = mid & 0177;
 385:     if (m >= midfree) {
 386:         printf("Use made of undefined machine id\n");
 387:         return(0);
 388:     }
 389:     return(xtab[m]->xh_attnet);
 390: }
 391: 
 392: /*
 393:  * Take a network name and optimize it.  This gloriously messy
 394:  * operation takes place as follows:  the name with machine names
 395:  * in it is tokenized by mapping each machine name into a single
 396:  * character machine id (netlook).  The separator characters (network
 397:  * metacharacters) are left intact.  The last component of the network
 398:  * name is stripped off and assumed to be the destination user name --
 399:  * it does not participate in the optimization.  As an example, the
 400:  * name "research!vax135!research!ucbvax!bill" becomes, tokenized,
 401:  * "r!x!r!v!" and "bill"  A low level routine, optim1, fixes up the
 402:  * network part (eg, "r!x!r!v!"), then we convert back to network
 403:  * machine names and tack the user name on the end.
 404:  *
 405:  * The result of this is copied into the parameter "name"
 406:  */
 407: 
 408: optim(net, name)
 409:     char net[], name[];
 410: {
 411:     char netcomp[BUFSIZ], netstr[40], xfstr[40];
 412:     register char *cp, *cp2;
 413:     register int c;
 414: 
 415:     strcpy(netstr, "");
 416:     cp = net;
 417:     for (;;) {
 418:         /*
 419: 		 * Rip off next path component into netcomp
 420: 		 */
 421:         cp2 = netcomp;
 422:         while (*cp && !any(*cp, metanet))
 423:             *cp2++ = *cp++;
 424:         *cp2 = 0;
 425:         /*
 426: 		 * If we hit null byte, then we just scanned
 427: 		 * the destination user name.  Go off and optimize
 428: 		 * if its so.
 429: 		 */
 430:         if (*cp == 0)
 431:             break;
 432:         if ((c = netlook(netcomp, *cp)) == 0) {
 433:             printf("No host named \"%s\"\n", netcomp);
 434: err:
 435:             strcpy(name, net);
 436:             return;
 437:         }
 438:         stradd(netstr, c);
 439:         stradd(netstr, *cp++);
 440:         /*
 441: 		 * If multiple network separators given,
 442: 		 * throw away the extras.
 443: 		 */
 444:         while (any(*cp, metanet))
 445:             cp++;
 446:     }
 447:     if (strlen(netcomp) == 0) {
 448:         printf("net name syntax\n");
 449:         goto err;
 450:     }
 451:     optim1(netstr, xfstr);
 452: 
 453:     /*
 454: 	 * Convert back to machine names.
 455: 	 */
 456: 
 457:     cp = xfstr;
 458:     strcpy(name, "");
 459:     while (*cp) {
 460:         if ((cp2 = netname(*cp++)) == NOSTR) {
 461:             printf("Made up bad net name\n");
 462:             printf("Machine code %c (0%o)\n", cp[-1], cp[-1]);
 463:             printf("Sorry -- dumping now.  Alert K. Shoens\n");
 464:             core(0);
 465:             goto err;
 466:         }
 467:         strcat(name, cp2);
 468:         stradd(name, *cp++);
 469:     }
 470:     strcat(name, netcomp);
 471: }
 472: 
 473: /*
 474:  * Take a string of network machine id's and separators and
 475:  * optimize them.  We process these by pulling off maximal
 476:  * leading strings of the same type, passing these to the appropriate
 477:  * optimizer and concatenating the results.
 478:  */
 479: 
 480: optim1(netstr, name)
 481:     char netstr[], name[];
 482: {
 483:     char path[40], rpath[40];
 484:     register char *cp, *cp2;
 485:     register int tp, nc;
 486: 
 487:     cp = netstr;
 488:     prefer(cp);
 489:     strcpy(name, "");
 490:     /*
 491: 	 * If the address ultimately points back to us,
 492: 	 * just return a null network path.
 493: 	 */
 494:     if (strlen(cp) > 1 && cp[strlen(cp) - 2] == LOCAL)
 495:         return;
 496:     while (*cp != 0) {
 497:         strcpy(path, "");
 498:         tp = ntype(cp[1]);
 499:         nc = cp[1];
 500:         while (*cp && tp == ntype(cp[1])) {
 501:             stradd(path, *cp++);
 502:             cp++;
 503:         }
 504:         switch (netkind(tp)) {
 505:         default:
 506:             strcpy(rpath, path);
 507:             break;
 508: 
 509:         case IMPLICIT:
 510:             optimimp(path, rpath);
 511:             break;
 512: 
 513:         case EXPLICIT:
 514:             optimex(path, rpath);
 515:             break;
 516:         }
 517:         for (cp2 = rpath; *cp2 != 0; cp2++) {
 518:             stradd(name, *cp2);
 519:             stradd(name, nc);
 520:         }
 521:     }
 522:     optiboth(name);
 523:     prefer(name);
 524: }
 525: 
 526: /*
 527:  * Return the network of the separator --
 528:  *	AN for arpa net
 529:  *	BN for Bell labs net
 530:  *	SN for Schmidt (berkeley net)
 531:  *	0 if we don't know.
 532:  */
 533: 
 534: ntype(nc)
 535:     register int nc;
 536: {
 537:     register struct ntypetab *np;
 538: 
 539:     for (np = ntypetab; np->nt_char != 0; np++)
 540:         if (np->nt_char == nc)
 541:             return(np->nt_bcode);
 542:     return(0);
 543: }
 544: 
 545: /*
 546:  * Return the kind of routing used for the particular net
 547:  * EXPLICIT means explicitly routed
 548:  * IMPLICIT means implicitly routed
 549:  * 0 means don't know
 550:  */
 551: 
 552: netkind(nt)
 553:     register int nt;
 554: {
 555:     register struct nkindtab *np;
 556: 
 557:     for (np = nkindtab; np->nk_type != 0; np++)
 558:         if (np->nk_type == nt)
 559:             return(np->nk_kind);
 560:     return(0);
 561: }
 562: 
 563: /*
 564:  * Do name optimization for an explicitly routed network (eg BTL network).
 565:  */
 566: 
 567: optimex(net, name)
 568:     char net[], name[];
 569: {
 570:     register char *cp, *rp;
 571:     register int m;
 572:     char *rindex();
 573: 
 574:     strcpy(name, net);
 575:     cp = name;
 576:     if (strlen(cp) == 0)
 577:         return(-1);
 578:     if (cp[strlen(cp)-1] == LOCAL) {
 579:         name[0] = 0;
 580:         return(0);
 581:     }
 582:     for (cp = name; *cp; cp++) {
 583:         m = *cp;
 584:         rp = rindex(cp+1, m);
 585:         if (rp != NOSTR)
 586:             strcpy(cp, rp);
 587:     }
 588:     return(0);
 589: }
 590: 
 591: /*
 592:  * Do name optimization for implicitly routed network (eg, arpanet,
 593:  * Berkeley network)
 594:  */
 595: 
 596: optimimp(net, name)
 597:     char net[], name[];
 598: {
 599:     register char *cp;
 600:     register int m;
 601: 
 602:     cp = net;
 603:     if (strlen(cp) == 0)
 604:         return(-1);
 605:     m = cp[strlen(cp) - 1];
 606:     if (m == LOCAL) {
 607:         strcpy(name, "");
 608:         return(0);
 609:     }
 610:     name[0] = m;
 611:     name[1] = 0;
 612:     return(0);
 613: }
 614: 
 615: /*
 616:  * Perform global optimization on the given network path.
 617:  * The trick here is to look ahead to see if there are any loops
 618:  * in the path and remove them.  The interpretation of loops is
 619:  * more strict here than in optimex since both the machine and net
 620:  * type must match.
 621:  */
 622: 
 623: optiboth(net)
 624:     char net[];
 625: {
 626:     register char *cp, *cp2;
 627:     char *rpair();
 628: 
 629:     cp = net;
 630:     if (strlen(cp) == 0)
 631:         return;
 632:     if ((strlen(cp) % 2) != 0) {
 633:         printf("Strange arg to optiboth\n");
 634:         return;
 635:     }
 636:     while (*cp) {
 637:         cp2 = rpair(cp+2, *cp);
 638:         if (cp2 != NOSTR)
 639:             strcpy(cp, cp2);
 640:         cp += 2;
 641:     }
 642: }
 643: 
 644: /*
 645:  * Find the rightmost instance of the given (machine, type) pair.
 646:  */
 647: 
 648: char *
 649: rpair(str, mach)
 650:     char str[];
 651: {
 652:     register char *cp, *last;
 653: 
 654:     last = NOSTR;
 655:     while (*cp) {
 656:         if (*cp == mach)
 657:             last = cp;
 658:         cp += 2;
 659:     }
 660:     return(last);
 661: }
 662: 
 663: /*
 664:  * Change the network separators in the given network path
 665:  * to the preferred network transmission means.
 666:  */
 667: 
 668: prefer(name)
 669:     char name[];
 670: {
 671:     register char *cp;
 672:     register int state, n;
 673: 
 674:     state = LOCAL;
 675:     for (cp = name; *cp; cp += 2) {
 676:         n = best(state, *cp);
 677:         if (n)
 678:             cp[1] = n;
 679:         state = *cp;
 680:     }
 681: }
 682: 
 683: /*
 684:  * Return the best network separator for the given machine pair.
 685:  */
 686: 
 687: best(src, dest)
 688: {
 689:     register int dtype, stype;
 690:     register struct netorder *np;
 691: 
 692:     stype = nettype(src);
 693:     dtype = nettype(dest);
 694:     fflush(stdout);
 695:     if (stype == 0 || dtype == 0) {
 696:         printf("ERROR:  unknown internal machine id\n");
 697:         return(0);
 698:     }
 699:     if ((stype & dtype) == 0)
 700:         return(0);
 701:     np = &netorder[0];
 702:     while ((np->no_stat & stype & dtype) == 0)
 703:         np++;
 704:     return(np->no_char);
 705: }
 706: 
 707: #ifdef  GETHOST
 708: /*
 709:  * Initialize the network name of the current host.
 710:  */
 711: inithost()
 712: {
 713:     register struct netmach *np;
 714:     static char host[64];
 715: 
 716:     gethostname(host, sizeof host);
 717:     for (np = netmach; np->nt_machine != 0; np++)
 718:         if (strcmp(np->nt_machine, EMPTY) == 0)
 719:             break;
 720:     if (np->nt_machine == 0) {
 721:         printf("Cannot find empty slot for dynamic host entry\n");
 722:         exit(1);
 723:     }
 724:     np->nt_machine = host;
 725: }
 726: #endif	GETHOST
 727: 
 728: /*
 729:  * Code to twist around arpa net names.
 730:  */
 731: 
 732: #define WORD 257            /* Token for a string */
 733: 
 734: static  char netbuf[256];
 735: static  char *yylval;
 736: 
 737: /*
 738:  * Reverse all of the arpa net addresses in the given name to
 739:  * be of the form "host @ user" instead of "user @ host"
 740:  * This function is its own inverse.
 741:  */
 742: 
 743: char *
 744: revarpa(str)
 745:     char str[];
 746: {
 747: 
 748:     if (yyinit(str) < 0)
 749:         return(NOSTR);
 750:     if (name())
 751:         return(NOSTR);
 752:     if (strcmp(str, netbuf) == 0)
 753:         return(str);
 754:     return(savestr(netbuf));
 755: }
 756: 
 757: /*
 758:  * Parse (by recursive descent) network names, using the following grammar:
 759:  *	name:
 760:  *		term {':' term}
 761:  *		term {'^' term}
 762:  *		term {'!' term}
 763:  *		term '@' name
 764:  *		term '%' name
 765:  *
 766:  *	term:
 767:  *		string of characters.
 768:  */
 769: 
 770: name()
 771: {
 772:     register int t;
 773:     register char *cp;
 774: 
 775:     for (;;) {
 776:         t = yylex();
 777:         if (t != WORD)
 778:             return(-1);
 779:         cp = yylval;
 780:         t = yylex();
 781:         switch (t) {
 782:         case 0:
 783:             strcat(netbuf, cp);
 784:             return(0);
 785: 
 786:         case '@':
 787:         case '%':
 788:             if (name())
 789:                 return(-1);
 790:             stradd(netbuf, '@');
 791:             strcat(netbuf, cp);
 792:             return(0);
 793: 
 794:         case WORD:
 795:             return(-1);
 796: 
 797:         default:
 798:             strcat(netbuf, cp);
 799:             stradd(netbuf, t);
 800:         }
 801:     }
 802: }
 803: 
 804: /*
 805:  * Scanner for network names.
 806:  */
 807: 
 808: static  char *charp;            /* Current input pointer */
 809: static  int nexttok;            /* Salted away next token */
 810: 
 811: /*
 812:  * Initialize the network name scanner.
 813:  */
 814: 
 815: yyinit(str)
 816:     char str[];
 817: {
 818:     static char lexbuf[BUFSIZ];
 819: 
 820:     netbuf[0] = 0;
 821:     if (strlen(str) >= sizeof lexbuf - 1)
 822:         return(-1);
 823:     nexttok = 0;
 824:     strcpy(lexbuf, str);
 825:     charp = lexbuf;
 826:     return(0);
 827: }
 828: 
 829: /*
 830:  * Scan and return a single token.
 831:  * yylval is set to point to a scanned string.
 832:  */
 833: 
 834: yylex()
 835: {
 836:     register char *cp, *dot;
 837:     register int s;
 838: 
 839:     if (nexttok) {
 840:         s = nexttok;
 841:         nexttok = 0;
 842:         return(s);
 843:     }
 844:     cp = charp;
 845:     while (*cp && isspace(*cp))
 846:         cp++;
 847:     if (*cp == 0)
 848:         return(0);
 849:     if (any(*cp, metanet)) {
 850:         charp = cp+1;
 851:         return(*cp);
 852:     }
 853:     dot = cp;
 854:     while (*cp && !any(*cp, metanet) && !any(*cp, " \t"))
 855:         cp++;
 856:     if (any(*cp, metanet))
 857:         nexttok = *cp;
 858:     if (*cp == 0)
 859:         charp = cp;
 860:     else
 861:         charp = cp+1;
 862:     *cp = 0;
 863:     yylval = dot;
 864:     return(WORD);
 865: }
 866: 
 867: /*
 868:  * Add a single character onto a string.
 869:  */
 870: 
 871: stradd(str, c)
 872:     register char *str;
 873:     register int c;
 874: {
 875: 
 876:     str += strlen(str);
 877:     *str++ = c;
 878:     *str = 0;
 879: }

Defined functions

arpafix defined in line 167; used 2 times
best defined in line 687; used 1 times
inithost defined in line 711; used 1 times
little defined in line 133; used 2 times
minit defined in line 261; used 1 times
mlook defined in line 358; used 2 times
mstash defined in line 285; used 1 times
mtype defined in line 378; used 1 times
name defined in line 770; used 60 times
netkind defined in line 552; used 1 times
netlook defined in line 90; used 3 times
netmap defined in line 22; used 3 times
netname defined in line 146; used 4 times
nettype defined in line 226; used 4 times
ntype defined in line 534; used 4 times
optiboth defined in line 623; used 1 times
optim defined in line 408; used 1 times
  • in line 44
optim1 defined in line 480; used 1 times
optimex defined in line 567; used 1 times
optimimp defined in line 596; used 1 times
prefer defined in line 668; used 3 times
rename defined in line 56; used 1 times
revarpa defined in line 743; used 4 times
rpair defined in line 648; used 3 times
stradd defined in line 871; used 12 times
xlocate defined in line 322; used 2 times
yyinit defined in line 815; used 1 times
yylex defined in line 834; used 2 times

Defined variables

SccsId defined in line 13; never used
charp defined in line 808; used 5 times
midfree defined in line 254; used 6 times
netbuf defined in line 734; used 8 times
nexttok defined in line 809; used 5 times
xtab defined in line 252; used 4 times
xtrahash defined in line 250; used 4 times
yylval defined in line 735; used 2 times

Defined struct's

xtrahash defined in line 246; used 18 times

Defined macros

NXMID defined in line 244; never used
WORD defined in line 732; used 2 times
XHSIZE defined in line 243; used 10 times
Last modified: 1983-03-03
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 2269
Valid CSS Valid XHTML 1.0 Strict