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