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