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