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