getnetgrent.c revision 1.39
1/*	$NetBSD: getnetgrent.c,v 1.39 2007/02/07 19:12:44 oster Exp $	*/
2
3/*
4 * Copyright (c) 1994 Christos Zoulas
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 *    notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 *    notice, this list of conditions and the following disclaimer in the
14 *    documentation and/or other materials provided with the distribution.
15 * 3. All advertising materials mentioning features or use of this software
16 *    must display the following acknowledgement:
17 *	This product includes software developed by Christos Zoulas.
18 * 4. The name of the author may not be used to endorse or promote products
19 *    derived from this software without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
22 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
23 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
25 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 */
33
34#include <sys/cdefs.h>
35#if defined(LIBC_SCCS) && !defined(lint)
36__RCSID("$NetBSD: getnetgrent.c,v 1.39 2007/02/07 19:12:44 oster Exp $");
37#endif /* LIBC_SCCS and not lint */
38
39#include "namespace.h"
40#include <sys/types.h>
41
42#include <assert.h>
43#include <ctype.h>
44#include <db.h>
45#include <err.h>
46#include <fcntl.h>
47#define _NETGROUP_PRIVATE
48#include <stringlist.h>
49#include <netgroup.h>
50#include <nsswitch.h>
51#include <stdarg.h>
52#include <stdio.h>
53#include <stdlib.h>
54#include <string.h>
55
56#ifdef YP
57#include <rpc/rpc.h>
58#include <rpcsvc/ypclnt.h>
59#include <rpcsvc/yp_prot.h>
60#endif
61
62#ifdef __weak_alias
63__weak_alias(endnetgrent,_endnetgrent)
64__weak_alias(getnetgrent,_getnetgrent)
65__weak_alias(innetgr,_innetgr)
66__weak_alias(setnetgrent,_setnetgrent)
67#endif
68
69#define _NG_STAR(s)	(((s) == NULL || *(s) == '\0') ? _ngstar : s)
70#define _NG_EMPTY(s)	((s) == NULL ? "" : s)
71#define _NG_ISSPACE(p)	(isspace((unsigned char) (p)) || (p) == '\n')
72
73static const char _ngstar[] = "*";
74static struct netgroup *_nghead = NULL;
75static struct netgroup *_nglist = NULL;
76static DB *_ng_db;
77
78static int getstring(char **, int, __aconst char **);
79static struct netgroup *getnetgroup(char **);
80static int lookup(char *, char **, int);
81static int addgroup(StringList *, char *);
82static int in_check(const char *, const char *, const char *,
83    struct netgroup *);
84static int in_find(StringList *, char *, const char *, const char *,
85    const char *);
86static char *in_lookup1(const char *, const char *, int);
87static int in_lookup(const char *, const char *, const char *, int);
88
89#ifdef NSSRC_FILES
90static const ns_src default_files_nis[] = {
91	{ NSSRC_FILES,	NS_SUCCESS | NS_NOTFOUND },
92#ifdef YP
93	{ NSSRC_NIS,	NS_SUCCESS },
94#endif
95	{ 0, 0 },
96};
97#endif
98
99/*
100 * getstring(): Get a string delimited by the character, skipping leading and
101 * trailing blanks and advancing the pointer
102 */
103static int
104getstring(char **pp, int del, char __aconst **str)
105{
106	size_t len;
107	char *sp, *ep, *dp;
108
109	_DIAGASSERT(pp != NULL);
110	_DIAGASSERT(str != NULL);
111
112	/* skip leading blanks */
113	for (sp = *pp; *sp && _NG_ISSPACE(*sp); sp++)
114		continue;
115
116	/* accumulate till delimiter or space */
117	for (ep = sp; *ep && *ep != del && !_NG_ISSPACE(*ep); ep++)
118		continue;
119
120	/* hunt for the delimiter */
121	for (dp = ep; *dp && *dp != del && _NG_ISSPACE(*dp); dp++)
122		continue;
123
124	if (*dp != del) {
125		*str = NULL;
126		return 0;
127	}
128
129	*pp = ++dp;
130
131	len = (ep - sp) + 1;
132	if (len > 1) {
133		dp = malloc(len);
134		if (dp == NULL)
135			return 0;
136		(void)memcpy(dp, sp, len);
137		dp[len - 1] = '\0';
138	} else
139		dp = NULL;
140
141	*str = dp;
142	return 1;
143}
144
145
146/*
147 * getnetgroup(): Parse a netgroup, and advance the pointer
148 */
149static struct netgroup *
150getnetgroup(pp)
151	char	**pp;
152{
153	struct netgroup *ng;
154
155	_DIAGASSERT(pp != NULL);
156	_DIAGASSERT(*pp != NULL);
157
158	ng = malloc(sizeof(struct netgroup));
159	if (ng == NULL)
160		return NULL;
161
162	(*pp)++;	/* skip '(' */
163	if (!getstring(pp, ',', &ng->ng_host))
164		goto badhost;
165
166	if (!getstring(pp, ',', &ng->ng_user))
167		goto baduser;
168
169	if (!getstring(pp, ')', &ng->ng_domain))
170		goto baddomain;
171
172#ifdef DEBUG_NG
173	{
174		char buf[1024];
175		(void) fprintf(stderr, "netgroup %s\n",
176		    _ng_print(buf, sizeof(buf), ng));
177	}
178#endif
179	return ng;
180
181baddomain:
182	if (ng->ng_user)
183		free(ng->ng_user);
184baduser:
185	if (ng->ng_host)
186		free(ng->ng_host);
187badhost:
188	free(ng);
189	return NULL;
190}
191
192void
193_ng_cycle(const char *grp, const StringList *sl)
194{
195	size_t i;
196	warnx("netgroup: Cycle in group `%s'", grp);
197	(void)fprintf(stderr, "groups: ");
198	for (i = 0; i < sl->sl_cur; i++)
199		(void)fprintf(stderr, "%s ", sl->sl_str[i]);
200	(void)fprintf(stderr, "\n");
201}
202
203static int _local_lookup(void *, void *, va_list);
204
205/*ARGSUSED*/
206static int
207_local_lookup(void *rv, void *cb_data, va_list ap)
208{
209	char	 *name = va_arg(ap, char *);
210	char	**line = va_arg(ap, char **);
211	int	  bywhat = va_arg(ap, int);
212
213	DBT	 key, data;
214	size_t	 len;
215	char	*ks;
216	int	 r;
217
218	if (_ng_db == NULL)
219		return NS_UNAVAIL;
220
221	len = strlen(name) + 2;
222	ks = malloc(len);
223	if (ks == NULL)
224		return NS_UNAVAIL;
225
226	ks[0] = bywhat;
227	(void)memcpy(&ks[1], name, len - 1);
228
229	key.data = (u_char *)ks;
230	key.size = len;
231
232	r = (*_ng_db->get)(_ng_db, &key, &data, 0);
233	free(ks);
234	switch (r) {
235	case 0:
236		break;
237	case 1:
238		return NS_NOTFOUND;
239	case -1:
240			/* XXX: call endnetgrent() here ? */
241		return NS_UNAVAIL;
242	}
243
244	*line = strdup(data.data);
245	if (*line == NULL)
246		return NS_UNAVAIL;
247	return NS_SUCCESS;
248}
249
250#ifdef YP
251static int _nis_lookup(void *, void *, va_list);
252
253/*ARGSUSED*/
254static int
255_nis_lookup(void *rv, void *cb_data, va_list ap)
256{
257	char	 *name = va_arg(ap, char *);
258	char	**line = va_arg(ap, char **);
259	int	  bywhat = va_arg(ap, int);
260
261	static char	*__ypdomain;
262	int              i;
263	const char      *map = NULL;
264
265	if(__ypdomain == NULL) {
266		switch (yp_get_default_domain(&__ypdomain)) {
267		case 0:
268			break;
269		case YPERR_RESRC:
270			return NS_TRYAGAIN;
271		default:
272			return NS_UNAVAIL;
273		}
274	}
275
276	switch (bywhat) {
277	case _NG_KEYBYNAME:
278		map = "netgroup";
279		break;
280
281	case _NG_KEYBYUSER:
282		map = "netgroup.byuser";
283		break;
284
285	case _NG_KEYBYHOST:
286		map = "netgroup.byhost";
287		break;
288
289	default:
290		abort();
291	}
292
293	*line = NULL;
294	switch (yp_match(__ypdomain, map, name, (int)strlen(name), line, &i)) {
295	case 0:
296		return NS_SUCCESS;
297	case YPERR_KEY:
298		if (*line)
299			free(*line);
300		return NS_NOTFOUND;
301	default:
302		if (*line)
303			free(*line);
304		return NS_UNAVAIL;
305	}
306	/* NOTREACHED */
307}
308#endif
309
310#ifdef NSSRC_FILES
311/*
312 * lookup(): Find the given key in the database or yp, and return its value
313 * in *line; returns 1 if key was found, 0 otherwise
314 */
315static int
316lookup(char *name, char	**line, int bywhat)
317{
318	int		r;
319	static const ns_dtab dtab[] = {
320		NS_FILES_CB(_local_lookup, NULL)
321		NS_NIS_CB(_nis_lookup, NULL)
322		NS_NULL_CB
323	};
324
325	_DIAGASSERT(name != NULL);
326	_DIAGASSERT(line != NULL);
327
328	r = nsdispatch(NULL, dtab, NSDB_NETGROUP, "lookup", default_files_nis,
329	    name, line, bywhat);
330	return (r == NS_SUCCESS) ? 1 : 0;
331}
332#else
333static int
334_local_lookupv(int *rv, void *cbdata, ...)
335{
336	int e;
337	va_list ap;
338	va_start(ap, cbdata);
339	e = _local_lookup(rv, cbdata, ap);
340	va_end(ap);
341	return e;
342}
343
344static int
345lookup(name, line, bywhat)
346	char	 *name;
347	char	**line;
348	int	  bywhat;
349{
350	return _local_lookupv(NULL, NULL, name, line, bywhat) == NS_SUCCESS;
351}
352#endif
353
354/*
355 * _ng_parse(): Parse a line and return: _NG_ERROR: Syntax Error _NG_NONE:
356 * line was empty or a comment _NG_GROUP: line had a netgroup definition,
357 * returned in ng _NG_NAME:  line had a netgroup name, returned in name
358 *
359 * Public since used by netgroup_mkdb
360 */
361int
362_ng_parse(char **p, char **name, struct netgroup **ng)
363{
364
365	_DIAGASSERT(p != NULL);
366	_DIAGASSERT(*p != NULL);
367	_DIAGASSERT(name != NULL);
368	_DIAGASSERT(ng != NULL);
369
370	while (**p) {
371		if (**p == '#')
372			/* comment */
373			return _NG_NONE;
374
375		while (**p && _NG_ISSPACE(**p))
376			/* skipblank */
377			(*p)++;
378
379		if (**p == '(') {
380			if ((*ng = getnetgroup(p)) == NULL)
381				return _NG_ERROR;
382			return _NG_GROUP;
383		} else {
384			char	*np;
385			size_t	i;
386
387			for (np = *p; **p && !_NG_ISSPACE(**p); (*p)++)
388				continue;
389			if (np != *p) {
390				i = (*p - np) + 1;
391				*name = malloc(i);
392				if (*name == NULL)
393					return _NG_ERROR;
394				(void)memcpy(*name, np, i);
395				(*name)[i - 1] = '\0';
396				return _NG_NAME;
397			}
398		}
399	}
400	return _NG_NONE;
401}
402
403
404/*
405 * addgroup(): Recursively add all the members of the netgroup to this group.
406 * returns 0 upon failure, nonzero upon success.
407 * grp is not a valid pointer after return (either free(3)ed or allocated
408 * to a stringlist). in either case, it shouldn't be used again.
409 */
410static int
411addgroup(StringList *sl, char *grp)
412{
413	char		*line, *p;
414	struct netgroup	*ng;
415	char		*name;
416
417	_DIAGASSERT(sl != NULL);
418	_DIAGASSERT(grp != NULL);
419
420#ifdef DEBUG_NG
421	(void)fprintf(stderr, "addgroup(%s)\n", grp);
422#endif
423	/* check for cycles */
424	if (sl_find(sl, grp) != NULL) {
425		_ng_cycle(grp, sl);
426		free(grp);
427		return 0;
428	}
429	if (sl_add(sl, grp) == -1) {
430		free(grp);
431		return 0;
432	}
433
434	/* Lookup this netgroup */
435	line = NULL;
436	if (!lookup(grp, &line, _NG_KEYBYNAME)) {
437		if (line)
438			free(line);
439		return 0;
440	}
441
442	p = line;
443
444	for (;;) {
445		switch (_ng_parse(&p, &name, &ng)) {
446		case _NG_NONE:
447			/* Done with the line */
448			free(line);
449			return 1;
450
451		case _NG_GROUP:
452			/* new netgroup */
453			/* add to the list */
454			ng->ng_next = _nglist;
455			_nglist = ng;
456			break;
457
458		case _NG_NAME:
459			/* netgroup name */
460			if (!addgroup(sl, name))
461				return 0;
462			break;
463
464		case _NG_ERROR:
465			return 0;
466
467		default:
468			abort();
469		}
470	}
471}
472
473
474/*
475 * in_check(): Compare the spec with the netgroup
476 */
477static int
478in_check(const char *host, const char *user, const char *domain,
479    struct netgroup *ng)
480{
481
482	/* host may be NULL */
483	/* user may be NULL */
484	/* domain may be NULL */
485	_DIAGASSERT(ng != NULL);
486
487	if ((host != NULL) && (ng->ng_host != NULL)
488	    && strcmp(ng->ng_host, host) != 0)
489		return 0;
490
491	if ((user != NULL) && (ng->ng_user != NULL)
492	    && strcmp(ng->ng_user, user) != 0)
493		return 0;
494
495	if ((domain != NULL) && (ng->ng_domain != NULL)
496	    && strcmp(ng->ng_domain, domain) != 0)
497		return 0;
498
499	return 1;
500}
501
502
503/*
504 * in_find(): Find a match for the host, user, domain spec.
505 * grp is not a valid pointer after return (either free(3)ed or allocated
506 * to a stringlist). in either case, it shouldn't be used again.
507 */
508static int
509in_find(StringList *sl, char *grp, const char *host, const char *user,
510    const char *domain)
511{
512	char		*line, *p;
513	int		 i;
514	struct netgroup	*ng;
515	char		*name;
516
517	_DIAGASSERT(sl != NULL);
518	_DIAGASSERT(grp != NULL);
519	/* host may be NULL */
520	/* user may be NULL */
521	/* domain may be NULL */
522
523#ifdef DEBUG_NG
524	(void)fprintf(stderr, "in_find(%s)\n", grp);
525#endif
526	/* check for cycles */
527	if (sl_find(sl, grp) != NULL) {
528		_ng_cycle(grp, sl);
529		free(grp);
530		return 0;
531	}
532	if (sl_add(sl, grp) == -1) {
533		free(grp);
534		return 0;
535	}
536
537	/* Lookup this netgroup */
538	line = NULL;
539	if (!lookup(grp, &line, _NG_KEYBYNAME)) {
540		if (line)
541			free(line);
542		return 0;
543	}
544
545	p = line;
546
547	for (;;) {
548		switch (_ng_parse(&p, &name, &ng)) {
549		case _NG_NONE:
550			/* Done with the line */
551			free(line);
552			return 0;
553
554		case _NG_GROUP:
555			/* new netgroup */
556			i = in_check(host, user, domain, ng);
557			if (ng->ng_host != NULL)
558				free(ng->ng_host);
559			if (ng->ng_user != NULL)
560				free(ng->ng_user);
561			if (ng->ng_domain != NULL)
562				free(ng->ng_domain);
563			free(ng);
564			if (i) {
565				free(line);
566				return 1;
567			}
568			break;
569
570		case _NG_NAME:
571			/* netgroup name */
572			if (in_find(sl, name, host, user, domain)) {
573				free(line);
574				return 1;
575			}
576			break;
577
578		case _NG_ERROR:
579			free(line);
580			return 0;
581
582		default:
583			abort();
584		}
585	}
586}
587
588/*
589 * _ng_makekey(): Make a key from the two names given. The key is of the form
590 * <name1>.<name2> Names strings are replaced with * if they are empty;
591 * Returns NULL if there's a problem.
592 */
593char *
594_ng_makekey(const char *s1, const char *s2, size_t len)
595{
596	char *buf;
597
598	/* s1 may be NULL */
599	/* s2 may be NULL */
600
601	buf = malloc(len);
602	if (buf != NULL)
603		(void)snprintf(buf, len, "%s.%s", _NG_STAR(s1), _NG_STAR(s2));
604	return buf;
605}
606
607void
608_ng_print(char *buf, size_t len, const struct netgroup *ng)
609{
610	_DIAGASSERT(buf != NULL);
611	_DIAGASSERT(ng != NULL);
612
613	(void)snprintf(buf, len, "(%s,%s,%s)", _NG_EMPTY(ng->ng_host),
614	    _NG_EMPTY(ng->ng_user), _NG_EMPTY(ng->ng_domain));
615}
616
617
618/*
619 * in_lookup1(): Fast lookup for a key in the appropriate map
620 */
621static char *
622in_lookup1(const char *key, const char *domain, int map)
623{
624	char	*line;
625	size_t	 len;
626	char	*ptr;
627	int	 res;
628
629	/* key may be NULL */
630	/* domain may be NULL */
631
632	len = (key ? strlen(key) : 1) + (domain ? strlen(domain) : 1) + 2;
633	ptr = _ng_makekey(key, domain, len);
634	if (ptr == NULL)
635		return NULL;
636	res = lookup(ptr, &line, map);
637	free(ptr);
638	return res ? line : NULL;
639}
640
641
642/*
643 * in_lookup(): Fast lookup for a key in the appropriate map
644 */
645static int
646in_lookup(const char *group, const char *key, const char *domain, int map)
647{
648	size_t	 len;
649	char	*ptr, *line;
650
651	_DIAGASSERT(group != NULL);
652	/* key may be NULL */
653	/* domain may be NULL */
654
655	if (domain != NULL) {
656		/* Domain specified; look in "group.domain" and "*.domain" */
657		if ((line = in_lookup1(key, domain, map)) == NULL)
658			line = in_lookup1(NULL, domain, map);
659	} else
660		line = NULL;
661
662	if (line == NULL) {
663	    /*
664	     * domain not specified or domain lookup failed; look in
665	     * "group.*" and "*.*"
666	     */
667	    if (((line = in_lookup1(key, NULL, map)) == NULL) &&
668		((line = in_lookup1(NULL, NULL, map)) == NULL))
669		return 0;
670	}
671
672	len = strlen(group);
673
674	for (ptr = line; (ptr = strstr(ptr, group)) != NULL;)
675		/* Make sure we did not find a substring */
676		if ((ptr != line && ptr[-1] != ',') ||
677		    (ptr[len] != '\0' && strchr("\n\t ,", ptr[len]) == NULL))
678			ptr++;
679		else {
680			free(line);
681			return 1;
682		}
683
684	free(line);
685	return 0;
686}
687
688/*ARGSUSED*/
689static int
690_local_endnetgrent(void *rv, void *cb_data, va_list ap)
691{
692	for (_nglist = _nghead; _nglist != NULL; _nglist = _nghead) {
693		_nghead = _nglist->ng_next;
694		if (_nglist->ng_host != NULL)
695			free(_nglist->ng_host);
696		if (_nglist->ng_user != NULL)
697			free(_nglist->ng_user);
698		if (_nglist->ng_domain != NULL)
699			free(_nglist->ng_domain);
700		free(_nglist);
701	}
702
703	if (_ng_db) {
704		(void)(*_ng_db->close)(_ng_db);
705		_ng_db = NULL;
706	}
707
708	return NS_SUCCESS;
709}
710
711/*ARGSUSED*/
712static int
713_local_setnetgrent(void *rv, void *cb_data, va_list ap)
714{
715	const char	*ng = va_arg(ap, const char *);
716	StringList	*sl;
717	char		*ng_copy;
718
719	_DIAGASSERT(ng != NULL);
720
721	sl = sl_init();
722	if (sl == NULL)
723		return NS_TRYAGAIN;
724
725	/* Cleanup any previous storage */
726	if (_nghead != NULL)
727		endnetgrent();
728
729	if (_ng_db == NULL)
730		_ng_db = dbopen(_PATH_NETGROUP_DB, O_RDONLY, 0, DB_HASH, NULL);
731
732	ng_copy = strdup(ng);
733	if (ng_copy != NULL)
734		addgroup(sl, ng_copy);
735	_nghead = _nglist;
736	sl_free(sl, 1);
737
738	return NS_SUCCESS;
739}
740
741/*ARGSUSED*/
742static int
743_local_getnetgrent(void *rv, void *cb_data, va_list ap)
744{
745	int *retval = va_arg(ap, int *);
746	const char **host = va_arg(ap, const char **);
747	const char **user = va_arg(ap, const char **);
748	const char **domain = va_arg(ap, const char **);
749
750	_DIAGASSERT(host != NULL);
751	_DIAGASSERT(user != NULL);
752	_DIAGASSERT(domain != NULL);
753
754	*retval = 0;
755
756	if (_nglist == NULL)
757		return NS_TRYAGAIN;
758
759	*host   = _nglist->ng_host;
760	*user   = _nglist->ng_user;
761	*domain = _nglist->ng_domain;
762
763	_nglist = _nglist->ng_next;
764
765	*retval = 1;
766
767	return NS_SUCCESS;
768}
769
770/*ARGSUSED*/
771static int
772_local_innetgr(void *rv, void *cb_data, va_list ap)
773{
774	int *retval = va_arg(ap, int *);
775	const char *grp = va_arg(ap, const char *);
776	const char *host = va_arg(ap, const char *);
777	const char *user = va_arg(ap, const char *);
778	const char *domain = va_arg(ap, const char *);
779
780	int	 found;
781	StringList *sl;
782	char *grcpy;
783
784	_DIAGASSERT(grp != NULL);
785	/* host may be NULL */
786	/* user may be NULL */
787	/* domain may be NULL */
788
789	if (_ng_db == NULL)
790		_ng_db = dbopen(_PATH_NETGROUP_DB, O_RDONLY, 0, DB_HASH, NULL);
791
792	/* Try the fast lookup first */
793	if (host != NULL && user == NULL) {
794		if (in_lookup(grp, host, domain, _NG_KEYBYHOST)) {
795			*retval = 1;
796			return NS_SUCCESS;
797		}
798	} else if (host == NULL && user != NULL) {
799		if (in_lookup(grp, user, domain, _NG_KEYBYUSER)) {
800			*retval = 1;
801			return NS_SUCCESS;
802		}
803	}
804	/* If a domainname is given, we would have found a match */
805	if (domain != NULL) {
806		*retval = 0;
807		return NS_SUCCESS;
808	}
809
810	/* Too bad need the slow recursive way */
811	sl = sl_init();
812	if (sl == NULL) {
813		*retval = 0;
814		return NS_SUCCESS;
815	}
816	if ((grcpy = strdup(grp)) == NULL) {
817		sl_free(sl, 1);
818		*retval = 0;
819		return NS_SUCCESS;
820	}
821	found = in_find(sl, grcpy, host, user, domain);
822	sl_free(sl, 1);
823
824	*retval = found;
825	return NS_SUCCESS;
826}
827
828#ifdef YP
829
830/*ARGSUSED*/
831static int
832_nis_endnetgrent(void *rv, void *cb_data, va_list ap)
833{
834	return _local_endnetgrent(rv, cb_data, ap);
835}
836
837/*ARGSUSED*/
838static int
839_nis_setnetgrent(void *rv, void *cb_data, va_list ap)
840{
841	return _local_setnetgrent(rv, cb_data, ap);
842}
843
844/*ARGSUSED*/
845static int
846_nis_getnetgrent(void *rv, void *cb_data, va_list ap)
847{
848	return _local_getnetgrent(rv, cb_data, ap);
849}
850
851/*ARGSUSED*/
852static int
853_nis_innetgr(void *rv, void *cb_data, va_list ap)
854{
855	return _local_innetgr(rv, cb_data, ap);
856}
857
858#endif
859
860
861#ifdef NSSRC_FILES
862void
863endnetgrent(void)
864{
865	static const ns_dtab dtab[] = {
866		NS_FILES_CB(_local_endnetgrent, NULL)
867		NS_NIS_CB(_nis_endnetgrent, NULL)
868		NS_NULL_CB
869	};
870
871	(void) nsdispatch(NULL, dtab, NSDB_NETGROUP, "endnetgrent",
872			  __nsdefaultcompat);
873}
874#else
875static int
876_local_endnetgrentv(int *rv, void *cbdata, ...)
877{
878	int e;
879	va_list ap;
880	va_start(ap, cbdata);
881	e = _local_endnetgrent(rv, cbdata, ap);
882	va_end(ap);
883	return e;
884}
885
886void
887endnetgrent(void)
888{
889	(void)_local_endnetgrentv(NULL, NULL, NULL);
890}
891#endif
892
893#ifdef NSSRC_FILES
894void
895setnetgrent(const char *ng)
896{
897	static const ns_dtab dtab[] = {
898		NS_FILES_CB(_local_setnetgrent, NULL)
899		NS_NIS_CB(_nis_setnetgrent, NULL)
900		NS_NULL_CB
901	};
902
903	(void ) nsdispatch(NULL, dtab, NSDB_NETGROUP, "setnetgrent",
904			   __nsdefaultnis, ng);
905}
906#else
907static int
908_local_setnetgrentv(int *rv, void *cbdata, ...)
909{
910	int e;
911	va_list ap;
912	va_start(ap, cbdata);
913	e = _local_setnetgrent(rv, cbdata, ap);
914	va_end(ap);
915	return e;
916}
917
918void
919setnetgrent(const char *ng)
920{
921	(void) _local_setnetgrentv(NULL, NULL,ng);
922}
923
924#endif
925
926#ifdef NSSRC_FILES
927int
928getnetgrent(const char **host, const char **user, const char **domain)
929{
930	int     r, retval;
931	static const ns_dtab dtab[] = {
932		NS_FILES_CB(_local_getnetgrent, NULL)
933		NS_NIS_CB(_nis_getnetgrent, NULL)
934		NS_NULL_CB
935	};
936
937	r = nsdispatch(NULL, dtab, NSDB_NETGROUP, "getnetgrent",
938		       __nsdefaultnis, &retval, host, user, domain);
939
940	return (r == NS_SUCCESS) ? retval : 0;
941}
942#else
943static int
944_local_getnetgrentv(int *rv, void *cbdata, ...)
945{
946	int e;
947	va_list ap;
948	va_start(ap, cbdata);
949	e = _local_getnetgrent(rv, cbdata, ap);
950	va_end(ap);
951	return e;
952}
953
954int
955getnetgrent(const char **host, const char **user, const char **domain)
956{
957	return _local_getnetgrentv(NULL, NULL, host, user, domain) == NS_SUCCESS;
958}
959#endif
960
961#ifdef NSSRC_FILES
962int
963innetgr(const char *grp, const char *host, const char *user,
964	const char *domain)
965{
966	int     r, retval;
967	static const ns_dtab dtab[] = {
968		NS_FILES_CB(_local_innetgr, NULL)
969		NS_NIS_CB(_nis_innetgr, NULL)
970		NS_NULL_CB
971	};
972
973	r = nsdispatch(NULL, dtab, NSDB_NETGROUP, "innetgr",
974		       __nsdefaultnis, &retval, grp, host, user, domain);
975
976	return (r == NS_SUCCESS) ? retval : 0;
977}
978#else
979static int
980_local_innetgrv(int *rv, void *cbdata, ...)
981{
982	int e;
983	va_list ap;
984	va_start(ap, cbdata);
985	e = _local_innetgr(rv, cbdata, ap);
986	va_end(ap);
987	return e;
988}
989
990int
991innetgr(const char *grp, const char *host, const char *user,
992	const char *domain)
993{
994	return _local_innetgrv(NULL, NULL, grp, host, user, domain) == NS_SUCCESS;
995}
996#endif
997