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 2005 Sun Microsystems, Inc.  All rights reserved.
24*7c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
25*7c478bd9Sstevel@tonic-gate  *
26*7c478bd9Sstevel@tonic-gate  * Common code and structures used by name-service-switch "compat" backends.
27*7c478bd9Sstevel@tonic-gate  *
28*7c478bd9Sstevel@tonic-gate  * Most of the code in the "compat" backend is a perverted form of code from
29*7c478bd9Sstevel@tonic-gate  * the "files" backend;  this file is no exception.
30*7c478bd9Sstevel@tonic-gate  */
31*7c478bd9Sstevel@tonic-gate 
32*7c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
33*7c478bd9Sstevel@tonic-gate 
34*7c478bd9Sstevel@tonic-gate #include <stdio.h>
35*7c478bd9Sstevel@tonic-gate #include <stdlib.h>
36*7c478bd9Sstevel@tonic-gate #include <string.h>
37*7c478bd9Sstevel@tonic-gate #include <ctype.h>
38*7c478bd9Sstevel@tonic-gate #include <bsm/libbsm.h>
39*7c478bd9Sstevel@tonic-gate #include <user_attr.h>
40*7c478bd9Sstevel@tonic-gate #include "compat_common.h"
41*7c478bd9Sstevel@tonic-gate #include "../../../libnsl/include/nsl_stdio_prv.h"
42*7c478bd9Sstevel@tonic-gate 
43*7c478bd9Sstevel@tonic-gate /*
44*7c478bd9Sstevel@tonic-gate  * This should be in a header.
45*7c478bd9Sstevel@tonic-gate  */
46*7c478bd9Sstevel@tonic-gate 
47*7c478bd9Sstevel@tonic-gate extern int yp_get_default_domain(char **domain);
48*7c478bd9Sstevel@tonic-gate 
49*7c478bd9Sstevel@tonic-gate /*
50*7c478bd9Sstevel@tonic-gate  * Routines to manage list of "-" users for get{pw, sp, gr}ent().  Current
51*7c478bd9Sstevel@tonic-gate  *   implementation is completely moronic; we use a linked list.  But then
52*7c478bd9Sstevel@tonic-gate  *   that's what it's always done in 4.x...
53*7c478bd9Sstevel@tonic-gate  */
54*7c478bd9Sstevel@tonic-gate 
55*7c478bd9Sstevel@tonic-gate struct setofstrings {
56*7c478bd9Sstevel@tonic-gate 	char			*name;
57*7c478bd9Sstevel@tonic-gate 	struct setofstrings	*next;
58*7c478bd9Sstevel@tonic-gate 	/*
59*7c478bd9Sstevel@tonic-gate 	 * === Should get smart and malloc the string and pointer as one
60*7c478bd9Sstevel@tonic-gate 	 *	object rather than two.
61*7c478bd9Sstevel@tonic-gate 	 */
62*7c478bd9Sstevel@tonic-gate };
63*7c478bd9Sstevel@tonic-gate typedef struct setofstrings	*strset_t;
64*7c478bd9Sstevel@tonic-gate 
65*7c478bd9Sstevel@tonic-gate static void
66*7c478bd9Sstevel@tonic-gate strset_free(ssp)
67*7c478bd9Sstevel@tonic-gate 	strset_t	*ssp;
68*7c478bd9Sstevel@tonic-gate {
69*7c478bd9Sstevel@tonic-gate 	strset_t	cur, nxt;
70*7c478bd9Sstevel@tonic-gate 
71*7c478bd9Sstevel@tonic-gate 	for (cur = *ssp;  cur != 0;  cur = nxt) {
72*7c478bd9Sstevel@tonic-gate 		nxt = cur->next;
73*7c478bd9Sstevel@tonic-gate 		free(cur->name);
74*7c478bd9Sstevel@tonic-gate 		free(cur);
75*7c478bd9Sstevel@tonic-gate 	}
76*7c478bd9Sstevel@tonic-gate 	*ssp = 0;
77*7c478bd9Sstevel@tonic-gate }
78*7c478bd9Sstevel@tonic-gate 
79*7c478bd9Sstevel@tonic-gate static boolean_t
80*7c478bd9Sstevel@tonic-gate strset_add(ssp, nam)
81*7c478bd9Sstevel@tonic-gate 	strset_t	*ssp;
82*7c478bd9Sstevel@tonic-gate 	const char	*nam;
83*7c478bd9Sstevel@tonic-gate {
84*7c478bd9Sstevel@tonic-gate 	strset_t	new;
85*7c478bd9Sstevel@tonic-gate 
86*7c478bd9Sstevel@tonic-gate 	if (0 == (new = (strset_t)malloc(sizeof (*new)))) {
87*7c478bd9Sstevel@tonic-gate 		return (B_FALSE);
88*7c478bd9Sstevel@tonic-gate 	}
89*7c478bd9Sstevel@tonic-gate 	if (0 == (new->name = malloc(strlen(nam) + 1))) {
90*7c478bd9Sstevel@tonic-gate 		free(new);
91*7c478bd9Sstevel@tonic-gate 		return (B_FALSE);
92*7c478bd9Sstevel@tonic-gate 	}
93*7c478bd9Sstevel@tonic-gate 	strcpy(new->name, nam);
94*7c478bd9Sstevel@tonic-gate 	new->next = *ssp;
95*7c478bd9Sstevel@tonic-gate 	*ssp = new;
96*7c478bd9Sstevel@tonic-gate 	return (B_TRUE);
97*7c478bd9Sstevel@tonic-gate }
98*7c478bd9Sstevel@tonic-gate 
99*7c478bd9Sstevel@tonic-gate static boolean_t
100*7c478bd9Sstevel@tonic-gate strset_in(ssp, nam)
101*7c478bd9Sstevel@tonic-gate 	const strset_t	*ssp;
102*7c478bd9Sstevel@tonic-gate 	const char	*nam;
103*7c478bd9Sstevel@tonic-gate {
104*7c478bd9Sstevel@tonic-gate 	strset_t	cur;
105*7c478bd9Sstevel@tonic-gate 
106*7c478bd9Sstevel@tonic-gate 	for (cur = *ssp;  cur != 0;  cur = cur->next) {
107*7c478bd9Sstevel@tonic-gate 		if (strcmp(cur->name, nam) == 0) {
108*7c478bd9Sstevel@tonic-gate 			return (B_TRUE);
109*7c478bd9Sstevel@tonic-gate 		}
110*7c478bd9Sstevel@tonic-gate 	}
111*7c478bd9Sstevel@tonic-gate 	return (B_FALSE);
112*7c478bd9Sstevel@tonic-gate }
113*7c478bd9Sstevel@tonic-gate 
114*7c478bd9Sstevel@tonic-gate 
115*7c478bd9Sstevel@tonic-gate struct compat_backend {
116*7c478bd9Sstevel@tonic-gate 	compat_backend_op_t	*ops;
117*7c478bd9Sstevel@tonic-gate 	int			n_ops;
118*7c478bd9Sstevel@tonic-gate 	const char		*filename;
119*7c478bd9Sstevel@tonic-gate 	__NSL_FILE		*f;
120*7c478bd9Sstevel@tonic-gate 	int			minbuf;
121*7c478bd9Sstevel@tonic-gate 	char			*buf;
122*7c478bd9Sstevel@tonic-gate 	int			linelen;	/* <== Explain use, lifetime */
123*7c478bd9Sstevel@tonic-gate 
124*7c478bd9Sstevel@tonic-gate 	nss_db_initf_t		db_initf;
125*7c478bd9Sstevel@tonic-gate 	nss_db_root_t		*db_rootp;	/* Shared between instances */
126*7c478bd9Sstevel@tonic-gate 	nss_getent_t		db_context;	/* Per-instance enumeration */
127*7c478bd9Sstevel@tonic-gate 
128*7c478bd9Sstevel@tonic-gate 	compat_get_name		getnamef;
129*7c478bd9Sstevel@tonic-gate 	compat_merge_func	mergef;
130*7c478bd9Sstevel@tonic-gate 
131*7c478bd9Sstevel@tonic-gate 	/* We wouldn't need all this hokey state stuff if we */
132*7c478bd9Sstevel@tonic-gate 	/*   used another thread to implement a coroutine... */
133*7c478bd9Sstevel@tonic-gate 	enum {
134*7c478bd9Sstevel@tonic-gate 		GETENT_FILE,
135*7c478bd9Sstevel@tonic-gate 		GETENT_NETGROUP,
136*7c478bd9Sstevel@tonic-gate 		GETENT_ATTRDB,
137*7c478bd9Sstevel@tonic-gate 		GETENT_ALL,
138*7c478bd9Sstevel@tonic-gate 		GETENT_DONE
139*7c478bd9Sstevel@tonic-gate 	}			state;
140*7c478bd9Sstevel@tonic-gate 	strset_t		minuses;
141*7c478bd9Sstevel@tonic-gate 
142*7c478bd9Sstevel@tonic-gate 	int			permit_netgroups;
143*7c478bd9Sstevel@tonic-gate 	const char		*yp_domain;
144*7c478bd9Sstevel@tonic-gate 	nss_backend_t		*getnetgrent_backend;
145*7c478bd9Sstevel@tonic-gate 	char			*netgr_buffer;
146*7c478bd9Sstevel@tonic-gate };
147*7c478bd9Sstevel@tonic-gate 
148*7c478bd9Sstevel@tonic-gate 
149*7c478bd9Sstevel@tonic-gate /*
150*7c478bd9Sstevel@tonic-gate  * Lookup and enumeration routines for +@group and -@group.
151*7c478bd9Sstevel@tonic-gate  *
152*7c478bd9Sstevel@tonic-gate  * This code knows a lot more about lib/libc/port/gen/getnetgrent.c than
153*7c478bd9Sstevel@tonic-gate  *   is really healthy.  The set/get/end routines below duplicate code
154*7c478bd9Sstevel@tonic-gate  *   from that file, but keep the state information per-backend-instance
155*7c478bd9Sstevel@tonic-gate  *   instead of just per-process.
156*7c478bd9Sstevel@tonic-gate  */
157*7c478bd9Sstevel@tonic-gate 
158*7c478bd9Sstevel@tonic-gate extern void _nss_initf_netgroup(nss_db_params_t *);
159*7c478bd9Sstevel@tonic-gate /*
160*7c478bd9Sstevel@tonic-gate  * Should really share the db_root in getnetgrent.c in order to get the
161*7c478bd9Sstevel@tonic-gate  *   resource-management quotas right, but this will have to do.
162*7c478bd9Sstevel@tonic-gate  */
163*7c478bd9Sstevel@tonic-gate static DEFINE_NSS_DB_ROOT(netgr_db_root);
164*7c478bd9Sstevel@tonic-gate 
165*7c478bd9Sstevel@tonic-gate static boolean_t
166*7c478bd9Sstevel@tonic-gate netgr_in(compat_backend_ptr_t be, const char *group, const char *user)
167*7c478bd9Sstevel@tonic-gate {
168*7c478bd9Sstevel@tonic-gate 	if (be->yp_domain == 0) {
169*7c478bd9Sstevel@tonic-gate 		if (yp_get_default_domain((char **)&be->yp_domain) != 0) {
170*7c478bd9Sstevel@tonic-gate 			return (B_FALSE);
171*7c478bd9Sstevel@tonic-gate 		}
172*7c478bd9Sstevel@tonic-gate 	}
173*7c478bd9Sstevel@tonic-gate 	return (innetgr(group, 0, user, be->yp_domain));
174*7c478bd9Sstevel@tonic-gate }
175*7c478bd9Sstevel@tonic-gate 
176*7c478bd9Sstevel@tonic-gate static boolean_t
177*7c478bd9Sstevel@tonic-gate netgr_all_in(compat_backend_ptr_t be, const char *group)
178*7c478bd9Sstevel@tonic-gate {
179*7c478bd9Sstevel@tonic-gate 	/*
180*7c478bd9Sstevel@tonic-gate 	 * 4.x does this;  ours not to reason why...
181*7c478bd9Sstevel@tonic-gate 	 */
182*7c478bd9Sstevel@tonic-gate 	return (netgr_in(be, group, "*"));
183*7c478bd9Sstevel@tonic-gate }
184*7c478bd9Sstevel@tonic-gate 
185*7c478bd9Sstevel@tonic-gate static void
186*7c478bd9Sstevel@tonic-gate netgr_set(be, netgroup)
187*7c478bd9Sstevel@tonic-gate 	compat_backend_ptr_t	be;
188*7c478bd9Sstevel@tonic-gate 	const char		*netgroup;
189*7c478bd9Sstevel@tonic-gate {
190*7c478bd9Sstevel@tonic-gate 	/*
191*7c478bd9Sstevel@tonic-gate 	 * ===> Need comment to explain that this first "if" is optimizing
192*7c478bd9Sstevel@tonic-gate 	 *	for the same-netgroup-as-last-time case
193*7c478bd9Sstevel@tonic-gate 	 */
194*7c478bd9Sstevel@tonic-gate 	if (be->getnetgrent_backend != 0 &&
195*7c478bd9Sstevel@tonic-gate 	    NSS_INVOKE_DBOP(be->getnetgrent_backend,
196*7c478bd9Sstevel@tonic-gate 			    NSS_DBOP_SETENT,
197*7c478bd9Sstevel@tonic-gate 			    (void *) netgroup) != NSS_SUCCESS) {
198*7c478bd9Sstevel@tonic-gate 		NSS_INVOKE_DBOP(be->getnetgrent_backend, NSS_DBOP_DESTRUCTOR,
199*7c478bd9Sstevel@tonic-gate 				0);
200*7c478bd9Sstevel@tonic-gate 		be->getnetgrent_backend = 0;
201*7c478bd9Sstevel@tonic-gate 	}
202*7c478bd9Sstevel@tonic-gate 	if (be->getnetgrent_backend == 0) {
203*7c478bd9Sstevel@tonic-gate 		struct nss_setnetgrent_args	args;
204*7c478bd9Sstevel@tonic-gate 
205*7c478bd9Sstevel@tonic-gate 		args.netgroup	= netgroup;
206*7c478bd9Sstevel@tonic-gate 		args.iterator	= 0;
207*7c478bd9Sstevel@tonic-gate 		nss_search(&netgr_db_root, _nss_initf_netgroup,
208*7c478bd9Sstevel@tonic-gate 			NSS_DBOP_NETGROUP_SET, &args);
209*7c478bd9Sstevel@tonic-gate 		be->getnetgrent_backend = args.iterator;
210*7c478bd9Sstevel@tonic-gate 	}
211*7c478bd9Sstevel@tonic-gate }
212*7c478bd9Sstevel@tonic-gate 
213*7c478bd9Sstevel@tonic-gate static boolean_t
214*7c478bd9Sstevel@tonic-gate netgr_next_u(be, up)
215*7c478bd9Sstevel@tonic-gate 	compat_backend_ptr_t	be;
216*7c478bd9Sstevel@tonic-gate 	char			**up;
217*7c478bd9Sstevel@tonic-gate {
218*7c478bd9Sstevel@tonic-gate 	if (be->netgr_buffer == 0 &&
219*7c478bd9Sstevel@tonic-gate 	    (be->netgr_buffer = malloc(NSS_BUFLEN_NETGROUP)) == 0) {
220*7c478bd9Sstevel@tonic-gate 		/* Out of memory */
221*7c478bd9Sstevel@tonic-gate 		return (B_FALSE);
222*7c478bd9Sstevel@tonic-gate 	}
223*7c478bd9Sstevel@tonic-gate 
224*7c478bd9Sstevel@tonic-gate 	do {
225*7c478bd9Sstevel@tonic-gate 		struct nss_getnetgrent_args	args;
226*7c478bd9Sstevel@tonic-gate 
227*7c478bd9Sstevel@tonic-gate 		args.buffer	= be->netgr_buffer;
228*7c478bd9Sstevel@tonic-gate 		args.buflen	= NSS_BUFLEN_NETGROUP;
229*7c478bd9Sstevel@tonic-gate 		args.status	= NSS_NETGR_NO;
230*7c478bd9Sstevel@tonic-gate 
231*7c478bd9Sstevel@tonic-gate 		if (be->getnetgrent_backend != 0) {
232*7c478bd9Sstevel@tonic-gate 			NSS_INVOKE_DBOP(be->getnetgrent_backend,
233*7c478bd9Sstevel@tonic-gate 					NSS_DBOP_GETENT, &args);
234*7c478bd9Sstevel@tonic-gate 		}
235*7c478bd9Sstevel@tonic-gate 
236*7c478bd9Sstevel@tonic-gate 		if (args.status == NSS_NETGR_FOUND) {
237*7c478bd9Sstevel@tonic-gate 			*up	  = args.retp[NSS_NETGR_USER];
238*7c478bd9Sstevel@tonic-gate 		} else {
239*7c478bd9Sstevel@tonic-gate 			return (B_FALSE);
240*7c478bd9Sstevel@tonic-gate 		}
241*7c478bd9Sstevel@tonic-gate 	} while (*up == 0);
242*7c478bd9Sstevel@tonic-gate 	return (B_TRUE);
243*7c478bd9Sstevel@tonic-gate }
244*7c478bd9Sstevel@tonic-gate 
245*7c478bd9Sstevel@tonic-gate static void
246*7c478bd9Sstevel@tonic-gate netgr_end(be)
247*7c478bd9Sstevel@tonic-gate 	compat_backend_ptr_t	be;
248*7c478bd9Sstevel@tonic-gate {
249*7c478bd9Sstevel@tonic-gate 	if (be->getnetgrent_backend != 0) {
250*7c478bd9Sstevel@tonic-gate 		NSS_INVOKE_DBOP(be->getnetgrent_backend,
251*7c478bd9Sstevel@tonic-gate 				NSS_DBOP_DESTRUCTOR, 0);
252*7c478bd9Sstevel@tonic-gate 		be->getnetgrent_backend = 0;
253*7c478bd9Sstevel@tonic-gate 	}
254*7c478bd9Sstevel@tonic-gate 	if (be->netgr_buffer != 0) {
255*7c478bd9Sstevel@tonic-gate 		free(be->netgr_buffer);
256*7c478bd9Sstevel@tonic-gate 		be->netgr_buffer = 0;
257*7c478bd9Sstevel@tonic-gate 	}
258*7c478bd9Sstevel@tonic-gate }
259*7c478bd9Sstevel@tonic-gate 
260*7c478bd9Sstevel@tonic-gate 
261*7c478bd9Sstevel@tonic-gate #define	MAXFIELDS 9	/* Sufficient for passwd (7), shadow (9), group (4) */
262*7c478bd9Sstevel@tonic-gate 
263*7c478bd9Sstevel@tonic-gate static nss_status_t
264*7c478bd9Sstevel@tonic-gate do_merge(be, args, instr, linelen)
265*7c478bd9Sstevel@tonic-gate 	compat_backend_ptr_t	be;
266*7c478bd9Sstevel@tonic-gate 	nss_XbyY_args_t		*args;
267*7c478bd9Sstevel@tonic-gate 	const char		*instr;
268*7c478bd9Sstevel@tonic-gate 	int			linelen;
269*7c478bd9Sstevel@tonic-gate {
270*7c478bd9Sstevel@tonic-gate 	char			*fields[MAXFIELDS];
271*7c478bd9Sstevel@tonic-gate 	int			i;
272*7c478bd9Sstevel@tonic-gate 	int			overrides;
273*7c478bd9Sstevel@tonic-gate 	const char		*p;
274*7c478bd9Sstevel@tonic-gate 	const char		*end = instr + linelen;
275*7c478bd9Sstevel@tonic-gate 	nss_status_t		res;
276*7c478bd9Sstevel@tonic-gate 
277*7c478bd9Sstevel@tonic-gate 	/*
278*7c478bd9Sstevel@tonic-gate 	 * Potential optimization:  only perform the field-splitting nonsense
279*7c478bd9Sstevel@tonic-gate 	 *   once per input line (at present, "+" and "+@netgroup" entries
280*7c478bd9Sstevel@tonic-gate 	 *   will cause us to do this multiple times in getent() requests).
281*7c478bd9Sstevel@tonic-gate 	 */
282*7c478bd9Sstevel@tonic-gate 
283*7c478bd9Sstevel@tonic-gate 	for (i = 0;  i < MAXFIELDS;  i++) {
284*7c478bd9Sstevel@tonic-gate 		fields[i] = 0;
285*7c478bd9Sstevel@tonic-gate 	}
286*7c478bd9Sstevel@tonic-gate 	for (p = instr, overrides = 0, i = 0; /* no test */; i++) {
287*7c478bd9Sstevel@tonic-gate 		const char	*q = memchr(p, ':', end - p);
288*7c478bd9Sstevel@tonic-gate 		const char	*r = (q == 0) ? end : q;
289*7c478bd9Sstevel@tonic-gate 		ssize_t		len = r - p;
290*7c478bd9Sstevel@tonic-gate 
291*7c478bd9Sstevel@tonic-gate 		if (len > 0) {
292*7c478bd9Sstevel@tonic-gate 			char	*s = malloc(len + 1);
293*7c478bd9Sstevel@tonic-gate 			if (s == 0) {
294*7c478bd9Sstevel@tonic-gate 				overrides = -1;	/* Indicates "you lose" */
295*7c478bd9Sstevel@tonic-gate 				break;
296*7c478bd9Sstevel@tonic-gate 			}
297*7c478bd9Sstevel@tonic-gate 			memcpy(s, p, len);
298*7c478bd9Sstevel@tonic-gate 			s[len] = '\0';
299*7c478bd9Sstevel@tonic-gate 			fields[i] = s;
300*7c478bd9Sstevel@tonic-gate 			overrides++;
301*7c478bd9Sstevel@tonic-gate 		}
302*7c478bd9Sstevel@tonic-gate 		if (q == 0) {
303*7c478bd9Sstevel@tonic-gate 			/* End of line */
304*7c478bd9Sstevel@tonic-gate 			break;
305*7c478bd9Sstevel@tonic-gate 		} else {
306*7c478bd9Sstevel@tonic-gate 			/* Skip the colon at (*q) */
307*7c478bd9Sstevel@tonic-gate 			p = q + 1;
308*7c478bd9Sstevel@tonic-gate 		}
309*7c478bd9Sstevel@tonic-gate 	}
310*7c478bd9Sstevel@tonic-gate 	if (overrides == 1) {
311*7c478bd9Sstevel@tonic-gate 		/* No real overrides, return (*args) intact */
312*7c478bd9Sstevel@tonic-gate 		res = NSS_SUCCESS;
313*7c478bd9Sstevel@tonic-gate 	} else if (overrides > 1) {
314*7c478bd9Sstevel@tonic-gate 		/*
315*7c478bd9Sstevel@tonic-gate 		 * The zero'th field is always nonempty (+/-...), but at least
316*7c478bd9Sstevel@tonic-gate 		 *   one other field was also nonempty, i.e. wants to override
317*7c478bd9Sstevel@tonic-gate 		 */
318*7c478bd9Sstevel@tonic-gate 		switch ((*be->mergef)(be, args, (const char **)fields)) {
319*7c478bd9Sstevel@tonic-gate 		    case NSS_STR_PARSE_SUCCESS:
320*7c478bd9Sstevel@tonic-gate 			args->returnval	= args->buf.result;
321*7c478bd9Sstevel@tonic-gate 			args->erange	= 0;
322*7c478bd9Sstevel@tonic-gate 			res = NSS_SUCCESS;
323*7c478bd9Sstevel@tonic-gate 			break;
324*7c478bd9Sstevel@tonic-gate 		    case NSS_STR_PARSE_ERANGE:
325*7c478bd9Sstevel@tonic-gate 			args->returnval	= 0;
326*7c478bd9Sstevel@tonic-gate 			args->erange	= 1;
327*7c478bd9Sstevel@tonic-gate 			res = NSS_NOTFOUND;
328*7c478bd9Sstevel@tonic-gate 			break;
329*7c478bd9Sstevel@tonic-gate 		    case NSS_STR_PARSE_PARSE:
330*7c478bd9Sstevel@tonic-gate 			args->returnval	= 0;
331*7c478bd9Sstevel@tonic-gate 			args->erange	= 0;
332*7c478bd9Sstevel@tonic-gate /* ===> Very likely the wrong thing to do... */
333*7c478bd9Sstevel@tonic-gate 			res = NSS_NOTFOUND;
334*7c478bd9Sstevel@tonic-gate 			break;
335*7c478bd9Sstevel@tonic-gate 		}
336*7c478bd9Sstevel@tonic-gate 	} else {
337*7c478bd9Sstevel@tonic-gate 		args->returnval	= 0;
338*7c478bd9Sstevel@tonic-gate 		args->erange	= 0;
339*7c478bd9Sstevel@tonic-gate 		res = NSS_UNAVAIL;	/* ==> Right? */
340*7c478bd9Sstevel@tonic-gate 	}
341*7c478bd9Sstevel@tonic-gate 
342*7c478bd9Sstevel@tonic-gate 	for (i = 0;  i < MAXFIELDS;  i++) {
343*7c478bd9Sstevel@tonic-gate 		if (fields[i] != 0) {
344*7c478bd9Sstevel@tonic-gate 			free(fields[i]);
345*7c478bd9Sstevel@tonic-gate 		}
346*7c478bd9Sstevel@tonic-gate 	}
347*7c478bd9Sstevel@tonic-gate 
348*7c478bd9Sstevel@tonic-gate 	return (res);
349*7c478bd9Sstevel@tonic-gate }
350*7c478bd9Sstevel@tonic-gate 
351*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/
352*7c478bd9Sstevel@tonic-gate nss_status_t
353*7c478bd9Sstevel@tonic-gate _nss_compat_setent(be, dummy)
354*7c478bd9Sstevel@tonic-gate 	compat_backend_ptr_t	be;
355*7c478bd9Sstevel@tonic-gate 	void			*dummy;
356*7c478bd9Sstevel@tonic-gate {
357*7c478bd9Sstevel@tonic-gate 	if (be->f == 0) {
358*7c478bd9Sstevel@tonic-gate 		if (be->filename == 0) {
359*7c478bd9Sstevel@tonic-gate 			/* Backend isn't initialized properly? */
360*7c478bd9Sstevel@tonic-gate 			return (NSS_UNAVAIL);
361*7c478bd9Sstevel@tonic-gate 		}
362*7c478bd9Sstevel@tonic-gate 		if ((be->f = __nsl_fopen(be->filename, "r")) == 0) {
363*7c478bd9Sstevel@tonic-gate 			return (NSS_UNAVAIL);
364*7c478bd9Sstevel@tonic-gate 		}
365*7c478bd9Sstevel@tonic-gate 	} else {
366*7c478bd9Sstevel@tonic-gate 		__nsl_rewind(be->f);
367*7c478bd9Sstevel@tonic-gate 	}
368*7c478bd9Sstevel@tonic-gate 	strset_free(&be->minuses);
369*7c478bd9Sstevel@tonic-gate 	/* ===> ??? nss_endent(be->db_rootp, be->db_initf, &be->db_context); */
370*7c478bd9Sstevel@tonic-gate 
371*7c478bd9Sstevel@tonic-gate 	if ((strcmp(be->filename, USERATTR_FILENAME) == 0) ||
372*7c478bd9Sstevel@tonic-gate 	    (strcmp(be->filename, AUDITUSER_FILENAME) == 0))
373*7c478bd9Sstevel@tonic-gate 		be->state = GETENT_ATTRDB;
374*7c478bd9Sstevel@tonic-gate 	else
375*7c478bd9Sstevel@tonic-gate 		be->state = GETENT_FILE;
376*7c478bd9Sstevel@tonic-gate 
377*7c478bd9Sstevel@tonic-gate 	/* ===> ??  netgroup stuff? */
378*7c478bd9Sstevel@tonic-gate 	return (NSS_SUCCESS);
379*7c478bd9Sstevel@tonic-gate }
380*7c478bd9Sstevel@tonic-gate 
381*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/
382*7c478bd9Sstevel@tonic-gate nss_status_t
383*7c478bd9Sstevel@tonic-gate _nss_compat_endent(be, dummy)
384*7c478bd9Sstevel@tonic-gate 	compat_backend_ptr_t	be;
385*7c478bd9Sstevel@tonic-gate 	void			*dummy;
386*7c478bd9Sstevel@tonic-gate {
387*7c478bd9Sstevel@tonic-gate 	if (be->f != 0) {
388*7c478bd9Sstevel@tonic-gate 		__nsl_fclose(be->f);
389*7c478bd9Sstevel@tonic-gate 		be->f = 0;
390*7c478bd9Sstevel@tonic-gate 	}
391*7c478bd9Sstevel@tonic-gate 	if (be->buf != 0) {
392*7c478bd9Sstevel@tonic-gate 		free(be->buf);
393*7c478bd9Sstevel@tonic-gate 		be->buf = 0;
394*7c478bd9Sstevel@tonic-gate 	}
395*7c478bd9Sstevel@tonic-gate 	nss_endent(be->db_rootp, be->db_initf, &be->db_context);
396*7c478bd9Sstevel@tonic-gate 
397*7c478bd9Sstevel@tonic-gate 	be->state = GETENT_FILE; /* Probably superfluous but comforting */
398*7c478bd9Sstevel@tonic-gate 	strset_free(&be->minuses);
399*7c478bd9Sstevel@tonic-gate 	netgr_end(be);
400*7c478bd9Sstevel@tonic-gate 
401*7c478bd9Sstevel@tonic-gate 	/*
402*7c478bd9Sstevel@tonic-gate 	 * Question: from the point of view of resource-freeing vs. time to
403*7c478bd9Sstevel@tonic-gate 	 *   start up again, how much should we do in endent() and how much
404*7c478bd9Sstevel@tonic-gate 	 *   in the destructor?
405*7c478bd9Sstevel@tonic-gate 	 */
406*7c478bd9Sstevel@tonic-gate 	return (NSS_SUCCESS);
407*7c478bd9Sstevel@tonic-gate }
408*7c478bd9Sstevel@tonic-gate 
409*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/
410*7c478bd9Sstevel@tonic-gate nss_status_t
411*7c478bd9Sstevel@tonic-gate _nss_compat_destr(be, dummy)
412*7c478bd9Sstevel@tonic-gate 	compat_backend_ptr_t	be;
413*7c478bd9Sstevel@tonic-gate 	void			*dummy;
414*7c478bd9Sstevel@tonic-gate {
415*7c478bd9Sstevel@tonic-gate 	if (be != 0) {
416*7c478bd9Sstevel@tonic-gate 		if (be->f != 0) {
417*7c478bd9Sstevel@tonic-gate 			_nss_compat_endent(be, 0);
418*7c478bd9Sstevel@tonic-gate 		}
419*7c478bd9Sstevel@tonic-gate 		nss_delete(be->db_rootp);
420*7c478bd9Sstevel@tonic-gate 		nss_delete(&netgr_db_root);
421*7c478bd9Sstevel@tonic-gate 		free(be);
422*7c478bd9Sstevel@tonic-gate 	}
423*7c478bd9Sstevel@tonic-gate 	return (NSS_SUCCESS);	/* In case anyone is dumb enough to check */
424*7c478bd9Sstevel@tonic-gate }
425*7c478bd9Sstevel@tonic-gate 
426*7c478bd9Sstevel@tonic-gate static int
427*7c478bd9Sstevel@tonic-gate read_line(f, buffer, buflen)
428*7c478bd9Sstevel@tonic-gate 	__NSL_FILE		*f;
429*7c478bd9Sstevel@tonic-gate 	char			*buffer;
430*7c478bd9Sstevel@tonic-gate 	int			buflen;
431*7c478bd9Sstevel@tonic-gate {
432*7c478bd9Sstevel@tonic-gate 	/*CONSTCOND*/
433*7c478bd9Sstevel@tonic-gate 	while (1) {
434*7c478bd9Sstevel@tonic-gate 		int	linelen;
435*7c478bd9Sstevel@tonic-gate 
436*7c478bd9Sstevel@tonic-gate 		if (__nsl_fgets(buffer, buflen, f) == 0) {
437*7c478bd9Sstevel@tonic-gate 			/* End of file */
438*7c478bd9Sstevel@tonic-gate 			return (-1);
439*7c478bd9Sstevel@tonic-gate 		}
440*7c478bd9Sstevel@tonic-gate 		linelen = strlen(buffer);
441*7c478bd9Sstevel@tonic-gate 		/* linelen >= 1 (since fgets didn't return 0) */
442*7c478bd9Sstevel@tonic-gate 
443*7c478bd9Sstevel@tonic-gate 		if (buffer[linelen - 1] == '\n') {
444*7c478bd9Sstevel@tonic-gate 			/*
445*7c478bd9Sstevel@tonic-gate 			 * ===> The code below that calls read_line() doesn't
446*7c478bd9Sstevel@tonic-gate 			 *	play by the rules;  it assumes in places that
447*7c478bd9Sstevel@tonic-gate 			 *	the line is null-terminated.  For now we'll
448*7c478bd9Sstevel@tonic-gate 			 *	humour it.
449*7c478bd9Sstevel@tonic-gate 			 */
450*7c478bd9Sstevel@tonic-gate 			buffer[--linelen] = '\0';
451*7c478bd9Sstevel@tonic-gate 			return (linelen);
452*7c478bd9Sstevel@tonic-gate 		}
453*7c478bd9Sstevel@tonic-gate 		if (__nsl_feof(f)) {
454*7c478bd9Sstevel@tonic-gate 			/* Line is last line in file, and has no newline */
455*7c478bd9Sstevel@tonic-gate 			return (linelen);
456*7c478bd9Sstevel@tonic-gate 		}
457*7c478bd9Sstevel@tonic-gate 		/* Line too long for buffer;  toss it and loop for next line */
458*7c478bd9Sstevel@tonic-gate 		/* ===== should syslog() in cases where previous code did */
459*7c478bd9Sstevel@tonic-gate 		while (__nsl_fgets(buffer, buflen, f) != 0 &&
460*7c478bd9Sstevel@tonic-gate 		    buffer[strlen(buffer) - 1] != '\n') {
461*7c478bd9Sstevel@tonic-gate 			;
462*7c478bd9Sstevel@tonic-gate 		}
463*7c478bd9Sstevel@tonic-gate 	}
464*7c478bd9Sstevel@tonic-gate }
465*7c478bd9Sstevel@tonic-gate 
466*7c478bd9Sstevel@tonic-gate static int _is_nss_lookup_by_name(int attrdb, nss_dbop_t op) {
467*7c478bd9Sstevel@tonic-gate 	int result = 0;
468*7c478bd9Sstevel@tonic-gate 
469*7c478bd9Sstevel@tonic-gate 	if ((attrdb != 0) &&
470*7c478bd9Sstevel@tonic-gate 		((op == NSS_DBOP_AUDITUSER_BYNAME) ||
471*7c478bd9Sstevel@tonic-gate 		(op == NSS_DBOP_USERATTR_BYNAME))) {
472*7c478bd9Sstevel@tonic-gate 		result = 1;
473*7c478bd9Sstevel@tonic-gate 	} else if ((attrdb == 0) &&
474*7c478bd9Sstevel@tonic-gate 		((op == NSS_DBOP_GROUP_BYNAME) ||
475*7c478bd9Sstevel@tonic-gate 		(op == NSS_DBOP_PASSWD_BYNAME) ||
476*7c478bd9Sstevel@tonic-gate 		(op == NSS_DBOP_SHADOW_BYNAME))) {
477*7c478bd9Sstevel@tonic-gate 		result = 1;
478*7c478bd9Sstevel@tonic-gate 	}
479*7c478bd9Sstevel@tonic-gate 
480*7c478bd9Sstevel@tonic-gate 	return (result);
481*7c478bd9Sstevel@tonic-gate }
482*7c478bd9Sstevel@tonic-gate 
483*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/
484*7c478bd9Sstevel@tonic-gate nss_status_t
485*7c478bd9Sstevel@tonic-gate _attrdb_compat_XY_all(be, argp, netdb, check, op_num)
486*7c478bd9Sstevel@tonic-gate     compat_backend_ptr_t be;
487*7c478bd9Sstevel@tonic-gate     nss_XbyY_args_t *argp;
488*7c478bd9Sstevel@tonic-gate     int netdb;
489*7c478bd9Sstevel@tonic-gate     compat_XY_check_func check;
490*7c478bd9Sstevel@tonic-gate     nss_dbop_t op_num;
491*7c478bd9Sstevel@tonic-gate {
492*7c478bd9Sstevel@tonic-gate 	int		parsestat;
493*7c478bd9Sstevel@tonic-gate 	int		(*func)();
494*7c478bd9Sstevel@tonic-gate 	const char	*filter = argp->key.name;
495*7c478bd9Sstevel@tonic-gate 	nss_status_t	res;
496*7c478bd9Sstevel@tonic-gate 
497*7c478bd9Sstevel@tonic-gate #ifdef	DEBUG
498*7c478bd9Sstevel@tonic-gate 	(void) fprintf(stdout, "\n[compat_common.c: _attrdb_compat_XY_all]\n");
499*7c478bd9Sstevel@tonic-gate #endif	/* DEBUG */
500*7c478bd9Sstevel@tonic-gate 
501*7c478bd9Sstevel@tonic-gate 	if (be->buf == 0 &&
502*7c478bd9Sstevel@tonic-gate 	    (be->buf = malloc(be->minbuf)) == 0) {
503*7c478bd9Sstevel@tonic-gate 		return (NSS_UNAVAIL);
504*7c478bd9Sstevel@tonic-gate 	}
505*7c478bd9Sstevel@tonic-gate 	if ((res = _nss_compat_setent(be, 0)) != NSS_SUCCESS) {
506*7c478bd9Sstevel@tonic-gate 		return (res);
507*7c478bd9Sstevel@tonic-gate 	}
508*7c478bd9Sstevel@tonic-gate 	res = NSS_NOTFOUND;
509*7c478bd9Sstevel@tonic-gate 
510*7c478bd9Sstevel@tonic-gate 	/*CONSTCOND*/
511*7c478bd9Sstevel@tonic-gate 	while (1) {
512*7c478bd9Sstevel@tonic-gate 		int	linelen;
513*7c478bd9Sstevel@tonic-gate 		char	*instr	= be->buf;
514*7c478bd9Sstevel@tonic-gate 
515*7c478bd9Sstevel@tonic-gate 		if ((linelen = read_line(be->f, instr, be->minbuf)) < 0) {
516*7c478bd9Sstevel@tonic-gate 			/* End of file */
517*7c478bd9Sstevel@tonic-gate 			argp->returnval = 0;
518*7c478bd9Sstevel@tonic-gate 			argp->erange    = 0;
519*7c478bd9Sstevel@tonic-gate 			break;
520*7c478bd9Sstevel@tonic-gate 		}
521*7c478bd9Sstevel@tonic-gate 		if (filter != 0 && strstr(instr, filter) == 0) {
522*7c478bd9Sstevel@tonic-gate 			/*
523*7c478bd9Sstevel@tonic-gate 			 * Optimization:  if the entry doesn't contain the
524*7c478bd9Sstevel@tonic-gate 			 * filter string then it can't be the entry we want,
525*7c478bd9Sstevel@tonic-gate 			 * so don't bother looking more closely at it.
526*7c478bd9Sstevel@tonic-gate 			 */
527*7c478bd9Sstevel@tonic-gate 			continue;
528*7c478bd9Sstevel@tonic-gate 		}
529*7c478bd9Sstevel@tonic-gate 		if (netdb) {
530*7c478bd9Sstevel@tonic-gate 			char	*first;
531*7c478bd9Sstevel@tonic-gate 			char	*last;
532*7c478bd9Sstevel@tonic-gate 
533*7c478bd9Sstevel@tonic-gate 			if ((last = strchr(instr, '#')) == 0) {
534*7c478bd9Sstevel@tonic-gate 				last = instr + linelen;
535*7c478bd9Sstevel@tonic-gate 			}
536*7c478bd9Sstevel@tonic-gate 			*last-- = '\0';		/* Nuke '\n' or #comment */
537*7c478bd9Sstevel@tonic-gate 
538*7c478bd9Sstevel@tonic-gate 			/*
539*7c478bd9Sstevel@tonic-gate 			 * Skip leading whitespace.  Normally there isn't
540*7c478bd9Sstevel@tonic-gate 			 * any, so it's not worth calling strspn().
541*7c478bd9Sstevel@tonic-gate 			 */
542*7c478bd9Sstevel@tonic-gate 			for (first = instr;  isspace(*first);  first++) {
543*7c478bd9Sstevel@tonic-gate 				;
544*7c478bd9Sstevel@tonic-gate 			}
545*7c478bd9Sstevel@tonic-gate 			if (*first == '\0') {
546*7c478bd9Sstevel@tonic-gate 				continue;
547*7c478bd9Sstevel@tonic-gate 			}
548*7c478bd9Sstevel@tonic-gate 			/*
549*7c478bd9Sstevel@tonic-gate 			 * Found something non-blank on the line.  Skip back
550*7c478bd9Sstevel@tonic-gate 			 * over any trailing whitespace;  since we know
551*7c478bd9Sstevel@tonic-gate 			 * there's non-whitespace earlier in the line,
552*7c478bd9Sstevel@tonic-gate 			 * checking for termination is easy.
553*7c478bd9Sstevel@tonic-gate 			 */
554*7c478bd9Sstevel@tonic-gate 			while (isspace(*last)) {
555*7c478bd9Sstevel@tonic-gate 				--last;
556*7c478bd9Sstevel@tonic-gate 			}
557*7c478bd9Sstevel@tonic-gate 			linelen = last - first + 1;
558*7c478bd9Sstevel@tonic-gate 			if (first != instr) {
559*7c478bd9Sstevel@tonic-gate 				instr = first;
560*7c478bd9Sstevel@tonic-gate 			}
561*7c478bd9Sstevel@tonic-gate 		}
562*7c478bd9Sstevel@tonic-gate 		argp->returnval = 0;
563*7c478bd9Sstevel@tonic-gate 		func = argp->str2ent;
564*7c478bd9Sstevel@tonic-gate 		parsestat = (*func)(instr, linelen, argp->buf.result,
565*7c478bd9Sstevel@tonic-gate 					argp->buf.buffer, argp->buf.buflen);
566*7c478bd9Sstevel@tonic-gate 		if (parsestat == NSS_STR_PARSE_SUCCESS) {
567*7c478bd9Sstevel@tonic-gate 			argp->returnval = argp->buf.result;
568*7c478bd9Sstevel@tonic-gate 			if (check == 0 || (*check)(argp)) {
569*7c478bd9Sstevel@tonic-gate 				res = NSS_SUCCESS;
570*7c478bd9Sstevel@tonic-gate 				break;
571*7c478bd9Sstevel@tonic-gate 			}
572*7c478bd9Sstevel@tonic-gate 		} else if (parsestat == NSS_STR_PARSE_ERANGE) {
573*7c478bd9Sstevel@tonic-gate 			argp->erange = 1;
574*7c478bd9Sstevel@tonic-gate 			break;
575*7c478bd9Sstevel@tonic-gate 		}
576*7c478bd9Sstevel@tonic-gate 	}
577*7c478bd9Sstevel@tonic-gate 	/*
578*7c478bd9Sstevel@tonic-gate 	 * stayopen is set to 0 by default in order to close the opened
579*7c478bd9Sstevel@tonic-gate 	 * file.  Some applications may break if it is set to 1.
580*7c478bd9Sstevel@tonic-gate 	 */
581*7c478bd9Sstevel@tonic-gate 	if (check != 0 && !argp->stayopen) {
582*7c478bd9Sstevel@tonic-gate 		(void) _nss_compat_endent(be, 0);
583*7c478bd9Sstevel@tonic-gate 	}
584*7c478bd9Sstevel@tonic-gate 
585*7c478bd9Sstevel@tonic-gate 	if (res != NSS_SUCCESS) {
586*7c478bd9Sstevel@tonic-gate 		if ((op_num == NSS_DBOP_USERATTR_BYNAME) ||
587*7c478bd9Sstevel@tonic-gate 		    (op_num == NSS_DBOP_AUDITUSER_BYNAME)) {
588*7c478bd9Sstevel@tonic-gate 			res = nss_search(be->db_rootp,
589*7c478bd9Sstevel@tonic-gate 			    be->db_initf,
590*7c478bd9Sstevel@tonic-gate 			    op_num,
591*7c478bd9Sstevel@tonic-gate 			    argp);
592*7c478bd9Sstevel@tonic-gate 		} else {
593*7c478bd9Sstevel@tonic-gate 			res = nss_getent(be->db_rootp,
594*7c478bd9Sstevel@tonic-gate 			    be->db_initf, &be->db_context, argp);
595*7c478bd9Sstevel@tonic-gate 		}
596*7c478bd9Sstevel@tonic-gate 		if (res != NSS_SUCCESS) {
597*7c478bd9Sstevel@tonic-gate 			argp->returnval	= 0;
598*7c478bd9Sstevel@tonic-gate 			argp->erange	= 0;
599*7c478bd9Sstevel@tonic-gate 		}
600*7c478bd9Sstevel@tonic-gate 	}
601*7c478bd9Sstevel@tonic-gate 
602*7c478bd9Sstevel@tonic-gate 	return (res);
603*7c478bd9Sstevel@tonic-gate }
604*7c478bd9Sstevel@tonic-gate 
605*7c478bd9Sstevel@tonic-gate nss_status_t
606*7c478bd9Sstevel@tonic-gate _nss_compat_XY_all(be, args, check, op_num)
607*7c478bd9Sstevel@tonic-gate 	compat_backend_ptr_t	be;
608*7c478bd9Sstevel@tonic-gate 	nss_XbyY_args_t		*args;
609*7c478bd9Sstevel@tonic-gate 	compat_XY_check_func	check;
610*7c478bd9Sstevel@tonic-gate 	nss_dbop_t		op_num;
611*7c478bd9Sstevel@tonic-gate {
612*7c478bd9Sstevel@tonic-gate 	nss_status_t		res;
613*7c478bd9Sstevel@tonic-gate 	int			parsestat;
614*7c478bd9Sstevel@tonic-gate 
615*7c478bd9Sstevel@tonic-gate 	if (be->buf == 0 &&
616*7c478bd9Sstevel@tonic-gate 	    (be->buf = malloc(be->minbuf)) == 0) {
617*7c478bd9Sstevel@tonic-gate 		return (NSS_UNAVAIL); /* really panic, malloc failed */
618*7c478bd9Sstevel@tonic-gate 	}
619*7c478bd9Sstevel@tonic-gate 
620*7c478bd9Sstevel@tonic-gate 	if ((res = _nss_compat_setent(be, 0)) != NSS_SUCCESS) {
621*7c478bd9Sstevel@tonic-gate 		return (res);
622*7c478bd9Sstevel@tonic-gate 	}
623*7c478bd9Sstevel@tonic-gate 
624*7c478bd9Sstevel@tonic-gate 	res = NSS_NOTFOUND;
625*7c478bd9Sstevel@tonic-gate 
626*7c478bd9Sstevel@tonic-gate 	/*CONSTCOND*/
627*7c478bd9Sstevel@tonic-gate 	while (1) {
628*7c478bd9Sstevel@tonic-gate 		int		linelen;
629*7c478bd9Sstevel@tonic-gate 		char		*instr	= be->buf;
630*7c478bd9Sstevel@tonic-gate 		char		*colon;
631*7c478bd9Sstevel@tonic-gate 
632*7c478bd9Sstevel@tonic-gate 		linelen = read_line(be->f, instr, be->minbuf);
633*7c478bd9Sstevel@tonic-gate 		if (linelen < 0) {
634*7c478bd9Sstevel@tonic-gate 			/* End of file */
635*7c478bd9Sstevel@tonic-gate 			args->returnval = 0;
636*7c478bd9Sstevel@tonic-gate 			args->erange    = 0;
637*7c478bd9Sstevel@tonic-gate 			break;
638*7c478bd9Sstevel@tonic-gate 		}
639*7c478bd9Sstevel@tonic-gate 
640*7c478bd9Sstevel@tonic-gate 		args->returnval = 0;	/* reset for both types of entries */
641*7c478bd9Sstevel@tonic-gate 
642*7c478bd9Sstevel@tonic-gate 		if (instr[0] != '+' && instr[0] != '-') {
643*7c478bd9Sstevel@tonic-gate 			/* Simple, wholesome, God-fearing entry */
644*7c478bd9Sstevel@tonic-gate 			parsestat = (*args->str2ent)(instr, linelen,
645*7c478bd9Sstevel@tonic-gate 						    args->buf.result,
646*7c478bd9Sstevel@tonic-gate 						    args->buf.buffer,
647*7c478bd9Sstevel@tonic-gate 						    args->buf.buflen);
648*7c478bd9Sstevel@tonic-gate 			if (parsestat == NSS_STR_PARSE_SUCCESS) {
649*7c478bd9Sstevel@tonic-gate 				args->returnval = args->buf.result;
650*7c478bd9Sstevel@tonic-gate 				if ((*check)(args) != 0) {
651*7c478bd9Sstevel@tonic-gate 					res = NSS_SUCCESS;
652*7c478bd9Sstevel@tonic-gate 					break;
653*7c478bd9Sstevel@tonic-gate 				}
654*7c478bd9Sstevel@tonic-gate 
655*7c478bd9Sstevel@tonic-gate /* ===> Check the Dani logic here... */
656*7c478bd9Sstevel@tonic-gate 
657*7c478bd9Sstevel@tonic-gate 			} else if (parsestat == NSS_STR_PARSE_ERANGE) {
658*7c478bd9Sstevel@tonic-gate 				args->erange = 1;
659*7c478bd9Sstevel@tonic-gate 				res = NSS_NOTFOUND;
660*7c478bd9Sstevel@tonic-gate 				break;
661*7c478bd9Sstevel@tonic-gate 				/* should we just skip this one long line ? */
662*7c478bd9Sstevel@tonic-gate 			} /* else if (parsestat == NSS_STR_PARSE_PARSE) */
663*7c478bd9Sstevel@tonic-gate 				/* don't care ! */
664*7c478bd9Sstevel@tonic-gate 
665*7c478bd9Sstevel@tonic-gate /* ==> ?? */		continue;
666*7c478bd9Sstevel@tonic-gate 		}
667*7c478bd9Sstevel@tonic-gate 
668*7c478bd9Sstevel@tonic-gate 		/*
669*7c478bd9Sstevel@tonic-gate 		 * Process "+", "+name", "+@netgroup", "-name" or "-@netgroup"
670*7c478bd9Sstevel@tonic-gate 		 *
671*7c478bd9Sstevel@tonic-gate 		 * This code is optimized for lookups by name.
672*7c478bd9Sstevel@tonic-gate 		 *
673*7c478bd9Sstevel@tonic-gate 		 * For lookups by identifier search key cannot be matched with
674*7c478bd9Sstevel@tonic-gate 		 * the name of the "+" or "-" entry. So nss_search() is to be
675*7c478bd9Sstevel@tonic-gate 		 * called before extracting the name i.e. via (*be->getnamef)().
676*7c478bd9Sstevel@tonic-gate 		 *
677*7c478bd9Sstevel@tonic-gate 		 * But for lookups by name, search key is compared with the name
678*7c478bd9Sstevel@tonic-gate 		 * of the "+" or "-" entry to acquire a match and thus
679*7c478bd9Sstevel@tonic-gate 		 * unnesessary calls to nss_search() is eliminated. Also for
680*7c478bd9Sstevel@tonic-gate 		 * matching "-" entries, calls to nss_search() is eliminated.
681*7c478bd9Sstevel@tonic-gate 		 */
682*7c478bd9Sstevel@tonic-gate 
683*7c478bd9Sstevel@tonic-gate 		if ((colon = strchr(instr, ':')) != 0) {
684*7c478bd9Sstevel@tonic-gate 			*colon = '\0';	/* terminate field to extract name */
685*7c478bd9Sstevel@tonic-gate 		}
686*7c478bd9Sstevel@tonic-gate 
687*7c478bd9Sstevel@tonic-gate 		if (instr[1] == '@') {
688*7c478bd9Sstevel@tonic-gate 			/*
689*7c478bd9Sstevel@tonic-gate 			 * Case 1:
690*7c478bd9Sstevel@tonic-gate 			 * The entry is of the form "+@netgroup" or
691*7c478bd9Sstevel@tonic-gate 			 * "-@netgroup".  If we're performing a lookup by name,
692*7c478bd9Sstevel@tonic-gate 			 * we can simply extract the name from the search key
693*7c478bd9Sstevel@tonic-gate 			 * (i.e. args->key.name).  If not, then we must call
694*7c478bd9Sstevel@tonic-gate 			 * nss_search() before extracting the name via the
695*7c478bd9Sstevel@tonic-gate 			 * get_XXname() function. i.e. (*be->getnamef)(args).
696*7c478bd9Sstevel@tonic-gate 			 */
697*7c478bd9Sstevel@tonic-gate 		    if (_is_nss_lookup_by_name(0, op_num) != 0) {
698*7c478bd9Sstevel@tonic-gate 			/* compare then search */
699*7c478bd9Sstevel@tonic-gate 			if (!be->permit_netgroups ||
700*7c478bd9Sstevel@tonic-gate 				!netgr_in(be, instr + 2, args->key.name))
701*7c478bd9Sstevel@tonic-gate 				continue;
702*7c478bd9Sstevel@tonic-gate 			if (instr[0] == '+') {
703*7c478bd9Sstevel@tonic-gate 				/* need to search for "+" entry */
704*7c478bd9Sstevel@tonic-gate 				nss_search(be->db_rootp, be->db_initf, op_num,
705*7c478bd9Sstevel@tonic-gate 					args);
706*7c478bd9Sstevel@tonic-gate 				if (args->returnval == 0)
707*7c478bd9Sstevel@tonic-gate 					continue;
708*7c478bd9Sstevel@tonic-gate 			}
709*7c478bd9Sstevel@tonic-gate 		    } else {
710*7c478bd9Sstevel@tonic-gate 			/* search then compare */
711*7c478bd9Sstevel@tonic-gate 			nss_search(be->db_rootp, be->db_initf, op_num, args);
712*7c478bd9Sstevel@tonic-gate 			if (args->returnval == 0)
713*7c478bd9Sstevel@tonic-gate 				continue;
714*7c478bd9Sstevel@tonic-gate 			if (!be->permit_netgroups ||
715*7c478bd9Sstevel@tonic-gate 				!netgr_in(be, instr + 2, (*be->getnamef)(args)))
716*7c478bd9Sstevel@tonic-gate 				continue;
717*7c478bd9Sstevel@tonic-gate 		    }
718*7c478bd9Sstevel@tonic-gate 		}	/* end of case 1 */
719*7c478bd9Sstevel@tonic-gate 		else if (instr[1] == '\0') {
720*7c478bd9Sstevel@tonic-gate 			/*
721*7c478bd9Sstevel@tonic-gate 			 * Case 2:
722*7c478bd9Sstevel@tonic-gate 			 * The entry is of the form "+" or "-".  The former
723*7c478bd9Sstevel@tonic-gate 			 * allows all entries from name services.  The latter
724*7c478bd9Sstevel@tonic-gate 			 * is illegal and ought to be ignored.
725*7c478bd9Sstevel@tonic-gate 			 */
726*7c478bd9Sstevel@tonic-gate 			if (instr[0] == '-')
727*7c478bd9Sstevel@tonic-gate 				continue;
728*7c478bd9Sstevel@tonic-gate 			/* need to search for "+" entry */
729*7c478bd9Sstevel@tonic-gate 			nss_search(be->db_rootp, be->db_initf, op_num, args);
730*7c478bd9Sstevel@tonic-gate 			if (args->returnval == 0)
731*7c478bd9Sstevel@tonic-gate 				continue;
732*7c478bd9Sstevel@tonic-gate 		}	/* end of case 2 */
733*7c478bd9Sstevel@tonic-gate 		else {
734*7c478bd9Sstevel@tonic-gate 			/*
735*7c478bd9Sstevel@tonic-gate 			 * Case 3:
736*7c478bd9Sstevel@tonic-gate 			 * The entry is of the form "+name" or "-name".
737*7c478bd9Sstevel@tonic-gate 			 * If we're performing a lookup by name, we can simply
738*7c478bd9Sstevel@tonic-gate 			 * extract the name from the search key
739*7c478bd9Sstevel@tonic-gate 			 * (i.e. args->key.name).  If not, then we must call
740*7c478bd9Sstevel@tonic-gate 			 * nss_search() before extracting the name via the
741*7c478bd9Sstevel@tonic-gate 			 * get_XXname() function. i.e. (*be->getnamef)(args).
742*7c478bd9Sstevel@tonic-gate 			 */
743*7c478bd9Sstevel@tonic-gate 			if (_is_nss_lookup_by_name(0, op_num) != 0) {
744*7c478bd9Sstevel@tonic-gate 				/* compare then search */
745*7c478bd9Sstevel@tonic-gate 				if (strcmp(instr + 1, args->key.name) != 0)
746*7c478bd9Sstevel@tonic-gate 					continue;
747*7c478bd9Sstevel@tonic-gate 				if (instr[0] == '+') {
748*7c478bd9Sstevel@tonic-gate 					/* need to search for "+" entry */
749*7c478bd9Sstevel@tonic-gate 					nss_search(be->db_rootp, be->db_initf,
750*7c478bd9Sstevel@tonic-gate 						op_num, args);
751*7c478bd9Sstevel@tonic-gate 					if (args->returnval == 0)
752*7c478bd9Sstevel@tonic-gate 						continue;
753*7c478bd9Sstevel@tonic-gate 				}
754*7c478bd9Sstevel@tonic-gate 			} else {
755*7c478bd9Sstevel@tonic-gate 				/* search then compare */
756*7c478bd9Sstevel@tonic-gate 				nss_search(be->db_rootp, be->db_initf, op_num,
757*7c478bd9Sstevel@tonic-gate 					args);
758*7c478bd9Sstevel@tonic-gate 				if (args->returnval == 0)
759*7c478bd9Sstevel@tonic-gate 					continue;
760*7c478bd9Sstevel@tonic-gate 				if (strcmp(instr + 1, (*be->getnamef)(args))
761*7c478bd9Sstevel@tonic-gate 					!= 0)
762*7c478bd9Sstevel@tonic-gate 					continue;
763*7c478bd9Sstevel@tonic-gate 			}
764*7c478bd9Sstevel@tonic-gate 		} 	/* end of case 3 */
765*7c478bd9Sstevel@tonic-gate 		if (instr[0] == '-') {
766*7c478bd9Sstevel@tonic-gate 			/* no need to search for "-" entry */
767*7c478bd9Sstevel@tonic-gate 			args->returnval = 0;
768*7c478bd9Sstevel@tonic-gate 			args->erange = 0;
769*7c478bd9Sstevel@tonic-gate 			res = NSS_NOTFOUND;
770*7c478bd9Sstevel@tonic-gate 		} else {
771*7c478bd9Sstevel@tonic-gate 			if (colon != 0)
772*7c478bd9Sstevel@tonic-gate 			*colon = ':';	/* restoration */
773*7c478bd9Sstevel@tonic-gate 			res = do_merge(be, args, instr, linelen);
774*7c478bd9Sstevel@tonic-gate 		}
775*7c478bd9Sstevel@tonic-gate 		break;
776*7c478bd9Sstevel@tonic-gate 	}
777*7c478bd9Sstevel@tonic-gate 
778*7c478bd9Sstevel@tonic-gate 	/*
779*7c478bd9Sstevel@tonic-gate 	 * stayopen is set to 0 by default in order to close the opened
780*7c478bd9Sstevel@tonic-gate 	 * file.  Some applications may break if it is set to 1.
781*7c478bd9Sstevel@tonic-gate 	 */
782*7c478bd9Sstevel@tonic-gate 	if (!args->stayopen) {
783*7c478bd9Sstevel@tonic-gate 		(void) _nss_compat_endent(be, 0);
784*7c478bd9Sstevel@tonic-gate 	}
785*7c478bd9Sstevel@tonic-gate 
786*7c478bd9Sstevel@tonic-gate 	return (res);
787*7c478bd9Sstevel@tonic-gate }
788*7c478bd9Sstevel@tonic-gate 
789*7c478bd9Sstevel@tonic-gate nss_status_t
790*7c478bd9Sstevel@tonic-gate _nss_compat_getent(be, a)
791*7c478bd9Sstevel@tonic-gate 	compat_backend_ptr_t	be;
792*7c478bd9Sstevel@tonic-gate 	void			*a;
793*7c478bd9Sstevel@tonic-gate {
794*7c478bd9Sstevel@tonic-gate 	nss_XbyY_args_t		*args = (nss_XbyY_args_t *)a;
795*7c478bd9Sstevel@tonic-gate 	nss_status_t		res;
796*7c478bd9Sstevel@tonic-gate 	char			*colon = 0; /* <=== need comment re lifetime */
797*7c478bd9Sstevel@tonic-gate 
798*7c478bd9Sstevel@tonic-gate 	if (be->f == 0) {
799*7c478bd9Sstevel@tonic-gate 		if ((res = _nss_compat_setent(be, 0)) != NSS_SUCCESS) {
800*7c478bd9Sstevel@tonic-gate 			return (res);
801*7c478bd9Sstevel@tonic-gate 		}
802*7c478bd9Sstevel@tonic-gate 	}
803*7c478bd9Sstevel@tonic-gate 
804*7c478bd9Sstevel@tonic-gate 	if (be->buf == 0 &&
805*7c478bd9Sstevel@tonic-gate 	    (be->buf = malloc(be->minbuf)) == 0) {
806*7c478bd9Sstevel@tonic-gate 		return (NSS_UNAVAIL); /* really panic, malloc failed */
807*7c478bd9Sstevel@tonic-gate 	}
808*7c478bd9Sstevel@tonic-gate 
809*7c478bd9Sstevel@tonic-gate 	/*CONSTCOND*/
810*7c478bd9Sstevel@tonic-gate 	while (1) {
811*7c478bd9Sstevel@tonic-gate 		char		*instr	= be->buf;
812*7c478bd9Sstevel@tonic-gate 		int		linelen;
813*7c478bd9Sstevel@tonic-gate 		char		*name;	/* === Need more distinctive label */
814*7c478bd9Sstevel@tonic-gate 		const char	*savename;
815*7c478bd9Sstevel@tonic-gate 
816*7c478bd9Sstevel@tonic-gate 		/*
817*7c478bd9Sstevel@tonic-gate 		 * In the code below...
818*7c478bd9Sstevel@tonic-gate 		 *    break	means "I found one, I think" (i.e. goto the
819*7c478bd9Sstevel@tonic-gate 		 *		code after the end of the switch statement),
820*7c478bd9Sstevel@tonic-gate 		 *    continue	means "Next candidate"
821*7c478bd9Sstevel@tonic-gate 		 *		(i.e. loop around to the switch statement),
822*7c478bd9Sstevel@tonic-gate 		 *    return	means "I'm quite sure" (either Yes or No).
823*7c478bd9Sstevel@tonic-gate 		 */
824*7c478bd9Sstevel@tonic-gate 		switch (be->state) {
825*7c478bd9Sstevel@tonic-gate 
826*7c478bd9Sstevel@tonic-gate 		    case GETENT_DONE:
827*7c478bd9Sstevel@tonic-gate 			args->returnval	= 0;
828*7c478bd9Sstevel@tonic-gate 			args->erange	= 0;
829*7c478bd9Sstevel@tonic-gate 			return (NSS_NOTFOUND);
830*7c478bd9Sstevel@tonic-gate 
831*7c478bd9Sstevel@tonic-gate 		    case GETENT_ATTRDB:
832*7c478bd9Sstevel@tonic-gate 			res = _attrdb_compat_XY_all(be,
833*7c478bd9Sstevel@tonic-gate 			    args, 1, (compat_XY_check_func)NULL, 0);
834*7c478bd9Sstevel@tonic-gate 			return (res);
835*7c478bd9Sstevel@tonic-gate 
836*7c478bd9Sstevel@tonic-gate 		    case GETENT_FILE:
837*7c478bd9Sstevel@tonic-gate 			linelen = read_line(be->f, instr, be->minbuf);
838*7c478bd9Sstevel@tonic-gate 			if (linelen < 0) {
839*7c478bd9Sstevel@tonic-gate 				/* End of file */
840*7c478bd9Sstevel@tonic-gate 				be->state = GETENT_DONE;
841*7c478bd9Sstevel@tonic-gate 				continue;
842*7c478bd9Sstevel@tonic-gate 			}
843*7c478bd9Sstevel@tonic-gate 			if ((colon = strchr(instr, ':')) != 0) {
844*7c478bd9Sstevel@tonic-gate 				*colon = '\0';
845*7c478bd9Sstevel@tonic-gate 			}
846*7c478bd9Sstevel@tonic-gate 			if (instr[0] == '-') {
847*7c478bd9Sstevel@tonic-gate 				if (instr[1] != '@') {
848*7c478bd9Sstevel@tonic-gate 					strset_add(&be->minuses, instr + 1);
849*7c478bd9Sstevel@tonic-gate 				} else if (be->permit_netgroups) {
850*7c478bd9Sstevel@tonic-gate 					netgr_set(be, instr + 2);
851*7c478bd9Sstevel@tonic-gate 					while (netgr_next_u(be, &name)) {
852*7c478bd9Sstevel@tonic-gate 						strset_add(&be->minuses,
853*7c478bd9Sstevel@tonic-gate 							name);
854*7c478bd9Sstevel@tonic-gate 					}
855*7c478bd9Sstevel@tonic-gate 					netgr_end(be);
856*7c478bd9Sstevel@tonic-gate 				} /* Else (silently) ignore the entry */
857*7c478bd9Sstevel@tonic-gate 				continue;
858*7c478bd9Sstevel@tonic-gate 			} else if (instr[0] != '+') {
859*7c478bd9Sstevel@tonic-gate 				int	parsestat;
860*7c478bd9Sstevel@tonic-gate 				/*
861*7c478bd9Sstevel@tonic-gate 				 * Normal entry, no +/- nonsense
862*7c478bd9Sstevel@tonic-gate 				 */
863*7c478bd9Sstevel@tonic-gate 				if (colon != 0) {
864*7c478bd9Sstevel@tonic-gate 					*colon = ':';
865*7c478bd9Sstevel@tonic-gate 				}
866*7c478bd9Sstevel@tonic-gate 				args->returnval = 0;
867*7c478bd9Sstevel@tonic-gate 				parsestat = (*args->str2ent)(instr, linelen,
868*7c478bd9Sstevel@tonic-gate 							args->buf.result,
869*7c478bd9Sstevel@tonic-gate 							args->buf.buffer,
870*7c478bd9Sstevel@tonic-gate 							args->buf.buflen);
871*7c478bd9Sstevel@tonic-gate 				if (parsestat == NSS_STR_PARSE_SUCCESS) {
872*7c478bd9Sstevel@tonic-gate 					args->returnval = args->buf.result;
873*7c478bd9Sstevel@tonic-gate 					return (NSS_SUCCESS);
874*7c478bd9Sstevel@tonic-gate 				}
875*7c478bd9Sstevel@tonic-gate 				/* ==> ?? Treat ERANGE differently ?? */
876*7c478bd9Sstevel@tonic-gate 				if (parsestat == NSS_STR_PARSE_ERANGE) {
877*7c478bd9Sstevel@tonic-gate 					args->returnval = 0;
878*7c478bd9Sstevel@tonic-gate 					args->erange = 1;
879*7c478bd9Sstevel@tonic-gate 					return (NSS_NOTFOUND);
880*7c478bd9Sstevel@tonic-gate 				}
881*7c478bd9Sstevel@tonic-gate 				/* Skip the offending entry, get next */
882*7c478bd9Sstevel@tonic-gate 				continue;
883*7c478bd9Sstevel@tonic-gate 			} else if (instr[1] == '\0') {
884*7c478bd9Sstevel@tonic-gate 				/* Plain "+" */
885*7c478bd9Sstevel@tonic-gate 				nss_setent(be->db_rootp, be->db_initf,
886*7c478bd9Sstevel@tonic-gate 					&be->db_context);
887*7c478bd9Sstevel@tonic-gate 				be->state = GETENT_ALL;
888*7c478bd9Sstevel@tonic-gate 				be->linelen = linelen;
889*7c478bd9Sstevel@tonic-gate 				continue;
890*7c478bd9Sstevel@tonic-gate 			} else if (instr[1] == '@') {
891*7c478bd9Sstevel@tonic-gate 				/* "+@netgroup" */
892*7c478bd9Sstevel@tonic-gate 				netgr_set(be, instr + 2);
893*7c478bd9Sstevel@tonic-gate 				be->state = GETENT_NETGROUP;
894*7c478bd9Sstevel@tonic-gate 				be->linelen = linelen;
895*7c478bd9Sstevel@tonic-gate 				continue;
896*7c478bd9Sstevel@tonic-gate 			} else {
897*7c478bd9Sstevel@tonic-gate 				/* "+name" */
898*7c478bd9Sstevel@tonic-gate 				name = instr + 1;
899*7c478bd9Sstevel@tonic-gate 				break;
900*7c478bd9Sstevel@tonic-gate 			}
901*7c478bd9Sstevel@tonic-gate 			/* NOTREACHED */
902*7c478bd9Sstevel@tonic-gate 
903*7c478bd9Sstevel@tonic-gate 		    case GETENT_ALL:
904*7c478bd9Sstevel@tonic-gate 			linelen = be->linelen;
905*7c478bd9Sstevel@tonic-gate 			args->returnval = 0;
906*7c478bd9Sstevel@tonic-gate 			nss_getent(be->db_rootp, be->db_initf,
907*7c478bd9Sstevel@tonic-gate 				&be->db_context, args);
908*7c478bd9Sstevel@tonic-gate 			if (args->returnval == 0) {
909*7c478bd9Sstevel@tonic-gate 				/* ==> ?? Treat ERANGE differently ?? */
910*7c478bd9Sstevel@tonic-gate 				nss_endent(be->db_rootp, be->db_initf,
911*7c478bd9Sstevel@tonic-gate 					&be->db_context);
912*7c478bd9Sstevel@tonic-gate 				be->state = GETENT_FILE;
913*7c478bd9Sstevel@tonic-gate 				continue;
914*7c478bd9Sstevel@tonic-gate 			}
915*7c478bd9Sstevel@tonic-gate 			if (strset_in(&be->minuses, (*be->getnamef)(args))) {
916*7c478bd9Sstevel@tonic-gate 				continue;
917*7c478bd9Sstevel@tonic-gate 			}
918*7c478bd9Sstevel@tonic-gate 			name = 0; /* tell code below we've done the lookup */
919*7c478bd9Sstevel@tonic-gate 			break;
920*7c478bd9Sstevel@tonic-gate 
921*7c478bd9Sstevel@tonic-gate 		    case GETENT_NETGROUP:
922*7c478bd9Sstevel@tonic-gate 			linelen = be->linelen;
923*7c478bd9Sstevel@tonic-gate 			if (!netgr_next_u(be, &name)) {
924*7c478bd9Sstevel@tonic-gate 				netgr_end(be);
925*7c478bd9Sstevel@tonic-gate 				be->state = GETENT_FILE;
926*7c478bd9Sstevel@tonic-gate 				continue;
927*7c478bd9Sstevel@tonic-gate 			}
928*7c478bd9Sstevel@tonic-gate 			/* pass "name" variable to code below... */
929*7c478bd9Sstevel@tonic-gate 			break;
930*7c478bd9Sstevel@tonic-gate 		}
931*7c478bd9Sstevel@tonic-gate 
932*7c478bd9Sstevel@tonic-gate 		if (name != 0) {
933*7c478bd9Sstevel@tonic-gate 			if (strset_in(&be->minuses, name)) {
934*7c478bd9Sstevel@tonic-gate 				continue;
935*7c478bd9Sstevel@tonic-gate 			}
936*7c478bd9Sstevel@tonic-gate 			/*
937*7c478bd9Sstevel@tonic-gate 			 * Do a getXXXnam(name).  If we were being pure,
938*7c478bd9Sstevel@tonic-gate 			 *   we'd introduce yet another function-pointer
939*7c478bd9Sstevel@tonic-gate 			 *   that the database-specific code had to supply
940*7c478bd9Sstevel@tonic-gate 			 *   to us.  Instead we'll be grotty and hard-code
941*7c478bd9Sstevel@tonic-gate 			 *   the knowledge that
942*7c478bd9Sstevel@tonic-gate 			 *	(a) The username is always passwd in key.name,
943*7c478bd9Sstevel@tonic-gate 			 *	(b) NSS_DBOP_PASSWD_BYNAME ==
944*7c478bd9Sstevel@tonic-gate 			 *		NSS_DBOP_SHADOW_BYNAME ==
945*7c478bd9Sstevel@tonic-gate 			 *		NSS_DBOP_next_iter.
946*7c478bd9Sstevel@tonic-gate 			 */
947*7c478bd9Sstevel@tonic-gate 			savename = args->key.name;
948*7c478bd9Sstevel@tonic-gate 			args->key.name	= name;
949*7c478bd9Sstevel@tonic-gate 			args->returnval	= 0;
950*7c478bd9Sstevel@tonic-gate 			nss_search(be->db_rootp, be->db_initf,
951*7c478bd9Sstevel@tonic-gate 				NSS_DBOP_next_iter, args);
952*7c478bd9Sstevel@tonic-gate 			args->key.name = savename;  /* In case anyone cares */
953*7c478bd9Sstevel@tonic-gate 		}
954*7c478bd9Sstevel@tonic-gate 		/*
955*7c478bd9Sstevel@tonic-gate 		 * Found one via "+", "+name" or "@netgroup".
956*7c478bd9Sstevel@tonic-gate 		 * Override some fields if the /etc file says to do so.
957*7c478bd9Sstevel@tonic-gate 		 */
958*7c478bd9Sstevel@tonic-gate 		if (args->returnval == 0) {
959*7c478bd9Sstevel@tonic-gate 			/* ==> ?? Should treat erange differently? */
960*7c478bd9Sstevel@tonic-gate 			continue;
961*7c478bd9Sstevel@tonic-gate 		}
962*7c478bd9Sstevel@tonic-gate 		/* 'colon' was set umpteen iterations ago in GETENT_FILE */
963*7c478bd9Sstevel@tonic-gate 		if (colon != 0) {
964*7c478bd9Sstevel@tonic-gate 			*colon = ':';
965*7c478bd9Sstevel@tonic-gate 			colon = 0;
966*7c478bd9Sstevel@tonic-gate 		}
967*7c478bd9Sstevel@tonic-gate 		return (do_merge(be, args, instr, linelen));
968*7c478bd9Sstevel@tonic-gate 	}
969*7c478bd9Sstevel@tonic-gate }
970*7c478bd9Sstevel@tonic-gate 
971*7c478bd9Sstevel@tonic-gate /* We don't use this directly;  we just copy the bits when we want to	 */
972*7c478bd9Sstevel@tonic-gate /* initialize the variable (in the compat_backend struct) that we do use */
973*7c478bd9Sstevel@tonic-gate static DEFINE_NSS_GETENT(context_initval);
974*7c478bd9Sstevel@tonic-gate 
975*7c478bd9Sstevel@tonic-gate nss_backend_t *
976*7c478bd9Sstevel@tonic-gate _nss_compat_constr(ops, n_ops, filename, min_bufsize, rootp, initf, netgroups,
977*7c478bd9Sstevel@tonic-gate 		getname_func, merge_func)
978*7c478bd9Sstevel@tonic-gate 	compat_backend_op_t	ops[];
979*7c478bd9Sstevel@tonic-gate 	int			n_ops;
980*7c478bd9Sstevel@tonic-gate 	const char		*filename;
981*7c478bd9Sstevel@tonic-gate 	int			min_bufsize;
982*7c478bd9Sstevel@tonic-gate 	nss_db_root_t		*rootp;
983*7c478bd9Sstevel@tonic-gate 	nss_db_initf_t		initf;
984*7c478bd9Sstevel@tonic-gate 	int			netgroups;
985*7c478bd9Sstevel@tonic-gate 	compat_get_name		getname_func;
986*7c478bd9Sstevel@tonic-gate 	compat_merge_func	merge_func;
987*7c478bd9Sstevel@tonic-gate {
988*7c478bd9Sstevel@tonic-gate 	compat_backend_ptr_t	be;
989*7c478bd9Sstevel@tonic-gate 
990*7c478bd9Sstevel@tonic-gate 	if ((be = (compat_backend_ptr_t)malloc(sizeof (*be))) == 0) {
991*7c478bd9Sstevel@tonic-gate 		return (0);
992*7c478bd9Sstevel@tonic-gate 	}
993*7c478bd9Sstevel@tonic-gate 	be->ops		= ops;
994*7c478bd9Sstevel@tonic-gate 	be->n_ops	= n_ops;
995*7c478bd9Sstevel@tonic-gate 	be->filename	= filename;
996*7c478bd9Sstevel@tonic-gate 	be->f		= 0;
997*7c478bd9Sstevel@tonic-gate 	be->minbuf	= min_bufsize;
998*7c478bd9Sstevel@tonic-gate 	be->buf		= 0;
999*7c478bd9Sstevel@tonic-gate 
1000*7c478bd9Sstevel@tonic-gate 	be->db_rootp	= rootp;
1001*7c478bd9Sstevel@tonic-gate 	be->db_initf	= initf;
1002*7c478bd9Sstevel@tonic-gate 	be->db_context	= context_initval;
1003*7c478bd9Sstevel@tonic-gate 
1004*7c478bd9Sstevel@tonic-gate 	be->getnamef	= getname_func;
1005*7c478bd9Sstevel@tonic-gate 	be->mergef	= merge_func;
1006*7c478bd9Sstevel@tonic-gate 
1007*7c478bd9Sstevel@tonic-gate 	if ((strcmp(be->filename, USERATTR_FILENAME) == 0) ||
1008*7c478bd9Sstevel@tonic-gate 	    (strcmp(be->filename, AUDITUSER_FILENAME) == 0))
1009*7c478bd9Sstevel@tonic-gate 		be->state = GETENT_ATTRDB;
1010*7c478bd9Sstevel@tonic-gate 	else
1011*7c478bd9Sstevel@tonic-gate 		be->state = GETENT_FILE;    /* i.e. do Automatic setent(); */
1012*7c478bd9Sstevel@tonic-gate 
1013*7c478bd9Sstevel@tonic-gate 	be->minuses	= 0;
1014*7c478bd9Sstevel@tonic-gate 
1015*7c478bd9Sstevel@tonic-gate 	be->permit_netgroups = netgroups;
1016*7c478bd9Sstevel@tonic-gate 	be->yp_domain	= 0;
1017*7c478bd9Sstevel@tonic-gate 	be->getnetgrent_backend	= 0;
1018*7c478bd9Sstevel@tonic-gate 	be->netgr_buffer = 0;
1019*7c478bd9Sstevel@tonic-gate 
1020*7c478bd9Sstevel@tonic-gate 	return ((nss_backend_t *)be);
1021*7c478bd9Sstevel@tonic-gate }
1022