xref: /illumos-gate/usr/src/cmd/mailx/optim.c (revision 2a8bcb4e)
17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
57c478bd9Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
67c478bd9Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
77c478bd9Sstevel@tonic-gate  * with the License.
87c478bd9Sstevel@tonic-gate  *
97c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
107c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
117c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
127c478bd9Sstevel@tonic-gate  * and limitations under the License.
137c478bd9Sstevel@tonic-gate  *
147c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
157c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
167c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
177c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
187c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
197c478bd9Sstevel@tonic-gate  *
207c478bd9Sstevel@tonic-gate  * CDDL HEADER END
217c478bd9Sstevel@tonic-gate  */
227c478bd9Sstevel@tonic-gate /*
237c478bd9Sstevel@tonic-gate  * Copyright 1998 Sun Microsystems, Inc.  All rights reserved.
247c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
257c478bd9Sstevel@tonic-gate  */
267c478bd9Sstevel@tonic-gate 
277c478bd9Sstevel@tonic-gate /*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
287c478bd9Sstevel@tonic-gate /*	  All Rights Reserved  	*/
297c478bd9Sstevel@tonic-gate 
307c478bd9Sstevel@tonic-gate /*
317c478bd9Sstevel@tonic-gate  * mailx -- a modified version of a University of California at Berkeley
327c478bd9Sstevel@tonic-gate  *	mail program
337c478bd9Sstevel@tonic-gate  *
347c478bd9Sstevel@tonic-gate  * Network name modification routines.
357c478bd9Sstevel@tonic-gate  */
367c478bd9Sstevel@tonic-gate 
377c478bd9Sstevel@tonic-gate #include "rcv.h"
387c478bd9Sstevel@tonic-gate #include "configdefs.h"
397c478bd9Sstevel@tonic-gate #include <locale.h>
407c478bd9Sstevel@tonic-gate 
417c478bd9Sstevel@tonic-gate static char		*arpafix(char name[], char from[]);
427c478bd9Sstevel@tonic-gate static char		*lasthost(char *addr);
437c478bd9Sstevel@tonic-gate static char		*makeremote(char name[], char from[]);
447c478bd9Sstevel@tonic-gate static int		mstash(char name[], int attnet);
457c478bd9Sstevel@tonic-gate static int		mtype(int mid);
467c478bd9Sstevel@tonic-gate static int		netlook(char machine[], int attnet);
477c478bd9Sstevel@tonic-gate static int		nettype(int mid);
487c478bd9Sstevel@tonic-gate static int		ntype(register int nc);
497c478bd9Sstevel@tonic-gate static void		stradd(register char *str, int n, register int c);
507c478bd9Sstevel@tonic-gate static char		*tackon(char *sys, char *rest);
517c478bd9Sstevel@tonic-gate static struct xtrahash	*xlocate(char name[]);
527c478bd9Sstevel@tonic-gate #ifdef OPTIM
537c478bd9Sstevel@tonic-gate static char		best(int src, int dest);
547c478bd9Sstevel@tonic-gate static char		*mlook(int mid);
557c478bd9Sstevel@tonic-gate static int		netkind(register int nt);
567c478bd9Sstevel@tonic-gate static void		optiboth(char net[]);
577c478bd9Sstevel@tonic-gate static void		optim(char net[], char name[]);
587c478bd9Sstevel@tonic-gate static void		optim1(char netstr[], char name[]);
597c478bd9Sstevel@tonic-gate static int		optimex(char net[], char name[]);
607c478bd9Sstevel@tonic-gate static int		optimimp(char net[], char name[]);
617c478bd9Sstevel@tonic-gate static void		prefer(char name[]);
627c478bd9Sstevel@tonic-gate static char		*rpair(char str[], int mach);
637c478bd9Sstevel@tonic-gate #endif
647c478bd9Sstevel@tonic-gate 
657c478bd9Sstevel@tonic-gate /*
667c478bd9Sstevel@tonic-gate  * Map a name into the correct network "view" of the
677c478bd9Sstevel@tonic-gate  * name.  This is done by prepending the name with the
687c478bd9Sstevel@tonic-gate  * network address of the sender, then optimizing away
697c478bd9Sstevel@tonic-gate  * nonsense.
707c478bd9Sstevel@tonic-gate  */
717c478bd9Sstevel@tonic-gate 
727c478bd9Sstevel@tonic-gate char *
netmap(char name[],char from[])737c478bd9Sstevel@tonic-gate netmap(char name[], char from[])
747c478bd9Sstevel@tonic-gate {
757c478bd9Sstevel@tonic-gate 	char nbuf[BUFSIZ], ret[BUFSIZ];
767c478bd9Sstevel@tonic-gate 	register char *cp, *oname;
777c478bd9Sstevel@tonic-gate 
787c478bd9Sstevel@tonic-gate 	if (debug) fprintf(stderr, "netmap(name '%s', from '%s')\n", name, from);
797c478bd9Sstevel@tonic-gate 	if (strlen(from) == 0)
807c478bd9Sstevel@tonic-gate 		return(name);	/* "from" is empty - can't do anything */
817c478bd9Sstevel@tonic-gate 
827c478bd9Sstevel@tonic-gate 	if (strcmp(from, name) == 0)
837c478bd9Sstevel@tonic-gate 		return(name);	/* "from" and "name" are the same, do nothing */
847c478bd9Sstevel@tonic-gate 
857c478bd9Sstevel@tonic-gate 	/*
867c478bd9Sstevel@tonic-gate 	 * If the name contains an "@" or a "%", remove it and the host
877c478bd9Sstevel@tonic-gate 	 * following it if that host is "known".
887c478bd9Sstevel@tonic-gate 	 */
897c478bd9Sstevel@tonic-gate 	if (any('@', name) || any('%', name))
907c478bd9Sstevel@tonic-gate 		return(arpafix(name, from));
917c478bd9Sstevel@tonic-gate 
927c478bd9Sstevel@tonic-gate 	/*
937c478bd9Sstevel@tonic-gate 	 * If the sender contains a "@" or a "%", make "name" into an
947c478bd9Sstevel@tonic-gate 	 * address on that host, on the presumption that it should
957c478bd9Sstevel@tonic-gate 	 * really have read "name@from" when we received the message
967c478bd9Sstevel@tonic-gate 	 * rather than just "name".
977c478bd9Sstevel@tonic-gate 	 */
987c478bd9Sstevel@tonic-gate 	if (any('@', from) || any('%', from))
997c478bd9Sstevel@tonic-gate 		return(unuucp(makeremote(name, from)));
1007c478bd9Sstevel@tonic-gate 	if (value("onehop") && (cp = strchr(name, '!')) && cp > name) {
1017c478bd9Sstevel@tonic-gate 		/*
1027c478bd9Sstevel@tonic-gate 		 * "onehop" is set, meaning all machines are one UUCP
1037c478bd9Sstevel@tonic-gate 		 * hop away (fat chance, in this day and age), and "name"
1047c478bd9Sstevel@tonic-gate 		 * is a UUCP path rather than just a name.  Leave it alone.
1057c478bd9Sstevel@tonic-gate 		 */
1067c478bd9Sstevel@tonic-gate 		nstrcpy(nbuf, sizeof (nbuf), name);
1077c478bd9Sstevel@tonic-gate 	} else {
1087c478bd9Sstevel@tonic-gate 		from = tackon(host, from);
1097c478bd9Sstevel@tonic-gate 		*strrchr(from, '!') = 0;
1107c478bd9Sstevel@tonic-gate 		name = tackon(lasthost(from), name);
1117c478bd9Sstevel@tonic-gate 		while (((cp = lasthost(from)) != 0) && ishost(cp, name)) {
1127c478bd9Sstevel@tonic-gate 			oname = name;
1137c478bd9Sstevel@tonic-gate 			name = strchr(name, '!') + 1;
1147c478bd9Sstevel@tonic-gate 			if (cp == from) {
1157c478bd9Sstevel@tonic-gate 				from[strlen(from)] = '!';
1167c478bd9Sstevel@tonic-gate 				if (value("mustbang") && !strchr(name, '!'))
1177c478bd9Sstevel@tonic-gate 					name = oname;
1187c478bd9Sstevel@tonic-gate 				return(unuucp(name));
1197c478bd9Sstevel@tonic-gate 			}
1207c478bd9Sstevel@tonic-gate 			*--cp = 0;
1217c478bd9Sstevel@tonic-gate 		}
1227c478bd9Sstevel@tonic-gate 		from[strlen(from)] = '!';
1237c478bd9Sstevel@tonic-gate 		from = strchr(from, '!') + 1;
1247c478bd9Sstevel@tonic-gate 		snprintf(nbuf, sizeof (nbuf), "%s!%s", from, name);
1257c478bd9Sstevel@tonic-gate 	}
1267c478bd9Sstevel@tonic-gate 	if (debug) fprintf(stderr, "before optim, nbuf '%s'\n", name);
1277c478bd9Sstevel@tonic-gate #ifdef	OPTIM
1287c478bd9Sstevel@tonic-gate 	if ((cp = value("conv"))==NOSTR || strcmp(cp, "optimize") != 0)
1297c478bd9Sstevel@tonic-gate 		nstrcpy(ret, sizeof (ret), nbuf);
1307c478bd9Sstevel@tonic-gate 	else
1317c478bd9Sstevel@tonic-gate 		optim(nbuf, ret);
1327c478bd9Sstevel@tonic-gate #else
1337c478bd9Sstevel@tonic-gate 	nstrcpy(ret, sizeof (ret), nbuf);
1346c83d09fSrobbin #endif	/* OPTIM */
1357c478bd9Sstevel@tonic-gate 	if (debug) fprintf(stderr, "after  optim, nbuf '%s', ret '%s'\n", nbuf, ret);
1367c478bd9Sstevel@tonic-gate 	cp = ret;
1377c478bd9Sstevel@tonic-gate 	if (debug) fprintf(stderr, "wind up with '%s'\n", name);
1387c478bd9Sstevel@tonic-gate 	if (!icequal(name, cp))
1397c478bd9Sstevel@tonic-gate 		return(unuucp((char *) savestr(cp)));
1407c478bd9Sstevel@tonic-gate 	return(unuucp(name));
1417c478bd9Sstevel@tonic-gate }
1427c478bd9Sstevel@tonic-gate 
1437c478bd9Sstevel@tonic-gate /*
1447c478bd9Sstevel@tonic-gate  * Stick a host on the beginning of a uucp
1457c478bd9Sstevel@tonic-gate  * address if it isn't there already.
1467c478bd9Sstevel@tonic-gate  */
1477c478bd9Sstevel@tonic-gate static char *
tackon(char * sys,char * rest)1487c478bd9Sstevel@tonic-gate tackon(char *sys, char *rest)
1497c478bd9Sstevel@tonic-gate {
1507c478bd9Sstevel@tonic-gate 	while (*rest == '!')
1517c478bd9Sstevel@tonic-gate 		rest++;
1527c478bd9Sstevel@tonic-gate 	if (!ishost(sys, rest)) {
1537c478bd9Sstevel@tonic-gate 		char *r = (char *)salloc(strlen(sys) + strlen(rest) + 2);
1547c478bd9Sstevel@tonic-gate 		sprintf(r, "%s!%s", sys, rest);
1557c478bd9Sstevel@tonic-gate 		rest = r;
1567c478bd9Sstevel@tonic-gate 	}
1577c478bd9Sstevel@tonic-gate 	return rest;
1587c478bd9Sstevel@tonic-gate }
1597c478bd9Sstevel@tonic-gate 
1607c478bd9Sstevel@tonic-gate /*
1617c478bd9Sstevel@tonic-gate  * Check equality of the first host in a uucp address.
1627c478bd9Sstevel@tonic-gate  */
163*2a8bcb4eSToomas Soome int
ishost(char * sys,char * rest)1647c478bd9Sstevel@tonic-gate ishost(char *sys, char *rest)
1657c478bd9Sstevel@tonic-gate {
1667c478bd9Sstevel@tonic-gate 	while (*sys && *sys == *rest)
1677c478bd9Sstevel@tonic-gate 		sys++, rest++;
1687c478bd9Sstevel@tonic-gate 	return(*sys == 0 && *rest == '!');
1697c478bd9Sstevel@tonic-gate }
1707c478bd9Sstevel@tonic-gate 
1717c478bd9Sstevel@tonic-gate /*
1727c478bd9Sstevel@tonic-gate  * Return last host in a uucp address.
1737c478bd9Sstevel@tonic-gate  */
1747c478bd9Sstevel@tonic-gate static char *
lasthost(char * addr)1757c478bd9Sstevel@tonic-gate lasthost(char *addr)
1767c478bd9Sstevel@tonic-gate {
1777c478bd9Sstevel@tonic-gate 	char *r = strrchr(addr, '!');
1787c478bd9Sstevel@tonic-gate 	return r ? ++r : addr;
1797c478bd9Sstevel@tonic-gate }
1807c478bd9Sstevel@tonic-gate 
1817c478bd9Sstevel@tonic-gate /*
1827c478bd9Sstevel@tonic-gate  * Optionally translate an old format uucp name into a new one, e.g.
1837c478bd9Sstevel@tonic-gate  * "mach1!mach2!user" becomes "user@mach2.UUCP".  This optional because
1847c478bd9Sstevel@tonic-gate  * some information is necessarily lost (e.g. the route it got here
1857c478bd9Sstevel@tonic-gate  * via) and if we don't have the host in our routing tables, we lose.
1867c478bd9Sstevel@tonic-gate  * XXX THIS IS NO LONGER VALID WITH THE NEW UUCP PROJECT PLANS TO
1877c478bd9Sstevel@tonic-gate  * REGISTER UUCP HOSTS IN THE STANDARD INTERNET NAMESPACE, E.G.
1887c478bd9Sstevel@tonic-gate  * ihnp4 BECOMES "ihnp4.att.com".
1897c478bd9Sstevel@tonic-gate  */
1907c478bd9Sstevel@tonic-gate char *
unuucp(char * name)1917c478bd9Sstevel@tonic-gate unuucp(char *name)
1927c478bd9Sstevel@tonic-gate {
1937c478bd9Sstevel@tonic-gate 	register char *np, *hp, *cp;
1947c478bd9Sstevel@tonic-gate 	char result[100];
1957c478bd9Sstevel@tonic-gate 	char tname[300];
1967c478bd9Sstevel@tonic-gate 
1977c478bd9Sstevel@tonic-gate 	if (UnUUCP==0 &&
1987c478bd9Sstevel@tonic-gate 	    ((cp = value("conv"))==NOSTR || strcmp(cp, "internet")))
1997c478bd9Sstevel@tonic-gate 		return name;
2007c478bd9Sstevel@tonic-gate 	if (debug) fprintf(stderr, "unuucp(%s)\n", name);
2017c478bd9Sstevel@tonic-gate 	nstrcpy(tname, sizeof (tname), name);
2027c478bd9Sstevel@tonic-gate 	np = strrchr(tname, '!');
2037c478bd9Sstevel@tonic-gate 	if (np == NOSTR)
2047c478bd9Sstevel@tonic-gate 		return name;
2057c478bd9Sstevel@tonic-gate 	*np++ = 0;
2067c478bd9Sstevel@tonic-gate 	hp = strrchr(tname, '!');
2077c478bd9Sstevel@tonic-gate 	if (hp == NOSTR)
2087c478bd9Sstevel@tonic-gate 		hp = tname;
2097c478bd9Sstevel@tonic-gate 	else
2107c478bd9Sstevel@tonic-gate 		*hp++ = 0;
2117c478bd9Sstevel@tonic-gate 	cp = strchr(np, '@');
2127c478bd9Sstevel@tonic-gate 	if (cp == NOSTR)
2137c478bd9Sstevel@tonic-gate 		cp = strchr(np, '%');
2147c478bd9Sstevel@tonic-gate 	if (cp)
2157c478bd9Sstevel@tonic-gate 		*cp = 0;
2167c478bd9Sstevel@tonic-gate 	if (debug) fprintf(stderr, "host %s, name %s\n", hp, np);
2177c478bd9Sstevel@tonic-gate 	snprintf(result, sizeof (result), "%s@%s.UUCP", np, hp);
2187c478bd9Sstevel@tonic-gate 	if (debug) fprintf(stderr, "unuucp returns %s\n", result);
2197c478bd9Sstevel@tonic-gate 	return savestr(result);
2207c478bd9Sstevel@tonic-gate }
2217c478bd9Sstevel@tonic-gate 
2227c478bd9Sstevel@tonic-gate /*
2237c478bd9Sstevel@tonic-gate  * Turn a network machine name into a unique character
2247c478bd9Sstevel@tonic-gate  */
225*2a8bcb4eSToomas Soome static int
netlook(char machine[],int attnet)2267c478bd9Sstevel@tonic-gate netlook(char machine[], int attnet)
2277c478bd9Sstevel@tonic-gate {
2287c478bd9Sstevel@tonic-gate 	register struct netmach *np;
2297c478bd9Sstevel@tonic-gate 	register char *cp, *cp2;
2307c478bd9Sstevel@tonic-gate 	char nbuf[BUFSIZ];
2317c478bd9Sstevel@tonic-gate 
2327c478bd9Sstevel@tonic-gate 	/*
2337c478bd9Sstevel@tonic-gate 	 * Make into lower case.
2347c478bd9Sstevel@tonic-gate 	 */
2357c478bd9Sstevel@tonic-gate 	for (cp = machine, cp2 = nbuf;
2367c478bd9Sstevel@tonic-gate 	     *cp && cp2 < &nbuf[BUFSIZ-1];
2377c478bd9Sstevel@tonic-gate 	     *cp2++ = tolower(*cp++))
2387c478bd9Sstevel@tonic-gate 		/*nothing*/;
2397c478bd9Sstevel@tonic-gate 	*cp2 = 0;
2407c478bd9Sstevel@tonic-gate 
2417c478bd9Sstevel@tonic-gate 	/*
2427c478bd9Sstevel@tonic-gate 	 * If a single letter machine, look through those first.
2437c478bd9Sstevel@tonic-gate 	 */
2447c478bd9Sstevel@tonic-gate 
2457c478bd9Sstevel@tonic-gate 	if (strlen(nbuf) == 1)
2467c478bd9Sstevel@tonic-gate 		for (np = netmach; np->nt_mid != 0; np++)
2477c478bd9Sstevel@tonic-gate 			if (np->nt_mid == nbuf[0])
2487c478bd9Sstevel@tonic-gate 				return(nbuf[0]);
2497c478bd9Sstevel@tonic-gate 
2507c478bd9Sstevel@tonic-gate 	/*
2517c478bd9Sstevel@tonic-gate 	 * Look for usual name
2527c478bd9Sstevel@tonic-gate 	 */
2537c478bd9Sstevel@tonic-gate 
2547c478bd9Sstevel@tonic-gate 	for (np = netmach; np->nt_mid != 0; np++)
2557c478bd9Sstevel@tonic-gate 		if (strcmp(np->nt_machine, nbuf) == 0)
2567c478bd9Sstevel@tonic-gate 			return(np->nt_mid);
2577c478bd9Sstevel@tonic-gate 
2587c478bd9Sstevel@tonic-gate 	/*
2597c478bd9Sstevel@tonic-gate 	 * Look in side hash table.
2607c478bd9Sstevel@tonic-gate 	 */
2617c478bd9Sstevel@tonic-gate 
2627c478bd9Sstevel@tonic-gate 	return(mstash(nbuf, attnet));
2637c478bd9Sstevel@tonic-gate }
2647c478bd9Sstevel@tonic-gate 
2657c478bd9Sstevel@tonic-gate #ifdef OPTIM
2667c478bd9Sstevel@tonic-gate /*
2677c478bd9Sstevel@tonic-gate  * Turn a network unique character identifier into a network name.
2687c478bd9Sstevel@tonic-gate  */
2697c478bd9Sstevel@tonic-gate 
2707c478bd9Sstevel@tonic-gate static char *
netname(int mid)2717c478bd9Sstevel@tonic-gate netname(int mid)
2727c478bd9Sstevel@tonic-gate {
2737c478bd9Sstevel@tonic-gate 	register struct netmach *np;
2747c478bd9Sstevel@tonic-gate 
2757c478bd9Sstevel@tonic-gate 	if (mid & 0200)
2767c478bd9Sstevel@tonic-gate 		return(mlook(mid));
2777c478bd9Sstevel@tonic-gate 	for (np = netmach; np->nt_mid != 0; np++)
2787c478bd9Sstevel@tonic-gate 		if (np->nt_mid == mid)
2797c478bd9Sstevel@tonic-gate 			return(np->nt_machine);
2807c478bd9Sstevel@tonic-gate 	return(NOSTR);
2817c478bd9Sstevel@tonic-gate }
2827c478bd9Sstevel@tonic-gate #endif
2837c478bd9Sstevel@tonic-gate 
2847c478bd9Sstevel@tonic-gate /*
2857c478bd9Sstevel@tonic-gate  * Deal with arpa net addresses.  The way this is done is strange.
2867c478bd9Sstevel@tonic-gate  * name contains an "@" or "%".  Look up the machine after it in
2877c478bd9Sstevel@tonic-gate  * the hash table.  If it isn't found, return name unmolested.
2887c478bd9Sstevel@tonic-gate  * If ???, return name unmolested.
2897c478bd9Sstevel@tonic-gate  * Otherwise, delete the "@" or "%" and the machine after it from
2907c478bd9Sstevel@tonic-gate  * name, and return the new string.
2917c478bd9Sstevel@tonic-gate  */
2927c478bd9Sstevel@tonic-gate static char *
arpafix(char name[],char from[])2937c478bd9Sstevel@tonic-gate arpafix(char name[], char from[])
2947c478bd9Sstevel@tonic-gate {
2957c478bd9Sstevel@tonic-gate 	register char *cp;
2967c478bd9Sstevel@tonic-gate 	register int arpamach;
2977c478bd9Sstevel@tonic-gate 	char newname[BUFSIZ];
2987c478bd9Sstevel@tonic-gate 
2997c478bd9Sstevel@tonic-gate 	if (debug) {
3007c478bd9Sstevel@tonic-gate 		fprintf(stderr, "arpafix(%s, %s)\n", name, from);
3017c478bd9Sstevel@tonic-gate 	}
3027c478bd9Sstevel@tonic-gate 	cp = strrchr(name, '@');
3037c478bd9Sstevel@tonic-gate 	if (cp == NOSTR)
3047c478bd9Sstevel@tonic-gate 		cp = strrchr(name, '%');
3057c478bd9Sstevel@tonic-gate 	if (cp == NOSTR) {
3067c478bd9Sstevel@tonic-gate 		fprintf(stderr,
3077c478bd9Sstevel@tonic-gate 		    gettext("Something's amiss -- no @ or %% in arpafix\n"));
3087c478bd9Sstevel@tonic-gate 		return(name);
3097c478bd9Sstevel@tonic-gate 	}
3107c478bd9Sstevel@tonic-gate 	cp++;
3117c478bd9Sstevel@tonic-gate 	arpamach = netlook(cp, '@');
3127c478bd9Sstevel@tonic-gate 	if (debug)
3137c478bd9Sstevel@tonic-gate 		fprintf(stderr,
3147c478bd9Sstevel@tonic-gate 		    "cp '%s', arpamach %o, nettypes arpamach %o LOCAL %o\n",
3157c478bd9Sstevel@tonic-gate 		    cp, arpamach, nettype(arpamach), nettype(LOCAL));
3167c478bd9Sstevel@tonic-gate 	if (arpamach == 0) {
3177c478bd9Sstevel@tonic-gate 		if (debug)
3187c478bd9Sstevel@tonic-gate 			fprintf(stderr, "machine %s unknown, uses: %s\n",
3197c478bd9Sstevel@tonic-gate 			    cp, name);
3207c478bd9Sstevel@tonic-gate 		return(name);
3217c478bd9Sstevel@tonic-gate 	}
3227c478bd9Sstevel@tonic-gate 	if (((nettype(arpamach) & nettype(LOCAL)) & ~AN) == 0) {
3237c478bd9Sstevel@tonic-gate 		if (debug)
3247c478bd9Sstevel@tonic-gate 			fprintf(stderr, "machine %s known but remote, uses: %s\n",
3257c478bd9Sstevel@tonic-gate 			    cp, name);
3267c478bd9Sstevel@tonic-gate 		return(name);
3277c478bd9Sstevel@tonic-gate 	}
3287c478bd9Sstevel@tonic-gate 	nstrcpy(newname, sizeof (newname), name);
3297c478bd9Sstevel@tonic-gate 	cp = strrchr(newname, '@');
3307c478bd9Sstevel@tonic-gate 	if (cp == NOSTR)
3317c478bd9Sstevel@tonic-gate 		cp = strrchr(newname, '%');
3327c478bd9Sstevel@tonic-gate 	*cp = 0;
3337c478bd9Sstevel@tonic-gate 	if (debug) fprintf(stderr, "local address, return '%s'\n", newname);
3347c478bd9Sstevel@tonic-gate 	return(savestr(newname));
3357c478bd9Sstevel@tonic-gate }
3367c478bd9Sstevel@tonic-gate 
3377c478bd9Sstevel@tonic-gate /*
3387c478bd9Sstevel@tonic-gate  * We have name with no @'s in it, and from with @'s.
3397c478bd9Sstevel@tonic-gate  * Assume that name is meaningful only on the site in from,
3407c478bd9Sstevel@tonic-gate  * and return "name@site_in_from".
3417c478bd9Sstevel@tonic-gate  */
3427c478bd9Sstevel@tonic-gate static char *
makeremote(char name[],char from[])3437c478bd9Sstevel@tonic-gate makeremote(char name[], char from[])
3447c478bd9Sstevel@tonic-gate {
3457c478bd9Sstevel@tonic-gate 	register char *cp;
3467c478bd9Sstevel@tonic-gate 	char rbuf[BUFSIZ];
3477c478bd9Sstevel@tonic-gate 
3487c478bd9Sstevel@tonic-gate 	if (!value("makeremote"))
3497c478bd9Sstevel@tonic-gate 		return(name);
3507c478bd9Sstevel@tonic-gate 	if (debug) fprintf(stderr, "makeremote(%s, %s) returns ", name, from);
3517c478bd9Sstevel@tonic-gate 	cp = strrchr(from, '@');
3527c478bd9Sstevel@tonic-gate 	if (cp == NOSTR)
3537c478bd9Sstevel@tonic-gate 		cp = strrchr(from, '%');
3547c478bd9Sstevel@tonic-gate 	snprintf(rbuf, sizeof (rbuf), "%s%s", name, cp);
3557c478bd9Sstevel@tonic-gate 	if (debug) fprintf(stderr, "%s\n", rbuf);
3567c478bd9Sstevel@tonic-gate 	return(savestr(rbuf));
3577c478bd9Sstevel@tonic-gate }
3587c478bd9Sstevel@tonic-gate 
3597c478bd9Sstevel@tonic-gate /*
3607c478bd9Sstevel@tonic-gate  * Take a network machine descriptor and find the types of connected
3617c478bd9Sstevel@tonic-gate  * nets and return it.
3627c478bd9Sstevel@tonic-gate  */
363*2a8bcb4eSToomas Soome static int
nettype(int mid)3647c478bd9Sstevel@tonic-gate nettype(int mid)
3657c478bd9Sstevel@tonic-gate {
3667c478bd9Sstevel@tonic-gate 	register struct netmach *np;
3677c478bd9Sstevel@tonic-gate 
3687c478bd9Sstevel@tonic-gate 	if (mid & 0200)
3697c478bd9Sstevel@tonic-gate 		return(mtype(mid));
3707c478bd9Sstevel@tonic-gate 	for (np = netmach; np->nt_mid != 0; np++)
3717c478bd9Sstevel@tonic-gate 		if (np->nt_mid == mid)
3727c478bd9Sstevel@tonic-gate 			return(np->nt_type);
3737c478bd9Sstevel@tonic-gate 	return(0);
3747c478bd9Sstevel@tonic-gate }
3757c478bd9Sstevel@tonic-gate 
3767c478bd9Sstevel@tonic-gate /*
3777c478bd9Sstevel@tonic-gate  * Hashing routines to salt away machines seen scanning
3787c478bd9Sstevel@tonic-gate  * networks paths that we don't know about.
3797c478bd9Sstevel@tonic-gate  */
3807c478bd9Sstevel@tonic-gate 
3817c478bd9Sstevel@tonic-gate #define	XHSIZE		97		/* Size of extra hash table */
3827c478bd9Sstevel@tonic-gate #define	NXMID		(XHSIZE*3/4)	/* Max extra machines */
3837c478bd9Sstevel@tonic-gate 
3847c478bd9Sstevel@tonic-gate struct xtrahash {
3857c478bd9Sstevel@tonic-gate 	char	*xh_name;		/* Name of machine */
3867c478bd9Sstevel@tonic-gate 	short	xh_mid;			/* Machine ID */
3877c478bd9Sstevel@tonic-gate 	short	xh_attnet;		/* Attached networks */
3887c478bd9Sstevel@tonic-gate } xtrahash[XHSIZE];
3897c478bd9Sstevel@tonic-gate 
3907c478bd9Sstevel@tonic-gate static struct xtrahash	*xtab[XHSIZE];		/* F: mid-->machine name */
3917c478bd9Sstevel@tonic-gate 
3927c478bd9Sstevel@tonic-gate static short	midfree;			/* Next free machine id */
3937c478bd9Sstevel@tonic-gate 
3947c478bd9Sstevel@tonic-gate /*
3957c478bd9Sstevel@tonic-gate  * Initialize the extra host hash table.
3967c478bd9Sstevel@tonic-gate  * Called by sreset.
3977c478bd9Sstevel@tonic-gate  */
398*2a8bcb4eSToomas Soome void
minit(void)3997c478bd9Sstevel@tonic-gate minit(void)
4007c478bd9Sstevel@tonic-gate {
4017c478bd9Sstevel@tonic-gate 	register struct xtrahash *xp, **tp;
4027c478bd9Sstevel@tonic-gate 
4037c478bd9Sstevel@tonic-gate 	midfree = 0;
4047c478bd9Sstevel@tonic-gate 	tp = &xtab[0];
4057c478bd9Sstevel@tonic-gate 	for (xp = &xtrahash[0]; xp < &xtrahash[XHSIZE]; xp++) {
4067c478bd9Sstevel@tonic-gate 		xp->xh_name = NOSTR;
4077c478bd9Sstevel@tonic-gate 		xp->xh_mid = 0;
4087c478bd9Sstevel@tonic-gate 		xp->xh_attnet = 0;
4097c478bd9Sstevel@tonic-gate 		*tp++ = (struct xtrahash *) 0;
4107c478bd9Sstevel@tonic-gate 	}
4117c478bd9Sstevel@tonic-gate }
4127c478bd9Sstevel@tonic-gate 
4137c478bd9Sstevel@tonic-gate /*
4147c478bd9Sstevel@tonic-gate  * Stash a net name in the extra host hash table.
4157c478bd9Sstevel@tonic-gate  * If a new entry is put in the hash table, deduce what
4167c478bd9Sstevel@tonic-gate  * net the machine is attached to from the net character.
4177c478bd9Sstevel@tonic-gate  *
4187c478bd9Sstevel@tonic-gate  * If the machine is already known, add the given attached
4197c478bd9Sstevel@tonic-gate  * net to those already known.
4207c478bd9Sstevel@tonic-gate  */
421*2a8bcb4eSToomas Soome static int
mstash(char name[],int attnet)4227c478bd9Sstevel@tonic-gate mstash(char name[], int attnet)
4237c478bd9Sstevel@tonic-gate {
4247c478bd9Sstevel@tonic-gate 	register struct xtrahash *xp;
4257c478bd9Sstevel@tonic-gate 	int x;
4267c478bd9Sstevel@tonic-gate 
4277c478bd9Sstevel@tonic-gate 	xp = xlocate(name);
4287c478bd9Sstevel@tonic-gate 	if (xp == (struct xtrahash *) 0) {
4297c478bd9Sstevel@tonic-gate 		printf(gettext("Ran out of machine id spots\n"));
4307c478bd9Sstevel@tonic-gate 		return(0);
4317c478bd9Sstevel@tonic-gate 	}
4327c478bd9Sstevel@tonic-gate 	if (xp->xh_name == NOSTR) {
4337c478bd9Sstevel@tonic-gate 		if (midfree >= XHSIZE) {
4347c478bd9Sstevel@tonic-gate 			printf(gettext("Out of machine ids\n"));
4357c478bd9Sstevel@tonic-gate 			return(0);
4367c478bd9Sstevel@tonic-gate 		}
4377c478bd9Sstevel@tonic-gate 		xtab[midfree] = xp;
4387c478bd9Sstevel@tonic-gate 		xp->xh_name = savestr(name);
4397c478bd9Sstevel@tonic-gate 		xp->xh_mid = 0200 + midfree++;
4407c478bd9Sstevel@tonic-gate 	}
4417c478bd9Sstevel@tonic-gate 	x = ntype(attnet);
4427c478bd9Sstevel@tonic-gate 	if (x == 0)
4437c478bd9Sstevel@tonic-gate 		xp->xh_attnet |= AN;
4447c478bd9Sstevel@tonic-gate 	else
4457c478bd9Sstevel@tonic-gate 		xp->xh_attnet |= x;
4467c478bd9Sstevel@tonic-gate 	return(xp->xh_mid);
4477c478bd9Sstevel@tonic-gate }
4487c478bd9Sstevel@tonic-gate 
4497c478bd9Sstevel@tonic-gate /*
4507c478bd9Sstevel@tonic-gate  * Search for the given name in the hash table
4517c478bd9Sstevel@tonic-gate  * and return the pointer to it if found, or to the first
4527c478bd9Sstevel@tonic-gate  * empty slot if not found.
4537c478bd9Sstevel@tonic-gate  *
4547c478bd9Sstevel@tonic-gate  * If no free slots can be found, return 0.
4557c478bd9Sstevel@tonic-gate  */
4567c478bd9Sstevel@tonic-gate 
4577c478bd9Sstevel@tonic-gate static struct xtrahash *
xlocate(char name[])4587c478bd9Sstevel@tonic-gate xlocate(char name[])
4597c478bd9Sstevel@tonic-gate {
4607c478bd9Sstevel@tonic-gate 	register int h, q, i;
4617c478bd9Sstevel@tonic-gate 	register char *cp;
4627c478bd9Sstevel@tonic-gate 	register struct xtrahash *xp;
4637c478bd9Sstevel@tonic-gate 
4647c478bd9Sstevel@tonic-gate 	for (h = 0, cp = name; *cp; h = (h << 2) + *cp++)
4657c478bd9Sstevel@tonic-gate 		;
4667c478bd9Sstevel@tonic-gate 	if (h < 0 && (h = -h) < 0)
4677c478bd9Sstevel@tonic-gate 		h = 0;
4687c478bd9Sstevel@tonic-gate 	h = h % XHSIZE;
4697c478bd9Sstevel@tonic-gate 	cp = name;
4707c478bd9Sstevel@tonic-gate 	for (i = 0, q = 0; q < XHSIZE; i++, q = i * i) {
4717c478bd9Sstevel@tonic-gate 		xp = &xtrahash[(h + q) % XHSIZE];
4727c478bd9Sstevel@tonic-gate 		if (xp->xh_name == NOSTR)
4737c478bd9Sstevel@tonic-gate 			return(xp);
4747c478bd9Sstevel@tonic-gate 		if (strcmp(cp, xp->xh_name) == 0)
4757c478bd9Sstevel@tonic-gate 			return(xp);
4767c478bd9Sstevel@tonic-gate 		if (h - q < 0)
4777c478bd9Sstevel@tonic-gate 			h += XHSIZE;
4787c478bd9Sstevel@tonic-gate 		xp = &xtrahash[(h - q) % XHSIZE];
4797c478bd9Sstevel@tonic-gate 		if (xp->xh_name == NOSTR)
4807c478bd9Sstevel@tonic-gate 			return(xp);
4817c478bd9Sstevel@tonic-gate 		if (strcmp(cp, xp->xh_name) == 0)
4827c478bd9Sstevel@tonic-gate 			return(xp);
4837c478bd9Sstevel@tonic-gate 	}
4847c478bd9Sstevel@tonic-gate 	return((struct xtrahash *) 0);
4857c478bd9Sstevel@tonic-gate }
4867c478bd9Sstevel@tonic-gate 
4877c478bd9Sstevel@tonic-gate #ifdef OPTIM
4887c478bd9Sstevel@tonic-gate /*
4897c478bd9Sstevel@tonic-gate  * Return the name from the extra host hash table corresponding
4907c478bd9Sstevel@tonic-gate  * to the passed machine id.
4917c478bd9Sstevel@tonic-gate  */
4927c478bd9Sstevel@tonic-gate 
4937c478bd9Sstevel@tonic-gate static char *
mlook(int mid)4947c478bd9Sstevel@tonic-gate mlook(int mid)
4957c478bd9Sstevel@tonic-gate {
4967c478bd9Sstevel@tonic-gate 	register int m;
4977c478bd9Sstevel@tonic-gate 
4987c478bd9Sstevel@tonic-gate 	if ((mid & 0200) == 0)
4997c478bd9Sstevel@tonic-gate 		return(NOSTR);
5007c478bd9Sstevel@tonic-gate 	m = mid & 0177;
5017c478bd9Sstevel@tonic-gate 	if (m >= midfree) {
5027c478bd9Sstevel@tonic-gate 		printf(gettext("Use made of undefined machine id\n"));
5037c478bd9Sstevel@tonic-gate 		return(NOSTR);
5047c478bd9Sstevel@tonic-gate 	}
5057c478bd9Sstevel@tonic-gate 	return(xtab[m]->xh_name);
5067c478bd9Sstevel@tonic-gate }
5077c478bd9Sstevel@tonic-gate #endif
5087c478bd9Sstevel@tonic-gate 
5097c478bd9Sstevel@tonic-gate /*
5107c478bd9Sstevel@tonic-gate  * Return the bit mask of net's that the given extra host machine
5117c478bd9Sstevel@tonic-gate  * id has so far.
5127c478bd9Sstevel@tonic-gate  */
513*2a8bcb4eSToomas Soome static int
mtype(int mid)5147c478bd9Sstevel@tonic-gate mtype(int mid)
5157c478bd9Sstevel@tonic-gate {
5167c478bd9Sstevel@tonic-gate 	register int m;
5177c478bd9Sstevel@tonic-gate 
5187c478bd9Sstevel@tonic-gate 	if ((mid & 0200) == 0)
5197c478bd9Sstevel@tonic-gate 		return(0);
5207c478bd9Sstevel@tonic-gate 	m = mid & 0177;
5217c478bd9Sstevel@tonic-gate 	if (m >= midfree) {
5227c478bd9Sstevel@tonic-gate 		printf(gettext("Use made of undefined machine id\n"));
5237c478bd9Sstevel@tonic-gate 		return(0);
5247c478bd9Sstevel@tonic-gate 	}
5257c478bd9Sstevel@tonic-gate 	return(xtab[m]->xh_attnet);
5267c478bd9Sstevel@tonic-gate }
5277c478bd9Sstevel@tonic-gate 
5287c478bd9Sstevel@tonic-gate #ifdef	OPTIM
5297c478bd9Sstevel@tonic-gate /*
5307c478bd9Sstevel@tonic-gate  * Take a network name and optimize it.  This gloriously messy
5317c478bd9Sstevel@tonic-gate  * operation takes place as follows:  the name with machine names
5327c478bd9Sstevel@tonic-gate  * in it is tokenized by mapping each machine name into a single
5337c478bd9Sstevel@tonic-gate  * character machine id (netlook).  The separator characters (network
5347c478bd9Sstevel@tonic-gate  * metacharacters) are left intact.  The last component of the network
5357c478bd9Sstevel@tonic-gate  * name is stripped off and assumed to be the destination user name --
5367c478bd9Sstevel@tonic-gate  * it does not participate in the optimization.  As an example, the
5377c478bd9Sstevel@tonic-gate  * name "res!vax!res!uvax!bill" becomes, tokenized,
5387c478bd9Sstevel@tonic-gate  * "r!x!r!v!" and "bill"  A low level routine, optim1, fixes up the
5397c478bd9Sstevel@tonic-gate  * network part (eg, "r!x!r!v!"), then we convert back to network
5407c478bd9Sstevel@tonic-gate  * machine names and tack the user name on the end.
5417c478bd9Sstevel@tonic-gate  *
5427c478bd9Sstevel@tonic-gate  * The result of this is copied into the parameter "name"
5437c478bd9Sstevel@tonic-gate  */
5447c478bd9Sstevel@tonic-gate 
5457c478bd9Sstevel@tonic-gate static void
optim(char net[],char name[])5467c478bd9Sstevel@tonic-gate optim(char net[], char name[])
5477c478bd9Sstevel@tonic-gate {
5487c478bd9Sstevel@tonic-gate 	char netcomp[BUFSIZ], netstr[STSIZ], xfstr[STSIZ];
5497c478bd9Sstevel@tonic-gate 	register char *cp, *cp2;
5507c478bd9Sstevel@tonic-gate 	register int c;
5517c478bd9Sstevel@tonic-gate 
5527c478bd9Sstevel@tonic-gate 	if (debug) fprintf(stderr, "optim(%s, %s) called\n", net, name);
5537c478bd9Sstevel@tonic-gate 	*netstr = '\0';
5547c478bd9Sstevel@tonic-gate 	cp = net;
5557c478bd9Sstevel@tonic-gate 	for (;;) {
5567c478bd9Sstevel@tonic-gate 		/*
5577c478bd9Sstevel@tonic-gate 		 * Rip off next path component into netcomp
5587c478bd9Sstevel@tonic-gate 		 */
5597c478bd9Sstevel@tonic-gate 		cp2 = netcomp;
5607c478bd9Sstevel@tonic-gate 		while (*cp && !any(*cp, metanet))
5617c478bd9Sstevel@tonic-gate 			*cp2++ = *cp++;
5627c478bd9Sstevel@tonic-gate 		*cp2 = 0;
5637c478bd9Sstevel@tonic-gate 		/*
5647c478bd9Sstevel@tonic-gate 		 * If we hit null byte, then we just scanned
5657c478bd9Sstevel@tonic-gate 		 * the destination user name.  Go off and optimize
5667c478bd9Sstevel@tonic-gate 		 * if its so.
5677c478bd9Sstevel@tonic-gate 		 */
5687c478bd9Sstevel@tonic-gate 		if (*cp == 0)
5697c478bd9Sstevel@tonic-gate 			break;
5707c478bd9Sstevel@tonic-gate 		if ((c = netlook(netcomp, *cp)) == 0) {
5717c478bd9Sstevel@tonic-gate 			printf(gettext("No host named \"%s\"\n"), netcomp);
5727c478bd9Sstevel@tonic-gate err:
5737c478bd9Sstevel@tonic-gate 			nstrcpy(name, BUFSIZ, net);
5747c478bd9Sstevel@tonic-gate 			return;
5757c478bd9Sstevel@tonic-gate 		}
5767c478bd9Sstevel@tonic-gate 		stradd(name, BUFSIZ, c);
5777c478bd9Sstevel@tonic-gate 		stradd(name, BUFSIZ, *cp++);
5787c478bd9Sstevel@tonic-gate 		/*
5797c478bd9Sstevel@tonic-gate 		 * If multiple network separators given,
5807c478bd9Sstevel@tonic-gate 		 * throw away the extras.
5817c478bd9Sstevel@tonic-gate 		 */
5827c478bd9Sstevel@tonic-gate 		while (any(*cp, metanet))
5837c478bd9Sstevel@tonic-gate 			cp++;
5847c478bd9Sstevel@tonic-gate 	}
5857c478bd9Sstevel@tonic-gate 	if (strlen(netcomp) == 0) {
5867c478bd9Sstevel@tonic-gate 		printf(gettext("net name syntax\n"));
5877c478bd9Sstevel@tonic-gate 		goto err;
5887c478bd9Sstevel@tonic-gate 	}
5897c478bd9Sstevel@tonic-gate 	if (debug) fprintf(stderr, "optim1(%s,%s) called\n", netstr, xfstr);
5907c478bd9Sstevel@tonic-gate 	optim1(netstr, xfstr);
5917c478bd9Sstevel@tonic-gate 	if (debug) fprintf(stderr, "optim1(%s,%s) returns\n", netstr, xfstr);
5927c478bd9Sstevel@tonic-gate 
5937c478bd9Sstevel@tonic-gate 	/*
5947c478bd9Sstevel@tonic-gate 	 * Convert back to machine names.
5957c478bd9Sstevel@tonic-gate 	 */
5967c478bd9Sstevel@tonic-gate 
5977c478bd9Sstevel@tonic-gate 	cp = xfstr;
5987c478bd9Sstevel@tonic-gate 	*name = '\0';
5997c478bd9Sstevel@tonic-gate 	while (*cp) {
6007c478bd9Sstevel@tonic-gate 		if ((cp2 = netname(*cp++)) == NOSTR) {
6017c478bd9Sstevel@tonic-gate 			printf(gettext("Made up bad net name\n"));
6027c478bd9Sstevel@tonic-gate 			printf(gettext("Machine code %c (0%o)\n"), cp[-1],
6037c478bd9Sstevel@tonic-gate cp[-1]);
6047c478bd9Sstevel@tonic-gate 			printf(gettext("Sorry.\n"));
6057c478bd9Sstevel@tonic-gate 			goto err;
6067c478bd9Sstevel@tonic-gate 		}
6077c478bd9Sstevel@tonic-gate 		nstrcat(name, BUFSIZ, cp2);
6087c478bd9Sstevel@tonic-gate 		stradd(name, BUFSIZ, *cp++);
6097c478bd9Sstevel@tonic-gate 	}
6107c478bd9Sstevel@tonic-gate 	nstrcat(name, BUFSIZ, netcomp);
6117c478bd9Sstevel@tonic-gate 	if (debug) fprintf(stderr, "optim returns %s in name\n", name);
6127c478bd9Sstevel@tonic-gate }
6137c478bd9Sstevel@tonic-gate 
6147c478bd9Sstevel@tonic-gate /*
6157c478bd9Sstevel@tonic-gate  * Take a string of network machine id's and separators and
6167c478bd9Sstevel@tonic-gate  * optimize them.  We process these by pulling off maximal
6177c478bd9Sstevel@tonic-gate  * leading strings of the same type, passing these to the appropriate
6187c478bd9Sstevel@tonic-gate  * optimizer and concatenating the results.
6197c478bd9Sstevel@tonic-gate  */
6207c478bd9Sstevel@tonic-gate 
621*2a8bcb4eSToomas Soome static void
optim1(char netstr[],char name[])6227c478bd9Sstevel@tonic-gate optim1(char netstr[], char name[])
6237c478bd9Sstevel@tonic-gate {
6247c478bd9Sstevel@tonic-gate 	char path[STSIZ], rpath[STSIZ];
6257c478bd9Sstevel@tonic-gate 	register char *cp, *cp2;
6267c478bd9Sstevel@tonic-gate 	register int tp, nc;
627*2a8bcb4eSToomas Soome 
6287c478bd9Sstevel@tonic-gate 	cp = netstr;
6297c478bd9Sstevel@tonic-gate 	prefer(cp);
6307c478bd9Sstevel@tonic-gate 	*name  = '\0';
6317c478bd9Sstevel@tonic-gate 	/*
6327c478bd9Sstevel@tonic-gate 	 * If the address ultimately points back to us,
6337c478bd9Sstevel@tonic-gate 	 * just return a null network path.
6347c478bd9Sstevel@tonic-gate 	 */
6357c478bd9Sstevel@tonic-gate 	if ((int)strlen(cp) > 1 && cp[strlen(cp) - 2] == LOCAL)
6367c478bd9Sstevel@tonic-gate 		return;
6377c478bd9Sstevel@tonic-gate 	while (*cp != 0) {
6387c478bd9Sstevel@tonic-gate 		*path = '\0';
6397c478bd9Sstevel@tonic-gate 
6407c478bd9Sstevel@tonic-gate 		tp = ntype(cp[1]);
6417c478bd9Sstevel@tonic-gate 		nc = cp[1];
6427c478bd9Sstevel@tonic-gate 		while (*cp && tp == ntype(cp[1])) {
6437c478bd9Sstevel@tonic-gate 			stradd(path, sizeof (path), *cp++);
6447c478bd9Sstevel@tonic-gate 			cp++;
6457c478bd9Sstevel@tonic-gate 		}
6467c478bd9Sstevel@tonic-gate 		switch (netkind(tp)) {
6477c478bd9Sstevel@tonic-gate 		default:
6487c478bd9Sstevel@tonic-gate 			nstrcpy(rpath, sizeof (rpath), path);
6497c478bd9Sstevel@tonic-gate 			break;
6507c478bd9Sstevel@tonic-gate 
6517c478bd9Sstevel@tonic-gate 		case IMPLICIT:
6527c478bd9Sstevel@tonic-gate 			optimimp(path, rpath);
6537c478bd9Sstevel@tonic-gate 			break;
6547c478bd9Sstevel@tonic-gate 
6557c478bd9Sstevel@tonic-gate 		case EXPLICIT:
6567c478bd9Sstevel@tonic-gate 			optimex(path, rpath);
6577c478bd9Sstevel@tonic-gate 			break;
6587c478bd9Sstevel@tonic-gate 		}
6597c478bd9Sstevel@tonic-gate 		for (cp2 = rpath; *cp2 != 0; cp2++) {
6607c478bd9Sstevel@tonic-gate 			stradd(name, BUFSIZ, *cp2);
6617c478bd9Sstevel@tonic-gate 			stradd(name, BUFSIZ, nc);
6627c478bd9Sstevel@tonic-gate 		}
6637c478bd9Sstevel@tonic-gate 	}
6647c478bd9Sstevel@tonic-gate 	optiboth(name);
6657c478bd9Sstevel@tonic-gate 	prefer(name);
6667c478bd9Sstevel@tonic-gate }
6676c83d09fSrobbin #endif	/* OPTIM */
6687c478bd9Sstevel@tonic-gate 
6697c478bd9Sstevel@tonic-gate /*
6707c478bd9Sstevel@tonic-gate  * Return the network of the separator --
6717c478bd9Sstevel@tonic-gate  *	AN for arpa net
6727c478bd9Sstevel@tonic-gate  *	BN for Bell labs net	(e.g. UUCP, NOT Berknet)
6737c478bd9Sstevel@tonic-gate  *	SN for Schmidt net	(Berknet)
6747c478bd9Sstevel@tonic-gate  *	0 if we don't know.
6757c478bd9Sstevel@tonic-gate  */
676*2a8bcb4eSToomas Soome static int
ntype(register int nc)6777c478bd9Sstevel@tonic-gate ntype(register int nc)
6787c478bd9Sstevel@tonic-gate {
6797c478bd9Sstevel@tonic-gate 	register struct ntypetab *np;
6807c478bd9Sstevel@tonic-gate 
6817c478bd9Sstevel@tonic-gate 	for (np = ntypetab; np->nt_char != 0; np++)
6827c478bd9Sstevel@tonic-gate 		if (np->nt_char == nc)
6837c478bd9Sstevel@tonic-gate 			return(np->nt_bcode);
6847c478bd9Sstevel@tonic-gate 	return(0);
6857c478bd9Sstevel@tonic-gate }
6867c478bd9Sstevel@tonic-gate 
6877c478bd9Sstevel@tonic-gate #ifdef	OPTIM
6887c478bd9Sstevel@tonic-gate /*
6897c478bd9Sstevel@tonic-gate  * Return the kind of routing used for the particular net
6907c478bd9Sstevel@tonic-gate  * EXPLICIT means explicitly routed
6917c478bd9Sstevel@tonic-gate  * IMPLICIT means implicitly routed
6927c478bd9Sstevel@tonic-gate  * 0 means don't know
6937c478bd9Sstevel@tonic-gate  */
6947c478bd9Sstevel@tonic-gate 
695*2a8bcb4eSToomas Soome static int
netkind(register int nt)6967c478bd9Sstevel@tonic-gate netkind(register int nt)
6977c478bd9Sstevel@tonic-gate {
6987c478bd9Sstevel@tonic-gate 	register struct nkindtab *np;
6997c478bd9Sstevel@tonic-gate 
7007c478bd9Sstevel@tonic-gate 	for (np = nkindtab; np->nk_type != 0; np++)
7017c478bd9Sstevel@tonic-gate 		if (np->nk_type == nt)
7027c478bd9Sstevel@tonic-gate 			return(np->nk_kind);
7037c478bd9Sstevel@tonic-gate 	return(0);
7047c478bd9Sstevel@tonic-gate }
7057c478bd9Sstevel@tonic-gate 
7067c478bd9Sstevel@tonic-gate /*
7077c478bd9Sstevel@tonic-gate  * Do name optimization for an explicitly routed network (eg uucp).
7087c478bd9Sstevel@tonic-gate  */
7097c478bd9Sstevel@tonic-gate 
710*2a8bcb4eSToomas Soome static int
optimex(char net[],char name[])7117c478bd9Sstevel@tonic-gate optimex(char net[], char name[])
7127c478bd9Sstevel@tonic-gate {
7137c478bd9Sstevel@tonic-gate 	register char *cp, *rp;
7147c478bd9Sstevel@tonic-gate 	register int m;
7157c478bd9Sstevel@tonic-gate 
7167c478bd9Sstevel@tonic-gate 	nstrcpy(name, STSIZ, net);
7177c478bd9Sstevel@tonic-gate 	cp = name;
7187c478bd9Sstevel@tonic-gate 	if (strlen(cp) == 0)
7197c478bd9Sstevel@tonic-gate 		return(-1);
7207c478bd9Sstevel@tonic-gate 	if (cp[strlen(cp)-1] == LOCAL) {
7217c478bd9Sstevel@tonic-gate 		name[0] = 0;
7227c478bd9Sstevel@tonic-gate 		return(0);
7237c478bd9Sstevel@tonic-gate 	}
7247c478bd9Sstevel@tonic-gate 	for (cp = name; *cp; cp++) {
7257c478bd9Sstevel@tonic-gate 		m = *cp;
7267c478bd9Sstevel@tonic-gate 		rp = strrchr(cp+1, m);
7277c478bd9Sstevel@tonic-gate 		if (rp != NOSTR)
7287c478bd9Sstevel@tonic-gate 			strcpy(cp, rp);
7297c478bd9Sstevel@tonic-gate 	}
7307c478bd9Sstevel@tonic-gate 	return(0);
7317c478bd9Sstevel@tonic-gate }
7327c478bd9Sstevel@tonic-gate 
7337c478bd9Sstevel@tonic-gate /*
7347c478bd9Sstevel@tonic-gate  * Do name optimization for implicitly routed network (eg, arpanet).
7357c478bd9Sstevel@tonic-gate  */
7367c478bd9Sstevel@tonic-gate 
737*2a8bcb4eSToomas Soome static int
optimimp(char net[],char name[])7387c478bd9Sstevel@tonic-gate optimimp(char net[], char name[])
7397c478bd9Sstevel@tonic-gate {
7407c478bd9Sstevel@tonic-gate 	register char *cp;
7417c478bd9Sstevel@tonic-gate 	register char m;
7427c478bd9Sstevel@tonic-gate 
7437c478bd9Sstevel@tonic-gate 	cp = net;
7447c478bd9Sstevel@tonic-gate 	if (strlen(cp) == 0)
7457c478bd9Sstevel@tonic-gate 		return(-1);
7467c478bd9Sstevel@tonic-gate 	m = cp[strlen(cp) - 1];
7477c478bd9Sstevel@tonic-gate 	if (m == LOCAL) {
7487c478bd9Sstevel@tonic-gate 		*name = '\0';
7497c478bd9Sstevel@tonic-gate 		return(0);
7507c478bd9Sstevel@tonic-gate 	}
7517c478bd9Sstevel@tonic-gate 	name[0] = m;
7527c478bd9Sstevel@tonic-gate 	name[1] = 0;
7537c478bd9Sstevel@tonic-gate 	return(0);
7547c478bd9Sstevel@tonic-gate }
7557c478bd9Sstevel@tonic-gate 
7567c478bd9Sstevel@tonic-gate /*
7577c478bd9Sstevel@tonic-gate  * Perform global optimization on the given network path.
7587c478bd9Sstevel@tonic-gate  * The trick here is to look ahead to see if there are any loops
7597c478bd9Sstevel@tonic-gate  * in the path and remove them.  The interpretation of loops is
7607c478bd9Sstevel@tonic-gate  * more strict here than in optimex since both the machine and net
7617c478bd9Sstevel@tonic-gate  * type must match.
7627c478bd9Sstevel@tonic-gate  */
7637c478bd9Sstevel@tonic-gate 
764*2a8bcb4eSToomas Soome static void
optiboth(char net[])7657c478bd9Sstevel@tonic-gate optiboth(char net[])
7667c478bd9Sstevel@tonic-gate {
7677c478bd9Sstevel@tonic-gate 	register char *cp, *cp2;
7687c478bd9Sstevel@tonic-gate 
7697c478bd9Sstevel@tonic-gate 	cp = net;
7707c478bd9Sstevel@tonic-gate 	if (strlen(cp) == 0)
7717c478bd9Sstevel@tonic-gate 		return;
7727c478bd9Sstevel@tonic-gate 	if (((int)strlen(cp) % 2) != 0) {
7737c478bd9Sstevel@tonic-gate 		printf(gettext("Strange arg to optiboth\n"));
7747c478bd9Sstevel@tonic-gate 		return;
7757c478bd9Sstevel@tonic-gate 	}
7767c478bd9Sstevel@tonic-gate 	while (*cp) {
7777c478bd9Sstevel@tonic-gate 		cp2 = rpair(cp+2, *cp);
7787c478bd9Sstevel@tonic-gate 		if (cp2 != NOSTR)
7797c478bd9Sstevel@tonic-gate 			strcpy(cp, cp2);
7807c478bd9Sstevel@tonic-gate 		cp += 2;
7817c478bd9Sstevel@tonic-gate 	}
7827c478bd9Sstevel@tonic-gate }
7837c478bd9Sstevel@tonic-gate 
7847c478bd9Sstevel@tonic-gate /*
7857c478bd9Sstevel@tonic-gate  * Find the rightmost instance of the given (machine, type) pair.
7867c478bd9Sstevel@tonic-gate  */
7877c478bd9Sstevel@tonic-gate 
7887c478bd9Sstevel@tonic-gate static char *
rpair(char str[],int mach)7897c478bd9Sstevel@tonic-gate rpair(char str[], int mach)
7907c478bd9Sstevel@tonic-gate {
7917c478bd9Sstevel@tonic-gate 	register char *cp, *last;
7927c478bd9Sstevel@tonic-gate 
7937c478bd9Sstevel@tonic-gate 	cp = str;
7947c478bd9Sstevel@tonic-gate 	last = NOSTR;
7957c478bd9Sstevel@tonic-gate 	while (*cp) {
7967c478bd9Sstevel@tonic-gate 		if (*cp == mach)
7977c478bd9Sstevel@tonic-gate 			last = cp;
7987c478bd9Sstevel@tonic-gate 		cp += 2;
7997c478bd9Sstevel@tonic-gate 	}
8007c478bd9Sstevel@tonic-gate 	return(last);
8017c478bd9Sstevel@tonic-gate }
8027c478bd9Sstevel@tonic-gate 
8037c478bd9Sstevel@tonic-gate /*
8047c478bd9Sstevel@tonic-gate  * Change the network separators in the given network path
8057c478bd9Sstevel@tonic-gate  * to the preferred network transmission means.
8067c478bd9Sstevel@tonic-gate  */
8077c478bd9Sstevel@tonic-gate 
808*2a8bcb4eSToomas Soome static void
prefer(char name[])8097c478bd9Sstevel@tonic-gate prefer(char name[])
8107c478bd9Sstevel@tonic-gate {
8117c478bd9Sstevel@tonic-gate 	register char *cp, n;
8127c478bd9Sstevel@tonic-gate 	register int state;
8137c478bd9Sstevel@tonic-gate 
8147c478bd9Sstevel@tonic-gate 	state = LOCAL;
8157c478bd9Sstevel@tonic-gate 	for (cp = name; *cp; cp += 2) {
8167c478bd9Sstevel@tonic-gate 		n = best(state, *cp);
8177c478bd9Sstevel@tonic-gate 		if (n)
8187c478bd9Sstevel@tonic-gate 			cp[1] = n;
8197c478bd9Sstevel@tonic-gate 		state = *cp;
8207c478bd9Sstevel@tonic-gate 	}
8217c478bd9Sstevel@tonic-gate }
8227c478bd9Sstevel@tonic-gate 
8237c478bd9Sstevel@tonic-gate /*
8247c478bd9Sstevel@tonic-gate  * Return the best network separator for the given machine pair.
8257c478bd9Sstevel@tonic-gate  */
8267c478bd9Sstevel@tonic-gate 
827*2a8bcb4eSToomas Soome static char
best(int src,int dest)8287c478bd9Sstevel@tonic-gate best(int src, int dest)
8297c478bd9Sstevel@tonic-gate {
8307c478bd9Sstevel@tonic-gate 	register int dtype, stype;
8317c478bd9Sstevel@tonic-gate 	register struct netorder *np;
8327c478bd9Sstevel@tonic-gate 
8337c478bd9Sstevel@tonic-gate 	stype = nettype(src);
8347c478bd9Sstevel@tonic-gate 	dtype = nettype(dest);
8357c478bd9Sstevel@tonic-gate 	fflush(stdout);
8367c478bd9Sstevel@tonic-gate 	if (stype == 0 || dtype == 0) {
8377c478bd9Sstevel@tonic-gate 		printf(gettext("ERROR:  unknown internal machine id\n"));
8387c478bd9Sstevel@tonic-gate 		return(0);
8397c478bd9Sstevel@tonic-gate 	}
8407c478bd9Sstevel@tonic-gate 	if ((stype & dtype) == 0)
8417c478bd9Sstevel@tonic-gate 		return(0);
8427c478bd9Sstevel@tonic-gate 	np = &netorder[0];
8437c478bd9Sstevel@tonic-gate 	while ((np->no_stat & stype & dtype) == 0)
8447c478bd9Sstevel@tonic-gate 		np++;
8457c478bd9Sstevel@tonic-gate 	return(np->no_char);
8467c478bd9Sstevel@tonic-gate }
8476c83d09fSrobbin #endif	/* OPTIM */
8487c478bd9Sstevel@tonic-gate 
8497c478bd9Sstevel@tonic-gate #ifdef notdef
8507c478bd9Sstevel@tonic-gate /*
8517c478bd9Sstevel@tonic-gate  * Code to twist around arpa net names.
8527c478bd9Sstevel@tonic-gate  */
8537c478bd9Sstevel@tonic-gate 
8547c478bd9Sstevel@tonic-gate #define WORD 257			/* Token for a string */
8557c478bd9Sstevel@tonic-gate 
8567c478bd9Sstevel@tonic-gate static	char netbuf[256];
8577c478bd9Sstevel@tonic-gate static	char *yylval;
8587c478bd9Sstevel@tonic-gate 
8597c478bd9Sstevel@tonic-gate /*
8607c478bd9Sstevel@tonic-gate  * Reverse all of the arpa net addresses in the given name to
8617c478bd9Sstevel@tonic-gate  * be of the form "host @ user" instead of "user @ host"
8627c478bd9Sstevel@tonic-gate  * This function is its own inverse.
8637c478bd9Sstevel@tonic-gate  */
8647c478bd9Sstevel@tonic-gate 
8657c478bd9Sstevel@tonic-gate char *
revarpa(char str[])8667c478bd9Sstevel@tonic-gate revarpa(char str[])
8677c478bd9Sstevel@tonic-gate {
8687c478bd9Sstevel@tonic-gate 
8697c478bd9Sstevel@tonic-gate 	if (yyinit(str) < 0)
8707c478bd9Sstevel@tonic-gate 		return(NOSTR);
8717c478bd9Sstevel@tonic-gate 	if (name())
8727c478bd9Sstevel@tonic-gate 		return(NOSTR);
8737c478bd9Sstevel@tonic-gate 	if (strcmp(str, netbuf) == 0)
8747c478bd9Sstevel@tonic-gate 		return(str);
8757c478bd9Sstevel@tonic-gate 	return(savestr(netbuf));
8767c478bd9Sstevel@tonic-gate }
8777c478bd9Sstevel@tonic-gate 
8787c478bd9Sstevel@tonic-gate /*
8797c478bd9Sstevel@tonic-gate  * Parse (by recursive descent) network names, using the following grammar:
8807c478bd9Sstevel@tonic-gate  *	name:
8817c478bd9Sstevel@tonic-gate  *		term {':' term}
8827c478bd9Sstevel@tonic-gate  *		term {'^' term}
8837c478bd9Sstevel@tonic-gate  *		term {'!' term}
8847c478bd9Sstevel@tonic-gate  *		term '@' name
8857c478bd9Sstevel@tonic-gate  *		term '%' name
8867c478bd9Sstevel@tonic-gate  *
8877c478bd9Sstevel@tonic-gate  *	term:
8887c478bd9Sstevel@tonic-gate  *		string of characters.
8897c478bd9Sstevel@tonic-gate  */
8907c478bd9Sstevel@tonic-gate 
891*2a8bcb4eSToomas Soome static int
name(void)8927c478bd9Sstevel@tonic-gate name(void)
8937c478bd9Sstevel@tonic-gate {
8947c478bd9Sstevel@tonic-gate 	register int t;
8957c478bd9Sstevel@tonic-gate 	register char *cp;
8967c478bd9Sstevel@tonic-gate 
8977c478bd9Sstevel@tonic-gate 	for (;;) {
8987c478bd9Sstevel@tonic-gate 		t = yylex();
8997c478bd9Sstevel@tonic-gate 		if (t != WORD)
9007c478bd9Sstevel@tonic-gate 			return(-1);
9017c478bd9Sstevel@tonic-gate 		cp = yylval;
9027c478bd9Sstevel@tonic-gate 		t = yylex();
9037c478bd9Sstevel@tonic-gate 		switch (t) {
9047c478bd9Sstevel@tonic-gate 		case 0:
9057c478bd9Sstevel@tonic-gate 			nstrcat(netbuf, sizeof (netbuf), cp);
9067c478bd9Sstevel@tonic-gate 			return(0);
9077c478bd9Sstevel@tonic-gate 
9087c478bd9Sstevel@tonic-gate 		case '@':
9097c478bd9Sstevel@tonic-gate 		case '%':
9107c478bd9Sstevel@tonic-gate 			if (name())
9117c478bd9Sstevel@tonic-gate 				return(-1);
9127c478bd9Sstevel@tonic-gate 			stradd(netbuf, sizeof (netbuf), '@');
9137c478bd9Sstevel@tonic-gate 			nstrcat(netbuf, sizeof (netbuf), cp);
914*2a8bcb4eSToomas Soome 			return(0);
9157c478bd9Sstevel@tonic-gate 		case WORD:
9167c478bd9Sstevel@tonic-gate 			return(-1);
9177c478bd9Sstevel@tonic-gate 
9187c478bd9Sstevel@tonic-gate 		default:
9197c478bd9Sstevel@tonic-gate 			nstrcat(netbuf, sizeof (netbuf), cp);
9207c478bd9Sstevel@tonic-gate 			stradd(netbuf, sizeof (netbuf), t);
9217c478bd9Sstevel@tonic-gate 		}
9227c478bd9Sstevel@tonic-gate 	}
9237c478bd9Sstevel@tonic-gate }
9247c478bd9Sstevel@tonic-gate 
9257c478bd9Sstevel@tonic-gate /*
9267c478bd9Sstevel@tonic-gate  * Scanner for network names.
9277c478bd9Sstevel@tonic-gate  */
9287c478bd9Sstevel@tonic-gate 
9297c478bd9Sstevel@tonic-gate static	char *charp;			/* Current input pointer */
9307c478bd9Sstevel@tonic-gate static	int nexttok;			/* Salted away next token */
9317c478bd9Sstevel@tonic-gate 
9327c478bd9Sstevel@tonic-gate /*
9337c478bd9Sstevel@tonic-gate  * Initialize the network name scanner.
9347c478bd9Sstevel@tonic-gate  */
9357c478bd9Sstevel@tonic-gate 
936*2a8bcb4eSToomas Soome int
yyinit(char str[])9377c478bd9Sstevel@tonic-gate yyinit(char str[])
9387c478bd9Sstevel@tonic-gate {
9397c478bd9Sstevel@tonic-gate 	static char lexbuf[BUFSIZ];
9407c478bd9Sstevel@tonic-gate 
9417c478bd9Sstevel@tonic-gate 	netbuf[0] = 0;
9427c478bd9Sstevel@tonic-gate 	if (strlen(str) >= sizeof lexbuf - 1)
9437c478bd9Sstevel@tonic-gate 		return(-1);
9447c478bd9Sstevel@tonic-gate 	nexttok = 0;
9457c478bd9Sstevel@tonic-gate 	nstrcpy(lexbuf, sizeof (lexbuf), str);
9467c478bd9Sstevel@tonic-gate 	charp = lexbuf;
9477c478bd9Sstevel@tonic-gate 	return(0);
9487c478bd9Sstevel@tonic-gate }
9497c478bd9Sstevel@tonic-gate 
9507c478bd9Sstevel@tonic-gate /*
9517c478bd9Sstevel@tonic-gate  * Scan and return a single token.
9527c478bd9Sstevel@tonic-gate  * yylval is set to point to a scanned string.
9537c478bd9Sstevel@tonic-gate  */
9547c478bd9Sstevel@tonic-gate 
955*2a8bcb4eSToomas Soome int
yylex(void)9567c478bd9Sstevel@tonic-gate yylex(void)
9577c478bd9Sstevel@tonic-gate {
9587c478bd9Sstevel@tonic-gate 	register char *cp, *dotp;
9597c478bd9Sstevel@tonic-gate 	register int s;
9607c478bd9Sstevel@tonic-gate 
9617c478bd9Sstevel@tonic-gate 	if (nexttok) {
9627c478bd9Sstevel@tonic-gate 		s = nexttok;
9637c478bd9Sstevel@tonic-gate 		nexttok = 0;
9647c478bd9Sstevel@tonic-gate 		return(s);
9657c478bd9Sstevel@tonic-gate 	}
9667c478bd9Sstevel@tonic-gate 	cp = charp;
9677c478bd9Sstevel@tonic-gate 	while (*cp && isspace(*cp))
9687c478bd9Sstevel@tonic-gate 		cp++;
9697c478bd9Sstevel@tonic-gate 	if (*cp == 0)
9707c478bd9Sstevel@tonic-gate 		return(0);
9717c478bd9Sstevel@tonic-gate 	if (any(*cp, metanet)) {
9727c478bd9Sstevel@tonic-gate 		charp = cp+1;
9737c478bd9Sstevel@tonic-gate 		return(*cp);
9747c478bd9Sstevel@tonic-gate 	}
9757c478bd9Sstevel@tonic-gate 	dotp = cp;
9767c478bd9Sstevel@tonic-gate 	while (*cp && !any(*cp, metanet) && !any(*cp, " \t"))
9777c478bd9Sstevel@tonic-gate 		cp++;
9787c478bd9Sstevel@tonic-gate 	if (any(*cp, metanet))
9797c478bd9Sstevel@tonic-gate 		nexttok = *cp;
9807c478bd9Sstevel@tonic-gate 	if (*cp == 0)
9817c478bd9Sstevel@tonic-gate 		charp = cp;
9827c478bd9Sstevel@tonic-gate 	else
9837c478bd9Sstevel@tonic-gate 		charp = cp+1;
9847c478bd9Sstevel@tonic-gate 	*cp = 0;
9857c478bd9Sstevel@tonic-gate 	yylval = dotp;
9867c478bd9Sstevel@tonic-gate 	return(WORD);
9877c478bd9Sstevel@tonic-gate }
9887c478bd9Sstevel@tonic-gate #endif
9897c478bd9Sstevel@tonic-gate 
9907c478bd9Sstevel@tonic-gate /*
991*2a8bcb4eSToomas Soome  * Add a single character onto a string. Here dstsize is the size of the
9927c478bd9Sstevel@tonic-gate  * destnation buffer.
9937c478bd9Sstevel@tonic-gate  */
9947c478bd9Sstevel@tonic-gate 
995*2a8bcb4eSToomas Soome static void
stradd(register char * dst,int dstsize,register int c)9967c478bd9Sstevel@tonic-gate stradd(register char *dst, int dstsize, register int c)
9977c478bd9Sstevel@tonic-gate {
9987c478bd9Sstevel@tonic-gate 	while (*dst != '\0') {
9997c478bd9Sstevel@tonic-gate 		dst++;
10007c478bd9Sstevel@tonic-gate 		dstsize--;
10017c478bd9Sstevel@tonic-gate 	}
10027c478bd9Sstevel@tonic-gate 	if (--dstsize > 0)
10037c478bd9Sstevel@tonic-gate 		*dst++ = (char)c;
10047c478bd9Sstevel@tonic-gate 	*dst = '\0';
10057c478bd9Sstevel@tonic-gate }
1006