|
|
1.1 ! root 1: #ifndef lint ! 2: static char sccsid[] = "@(#)optim.c 2.9 (Berkeley) 8/11/83"; ! 3: #endif ! 4: ! 5: /* ! 6: * Mail -- a program for sending and receiving mail. ! 7: * ! 8: * Network name modification routines. ! 9: */ ! 10: ! 11: #include "rcv.h" ! 12: #include "configdefs.h" ! 13: #include <ctype.h> ! 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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.