1*0Sstevel@tonic-gate /* 2*0Sstevel@tonic-gate * CDDL HEADER START 3*0Sstevel@tonic-gate * 4*0Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*0Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*0Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*0Sstevel@tonic-gate * with the License. 8*0Sstevel@tonic-gate * 9*0Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*0Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*0Sstevel@tonic-gate * See the License for the specific language governing permissions 12*0Sstevel@tonic-gate * and limitations under the License. 13*0Sstevel@tonic-gate * 14*0Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*0Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*0Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*0Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*0Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*0Sstevel@tonic-gate * 20*0Sstevel@tonic-gate * CDDL HEADER END 21*0Sstevel@tonic-gate */ 22*0Sstevel@tonic-gate /* 23*0Sstevel@tonic-gate * Copyright 1998 Sun Microsystems, Inc. All rights reserved. 24*0Sstevel@tonic-gate * Use is subject to license terms. 25*0Sstevel@tonic-gate */ 26*0Sstevel@tonic-gate 27*0Sstevel@tonic-gate /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 28*0Sstevel@tonic-gate /* All Rights Reserved */ 29*0Sstevel@tonic-gate 30*0Sstevel@tonic-gate 31*0Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 32*0Sstevel@tonic-gate 33*0Sstevel@tonic-gate /* 34*0Sstevel@tonic-gate * mailx -- a modified version of a University of California at Berkeley 35*0Sstevel@tonic-gate * mail program 36*0Sstevel@tonic-gate * 37*0Sstevel@tonic-gate * Network name modification routines. 38*0Sstevel@tonic-gate */ 39*0Sstevel@tonic-gate 40*0Sstevel@tonic-gate #include "rcv.h" 41*0Sstevel@tonic-gate #include "configdefs.h" 42*0Sstevel@tonic-gate #include <locale.h> 43*0Sstevel@tonic-gate 44*0Sstevel@tonic-gate static char *arpafix(char name[], char from[]); 45*0Sstevel@tonic-gate static char *lasthost(char *addr); 46*0Sstevel@tonic-gate static char *makeremote(char name[], char from[]); 47*0Sstevel@tonic-gate static int mstash(char name[], int attnet); 48*0Sstevel@tonic-gate static int mtype(int mid); 49*0Sstevel@tonic-gate static int netlook(char machine[], int attnet); 50*0Sstevel@tonic-gate static int nettype(int mid); 51*0Sstevel@tonic-gate static int ntype(register int nc); 52*0Sstevel@tonic-gate static void stradd(register char *str, int n, register int c); 53*0Sstevel@tonic-gate static char *tackon(char *sys, char *rest); 54*0Sstevel@tonic-gate static struct xtrahash *xlocate(char name[]); 55*0Sstevel@tonic-gate #ifdef OPTIM 56*0Sstevel@tonic-gate static char best(int src, int dest); 57*0Sstevel@tonic-gate static char *mlook(int mid); 58*0Sstevel@tonic-gate static int netkind(register int nt); 59*0Sstevel@tonic-gate static void optiboth(char net[]); 60*0Sstevel@tonic-gate static void optim(char net[], char name[]); 61*0Sstevel@tonic-gate static void optim1(char netstr[], char name[]); 62*0Sstevel@tonic-gate static int optimex(char net[], char name[]); 63*0Sstevel@tonic-gate static int optimimp(char net[], char name[]); 64*0Sstevel@tonic-gate static void prefer(char name[]); 65*0Sstevel@tonic-gate static char *rpair(char str[], int mach); 66*0Sstevel@tonic-gate #endif 67*0Sstevel@tonic-gate 68*0Sstevel@tonic-gate /* 69*0Sstevel@tonic-gate * Map a name into the correct network "view" of the 70*0Sstevel@tonic-gate * name. This is done by prepending the name with the 71*0Sstevel@tonic-gate * network address of the sender, then optimizing away 72*0Sstevel@tonic-gate * nonsense. 73*0Sstevel@tonic-gate */ 74*0Sstevel@tonic-gate 75*0Sstevel@tonic-gate char * 76*0Sstevel@tonic-gate netmap(char name[], char from[]) 77*0Sstevel@tonic-gate { 78*0Sstevel@tonic-gate char nbuf[BUFSIZ], ret[BUFSIZ]; 79*0Sstevel@tonic-gate register char *cp, *oname; 80*0Sstevel@tonic-gate 81*0Sstevel@tonic-gate if (debug) fprintf(stderr, "netmap(name '%s', from '%s')\n", name, from); 82*0Sstevel@tonic-gate if (strlen(from) == 0) 83*0Sstevel@tonic-gate return(name); /* "from" is empty - can't do anything */ 84*0Sstevel@tonic-gate 85*0Sstevel@tonic-gate if (strcmp(from, name) == 0) 86*0Sstevel@tonic-gate return(name); /* "from" and "name" are the same, do nothing */ 87*0Sstevel@tonic-gate 88*0Sstevel@tonic-gate /* 89*0Sstevel@tonic-gate * If the name contains an "@" or a "%", remove it and the host 90*0Sstevel@tonic-gate * following it if that host is "known". 91*0Sstevel@tonic-gate */ 92*0Sstevel@tonic-gate if (any('@', name) || any('%', name)) 93*0Sstevel@tonic-gate return(arpafix(name, from)); 94*0Sstevel@tonic-gate 95*0Sstevel@tonic-gate /* 96*0Sstevel@tonic-gate * If the sender contains a "@" or a "%", make "name" into an 97*0Sstevel@tonic-gate * address on that host, on the presumption that it should 98*0Sstevel@tonic-gate * really have read "name@from" when we received the message 99*0Sstevel@tonic-gate * rather than just "name". 100*0Sstevel@tonic-gate */ 101*0Sstevel@tonic-gate if (any('@', from) || any('%', from)) 102*0Sstevel@tonic-gate return(unuucp(makeremote(name, from))); 103*0Sstevel@tonic-gate if (value("onehop") && (cp = strchr(name, '!')) && cp > name) { 104*0Sstevel@tonic-gate /* 105*0Sstevel@tonic-gate * "onehop" is set, meaning all machines are one UUCP 106*0Sstevel@tonic-gate * hop away (fat chance, in this day and age), and "name" 107*0Sstevel@tonic-gate * is a UUCP path rather than just a name. Leave it alone. 108*0Sstevel@tonic-gate */ 109*0Sstevel@tonic-gate nstrcpy(nbuf, sizeof (nbuf), name); 110*0Sstevel@tonic-gate } else { 111*0Sstevel@tonic-gate from = tackon(host, from); 112*0Sstevel@tonic-gate *strrchr(from, '!') = 0; 113*0Sstevel@tonic-gate name = tackon(lasthost(from), name); 114*0Sstevel@tonic-gate while (((cp = lasthost(from)) != 0) && ishost(cp, name)) { 115*0Sstevel@tonic-gate oname = name; 116*0Sstevel@tonic-gate name = strchr(name, '!') + 1; 117*0Sstevel@tonic-gate if (cp == from) { 118*0Sstevel@tonic-gate from[strlen(from)] = '!'; 119*0Sstevel@tonic-gate if (value("mustbang") && !strchr(name, '!')) 120*0Sstevel@tonic-gate name = oname; 121*0Sstevel@tonic-gate return(unuucp(name)); 122*0Sstevel@tonic-gate } 123*0Sstevel@tonic-gate *--cp = 0; 124*0Sstevel@tonic-gate } 125*0Sstevel@tonic-gate from[strlen(from)] = '!'; 126*0Sstevel@tonic-gate from = strchr(from, '!') + 1; 127*0Sstevel@tonic-gate snprintf(nbuf, sizeof (nbuf), "%s!%s", from, name); 128*0Sstevel@tonic-gate } 129*0Sstevel@tonic-gate if (debug) fprintf(stderr, "before optim, nbuf '%s'\n", name); 130*0Sstevel@tonic-gate #ifdef OPTIM 131*0Sstevel@tonic-gate if ((cp = value("conv"))==NOSTR || strcmp(cp, "optimize") != 0) 132*0Sstevel@tonic-gate nstrcpy(ret, sizeof (ret), nbuf); 133*0Sstevel@tonic-gate else 134*0Sstevel@tonic-gate optim(nbuf, ret); 135*0Sstevel@tonic-gate #else 136*0Sstevel@tonic-gate nstrcpy(ret, sizeof (ret), nbuf); 137*0Sstevel@tonic-gate #endif OPTIM 138*0Sstevel@tonic-gate if (debug) fprintf(stderr, "after optim, nbuf '%s', ret '%s'\n", nbuf, ret); 139*0Sstevel@tonic-gate cp = ret; 140*0Sstevel@tonic-gate if (debug) fprintf(stderr, "wind up with '%s'\n", name); 141*0Sstevel@tonic-gate if (!icequal(name, cp)) 142*0Sstevel@tonic-gate return(unuucp((char *) savestr(cp))); 143*0Sstevel@tonic-gate return(unuucp(name)); 144*0Sstevel@tonic-gate } 145*0Sstevel@tonic-gate 146*0Sstevel@tonic-gate /* 147*0Sstevel@tonic-gate * Stick a host on the beginning of a uucp 148*0Sstevel@tonic-gate * address if it isn't there already. 149*0Sstevel@tonic-gate */ 150*0Sstevel@tonic-gate static char * 151*0Sstevel@tonic-gate tackon(char *sys, char *rest) 152*0Sstevel@tonic-gate { 153*0Sstevel@tonic-gate while (*rest == '!') 154*0Sstevel@tonic-gate rest++; 155*0Sstevel@tonic-gate if (!ishost(sys, rest)) { 156*0Sstevel@tonic-gate char *r = (char *)salloc(strlen(sys) + strlen(rest) + 2); 157*0Sstevel@tonic-gate sprintf(r, "%s!%s", sys, rest); 158*0Sstevel@tonic-gate rest = r; 159*0Sstevel@tonic-gate } 160*0Sstevel@tonic-gate return rest; 161*0Sstevel@tonic-gate } 162*0Sstevel@tonic-gate 163*0Sstevel@tonic-gate /* 164*0Sstevel@tonic-gate * Check equality of the first host in a uucp address. 165*0Sstevel@tonic-gate */ 166*0Sstevel@tonic-gate int 167*0Sstevel@tonic-gate ishost(char *sys, char *rest) 168*0Sstevel@tonic-gate { 169*0Sstevel@tonic-gate while (*sys && *sys == *rest) 170*0Sstevel@tonic-gate sys++, rest++; 171*0Sstevel@tonic-gate return(*sys == 0 && *rest == '!'); 172*0Sstevel@tonic-gate } 173*0Sstevel@tonic-gate 174*0Sstevel@tonic-gate /* 175*0Sstevel@tonic-gate * Return last host in a uucp address. 176*0Sstevel@tonic-gate */ 177*0Sstevel@tonic-gate static char * 178*0Sstevel@tonic-gate lasthost(char *addr) 179*0Sstevel@tonic-gate { 180*0Sstevel@tonic-gate char *r = strrchr(addr, '!'); 181*0Sstevel@tonic-gate return r ? ++r : addr; 182*0Sstevel@tonic-gate } 183*0Sstevel@tonic-gate 184*0Sstevel@tonic-gate /* 185*0Sstevel@tonic-gate * Optionally translate an old format uucp name into a new one, e.g. 186*0Sstevel@tonic-gate * "mach1!mach2!user" becomes "user@mach2.UUCP". This optional because 187*0Sstevel@tonic-gate * some information is necessarily lost (e.g. the route it got here 188*0Sstevel@tonic-gate * via) and if we don't have the host in our routing tables, we lose. 189*0Sstevel@tonic-gate * XXX THIS IS NO LONGER VALID WITH THE NEW UUCP PROJECT PLANS TO 190*0Sstevel@tonic-gate * REGISTER UUCP HOSTS IN THE STANDARD INTERNET NAMESPACE, E.G. 191*0Sstevel@tonic-gate * ihnp4 BECOMES "ihnp4.att.com". 192*0Sstevel@tonic-gate */ 193*0Sstevel@tonic-gate char * 194*0Sstevel@tonic-gate unuucp(char *name) 195*0Sstevel@tonic-gate { 196*0Sstevel@tonic-gate register char *np, *hp, *cp; 197*0Sstevel@tonic-gate char result[100]; 198*0Sstevel@tonic-gate char tname[300]; 199*0Sstevel@tonic-gate 200*0Sstevel@tonic-gate if (UnUUCP==0 && 201*0Sstevel@tonic-gate ((cp = value("conv"))==NOSTR || strcmp(cp, "internet"))) 202*0Sstevel@tonic-gate return name; 203*0Sstevel@tonic-gate if (debug) fprintf(stderr, "unuucp(%s)\n", name); 204*0Sstevel@tonic-gate nstrcpy(tname, sizeof (tname), name); 205*0Sstevel@tonic-gate np = strrchr(tname, '!'); 206*0Sstevel@tonic-gate if (np == NOSTR) 207*0Sstevel@tonic-gate return name; 208*0Sstevel@tonic-gate *np++ = 0; 209*0Sstevel@tonic-gate hp = strrchr(tname, '!'); 210*0Sstevel@tonic-gate if (hp == NOSTR) 211*0Sstevel@tonic-gate hp = tname; 212*0Sstevel@tonic-gate else 213*0Sstevel@tonic-gate *hp++ = 0; 214*0Sstevel@tonic-gate cp = strchr(np, '@'); 215*0Sstevel@tonic-gate if (cp == NOSTR) 216*0Sstevel@tonic-gate cp = strchr(np, '%'); 217*0Sstevel@tonic-gate if (cp) 218*0Sstevel@tonic-gate *cp = 0; 219*0Sstevel@tonic-gate if (debug) fprintf(stderr, "host %s, name %s\n", hp, np); 220*0Sstevel@tonic-gate snprintf(result, sizeof (result), "%s@%s.UUCP", np, hp); 221*0Sstevel@tonic-gate if (debug) fprintf(stderr, "unuucp returns %s\n", result); 222*0Sstevel@tonic-gate return savestr(result); 223*0Sstevel@tonic-gate } 224*0Sstevel@tonic-gate 225*0Sstevel@tonic-gate /* 226*0Sstevel@tonic-gate * Turn a network machine name into a unique character 227*0Sstevel@tonic-gate */ 228*0Sstevel@tonic-gate static int 229*0Sstevel@tonic-gate netlook(char machine[], int attnet) 230*0Sstevel@tonic-gate { 231*0Sstevel@tonic-gate register struct netmach *np; 232*0Sstevel@tonic-gate register char *cp, *cp2; 233*0Sstevel@tonic-gate char nbuf[BUFSIZ]; 234*0Sstevel@tonic-gate 235*0Sstevel@tonic-gate /* 236*0Sstevel@tonic-gate * Make into lower case. 237*0Sstevel@tonic-gate */ 238*0Sstevel@tonic-gate for (cp = machine, cp2 = nbuf; 239*0Sstevel@tonic-gate *cp && cp2 < &nbuf[BUFSIZ-1]; 240*0Sstevel@tonic-gate *cp2++ = tolower(*cp++)) 241*0Sstevel@tonic-gate /*nothing*/; 242*0Sstevel@tonic-gate *cp2 = 0; 243*0Sstevel@tonic-gate 244*0Sstevel@tonic-gate /* 245*0Sstevel@tonic-gate * If a single letter machine, look through those first. 246*0Sstevel@tonic-gate */ 247*0Sstevel@tonic-gate 248*0Sstevel@tonic-gate if (strlen(nbuf) == 1) 249*0Sstevel@tonic-gate for (np = netmach; np->nt_mid != 0; np++) 250*0Sstevel@tonic-gate if (np->nt_mid == nbuf[0]) 251*0Sstevel@tonic-gate return(nbuf[0]); 252*0Sstevel@tonic-gate 253*0Sstevel@tonic-gate /* 254*0Sstevel@tonic-gate * Look for usual name 255*0Sstevel@tonic-gate */ 256*0Sstevel@tonic-gate 257*0Sstevel@tonic-gate for (np = netmach; np->nt_mid != 0; np++) 258*0Sstevel@tonic-gate if (strcmp(np->nt_machine, nbuf) == 0) 259*0Sstevel@tonic-gate return(np->nt_mid); 260*0Sstevel@tonic-gate 261*0Sstevel@tonic-gate /* 262*0Sstevel@tonic-gate * Look in side hash table. 263*0Sstevel@tonic-gate */ 264*0Sstevel@tonic-gate 265*0Sstevel@tonic-gate return(mstash(nbuf, attnet)); 266*0Sstevel@tonic-gate } 267*0Sstevel@tonic-gate 268*0Sstevel@tonic-gate #ifdef OPTIM 269*0Sstevel@tonic-gate /* 270*0Sstevel@tonic-gate * Turn a network unique character identifier into a network name. 271*0Sstevel@tonic-gate */ 272*0Sstevel@tonic-gate 273*0Sstevel@tonic-gate static char * 274*0Sstevel@tonic-gate netname(int mid) 275*0Sstevel@tonic-gate { 276*0Sstevel@tonic-gate register struct netmach *np; 277*0Sstevel@tonic-gate 278*0Sstevel@tonic-gate if (mid & 0200) 279*0Sstevel@tonic-gate return(mlook(mid)); 280*0Sstevel@tonic-gate for (np = netmach; np->nt_mid != 0; np++) 281*0Sstevel@tonic-gate if (np->nt_mid == mid) 282*0Sstevel@tonic-gate return(np->nt_machine); 283*0Sstevel@tonic-gate return(NOSTR); 284*0Sstevel@tonic-gate } 285*0Sstevel@tonic-gate #endif 286*0Sstevel@tonic-gate 287*0Sstevel@tonic-gate /* 288*0Sstevel@tonic-gate * Deal with arpa net addresses. The way this is done is strange. 289*0Sstevel@tonic-gate * name contains an "@" or "%". Look up the machine after it in 290*0Sstevel@tonic-gate * the hash table. If it isn't found, return name unmolested. 291*0Sstevel@tonic-gate * If ???, return name unmolested. 292*0Sstevel@tonic-gate * Otherwise, delete the "@" or "%" and the machine after it from 293*0Sstevel@tonic-gate * name, and return the new string. 294*0Sstevel@tonic-gate */ 295*0Sstevel@tonic-gate static char * 296*0Sstevel@tonic-gate arpafix(char name[], char from[]) 297*0Sstevel@tonic-gate { 298*0Sstevel@tonic-gate register char *cp; 299*0Sstevel@tonic-gate register int arpamach; 300*0Sstevel@tonic-gate char newname[BUFSIZ]; 301*0Sstevel@tonic-gate 302*0Sstevel@tonic-gate if (debug) { 303*0Sstevel@tonic-gate fprintf(stderr, "arpafix(%s, %s)\n", name, from); 304*0Sstevel@tonic-gate } 305*0Sstevel@tonic-gate cp = strrchr(name, '@'); 306*0Sstevel@tonic-gate if (cp == NOSTR) 307*0Sstevel@tonic-gate cp = strrchr(name, '%'); 308*0Sstevel@tonic-gate if (cp == NOSTR) { 309*0Sstevel@tonic-gate fprintf(stderr, 310*0Sstevel@tonic-gate gettext("Something's amiss -- no @ or %% in arpafix\n")); 311*0Sstevel@tonic-gate return(name); 312*0Sstevel@tonic-gate } 313*0Sstevel@tonic-gate cp++; 314*0Sstevel@tonic-gate arpamach = netlook(cp, '@'); 315*0Sstevel@tonic-gate if (debug) 316*0Sstevel@tonic-gate fprintf(stderr, 317*0Sstevel@tonic-gate "cp '%s', arpamach %o, nettypes arpamach %o LOCAL %o\n", 318*0Sstevel@tonic-gate cp, arpamach, nettype(arpamach), nettype(LOCAL)); 319*0Sstevel@tonic-gate if (arpamach == 0) { 320*0Sstevel@tonic-gate if (debug) 321*0Sstevel@tonic-gate fprintf(stderr, "machine %s unknown, uses: %s\n", 322*0Sstevel@tonic-gate cp, name); 323*0Sstevel@tonic-gate return(name); 324*0Sstevel@tonic-gate } 325*0Sstevel@tonic-gate if (((nettype(arpamach) & nettype(LOCAL)) & ~AN) == 0) { 326*0Sstevel@tonic-gate if (debug) 327*0Sstevel@tonic-gate fprintf(stderr, "machine %s known but remote, uses: %s\n", 328*0Sstevel@tonic-gate cp, name); 329*0Sstevel@tonic-gate return(name); 330*0Sstevel@tonic-gate } 331*0Sstevel@tonic-gate nstrcpy(newname, sizeof (newname), name); 332*0Sstevel@tonic-gate cp = strrchr(newname, '@'); 333*0Sstevel@tonic-gate if (cp == NOSTR) 334*0Sstevel@tonic-gate cp = strrchr(newname, '%'); 335*0Sstevel@tonic-gate *cp = 0; 336*0Sstevel@tonic-gate if (debug) fprintf(stderr, "local address, return '%s'\n", newname); 337*0Sstevel@tonic-gate return(savestr(newname)); 338*0Sstevel@tonic-gate } 339*0Sstevel@tonic-gate 340*0Sstevel@tonic-gate /* 341*0Sstevel@tonic-gate * We have name with no @'s in it, and from with @'s. 342*0Sstevel@tonic-gate * Assume that name is meaningful only on the site in from, 343*0Sstevel@tonic-gate * and return "name@site_in_from". 344*0Sstevel@tonic-gate */ 345*0Sstevel@tonic-gate static char * 346*0Sstevel@tonic-gate makeremote(char name[], char from[]) 347*0Sstevel@tonic-gate { 348*0Sstevel@tonic-gate register char *cp; 349*0Sstevel@tonic-gate char rbuf[BUFSIZ]; 350*0Sstevel@tonic-gate 351*0Sstevel@tonic-gate if (!value("makeremote")) 352*0Sstevel@tonic-gate return(name); 353*0Sstevel@tonic-gate if (debug) fprintf(stderr, "makeremote(%s, %s) returns ", name, from); 354*0Sstevel@tonic-gate cp = strrchr(from, '@'); 355*0Sstevel@tonic-gate if (cp == NOSTR) 356*0Sstevel@tonic-gate cp = strrchr(from, '%'); 357*0Sstevel@tonic-gate snprintf(rbuf, sizeof (rbuf), "%s%s", name, cp); 358*0Sstevel@tonic-gate if (debug) fprintf(stderr, "%s\n", rbuf); 359*0Sstevel@tonic-gate return(savestr(rbuf)); 360*0Sstevel@tonic-gate } 361*0Sstevel@tonic-gate 362*0Sstevel@tonic-gate /* 363*0Sstevel@tonic-gate * Take a network machine descriptor and find the types of connected 364*0Sstevel@tonic-gate * nets and return it. 365*0Sstevel@tonic-gate */ 366*0Sstevel@tonic-gate static int 367*0Sstevel@tonic-gate nettype(int mid) 368*0Sstevel@tonic-gate { 369*0Sstevel@tonic-gate register struct netmach *np; 370*0Sstevel@tonic-gate 371*0Sstevel@tonic-gate if (mid & 0200) 372*0Sstevel@tonic-gate return(mtype(mid)); 373*0Sstevel@tonic-gate for (np = netmach; np->nt_mid != 0; np++) 374*0Sstevel@tonic-gate if (np->nt_mid == mid) 375*0Sstevel@tonic-gate return(np->nt_type); 376*0Sstevel@tonic-gate return(0); 377*0Sstevel@tonic-gate } 378*0Sstevel@tonic-gate 379*0Sstevel@tonic-gate /* 380*0Sstevel@tonic-gate * Hashing routines to salt away machines seen scanning 381*0Sstevel@tonic-gate * networks paths that we don't know about. 382*0Sstevel@tonic-gate */ 383*0Sstevel@tonic-gate 384*0Sstevel@tonic-gate #define XHSIZE 97 /* Size of extra hash table */ 385*0Sstevel@tonic-gate #define NXMID (XHSIZE*3/4) /* Max extra machines */ 386*0Sstevel@tonic-gate 387*0Sstevel@tonic-gate struct xtrahash { 388*0Sstevel@tonic-gate char *xh_name; /* Name of machine */ 389*0Sstevel@tonic-gate short xh_mid; /* Machine ID */ 390*0Sstevel@tonic-gate short xh_attnet; /* Attached networks */ 391*0Sstevel@tonic-gate } xtrahash[XHSIZE]; 392*0Sstevel@tonic-gate 393*0Sstevel@tonic-gate static struct xtrahash *xtab[XHSIZE]; /* F: mid-->machine name */ 394*0Sstevel@tonic-gate 395*0Sstevel@tonic-gate static short midfree; /* Next free machine id */ 396*0Sstevel@tonic-gate 397*0Sstevel@tonic-gate /* 398*0Sstevel@tonic-gate * Initialize the extra host hash table. 399*0Sstevel@tonic-gate * Called by sreset. 400*0Sstevel@tonic-gate */ 401*0Sstevel@tonic-gate void 402*0Sstevel@tonic-gate minit(void) 403*0Sstevel@tonic-gate { 404*0Sstevel@tonic-gate register struct xtrahash *xp, **tp; 405*0Sstevel@tonic-gate 406*0Sstevel@tonic-gate midfree = 0; 407*0Sstevel@tonic-gate tp = &xtab[0]; 408*0Sstevel@tonic-gate for (xp = &xtrahash[0]; xp < &xtrahash[XHSIZE]; xp++) { 409*0Sstevel@tonic-gate xp->xh_name = NOSTR; 410*0Sstevel@tonic-gate xp->xh_mid = 0; 411*0Sstevel@tonic-gate xp->xh_attnet = 0; 412*0Sstevel@tonic-gate *tp++ = (struct xtrahash *) 0; 413*0Sstevel@tonic-gate } 414*0Sstevel@tonic-gate } 415*0Sstevel@tonic-gate 416*0Sstevel@tonic-gate /* 417*0Sstevel@tonic-gate * Stash a net name in the extra host hash table. 418*0Sstevel@tonic-gate * If a new entry is put in the hash table, deduce what 419*0Sstevel@tonic-gate * net the machine is attached to from the net character. 420*0Sstevel@tonic-gate * 421*0Sstevel@tonic-gate * If the machine is already known, add the given attached 422*0Sstevel@tonic-gate * net to those already known. 423*0Sstevel@tonic-gate */ 424*0Sstevel@tonic-gate static int 425*0Sstevel@tonic-gate mstash(char name[], int attnet) 426*0Sstevel@tonic-gate { 427*0Sstevel@tonic-gate register struct xtrahash *xp; 428*0Sstevel@tonic-gate int x; 429*0Sstevel@tonic-gate 430*0Sstevel@tonic-gate xp = xlocate(name); 431*0Sstevel@tonic-gate if (xp == (struct xtrahash *) 0) { 432*0Sstevel@tonic-gate printf(gettext("Ran out of machine id spots\n")); 433*0Sstevel@tonic-gate return(0); 434*0Sstevel@tonic-gate } 435*0Sstevel@tonic-gate if (xp->xh_name == NOSTR) { 436*0Sstevel@tonic-gate if (midfree >= XHSIZE) { 437*0Sstevel@tonic-gate printf(gettext("Out of machine ids\n")); 438*0Sstevel@tonic-gate return(0); 439*0Sstevel@tonic-gate } 440*0Sstevel@tonic-gate xtab[midfree] = xp; 441*0Sstevel@tonic-gate xp->xh_name = savestr(name); 442*0Sstevel@tonic-gate xp->xh_mid = 0200 + midfree++; 443*0Sstevel@tonic-gate } 444*0Sstevel@tonic-gate x = ntype(attnet); 445*0Sstevel@tonic-gate if (x == 0) 446*0Sstevel@tonic-gate xp->xh_attnet |= AN; 447*0Sstevel@tonic-gate else 448*0Sstevel@tonic-gate xp->xh_attnet |= x; 449*0Sstevel@tonic-gate return(xp->xh_mid); 450*0Sstevel@tonic-gate } 451*0Sstevel@tonic-gate 452*0Sstevel@tonic-gate /* 453*0Sstevel@tonic-gate * Search for the given name in the hash table 454*0Sstevel@tonic-gate * and return the pointer to it if found, or to the first 455*0Sstevel@tonic-gate * empty slot if not found. 456*0Sstevel@tonic-gate * 457*0Sstevel@tonic-gate * If no free slots can be found, return 0. 458*0Sstevel@tonic-gate */ 459*0Sstevel@tonic-gate 460*0Sstevel@tonic-gate static struct xtrahash * 461*0Sstevel@tonic-gate xlocate(char name[]) 462*0Sstevel@tonic-gate { 463*0Sstevel@tonic-gate register int h, q, i; 464*0Sstevel@tonic-gate register char *cp; 465*0Sstevel@tonic-gate register struct xtrahash *xp; 466*0Sstevel@tonic-gate 467*0Sstevel@tonic-gate for (h = 0, cp = name; *cp; h = (h << 2) + *cp++) 468*0Sstevel@tonic-gate ; 469*0Sstevel@tonic-gate if (h < 0 && (h = -h) < 0) 470*0Sstevel@tonic-gate h = 0; 471*0Sstevel@tonic-gate h = h % XHSIZE; 472*0Sstevel@tonic-gate cp = name; 473*0Sstevel@tonic-gate for (i = 0, q = 0; q < XHSIZE; i++, q = i * i) { 474*0Sstevel@tonic-gate xp = &xtrahash[(h + q) % XHSIZE]; 475*0Sstevel@tonic-gate if (xp->xh_name == NOSTR) 476*0Sstevel@tonic-gate return(xp); 477*0Sstevel@tonic-gate if (strcmp(cp, xp->xh_name) == 0) 478*0Sstevel@tonic-gate return(xp); 479*0Sstevel@tonic-gate if (h - q < 0) 480*0Sstevel@tonic-gate h += XHSIZE; 481*0Sstevel@tonic-gate xp = &xtrahash[(h - q) % XHSIZE]; 482*0Sstevel@tonic-gate if (xp->xh_name == NOSTR) 483*0Sstevel@tonic-gate return(xp); 484*0Sstevel@tonic-gate if (strcmp(cp, xp->xh_name) == 0) 485*0Sstevel@tonic-gate return(xp); 486*0Sstevel@tonic-gate } 487*0Sstevel@tonic-gate return((struct xtrahash *) 0); 488*0Sstevel@tonic-gate } 489*0Sstevel@tonic-gate 490*0Sstevel@tonic-gate #ifdef OPTIM 491*0Sstevel@tonic-gate /* 492*0Sstevel@tonic-gate * Return the name from the extra host hash table corresponding 493*0Sstevel@tonic-gate * to the passed machine id. 494*0Sstevel@tonic-gate */ 495*0Sstevel@tonic-gate 496*0Sstevel@tonic-gate static char * 497*0Sstevel@tonic-gate mlook(int mid) 498*0Sstevel@tonic-gate { 499*0Sstevel@tonic-gate register int m; 500*0Sstevel@tonic-gate 501*0Sstevel@tonic-gate if ((mid & 0200) == 0) 502*0Sstevel@tonic-gate return(NOSTR); 503*0Sstevel@tonic-gate m = mid & 0177; 504*0Sstevel@tonic-gate if (m >= midfree) { 505*0Sstevel@tonic-gate printf(gettext("Use made of undefined machine id\n")); 506*0Sstevel@tonic-gate return(NOSTR); 507*0Sstevel@tonic-gate } 508*0Sstevel@tonic-gate return(xtab[m]->xh_name); 509*0Sstevel@tonic-gate } 510*0Sstevel@tonic-gate #endif 511*0Sstevel@tonic-gate 512*0Sstevel@tonic-gate /* 513*0Sstevel@tonic-gate * Return the bit mask of net's that the given extra host machine 514*0Sstevel@tonic-gate * id has so far. 515*0Sstevel@tonic-gate */ 516*0Sstevel@tonic-gate static int 517*0Sstevel@tonic-gate mtype(int mid) 518*0Sstevel@tonic-gate { 519*0Sstevel@tonic-gate register int m; 520*0Sstevel@tonic-gate 521*0Sstevel@tonic-gate if ((mid & 0200) == 0) 522*0Sstevel@tonic-gate return(0); 523*0Sstevel@tonic-gate m = mid & 0177; 524*0Sstevel@tonic-gate if (m >= midfree) { 525*0Sstevel@tonic-gate printf(gettext("Use made of undefined machine id\n")); 526*0Sstevel@tonic-gate return(0); 527*0Sstevel@tonic-gate } 528*0Sstevel@tonic-gate return(xtab[m]->xh_attnet); 529*0Sstevel@tonic-gate } 530*0Sstevel@tonic-gate 531*0Sstevel@tonic-gate #ifdef OPTIM 532*0Sstevel@tonic-gate /* 533*0Sstevel@tonic-gate * Take a network name and optimize it. This gloriously messy 534*0Sstevel@tonic-gate * operation takes place as follows: the name with machine names 535*0Sstevel@tonic-gate * in it is tokenized by mapping each machine name into a single 536*0Sstevel@tonic-gate * character machine id (netlook). The separator characters (network 537*0Sstevel@tonic-gate * metacharacters) are left intact. The last component of the network 538*0Sstevel@tonic-gate * name is stripped off and assumed to be the destination user name -- 539*0Sstevel@tonic-gate * it does not participate in the optimization. As an example, the 540*0Sstevel@tonic-gate * name "res!vax!res!uvax!bill" becomes, tokenized, 541*0Sstevel@tonic-gate * "r!x!r!v!" and "bill" A low level routine, optim1, fixes up the 542*0Sstevel@tonic-gate * network part (eg, "r!x!r!v!"), then we convert back to network 543*0Sstevel@tonic-gate * machine names and tack the user name on the end. 544*0Sstevel@tonic-gate * 545*0Sstevel@tonic-gate * The result of this is copied into the parameter "name" 546*0Sstevel@tonic-gate */ 547*0Sstevel@tonic-gate 548*0Sstevel@tonic-gate static void 549*0Sstevel@tonic-gate optim(char net[], char name[]) 550*0Sstevel@tonic-gate { 551*0Sstevel@tonic-gate char netcomp[BUFSIZ], netstr[STSIZ], xfstr[STSIZ]; 552*0Sstevel@tonic-gate register char *cp, *cp2; 553*0Sstevel@tonic-gate register int c; 554*0Sstevel@tonic-gate 555*0Sstevel@tonic-gate if (debug) fprintf(stderr, "optim(%s, %s) called\n", net, name); 556*0Sstevel@tonic-gate *netstr = '\0'; 557*0Sstevel@tonic-gate cp = net; 558*0Sstevel@tonic-gate for (;;) { 559*0Sstevel@tonic-gate /* 560*0Sstevel@tonic-gate * Rip off next path component into netcomp 561*0Sstevel@tonic-gate */ 562*0Sstevel@tonic-gate cp2 = netcomp; 563*0Sstevel@tonic-gate while (*cp && !any(*cp, metanet)) 564*0Sstevel@tonic-gate *cp2++ = *cp++; 565*0Sstevel@tonic-gate *cp2 = 0; 566*0Sstevel@tonic-gate /* 567*0Sstevel@tonic-gate * If we hit null byte, then we just scanned 568*0Sstevel@tonic-gate * the destination user name. Go off and optimize 569*0Sstevel@tonic-gate * if its so. 570*0Sstevel@tonic-gate */ 571*0Sstevel@tonic-gate if (*cp == 0) 572*0Sstevel@tonic-gate break; 573*0Sstevel@tonic-gate if ((c = netlook(netcomp, *cp)) == 0) { 574*0Sstevel@tonic-gate printf(gettext("No host named \"%s\"\n"), netcomp); 575*0Sstevel@tonic-gate err: 576*0Sstevel@tonic-gate nstrcpy(name, BUFSIZ, net); 577*0Sstevel@tonic-gate return; 578*0Sstevel@tonic-gate } 579*0Sstevel@tonic-gate stradd(name, BUFSIZ, c); 580*0Sstevel@tonic-gate stradd(name, BUFSIZ, *cp++); 581*0Sstevel@tonic-gate /* 582*0Sstevel@tonic-gate * If multiple network separators given, 583*0Sstevel@tonic-gate * throw away the extras. 584*0Sstevel@tonic-gate */ 585*0Sstevel@tonic-gate while (any(*cp, metanet)) 586*0Sstevel@tonic-gate cp++; 587*0Sstevel@tonic-gate } 588*0Sstevel@tonic-gate if (strlen(netcomp) == 0) { 589*0Sstevel@tonic-gate printf(gettext("net name syntax\n")); 590*0Sstevel@tonic-gate goto err; 591*0Sstevel@tonic-gate } 592*0Sstevel@tonic-gate if (debug) fprintf(stderr, "optim1(%s,%s) called\n", netstr, xfstr); 593*0Sstevel@tonic-gate optim1(netstr, xfstr); 594*0Sstevel@tonic-gate if (debug) fprintf(stderr, "optim1(%s,%s) returns\n", netstr, xfstr); 595*0Sstevel@tonic-gate 596*0Sstevel@tonic-gate /* 597*0Sstevel@tonic-gate * Convert back to machine names. 598*0Sstevel@tonic-gate */ 599*0Sstevel@tonic-gate 600*0Sstevel@tonic-gate cp = xfstr; 601*0Sstevel@tonic-gate *name = '\0'; 602*0Sstevel@tonic-gate while (*cp) { 603*0Sstevel@tonic-gate if ((cp2 = netname(*cp++)) == NOSTR) { 604*0Sstevel@tonic-gate printf(gettext("Made up bad net name\n")); 605*0Sstevel@tonic-gate printf(gettext("Machine code %c (0%o)\n"), cp[-1], 606*0Sstevel@tonic-gate cp[-1]); 607*0Sstevel@tonic-gate printf(gettext("Sorry.\n")); 608*0Sstevel@tonic-gate goto err; 609*0Sstevel@tonic-gate } 610*0Sstevel@tonic-gate nstrcat(name, BUFSIZ, cp2); 611*0Sstevel@tonic-gate stradd(name, BUFSIZ, *cp++); 612*0Sstevel@tonic-gate } 613*0Sstevel@tonic-gate nstrcat(name, BUFSIZ, netcomp); 614*0Sstevel@tonic-gate if (debug) fprintf(stderr, "optim returns %s in name\n", name); 615*0Sstevel@tonic-gate } 616*0Sstevel@tonic-gate 617*0Sstevel@tonic-gate /* 618*0Sstevel@tonic-gate * Take a string of network machine id's and separators and 619*0Sstevel@tonic-gate * optimize them. We process these by pulling off maximal 620*0Sstevel@tonic-gate * leading strings of the same type, passing these to the appropriate 621*0Sstevel@tonic-gate * optimizer and concatenating the results. 622*0Sstevel@tonic-gate */ 623*0Sstevel@tonic-gate 624*0Sstevel@tonic-gate static void 625*0Sstevel@tonic-gate optim1(char netstr[], char name[]) 626*0Sstevel@tonic-gate { 627*0Sstevel@tonic-gate char path[STSIZ], rpath[STSIZ]; 628*0Sstevel@tonic-gate register char *cp, *cp2; 629*0Sstevel@tonic-gate register int tp, nc; 630*0Sstevel@tonic-gate 631*0Sstevel@tonic-gate cp = netstr; 632*0Sstevel@tonic-gate prefer(cp); 633*0Sstevel@tonic-gate *name = '\0'; 634*0Sstevel@tonic-gate /* 635*0Sstevel@tonic-gate * If the address ultimately points back to us, 636*0Sstevel@tonic-gate * just return a null network path. 637*0Sstevel@tonic-gate */ 638*0Sstevel@tonic-gate if ((int)strlen(cp) > 1 && cp[strlen(cp) - 2] == LOCAL) 639*0Sstevel@tonic-gate return; 640*0Sstevel@tonic-gate while (*cp != 0) { 641*0Sstevel@tonic-gate *path = '\0'; 642*0Sstevel@tonic-gate 643*0Sstevel@tonic-gate tp = ntype(cp[1]); 644*0Sstevel@tonic-gate nc = cp[1]; 645*0Sstevel@tonic-gate while (*cp && tp == ntype(cp[1])) { 646*0Sstevel@tonic-gate stradd(path, sizeof (path), *cp++); 647*0Sstevel@tonic-gate cp++; 648*0Sstevel@tonic-gate } 649*0Sstevel@tonic-gate switch (netkind(tp)) { 650*0Sstevel@tonic-gate default: 651*0Sstevel@tonic-gate nstrcpy(rpath, sizeof (rpath), path); 652*0Sstevel@tonic-gate break; 653*0Sstevel@tonic-gate 654*0Sstevel@tonic-gate case IMPLICIT: 655*0Sstevel@tonic-gate optimimp(path, rpath); 656*0Sstevel@tonic-gate break; 657*0Sstevel@tonic-gate 658*0Sstevel@tonic-gate case EXPLICIT: 659*0Sstevel@tonic-gate optimex(path, rpath); 660*0Sstevel@tonic-gate break; 661*0Sstevel@tonic-gate } 662*0Sstevel@tonic-gate for (cp2 = rpath; *cp2 != 0; cp2++) { 663*0Sstevel@tonic-gate stradd(name, BUFSIZ, *cp2); 664*0Sstevel@tonic-gate stradd(name, BUFSIZ, nc); 665*0Sstevel@tonic-gate } 666*0Sstevel@tonic-gate } 667*0Sstevel@tonic-gate optiboth(name); 668*0Sstevel@tonic-gate prefer(name); 669*0Sstevel@tonic-gate } 670*0Sstevel@tonic-gate #endif OPTIM 671*0Sstevel@tonic-gate 672*0Sstevel@tonic-gate /* 673*0Sstevel@tonic-gate * Return the network of the separator -- 674*0Sstevel@tonic-gate * AN for arpa net 675*0Sstevel@tonic-gate * BN for Bell labs net (e.g. UUCP, NOT Berknet) 676*0Sstevel@tonic-gate * SN for Schmidt net (Berknet) 677*0Sstevel@tonic-gate * 0 if we don't know. 678*0Sstevel@tonic-gate */ 679*0Sstevel@tonic-gate static int 680*0Sstevel@tonic-gate ntype(register int nc) 681*0Sstevel@tonic-gate { 682*0Sstevel@tonic-gate register struct ntypetab *np; 683*0Sstevel@tonic-gate 684*0Sstevel@tonic-gate for (np = ntypetab; np->nt_char != 0; np++) 685*0Sstevel@tonic-gate if (np->nt_char == nc) 686*0Sstevel@tonic-gate return(np->nt_bcode); 687*0Sstevel@tonic-gate return(0); 688*0Sstevel@tonic-gate } 689*0Sstevel@tonic-gate 690*0Sstevel@tonic-gate #ifdef OPTIM 691*0Sstevel@tonic-gate /* 692*0Sstevel@tonic-gate * Return the kind of routing used for the particular net 693*0Sstevel@tonic-gate * EXPLICIT means explicitly routed 694*0Sstevel@tonic-gate * IMPLICIT means implicitly routed 695*0Sstevel@tonic-gate * 0 means don't know 696*0Sstevel@tonic-gate */ 697*0Sstevel@tonic-gate 698*0Sstevel@tonic-gate static int 699*0Sstevel@tonic-gate netkind(register int nt) 700*0Sstevel@tonic-gate { 701*0Sstevel@tonic-gate register struct nkindtab *np; 702*0Sstevel@tonic-gate 703*0Sstevel@tonic-gate for (np = nkindtab; np->nk_type != 0; np++) 704*0Sstevel@tonic-gate if (np->nk_type == nt) 705*0Sstevel@tonic-gate return(np->nk_kind); 706*0Sstevel@tonic-gate return(0); 707*0Sstevel@tonic-gate } 708*0Sstevel@tonic-gate 709*0Sstevel@tonic-gate /* 710*0Sstevel@tonic-gate * Do name optimization for an explicitly routed network (eg uucp). 711*0Sstevel@tonic-gate */ 712*0Sstevel@tonic-gate 713*0Sstevel@tonic-gate static int 714*0Sstevel@tonic-gate optimex(char net[], char name[]) 715*0Sstevel@tonic-gate { 716*0Sstevel@tonic-gate register char *cp, *rp; 717*0Sstevel@tonic-gate register int m; 718*0Sstevel@tonic-gate 719*0Sstevel@tonic-gate nstrcpy(name, STSIZ, net); 720*0Sstevel@tonic-gate cp = name; 721*0Sstevel@tonic-gate if (strlen(cp) == 0) 722*0Sstevel@tonic-gate return(-1); 723*0Sstevel@tonic-gate if (cp[strlen(cp)-1] == LOCAL) { 724*0Sstevel@tonic-gate name[0] = 0; 725*0Sstevel@tonic-gate return(0); 726*0Sstevel@tonic-gate } 727*0Sstevel@tonic-gate for (cp = name; *cp; cp++) { 728*0Sstevel@tonic-gate m = *cp; 729*0Sstevel@tonic-gate rp = strrchr(cp+1, m); 730*0Sstevel@tonic-gate if (rp != NOSTR) 731*0Sstevel@tonic-gate strcpy(cp, rp); 732*0Sstevel@tonic-gate } 733*0Sstevel@tonic-gate return(0); 734*0Sstevel@tonic-gate } 735*0Sstevel@tonic-gate 736*0Sstevel@tonic-gate /* 737*0Sstevel@tonic-gate * Do name optimization for implicitly routed network (eg, arpanet). 738*0Sstevel@tonic-gate */ 739*0Sstevel@tonic-gate 740*0Sstevel@tonic-gate static int 741*0Sstevel@tonic-gate optimimp(char net[], char name[]) 742*0Sstevel@tonic-gate { 743*0Sstevel@tonic-gate register char *cp; 744*0Sstevel@tonic-gate register char m; 745*0Sstevel@tonic-gate 746*0Sstevel@tonic-gate cp = net; 747*0Sstevel@tonic-gate if (strlen(cp) == 0) 748*0Sstevel@tonic-gate return(-1); 749*0Sstevel@tonic-gate m = cp[strlen(cp) - 1]; 750*0Sstevel@tonic-gate if (m == LOCAL) { 751*0Sstevel@tonic-gate *name = '\0'; 752*0Sstevel@tonic-gate return(0); 753*0Sstevel@tonic-gate } 754*0Sstevel@tonic-gate name[0] = m; 755*0Sstevel@tonic-gate name[1] = 0; 756*0Sstevel@tonic-gate return(0); 757*0Sstevel@tonic-gate } 758*0Sstevel@tonic-gate 759*0Sstevel@tonic-gate /* 760*0Sstevel@tonic-gate * Perform global optimization on the given network path. 761*0Sstevel@tonic-gate * The trick here is to look ahead to see if there are any loops 762*0Sstevel@tonic-gate * in the path and remove them. The interpretation of loops is 763*0Sstevel@tonic-gate * more strict here than in optimex since both the machine and net 764*0Sstevel@tonic-gate * type must match. 765*0Sstevel@tonic-gate */ 766*0Sstevel@tonic-gate 767*0Sstevel@tonic-gate static void 768*0Sstevel@tonic-gate optiboth(char net[]) 769*0Sstevel@tonic-gate { 770*0Sstevel@tonic-gate register char *cp, *cp2; 771*0Sstevel@tonic-gate 772*0Sstevel@tonic-gate cp = net; 773*0Sstevel@tonic-gate if (strlen(cp) == 0) 774*0Sstevel@tonic-gate return; 775*0Sstevel@tonic-gate if (((int)strlen(cp) % 2) != 0) { 776*0Sstevel@tonic-gate printf(gettext("Strange arg to optiboth\n")); 777*0Sstevel@tonic-gate return; 778*0Sstevel@tonic-gate } 779*0Sstevel@tonic-gate while (*cp) { 780*0Sstevel@tonic-gate cp2 = rpair(cp+2, *cp); 781*0Sstevel@tonic-gate if (cp2 != NOSTR) 782*0Sstevel@tonic-gate strcpy(cp, cp2); 783*0Sstevel@tonic-gate cp += 2; 784*0Sstevel@tonic-gate } 785*0Sstevel@tonic-gate } 786*0Sstevel@tonic-gate 787*0Sstevel@tonic-gate /* 788*0Sstevel@tonic-gate * Find the rightmost instance of the given (machine, type) pair. 789*0Sstevel@tonic-gate */ 790*0Sstevel@tonic-gate 791*0Sstevel@tonic-gate static char * 792*0Sstevel@tonic-gate rpair(char str[], int mach) 793*0Sstevel@tonic-gate { 794*0Sstevel@tonic-gate register char *cp, *last; 795*0Sstevel@tonic-gate 796*0Sstevel@tonic-gate cp = str; 797*0Sstevel@tonic-gate last = NOSTR; 798*0Sstevel@tonic-gate while (*cp) { 799*0Sstevel@tonic-gate if (*cp == mach) 800*0Sstevel@tonic-gate last = cp; 801*0Sstevel@tonic-gate cp += 2; 802*0Sstevel@tonic-gate } 803*0Sstevel@tonic-gate return(last); 804*0Sstevel@tonic-gate } 805*0Sstevel@tonic-gate 806*0Sstevel@tonic-gate /* 807*0Sstevel@tonic-gate * Change the network separators in the given network path 808*0Sstevel@tonic-gate * to the preferred network transmission means. 809*0Sstevel@tonic-gate */ 810*0Sstevel@tonic-gate 811*0Sstevel@tonic-gate static void 812*0Sstevel@tonic-gate prefer(char name[]) 813*0Sstevel@tonic-gate { 814*0Sstevel@tonic-gate register char *cp, n; 815*0Sstevel@tonic-gate register int state; 816*0Sstevel@tonic-gate 817*0Sstevel@tonic-gate state = LOCAL; 818*0Sstevel@tonic-gate for (cp = name; *cp; cp += 2) { 819*0Sstevel@tonic-gate n = best(state, *cp); 820*0Sstevel@tonic-gate if (n) 821*0Sstevel@tonic-gate cp[1] = n; 822*0Sstevel@tonic-gate state = *cp; 823*0Sstevel@tonic-gate } 824*0Sstevel@tonic-gate } 825*0Sstevel@tonic-gate 826*0Sstevel@tonic-gate /* 827*0Sstevel@tonic-gate * Return the best network separator for the given machine pair. 828*0Sstevel@tonic-gate */ 829*0Sstevel@tonic-gate 830*0Sstevel@tonic-gate static char 831*0Sstevel@tonic-gate best(int src, int dest) 832*0Sstevel@tonic-gate { 833*0Sstevel@tonic-gate register int dtype, stype; 834*0Sstevel@tonic-gate register struct netorder *np; 835*0Sstevel@tonic-gate 836*0Sstevel@tonic-gate stype = nettype(src); 837*0Sstevel@tonic-gate dtype = nettype(dest); 838*0Sstevel@tonic-gate fflush(stdout); 839*0Sstevel@tonic-gate if (stype == 0 || dtype == 0) { 840*0Sstevel@tonic-gate printf(gettext("ERROR: unknown internal machine id\n")); 841*0Sstevel@tonic-gate return(0); 842*0Sstevel@tonic-gate } 843*0Sstevel@tonic-gate if ((stype & dtype) == 0) 844*0Sstevel@tonic-gate return(0); 845*0Sstevel@tonic-gate np = &netorder[0]; 846*0Sstevel@tonic-gate while ((np->no_stat & stype & dtype) == 0) 847*0Sstevel@tonic-gate np++; 848*0Sstevel@tonic-gate return(np->no_char); 849*0Sstevel@tonic-gate } 850*0Sstevel@tonic-gate #endif OPTIM 851*0Sstevel@tonic-gate 852*0Sstevel@tonic-gate #ifdef notdef 853*0Sstevel@tonic-gate /* 854*0Sstevel@tonic-gate * Code to twist around arpa net names. 855*0Sstevel@tonic-gate */ 856*0Sstevel@tonic-gate 857*0Sstevel@tonic-gate #define WORD 257 /* Token for a string */ 858*0Sstevel@tonic-gate 859*0Sstevel@tonic-gate static char netbuf[256]; 860*0Sstevel@tonic-gate static char *yylval; 861*0Sstevel@tonic-gate 862*0Sstevel@tonic-gate /* 863*0Sstevel@tonic-gate * Reverse all of the arpa net addresses in the given name to 864*0Sstevel@tonic-gate * be of the form "host @ user" instead of "user @ host" 865*0Sstevel@tonic-gate * This function is its own inverse. 866*0Sstevel@tonic-gate */ 867*0Sstevel@tonic-gate 868*0Sstevel@tonic-gate char * 869*0Sstevel@tonic-gate revarpa(char str[]) 870*0Sstevel@tonic-gate { 871*0Sstevel@tonic-gate 872*0Sstevel@tonic-gate if (yyinit(str) < 0) 873*0Sstevel@tonic-gate return(NOSTR); 874*0Sstevel@tonic-gate if (name()) 875*0Sstevel@tonic-gate return(NOSTR); 876*0Sstevel@tonic-gate if (strcmp(str, netbuf) == 0) 877*0Sstevel@tonic-gate return(str); 878*0Sstevel@tonic-gate return(savestr(netbuf)); 879*0Sstevel@tonic-gate } 880*0Sstevel@tonic-gate 881*0Sstevel@tonic-gate /* 882*0Sstevel@tonic-gate * Parse (by recursive descent) network names, using the following grammar: 883*0Sstevel@tonic-gate * name: 884*0Sstevel@tonic-gate * term {':' term} 885*0Sstevel@tonic-gate * term {'^' term} 886*0Sstevel@tonic-gate * term {'!' term} 887*0Sstevel@tonic-gate * term '@' name 888*0Sstevel@tonic-gate * term '%' name 889*0Sstevel@tonic-gate * 890*0Sstevel@tonic-gate * term: 891*0Sstevel@tonic-gate * string of characters. 892*0Sstevel@tonic-gate */ 893*0Sstevel@tonic-gate 894*0Sstevel@tonic-gate static int 895*0Sstevel@tonic-gate name(void) 896*0Sstevel@tonic-gate { 897*0Sstevel@tonic-gate register int t; 898*0Sstevel@tonic-gate register char *cp; 899*0Sstevel@tonic-gate 900*0Sstevel@tonic-gate for (;;) { 901*0Sstevel@tonic-gate t = yylex(); 902*0Sstevel@tonic-gate if (t != WORD) 903*0Sstevel@tonic-gate return(-1); 904*0Sstevel@tonic-gate cp = yylval; 905*0Sstevel@tonic-gate t = yylex(); 906*0Sstevel@tonic-gate switch (t) { 907*0Sstevel@tonic-gate case 0: 908*0Sstevel@tonic-gate nstrcat(netbuf, sizeof (netbuf), cp); 909*0Sstevel@tonic-gate return(0); 910*0Sstevel@tonic-gate 911*0Sstevel@tonic-gate case '@': 912*0Sstevel@tonic-gate case '%': 913*0Sstevel@tonic-gate if (name()) 914*0Sstevel@tonic-gate return(-1); 915*0Sstevel@tonic-gate stradd(netbuf, sizeof (netbuf), '@'); 916*0Sstevel@tonic-gate nstrcat(netbuf, sizeof (netbuf), cp); 917*0Sstevel@tonic-gate return(0); 918*0Sstevel@tonic-gate case WORD: 919*0Sstevel@tonic-gate return(-1); 920*0Sstevel@tonic-gate 921*0Sstevel@tonic-gate default: 922*0Sstevel@tonic-gate nstrcat(netbuf, sizeof (netbuf), cp); 923*0Sstevel@tonic-gate stradd(netbuf, sizeof (netbuf), t); 924*0Sstevel@tonic-gate } 925*0Sstevel@tonic-gate } 926*0Sstevel@tonic-gate } 927*0Sstevel@tonic-gate 928*0Sstevel@tonic-gate /* 929*0Sstevel@tonic-gate * Scanner for network names. 930*0Sstevel@tonic-gate */ 931*0Sstevel@tonic-gate 932*0Sstevel@tonic-gate static char *charp; /* Current input pointer */ 933*0Sstevel@tonic-gate static int nexttok; /* Salted away next token */ 934*0Sstevel@tonic-gate 935*0Sstevel@tonic-gate /* 936*0Sstevel@tonic-gate * Initialize the network name scanner. 937*0Sstevel@tonic-gate */ 938*0Sstevel@tonic-gate 939*0Sstevel@tonic-gate int 940*0Sstevel@tonic-gate yyinit(char str[]) 941*0Sstevel@tonic-gate { 942*0Sstevel@tonic-gate static char lexbuf[BUFSIZ]; 943*0Sstevel@tonic-gate 944*0Sstevel@tonic-gate netbuf[0] = 0; 945*0Sstevel@tonic-gate if (strlen(str) >= sizeof lexbuf - 1) 946*0Sstevel@tonic-gate return(-1); 947*0Sstevel@tonic-gate nexttok = 0; 948*0Sstevel@tonic-gate nstrcpy(lexbuf, sizeof (lexbuf), str); 949*0Sstevel@tonic-gate charp = lexbuf; 950*0Sstevel@tonic-gate return(0); 951*0Sstevel@tonic-gate } 952*0Sstevel@tonic-gate 953*0Sstevel@tonic-gate /* 954*0Sstevel@tonic-gate * Scan and return a single token. 955*0Sstevel@tonic-gate * yylval is set to point to a scanned string. 956*0Sstevel@tonic-gate */ 957*0Sstevel@tonic-gate 958*0Sstevel@tonic-gate int 959*0Sstevel@tonic-gate yylex(void) 960*0Sstevel@tonic-gate { 961*0Sstevel@tonic-gate register char *cp, *dotp; 962*0Sstevel@tonic-gate register int s; 963*0Sstevel@tonic-gate 964*0Sstevel@tonic-gate if (nexttok) { 965*0Sstevel@tonic-gate s = nexttok; 966*0Sstevel@tonic-gate nexttok = 0; 967*0Sstevel@tonic-gate return(s); 968*0Sstevel@tonic-gate } 969*0Sstevel@tonic-gate cp = charp; 970*0Sstevel@tonic-gate while (*cp && isspace(*cp)) 971*0Sstevel@tonic-gate cp++; 972*0Sstevel@tonic-gate if (*cp == 0) 973*0Sstevel@tonic-gate return(0); 974*0Sstevel@tonic-gate if (any(*cp, metanet)) { 975*0Sstevel@tonic-gate charp = cp+1; 976*0Sstevel@tonic-gate return(*cp); 977*0Sstevel@tonic-gate } 978*0Sstevel@tonic-gate dotp = cp; 979*0Sstevel@tonic-gate while (*cp && !any(*cp, metanet) && !any(*cp, " \t")) 980*0Sstevel@tonic-gate cp++; 981*0Sstevel@tonic-gate if (any(*cp, metanet)) 982*0Sstevel@tonic-gate nexttok = *cp; 983*0Sstevel@tonic-gate if (*cp == 0) 984*0Sstevel@tonic-gate charp = cp; 985*0Sstevel@tonic-gate else 986*0Sstevel@tonic-gate charp = cp+1; 987*0Sstevel@tonic-gate *cp = 0; 988*0Sstevel@tonic-gate yylval = dotp; 989*0Sstevel@tonic-gate return(WORD); 990*0Sstevel@tonic-gate } 991*0Sstevel@tonic-gate #endif 992*0Sstevel@tonic-gate 993*0Sstevel@tonic-gate /* 994*0Sstevel@tonic-gate * Add a single character onto a string. Here dstsize is the size of the 995*0Sstevel@tonic-gate * destnation buffer. 996*0Sstevel@tonic-gate */ 997*0Sstevel@tonic-gate 998*0Sstevel@tonic-gate static void 999*0Sstevel@tonic-gate stradd(register char *dst, int dstsize, register int c) 1000*0Sstevel@tonic-gate { 1001*0Sstevel@tonic-gate while (*dst != '\0') { 1002*0Sstevel@tonic-gate dst++; 1003*0Sstevel@tonic-gate dstsize--; 1004*0Sstevel@tonic-gate } 1005*0Sstevel@tonic-gate if (--dstsize > 0) 1006*0Sstevel@tonic-gate *dst++ = (char)c; 1007*0Sstevel@tonic-gate *dst = '\0'; 1008*0Sstevel@tonic-gate } 1009