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