1*0Sstevel@tonic-gate /*
2*0Sstevel@tonic-gate  * CDDL HEADER START
3*0Sstevel@tonic-gate  *
4*0Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*0Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
6*0Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
7*0Sstevel@tonic-gate  * with the License.
8*0Sstevel@tonic-gate  *
9*0Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*0Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
11*0Sstevel@tonic-gate  * See the License for the specific language governing permissions
12*0Sstevel@tonic-gate  * and limitations under the License.
13*0Sstevel@tonic-gate  *
14*0Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
15*0Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*0Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
17*0Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
18*0Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
19*0Sstevel@tonic-gate  *
20*0Sstevel@tonic-gate  * CDDL HEADER END
21*0Sstevel@tonic-gate  */
22*0Sstevel@tonic-gate /*
23*0Sstevel@tonic-gate  * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
24*0Sstevel@tonic-gate  * Use is subject to license terms.
25*0Sstevel@tonic-gate  *
26*0Sstevel@tonic-gate  * files/gethostent.c -- "files" backend for nsswitch "hosts" database
27*0Sstevel@tonic-gate  */
28*0Sstevel@tonic-gate 
29*0Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
30*0Sstevel@tonic-gate 
31*0Sstevel@tonic-gate #include <netdb.h>
32*0Sstevel@tonic-gate #include "files_common.h"
33*0Sstevel@tonic-gate #include <string.h>
34*0Sstevel@tonic-gate #include <strings.h>
35*0Sstevel@tonic-gate #include <stddef.h>
36*0Sstevel@tonic-gate #include <stdlib.h>
37*0Sstevel@tonic-gate #include <sys/types.h>
38*0Sstevel@tonic-gate #include <sys/socket.h>
39*0Sstevel@tonic-gate #include <netinet/in.h>
40*0Sstevel@tonic-gate #include <arpa/nameser.h>
41*0Sstevel@tonic-gate #include <ctype.h>
42*0Sstevel@tonic-gate 
43*0Sstevel@tonic-gate static int check_name();
44*0Sstevel@tonic-gate static char *do_aliases();
45*0Sstevel@tonic-gate static char *strcasestr();
46*0Sstevel@tonic-gate nss_status_t __nss_files_XY_hostbyname();
47*0Sstevel@tonic-gate int __nss_files_2herrno();
48*0Sstevel@tonic-gate 
49*0Sstevel@tonic-gate static int
50*0Sstevel@tonic-gate check_name(host, args)
51*0Sstevel@tonic-gate 	struct hostent		*host;
52*0Sstevel@tonic-gate 	nss_XbyY_args_t		*args;
53*0Sstevel@tonic-gate {
54*0Sstevel@tonic-gate 	const char		*name = args->key.name;
55*0Sstevel@tonic-gate 	char			**aliasp;
56*0Sstevel@tonic-gate 
57*0Sstevel@tonic-gate 	if (!host->h_name)
58*0Sstevel@tonic-gate 		return (0);
59*0Sstevel@tonic-gate 	if (strcasecmp(host->h_name, name) == 0) {
60*0Sstevel@tonic-gate 		return (1);
61*0Sstevel@tonic-gate 	}
62*0Sstevel@tonic-gate 	for (aliasp = host->h_aliases;  *aliasp != 0;  aliasp++) {
63*0Sstevel@tonic-gate 		if (strcasecmp(*aliasp, name) == 0) {
64*0Sstevel@tonic-gate 			return (1);
65*0Sstevel@tonic-gate 		}
66*0Sstevel@tonic-gate 	}
67*0Sstevel@tonic-gate 	return (0);
68*0Sstevel@tonic-gate }
69*0Sstevel@tonic-gate 
70*0Sstevel@tonic-gate static nss_status_t
71*0Sstevel@tonic-gate getbyname(be, a)
72*0Sstevel@tonic-gate 	files_backend_ptr_t	be;
73*0Sstevel@tonic-gate 	void			*a;
74*0Sstevel@tonic-gate {
75*0Sstevel@tonic-gate 	nss_XbyY_args_t		*argp = (nss_XbyY_args_t *)a;
76*0Sstevel@tonic-gate 	nss_status_t		res;
77*0Sstevel@tonic-gate 
78*0Sstevel@tonic-gate 	res = __nss_files_XY_hostbyname(be, argp, argp->key.name, AF_INET);
79*0Sstevel@tonic-gate 	if (res != NSS_SUCCESS)
80*0Sstevel@tonic-gate 		argp->h_errno = __nss_files_2herrno(res);
81*0Sstevel@tonic-gate 	return (res);
82*0Sstevel@tonic-gate }
83*0Sstevel@tonic-gate 
84*0Sstevel@tonic-gate 
85*0Sstevel@tonic-gate int
86*0Sstevel@tonic-gate __nss_files_check_addr(argp)
87*0Sstevel@tonic-gate 	nss_XbyY_args_t		*argp;
88*0Sstevel@tonic-gate {
89*0Sstevel@tonic-gate 	struct hostent		*host	= (struct hostent *)argp->returnval;
90*0Sstevel@tonic-gate 
91*0Sstevel@tonic-gate 	/*
92*0Sstevel@tonic-gate 	 * We know that /etc/hosts can only store one address per host, so...
93*0Sstevel@tonic-gate 	 */
94*0Sstevel@tonic-gate 	return (host->h_length == argp->key.hostaddr.len &&
95*0Sstevel@tonic-gate 		host->h_addrtype == argp->key.hostaddr.type &&
96*0Sstevel@tonic-gate 		memcmp(host->h_addr_list[0], argp->key.hostaddr.addr,
97*0Sstevel@tonic-gate 			argp->key.hostaddr.len) == 0);
98*0Sstevel@tonic-gate }
99*0Sstevel@tonic-gate 
100*0Sstevel@tonic-gate 
101*0Sstevel@tonic-gate static nss_status_t
102*0Sstevel@tonic-gate getbyaddr(be, a)
103*0Sstevel@tonic-gate 	files_backend_ptr_t	be;
104*0Sstevel@tonic-gate 	void			*a;
105*0Sstevel@tonic-gate {
106*0Sstevel@tonic-gate 	nss_XbyY_args_t		*argp	= (nss_XbyY_args_t *)a;
107*0Sstevel@tonic-gate 	nss_status_t		res;
108*0Sstevel@tonic-gate 
109*0Sstevel@tonic-gate 	res = _nss_files_XY_all(be, argp, 1, 0, __nss_files_check_addr);
110*0Sstevel@tonic-gate 	if (res != NSS_SUCCESS)
111*0Sstevel@tonic-gate 		argp->h_errno = __nss_files_2herrno(res);
112*0Sstevel@tonic-gate 	return (res);
113*0Sstevel@tonic-gate }
114*0Sstevel@tonic-gate 
115*0Sstevel@tonic-gate 
116*0Sstevel@tonic-gate static files_backend_op_t host_ops[] = {
117*0Sstevel@tonic-gate 	_nss_files_destr,
118*0Sstevel@tonic-gate 	_nss_files_endent,
119*0Sstevel@tonic-gate 	_nss_files_setent,
120*0Sstevel@tonic-gate 	_nss_files_getent_netdb,
121*0Sstevel@tonic-gate 	getbyname,
122*0Sstevel@tonic-gate 	getbyaddr,
123*0Sstevel@tonic-gate };
124*0Sstevel@tonic-gate 
125*0Sstevel@tonic-gate /*ARGSUSED*/
126*0Sstevel@tonic-gate nss_backend_t *
127*0Sstevel@tonic-gate _nss_files_hosts_constr(dummy1, dummy2, dummy3)
128*0Sstevel@tonic-gate 	const char	*dummy1, *dummy2, *dummy3;
129*0Sstevel@tonic-gate {
130*0Sstevel@tonic-gate 	return (_nss_files_constr(host_ops,
131*0Sstevel@tonic-gate 				sizeof (host_ops) / sizeof (host_ops[0]),
132*0Sstevel@tonic-gate 				_PATH_HOSTS,
133*0Sstevel@tonic-gate 				NSS_LINELEN_HOSTS,
134*0Sstevel@tonic-gate 				NULL));
135*0Sstevel@tonic-gate }
136*0Sstevel@tonic-gate 
137*0Sstevel@tonic-gate 
138*0Sstevel@tonic-gate /*
139*0Sstevel@tonic-gate  * XXX - this duplicates code from files_common.c because we need to keep
140*0Sstevel@tonic-gate  * going after we've found a match to satisfy the multihomed host case.
141*0Sstevel@tonic-gate  */
142*0Sstevel@tonic-gate nss_status_t
143*0Sstevel@tonic-gate __nss_files_XY_hostbyname(be, args, filter, type)
144*0Sstevel@tonic-gate 	files_backend_ptr_t be;
145*0Sstevel@tonic-gate 	nss_XbyY_args_t *args;
146*0Sstevel@tonic-gate 	const char *filter;		/* hint for name string */
147*0Sstevel@tonic-gate 	int type;
148*0Sstevel@tonic-gate {
149*0Sstevel@tonic-gate 	nss_status_t res;
150*0Sstevel@tonic-gate 	int parsestat;
151*0Sstevel@tonic-gate 	char *first;
152*0Sstevel@tonic-gate 	char *last;
153*0Sstevel@tonic-gate 	int i, nhosts = 0;
154*0Sstevel@tonic-gate 	struct hostent he, *hp, *thp;
155*0Sstevel@tonic-gate 	in_addr_t taddr[MAXADDRS];
156*0Sstevel@tonic-gate 	struct in6_addr taddr6[MAXADDRS];
157*0Sstevel@tonic-gate 	char *abuf = 0;		/* alias buffer */
158*0Sstevel@tonic-gate 	char *abuf_start = 0, *abuf_end;
159*0Sstevel@tonic-gate 	int	(*func)();
160*0Sstevel@tonic-gate 
161*0Sstevel@tonic-gate 	if (be->buf == 0 &&
162*0Sstevel@tonic-gate 		(be->buf = malloc(be->minbuf)) == 0) {
163*0Sstevel@tonic-gate 		return (NSS_UNAVAIL);
164*0Sstevel@tonic-gate 	}
165*0Sstevel@tonic-gate 
166*0Sstevel@tonic-gate 	if (be->f == 0) {
167*0Sstevel@tonic-gate 		if ((res = _nss_files_setent(be, 0)) != NSS_SUCCESS)
168*0Sstevel@tonic-gate 			return (res);
169*0Sstevel@tonic-gate 	}
170*0Sstevel@tonic-gate 
171*0Sstevel@tonic-gate 	res = NSS_NOTFOUND;
172*0Sstevel@tonic-gate 	args->erange = 0;
173*0Sstevel@tonic-gate 	args->returnval = (char *)0;
174*0Sstevel@tonic-gate 	hp = thp = (struct hostent *)args->buf.result;
175*0Sstevel@tonic-gate 
176*0Sstevel@tonic-gate 	for (;;) {
177*0Sstevel@tonic-gate 		char *instr = be->buf;
178*0Sstevel@tonic-gate 		int linelen;
179*0Sstevel@tonic-gate 
180*0Sstevel@tonic-gate 		if ((linelen = _nss_files_read_line(be->f,
181*0Sstevel@tonic-gate 		    instr, be->minbuf)) < 0) {
182*0Sstevel@tonic-gate 			break;		/* EOF */
183*0Sstevel@tonic-gate 		}
184*0Sstevel@tonic-gate 
185*0Sstevel@tonic-gate 		/*
186*0Sstevel@tonic-gate 		 * This check avoids a malloc()/free() for the common
187*0Sstevel@tonic-gate 		 * case. Also, if we're trying to match an alias and an
188*0Sstevel@tonic-gate 		 * already matched entry doesn't share a canonical name
189*0Sstevel@tonic-gate 		 * with the current one, bail.
190*0Sstevel@tonic-gate 		 */
191*0Sstevel@tonic-gate 		if (nhosts == 0 && strcasestr(instr, filter) == 0) {
192*0Sstevel@tonic-gate 			continue;
193*0Sstevel@tonic-gate 		}
194*0Sstevel@tonic-gate 
195*0Sstevel@tonic-gate 		if ((last = strchr(instr, '#')) == 0)
196*0Sstevel@tonic-gate 			last = instr + linelen;
197*0Sstevel@tonic-gate 		*last-- = '\0';
198*0Sstevel@tonic-gate 		for (first = instr;  isspace(*first);  first++)
199*0Sstevel@tonic-gate 			;
200*0Sstevel@tonic-gate 		/* Ignore blank and comment lines */
201*0Sstevel@tonic-gate 		if (*first == '\0')
202*0Sstevel@tonic-gate 			continue;
203*0Sstevel@tonic-gate 
204*0Sstevel@tonic-gate 		while (isspace(*last))
205*0Sstevel@tonic-gate 			--last;
206*0Sstevel@tonic-gate 		linelen = last - first + 1;
207*0Sstevel@tonic-gate 		if (first != instr)
208*0Sstevel@tonic-gate 			instr = first;
209*0Sstevel@tonic-gate 
210*0Sstevel@tonic-gate 		if (nhosts && strcasestr(instr, hp->h_name) == 0) {
211*0Sstevel@tonic-gate 			break;
212*0Sstevel@tonic-gate 		}
213*0Sstevel@tonic-gate 		/*
214*0Sstevel@tonic-gate 		 * If we've already matched once and have a possible match
215*0Sstevel@tonic-gate 		 * on this line, copy the aliases where they're safe from
216*0Sstevel@tonic-gate 		 * being overwritten when we look at the next entry. They're
217*0Sstevel@tonic-gate 		 * saved as a string of blank separated names for the alias
218*0Sstevel@tonic-gate 		 * parser. On errors, we return failure whether or not we
219*0Sstevel@tonic-gate 		 * have already obtained a valid address.
220*0Sstevel@tonic-gate 		 */
221*0Sstevel@tonic-gate 		if (nhosts == 1 && !abuf) {
222*0Sstevel@tonic-gate 			abuf = malloc(args->buf.buflen);
223*0Sstevel@tonic-gate 			if (abuf == NULL) {
224*0Sstevel@tonic-gate 				res = NSS_UNAVAIL;
225*0Sstevel@tonic-gate 				break;
226*0Sstevel@tonic-gate 			}
227*0Sstevel@tonic-gate 			abuf_start = &abuf[0];
228*0Sstevel@tonic-gate 			abuf_end = abuf_start + args->buf.buflen;
229*0Sstevel@tonic-gate 			if (abuf + strlen(hp->h_name) + 1 > abuf_end) {
230*0Sstevel@tonic-gate 				free(abuf_start);
231*0Sstevel@tonic-gate 				abuf = NULL;
232*0Sstevel@tonic-gate 				args->erange = 1;
233*0Sstevel@tonic-gate 				res = NSS_NOTFOUND;
234*0Sstevel@tonic-gate 				break;
235*0Sstevel@tonic-gate 			}
236*0Sstevel@tonic-gate 			(void) strcpy(abuf, hp->h_name);
237*0Sstevel@tonic-gate 			abuf += strlen(hp->h_name);
238*0Sstevel@tonic-gate 			*abuf++ = ' ';
239*0Sstevel@tonic-gate 			abuf = do_aliases(hp, abuf, abuf_start, abuf_end);
240*0Sstevel@tonic-gate 			if (abuf == NULL) {
241*0Sstevel@tonic-gate 				args->erange = 1;
242*0Sstevel@tonic-gate 				res = NSS_NOTFOUND;
243*0Sstevel@tonic-gate 				break;
244*0Sstevel@tonic-gate 			}
245*0Sstevel@tonic-gate 		}
246*0Sstevel@tonic-gate 		func = args->str2ent;
247*0Sstevel@tonic-gate 		parsestat = (*func)(instr, linelen, thp,
248*0Sstevel@tonic-gate 		    args->buf.buffer, args->buf.buflen);
249*0Sstevel@tonic-gate 
250*0Sstevel@tonic-gate 		if (parsestat != NSS_STR_PARSE_SUCCESS) {
251*0Sstevel@tonic-gate 			if (parsestat == NSS_STR_PARSE_ERANGE)
252*0Sstevel@tonic-gate 				args->erange = 1;
253*0Sstevel@tonic-gate 			continue;
254*0Sstevel@tonic-gate 		}
255*0Sstevel@tonic-gate 
256*0Sstevel@tonic-gate 		/*
257*0Sstevel@tonic-gate 		 * Still need to check, strcasestr() above is just a hint.
258*0Sstevel@tonic-gate 		 */
259*0Sstevel@tonic-gate 
260*0Sstevel@tonic-gate 		if (type == thp->h_addrtype)
261*0Sstevel@tonic-gate 		if (check_name(thp, args)) {
262*0Sstevel@tonic-gate 			if (type == AF_INET)
263*0Sstevel@tonic-gate 				taddr[nhosts++] =
264*0Sstevel@tonic-gate 				(*(in_addr_t *)thp->h_addr_list[0]);
265*0Sstevel@tonic-gate 			else {
266*0Sstevel@tonic-gate 				memcpy(&taddr6[nhosts++], thp->h_addr_list[0],
267*0Sstevel@tonic-gate 				sizeof (struct in6_addr));
268*0Sstevel@tonic-gate 			}
269*0Sstevel@tonic-gate 
270*0Sstevel@tonic-gate 
271*0Sstevel@tonic-gate 			if (nhosts == 1) {
272*0Sstevel@tonic-gate 				res = NSS_SUCCESS;
273*0Sstevel@tonic-gate 				args->returnval = args->buf.result;
274*0Sstevel@tonic-gate 				thp = &he;	/* switch to tmp hostent */
275*0Sstevel@tonic-gate 				continue;
276*0Sstevel@tonic-gate 			}
277*0Sstevel@tonic-gate 			if (nhosts >= MAXADDRS)
278*0Sstevel@tonic-gate 				break;
279*0Sstevel@tonic-gate 			abuf = do_aliases(thp, abuf, abuf_start, abuf_end);
280*0Sstevel@tonic-gate 			if (abuf == NULL) {
281*0Sstevel@tonic-gate 				args->erange = 1;
282*0Sstevel@tonic-gate 				res = NSS_NOTFOUND;
283*0Sstevel@tonic-gate 				break;
284*0Sstevel@tonic-gate 			}
285*0Sstevel@tonic-gate 		} else if (abuf &&
286*0Sstevel@tonic-gate 		    strcasecmp(hp->h_name, thp->h_name) == 0) {
287*0Sstevel@tonic-gate 			/*
288*0Sstevel@tonic-gate 			 * This line didn't have the requested name but
289*0Sstevel@tonic-gate 			 * is part of the same multihomed host (i.e. it
290*0Sstevel@tonic-gate 			 * has the same canonical name as the previous
291*0Sstevel@tonic-gate 			 * line), so march on...
292*0Sstevel@tonic-gate 			 */
293*0Sstevel@tonic-gate 			continue;
294*0Sstevel@tonic-gate 		} else if (nhosts) {
295*0Sstevel@tonic-gate 			break;
296*0Sstevel@tonic-gate 		}
297*0Sstevel@tonic-gate 	}
298*0Sstevel@tonic-gate 
299*0Sstevel@tonic-gate 	if (abuf) {
300*0Sstevel@tonic-gate 		struct in_addr *addrp;
301*0Sstevel@tonic-gate 		struct in6_addr *addrp6;
302*0Sstevel@tonic-gate 
303*0Sstevel@tonic-gate 		if (type == AF_INET) {
304*0Sstevel@tonic-gate 			addrp = (struct in_addr *)(ROUND_DOWN(args->buf.buffer +
305*0Sstevel@tonic-gate 			    args->buf.buflen, sizeof (*addrp)));
306*0Sstevel@tonic-gate 			hp->h_addr_list = (char **)(ROUND_DOWN(addrp -
307*0Sstevel@tonic-gate 			    ((nhosts + 1) * sizeof (char *) +
308*0Sstevel@tonic-gate 			    (nhosts * sizeof (*addrp))), sizeof (char *)));
309*0Sstevel@tonic-gate 			for (i = 0, --addrp; i < nhosts; i++, --addrp) {
310*0Sstevel@tonic-gate 				(*(in_addr_t *)addrp) = taddr[i];
311*0Sstevel@tonic-gate 				hp->h_addr_list[i] = (char *)addrp;
312*0Sstevel@tonic-gate 			}
313*0Sstevel@tonic-gate 		} else {
314*0Sstevel@tonic-gate 			addrp6 = (struct in6_addr *)
315*0Sstevel@tonic-gate 			(ROUND_DOWN(args->buf.buffer + args->buf.buflen,
316*0Sstevel@tonic-gate 			sizeof (*addrp6)));
317*0Sstevel@tonic-gate 			hp->h_addr_list = (char **)(ROUND_DOWN(addrp6 -
318*0Sstevel@tonic-gate 			    ((nhosts + 1) * sizeof (char *) +
319*0Sstevel@tonic-gate 			    (nhosts * sizeof (*addrp6))), sizeof (char *)));
320*0Sstevel@tonic-gate 			for (i = 0, --addrp6; i < nhosts; i++, --addrp6) {
321*0Sstevel@tonic-gate 				memcpy(addrp6, &taddr6[i],
322*0Sstevel@tonic-gate 				sizeof (struct in6_addr));
323*0Sstevel@tonic-gate 				hp->h_addr_list[i] = (char *)addrp6;
324*0Sstevel@tonic-gate 			}
325*0Sstevel@tonic-gate 		}
326*0Sstevel@tonic-gate 
327*0Sstevel@tonic-gate 		hp->h_addr_list[nhosts] = 0;
328*0Sstevel@tonic-gate 		hp->h_aliases = _nss_netdb_aliases(abuf_start,
329*0Sstevel@tonic-gate 		    abuf - abuf_start, args->buf.buffer,
330*0Sstevel@tonic-gate 		    (char *)hp->h_addr_list - args->buf.buffer);
331*0Sstevel@tonic-gate 		if (hp->h_aliases == 0) {
332*0Sstevel@tonic-gate 			args->erange = 1;
333*0Sstevel@tonic-gate 			res = NSS_STR_PARSE_ERANGE;
334*0Sstevel@tonic-gate 		} else {
335*0Sstevel@tonic-gate 			hp->h_name = hp->h_aliases[0];
336*0Sstevel@tonic-gate 			hp->h_aliases++;
337*0Sstevel@tonic-gate 		}
338*0Sstevel@tonic-gate 		free(abuf_start);
339*0Sstevel@tonic-gate 	}
340*0Sstevel@tonic-gate 
341*0Sstevel@tonic-gate 	/*
342*0Sstevel@tonic-gate 	 * stayopen is set to 0 by default in order to close the opened
343*0Sstevel@tonic-gate 	 * file.  Some applications may break if it is set to 1.
344*0Sstevel@tonic-gate 	 */
345*0Sstevel@tonic-gate 	if (!args->stayopen)
346*0Sstevel@tonic-gate 		(void) _nss_files_endent(be, 0);
347*0Sstevel@tonic-gate 
348*0Sstevel@tonic-gate 	return (res);
349*0Sstevel@tonic-gate }
350*0Sstevel@tonic-gate 
351*0Sstevel@tonic-gate /*
352*0Sstevel@tonic-gate  * A case-insensitive version of strstr().
353*0Sstevel@tonic-gate  */
354*0Sstevel@tonic-gate static char *
355*0Sstevel@tonic-gate strcasestr(as1, as2)
356*0Sstevel@tonic-gate 	char *as1;
357*0Sstevel@tonic-gate 	char *as2;
358*0Sstevel@tonic-gate {
359*0Sstevel@tonic-gate 	int c2;
360*0Sstevel@tonic-gate 	register char *tptr;
361*0Sstevel@tonic-gate 	register char *s1, *s2;
362*0Sstevel@tonic-gate 
363*0Sstevel@tonic-gate 	s1 = as1;
364*0Sstevel@tonic-gate 	s2 = as2;
365*0Sstevel@tonic-gate 
366*0Sstevel@tonic-gate 	if (s2 == NULL || *s2 == '\0')
367*0Sstevel@tonic-gate 		return (0);
368*0Sstevel@tonic-gate 
369*0Sstevel@tonic-gate 	while (*s1) {
370*0Sstevel@tonic-gate 		if (tolower(*s1++) == tolower(c2 = *s2)) {
371*0Sstevel@tonic-gate 			tptr = s1;
372*0Sstevel@tonic-gate 			while ((tolower(c2 = *++s2) ==
373*0Sstevel@tonic-gate 			    tolower(*s1++)) && c2 != 0)
374*0Sstevel@tonic-gate 				;
375*0Sstevel@tonic-gate 			if (c2 == 0)
376*0Sstevel@tonic-gate 				return ((char *)tptr - 1);
377*0Sstevel@tonic-gate 			s1 = tptr;
378*0Sstevel@tonic-gate 			s2 = as2;
379*0Sstevel@tonic-gate 		}
380*0Sstevel@tonic-gate 	}
381*0Sstevel@tonic-gate 	return (0);
382*0Sstevel@tonic-gate }
383*0Sstevel@tonic-gate 
384*0Sstevel@tonic-gate 
385*0Sstevel@tonic-gate static char *
386*0Sstevel@tonic-gate do_aliases(hp, abuf, start, end)
387*0Sstevel@tonic-gate 	struct hostent *hp;
388*0Sstevel@tonic-gate 	char *abuf;
389*0Sstevel@tonic-gate 	char *start;
390*0Sstevel@tonic-gate 	char *end;
391*0Sstevel@tonic-gate {
392*0Sstevel@tonic-gate 	char **cp;
393*0Sstevel@tonic-gate 
394*0Sstevel@tonic-gate 	for (cp = hp->h_aliases; cp && *cp && **cp; cp++) {
395*0Sstevel@tonic-gate 		size_t len;
396*0Sstevel@tonic-gate 
397*0Sstevel@tonic-gate 		len = strlen(*cp);
398*0Sstevel@tonic-gate 		if (abuf+len+1 >= end) {
399*0Sstevel@tonic-gate 			free(start);
400*0Sstevel@tonic-gate 			return ((char *)0);
401*0Sstevel@tonic-gate 		}
402*0Sstevel@tonic-gate 		(void) strcpy(abuf, *cp);
403*0Sstevel@tonic-gate 		abuf += len;
404*0Sstevel@tonic-gate 		*abuf++ = ' ';
405*0Sstevel@tonic-gate 	}
406*0Sstevel@tonic-gate 	*abuf = '\0';
407*0Sstevel@tonic-gate 
408*0Sstevel@tonic-gate 	return (abuf);
409*0Sstevel@tonic-gate }
410*0Sstevel@tonic-gate 
411*0Sstevel@tonic-gate 
412*0Sstevel@tonic-gate /*
413*0Sstevel@tonic-gate  * This is a copy of a routine in libnsl/nss/netdir_inet.c.  It is
414*0Sstevel@tonic-gate  * here because /etc/lib/nss_files.so.1 cannot call routines
415*0Sstevel@tonic-gate  * in libnsl.  Care should be taken to keep the two copies in sync.
416*0Sstevel@tonic-gate  */
417*0Sstevel@tonic-gate int
418*0Sstevel@tonic-gate __nss_files_2herrno(nsstat)
419*0Sstevel@tonic-gate 	nss_status_t nsstat;
420*0Sstevel@tonic-gate {
421*0Sstevel@tonic-gate 	switch (nsstat) {
422*0Sstevel@tonic-gate 	case NSS_SUCCESS:
423*0Sstevel@tonic-gate 		/* no macro-defined success code for h_errno */
424*0Sstevel@tonic-gate 		return (0);
425*0Sstevel@tonic-gate 	case NSS_NOTFOUND:
426*0Sstevel@tonic-gate 		return (HOST_NOT_FOUND);
427*0Sstevel@tonic-gate 	case NSS_TRYAGAIN:
428*0Sstevel@tonic-gate 		return (TRY_AGAIN);
429*0Sstevel@tonic-gate 	case NSS_UNAVAIL:
430*0Sstevel@tonic-gate 		return (NO_RECOVERY);
431*0Sstevel@tonic-gate 	}
432*0Sstevel@tonic-gate 	/* anything else */
433*0Sstevel@tonic-gate 	return (NO_RECOVERY);
434*0Sstevel@tonic-gate }
435