122462Sdist /* 222462Sdist * Copyright (c) 1980 Regents of the University of California. 322462Sdist * All rights reserved. The Berkeley software License Agreement 422462Sdist * specifies the terms and conditions for redistribution. 522462Sdist */ 622462Sdist 714538Ssam #ifndef lint 8*31142Sedward static char *sccsid = "@(#)optim.c 5.7 (Berkeley) 05/18/87"; 922462Sdist #endif not lint 101242Skas 111242Skas /* 121242Skas * Mail -- a program for sending and receiving mail. 131242Skas * 141242Skas * Network name modification routines. 151242Skas */ 161242Skas 171242Skas #include "rcv.h" 184337Skurt #include "configdefs.h" 191242Skas 201242Skas /* 211242Skas * Map a name into the correct network "view" of the 221242Skas * name. This is done by prepending the name with the 231242Skas * network address of the sender, then optimizing away 241242Skas * nonsense. 251242Skas */ 261242Skas 271242Skas char * 281242Skas netmap(name, from) 291242Skas char name[], from[]; 301242Skas { 311242Skas char nbuf[BUFSIZ], ret[BUFSIZ]; 321242Skas register char *cp; 331242Skas 341242Skas if (strlen(from) == 0) 351242Skas return(name); 361242Skas if (any('@', name) || any('%', name)) 3711387Sleres return(savestr(arpafix(name, from))); 381242Skas cp = revarpa(from); 391242Skas if (cp == NOSTR) 401242Skas return(name); 411242Skas strcpy(nbuf, cp); 421242Skas cp = &nbuf[strlen(nbuf) - 1]; 431242Skas while (!any(*cp, metanet) && cp > nbuf) 441242Skas cp--; 451242Skas if (cp == nbuf) 461242Skas return(name); 471242Skas *++cp = 0; 481242Skas strcat(nbuf, revarpa(name)); 491242Skas optim(nbuf, ret); 501242Skas cp = revarpa(ret); 511242Skas if (!icequal(name, cp)) 5211387Sleres return(savestr(cp)); 531242Skas return(name); 541242Skas } 551242Skas 561242Skas /* 571242Skas * Turn a network machine name into a unique character 581242Skas */ 591242Skas netlook(machine, attnet) 601242Skas char machine[]; 611242Skas { 621242Skas register struct netmach *np; 631242Skas register char *cp, *cp2; 6425374Sserge char nbuf[BUFSIZ]; 651242Skas 661242Skas /* 671242Skas * Make into lower case. 681242Skas */ 691242Skas 701242Skas for (cp = machine, cp2 = nbuf; *cp; *cp2++ = little(*cp++)) 7116768Sralph if (cp2 >= &nbuf[sizeof(nbuf)-1]) 7216768Sralph break; 731242Skas *cp2 = 0; 741242Skas 751242Skas /* 761242Skas * If a single letter machine, look through those first. 771242Skas */ 781242Skas 791242Skas if (strlen(nbuf) == 1) 801242Skas for (np = netmach; np->nt_mid != 0; np++) 811242Skas if (np->nt_mid == nbuf[0]) 821242Skas return(nbuf[0]); 831242Skas 841242Skas /* 851242Skas * Look for usual name 861242Skas */ 871242Skas 881242Skas for (np = netmach; np->nt_mid != 0; np++) 891242Skas if (strcmp(np->nt_machine, nbuf) == 0) 901242Skas return(np->nt_mid); 911242Skas 921242Skas /* 931242Skas * Look in side hash table. 941242Skas */ 951242Skas 961242Skas return(mstash(nbuf, attnet)); 971242Skas } 981242Skas 991242Skas /* 1001242Skas * Make a little character. 1011242Skas */ 1021242Skas 1031242Skas little(c) 1041242Skas register int c; 1051242Skas { 1061242Skas 1071242Skas if (c >= 'A' && c <= 'Z') 1081242Skas c += 'a' - 'A'; 1091242Skas return(c); 1101242Skas } 1111242Skas 1121242Skas /* 1131242Skas * Turn a network unique character identifier into a network name. 1141242Skas */ 1151242Skas 1161242Skas char * 1171242Skas netname(mid) 1181242Skas { 1191242Skas register struct netmach *np; 1201242Skas char *mlook(); 1211242Skas 1221242Skas if (mid & 0200) 1231242Skas return(mlook(mid)); 1241242Skas for (np = netmach; np->nt_mid != 0; np++) 1251242Skas if (np->nt_mid == mid) 1261242Skas return(np->nt_machine); 1271242Skas return(NOSTR); 1281242Skas } 1291242Skas 1301242Skas /* 1311242Skas * Deal with arpa net addresses. The way this is done is strange. 1321242Skas * In particular, if the destination arpa net host is not Berkeley, 1331242Skas * then the address is correct as stands. Otherwise, we strip off 1341242Skas * the trailing @Berkeley, then cook up a phony person for it to 1351242Skas * be from and optimize the result. 1361242Skas */ 1371242Skas char * 1381242Skas arpafix(name, from) 1391242Skas char name[]; 1401242Skas char from[]; 1411242Skas { 1421242Skas register char *cp; 1431242Skas register int arpamach; 1441242Skas char newname[BUFSIZ]; 1451242Skas char fake[5]; 1461242Skas char fakepath[20]; 1471242Skas 1481242Skas if (debug) { 1491242Skas fprintf(stderr, "arpafix(%s, %s)\n", name, from); 1501242Skas } 1511242Skas cp = rindex(name, '@'); 1521242Skas if (cp == NOSTR) 1531242Skas cp = rindex(name, '%'); 1541242Skas if (cp == NOSTR) { 155*31142Sedward fprintf(stderr, "Somethings amiss -- no @ or %% in arpafix\n"); 1561242Skas return(name); 1571242Skas } 1581242Skas cp++; 1591242Skas arpamach = netlook(cp, '@'); 1601242Skas if (arpamach == 0) { 1611242Skas if (debug) 1621242Skas fprintf(stderr, "machine %s unknown, uses: %s\n", cp, name); 1631242Skas return(name); 1641242Skas } 1651242Skas if (((nettype(arpamach) & nettype(LOCAL)) & ~AN) == 0) { 1661242Skas if (debug) 1671242Skas fprintf(stderr, "machine %s known but remote, uses: %s\n", 1681242Skas cp, name); 1691242Skas return(name); 1701242Skas } 1711242Skas strcpy(newname, name); 1721242Skas cp = rindex(newname, '@'); 1731242Skas if (cp == NOSTR) 1741242Skas cp = rindex(newname, '%'); 1751242Skas *cp = 0; 1761242Skas fake[0] = arpamach; 1771242Skas fake[1] = ':'; 1781242Skas fake[2] = LOCAL; 1791242Skas fake[3] = ':'; 1801242Skas fake[4] = 0; 1811242Skas prefer(fake); 1821242Skas strcpy(fakepath, netname(fake[0])); 1831242Skas stradd(fakepath, fake[1]); 1841242Skas strcat(fakepath, "daemon"); 1851242Skas if (debug) 1861242Skas fprintf(stderr, "machine local, call netmap(%s, %s)\n", 1871242Skas newname, fakepath); 1881242Skas return(netmap(newname, fakepath)); 1891242Skas } 1901242Skas 1911242Skas /* 1921242Skas * Take a network machine descriptor and find the types of connected 1931242Skas * nets and return it. 1941242Skas */ 1951242Skas 1961242Skas nettype(mid) 1971242Skas { 1981242Skas register struct netmach *np; 1991242Skas 2001242Skas if (mid & 0200) 2011242Skas return(mtype(mid)); 2021242Skas for (np = netmach; np->nt_mid != 0; np++) 2031242Skas if (np->nt_mid == mid) 2041242Skas return(np->nt_type); 2051242Skas return(0); 2061242Skas } 2071242Skas 2081242Skas /* 2091242Skas * Hashing routines to salt away machines seen scanning 2101242Skas * networks paths that we don't know about. 2111242Skas */ 2121242Skas 2131242Skas #define XHSIZE 19 /* Size of extra hash table */ 2141242Skas #define NXMID (XHSIZE*3/4) /* Max extra machines */ 2151242Skas 2161242Skas struct xtrahash { 2171242Skas char *xh_name; /* Name of machine */ 2181242Skas short xh_mid; /* Machine ID */ 2191242Skas short xh_attnet; /* Attached networks */ 2201242Skas } xtrahash[XHSIZE]; 2211242Skas 2221242Skas struct xtrahash *xtab[XHSIZE]; /* F: mid-->machine name */ 2231242Skas 2241242Skas short midfree; /* Next free machine id */ 2251242Skas 2261242Skas /* 2271242Skas * Initialize the extra host hash table. 2281242Skas * Called by sreset. 2291242Skas */ 2301242Skas 2311242Skas minit() 2321242Skas { 2331242Skas register struct xtrahash *xp, **tp; 2341242Skas 2351242Skas midfree = 0; 2361242Skas tp = &xtab[0]; 2371242Skas for (xp = &xtrahash[0]; xp < &xtrahash[XHSIZE]; xp++) { 2381242Skas xp->xh_name = NOSTR; 2391242Skas xp->xh_mid = 0; 2401242Skas xp->xh_attnet = 0; 2411242Skas *tp++ = (struct xtrahash *) 0; 2421242Skas } 2431242Skas } 2441242Skas 2451242Skas /* 2461242Skas * Stash a net name in the extra host hash table. 2471242Skas * If a new entry is put in the hash table, deduce what 2481242Skas * net the machine is attached to from the net character. 2491242Skas * 2501242Skas * If the machine is already known, add the given attached 2511242Skas * net to those already known. 2521242Skas */ 2531242Skas 2541242Skas mstash(name, attnet) 2551242Skas char name[]; 2561242Skas { 2571242Skas register struct xtrahash *xp; 2581242Skas struct xtrahash *xlocate(); 2594337Skurt int x; 2601242Skas 2611242Skas xp = xlocate(name); 2621242Skas if (xp == (struct xtrahash *) 0) { 2631242Skas printf("Ran out of machine id spots\n"); 2641242Skas return(0); 2651242Skas } 2661242Skas if (xp->xh_name == NOSTR) { 2671242Skas if (midfree >= XHSIZE) { 2681242Skas printf("Out of machine ids\n"); 2691242Skas return(0); 2701242Skas } 2711242Skas xtab[midfree] = xp; 2721242Skas xp->xh_name = savestr(name); 2731242Skas xp->xh_mid = 0200 + midfree++; 2741242Skas } 2754337Skurt x = ntype(attnet); 2764337Skurt if (x == 0) 2771242Skas xp->xh_attnet |= SN; 2784337Skurt else 2794337Skurt xp->xh_attnet |= x; 2801242Skas return(xp->xh_mid); 2811242Skas } 2821242Skas 2831242Skas /* 2841242Skas * Search for the given name in the hash table 2851242Skas * and return the pointer to it if found, or to the first 2861242Skas * empty slot if not found. 2871242Skas * 2881242Skas * If no free slots can be found, return 0. 2891242Skas */ 2901242Skas 2911242Skas struct xtrahash * 2921242Skas xlocate(name) 2931242Skas char name[]; 2941242Skas { 2951242Skas register int h, q, i; 2961242Skas register char *cp; 2971242Skas register struct xtrahash *xp; 2981242Skas 2991242Skas for (h = 0, cp = name; *cp; h = (h << 2) + *cp++) 3001242Skas ; 3011242Skas if (h < 0 && (h = -h) < 0) 3021242Skas h = 0; 3031242Skas h = h % XHSIZE; 3041242Skas cp = name; 3051242Skas for (i = 0, q = 0; q < XHSIZE; i++, q = i * i) { 3061242Skas xp = &xtrahash[(h + q) % XHSIZE]; 3071242Skas if (xp->xh_name == NOSTR) 3081242Skas return(xp); 3091242Skas if (strcmp(cp, xp->xh_name) == 0) 3101242Skas return(xp); 3111242Skas if (h - q < 0) 31223466Slepreau h += XHSIZE; 3131242Skas xp = &xtrahash[(h - q) % XHSIZE]; 3141242Skas if (xp->xh_name == NOSTR) 3151242Skas return(xp); 3161242Skas if (strcmp(cp, xp->xh_name) == 0) 3171242Skas return(xp); 3181242Skas } 3191242Skas return((struct xtrahash *) 0); 3201242Skas } 3211242Skas 3221242Skas /* 3231242Skas * Return the name from the extra host hash table corresponding 3241242Skas * to the passed machine id. 3251242Skas */ 3261242Skas 3271242Skas char * 3281242Skas mlook(mid) 3291242Skas { 3301242Skas register int m; 3311242Skas 3321242Skas if ((mid & 0200) == 0) 3331242Skas return(NOSTR); 3341242Skas m = mid & 0177; 3351242Skas if (m >= midfree) { 3361242Skas printf("Use made of undefined machine id\n"); 3371242Skas return(NOSTR); 3381242Skas } 3391242Skas return(xtab[m]->xh_name); 3401242Skas } 3411242Skas 3421242Skas /* 3431242Skas * Return the bit mask of net's that the given extra host machine 3441242Skas * id has so far. 3451242Skas */ 3461242Skas 3471242Skas mtype(mid) 3481242Skas { 3491242Skas register int m; 3501242Skas 3511242Skas if ((mid & 0200) == 0) 3521242Skas return(0); 3531242Skas m = mid & 0177; 3541242Skas if (m >= midfree) { 3551242Skas printf("Use made of undefined machine id\n"); 3561242Skas return(0); 3571242Skas } 3581242Skas return(xtab[m]->xh_attnet); 3591242Skas } 3601242Skas 3611242Skas /* 3621242Skas * Take a network name and optimize it. This gloriously messy 3633915Skurt * operation takes place as follows: the name with machine names 3641242Skas * in it is tokenized by mapping each machine name into a single 3651242Skas * character machine id (netlook). The separator characters (network 3661242Skas * metacharacters) are left intact. The last component of the network 3671242Skas * name is stripped off and assumed to be the destination user name -- 3681242Skas * it does not participate in the optimization. As an example, the 3691242Skas * name "research!vax135!research!ucbvax!bill" becomes, tokenized, 3701242Skas * "r!x!r!v!" and "bill" A low level routine, optim1, fixes up the 3711242Skas * network part (eg, "r!x!r!v!"), then we convert back to network 3721242Skas * machine names and tack the user name on the end. 3731242Skas * 3741242Skas * The result of this is copied into the parameter "name" 3751242Skas */ 3761242Skas 3771242Skas optim(net, name) 3781242Skas char net[], name[]; 3791242Skas { 3801242Skas char netcomp[BUFSIZ], netstr[40], xfstr[40]; 3811242Skas register char *cp, *cp2; 3821242Skas register int c; 3831242Skas 3841242Skas strcpy(netstr, ""); 3851242Skas cp = net; 3861242Skas for (;;) { 3871242Skas /* 3881242Skas * Rip off next path component into netcomp 3891242Skas */ 3901242Skas cp2 = netcomp; 3911242Skas while (*cp && !any(*cp, metanet)) 3921242Skas *cp2++ = *cp++; 3931242Skas *cp2 = 0; 3941242Skas /* 3951242Skas * If we hit null byte, then we just scanned 3961242Skas * the destination user name. Go off and optimize 3971242Skas * if its so. 3981242Skas */ 3991242Skas if (*cp == 0) 4001242Skas break; 4011242Skas if ((c = netlook(netcomp, *cp)) == 0) { 4021242Skas printf("No host named \"%s\"\n", netcomp); 4031242Skas err: 4041242Skas strcpy(name, net); 4051242Skas return; 4061242Skas } 4071242Skas stradd(netstr, c); 4081242Skas stradd(netstr, *cp++); 4091242Skas /* 4101242Skas * If multiple network separators given, 4111242Skas * throw away the extras. 4121242Skas */ 4131242Skas while (any(*cp, metanet)) 4141242Skas cp++; 4151242Skas } 4161242Skas if (strlen(netcomp) == 0) { 4171242Skas printf("net name syntax\n"); 4181242Skas goto err; 4191242Skas } 4201242Skas optim1(netstr, xfstr); 4211242Skas 4221242Skas /* 4231242Skas * Convert back to machine names. 4241242Skas */ 4251242Skas 4261242Skas cp = xfstr; 4271242Skas strcpy(name, ""); 4281242Skas while (*cp) { 4291242Skas if ((cp2 = netname(*cp++)) == NOSTR) { 4301242Skas printf("Made up bad net name\n"); 4314333Skurt printf("Machine code %c (0%o)\n", cp[-1], cp[-1]); 4324333Skurt printf("Sorry -- dumping now. Alert K. Shoens\n"); 433*31142Sedward core(); 4341242Skas goto err; 4351242Skas } 4361242Skas strcat(name, cp2); 4371242Skas stradd(name, *cp++); 4381242Skas } 4391242Skas strcat(name, netcomp); 4401242Skas } 4411242Skas 4421242Skas /* 4431242Skas * Take a string of network machine id's and separators and 4441242Skas * optimize them. We process these by pulling off maximal 4451242Skas * leading strings of the same type, passing these to the appropriate 4461242Skas * optimizer and concatenating the results. 4471242Skas */ 4481242Skas 4491242Skas optim1(netstr, name) 4501242Skas char netstr[], name[]; 4511242Skas { 4521242Skas char path[40], rpath[40]; 4531242Skas register char *cp, *cp2; 4541242Skas register int tp, nc; 4551242Skas 4561242Skas cp = netstr; 4571242Skas prefer(cp); 4584342Skurt strcpy(name, ""); 4593915Skurt /* 4603915Skurt * If the address ultimately points back to us, 4613915Skurt * just return a null network path. 4623915Skurt */ 4633915Skurt if (strlen(cp) > 1 && cp[strlen(cp) - 2] == LOCAL) 4643915Skurt return; 4651242Skas while (*cp != 0) { 4661242Skas strcpy(path, ""); 4671242Skas tp = ntype(cp[1]); 4681242Skas nc = cp[1]; 4691242Skas while (*cp && tp == ntype(cp[1])) { 4701242Skas stradd(path, *cp++); 4711242Skas cp++; 4721242Skas } 4731242Skas switch (netkind(tp)) { 4741242Skas default: 4751242Skas strcpy(rpath, path); 4761242Skas break; 4771242Skas 4781242Skas case IMPLICIT: 4791242Skas optimimp(path, rpath); 4801242Skas break; 4811242Skas 4821242Skas case EXPLICIT: 4831242Skas optimex(path, rpath); 4841242Skas break; 4851242Skas } 4861242Skas for (cp2 = rpath; *cp2 != 0; cp2++) { 4871242Skas stradd(name, *cp2); 4881242Skas stradd(name, nc); 4891242Skas } 4901242Skas } 4911242Skas optiboth(name); 4921242Skas prefer(name); 4931242Skas } 4941242Skas 4951242Skas /* 4961242Skas * Return the network of the separator -- 4971242Skas * AN for arpa net 4981242Skas * BN for Bell labs net 4991242Skas * SN for Schmidt (berkeley net) 5001242Skas * 0 if we don't know. 5011242Skas */ 5021242Skas 5031242Skas ntype(nc) 5041242Skas register int nc; 5051242Skas { 5067566Skurt register struct ntypetab *np; 5071242Skas 5087566Skurt for (np = ntypetab; np->nt_char != 0; np++) 5094337Skurt if (np->nt_char == nc) 5107566Skurt return(np->nt_bcode); 5114337Skurt return(0); 5121242Skas } 5131242Skas 5141242Skas /* 5151242Skas * Return the kind of routing used for the particular net 5161242Skas * EXPLICIT means explicitly routed 5171242Skas * IMPLICIT means implicitly routed 5181242Skas * 0 means don't know 5191242Skas */ 5201242Skas 5211242Skas netkind(nt) 5221242Skas register int nt; 5231242Skas { 5247566Skurt register struct nkindtab *np; 5251242Skas 5267566Skurt for (np = nkindtab; np->nk_type != 0; np++) 5274337Skurt if (np->nk_type == nt) 5284337Skurt return(np->nk_kind); 5294337Skurt return(0); 5301242Skas } 5311242Skas 5321242Skas /* 5331242Skas * Do name optimization for an explicitly routed network (eg BTL network). 5341242Skas */ 5351242Skas 5361242Skas optimex(net, name) 5371242Skas char net[], name[]; 5381242Skas { 5391242Skas register char *cp, *rp; 5401242Skas register int m; 5411242Skas 5421242Skas strcpy(name, net); 5431242Skas cp = name; 5441242Skas if (strlen(cp) == 0) 5451242Skas return(-1); 5461242Skas if (cp[strlen(cp)-1] == LOCAL) { 5471242Skas name[0] = 0; 5481242Skas return(0); 5491242Skas } 5501242Skas for (cp = name; *cp; cp++) { 5511242Skas m = *cp; 5521242Skas rp = rindex(cp+1, m); 5531242Skas if (rp != NOSTR) 5541242Skas strcpy(cp, rp); 5551242Skas } 5561242Skas return(0); 5571242Skas } 5581242Skas 5591242Skas /* 5601242Skas * Do name optimization for implicitly routed network (eg, arpanet, 5611242Skas * Berkeley network) 5621242Skas */ 5631242Skas 5641242Skas optimimp(net, name) 5651242Skas char net[], name[]; 5661242Skas { 5671242Skas register char *cp; 5681242Skas register int m; 5691242Skas 5701242Skas cp = net; 5711242Skas if (strlen(cp) == 0) 5721242Skas return(-1); 5731242Skas m = cp[strlen(cp) - 1]; 5741242Skas if (m == LOCAL) { 5751242Skas strcpy(name, ""); 5761242Skas return(0); 5771242Skas } 5781242Skas name[0] = m; 5791242Skas name[1] = 0; 5801242Skas return(0); 5811242Skas } 5821242Skas 5831242Skas /* 5841242Skas * Perform global optimization on the given network path. 5851242Skas * The trick here is to look ahead to see if there are any loops 5861242Skas * in the path and remove them. The interpretation of loops is 5871242Skas * more strict here than in optimex since both the machine and net 5881242Skas * type must match. 5891242Skas */ 5901242Skas 5911242Skas optiboth(net) 5921242Skas char net[]; 5931242Skas { 5941242Skas register char *cp, *cp2; 5951242Skas char *rpair(); 5961242Skas 5971242Skas cp = net; 5981242Skas if (strlen(cp) == 0) 5991242Skas return; 6001242Skas if ((strlen(cp) % 2) != 0) { 6011242Skas printf("Strange arg to optiboth\n"); 6021242Skas return; 6031242Skas } 6041242Skas while (*cp) { 6051242Skas cp2 = rpair(cp+2, *cp); 6061242Skas if (cp2 != NOSTR) 6071242Skas strcpy(cp, cp2); 6081242Skas cp += 2; 6091242Skas } 6101242Skas } 6111242Skas 6121242Skas /* 6131242Skas * Find the rightmost instance of the given (machine, type) pair. 6141242Skas */ 6151242Skas 6161242Skas char * 6171242Skas rpair(str, mach) 6181242Skas char str[]; 6191242Skas { 6201242Skas register char *cp, *last; 6211242Skas 62224756Sserge cp = str; 6231242Skas last = NOSTR; 6241242Skas while (*cp) { 6251242Skas if (*cp == mach) 6261242Skas last = cp; 6271242Skas cp += 2; 6281242Skas } 6291242Skas return(last); 6301242Skas } 6311242Skas 6321242Skas /* 6331242Skas * Change the network separators in the given network path 6341242Skas * to the preferred network transmission means. 6351242Skas */ 6361242Skas 6371242Skas prefer(name) 6381242Skas char name[]; 6391242Skas { 6401242Skas register char *cp; 6411242Skas register int state, n; 6421242Skas 6431242Skas state = LOCAL; 6441242Skas for (cp = name; *cp; cp += 2) { 6451242Skas n = best(state, *cp); 6461242Skas if (n) 6471242Skas cp[1] = n; 6481242Skas state = *cp; 6491242Skas } 6501242Skas } 6511242Skas 6521242Skas /* 6531242Skas * Return the best network separator for the given machine pair. 6541242Skas */ 6551242Skas 6561242Skas best(src, dest) 6571242Skas { 6581242Skas register int dtype, stype; 6591242Skas register struct netorder *np; 6601242Skas 6611242Skas stype = nettype(src); 6621242Skas dtype = nettype(dest); 6633915Skurt fflush(stdout); 6641242Skas if (stype == 0 || dtype == 0) { 6651242Skas printf("ERROR: unknown internal machine id\n"); 6661242Skas return(0); 6671242Skas } 6683915Skurt if ((stype & dtype) == 0) 6691242Skas return(0); 6701242Skas np = &netorder[0]; 6711242Skas while ((np->no_stat & stype & dtype) == 0) 6721242Skas np++; 6731242Skas return(np->no_char); 6741242Skas } 6751242Skas 6769069Smckusick #ifdef GETHOST 6771242Skas /* 6788014Smckusick * Initialize the network name of the current host. 6798014Smckusick */ 6808014Smckusick inithost() 6818014Smckusick { 6828014Smckusick register struct netmach *np; 6838014Smckusick static char host[64]; 6848014Smckusick 6858014Smckusick gethostname(host, sizeof host); 6868014Smckusick for (np = netmach; np->nt_machine != 0; np++) 6878014Smckusick if (strcmp(np->nt_machine, EMPTY) == 0) 6888014Smckusick break; 6898014Smckusick if (np->nt_machine == 0) { 6908014Smckusick printf("Cannot find empty slot for dynamic host entry\n"); 6918014Smckusick exit(1); 6928014Smckusick } 6938014Smckusick np->nt_machine = host; 6948014Smckusick } 6959069Smckusick #endif GETHOST 6968014Smckusick 6978014Smckusick /* 6981242Skas * Code to twist around arpa net names. 6991242Skas */ 7001242Skas 7011242Skas #define WORD 257 /* Token for a string */ 7021242Skas 7031242Skas static char netbuf[256]; 7041242Skas static char *yylval; 7051242Skas 7061242Skas /* 7071242Skas * Reverse all of the arpa net addresses in the given name to 7081242Skas * be of the form "host @ user" instead of "user @ host" 7091242Skas * This function is its own inverse. 7101242Skas */ 7111242Skas 7121242Skas char * 7131242Skas revarpa(str) 7141242Skas char str[]; 7151242Skas { 7161242Skas 7171242Skas if (yyinit(str) < 0) 7181242Skas return(NOSTR); 7191242Skas if (name()) 7201242Skas return(NOSTR); 7211242Skas if (strcmp(str, netbuf) == 0) 7221242Skas return(str); 7231242Skas return(savestr(netbuf)); 7241242Skas } 7251242Skas 7261242Skas /* 7271242Skas * Parse (by recursive descent) network names, using the following grammar: 7281242Skas * name: 7291242Skas * term {':' term} 7301242Skas * term {'^' term} 7311242Skas * term {'!' term} 7321242Skas * term '@' name 7331242Skas * term '%' name 7341242Skas * 7351242Skas * term: 7361242Skas * string of characters. 7371242Skas */ 7381242Skas 7391242Skas name() 7401242Skas { 7411242Skas register int t; 7421242Skas register char *cp; 7431242Skas 7441242Skas for (;;) { 7451242Skas t = yylex(); 7461242Skas if (t != WORD) 7471242Skas return(-1); 7481242Skas cp = yylval; 7491242Skas t = yylex(); 7501242Skas switch (t) { 7511242Skas case 0: 7521242Skas strcat(netbuf, cp); 7531242Skas return(0); 7541242Skas 7551242Skas case '@': 7561242Skas case '%': 7571242Skas if (name()) 7581242Skas return(-1); 7591242Skas stradd(netbuf, '@'); 7601242Skas strcat(netbuf, cp); 7611242Skas return(0); 7621242Skas 7631242Skas case WORD: 7641242Skas return(-1); 7651242Skas 7661242Skas default: 7671242Skas strcat(netbuf, cp); 7681242Skas stradd(netbuf, t); 7691242Skas } 7701242Skas } 7711242Skas } 7721242Skas 7731242Skas /* 7741242Skas * Scanner for network names. 7751242Skas */ 7761242Skas 7771242Skas static char *charp; /* Current input pointer */ 7781242Skas static int nexttok; /* Salted away next token */ 7791242Skas 7801242Skas /* 7811242Skas * Initialize the network name scanner. 7821242Skas */ 7831242Skas 7841242Skas yyinit(str) 7851242Skas char str[]; 7861242Skas { 7871242Skas static char lexbuf[BUFSIZ]; 7881242Skas 7891242Skas netbuf[0] = 0; 7901242Skas if (strlen(str) >= sizeof lexbuf - 1) 7911242Skas return(-1); 7921242Skas nexttok = 0; 7931242Skas strcpy(lexbuf, str); 7941242Skas charp = lexbuf; 7951242Skas return(0); 7961242Skas } 7971242Skas 7981242Skas /* 7991242Skas * Scan and return a single token. 8001242Skas * yylval is set to point to a scanned string. 8011242Skas */ 8021242Skas 8031242Skas yylex() 8041242Skas { 8051242Skas register char *cp, *dot; 8061242Skas register int s; 8071242Skas 8081242Skas if (nexttok) { 8091242Skas s = nexttok; 8101242Skas nexttok = 0; 8111242Skas return(s); 8121242Skas } 8131242Skas cp = charp; 8141242Skas while (*cp && isspace(*cp)) 8151242Skas cp++; 8161242Skas if (*cp == 0) 8171242Skas return(0); 8184337Skurt if (any(*cp, metanet)) { 8191242Skas charp = cp+1; 8201242Skas return(*cp); 8211242Skas } 8221242Skas dot = cp; 8234337Skurt while (*cp && !any(*cp, metanet) && !any(*cp, " \t")) 8241242Skas cp++; 8254337Skurt if (any(*cp, metanet)) 8261242Skas nexttok = *cp; 8271242Skas if (*cp == 0) 8281242Skas charp = cp; 8291242Skas else 8301242Skas charp = cp+1; 8311242Skas *cp = 0; 8321242Skas yylval = dot; 8331242Skas return(WORD); 8341242Skas } 835