10Sstevel@tonic-gate /* 20Sstevel@tonic-gate * CDDL HEADER START 30Sstevel@tonic-gate * 40Sstevel@tonic-gate * The contents of this file are subject to the terms of the 50Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 60Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 70Sstevel@tonic-gate * with the License. 80Sstevel@tonic-gate * 90Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 100Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 110Sstevel@tonic-gate * See the License for the specific language governing permissions 120Sstevel@tonic-gate * and limitations under the License. 130Sstevel@tonic-gate * 140Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 150Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 160Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 170Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 180Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 190Sstevel@tonic-gate * 200Sstevel@tonic-gate * CDDL HEADER END 210Sstevel@tonic-gate */ 220Sstevel@tonic-gate /* 230Sstevel@tonic-gate * Copyright 1998 Sun Microsystems, Inc. All rights reserved. 240Sstevel@tonic-gate * Use is subject to license terms. 250Sstevel@tonic-gate */ 260Sstevel@tonic-gate 270Sstevel@tonic-gate /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 280Sstevel@tonic-gate /* All Rights Reserved */ 290Sstevel@tonic-gate 300Sstevel@tonic-gate 310Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 320Sstevel@tonic-gate 330Sstevel@tonic-gate /* 340Sstevel@tonic-gate * mailx -- a modified version of a University of California at Berkeley 350Sstevel@tonic-gate * mail program 360Sstevel@tonic-gate * 370Sstevel@tonic-gate * Network name modification routines. 380Sstevel@tonic-gate */ 390Sstevel@tonic-gate 400Sstevel@tonic-gate #include "rcv.h" 410Sstevel@tonic-gate #include "configdefs.h" 420Sstevel@tonic-gate #include <locale.h> 430Sstevel@tonic-gate 440Sstevel@tonic-gate static char *arpafix(char name[], char from[]); 450Sstevel@tonic-gate static char *lasthost(char *addr); 460Sstevel@tonic-gate static char *makeremote(char name[], char from[]); 470Sstevel@tonic-gate static int mstash(char name[], int attnet); 480Sstevel@tonic-gate static int mtype(int mid); 490Sstevel@tonic-gate static int netlook(char machine[], int attnet); 500Sstevel@tonic-gate static int nettype(int mid); 510Sstevel@tonic-gate static int ntype(register int nc); 520Sstevel@tonic-gate static void stradd(register char *str, int n, register int c); 530Sstevel@tonic-gate static char *tackon(char *sys, char *rest); 540Sstevel@tonic-gate static struct xtrahash *xlocate(char name[]); 550Sstevel@tonic-gate #ifdef OPTIM 560Sstevel@tonic-gate static char best(int src, int dest); 570Sstevel@tonic-gate static char *mlook(int mid); 580Sstevel@tonic-gate static int netkind(register int nt); 590Sstevel@tonic-gate static void optiboth(char net[]); 600Sstevel@tonic-gate static void optim(char net[], char name[]); 610Sstevel@tonic-gate static void optim1(char netstr[], char name[]); 620Sstevel@tonic-gate static int optimex(char net[], char name[]); 630Sstevel@tonic-gate static int optimimp(char net[], char name[]); 640Sstevel@tonic-gate static void prefer(char name[]); 650Sstevel@tonic-gate static char *rpair(char str[], int mach); 660Sstevel@tonic-gate #endif 670Sstevel@tonic-gate 680Sstevel@tonic-gate /* 690Sstevel@tonic-gate * Map a name into the correct network "view" of the 700Sstevel@tonic-gate * name. This is done by prepending the name with the 710Sstevel@tonic-gate * network address of the sender, then optimizing away 720Sstevel@tonic-gate * nonsense. 730Sstevel@tonic-gate */ 740Sstevel@tonic-gate 750Sstevel@tonic-gate char * 760Sstevel@tonic-gate netmap(char name[], char from[]) 770Sstevel@tonic-gate { 780Sstevel@tonic-gate char nbuf[BUFSIZ], ret[BUFSIZ]; 790Sstevel@tonic-gate register char *cp, *oname; 800Sstevel@tonic-gate 810Sstevel@tonic-gate if (debug) fprintf(stderr, "netmap(name '%s', from '%s')\n", name, from); 820Sstevel@tonic-gate if (strlen(from) == 0) 830Sstevel@tonic-gate return(name); /* "from" is empty - can't do anything */ 840Sstevel@tonic-gate 850Sstevel@tonic-gate if (strcmp(from, name) == 0) 860Sstevel@tonic-gate return(name); /* "from" and "name" are the same, do nothing */ 870Sstevel@tonic-gate 880Sstevel@tonic-gate /* 890Sstevel@tonic-gate * If the name contains an "@" or a "%", remove it and the host 900Sstevel@tonic-gate * following it if that host is "known". 910Sstevel@tonic-gate */ 920Sstevel@tonic-gate if (any('@', name) || any('%', name)) 930Sstevel@tonic-gate return(arpafix(name, from)); 940Sstevel@tonic-gate 950Sstevel@tonic-gate /* 960Sstevel@tonic-gate * If the sender contains a "@" or a "%", make "name" into an 970Sstevel@tonic-gate * address on that host, on the presumption that it should 980Sstevel@tonic-gate * really have read "name@from" when we received the message 990Sstevel@tonic-gate * rather than just "name". 1000Sstevel@tonic-gate */ 1010Sstevel@tonic-gate if (any('@', from) || any('%', from)) 1020Sstevel@tonic-gate return(unuucp(makeremote(name, from))); 1030Sstevel@tonic-gate if (value("onehop") && (cp = strchr(name, '!')) && cp > name) { 1040Sstevel@tonic-gate /* 1050Sstevel@tonic-gate * "onehop" is set, meaning all machines are one UUCP 1060Sstevel@tonic-gate * hop away (fat chance, in this day and age), and "name" 1070Sstevel@tonic-gate * is a UUCP path rather than just a name. Leave it alone. 1080Sstevel@tonic-gate */ 1090Sstevel@tonic-gate nstrcpy(nbuf, sizeof (nbuf), name); 1100Sstevel@tonic-gate } else { 1110Sstevel@tonic-gate from = tackon(host, from); 1120Sstevel@tonic-gate *strrchr(from, '!') = 0; 1130Sstevel@tonic-gate name = tackon(lasthost(from), name); 1140Sstevel@tonic-gate while (((cp = lasthost(from)) != 0) && ishost(cp, name)) { 1150Sstevel@tonic-gate oname = name; 1160Sstevel@tonic-gate name = strchr(name, '!') + 1; 1170Sstevel@tonic-gate if (cp == from) { 1180Sstevel@tonic-gate from[strlen(from)] = '!'; 1190Sstevel@tonic-gate if (value("mustbang") && !strchr(name, '!')) 1200Sstevel@tonic-gate name = oname; 1210Sstevel@tonic-gate return(unuucp(name)); 1220Sstevel@tonic-gate } 1230Sstevel@tonic-gate *--cp = 0; 1240Sstevel@tonic-gate } 1250Sstevel@tonic-gate from[strlen(from)] = '!'; 1260Sstevel@tonic-gate from = strchr(from, '!') + 1; 1270Sstevel@tonic-gate snprintf(nbuf, sizeof (nbuf), "%s!%s", from, name); 1280Sstevel@tonic-gate } 1290Sstevel@tonic-gate if (debug) fprintf(stderr, "before optim, nbuf '%s'\n", name); 1300Sstevel@tonic-gate #ifdef OPTIM 1310Sstevel@tonic-gate if ((cp = value("conv"))==NOSTR || strcmp(cp, "optimize") != 0) 1320Sstevel@tonic-gate nstrcpy(ret, sizeof (ret), nbuf); 1330Sstevel@tonic-gate else 1340Sstevel@tonic-gate optim(nbuf, ret); 1350Sstevel@tonic-gate #else 1360Sstevel@tonic-gate nstrcpy(ret, sizeof (ret), nbuf); 137*18Srobbin #endif /* OPTIM */ 1380Sstevel@tonic-gate if (debug) fprintf(stderr, "after optim, nbuf '%s', ret '%s'\n", nbuf, ret); 1390Sstevel@tonic-gate cp = ret; 1400Sstevel@tonic-gate if (debug) fprintf(stderr, "wind up with '%s'\n", name); 1410Sstevel@tonic-gate if (!icequal(name, cp)) 1420Sstevel@tonic-gate return(unuucp((char *) savestr(cp))); 1430Sstevel@tonic-gate return(unuucp(name)); 1440Sstevel@tonic-gate } 1450Sstevel@tonic-gate 1460Sstevel@tonic-gate /* 1470Sstevel@tonic-gate * Stick a host on the beginning of a uucp 1480Sstevel@tonic-gate * address if it isn't there already. 1490Sstevel@tonic-gate */ 1500Sstevel@tonic-gate static char * 1510Sstevel@tonic-gate tackon(char *sys, char *rest) 1520Sstevel@tonic-gate { 1530Sstevel@tonic-gate while (*rest == '!') 1540Sstevel@tonic-gate rest++; 1550Sstevel@tonic-gate if (!ishost(sys, rest)) { 1560Sstevel@tonic-gate char *r = (char *)salloc(strlen(sys) + strlen(rest) + 2); 1570Sstevel@tonic-gate sprintf(r, "%s!%s", sys, rest); 1580Sstevel@tonic-gate rest = r; 1590Sstevel@tonic-gate } 1600Sstevel@tonic-gate return rest; 1610Sstevel@tonic-gate } 1620Sstevel@tonic-gate 1630Sstevel@tonic-gate /* 1640Sstevel@tonic-gate * Check equality of the first host in a uucp address. 1650Sstevel@tonic-gate */ 1660Sstevel@tonic-gate int 1670Sstevel@tonic-gate ishost(char *sys, char *rest) 1680Sstevel@tonic-gate { 1690Sstevel@tonic-gate while (*sys && *sys == *rest) 1700Sstevel@tonic-gate sys++, rest++; 1710Sstevel@tonic-gate return(*sys == 0 && *rest == '!'); 1720Sstevel@tonic-gate } 1730Sstevel@tonic-gate 1740Sstevel@tonic-gate /* 1750Sstevel@tonic-gate * Return last host in a uucp address. 1760Sstevel@tonic-gate */ 1770Sstevel@tonic-gate static char * 1780Sstevel@tonic-gate lasthost(char *addr) 1790Sstevel@tonic-gate { 1800Sstevel@tonic-gate char *r = strrchr(addr, '!'); 1810Sstevel@tonic-gate return r ? ++r : addr; 1820Sstevel@tonic-gate } 1830Sstevel@tonic-gate 1840Sstevel@tonic-gate /* 1850Sstevel@tonic-gate * Optionally translate an old format uucp name into a new one, e.g. 1860Sstevel@tonic-gate * "mach1!mach2!user" becomes "user@mach2.UUCP". This optional because 1870Sstevel@tonic-gate * some information is necessarily lost (e.g. the route it got here 1880Sstevel@tonic-gate * via) and if we don't have the host in our routing tables, we lose. 1890Sstevel@tonic-gate * XXX THIS IS NO LONGER VALID WITH THE NEW UUCP PROJECT PLANS TO 1900Sstevel@tonic-gate * REGISTER UUCP HOSTS IN THE STANDARD INTERNET NAMESPACE, E.G. 1910Sstevel@tonic-gate * ihnp4 BECOMES "ihnp4.att.com". 1920Sstevel@tonic-gate */ 1930Sstevel@tonic-gate char * 1940Sstevel@tonic-gate unuucp(char *name) 1950Sstevel@tonic-gate { 1960Sstevel@tonic-gate register char *np, *hp, *cp; 1970Sstevel@tonic-gate char result[100]; 1980Sstevel@tonic-gate char tname[300]; 1990Sstevel@tonic-gate 2000Sstevel@tonic-gate if (UnUUCP==0 && 2010Sstevel@tonic-gate ((cp = value("conv"))==NOSTR || strcmp(cp, "internet"))) 2020Sstevel@tonic-gate return name; 2030Sstevel@tonic-gate if (debug) fprintf(stderr, "unuucp(%s)\n", name); 2040Sstevel@tonic-gate nstrcpy(tname, sizeof (tname), name); 2050Sstevel@tonic-gate np = strrchr(tname, '!'); 2060Sstevel@tonic-gate if (np == NOSTR) 2070Sstevel@tonic-gate return name; 2080Sstevel@tonic-gate *np++ = 0; 2090Sstevel@tonic-gate hp = strrchr(tname, '!'); 2100Sstevel@tonic-gate if (hp == NOSTR) 2110Sstevel@tonic-gate hp = tname; 2120Sstevel@tonic-gate else 2130Sstevel@tonic-gate *hp++ = 0; 2140Sstevel@tonic-gate cp = strchr(np, '@'); 2150Sstevel@tonic-gate if (cp == NOSTR) 2160Sstevel@tonic-gate cp = strchr(np, '%'); 2170Sstevel@tonic-gate if (cp) 2180Sstevel@tonic-gate *cp = 0; 2190Sstevel@tonic-gate if (debug) fprintf(stderr, "host %s, name %s\n", hp, np); 2200Sstevel@tonic-gate snprintf(result, sizeof (result), "%s@%s.UUCP", np, hp); 2210Sstevel@tonic-gate if (debug) fprintf(stderr, "unuucp returns %s\n", result); 2220Sstevel@tonic-gate return savestr(result); 2230Sstevel@tonic-gate } 2240Sstevel@tonic-gate 2250Sstevel@tonic-gate /* 2260Sstevel@tonic-gate * Turn a network machine name into a unique character 2270Sstevel@tonic-gate */ 2280Sstevel@tonic-gate static int 2290Sstevel@tonic-gate netlook(char machine[], int attnet) 2300Sstevel@tonic-gate { 2310Sstevel@tonic-gate register struct netmach *np; 2320Sstevel@tonic-gate register char *cp, *cp2; 2330Sstevel@tonic-gate char nbuf[BUFSIZ]; 2340Sstevel@tonic-gate 2350Sstevel@tonic-gate /* 2360Sstevel@tonic-gate * Make into lower case. 2370Sstevel@tonic-gate */ 2380Sstevel@tonic-gate for (cp = machine, cp2 = nbuf; 2390Sstevel@tonic-gate *cp && cp2 < &nbuf[BUFSIZ-1]; 2400Sstevel@tonic-gate *cp2++ = tolower(*cp++)) 2410Sstevel@tonic-gate /*nothing*/; 2420Sstevel@tonic-gate *cp2 = 0; 2430Sstevel@tonic-gate 2440Sstevel@tonic-gate /* 2450Sstevel@tonic-gate * If a single letter machine, look through those first. 2460Sstevel@tonic-gate */ 2470Sstevel@tonic-gate 2480Sstevel@tonic-gate if (strlen(nbuf) == 1) 2490Sstevel@tonic-gate for (np = netmach; np->nt_mid != 0; np++) 2500Sstevel@tonic-gate if (np->nt_mid == nbuf[0]) 2510Sstevel@tonic-gate return(nbuf[0]); 2520Sstevel@tonic-gate 2530Sstevel@tonic-gate /* 2540Sstevel@tonic-gate * Look for usual name 2550Sstevel@tonic-gate */ 2560Sstevel@tonic-gate 2570Sstevel@tonic-gate for (np = netmach; np->nt_mid != 0; np++) 2580Sstevel@tonic-gate if (strcmp(np->nt_machine, nbuf) == 0) 2590Sstevel@tonic-gate return(np->nt_mid); 2600Sstevel@tonic-gate 2610Sstevel@tonic-gate /* 2620Sstevel@tonic-gate * Look in side hash table. 2630Sstevel@tonic-gate */ 2640Sstevel@tonic-gate 2650Sstevel@tonic-gate return(mstash(nbuf, attnet)); 2660Sstevel@tonic-gate } 2670Sstevel@tonic-gate 2680Sstevel@tonic-gate #ifdef OPTIM 2690Sstevel@tonic-gate /* 2700Sstevel@tonic-gate * Turn a network unique character identifier into a network name. 2710Sstevel@tonic-gate */ 2720Sstevel@tonic-gate 2730Sstevel@tonic-gate static char * 2740Sstevel@tonic-gate netname(int mid) 2750Sstevel@tonic-gate { 2760Sstevel@tonic-gate register struct netmach *np; 2770Sstevel@tonic-gate 2780Sstevel@tonic-gate if (mid & 0200) 2790Sstevel@tonic-gate return(mlook(mid)); 2800Sstevel@tonic-gate for (np = netmach; np->nt_mid != 0; np++) 2810Sstevel@tonic-gate if (np->nt_mid == mid) 2820Sstevel@tonic-gate return(np->nt_machine); 2830Sstevel@tonic-gate return(NOSTR); 2840Sstevel@tonic-gate } 2850Sstevel@tonic-gate #endif 2860Sstevel@tonic-gate 2870Sstevel@tonic-gate /* 2880Sstevel@tonic-gate * Deal with arpa net addresses. The way this is done is strange. 2890Sstevel@tonic-gate * name contains an "@" or "%". Look up the machine after it in 2900Sstevel@tonic-gate * the hash table. If it isn't found, return name unmolested. 2910Sstevel@tonic-gate * If ???, return name unmolested. 2920Sstevel@tonic-gate * Otherwise, delete the "@" or "%" and the machine after it from 2930Sstevel@tonic-gate * name, and return the new string. 2940Sstevel@tonic-gate */ 2950Sstevel@tonic-gate static char * 2960Sstevel@tonic-gate arpafix(char name[], char from[]) 2970Sstevel@tonic-gate { 2980Sstevel@tonic-gate register char *cp; 2990Sstevel@tonic-gate register int arpamach; 3000Sstevel@tonic-gate char newname[BUFSIZ]; 3010Sstevel@tonic-gate 3020Sstevel@tonic-gate if (debug) { 3030Sstevel@tonic-gate fprintf(stderr, "arpafix(%s, %s)\n", name, from); 3040Sstevel@tonic-gate } 3050Sstevel@tonic-gate cp = strrchr(name, '@'); 3060Sstevel@tonic-gate if (cp == NOSTR) 3070Sstevel@tonic-gate cp = strrchr(name, '%'); 3080Sstevel@tonic-gate if (cp == NOSTR) { 3090Sstevel@tonic-gate fprintf(stderr, 3100Sstevel@tonic-gate gettext("Something's amiss -- no @ or %% in arpafix\n")); 3110Sstevel@tonic-gate return(name); 3120Sstevel@tonic-gate } 3130Sstevel@tonic-gate cp++; 3140Sstevel@tonic-gate arpamach = netlook(cp, '@'); 3150Sstevel@tonic-gate if (debug) 3160Sstevel@tonic-gate fprintf(stderr, 3170Sstevel@tonic-gate "cp '%s', arpamach %o, nettypes arpamach %o LOCAL %o\n", 3180Sstevel@tonic-gate cp, arpamach, nettype(arpamach), nettype(LOCAL)); 3190Sstevel@tonic-gate if (arpamach == 0) { 3200Sstevel@tonic-gate if (debug) 3210Sstevel@tonic-gate fprintf(stderr, "machine %s unknown, uses: %s\n", 3220Sstevel@tonic-gate cp, name); 3230Sstevel@tonic-gate return(name); 3240Sstevel@tonic-gate } 3250Sstevel@tonic-gate if (((nettype(arpamach) & nettype(LOCAL)) & ~AN) == 0) { 3260Sstevel@tonic-gate if (debug) 3270Sstevel@tonic-gate fprintf(stderr, "machine %s known but remote, uses: %s\n", 3280Sstevel@tonic-gate cp, name); 3290Sstevel@tonic-gate return(name); 3300Sstevel@tonic-gate } 3310Sstevel@tonic-gate nstrcpy(newname, sizeof (newname), name); 3320Sstevel@tonic-gate cp = strrchr(newname, '@'); 3330Sstevel@tonic-gate if (cp == NOSTR) 3340Sstevel@tonic-gate cp = strrchr(newname, '%'); 3350Sstevel@tonic-gate *cp = 0; 3360Sstevel@tonic-gate if (debug) fprintf(stderr, "local address, return '%s'\n", newname); 3370Sstevel@tonic-gate return(savestr(newname)); 3380Sstevel@tonic-gate } 3390Sstevel@tonic-gate 3400Sstevel@tonic-gate /* 3410Sstevel@tonic-gate * We have name with no @'s in it, and from with @'s. 3420Sstevel@tonic-gate * Assume that name is meaningful only on the site in from, 3430Sstevel@tonic-gate * and return "name@site_in_from". 3440Sstevel@tonic-gate */ 3450Sstevel@tonic-gate static char * 3460Sstevel@tonic-gate makeremote(char name[], char from[]) 3470Sstevel@tonic-gate { 3480Sstevel@tonic-gate register char *cp; 3490Sstevel@tonic-gate char rbuf[BUFSIZ]; 3500Sstevel@tonic-gate 3510Sstevel@tonic-gate if (!value("makeremote")) 3520Sstevel@tonic-gate return(name); 3530Sstevel@tonic-gate if (debug) fprintf(stderr, "makeremote(%s, %s) returns ", name, from); 3540Sstevel@tonic-gate cp = strrchr(from, '@'); 3550Sstevel@tonic-gate if (cp == NOSTR) 3560Sstevel@tonic-gate cp = strrchr(from, '%'); 3570Sstevel@tonic-gate snprintf(rbuf, sizeof (rbuf), "%s%s", name, cp); 3580Sstevel@tonic-gate if (debug) fprintf(stderr, "%s\n", rbuf); 3590Sstevel@tonic-gate return(savestr(rbuf)); 3600Sstevel@tonic-gate } 3610Sstevel@tonic-gate 3620Sstevel@tonic-gate /* 3630Sstevel@tonic-gate * Take a network machine descriptor and find the types of connected 3640Sstevel@tonic-gate * nets and return it. 3650Sstevel@tonic-gate */ 3660Sstevel@tonic-gate static int 3670Sstevel@tonic-gate nettype(int mid) 3680Sstevel@tonic-gate { 3690Sstevel@tonic-gate register struct netmach *np; 3700Sstevel@tonic-gate 3710Sstevel@tonic-gate if (mid & 0200) 3720Sstevel@tonic-gate return(mtype(mid)); 3730Sstevel@tonic-gate for (np = netmach; np->nt_mid != 0; np++) 3740Sstevel@tonic-gate if (np->nt_mid == mid) 3750Sstevel@tonic-gate return(np->nt_type); 3760Sstevel@tonic-gate return(0); 3770Sstevel@tonic-gate } 3780Sstevel@tonic-gate 3790Sstevel@tonic-gate /* 3800Sstevel@tonic-gate * Hashing routines to salt away machines seen scanning 3810Sstevel@tonic-gate * networks paths that we don't know about. 3820Sstevel@tonic-gate */ 3830Sstevel@tonic-gate 3840Sstevel@tonic-gate #define XHSIZE 97 /* Size of extra hash table */ 3850Sstevel@tonic-gate #define NXMID (XHSIZE*3/4) /* Max extra machines */ 3860Sstevel@tonic-gate 3870Sstevel@tonic-gate struct xtrahash { 3880Sstevel@tonic-gate char *xh_name; /* Name of machine */ 3890Sstevel@tonic-gate short xh_mid; /* Machine ID */ 3900Sstevel@tonic-gate short xh_attnet; /* Attached networks */ 3910Sstevel@tonic-gate } xtrahash[XHSIZE]; 3920Sstevel@tonic-gate 3930Sstevel@tonic-gate static struct xtrahash *xtab[XHSIZE]; /* F: mid-->machine name */ 3940Sstevel@tonic-gate 3950Sstevel@tonic-gate static short midfree; /* Next free machine id */ 3960Sstevel@tonic-gate 3970Sstevel@tonic-gate /* 3980Sstevel@tonic-gate * Initialize the extra host hash table. 3990Sstevel@tonic-gate * Called by sreset. 4000Sstevel@tonic-gate */ 4010Sstevel@tonic-gate void 4020Sstevel@tonic-gate minit(void) 4030Sstevel@tonic-gate { 4040Sstevel@tonic-gate register struct xtrahash *xp, **tp; 4050Sstevel@tonic-gate 4060Sstevel@tonic-gate midfree = 0; 4070Sstevel@tonic-gate tp = &xtab[0]; 4080Sstevel@tonic-gate for (xp = &xtrahash[0]; xp < &xtrahash[XHSIZE]; xp++) { 4090Sstevel@tonic-gate xp->xh_name = NOSTR; 4100Sstevel@tonic-gate xp->xh_mid = 0; 4110Sstevel@tonic-gate xp->xh_attnet = 0; 4120Sstevel@tonic-gate *tp++ = (struct xtrahash *) 0; 4130Sstevel@tonic-gate } 4140Sstevel@tonic-gate } 4150Sstevel@tonic-gate 4160Sstevel@tonic-gate /* 4170Sstevel@tonic-gate * Stash a net name in the extra host hash table. 4180Sstevel@tonic-gate * If a new entry is put in the hash table, deduce what 4190Sstevel@tonic-gate * net the machine is attached to from the net character. 4200Sstevel@tonic-gate * 4210Sstevel@tonic-gate * If the machine is already known, add the given attached 4220Sstevel@tonic-gate * net to those already known. 4230Sstevel@tonic-gate */ 4240Sstevel@tonic-gate static int 4250Sstevel@tonic-gate mstash(char name[], int attnet) 4260Sstevel@tonic-gate { 4270Sstevel@tonic-gate register struct xtrahash *xp; 4280Sstevel@tonic-gate int x; 4290Sstevel@tonic-gate 4300Sstevel@tonic-gate xp = xlocate(name); 4310Sstevel@tonic-gate if (xp == (struct xtrahash *) 0) { 4320Sstevel@tonic-gate printf(gettext("Ran out of machine id spots\n")); 4330Sstevel@tonic-gate return(0); 4340Sstevel@tonic-gate } 4350Sstevel@tonic-gate if (xp->xh_name == NOSTR) { 4360Sstevel@tonic-gate if (midfree >= XHSIZE) { 4370Sstevel@tonic-gate printf(gettext("Out of machine ids\n")); 4380Sstevel@tonic-gate return(0); 4390Sstevel@tonic-gate } 4400Sstevel@tonic-gate xtab[midfree] = xp; 4410Sstevel@tonic-gate xp->xh_name = savestr(name); 4420Sstevel@tonic-gate xp->xh_mid = 0200 + midfree++; 4430Sstevel@tonic-gate } 4440Sstevel@tonic-gate x = ntype(attnet); 4450Sstevel@tonic-gate if (x == 0) 4460Sstevel@tonic-gate xp->xh_attnet |= AN; 4470Sstevel@tonic-gate else 4480Sstevel@tonic-gate xp->xh_attnet |= x; 4490Sstevel@tonic-gate return(xp->xh_mid); 4500Sstevel@tonic-gate } 4510Sstevel@tonic-gate 4520Sstevel@tonic-gate /* 4530Sstevel@tonic-gate * Search for the given name in the hash table 4540Sstevel@tonic-gate * and return the pointer to it if found, or to the first 4550Sstevel@tonic-gate * empty slot if not found. 4560Sstevel@tonic-gate * 4570Sstevel@tonic-gate * If no free slots can be found, return 0. 4580Sstevel@tonic-gate */ 4590Sstevel@tonic-gate 4600Sstevel@tonic-gate static struct xtrahash * 4610Sstevel@tonic-gate xlocate(char name[]) 4620Sstevel@tonic-gate { 4630Sstevel@tonic-gate register int h, q, i; 4640Sstevel@tonic-gate register char *cp; 4650Sstevel@tonic-gate register struct xtrahash *xp; 4660Sstevel@tonic-gate 4670Sstevel@tonic-gate for (h = 0, cp = name; *cp; h = (h << 2) + *cp++) 4680Sstevel@tonic-gate ; 4690Sstevel@tonic-gate if (h < 0 && (h = -h) < 0) 4700Sstevel@tonic-gate h = 0; 4710Sstevel@tonic-gate h = h % XHSIZE; 4720Sstevel@tonic-gate cp = name; 4730Sstevel@tonic-gate for (i = 0, q = 0; q < XHSIZE; i++, q = i * i) { 4740Sstevel@tonic-gate xp = &xtrahash[(h + q) % XHSIZE]; 4750Sstevel@tonic-gate if (xp->xh_name == NOSTR) 4760Sstevel@tonic-gate return(xp); 4770Sstevel@tonic-gate if (strcmp(cp, xp->xh_name) == 0) 4780Sstevel@tonic-gate return(xp); 4790Sstevel@tonic-gate if (h - q < 0) 4800Sstevel@tonic-gate h += XHSIZE; 4810Sstevel@tonic-gate xp = &xtrahash[(h - q) % XHSIZE]; 4820Sstevel@tonic-gate if (xp->xh_name == NOSTR) 4830Sstevel@tonic-gate return(xp); 4840Sstevel@tonic-gate if (strcmp(cp, xp->xh_name) == 0) 4850Sstevel@tonic-gate return(xp); 4860Sstevel@tonic-gate } 4870Sstevel@tonic-gate return((struct xtrahash *) 0); 4880Sstevel@tonic-gate } 4890Sstevel@tonic-gate 4900Sstevel@tonic-gate #ifdef OPTIM 4910Sstevel@tonic-gate /* 4920Sstevel@tonic-gate * Return the name from the extra host hash table corresponding 4930Sstevel@tonic-gate * to the passed machine id. 4940Sstevel@tonic-gate */ 4950Sstevel@tonic-gate 4960Sstevel@tonic-gate static char * 4970Sstevel@tonic-gate mlook(int mid) 4980Sstevel@tonic-gate { 4990Sstevel@tonic-gate register int m; 5000Sstevel@tonic-gate 5010Sstevel@tonic-gate if ((mid & 0200) == 0) 5020Sstevel@tonic-gate return(NOSTR); 5030Sstevel@tonic-gate m = mid & 0177; 5040Sstevel@tonic-gate if (m >= midfree) { 5050Sstevel@tonic-gate printf(gettext("Use made of undefined machine id\n")); 5060Sstevel@tonic-gate return(NOSTR); 5070Sstevel@tonic-gate } 5080Sstevel@tonic-gate return(xtab[m]->xh_name); 5090Sstevel@tonic-gate } 5100Sstevel@tonic-gate #endif 5110Sstevel@tonic-gate 5120Sstevel@tonic-gate /* 5130Sstevel@tonic-gate * Return the bit mask of net's that the given extra host machine 5140Sstevel@tonic-gate * id has so far. 5150Sstevel@tonic-gate */ 5160Sstevel@tonic-gate static int 5170Sstevel@tonic-gate mtype(int mid) 5180Sstevel@tonic-gate { 5190Sstevel@tonic-gate register int m; 5200Sstevel@tonic-gate 5210Sstevel@tonic-gate if ((mid & 0200) == 0) 5220Sstevel@tonic-gate return(0); 5230Sstevel@tonic-gate m = mid & 0177; 5240Sstevel@tonic-gate if (m >= midfree) { 5250Sstevel@tonic-gate printf(gettext("Use made of undefined machine id\n")); 5260Sstevel@tonic-gate return(0); 5270Sstevel@tonic-gate } 5280Sstevel@tonic-gate return(xtab[m]->xh_attnet); 5290Sstevel@tonic-gate } 5300Sstevel@tonic-gate 5310Sstevel@tonic-gate #ifdef OPTIM 5320Sstevel@tonic-gate /* 5330Sstevel@tonic-gate * Take a network name and optimize it. This gloriously messy 5340Sstevel@tonic-gate * operation takes place as follows: the name with machine names 5350Sstevel@tonic-gate * in it is tokenized by mapping each machine name into a single 5360Sstevel@tonic-gate * character machine id (netlook). The separator characters (network 5370Sstevel@tonic-gate * metacharacters) are left intact. The last component of the network 5380Sstevel@tonic-gate * name is stripped off and assumed to be the destination user name -- 5390Sstevel@tonic-gate * it does not participate in the optimization. As an example, the 5400Sstevel@tonic-gate * name "res!vax!res!uvax!bill" becomes, tokenized, 5410Sstevel@tonic-gate * "r!x!r!v!" and "bill" A low level routine, optim1, fixes up the 5420Sstevel@tonic-gate * network part (eg, "r!x!r!v!"), then we convert back to network 5430Sstevel@tonic-gate * machine names and tack the user name on the end. 5440Sstevel@tonic-gate * 5450Sstevel@tonic-gate * The result of this is copied into the parameter "name" 5460Sstevel@tonic-gate */ 5470Sstevel@tonic-gate 5480Sstevel@tonic-gate static void 5490Sstevel@tonic-gate optim(char net[], char name[]) 5500Sstevel@tonic-gate { 5510Sstevel@tonic-gate char netcomp[BUFSIZ], netstr[STSIZ], xfstr[STSIZ]; 5520Sstevel@tonic-gate register char *cp, *cp2; 5530Sstevel@tonic-gate register int c; 5540Sstevel@tonic-gate 5550Sstevel@tonic-gate if (debug) fprintf(stderr, "optim(%s, %s) called\n", net, name); 5560Sstevel@tonic-gate *netstr = '\0'; 5570Sstevel@tonic-gate cp = net; 5580Sstevel@tonic-gate for (;;) { 5590Sstevel@tonic-gate /* 5600Sstevel@tonic-gate * Rip off next path component into netcomp 5610Sstevel@tonic-gate */ 5620Sstevel@tonic-gate cp2 = netcomp; 5630Sstevel@tonic-gate while (*cp && !any(*cp, metanet)) 5640Sstevel@tonic-gate *cp2++ = *cp++; 5650Sstevel@tonic-gate *cp2 = 0; 5660Sstevel@tonic-gate /* 5670Sstevel@tonic-gate * If we hit null byte, then we just scanned 5680Sstevel@tonic-gate * the destination user name. Go off and optimize 5690Sstevel@tonic-gate * if its so. 5700Sstevel@tonic-gate */ 5710Sstevel@tonic-gate if (*cp == 0) 5720Sstevel@tonic-gate break; 5730Sstevel@tonic-gate if ((c = netlook(netcomp, *cp)) == 0) { 5740Sstevel@tonic-gate printf(gettext("No host named \"%s\"\n"), netcomp); 5750Sstevel@tonic-gate err: 5760Sstevel@tonic-gate nstrcpy(name, BUFSIZ, net); 5770Sstevel@tonic-gate return; 5780Sstevel@tonic-gate } 5790Sstevel@tonic-gate stradd(name, BUFSIZ, c); 5800Sstevel@tonic-gate stradd(name, BUFSIZ, *cp++); 5810Sstevel@tonic-gate /* 5820Sstevel@tonic-gate * If multiple network separators given, 5830Sstevel@tonic-gate * throw away the extras. 5840Sstevel@tonic-gate */ 5850Sstevel@tonic-gate while (any(*cp, metanet)) 5860Sstevel@tonic-gate cp++; 5870Sstevel@tonic-gate } 5880Sstevel@tonic-gate if (strlen(netcomp) == 0) { 5890Sstevel@tonic-gate printf(gettext("net name syntax\n")); 5900Sstevel@tonic-gate goto err; 5910Sstevel@tonic-gate } 5920Sstevel@tonic-gate if (debug) fprintf(stderr, "optim1(%s,%s) called\n", netstr, xfstr); 5930Sstevel@tonic-gate optim1(netstr, xfstr); 5940Sstevel@tonic-gate if (debug) fprintf(stderr, "optim1(%s,%s) returns\n", netstr, xfstr); 5950Sstevel@tonic-gate 5960Sstevel@tonic-gate /* 5970Sstevel@tonic-gate * Convert back to machine names. 5980Sstevel@tonic-gate */ 5990Sstevel@tonic-gate 6000Sstevel@tonic-gate cp = xfstr; 6010Sstevel@tonic-gate *name = '\0'; 6020Sstevel@tonic-gate while (*cp) { 6030Sstevel@tonic-gate if ((cp2 = netname(*cp++)) == NOSTR) { 6040Sstevel@tonic-gate printf(gettext("Made up bad net name\n")); 6050Sstevel@tonic-gate printf(gettext("Machine code %c (0%o)\n"), cp[-1], 6060Sstevel@tonic-gate cp[-1]); 6070Sstevel@tonic-gate printf(gettext("Sorry.\n")); 6080Sstevel@tonic-gate goto err; 6090Sstevel@tonic-gate } 6100Sstevel@tonic-gate nstrcat(name, BUFSIZ, cp2); 6110Sstevel@tonic-gate stradd(name, BUFSIZ, *cp++); 6120Sstevel@tonic-gate } 6130Sstevel@tonic-gate nstrcat(name, BUFSIZ, netcomp); 6140Sstevel@tonic-gate if (debug) fprintf(stderr, "optim returns %s in name\n", name); 6150Sstevel@tonic-gate } 6160Sstevel@tonic-gate 6170Sstevel@tonic-gate /* 6180Sstevel@tonic-gate * Take a string of network machine id's and separators and 6190Sstevel@tonic-gate * optimize them. We process these by pulling off maximal 6200Sstevel@tonic-gate * leading strings of the same type, passing these to the appropriate 6210Sstevel@tonic-gate * optimizer and concatenating the results. 6220Sstevel@tonic-gate */ 6230Sstevel@tonic-gate 6240Sstevel@tonic-gate static void 6250Sstevel@tonic-gate optim1(char netstr[], char name[]) 6260Sstevel@tonic-gate { 6270Sstevel@tonic-gate char path[STSIZ], rpath[STSIZ]; 6280Sstevel@tonic-gate register char *cp, *cp2; 6290Sstevel@tonic-gate register int tp, nc; 6300Sstevel@tonic-gate 6310Sstevel@tonic-gate cp = netstr; 6320Sstevel@tonic-gate prefer(cp); 6330Sstevel@tonic-gate *name = '\0'; 6340Sstevel@tonic-gate /* 6350Sstevel@tonic-gate * If the address ultimately points back to us, 6360Sstevel@tonic-gate * just return a null network path. 6370Sstevel@tonic-gate */ 6380Sstevel@tonic-gate if ((int)strlen(cp) > 1 && cp[strlen(cp) - 2] == LOCAL) 6390Sstevel@tonic-gate return; 6400Sstevel@tonic-gate while (*cp != 0) { 6410Sstevel@tonic-gate *path = '\0'; 6420Sstevel@tonic-gate 6430Sstevel@tonic-gate tp = ntype(cp[1]); 6440Sstevel@tonic-gate nc = cp[1]; 6450Sstevel@tonic-gate while (*cp && tp == ntype(cp[1])) { 6460Sstevel@tonic-gate stradd(path, sizeof (path), *cp++); 6470Sstevel@tonic-gate cp++; 6480Sstevel@tonic-gate } 6490Sstevel@tonic-gate switch (netkind(tp)) { 6500Sstevel@tonic-gate default: 6510Sstevel@tonic-gate nstrcpy(rpath, sizeof (rpath), path); 6520Sstevel@tonic-gate break; 6530Sstevel@tonic-gate 6540Sstevel@tonic-gate case IMPLICIT: 6550Sstevel@tonic-gate optimimp(path, rpath); 6560Sstevel@tonic-gate break; 6570Sstevel@tonic-gate 6580Sstevel@tonic-gate case EXPLICIT: 6590Sstevel@tonic-gate optimex(path, rpath); 6600Sstevel@tonic-gate break; 6610Sstevel@tonic-gate } 6620Sstevel@tonic-gate for (cp2 = rpath; *cp2 != 0; cp2++) { 6630Sstevel@tonic-gate stradd(name, BUFSIZ, *cp2); 6640Sstevel@tonic-gate stradd(name, BUFSIZ, nc); 6650Sstevel@tonic-gate } 6660Sstevel@tonic-gate } 6670Sstevel@tonic-gate optiboth(name); 6680Sstevel@tonic-gate prefer(name); 6690Sstevel@tonic-gate } 670*18Srobbin #endif /* OPTIM */ 6710Sstevel@tonic-gate 6720Sstevel@tonic-gate /* 6730Sstevel@tonic-gate * Return the network of the separator -- 6740Sstevel@tonic-gate * AN for arpa net 6750Sstevel@tonic-gate * BN for Bell labs net (e.g. UUCP, NOT Berknet) 6760Sstevel@tonic-gate * SN for Schmidt net (Berknet) 6770Sstevel@tonic-gate * 0 if we don't know. 6780Sstevel@tonic-gate */ 6790Sstevel@tonic-gate static int 6800Sstevel@tonic-gate ntype(register int nc) 6810Sstevel@tonic-gate { 6820Sstevel@tonic-gate register struct ntypetab *np; 6830Sstevel@tonic-gate 6840Sstevel@tonic-gate for (np = ntypetab; np->nt_char != 0; np++) 6850Sstevel@tonic-gate if (np->nt_char == nc) 6860Sstevel@tonic-gate return(np->nt_bcode); 6870Sstevel@tonic-gate return(0); 6880Sstevel@tonic-gate } 6890Sstevel@tonic-gate 6900Sstevel@tonic-gate #ifdef OPTIM 6910Sstevel@tonic-gate /* 6920Sstevel@tonic-gate * Return the kind of routing used for the particular net 6930Sstevel@tonic-gate * EXPLICIT means explicitly routed 6940Sstevel@tonic-gate * IMPLICIT means implicitly routed 6950Sstevel@tonic-gate * 0 means don't know 6960Sstevel@tonic-gate */ 6970Sstevel@tonic-gate 6980Sstevel@tonic-gate static int 6990Sstevel@tonic-gate netkind(register int nt) 7000Sstevel@tonic-gate { 7010Sstevel@tonic-gate register struct nkindtab *np; 7020Sstevel@tonic-gate 7030Sstevel@tonic-gate for (np = nkindtab; np->nk_type != 0; np++) 7040Sstevel@tonic-gate if (np->nk_type == nt) 7050Sstevel@tonic-gate return(np->nk_kind); 7060Sstevel@tonic-gate return(0); 7070Sstevel@tonic-gate } 7080Sstevel@tonic-gate 7090Sstevel@tonic-gate /* 7100Sstevel@tonic-gate * Do name optimization for an explicitly routed network (eg uucp). 7110Sstevel@tonic-gate */ 7120Sstevel@tonic-gate 7130Sstevel@tonic-gate static int 7140Sstevel@tonic-gate optimex(char net[], char name[]) 7150Sstevel@tonic-gate { 7160Sstevel@tonic-gate register char *cp, *rp; 7170Sstevel@tonic-gate register int m; 7180Sstevel@tonic-gate 7190Sstevel@tonic-gate nstrcpy(name, STSIZ, net); 7200Sstevel@tonic-gate cp = name; 7210Sstevel@tonic-gate if (strlen(cp) == 0) 7220Sstevel@tonic-gate return(-1); 7230Sstevel@tonic-gate if (cp[strlen(cp)-1] == LOCAL) { 7240Sstevel@tonic-gate name[0] = 0; 7250Sstevel@tonic-gate return(0); 7260Sstevel@tonic-gate } 7270Sstevel@tonic-gate for (cp = name; *cp; cp++) { 7280Sstevel@tonic-gate m = *cp; 7290Sstevel@tonic-gate rp = strrchr(cp+1, m); 7300Sstevel@tonic-gate if (rp != NOSTR) 7310Sstevel@tonic-gate strcpy(cp, rp); 7320Sstevel@tonic-gate } 7330Sstevel@tonic-gate return(0); 7340Sstevel@tonic-gate } 7350Sstevel@tonic-gate 7360Sstevel@tonic-gate /* 7370Sstevel@tonic-gate * Do name optimization for implicitly routed network (eg, arpanet). 7380Sstevel@tonic-gate */ 7390Sstevel@tonic-gate 7400Sstevel@tonic-gate static int 7410Sstevel@tonic-gate optimimp(char net[], char name[]) 7420Sstevel@tonic-gate { 7430Sstevel@tonic-gate register char *cp; 7440Sstevel@tonic-gate register char m; 7450Sstevel@tonic-gate 7460Sstevel@tonic-gate cp = net; 7470Sstevel@tonic-gate if (strlen(cp) == 0) 7480Sstevel@tonic-gate return(-1); 7490Sstevel@tonic-gate m = cp[strlen(cp) - 1]; 7500Sstevel@tonic-gate if (m == LOCAL) { 7510Sstevel@tonic-gate *name = '\0'; 7520Sstevel@tonic-gate return(0); 7530Sstevel@tonic-gate } 7540Sstevel@tonic-gate name[0] = m; 7550Sstevel@tonic-gate name[1] = 0; 7560Sstevel@tonic-gate return(0); 7570Sstevel@tonic-gate } 7580Sstevel@tonic-gate 7590Sstevel@tonic-gate /* 7600Sstevel@tonic-gate * Perform global optimization on the given network path. 7610Sstevel@tonic-gate * The trick here is to look ahead to see if there are any loops 7620Sstevel@tonic-gate * in the path and remove them. The interpretation of loops is 7630Sstevel@tonic-gate * more strict here than in optimex since both the machine and net 7640Sstevel@tonic-gate * type must match. 7650Sstevel@tonic-gate */ 7660Sstevel@tonic-gate 7670Sstevel@tonic-gate static void 7680Sstevel@tonic-gate optiboth(char net[]) 7690Sstevel@tonic-gate { 7700Sstevel@tonic-gate register char *cp, *cp2; 7710Sstevel@tonic-gate 7720Sstevel@tonic-gate cp = net; 7730Sstevel@tonic-gate if (strlen(cp) == 0) 7740Sstevel@tonic-gate return; 7750Sstevel@tonic-gate if (((int)strlen(cp) % 2) != 0) { 7760Sstevel@tonic-gate printf(gettext("Strange arg to optiboth\n")); 7770Sstevel@tonic-gate return; 7780Sstevel@tonic-gate } 7790Sstevel@tonic-gate while (*cp) { 7800Sstevel@tonic-gate cp2 = rpair(cp+2, *cp); 7810Sstevel@tonic-gate if (cp2 != NOSTR) 7820Sstevel@tonic-gate strcpy(cp, cp2); 7830Sstevel@tonic-gate cp += 2; 7840Sstevel@tonic-gate } 7850Sstevel@tonic-gate } 7860Sstevel@tonic-gate 7870Sstevel@tonic-gate /* 7880Sstevel@tonic-gate * Find the rightmost instance of the given (machine, type) pair. 7890Sstevel@tonic-gate */ 7900Sstevel@tonic-gate 7910Sstevel@tonic-gate static char * 7920Sstevel@tonic-gate rpair(char str[], int mach) 7930Sstevel@tonic-gate { 7940Sstevel@tonic-gate register char *cp, *last; 7950Sstevel@tonic-gate 7960Sstevel@tonic-gate cp = str; 7970Sstevel@tonic-gate last = NOSTR; 7980Sstevel@tonic-gate while (*cp) { 7990Sstevel@tonic-gate if (*cp == mach) 8000Sstevel@tonic-gate last = cp; 8010Sstevel@tonic-gate cp += 2; 8020Sstevel@tonic-gate } 8030Sstevel@tonic-gate return(last); 8040Sstevel@tonic-gate } 8050Sstevel@tonic-gate 8060Sstevel@tonic-gate /* 8070Sstevel@tonic-gate * Change the network separators in the given network path 8080Sstevel@tonic-gate * to the preferred network transmission means. 8090Sstevel@tonic-gate */ 8100Sstevel@tonic-gate 8110Sstevel@tonic-gate static void 8120Sstevel@tonic-gate prefer(char name[]) 8130Sstevel@tonic-gate { 8140Sstevel@tonic-gate register char *cp, n; 8150Sstevel@tonic-gate register int state; 8160Sstevel@tonic-gate 8170Sstevel@tonic-gate state = LOCAL; 8180Sstevel@tonic-gate for (cp = name; *cp; cp += 2) { 8190Sstevel@tonic-gate n = best(state, *cp); 8200Sstevel@tonic-gate if (n) 8210Sstevel@tonic-gate cp[1] = n; 8220Sstevel@tonic-gate state = *cp; 8230Sstevel@tonic-gate } 8240Sstevel@tonic-gate } 8250Sstevel@tonic-gate 8260Sstevel@tonic-gate /* 8270Sstevel@tonic-gate * Return the best network separator for the given machine pair. 8280Sstevel@tonic-gate */ 8290Sstevel@tonic-gate 8300Sstevel@tonic-gate static char 8310Sstevel@tonic-gate best(int src, int dest) 8320Sstevel@tonic-gate { 8330Sstevel@tonic-gate register int dtype, stype; 8340Sstevel@tonic-gate register struct netorder *np; 8350Sstevel@tonic-gate 8360Sstevel@tonic-gate stype = nettype(src); 8370Sstevel@tonic-gate dtype = nettype(dest); 8380Sstevel@tonic-gate fflush(stdout); 8390Sstevel@tonic-gate if (stype == 0 || dtype == 0) { 8400Sstevel@tonic-gate printf(gettext("ERROR: unknown internal machine id\n")); 8410Sstevel@tonic-gate return(0); 8420Sstevel@tonic-gate } 8430Sstevel@tonic-gate if ((stype & dtype) == 0) 8440Sstevel@tonic-gate return(0); 8450Sstevel@tonic-gate np = &netorder[0]; 8460Sstevel@tonic-gate while ((np->no_stat & stype & dtype) == 0) 8470Sstevel@tonic-gate np++; 8480Sstevel@tonic-gate return(np->no_char); 8490Sstevel@tonic-gate } 850*18Srobbin #endif /* OPTIM */ 8510Sstevel@tonic-gate 8520Sstevel@tonic-gate #ifdef notdef 8530Sstevel@tonic-gate /* 8540Sstevel@tonic-gate * Code to twist around arpa net names. 8550Sstevel@tonic-gate */ 8560Sstevel@tonic-gate 8570Sstevel@tonic-gate #define WORD 257 /* Token for a string */ 8580Sstevel@tonic-gate 8590Sstevel@tonic-gate static char netbuf[256]; 8600Sstevel@tonic-gate static char *yylval; 8610Sstevel@tonic-gate 8620Sstevel@tonic-gate /* 8630Sstevel@tonic-gate * Reverse all of the arpa net addresses in the given name to 8640Sstevel@tonic-gate * be of the form "host @ user" instead of "user @ host" 8650Sstevel@tonic-gate * This function is its own inverse. 8660Sstevel@tonic-gate */ 8670Sstevel@tonic-gate 8680Sstevel@tonic-gate char * 8690Sstevel@tonic-gate revarpa(char str[]) 8700Sstevel@tonic-gate { 8710Sstevel@tonic-gate 8720Sstevel@tonic-gate if (yyinit(str) < 0) 8730Sstevel@tonic-gate return(NOSTR); 8740Sstevel@tonic-gate if (name()) 8750Sstevel@tonic-gate return(NOSTR); 8760Sstevel@tonic-gate if (strcmp(str, netbuf) == 0) 8770Sstevel@tonic-gate return(str); 8780Sstevel@tonic-gate return(savestr(netbuf)); 8790Sstevel@tonic-gate } 8800Sstevel@tonic-gate 8810Sstevel@tonic-gate /* 8820Sstevel@tonic-gate * Parse (by recursive descent) network names, using the following grammar: 8830Sstevel@tonic-gate * name: 8840Sstevel@tonic-gate * term {':' term} 8850Sstevel@tonic-gate * term {'^' term} 8860Sstevel@tonic-gate * term {'!' term} 8870Sstevel@tonic-gate * term '@' name 8880Sstevel@tonic-gate * term '%' name 8890Sstevel@tonic-gate * 8900Sstevel@tonic-gate * term: 8910Sstevel@tonic-gate * string of characters. 8920Sstevel@tonic-gate */ 8930Sstevel@tonic-gate 8940Sstevel@tonic-gate static int 8950Sstevel@tonic-gate name(void) 8960Sstevel@tonic-gate { 8970Sstevel@tonic-gate register int t; 8980Sstevel@tonic-gate register char *cp; 8990Sstevel@tonic-gate 9000Sstevel@tonic-gate for (;;) { 9010Sstevel@tonic-gate t = yylex(); 9020Sstevel@tonic-gate if (t != WORD) 9030Sstevel@tonic-gate return(-1); 9040Sstevel@tonic-gate cp = yylval; 9050Sstevel@tonic-gate t = yylex(); 9060Sstevel@tonic-gate switch (t) { 9070Sstevel@tonic-gate case 0: 9080Sstevel@tonic-gate nstrcat(netbuf, sizeof (netbuf), cp); 9090Sstevel@tonic-gate return(0); 9100Sstevel@tonic-gate 9110Sstevel@tonic-gate case '@': 9120Sstevel@tonic-gate case '%': 9130Sstevel@tonic-gate if (name()) 9140Sstevel@tonic-gate return(-1); 9150Sstevel@tonic-gate stradd(netbuf, sizeof (netbuf), '@'); 9160Sstevel@tonic-gate nstrcat(netbuf, sizeof (netbuf), cp); 9170Sstevel@tonic-gate return(0); 9180Sstevel@tonic-gate case WORD: 9190Sstevel@tonic-gate return(-1); 9200Sstevel@tonic-gate 9210Sstevel@tonic-gate default: 9220Sstevel@tonic-gate nstrcat(netbuf, sizeof (netbuf), cp); 9230Sstevel@tonic-gate stradd(netbuf, sizeof (netbuf), t); 9240Sstevel@tonic-gate } 9250Sstevel@tonic-gate } 9260Sstevel@tonic-gate } 9270Sstevel@tonic-gate 9280Sstevel@tonic-gate /* 9290Sstevel@tonic-gate * Scanner for network names. 9300Sstevel@tonic-gate */ 9310Sstevel@tonic-gate 9320Sstevel@tonic-gate static char *charp; /* Current input pointer */ 9330Sstevel@tonic-gate static int nexttok; /* Salted away next token */ 9340Sstevel@tonic-gate 9350Sstevel@tonic-gate /* 9360Sstevel@tonic-gate * Initialize the network name scanner. 9370Sstevel@tonic-gate */ 9380Sstevel@tonic-gate 9390Sstevel@tonic-gate int 9400Sstevel@tonic-gate yyinit(char str[]) 9410Sstevel@tonic-gate { 9420Sstevel@tonic-gate static char lexbuf[BUFSIZ]; 9430Sstevel@tonic-gate 9440Sstevel@tonic-gate netbuf[0] = 0; 9450Sstevel@tonic-gate if (strlen(str) >= sizeof lexbuf - 1) 9460Sstevel@tonic-gate return(-1); 9470Sstevel@tonic-gate nexttok = 0; 9480Sstevel@tonic-gate nstrcpy(lexbuf, sizeof (lexbuf), str); 9490Sstevel@tonic-gate charp = lexbuf; 9500Sstevel@tonic-gate return(0); 9510Sstevel@tonic-gate } 9520Sstevel@tonic-gate 9530Sstevel@tonic-gate /* 9540Sstevel@tonic-gate * Scan and return a single token. 9550Sstevel@tonic-gate * yylval is set to point to a scanned string. 9560Sstevel@tonic-gate */ 9570Sstevel@tonic-gate 9580Sstevel@tonic-gate int 9590Sstevel@tonic-gate yylex(void) 9600Sstevel@tonic-gate { 9610Sstevel@tonic-gate register char *cp, *dotp; 9620Sstevel@tonic-gate register int s; 9630Sstevel@tonic-gate 9640Sstevel@tonic-gate if (nexttok) { 9650Sstevel@tonic-gate s = nexttok; 9660Sstevel@tonic-gate nexttok = 0; 9670Sstevel@tonic-gate return(s); 9680Sstevel@tonic-gate } 9690Sstevel@tonic-gate cp = charp; 9700Sstevel@tonic-gate while (*cp && isspace(*cp)) 9710Sstevel@tonic-gate cp++; 9720Sstevel@tonic-gate if (*cp == 0) 9730Sstevel@tonic-gate return(0); 9740Sstevel@tonic-gate if (any(*cp, metanet)) { 9750Sstevel@tonic-gate charp = cp+1; 9760Sstevel@tonic-gate return(*cp); 9770Sstevel@tonic-gate } 9780Sstevel@tonic-gate dotp = cp; 9790Sstevel@tonic-gate while (*cp && !any(*cp, metanet) && !any(*cp, " \t")) 9800Sstevel@tonic-gate cp++; 9810Sstevel@tonic-gate if (any(*cp, metanet)) 9820Sstevel@tonic-gate nexttok = *cp; 9830Sstevel@tonic-gate if (*cp == 0) 9840Sstevel@tonic-gate charp = cp; 9850Sstevel@tonic-gate else 9860Sstevel@tonic-gate charp = cp+1; 9870Sstevel@tonic-gate *cp = 0; 9880Sstevel@tonic-gate yylval = dotp; 9890Sstevel@tonic-gate return(WORD); 9900Sstevel@tonic-gate } 9910Sstevel@tonic-gate #endif 9920Sstevel@tonic-gate 9930Sstevel@tonic-gate /* 9940Sstevel@tonic-gate * Add a single character onto a string. Here dstsize is the size of the 9950Sstevel@tonic-gate * destnation buffer. 9960Sstevel@tonic-gate */ 9970Sstevel@tonic-gate 9980Sstevel@tonic-gate static void 9990Sstevel@tonic-gate stradd(register char *dst, int dstsize, register int c) 10000Sstevel@tonic-gate { 10010Sstevel@tonic-gate while (*dst != '\0') { 10020Sstevel@tonic-gate dst++; 10030Sstevel@tonic-gate dstsize--; 10040Sstevel@tonic-gate } 10050Sstevel@tonic-gate if (--dstsize > 0) 10060Sstevel@tonic-gate *dst++ = (char)c; 10070Sstevel@tonic-gate *dst = '\0'; 10080Sstevel@tonic-gate } 1009