xref: /titanic_53/usr/src/cmd/mailx/optim.c (revision 7c478bd95313f5f23a4c958a745db2134aa03244)
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