Home | History | Annotate | Line # | Download | only in gen
getgrent.c revision 1.61.10.1
      1  1.61.10.1      yamt /*	$NetBSD: getgrent.c,v 1.61.10.1 2008/05/18 12:30:15 yamt Exp $	*/
      2       1.49     lukem 
      3       1.49     lukem /*-
      4       1.54     lukem  * Copyright (c) 1999-2000, 2004-2005 The NetBSD Foundation, Inc.
      5       1.49     lukem  * All rights reserved.
      6       1.49     lukem  *
      7       1.49     lukem  * This code is derived from software contributed to The NetBSD Foundation
      8       1.49     lukem  * by Luke Mewburn.
      9       1.49     lukem  *
     10       1.49     lukem  * Redistribution and use in source and binary forms, with or without
     11       1.49     lukem  * modification, are permitted provided that the following conditions
     12       1.49     lukem  * are met:
     13       1.49     lukem  * 1. Redistributions of source code must retain the above copyright
     14       1.49     lukem  *    notice, this list of conditions and the following disclaimer.
     15       1.49     lukem  * 2. Redistributions in binary form must reproduce the above copyright
     16       1.49     lukem  *    notice, this list of conditions and the following disclaimer in the
     17       1.49     lukem  *    documentation and/or other materials provided with the distribution.
     18       1.49     lukem  *
     19       1.49     lukem  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     20       1.49     lukem  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     21       1.49     lukem  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     22       1.49     lukem  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     23       1.49     lukem  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     24       1.49     lukem  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     25       1.49     lukem  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     26       1.49     lukem  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     27       1.49     lukem  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     28       1.49     lukem  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     29       1.49     lukem  * POSSIBILITY OF SUCH DAMAGE.
     30       1.49     lukem  */
     31       1.11       cgd 
     32        1.1       cgd /*
     33       1.11       cgd  * Copyright (c) 1989, 1993
     34       1.11       cgd  *	The Regents of the University of California.  All rights reserved.
     35       1.47       agc  *
     36       1.47       agc  * Redistribution and use in source and binary forms, with or without
     37       1.47       agc  * modification, are permitted provided that the following conditions
     38       1.47       agc  * are met:
     39       1.47       agc  * 1. Redistributions of source code must retain the above copyright
     40       1.47       agc  *    notice, this list of conditions and the following disclaimer.
     41       1.47       agc  * 2. Redistributions in binary form must reproduce the above copyright
     42       1.47       agc  *    notice, this list of conditions and the following disclaimer in the
     43       1.47       agc  *    documentation and/or other materials provided with the distribution.
     44       1.47       agc  * 3. Neither the name of the University nor the names of its contributors
     45       1.47       agc  *    may be used to endorse or promote products derived from this software
     46       1.47       agc  *    without specific prior written permission.
     47       1.47       agc  *
     48       1.47       agc  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     49       1.47       agc  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     50       1.47       agc  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     51       1.47       agc  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     52       1.47       agc  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     53       1.47       agc  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     54       1.47       agc  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     55       1.47       agc  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     56       1.47       agc  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     57       1.47       agc  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     58       1.47       agc  * SUCH DAMAGE.
     59       1.47       agc  */
     60       1.47       agc 
     61       1.47       agc /*
     62       1.13      phil  * Portions Copyright (c) 1994, Jason Downs. All Rights Reserved.
     63        1.1       cgd  *
     64        1.1       cgd  * Redistribution and use in source and binary forms, with or without
     65        1.1       cgd  * modification, are permitted provided that the following conditions
     66        1.1       cgd  * are met:
     67        1.1       cgd  * 1. Redistributions of source code must retain the above copyright
     68        1.1       cgd  *    notice, this list of conditions and the following disclaimer.
     69        1.1       cgd  * 2. Redistributions in binary form must reproduce the above copyright
     70        1.1       cgd  *    notice, this list of conditions and the following disclaimer in the
     71        1.1       cgd  *    documentation and/or other materials provided with the distribution.
     72        1.1       cgd  *
     73       1.48       agc  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS
     74       1.48       agc  * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
     75       1.48       agc  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
     76       1.48       agc  * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT,
     77       1.48       agc  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
     78       1.48       agc  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
     79       1.48       agc  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
     80       1.48       agc  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     81        1.1       cgd  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     82        1.1       cgd  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     83        1.1       cgd  * SUCH DAMAGE.
     84        1.1       cgd  */
     85        1.1       cgd 
     86       1.20  christos #include <sys/cdefs.h>
     87        1.1       cgd #if defined(LIBC_SCCS) && !defined(lint)
     88       1.11       cgd #if 0
     89       1.11       cgd static char sccsid[] = "@(#)getgrent.c	8.2 (Berkeley) 3/21/94";
     90       1.11       cgd #else
     91  1.61.10.1      yamt __RCSID("$NetBSD: getgrent.c,v 1.61.10.1 2008/05/18 12:30:15 yamt Exp $");
     92       1.11       cgd #endif
     93        1.1       cgd #endif /* LIBC_SCCS and not lint */
     94        1.1       cgd 
     95       1.21       jtc #include "namespace.h"
     96       1.51     lukem #include "reentrant.h"
     97       1.33     lukem 
     98       1.49     lukem #include <sys/param.h>
     99       1.33     lukem 
    100       1.37     lukem #include <assert.h>
    101       1.33     lukem #include <errno.h>
    102       1.27     lukem #include <grp.h>
    103       1.18     lukem #include <limits.h>
    104       1.27     lukem #include <nsswitch.h>
    105       1.50     lukem #include <stdarg.h>
    106        1.1       cgd #include <stdio.h>
    107        1.1       cgd #include <stdlib.h>
    108        1.2   deraadt #include <string.h>
    109       1.27     lukem #include <syslog.h>
    110       1.33     lukem 
    111       1.27     lukem #ifdef HESIOD
    112       1.27     lukem #include <hesiod.h>
    113       1.27     lukem #endif
    114       1.49     lukem 
    115        1.2   deraadt #ifdef YP
    116        1.2   deraadt #include <rpc/rpc.h>
    117        1.2   deraadt #include <rpcsvc/yp_prot.h>
    118        1.2   deraadt #include <rpcsvc/ypclnt.h>
    119       1.21       jtc #endif
    120       1.21       jtc 
    121       1.54     lukem #include "gr_private.h"
    122       1.34     lukem 
    123       1.21       jtc #ifdef __weak_alias
    124       1.39   mycroft __weak_alias(endgrent,_endgrent)
    125       1.39   mycroft __weak_alias(getgrent,_getgrent)
    126       1.56  christos __weak_alias(getgrent_r,_getgrent_r)
    127       1.39   mycroft __weak_alias(getgrgid,_getgrgid)
    128       1.49     lukem __weak_alias(getgrgid_r,_getgrgid_r)
    129       1.39   mycroft __weak_alias(getgrnam,_getgrnam)
    130       1.49     lukem __weak_alias(getgrnam_r,_getgrnam_r)
    131       1.39   mycroft __weak_alias(setgrent,_setgrent)
    132       1.39   mycroft __weak_alias(setgroupent,_setgroupent)
    133        1.2   deraadt #endif
    134       1.54     lukem 
    135       1.50     lukem #ifdef _REENTRANT
    136       1.54     lukem mutex_t	__grmutex = MUTEX_INITIALIZER;
    137       1.50     lukem #endif
    138        1.1       cgd 
    139       1.49     lukem /*
    140       1.49     lukem  * _gr_memfrombuf
    141       1.49     lukem  *	Obtain want bytes from buffer (of size buflen) and return a pointer
    142       1.49     lukem  *	to the available memory after adjusting buffer/buflen.
    143       1.49     lukem  *	Returns NULL if there is insufficient space.
    144       1.49     lukem  */
    145       1.49     lukem static char *
    146       1.49     lukem _gr_memfrombuf(size_t want, char **buffer, size_t *buflen)
    147       1.49     lukem {
    148       1.49     lukem 	char	*rv;
    149       1.49     lukem 
    150       1.49     lukem 	if (want > *buflen) {
    151       1.49     lukem 		errno = ERANGE;
    152       1.49     lukem 		return NULL;
    153       1.49     lukem 	}
    154       1.49     lukem 	rv = *buffer;
    155       1.49     lukem 	*buffer += want;
    156       1.49     lukem 	*buflen -= want;
    157       1.49     lukem 	return rv;
    158       1.49     lukem }
    159       1.27     lukem 
    160       1.49     lukem /*
    161       1.49     lukem  * _gr_parse
    162       1.49     lukem  *	Parses entry as a line per group(5) (without the trailing \n)
    163       1.49     lukem  *	and fills in grp with corresponding values; memory for strings
    164       1.49     lukem  *	and arrays will be allocated from buf (of size buflen).
    165       1.49     lukem  *	Returns 1 if parsed successfully, 0 on parse failure.
    166       1.49     lukem  */
    167       1.49     lukem static int
    168       1.49     lukem _gr_parse(const char *entry, struct group *grp, char *buf, size_t buflen)
    169       1.49     lukem {
    170       1.49     lukem 	unsigned long	id;
    171       1.49     lukem 	const char	*bp;
    172       1.49     lukem 	char		*ep;
    173       1.49     lukem 	size_t		count;
    174       1.49     lukem 	int		memc;
    175       1.49     lukem 
    176       1.49     lukem 	_DIAGASSERT(entry != NULL);
    177       1.49     lukem 	_DIAGASSERT(grp != NULL);
    178       1.49     lukem 	_DIAGASSERT(buf != NULL);
    179       1.49     lukem 
    180       1.49     lukem #define COPYTOBUF(to) \
    181       1.49     lukem 	do { \
    182       1.49     lukem 		(to) = _gr_memfrombuf(count+1, &buf, &buflen); \
    183       1.49     lukem 		if ((to) == NULL) \
    184       1.49     lukem 			return 0; \
    185       1.49     lukem 		memmove((to), entry, count); \
    186       1.49     lukem 		to[count] = '\0'; \
    187       1.49     lukem 	} while (0)	/* LINTED */
    188        1.1       cgd 
    189       1.49     lukem #if 0
    190       1.49     lukem 	if (*entry == '+')			/* fail on compat `+' token */
    191       1.49     lukem 		return 0;
    192       1.27     lukem #endif
    193       1.27     lukem 
    194       1.49     lukem 	count = strcspn(entry, ":");		/* parse gr_name */
    195       1.49     lukem 	if (entry[count] == '\0')
    196       1.49     lukem 		return 0;
    197       1.49     lukem 	COPYTOBUF(grp->gr_name);
    198       1.49     lukem 	entry += count + 1;
    199       1.49     lukem 
    200       1.49     lukem 	count = strcspn(entry, ":");		/* parse gr_passwd */
    201       1.49     lukem 	if (entry[count] == '\0')
    202       1.49     lukem 		return 0;
    203       1.49     lukem 	COPYTOBUF(grp->gr_passwd);
    204       1.49     lukem 	entry += count + 1;
    205       1.49     lukem 
    206       1.49     lukem 	count = strcspn(entry, ":");		/* parse gr_gid */
    207       1.49     lukem 	if (entry[count] == '\0')
    208       1.49     lukem 		return 0;
    209       1.49     lukem 	id = strtoul(entry, &ep, 10);
    210       1.49     lukem 	if (id > GID_MAX || *ep != ':')
    211       1.49     lukem 		return 0;
    212       1.49     lukem 	grp->gr_gid = (gid_t)id;
    213       1.49     lukem 	entry += count + 1;
    214       1.49     lukem 
    215       1.49     lukem 	memc = 1;				/* for final NULL */
    216       1.49     lukem 	if (*entry != '\0')
    217       1.49     lukem 		memc++;				/* for first item */
    218       1.49     lukem 	for (bp = entry; *bp != '\0'; bp++) {
    219       1.49     lukem 		if (*bp == ',')
    220       1.49     lukem 			memc++;
    221       1.49     lukem 	}
    222       1.49     lukem 				/* grab ALIGNed char **gr_mem from buf */
    223       1.49     lukem 	ep = _gr_memfrombuf(memc * sizeof(char *) + ALIGNBYTES, &buf, &buflen);
    224       1.49     lukem 	grp->gr_mem = (char **)ALIGN(ep);
    225       1.49     lukem 	if (grp->gr_mem == NULL)
    226       1.49     lukem 		return 0;
    227        1.2   deraadt 
    228       1.49     lukem 	for (memc = 0; *entry != '\0'; memc++) {
    229       1.49     lukem 		count = strcspn(entry, ",");	/* parse member */
    230       1.49     lukem 		COPYTOBUF(grp->gr_mem[memc]);
    231       1.49     lukem 		entry += count;
    232       1.49     lukem 		if (*entry == ',')
    233       1.49     lukem 			entry++;
    234       1.49     lukem 	}
    235       1.34     lukem 
    236       1.49     lukem #undef COPYTOBUF
    237       1.41     lukem 
    238       1.49     lukem 	grp->gr_mem[memc] = NULL;
    239       1.49     lukem 	return 1;
    240       1.45     elric }
    241       1.45     elric 
    242       1.45     elric /*
    243       1.49     lukem  * _gr_copy
    244       1.49     lukem  *	Copy the contents of fromgrp to grp; memory for strings
    245       1.49     lukem  *	and arrays will be allocated from buf (of size buflen).
    246       1.49     lukem  *	Returns 1 if copied successfully, 0 on copy failure.
    247       1.49     lukem  *	NOTE: fromgrp must not use buf for its own pointers.
    248       1.45     elric  */
    249       1.49     lukem static int
    250       1.49     lukem _gr_copy(struct group *fromgrp, struct group *grp, char *buf, size_t buflen)
    251       1.49     lukem {
    252       1.49     lukem 	char	*ep;
    253       1.49     lukem 	int	memc;
    254       1.49     lukem 
    255       1.49     lukem 	_DIAGASSERT(fromgrp != NULL);
    256       1.49     lukem 	_DIAGASSERT(grp != NULL);
    257       1.49     lukem 	_DIAGASSERT(buf != NULL);
    258       1.49     lukem 
    259       1.49     lukem #define COPYSTR(to, from) \
    260       1.49     lukem 	do { \
    261       1.49     lukem 		size_t count = strlen((from)); \
    262       1.49     lukem 		(to) = _gr_memfrombuf(count+1, &buf, &buflen); \
    263       1.49     lukem 		if ((to) == NULL) \
    264       1.49     lukem 			return 0; \
    265       1.49     lukem 		memmove((to), (from), count); \
    266       1.49     lukem 		to[count] = '\0'; \
    267       1.49     lukem 	} while (0)	/* LINTED */
    268       1.49     lukem 
    269       1.49     lukem 	COPYSTR(grp->gr_name, fromgrp->gr_name);
    270       1.49     lukem 	COPYSTR(grp->gr_passwd, fromgrp->gr_passwd);
    271       1.49     lukem 	grp->gr_gid = fromgrp->gr_gid;
    272       1.49     lukem 
    273       1.49     lukem 	for (memc = 0; fromgrp->gr_mem[memc]; memc++)
    274       1.49     lukem 		continue;
    275       1.49     lukem 	memc++;					/* for final NULL */
    276       1.49     lukem 
    277       1.49     lukem 				/* grab ALIGNed char **gr_mem from buf */
    278       1.49     lukem 	ep = _gr_memfrombuf(memc * sizeof(char *) + ALIGNBYTES, &buf, &buflen);
    279       1.49     lukem 	grp->gr_mem = (char **)ALIGN(ep);
    280       1.49     lukem 	if (grp->gr_mem == NULL)
    281       1.49     lukem 		return 0;
    282       1.49     lukem 
    283       1.49     lukem 	for (memc = 0; fromgrp->gr_mem[memc]; memc++) {
    284       1.49     lukem 		COPYSTR(grp->gr_mem[memc], fromgrp->gr_mem[memc]);
    285       1.49     lukem 	}
    286       1.49     lukem 
    287       1.49     lukem #undef COPYSTR
    288       1.45     elric 
    289       1.49     lukem 	grp->gr_mem[memc] = NULL;
    290       1.49     lukem 	return 1;
    291       1.49     lukem }
    292       1.49     lukem 
    293       1.49     lukem 		/*
    294       1.49     lukem 		 *	files methods
    295       1.49     lukem 		 */
    296       1.49     lukem 
    297       1.54     lukem int
    298       1.54     lukem __grstart_files(struct __grstate_files *state)
    299       1.45     elric {
    300       1.45     elric 
    301       1.49     lukem 	_DIAGASSERT(state != NULL);
    302       1.49     lukem 
    303       1.49     lukem 	if (state->fp == NULL) {
    304       1.49     lukem 		state->fp = fopen(_PATH_GROUP, "r");
    305       1.49     lukem 		if (state->fp == NULL)
    306       1.49     lukem 			return NS_UNAVAIL;
    307       1.49     lukem 	} else {
    308       1.49     lukem 		rewind(state->fp);
    309       1.49     lukem 	}
    310       1.49     lukem 	return NS_SUCCESS;
    311        1.1       cgd }
    312        1.1       cgd 
    313       1.54     lukem int
    314       1.54     lukem __grend_files(struct __grstate_files *state)
    315        1.1       cgd {
    316        1.1       cgd 
    317       1.49     lukem 	_DIAGASSERT(state != NULL);
    318       1.37     lukem 
    319       1.49     lukem 	if (state->fp) {
    320       1.49     lukem 		(void) fclose(state->fp);
    321       1.49     lukem 		state->fp = NULL;
    322       1.49     lukem 	}
    323       1.49     lukem 	return NS_SUCCESS;
    324        1.1       cgd }
    325        1.1       cgd 
    326       1.49     lukem /*
    327       1.54     lukem  * __grscan_files
    328       1.49     lukem  *	Scan state->fp for the next desired entry.
    329       1.49     lukem  *	If search is zero, return the next entry.
    330       1.49     lukem  *	If search is non-zero, look for a specific name (if name != NULL),
    331       1.49     lukem  *	or a specific gid (if name == NULL).
    332       1.57     lukem  *	Sets *retval to the errno if the result is not NS_SUCCESS
    333       1.57     lukem  *	or NS_NOTFOUND.
    334       1.49     lukem  */
    335       1.54     lukem int
    336       1.54     lukem __grscan_files(int *retval, struct group *grp, char *buffer, size_t buflen,
    337       1.54     lukem 	struct __grstate_files *state, int search, const char *name, gid_t gid)
    338        1.1       cgd {
    339       1.49     lukem 	int	rv;
    340       1.52     lukem 	char	filebuf[_GETGR_R_SIZE_MAX], *ep;
    341       1.49     lukem 
    342       1.49     lukem 	_DIAGASSERT(retval != NULL);
    343       1.49     lukem 	_DIAGASSERT(grp != NULL);
    344       1.49     lukem 	_DIAGASSERT(buffer != NULL);
    345       1.49     lukem 	_DIAGASSERT(state != NULL);
    346       1.49     lukem 	/* name is NULL to indicate searching for gid */
    347       1.49     lukem 
    348       1.49     lukem 	*retval = 0;
    349       1.49     lukem 
    350       1.49     lukem 	if (state->fp == NULL) {	/* only start if file not open yet */
    351       1.54     lukem 		rv = __grstart_files(state);
    352       1.49     lukem 		if (rv != NS_SUCCESS)
    353       1.49     lukem 			goto filesgrscan_out;
    354       1.49     lukem 	}
    355       1.49     lukem 
    356       1.49     lukem 	rv = NS_NOTFOUND;
    357       1.49     lukem 
    358       1.49     lukem 							/* scan line by line */
    359       1.49     lukem 	while (fgets(filebuf, sizeof(filebuf), state->fp) != NULL) {
    360       1.49     lukem 		ep = strchr(filebuf, '\n');
    361       1.58     lukem 		if (ep == NULL) {	/* skip lines that are too big */
    362       1.49     lukem 			int ch;
    363       1.49     lukem 
    364       1.49     lukem 			while ((ch = getc(state->fp)) != '\n' && ch != EOF)
    365       1.49     lukem 				continue;
    366       1.58     lukem 			continue;
    367       1.49     lukem 		}
    368       1.49     lukem 		*ep = '\0';				/* clear trailing \n */
    369       1.49     lukem 
    370       1.49     lukem 		if (filebuf[0] == '+')			/* skip compat line */
    371       1.49     lukem 			continue;
    372       1.49     lukem 
    373       1.49     lukem 							/* validate line */
    374       1.49     lukem 		if (! _gr_parse(filebuf, grp, buffer, buflen)) {
    375       1.58     lukem 			continue;			/* skip bad lines */
    376       1.49     lukem 		}
    377       1.49     lukem 		if (! search) {				/* just want this one */
    378       1.49     lukem 			rv = NS_SUCCESS;
    379       1.49     lukem 			break;
    380       1.49     lukem 		}
    381       1.49     lukem 							/* want specific */
    382       1.49     lukem 		if ((name && strcmp(name, grp->gr_name) == 0) ||
    383       1.49     lukem 		    (!name && gid == grp->gr_gid)) {
    384       1.49     lukem 			rv = NS_SUCCESS;
    385       1.49     lukem 			break;
    386       1.49     lukem 		}
    387       1.49     lukem 	}
    388        1.1       cgd 
    389       1.49     lukem  filesgrscan_out:
    390       1.57     lukem 	if (rv != NS_SUCCESS && rv != NS_NOTFOUND)
    391       1.49     lukem 		*retval = errno;
    392       1.49     lukem 	return rv;
    393        1.1       cgd }
    394        1.1       cgd 
    395       1.54     lukem 
    396       1.54     lukem static struct __grstate_files	_files_state;
    397       1.54     lukem 					/* storage for non _r functions */
    398       1.54     lukem static struct group		_files_group;
    399       1.54     lukem static char			_files_groupbuf[_GETGR_R_SIZE_MAX];
    400       1.54     lukem 
    401       1.49     lukem /*ARGSUSED*/
    402       1.49     lukem static int
    403       1.49     lukem _files_setgrent(void *nsrv, void *nscb, va_list ap)
    404        1.1       cgd {
    405       1.41     lukem 
    406       1.49     lukem 	_files_state.stayopen = 0;
    407       1.54     lukem 	return __grstart_files(&_files_state);
    408       1.36     lukem }
    409       1.36     lukem 
    410       1.49     lukem /*ARGSUSED*/
    411       1.36     lukem static int
    412       1.49     lukem _files_setgroupent(void *nsrv, void *nscb, va_list ap)
    413       1.36     lukem {
    414       1.49     lukem 	int	*retval		= va_arg(ap, int *);
    415       1.49     lukem 	int	 stayopen	= va_arg(ap, int);
    416       1.41     lukem 
    417       1.49     lukem 	int	rv;
    418       1.49     lukem 
    419       1.49     lukem 	_files_state.stayopen = stayopen;
    420       1.54     lukem 	rv = __grstart_files(&_files_state);
    421       1.49     lukem 	*retval = (rv == NS_SUCCESS);
    422       1.49     lukem 	return rv;
    423        1.1       cgd }
    424        1.1       cgd 
    425       1.49     lukem /*ARGSUSED*/
    426       1.49     lukem static int
    427       1.49     lukem _files_endgrent(void *nsrv, void *nscb, va_list ap)
    428        1.1       cgd {
    429       1.41     lukem 
    430       1.49     lukem 	_files_state.stayopen = 0;
    431       1.54     lukem 	return __grend_files(&_files_state);
    432        1.1       cgd }
    433        1.1       cgd 
    434       1.49     lukem /*ARGSUSED*/
    435       1.49     lukem static int
    436       1.49     lukem _files_getgrent(void *nsrv, void *nscb, va_list ap)
    437        1.1       cgd {
    438       1.49     lukem 	struct group	**retval = va_arg(ap, struct group **);
    439       1.49     lukem 
    440       1.49     lukem 	int	rv, rerror;
    441       1.49     lukem 
    442       1.49     lukem 	_DIAGASSERT(retval != NULL);
    443       1.41     lukem 
    444       1.49     lukem 	*retval = NULL;
    445       1.54     lukem 	rv = __grscan_files(&rerror, &_files_group,
    446       1.49     lukem 	    _files_groupbuf, sizeof(_files_groupbuf),
    447       1.49     lukem 	    &_files_state, 0, NULL, 0);
    448       1.49     lukem 	if (rv == NS_SUCCESS)
    449       1.49     lukem 		*retval = &_files_group;
    450       1.49     lukem 	return rv;
    451        1.1       cgd }
    452        1.1       cgd 
    453       1.49     lukem /*ARGSUSED*/
    454       1.49     lukem static int
    455       1.56  christos _files_getgrent_r(void *nsrv, void *nscb, va_list ap)
    456       1.56  christos {
    457       1.56  christos 	int		*retval	= va_arg(ap, int *);
    458       1.56  christos 	struct group	*grp	= va_arg(ap, struct group *);
    459       1.56  christos 	char		*buffer	= va_arg(ap, char *);
    460       1.56  christos 	size_t		 buflen	= va_arg(ap, size_t);
    461       1.56  christos 	struct group   **result	= va_arg(ap, struct group **);
    462       1.56  christos 
    463       1.56  christos 	int	rv;
    464       1.56  christos 
    465       1.56  christos 	_DIAGASSERT(retval != NULL);
    466       1.56  christos 	_DIAGASSERT(grp != NULL);
    467       1.56  christos 	_DIAGASSERT(buffer != NULL);
    468       1.56  christos 	_DIAGASSERT(result != NULL);
    469       1.56  christos 
    470       1.56  christos 	rv = __grscan_files(retval, grp, buffer, buflen,
    471       1.56  christos 	    &_files_state, 0, NULL, 0);
    472       1.56  christos 	if (rv == NS_SUCCESS)
    473       1.56  christos 		*result = grp;
    474       1.56  christos 	else
    475       1.56  christos 		*result = NULL;
    476       1.56  christos 	return rv;
    477       1.56  christos }
    478       1.56  christos 
    479       1.56  christos /*ARGSUSED*/
    480       1.56  christos static int
    481       1.49     lukem _files_getgrgid(void *nsrv, void *nscb, va_list ap)
    482        1.1       cgd {
    483       1.49     lukem 	struct group	**retval = va_arg(ap, struct group **);
    484       1.49     lukem 	gid_t		 gid	= va_arg(ap, gid_t);
    485       1.49     lukem 
    486       1.49     lukem 	int	rv, rerror;
    487       1.49     lukem 
    488       1.49     lukem 	_DIAGASSERT(retval != NULL);
    489       1.41     lukem 
    490       1.49     lukem 	*retval = NULL;
    491       1.54     lukem 	rv = __grstart_files(&_files_state);
    492       1.49     lukem 	if (rv != NS_SUCCESS)
    493       1.49     lukem 		return rv;
    494       1.54     lukem 	rv = __grscan_files(&rerror, &_files_group,
    495       1.49     lukem 	    _files_groupbuf, sizeof(_files_groupbuf),
    496       1.49     lukem 	    &_files_state, 1, NULL, gid);
    497       1.49     lukem 	if (!_files_state.stayopen)
    498       1.54     lukem 		__grend_files(&_files_state);
    499       1.49     lukem 	if (rv == NS_SUCCESS)
    500       1.49     lukem 		*retval = &_files_group;
    501       1.49     lukem 	return rv;
    502        1.1       cgd }
    503        1.1       cgd 
    504       1.49     lukem /*ARGSUSED*/
    505       1.49     lukem static int
    506       1.49     lukem _files_getgrgid_r(void *nsrv, void *nscb, va_list ap)
    507       1.49     lukem {
    508       1.49     lukem 	int		*retval	= va_arg(ap, int *);
    509       1.49     lukem 	gid_t		 gid	= va_arg(ap, gid_t);
    510       1.49     lukem 	struct group	*grp	= va_arg(ap, struct group *);
    511       1.49     lukem 	char		*buffer	= va_arg(ap, char *);
    512       1.49     lukem 	size_t		 buflen	= va_arg(ap, size_t);
    513       1.49     lukem 	struct group   **result	= va_arg(ap, struct group **);
    514       1.49     lukem 
    515       1.54     lukem 	struct __grstate_files state;
    516       1.49     lukem 	int	rv;
    517       1.49     lukem 
    518       1.49     lukem 	_DIAGASSERT(retval != NULL);
    519       1.49     lukem 	_DIAGASSERT(grp != NULL);
    520       1.49     lukem 	_DIAGASSERT(buffer != NULL);
    521       1.49     lukem 	_DIAGASSERT(result != NULL);
    522       1.49     lukem 
    523       1.49     lukem 	*result = NULL;
    524       1.49     lukem 	memset(&state, 0, sizeof(state));
    525       1.54     lukem 	rv = __grscan_files(retval, grp, buffer, buflen, &state, 1, NULL, gid);
    526       1.54     lukem 	__grend_files(&state);
    527       1.49     lukem 	if (rv == NS_SUCCESS)
    528       1.49     lukem 		*result = grp;
    529       1.49     lukem 	return rv;
    530       1.49     lukem }
    531       1.27     lukem 
    532       1.29  christos /*ARGSUSED*/
    533       1.27     lukem static int
    534       1.49     lukem _files_getgrnam(void *nsrv, void *nscb, va_list ap)
    535       1.27     lukem {
    536       1.49     lukem 	struct group	**retval = va_arg(ap, struct group **);
    537       1.49     lukem 	const char	*name	= va_arg(ap, const char *);
    538       1.49     lukem 
    539       1.49     lukem 	int	rv, rerror;
    540       1.49     lukem 
    541       1.49     lukem 	_DIAGASSERT(retval != NULL);
    542       1.27     lukem 
    543       1.49     lukem 	*retval = NULL;
    544       1.54     lukem 	rv = __grstart_files(&_files_state);
    545       1.49     lukem 	if (rv != NS_SUCCESS)
    546       1.49     lukem 		return rv;
    547       1.54     lukem 	rv = __grscan_files(&rerror, &_files_group,
    548       1.49     lukem 	    _files_groupbuf, sizeof(_files_groupbuf),
    549       1.49     lukem 	    &_files_state, 1, name, 0);
    550       1.49     lukem 	if (!_files_state.stayopen)
    551       1.54     lukem 		__grend_files(&_files_state);
    552       1.49     lukem 	if (rv == NS_SUCCESS)
    553       1.49     lukem 		*retval = &_files_group;
    554       1.49     lukem 	return rv;
    555       1.49     lukem }
    556       1.27     lukem 
    557       1.49     lukem /*ARGSUSED*/
    558       1.49     lukem static int
    559       1.49     lukem _files_getgrnam_r(void *nsrv, void *nscb, va_list ap)
    560       1.49     lukem {
    561       1.49     lukem 	int		*retval	= va_arg(ap, int *);
    562       1.49     lukem 	const char	*name	= va_arg(ap, const char *);
    563       1.49     lukem 	struct group	*grp	= va_arg(ap, struct group *);
    564       1.49     lukem 	char		*buffer	= va_arg(ap, char *);
    565       1.49     lukem 	size_t		 buflen	= va_arg(ap, size_t);
    566       1.49     lukem 	struct group   **result	= va_arg(ap, struct group **);
    567       1.49     lukem 
    568       1.54     lukem 	struct __grstate_files state;
    569       1.49     lukem 	int	rv;
    570       1.49     lukem 
    571       1.49     lukem 	_DIAGASSERT(retval != NULL);
    572       1.49     lukem 	_DIAGASSERT(grp != NULL);
    573       1.49     lukem 	_DIAGASSERT(buffer != NULL);
    574       1.49     lukem 	_DIAGASSERT(result != NULL);
    575       1.49     lukem 
    576       1.49     lukem 	*result = NULL;
    577       1.49     lukem 	memset(&state, 0, sizeof(state));
    578       1.54     lukem 	rv = __grscan_files(retval, grp, buffer, buflen, &state, 1, name, 0);
    579       1.54     lukem 	__grend_files(&state);
    580       1.49     lukem 	if (rv == NS_SUCCESS)
    581       1.49     lukem 		*result = grp;
    582       1.49     lukem 	return rv;
    583       1.27     lukem }
    584       1.27     lukem 
    585       1.49     lukem 
    586       1.27     lukem #ifdef HESIOD
    587       1.49     lukem 		/*
    588       1.49     lukem 		 *	dns methods
    589       1.49     lukem 		 */
    590       1.49     lukem 
    591       1.54     lukem int
    592       1.54     lukem __grstart_dns(struct __grstate_dns *state)
    593        1.1       cgd {
    594        1.1       cgd 
    595       1.49     lukem 	_DIAGASSERT(state != NULL);
    596       1.27     lukem 
    597       1.49     lukem 	state->num = 0;
    598       1.49     lukem 	if (state->context == NULL) {			/* setup Hesiod */
    599       1.49     lukem 		if (hesiod_init(&state->context) == -1)
    600       1.49     lukem 			return NS_UNAVAIL;
    601       1.27     lukem 	}
    602       1.49     lukem 
    603       1.49     lukem 	return NS_SUCCESS;
    604       1.27     lukem }
    605       1.45     elric 
    606       1.54     lukem int
    607       1.54     lukem __grend_dns(struct __grstate_dns *state)
    608       1.45     elric {
    609       1.45     elric 
    610       1.49     lukem 	_DIAGASSERT(state != NULL);
    611       1.45     elric 
    612       1.49     lukem 	state->num = 0;
    613       1.49     lukem 	if (state->context) {
    614       1.49     lukem 		hesiod_end(state->context);
    615       1.49     lukem 		state->context = NULL;
    616       1.49     lukem 	}
    617       1.49     lukem 	return NS_SUCCESS;
    618       1.49     lukem }
    619       1.45     elric 
    620       1.49     lukem /*
    621       1.54     lukem  * __grscan_dns
    622       1.54     lukem  *	Search Hesiod for the next desired entry.
    623       1.54     lukem  *	If search is zero, return the next entry.
    624       1.54     lukem  *	If search is non-zero, look for a specific name (if name != NULL),
    625       1.54     lukem  *	or a specific gid (if name == NULL).
    626       1.49     lukem  */
    627       1.54     lukem int
    628       1.54     lukem __grscan_dns(int *retval, struct group *grp, char *buffer, size_t buflen,
    629       1.54     lukem 	struct __grstate_dns *state, int search, const char *name, gid_t gid)
    630       1.49     lukem {
    631       1.49     lukem 	const char	**curzone;
    632       1.49     lukem 	char		**hp, *ep;
    633       1.49     lukem 	int		rv;
    634       1.49     lukem 
    635       1.54     lukem 	static const char *zones_gid_group[] = {
    636       1.54     lukem 		"gid",
    637       1.54     lukem 		"group",
    638       1.54     lukem 		NULL
    639       1.54     lukem 	};
    640       1.54     lukem 
    641       1.54     lukem 	static const char *zones_group[] = {
    642       1.54     lukem 		"group",
    643       1.54     lukem 		NULL
    644       1.54     lukem 	};
    645       1.54     lukem 
    646       1.49     lukem 	_DIAGASSERT(retval != NULL);
    647       1.49     lukem 	_DIAGASSERT(grp != NULL);
    648       1.49     lukem 	_DIAGASSERT(buffer != NULL);
    649       1.49     lukem 	_DIAGASSERT(state != NULL);
    650       1.54     lukem 	/* name is NULL to indicate searching for gid */
    651       1.49     lukem 
    652       1.49     lukem 	*retval = 0;
    653       1.49     lukem 
    654       1.49     lukem 	if (state->context == NULL) {	/* only start if Hesiod not setup */
    655       1.54     lukem 		rv = __grstart_dns(state);
    656       1.49     lukem 		if (rv != NS_SUCCESS)
    657       1.49     lukem 			return rv;
    658       1.49     lukem 	}
    659       1.45     elric 
    660       1.58     lukem  next_dns_entry:
    661       1.49     lukem 	hp = NULL;
    662       1.49     lukem 	rv = NS_NOTFOUND;
    663       1.45     elric 
    664       1.54     lukem 	if (! search) {			/* find next entry */
    665       1.54     lukem 		if (state->num == -1)		/* exhausted search */
    666       1.54     lukem 			return NS_NOTFOUND;
    667       1.54     lukem 						/* find group-NNN */
    668       1.54     lukem 		snprintf(buffer, buflen, "group-%u", state->num);
    669       1.54     lukem 		state->num++;
    670       1.54     lukem 		curzone = zones_group;
    671       1.54     lukem 	} else if (name) {		/* find group name */
    672       1.54     lukem 		snprintf(buffer, buflen, "%s", name);
    673       1.54     lukem 		curzone = zones_group;
    674       1.54     lukem 	} else {			/* find gid */
    675       1.54     lukem 		snprintf(buffer, buflen, "%u", (unsigned int)gid);
    676       1.54     lukem 		curzone = zones_gid_group;
    677       1.54     lukem 	}
    678       1.54     lukem 
    679       1.54     lukem 	for (; *curzone; curzone++) {		/* search zones */
    680       1.49     lukem 		hp = hesiod_resolve(state->context, buffer, *curzone);
    681       1.49     lukem 		if (hp != NULL)
    682       1.49     lukem 			break;
    683       1.49     lukem 		if (errno != ENOENT) {
    684       1.49     lukem 			rv = NS_UNAVAIL;
    685       1.49     lukem 			goto dnsgrscan_out;
    686       1.45     elric 		}
    687       1.49     lukem 	}
    688       1.54     lukem 	if (*curzone == NULL) {
    689       1.54     lukem 		if (! search)
    690       1.54     lukem 			state->num = -1;
    691       1.49     lukem 		goto dnsgrscan_out;
    692       1.54     lukem 	}
    693       1.45     elric 
    694       1.49     lukem 	if ((ep = strchr(hp[0], '\n')) != NULL)
    695       1.49     lukem 		*ep = '\0';				/* clear trailing \n */
    696       1.54     lukem 	if (_gr_parse(hp[0], grp, buffer, buflen)) {	/* validate line */
    697       1.54     lukem 		if (! search) {				/* just want this one */
    698       1.54     lukem 			rv = NS_SUCCESS;
    699       1.54     lukem 		} else if ((name && strcmp(name, grp->gr_name) == 0) ||
    700       1.54     lukem 		    (!name && gid == grp->gr_gid)) {	/* want specific */
    701       1.54     lukem 			rv = NS_SUCCESS;
    702       1.54     lukem 		}
    703       1.58     lukem 	} else {					/* dodgy entry */
    704       1.58     lukem 		if (!search) {			/* try again if ! searching */
    705       1.58     lukem 			hesiod_free_list(state->context, hp);
    706       1.58     lukem 			goto next_dns_entry;
    707       1.58     lukem 		}
    708       1.58     lukem 	}
    709       1.49     lukem 
    710       1.49     lukem  dnsgrscan_out:
    711       1.57     lukem 	if (rv != NS_SUCCESS && rv != NS_NOTFOUND)
    712       1.49     lukem 		*retval = errno;
    713       1.49     lukem 	if (hp)
    714       1.49     lukem 		hesiod_free_list(state->context, hp);
    715       1.49     lukem 	return rv;
    716       1.49     lukem }
    717       1.45     elric 
    718       1.54     lukem static struct __grstate_dns	_dns_state;
    719       1.54     lukem 					/* storage for non _r functions */
    720       1.54     lukem static struct group		_dns_group;
    721       1.54     lukem static char			_dns_groupbuf[_GETGR_R_SIZE_MAX];
    722       1.54     lukem 
    723       1.49     lukem /*ARGSUSED*/
    724       1.49     lukem static int
    725       1.49     lukem _dns_setgrent(void *nsrv, void *nscb, va_list ap)
    726       1.49     lukem {
    727       1.45     elric 
    728       1.49     lukem 	_dns_state.stayopen = 0;
    729       1.54     lukem 	return __grstart_dns(&_dns_state);
    730       1.49     lukem }
    731       1.45     elric 
    732       1.49     lukem /*ARGSUSED*/
    733       1.49     lukem static int
    734       1.49     lukem _dns_setgroupent(void *nsrv, void *nscb, va_list ap)
    735       1.49     lukem {
    736       1.49     lukem 	int	*retval		= va_arg(ap, int *);
    737       1.49     lukem 	int	 stayopen	= va_arg(ap, int);
    738       1.45     elric 
    739       1.49     lukem 	int	rv;
    740       1.45     elric 
    741       1.49     lukem 	_dns_state.stayopen = stayopen;
    742       1.54     lukem 	rv = __grstart_dns(&_dns_state);
    743       1.49     lukem 	*retval = (rv == NS_SUCCESS);
    744       1.49     lukem 	return rv;
    745       1.45     elric }
    746       1.27     lukem 
    747       1.49     lukem /*ARGSUSED*/
    748       1.49     lukem static int
    749       1.49     lukem _dns_endgrent(void *nsrv, void *nscb, va_list ap)
    750       1.49     lukem {
    751       1.49     lukem 
    752       1.49     lukem 	_dns_state.stayopen = 0;
    753       1.54     lukem 	return __grend_dns(&_dns_state);
    754       1.49     lukem }
    755       1.27     lukem 
    756       1.29  christos /*ARGSUSED*/
    757       1.27     lukem static int
    758       1.49     lukem _dns_getgrent(void *nsrv, void *nscb, va_list ap)
    759       1.27     lukem {
    760       1.49     lukem 	struct group	**retval = va_arg(ap, struct group **);
    761       1.49     lukem 
    762       1.54     lukem 	int	  rv, rerror;
    763       1.49     lukem 
    764       1.49     lukem 	_DIAGASSERT(retval != NULL);
    765       1.27     lukem 
    766       1.49     lukem 	*retval = NULL;
    767       1.54     lukem 	rv = __grscan_dns(&rerror, &_dns_group,
    768       1.54     lukem 	    _dns_groupbuf, sizeof(_dns_groupbuf), &_dns_state, 0, NULL, 0);
    769       1.49     lukem 	if (rv == NS_SUCCESS)
    770       1.49     lukem 		*retval = &_dns_group;
    771       1.49     lukem 	return rv;
    772       1.27     lukem }
    773       1.27     lukem 
    774       1.29  christos /*ARGSUSED*/
    775       1.27     lukem static int
    776       1.56  christos _dns_getgrent_r(void *nsrv, void *nscb, va_list ap)
    777       1.56  christos {
    778       1.56  christos 	int		*retval	= va_arg(ap, int *);
    779       1.56  christos 	struct group	*grp	= va_arg(ap, struct group *);
    780       1.56  christos 	char		*buffer	= va_arg(ap, char *);
    781       1.56  christos 	size_t		 buflen	= va_arg(ap, size_t);
    782       1.56  christos 	struct group   **result	= va_arg(ap, struct group **);
    783       1.56  christos 
    784       1.56  christos 	int	rv;
    785       1.56  christos 
    786       1.56  christos 	_DIAGASSERT(retval != NULL);
    787       1.56  christos 	_DIAGASSERT(grp != NULL);
    788       1.56  christos 	_DIAGASSERT(buffer != NULL);
    789       1.56  christos 	_DIAGASSERT(result != NULL);
    790       1.56  christos 
    791       1.56  christos 	rv = __grscan_dns(retval, grp, buffer, buflen,
    792       1.56  christos 	    &_dns_state, 0, NULL, 0);
    793       1.56  christos 	if (rv == NS_SUCCESS)
    794       1.56  christos 		*result = grp;
    795       1.56  christos 	else
    796       1.56  christos 		*result = NULL;
    797       1.56  christos 	return rv;
    798       1.56  christos }
    799       1.56  christos /*ARGSUSED*/
    800       1.56  christos static int
    801       1.49     lukem _dns_getgrgid(void *nsrv, void *nscb, va_list ap)
    802       1.27     lukem {
    803       1.49     lukem 	struct group	**retval = va_arg(ap, struct group **);
    804       1.49     lukem 	gid_t		 gid	= va_arg(ap, gid_t);
    805       1.49     lukem 
    806       1.49     lukem 	int	rv, rerror;
    807       1.27     lukem 
    808       1.49     lukem 	_DIAGASSERT(retval != NULL);
    809       1.37     lukem 
    810       1.49     lukem 	*retval = NULL;
    811       1.54     lukem 	rv = __grstart_dns(&_dns_state);
    812       1.49     lukem 	if (rv != NS_SUCCESS)
    813       1.49     lukem 		return rv;
    814       1.54     lukem 	rv = __grscan_dns(&rerror, &_dns_group,
    815       1.54     lukem 	    _dns_groupbuf, sizeof(_dns_groupbuf), &_dns_state, 1, NULL, gid);
    816       1.49     lukem 	if (!_dns_state.stayopen)
    817       1.54     lukem 		__grend_dns(&_dns_state);
    818       1.54     lukem 	if (rv == NS_SUCCESS)
    819       1.49     lukem 		*retval = &_dns_group;
    820       1.49     lukem 	return rv;
    821       1.27     lukem }
    822       1.27     lukem 
    823       1.49     lukem /*ARGSUSED*/
    824       1.49     lukem static int
    825       1.49     lukem _dns_getgrgid_r(void *nsrv, void *nscb, va_list ap)
    826       1.49     lukem {
    827       1.49     lukem 	int		*retval	= va_arg(ap, int *);
    828       1.49     lukem 	gid_t		 gid	= va_arg(ap, gid_t);
    829       1.49     lukem 	struct group	*grp	= va_arg(ap, struct group *);
    830       1.49     lukem 	char		*buffer	= va_arg(ap, char *);
    831       1.49     lukem 	size_t		 buflen	= va_arg(ap, size_t);
    832       1.49     lukem 	struct group   **result	= va_arg(ap, struct group **);
    833       1.49     lukem 
    834       1.54     lukem 	struct __grstate_dns state;
    835       1.49     lukem 	int	rv;
    836       1.49     lukem 
    837       1.49     lukem 	_DIAGASSERT(retval != NULL);
    838       1.49     lukem 	_DIAGASSERT(grp != NULL);
    839       1.49     lukem 	_DIAGASSERT(buffer != NULL);
    840       1.49     lukem 	_DIAGASSERT(result != NULL);
    841       1.49     lukem 
    842       1.49     lukem 	*result = NULL;
    843       1.49     lukem 	memset(&state, 0, sizeof(state));
    844       1.54     lukem 	rv = __grscan_dns(retval, grp, buffer, buflen, &state, 1, NULL, gid);
    845       1.54     lukem 	__grend_dns(&state);
    846       1.54     lukem 	if (rv == NS_SUCCESS)
    847       1.49     lukem 		*result = grp;
    848       1.54     lukem 	return rv;
    849       1.49     lukem }
    850       1.27     lukem 
    851       1.49     lukem /*ARGSUSED*/
    852       1.27     lukem static int
    853       1.49     lukem _dns_getgrnam(void *nsrv, void *nscb, va_list ap)
    854       1.27     lukem {
    855       1.49     lukem 	struct group	**retval = va_arg(ap, struct group **);
    856       1.49     lukem 	const char	*name	= va_arg(ap, const char *);
    857       1.49     lukem 
    858       1.49     lukem 	int	rv, rerror;
    859       1.27     lukem 
    860       1.49     lukem 	_DIAGASSERT(retval != NULL);
    861       1.37     lukem 
    862       1.49     lukem 	*retval = NULL;
    863       1.54     lukem 	rv = __grstart_dns(&_dns_state);
    864       1.49     lukem 	if (rv != NS_SUCCESS)
    865       1.49     lukem 		return rv;
    866       1.54     lukem 	rv = __grscan_dns(&rerror, &_dns_group,
    867       1.54     lukem 	    _dns_groupbuf, sizeof(_dns_groupbuf), &_dns_state, 1, name, 0);
    868       1.49     lukem 	if (!_dns_state.stayopen)
    869       1.54     lukem 		__grend_dns(&_dns_state);
    870       1.54     lukem 	if (rv == NS_SUCCESS)
    871       1.49     lukem 		*retval = &_dns_group;
    872       1.49     lukem 	return rv;
    873       1.27     lukem }
    874       1.27     lukem 
    875       1.29  christos /*ARGSUSED*/
    876       1.27     lukem static int
    877       1.49     lukem _dns_getgrnam_r(void *nsrv, void *nscb, va_list ap)
    878       1.27     lukem {
    879       1.49     lukem 	int		*retval	= va_arg(ap, int *);
    880       1.49     lukem 	const char	*name	= va_arg(ap, const char *);
    881       1.49     lukem 	struct group	*grp	= va_arg(ap, struct group *);
    882       1.49     lukem 	char		*buffer	= va_arg(ap, char *);
    883       1.49     lukem 	size_t		 buflen	= va_arg(ap, size_t);
    884       1.49     lukem 	struct group   **result	= va_arg(ap, struct group **);
    885       1.49     lukem 
    886       1.54     lukem 	struct __grstate_dns state;
    887       1.49     lukem 	int	rv;
    888       1.49     lukem 
    889       1.49     lukem 	_DIAGASSERT(retval != NULL);
    890       1.49     lukem 	_DIAGASSERT(grp != NULL);
    891       1.49     lukem 	_DIAGASSERT(buffer != NULL);
    892       1.49     lukem 	_DIAGASSERT(result != NULL);
    893       1.49     lukem 
    894       1.49     lukem 	*result = NULL;
    895       1.49     lukem 	memset(&state, 0, sizeof(state));
    896       1.54     lukem 	rv = __grscan_dns(retval, grp, buffer, buflen, &state, 1, name, 0);
    897       1.54     lukem 	__grend_dns(&state);
    898       1.54     lukem 	if (rv == NS_SUCCESS)
    899       1.49     lukem 		*result = grp;
    900       1.54     lukem 	return rv;
    901       1.49     lukem }
    902       1.49     lukem 
    903       1.49     lukem #endif /* HESIOD */
    904       1.49     lukem 
    905       1.49     lukem 
    906       1.49     lukem #ifdef YP
    907       1.49     lukem 		/*
    908       1.49     lukem 		 *	nis methods
    909       1.49     lukem 		 */
    910       1.49     lukem 
    911       1.54     lukem int
    912       1.54     lukem __grstart_nis(struct __grstate_nis *state)
    913       1.49     lukem {
    914       1.49     lukem 
    915       1.49     lukem 	_DIAGASSERT(state != NULL);
    916       1.49     lukem 
    917       1.49     lukem 	state->done = 0;
    918       1.49     lukem 	if (state->current) {
    919       1.49     lukem 		free(state->current);
    920       1.49     lukem 		state->current = NULL;
    921       1.49     lukem 	}
    922       1.49     lukem 	if (state->domain == NULL) {			/* setup NIS */
    923       1.49     lukem 		switch (yp_get_default_domain(&state->domain)) {
    924       1.49     lukem 		case 0:
    925       1.49     lukem 			break;
    926       1.49     lukem 		case YPERR_RESRC:
    927       1.49     lukem 			return NS_TRYAGAIN;
    928       1.49     lukem 		default:
    929       1.49     lukem 			return NS_UNAVAIL;
    930       1.49     lukem 		}
    931       1.49     lukem 	}
    932       1.49     lukem 	return NS_SUCCESS;
    933       1.49     lukem }
    934       1.49     lukem 
    935       1.54     lukem int
    936       1.54     lukem __grend_nis(struct __grstate_nis *state)
    937       1.49     lukem {
    938       1.49     lukem 
    939       1.49     lukem 	_DIAGASSERT(state != NULL);
    940       1.49     lukem 
    941       1.49     lukem 	if (state->domain) {
    942       1.49     lukem 		state->domain = NULL;
    943       1.49     lukem 	}
    944       1.49     lukem 	state->done = 0;
    945       1.49     lukem 	if (state->current) {
    946       1.49     lukem 		free(state->current);
    947       1.49     lukem 		state->current = NULL;
    948       1.49     lukem 	}
    949       1.49     lukem 	return NS_SUCCESS;
    950       1.49     lukem }
    951       1.49     lukem 
    952       1.49     lukem /*
    953       1.54     lukem  * __grscan_nis
    954       1.54     lukem  *	Search NIS for the next desired entry.
    955       1.54     lukem  *	If search is zero, return the next entry.
    956       1.54     lukem  *	If search is non-zero, look for a specific name (if name != NULL),
    957       1.54     lukem  *	or a specific gid (if name == NULL).
    958       1.49     lukem  */
    959       1.54     lukem int
    960       1.54     lukem __grscan_nis(int *retval, struct group *grp, char *buffer, size_t buflen,
    961       1.54     lukem 	struct __grstate_nis *state, int search, const char *name, gid_t gid)
    962       1.49     lukem {
    963       1.54     lukem 	const char *map;
    964       1.54     lukem 	char	*key, *data;
    965       1.54     lukem 	int	nisr, rv, keylen, datalen;
    966       1.49     lukem 
    967       1.49     lukem 	_DIAGASSERT(retval != NULL);
    968       1.49     lukem 	_DIAGASSERT(grp != NULL);
    969       1.49     lukem 	_DIAGASSERT(buffer != NULL);
    970       1.49     lukem 	_DIAGASSERT(state != NULL);
    971       1.54     lukem 	/* name is NULL to indicate searching for gid */
    972       1.49     lukem 
    973       1.49     lukem 	*retval = 0;
    974       1.49     lukem 
    975       1.49     lukem 	if (state->domain == NULL) {	/* only start if NIS not setup */
    976       1.54     lukem 		rv = __grstart_nis(state);
    977       1.49     lukem 		if (rv != NS_SUCCESS)
    978       1.49     lukem 			return rv;
    979       1.49     lukem 	}
    980       1.49     lukem 
    981       1.58     lukem  next_nis_entry:
    982       1.54     lukem 	key = NULL;
    983       1.49     lukem 	data = NULL;
    984       1.54     lukem 	rv = NS_SUCCESS;
    985       1.49     lukem 
    986       1.54     lukem 	if (! search) 	{			/* find next entry */
    987       1.54     lukem 		if (state->done)			/* exhausted search */
    988       1.54     lukem 			return NS_NOTFOUND;
    989       1.54     lukem 		map = "group.byname";
    990       1.54     lukem 		if (state->current) {			/* already searching */
    991       1.54     lukem 			nisr = yp_next(state->domain, map,
    992       1.54     lukem 			    state->current, state->currentlen,
    993       1.54     lukem 			    &key, &keylen, &data, &datalen);
    994       1.54     lukem 			free(state->current);
    995       1.54     lukem 			state->current = NULL;
    996       1.54     lukem 			switch (nisr) {
    997       1.54     lukem 			case 0:
    998       1.54     lukem 				state->current = key;
    999       1.54     lukem 				state->currentlen = keylen;
   1000       1.54     lukem 				key = NULL;
   1001       1.54     lukem 				break;
   1002       1.54     lukem 			case YPERR_NOMORE:
   1003       1.54     lukem 				rv = NS_NOTFOUND;
   1004       1.54     lukem 				state->done = 1;
   1005       1.54     lukem 				break;
   1006       1.54     lukem 			default:
   1007       1.54     lukem 				rv = NS_UNAVAIL;
   1008       1.54     lukem 				break;
   1009       1.54     lukem 			}
   1010       1.54     lukem 		} else {				/* new search */
   1011       1.54     lukem 			if (yp_first(state->domain, map,
   1012       1.54     lukem 			    &state->current, &state->currentlen,
   1013       1.54     lukem 			    &data, &datalen)) {
   1014       1.54     lukem 				rv = NS_UNAVAIL;
   1015       1.54     lukem 			}
   1016       1.54     lukem 		}
   1017       1.54     lukem 	} else {				/* search for specific item */
   1018       1.54     lukem 		if (name) {			/* find group name */
   1019       1.54     lukem 			snprintf(buffer, buflen, "%s", name);
   1020       1.54     lukem 			map = "group.byname";
   1021       1.54     lukem 		} else {			/* find gid */
   1022       1.54     lukem 			snprintf(buffer, buflen, "%u", (unsigned int)gid);
   1023       1.54     lukem 			map = "group.bygid";
   1024       1.54     lukem 		}
   1025       1.54     lukem 		nisr = yp_match(state->domain, map, buffer, (int)strlen(buffer),
   1026       1.54     lukem 		    &data, &datalen);
   1027       1.54     lukem 		switch (nisr) {
   1028       1.54     lukem 		case 0:
   1029       1.54     lukem 			break;
   1030       1.54     lukem 		case YPERR_KEY:
   1031       1.54     lukem 			rv = NS_NOTFOUND;
   1032       1.54     lukem 			break;
   1033       1.54     lukem 		default:
   1034       1.54     lukem 			rv = NS_UNAVAIL;
   1035       1.54     lukem 			break;
   1036       1.54     lukem 		}
   1037       1.54     lukem 	}
   1038       1.54     lukem 	if (rv == NS_SUCCESS) {				/* validate data */
   1039       1.49     lukem 		data[datalen] = '\0';			/* clear trailing \n */
   1040       1.54     lukem 		if (_gr_parse(data, grp, buffer, buflen)) {
   1041       1.54     lukem 			if (! search) {			/* just want this one */
   1042       1.54     lukem 				rv = NS_SUCCESS;
   1043       1.54     lukem 			} else if ((name && strcmp(name, grp->gr_name) == 0) ||
   1044       1.54     lukem 			    (!name && gid == grp->gr_gid)) {
   1045       1.54     lukem 							/* want specific */
   1046       1.54     lukem 				rv = NS_SUCCESS;
   1047       1.54     lukem 			}
   1048       1.58     lukem 		} else {				/* dodgy entry */
   1049       1.58     lukem 			if (!search) {		/* try again if ! searching */
   1050       1.58     lukem 				free(data);
   1051       1.58     lukem 				goto next_nis_entry;
   1052       1.58     lukem 			}
   1053       1.58     lukem 		}
   1054       1.49     lukem 	}
   1055       1.49     lukem 
   1056       1.57     lukem 	if (rv != NS_SUCCESS && rv != NS_NOTFOUND)
   1057       1.49     lukem 		*retval = errno;
   1058       1.54     lukem 	if (key)
   1059       1.54     lukem 		free(key);
   1060       1.49     lukem 	if (data)
   1061       1.49     lukem 		free(data);
   1062       1.49     lukem 	return rv;
   1063       1.49     lukem }
   1064       1.49     lukem 
   1065       1.54     lukem static struct __grstate_nis	_nis_state;
   1066       1.54     lukem 					/* storage for non _r functions */
   1067       1.54     lukem static struct group		_nis_group;
   1068       1.54     lukem static char			_nis_groupbuf[_GETGR_R_SIZE_MAX];
   1069       1.54     lukem 
   1070       1.49     lukem /*ARGSUSED*/
   1071       1.49     lukem static int
   1072       1.49     lukem _nis_setgrent(void *nsrv, void *nscb, va_list ap)
   1073       1.49     lukem {
   1074       1.49     lukem 
   1075       1.49     lukem 	_nis_state.stayopen = 0;
   1076       1.54     lukem 	return __grstart_nis(&_nis_state);
   1077       1.49     lukem }
   1078       1.49     lukem 
   1079       1.49     lukem /*ARGSUSED*/
   1080       1.49     lukem static int
   1081       1.49     lukem _nis_setgroupent(void *nsrv, void *nscb, va_list ap)
   1082       1.49     lukem {
   1083       1.49     lukem 	int	*retval		= va_arg(ap, int *);
   1084       1.49     lukem 	int	 stayopen	= va_arg(ap, int);
   1085       1.49     lukem 
   1086       1.49     lukem 	int	rv;
   1087       1.49     lukem 
   1088       1.49     lukem 	_nis_state.stayopen = stayopen;
   1089       1.54     lukem 	rv = __grstart_nis(&_nis_state);
   1090       1.49     lukem 	*retval = (rv == NS_SUCCESS);
   1091       1.49     lukem 	return rv;
   1092       1.49     lukem }
   1093       1.49     lukem 
   1094       1.49     lukem /*ARGSUSED*/
   1095       1.49     lukem static int
   1096       1.49     lukem _nis_endgrent(void *nsrv, void *nscb, va_list ap)
   1097       1.49     lukem {
   1098       1.49     lukem 
   1099       1.54     lukem 	return __grend_nis(&_nis_state);
   1100       1.49     lukem }
   1101       1.49     lukem 
   1102       1.49     lukem /*ARGSUSED*/
   1103       1.49     lukem static int
   1104       1.49     lukem _nis_getgrent(void *nsrv, void *nscb, va_list ap)
   1105       1.49     lukem {
   1106       1.49     lukem 	struct group	**retval = va_arg(ap, struct group **);
   1107       1.49     lukem 
   1108       1.54     lukem 	int	rv, rerror;
   1109       1.49     lukem 
   1110       1.49     lukem 	_DIAGASSERT(retval != NULL);
   1111       1.49     lukem 
   1112       1.49     lukem 	*retval = NULL;
   1113       1.54     lukem 	rv = __grscan_nis(&rerror, &_nis_group,
   1114       1.54     lukem 	    _nis_groupbuf, sizeof(_nis_groupbuf), &_nis_state, 0, NULL, 0);
   1115       1.49     lukem 	if (rv == NS_SUCCESS)
   1116       1.49     lukem 		*retval = &_nis_group;
   1117       1.49     lukem 	return rv;
   1118       1.49     lukem }
   1119       1.49     lukem 
   1120       1.49     lukem /*ARGSUSED*/
   1121       1.49     lukem static int
   1122       1.56  christos _nis_getgrent_r(void *nsrv, void *nscb, va_list ap)
   1123       1.56  christos {
   1124       1.56  christos 	int		*retval	= va_arg(ap, int *);
   1125       1.56  christos 	struct group	*grp	= va_arg(ap, struct group *);
   1126       1.56  christos 	char		*buffer	= va_arg(ap, char *);
   1127       1.56  christos 	size_t		 buflen	= va_arg(ap, size_t);
   1128       1.56  christos 	struct group   **result	= va_arg(ap, struct group **);
   1129       1.56  christos 
   1130       1.56  christos 	int	rv;
   1131       1.56  christos 
   1132       1.56  christos 	_DIAGASSERT(retval != NULL);
   1133       1.56  christos 	_DIAGASSERT(grp != NULL);
   1134       1.56  christos 	_DIAGASSERT(buffer != NULL);
   1135       1.56  christos 	_DIAGASSERT(result != NULL);
   1136       1.56  christos 
   1137       1.56  christos 	rv = __grscan_nis(retval, grp, buffer, buflen,
   1138       1.56  christos 	    &_nis_state, 0, NULL, 0);
   1139       1.56  christos 	if (rv == NS_SUCCESS)
   1140       1.56  christos 		*result = grp;
   1141       1.56  christos 	else
   1142       1.56  christos 		*result = NULL;
   1143       1.56  christos 	return rv;
   1144       1.56  christos }
   1145       1.56  christos 
   1146       1.56  christos /*ARGSUSED*/
   1147       1.56  christos static int
   1148       1.49     lukem _nis_getgrgid(void *nsrv, void *nscb, va_list ap)
   1149       1.49     lukem {
   1150       1.49     lukem 	struct group	**retval = va_arg(ap, struct group **);
   1151       1.49     lukem 	gid_t		 gid	= va_arg(ap, gid_t);
   1152       1.49     lukem 
   1153       1.49     lukem 	int	rv, rerror;
   1154       1.49     lukem 
   1155       1.49     lukem 	_DIAGASSERT(retval != NULL);
   1156       1.49     lukem 
   1157       1.49     lukem 	*retval = NULL;
   1158       1.54     lukem 	rv = __grstart_nis(&_nis_state);
   1159       1.49     lukem 	if (rv != NS_SUCCESS)
   1160       1.49     lukem 		return rv;
   1161       1.54     lukem 	rv = __grscan_nis(&rerror, &_nis_group,
   1162       1.54     lukem 	    _nis_groupbuf, sizeof(_nis_groupbuf), &_nis_state, 1, NULL, gid);
   1163       1.49     lukem 	if (!_nis_state.stayopen)
   1164       1.54     lukem 		__grend_nis(&_nis_state);
   1165       1.54     lukem 	if (rv == NS_SUCCESS)
   1166       1.49     lukem 		*retval = &_nis_group;
   1167       1.49     lukem 	return rv;
   1168       1.49     lukem }
   1169       1.49     lukem 
   1170       1.49     lukem /*ARGSUSED*/
   1171       1.49     lukem static int
   1172       1.49     lukem _nis_getgrgid_r(void *nsrv, void *nscb, va_list ap)
   1173       1.49     lukem {
   1174       1.49     lukem 	int		*retval	= va_arg(ap, int *);
   1175       1.49     lukem 	gid_t		 gid	= va_arg(ap, gid_t);
   1176       1.49     lukem 	struct group	*grp	= va_arg(ap, struct group *);
   1177       1.49     lukem 	char		*buffer	= va_arg(ap, char *);
   1178       1.49     lukem 	size_t		 buflen	= va_arg(ap, size_t);
   1179       1.49     lukem 	struct group   **result	= va_arg(ap, struct group **);
   1180       1.49     lukem 
   1181       1.54     lukem 	struct __grstate_nis state;
   1182       1.49     lukem 	int	rv;
   1183       1.49     lukem 
   1184       1.49     lukem 	_DIAGASSERT(retval != NULL);
   1185       1.49     lukem 	_DIAGASSERT(grp != NULL);
   1186       1.49     lukem 	_DIAGASSERT(buffer != NULL);
   1187       1.49     lukem 	_DIAGASSERT(result != NULL);
   1188       1.49     lukem 
   1189       1.49     lukem 	*result = NULL;
   1190       1.49     lukem 	memset(&state, 0, sizeof(state));
   1191       1.54     lukem 	rv = __grscan_nis(retval, grp, buffer, buflen, &state, 1, NULL, gid);
   1192       1.54     lukem 	__grend_nis(&state);
   1193       1.54     lukem 	if (rv == NS_SUCCESS)
   1194       1.49     lukem 		*result = grp;
   1195       1.54     lukem 	return rv;
   1196       1.49     lukem }
   1197       1.49     lukem 
   1198       1.49     lukem /*ARGSUSED*/
   1199       1.49     lukem static int
   1200       1.49     lukem _nis_getgrnam(void *nsrv, void *nscb, va_list ap)
   1201       1.49     lukem {
   1202       1.49     lukem 	struct group	**retval = va_arg(ap, struct group **);
   1203       1.49     lukem 	const char	*name	= va_arg(ap, const char *);
   1204       1.49     lukem 
   1205       1.49     lukem 	int	rv, rerror;
   1206       1.49     lukem 
   1207       1.49     lukem 	_DIAGASSERT(retval != NULL);
   1208       1.49     lukem 
   1209       1.49     lukem 	*retval = NULL;
   1210       1.54     lukem 	rv = __grstart_nis(&_nis_state);
   1211       1.49     lukem 	if (rv != NS_SUCCESS)
   1212       1.49     lukem 		return rv;
   1213       1.54     lukem 	rv = __grscan_nis(&rerror, &_nis_group,
   1214       1.54     lukem 	    _nis_groupbuf, sizeof(_nis_groupbuf), &_nis_state, 1, name, 0);
   1215       1.49     lukem 	if (!_nis_state.stayopen)
   1216       1.54     lukem 		__grend_nis(&_nis_state);
   1217       1.54     lukem 	if (rv == NS_SUCCESS)
   1218       1.49     lukem 		*retval = &_nis_group;
   1219       1.49     lukem 	return rv;
   1220       1.49     lukem }
   1221       1.49     lukem 
   1222       1.49     lukem /*ARGSUSED*/
   1223       1.49     lukem static int
   1224       1.49     lukem _nis_getgrnam_r(void *nsrv, void *nscb, va_list ap)
   1225       1.49     lukem {
   1226       1.49     lukem 	int		*retval	= va_arg(ap, int *);
   1227       1.49     lukem 	const char	*name	= va_arg(ap, const char *);
   1228       1.49     lukem 	struct group	*grp	= va_arg(ap, struct group *);
   1229       1.49     lukem 	char		*buffer	= va_arg(ap, char *);
   1230       1.49     lukem 	size_t		 buflen	= va_arg(ap, size_t);
   1231       1.49     lukem 	struct group   **result	= va_arg(ap, struct group **);
   1232       1.49     lukem 
   1233       1.54     lukem 	struct __grstate_nis state;
   1234       1.49     lukem 	int	rv;
   1235       1.49     lukem 
   1236       1.49     lukem 	_DIAGASSERT(retval != NULL);
   1237       1.49     lukem 	_DIAGASSERT(grp != NULL);
   1238       1.49     lukem 	_DIAGASSERT(buffer != NULL);
   1239       1.49     lukem 	_DIAGASSERT(result != NULL);
   1240       1.49     lukem 
   1241       1.49     lukem 	*result = NULL;
   1242       1.49     lukem 	memset(&state, 0, sizeof(state));
   1243       1.54     lukem 	rv = __grscan_nis(retval, grp, buffer, buflen, &state, 1, name, 0);
   1244       1.54     lukem 	__grend_nis(&state);
   1245       1.54     lukem 	if (rv == NS_SUCCESS)
   1246       1.49     lukem 		*result = grp;
   1247       1.54     lukem 	return rv;
   1248       1.49     lukem }
   1249       1.49     lukem 
   1250       1.49     lukem #endif /* YP */
   1251       1.49     lukem 
   1252       1.27     lukem 
   1253       1.34     lukem #ifdef _GROUP_COMPAT
   1254       1.49     lukem 		/*
   1255       1.49     lukem 		 *	compat methods
   1256       1.49     lukem 		 */
   1257       1.49     lukem 
   1258       1.54     lukem int
   1259       1.54     lukem __grstart_compat(struct __grstate_compat *state)
   1260       1.49     lukem {
   1261       1.49     lukem 
   1262       1.49     lukem 	_DIAGASSERT(state != NULL);
   1263       1.49     lukem 
   1264       1.49     lukem 	if (state->fp == NULL) {
   1265       1.49     lukem 		state->fp = fopen(_PATH_GROUP, "r");
   1266       1.49     lukem 		if (state->fp == NULL)
   1267       1.49     lukem 			return NS_UNAVAIL;
   1268       1.49     lukem 	} else {
   1269       1.49     lukem 		rewind(state->fp);
   1270       1.49     lukem 	}
   1271       1.49     lukem 	return NS_SUCCESS;
   1272       1.49     lukem }
   1273       1.49     lukem 
   1274       1.54     lukem int
   1275       1.54     lukem __grend_compat(struct __grstate_compat *state)
   1276       1.49     lukem {
   1277       1.49     lukem 
   1278       1.49     lukem 	_DIAGASSERT(state != NULL);
   1279       1.49     lukem 
   1280       1.49     lukem 	if (state->name) {
   1281       1.49     lukem 		free(state->name);
   1282       1.49     lukem 		state->name = NULL;
   1283       1.49     lukem 	}
   1284       1.49     lukem 	if (state->fp) {
   1285       1.49     lukem 		(void) fclose(state->fp);
   1286       1.49     lukem 		state->fp = NULL;
   1287       1.49     lukem 	}
   1288       1.49     lukem 	return NS_SUCCESS;
   1289       1.49     lukem }
   1290       1.49     lukem 
   1291       1.49     lukem 
   1292       1.49     lukem /*
   1293       1.54     lukem  * __grbad_compat
   1294       1.49     lukem  *	log an error if "files" or "compat" is specified in
   1295       1.49     lukem  *	group_compat database
   1296       1.49     lukem  */
   1297       1.49     lukem /*ARGSUSED*/
   1298       1.54     lukem int
   1299       1.54     lukem __grbad_compat(void *nsrv, void *nscb, va_list ap)
   1300       1.49     lukem {
   1301       1.49     lukem 	static int warned;
   1302       1.49     lukem 
   1303       1.61  christos 	_DIAGASSERT(nsrv != NULL);
   1304       1.61  christos 	_DIAGASSERT(nscb != NULL);
   1305       1.49     lukem 
   1306       1.49     lukem 	if (!warned) {
   1307       1.49     lukem 		syslog(LOG_ERR,
   1308       1.49     lukem 			"nsswitch.conf group_compat database can't use '%s'",
   1309       1.54     lukem 			(const char *)nscb);
   1310       1.49     lukem 	}
   1311       1.49     lukem 	warned = 1;
   1312       1.49     lukem 	return NS_UNAVAIL;
   1313       1.49     lukem }
   1314       1.49     lukem 
   1315       1.49     lukem /*
   1316       1.54     lukem  * __grscan_compat
   1317       1.49     lukem  *	Scan state->fp for the next desired entry.
   1318       1.49     lukem  *	If search is zero, return the next entry.
   1319       1.49     lukem  *	If search is non-zero, look for a specific name (if name != NULL),
   1320       1.49     lukem  *	or a specific gid (if name == NULL).
   1321       1.57     lukem  *	Sets *retval to the errno if the result is not NS_SUCCESS or
   1322       1.57     lukem  *	NS_NOTFOUND.
   1323       1.54     lukem  *
   1324       1.54     lukem  *	searchfunc is invoked when a compat "+" lookup is required;
   1325       1.54     lukem  *	searchcookie is passed as the first argument to searchfunc,
   1326       1.54     lukem  *	the second argument is the group result.
   1327       1.54     lukem  *	This should return NS_NOTFOUND when "no more groups" from compat src.
   1328       1.54     lukem  *	If searchfunc is NULL then nsdispatch of getgrent is used.
   1329       1.54     lukem  *	This is primarily intended for getgroupmembership(3)'s compat backend.
   1330       1.49     lukem  */
   1331       1.54     lukem int
   1332       1.54     lukem __grscan_compat(int *retval, struct group *grp, char *buffer, size_t buflen,
   1333       1.54     lukem 	struct __grstate_compat *state, int search, const char *name, gid_t gid,
   1334       1.54     lukem 	int (*searchfunc)(void *, struct group **), void *searchcookie)
   1335       1.49     lukem {
   1336       1.49     lukem 	int		rv;
   1337       1.52     lukem 	char		filebuf[_GETGR_R_SIZE_MAX], *ep;
   1338       1.49     lukem 
   1339       1.49     lukem 	static const ns_dtab compatentdtab[] = {
   1340       1.54     lukem 		NS_FILES_CB(__grbad_compat, "files")
   1341       1.56  christos 		NS_DNS_CB(_dns_getgrent_r, NULL)
   1342       1.56  christos 		NS_NIS_CB(_nis_getgrent_r, NULL)
   1343       1.54     lukem 		NS_COMPAT_CB(__grbad_compat, "compat")
   1344       1.60  christos 		NS_NULL_CB
   1345       1.49     lukem 	};
   1346       1.49     lukem 	static const ns_dtab compatgiddtab[] = {
   1347       1.54     lukem 		NS_FILES_CB(__grbad_compat, "files")
   1348       1.49     lukem 		NS_DNS_CB(_dns_getgrgid_r, NULL)
   1349       1.49     lukem 		NS_NIS_CB(_nis_getgrgid_r, NULL)
   1350       1.54     lukem 		NS_COMPAT_CB(__grbad_compat, "compat")
   1351       1.60  christos 		NS_NULL_CB
   1352       1.49     lukem 	};
   1353       1.49     lukem 	static const ns_dtab compatnamdtab[] = {
   1354       1.54     lukem 		NS_FILES_CB(__grbad_compat, "files")
   1355       1.49     lukem 		NS_DNS_CB(_dns_getgrnam_r, NULL)
   1356       1.49     lukem 		NS_NIS_CB(_nis_getgrnam_r, NULL)
   1357       1.54     lukem 		NS_COMPAT_CB(__grbad_compat, "compat")
   1358       1.60  christos 		NS_NULL_CB
   1359       1.49     lukem 	};
   1360       1.27     lukem 
   1361       1.49     lukem 	_DIAGASSERT(retval != NULL);
   1362       1.49     lukem 	_DIAGASSERT(grp != NULL);
   1363       1.49     lukem 	_DIAGASSERT(buffer != NULL);
   1364       1.49     lukem 	_DIAGASSERT(state != NULL);
   1365       1.49     lukem 	/* name is NULL to indicate searching for gid */
   1366       1.49     lukem 
   1367       1.49     lukem 	*retval = 0;
   1368       1.49     lukem 
   1369       1.49     lukem 	if (state->fp == NULL) {	/* only start if file not open yet */
   1370       1.54     lukem 		rv = __grstart_compat(state);
   1371       1.49     lukem 		if (rv != NS_SUCCESS)
   1372       1.49     lukem 			goto compatgrscan_out;
   1373       1.49     lukem 	}
   1374       1.49     lukem 	rv = NS_NOTFOUND;
   1375       1.27     lukem 
   1376       1.49     lukem 	for (;;) {					/* loop through file */
   1377       1.49     lukem 		if (state->name != NULL) {
   1378       1.49     lukem 					/* processing compat entry */
   1379       1.49     lukem 			int		crv, cretval;
   1380       1.49     lukem 			struct group	cgrp, *cgrpres;
   1381       1.49     lukem 
   1382       1.49     lukem 			if (state->name[0]) {		/* specific +group: */
   1383       1.49     lukem 				crv = nsdispatch(NULL, compatnamdtab,
   1384       1.53     lukem 				    NSDB_GROUP_COMPAT, "getgrnam_r",
   1385       1.53     lukem 				    __nsdefaultnis,
   1386       1.49     lukem 				    &cretval, state->name,
   1387       1.49     lukem 				    &cgrp, filebuf, sizeof(filebuf), &cgrpres);
   1388       1.49     lukem 				free(state->name);	/* (only check 1 grp) */
   1389       1.49     lukem 				state->name = NULL;
   1390       1.49     lukem 			} else if (!search) {		/* any group */
   1391       1.54     lukem 				if (searchfunc) {
   1392       1.54     lukem 					crv = searchfunc(searchcookie,
   1393       1.54     lukem 					    &cgrpres);
   1394       1.54     lukem 				} else {
   1395       1.54     lukem 					crv = nsdispatch(NULL, compatentdtab,
   1396       1.56  christos 					    NSDB_GROUP_COMPAT, "getgrent_r",
   1397       1.54     lukem 					    __nsdefaultnis,
   1398       1.56  christos 					    &cretval, &cgrp, filebuf,
   1399       1.56  christos 					    sizeof(filebuf), &cgrpres);
   1400       1.54     lukem 				}
   1401       1.49     lukem 			} else if (name) {		/* specific group */
   1402       1.49     lukem 				crv = nsdispatch(NULL, compatnamdtab,
   1403       1.53     lukem 				    NSDB_GROUP_COMPAT, "getgrnam_r",
   1404       1.53     lukem 				    __nsdefaultnis,
   1405       1.49     lukem 				    &cretval, name,
   1406       1.49     lukem 				    &cgrp, filebuf, sizeof(filebuf), &cgrpres);
   1407       1.49     lukem 			} else {			/* specific gid */
   1408       1.49     lukem 				crv = nsdispatch(NULL, compatgiddtab,
   1409       1.53     lukem 				    NSDB_GROUP_COMPAT, "getgrgid_r",
   1410       1.53     lukem 				    __nsdefaultnis,
   1411       1.49     lukem 				    &cretval, gid,
   1412       1.49     lukem 				    &cgrp, filebuf, sizeof(filebuf), &cgrpres);
   1413       1.49     lukem 			}
   1414       1.49     lukem 			if (crv != NS_SUCCESS) {	/* not found */
   1415       1.49     lukem 				free(state->name);
   1416       1.49     lukem 				state->name = NULL;
   1417       1.49     lukem 				continue;		/* try next line */
   1418       1.49     lukem 			}
   1419       1.49     lukem 			if (!_gr_copy(cgrpres, grp, buffer, buflen)) {
   1420       1.49     lukem 				rv = NS_UNAVAIL;
   1421       1.20  christos 				break;
   1422        1.2   deraadt 			}
   1423       1.49     lukem 			goto compatgrscan_cmpgrp;	/* skip to grp test */
   1424        1.2   deraadt 		}
   1425       1.27     lukem 
   1426       1.49     lukem 							/* get next file line */
   1427       1.49     lukem 		if (fgets(filebuf, sizeof(filebuf), state->fp) == NULL)
   1428       1.49     lukem 			break;
   1429       1.49     lukem 
   1430       1.49     lukem 		ep = strchr(filebuf, '\n');
   1431       1.58     lukem 		if (ep == NULL) {	/* skip lines that are too big */
   1432        1.1       cgd 			int ch;
   1433        1.1       cgd 
   1434       1.49     lukem 			while ((ch = getc(state->fp)) != '\n' && ch != EOF)
   1435       1.49     lukem 				continue;
   1436       1.58     lukem 			continue;
   1437        1.1       cgd 		}
   1438       1.49     lukem 		*ep = '\0';				/* clear trailing \n */
   1439       1.27     lukem 
   1440       1.49     lukem 		if (filebuf[0] == '+') {		/* parse compat line */
   1441       1.49     lukem 			if (state->name)
   1442       1.49     lukem 				free(state->name);
   1443       1.49     lukem 			state->name = NULL;
   1444       1.49     lukem 			switch(filebuf[1]) {
   1445       1.13      phil 			case ':':
   1446       1.13      phil 			case '\0':
   1447       1.49     lukem 				state->name = strdup("");
   1448       1.13      phil 				break;
   1449       1.13      phil 			default:
   1450       1.49     lukem 				ep = strchr(filebuf + 1, ':');
   1451       1.49     lukem 				if (ep == NULL)
   1452       1.49     lukem 					break;
   1453       1.49     lukem 				*ep = '\0';
   1454       1.49     lukem 				state->name = strdup(filebuf + 1);
   1455       1.49     lukem 				break;
   1456       1.49     lukem 			}
   1457       1.49     lukem 			if (state->name == NULL) {
   1458       1.49     lukem 				rv = NS_UNAVAIL;
   1459       1.13      phil 				break;
   1460        1.2   deraadt 			}
   1461        1.9   deraadt 			continue;
   1462        1.1       cgd 		}
   1463       1.49     lukem 
   1464       1.49     lukem 							/* validate line */
   1465       1.49     lukem 		if (! _gr_parse(filebuf, grp, buffer, buflen)) {
   1466       1.58     lukem 			continue;			/* skip bad lines */
   1467       1.49     lukem 		}
   1468       1.49     lukem 
   1469       1.49     lukem  compatgrscan_cmpgrp:
   1470       1.49     lukem 		if (! search) {				/* just want this one */
   1471       1.49     lukem 			rv = NS_SUCCESS;
   1472       1.49     lukem 			break;
   1473       1.49     lukem 		}
   1474       1.49     lukem 							/* want specific */
   1475       1.49     lukem 		if ((name && strcmp(name, grp->gr_name) == 0) ||
   1476       1.49     lukem 		    (!name && gid == grp->gr_gid)) {
   1477       1.49     lukem 			rv = NS_SUCCESS;
   1478       1.49     lukem 			break;
   1479       1.49     lukem 		}
   1480       1.49     lukem 
   1481        1.1       cgd 	}
   1482       1.49     lukem 
   1483       1.49     lukem  compatgrscan_out:
   1484       1.57     lukem 	if (rv != NS_SUCCESS && rv != NS_NOTFOUND)
   1485       1.49     lukem 		*retval = errno;
   1486       1.49     lukem 	return rv;
   1487       1.27     lukem }
   1488       1.27     lukem 
   1489       1.54     lukem static struct __grstate_compat	_compat_state;
   1490       1.54     lukem 					/* storage for non _r functions */
   1491       1.54     lukem static struct group		_compat_group;
   1492       1.54     lukem static char			_compat_groupbuf[_GETGR_R_SIZE_MAX];
   1493       1.54     lukem 
   1494       1.49     lukem /*ARGSUSED*/
   1495       1.27     lukem static int
   1496       1.49     lukem _compat_setgrent(void *nsrv, void *nscb, va_list ap)
   1497       1.27     lukem {
   1498       1.31     lukem 	static const ns_dtab dtab[] = {
   1499       1.54     lukem 		NS_FILES_CB(__grbad_compat, "files")
   1500       1.49     lukem 		NS_DNS_CB(_dns_setgrent, NULL)
   1501       1.49     lukem 		NS_NIS_CB(_nis_setgrent, NULL)
   1502       1.54     lukem 		NS_COMPAT_CB(__grbad_compat, "compat")
   1503       1.60  christos 		NS_NULL_CB
   1504       1.27     lukem 	};
   1505       1.49     lukem 
   1506       1.49     lukem 					/* force group_compat setgrent() */
   1507       1.49     lukem 	(void) nsdispatch(NULL, dtab, NSDB_GROUP_COMPAT, "setgrent",
   1508       1.53     lukem 	    __nsdefaultnis_forceall);
   1509       1.49     lukem 
   1510       1.49     lukem 					/* reset state, keep fp open */
   1511       1.49     lukem 	_compat_state.stayopen = 0;
   1512       1.54     lukem 	return __grstart_compat(&_compat_state);
   1513       1.49     lukem }
   1514       1.49     lukem 
   1515       1.49     lukem /*ARGSUSED*/
   1516       1.49     lukem static int
   1517       1.49     lukem _compat_setgroupent(void *nsrv, void *nscb, va_list ap)
   1518       1.49     lukem {
   1519       1.49     lukem 	int	*retval		= va_arg(ap, int *);
   1520       1.49     lukem 	int	 stayopen	= va_arg(ap, int);
   1521       1.49     lukem 
   1522       1.49     lukem 	int	rv;
   1523       1.49     lukem 
   1524       1.49     lukem 	static const ns_dtab dtab[] = {
   1525       1.54     lukem 		NS_FILES_CB(__grbad_compat, "files")
   1526       1.49     lukem 		NS_DNS_CB(_dns_setgroupent, NULL)
   1527       1.49     lukem 		NS_NIS_CB(_nis_setgroupent, NULL)
   1528       1.54     lukem 		NS_COMPAT_CB(__grbad_compat, "compat")
   1529       1.60  christos 		NS_NULL_CB
   1530       1.32     lukem 	};
   1531       1.27     lukem 
   1532       1.49     lukem 					/* force group_compat setgroupent() */
   1533       1.49     lukem 	(void) nsdispatch(NULL, dtab, NSDB_GROUP_COMPAT, "setgroupent",
   1534       1.53     lukem 	    __nsdefaultnis_forceall, &rv, stayopen);
   1535       1.49     lukem 
   1536       1.49     lukem 	_compat_state.stayopen = stayopen;
   1537       1.54     lukem 	rv = __grstart_compat(&_compat_state);
   1538       1.49     lukem 	*retval = (rv == NS_SUCCESS);
   1539       1.49     lukem 	return rv;
   1540       1.49     lukem }
   1541       1.37     lukem 
   1542       1.49     lukem /*ARGSUSED*/
   1543       1.49     lukem static int
   1544       1.49     lukem _compat_endgrent(void *nsrv, void *nscb, va_list ap)
   1545       1.49     lukem {
   1546       1.49     lukem 	static const ns_dtab dtab[] = {
   1547       1.54     lukem 		NS_FILES_CB(__grbad_compat, "files")
   1548       1.49     lukem 		NS_DNS_CB(_dns_endgrent, NULL)
   1549       1.49     lukem 		NS_NIS_CB(_nis_endgrent, NULL)
   1550       1.54     lukem 		NS_COMPAT_CB(__grbad_compat, "compat")
   1551       1.60  christos 		NS_NULL_CB
   1552       1.49     lukem 	};
   1553       1.49     lukem 
   1554       1.49     lukem 					/* force group_compat endgrent() */
   1555       1.49     lukem 	(void) nsdispatch(NULL, dtab, NSDB_GROUP_COMPAT, "endgrent",
   1556       1.53     lukem 	    __nsdefaultnis_forceall);
   1557       1.49     lukem 
   1558       1.49     lukem 					/* reset state, close fp */
   1559       1.49     lukem 	_compat_state.stayopen = 0;
   1560       1.54     lukem 	return __grend_compat(&_compat_state);
   1561       1.27     lukem }
   1562       1.27     lukem 
   1563       1.49     lukem /*ARGSUSED*/
   1564       1.49     lukem static int
   1565       1.49     lukem _compat_getgrent(void *nsrv, void *nscb, va_list ap)
   1566       1.49     lukem {
   1567       1.49     lukem 	struct group	**retval = va_arg(ap, struct group **);
   1568       1.49     lukem 
   1569       1.49     lukem 	int	rv, rerror;
   1570       1.49     lukem 
   1571       1.49     lukem 	_DIAGASSERT(retval != NULL);
   1572       1.49     lukem 
   1573       1.49     lukem 	*retval = NULL;
   1574       1.54     lukem 	rv = __grscan_compat(&rerror, &_compat_group,
   1575       1.49     lukem 	    _compat_groupbuf, sizeof(_compat_groupbuf),
   1576       1.54     lukem 	    &_compat_state, 0, NULL, 0, NULL, NULL);
   1577       1.49     lukem 	if (rv == NS_SUCCESS)
   1578       1.49     lukem 		*retval = &_compat_group;
   1579       1.49     lukem 	return rv;
   1580       1.49     lukem }
   1581       1.49     lukem 
   1582       1.49     lukem /*ARGSUSED*/
   1583       1.27     lukem static int
   1584       1.56  christos _compat_getgrent_r(void *nsrv, void *nscb, va_list ap)
   1585       1.56  christos {
   1586       1.56  christos 	int		*retval	= va_arg(ap, int *);
   1587       1.56  christos 	struct group	*grp	= va_arg(ap, struct group *);
   1588       1.56  christos 	char		*buffer	= va_arg(ap, char *);
   1589       1.56  christos 	size_t		 buflen	= va_arg(ap, size_t);
   1590       1.56  christos 	struct group   **result	= va_arg(ap, struct group **);
   1591       1.56  christos 
   1592       1.56  christos 	int	rv;
   1593       1.56  christos 
   1594       1.56  christos 	_DIAGASSERT(retval != NULL);
   1595       1.56  christos 	_DIAGASSERT(grp != NULL);
   1596       1.56  christos 	_DIAGASSERT(buffer != NULL);
   1597       1.56  christos 	_DIAGASSERT(result != NULL);
   1598       1.56  christos 
   1599       1.56  christos 	rv = __grscan_compat(retval, grp, buffer, buflen,
   1600       1.56  christos 	    &_compat_state, 0, NULL, 0, NULL, NULL);
   1601       1.56  christos 	if (rv == NS_SUCCESS)
   1602       1.56  christos 		*result = grp;
   1603       1.56  christos 	else
   1604       1.56  christos 		*result = NULL;
   1605       1.56  christos 	return rv;
   1606       1.56  christos }
   1607       1.56  christos 
   1608       1.56  christos /*ARGSUSED*/
   1609       1.56  christos static int
   1610       1.49     lukem _compat_getgrgid(void *nsrv, void *nscb, va_list ap)
   1611       1.49     lukem {
   1612       1.49     lukem 	struct group	**retval = va_arg(ap, struct group **);
   1613       1.49     lukem 	gid_t		 gid	= va_arg(ap, gid_t);
   1614       1.49     lukem 
   1615       1.49     lukem 	int	rv, rerror;
   1616       1.49     lukem 
   1617       1.49     lukem 	_DIAGASSERT(retval != NULL);
   1618       1.49     lukem 
   1619       1.49     lukem 	*retval = NULL;
   1620       1.54     lukem 	rv = __grstart_compat(&_compat_state);
   1621       1.49     lukem 	if (rv != NS_SUCCESS)
   1622       1.49     lukem 		return rv;
   1623       1.54     lukem 	rv = __grscan_compat(&rerror, &_compat_group,
   1624       1.49     lukem 	    _compat_groupbuf, sizeof(_compat_groupbuf),
   1625       1.54     lukem 	    &_compat_state, 1, NULL, gid, NULL, NULL);
   1626       1.49     lukem 	if (!_compat_state.stayopen)
   1627       1.54     lukem 		__grend_compat(&_compat_state);
   1628       1.49     lukem 	if (rv == NS_SUCCESS)
   1629       1.49     lukem 		*retval = &_compat_group;
   1630       1.49     lukem 	return rv;
   1631       1.49     lukem }
   1632       1.49     lukem 
   1633       1.49     lukem /*ARGSUSED*/
   1634       1.49     lukem static int
   1635       1.49     lukem _compat_getgrgid_r(void *nsrv, void *nscb, va_list ap)
   1636       1.49     lukem {
   1637       1.49     lukem 	int		*retval	= va_arg(ap, int *);
   1638       1.49     lukem 	gid_t		 gid	= va_arg(ap, gid_t);
   1639       1.49     lukem 	struct group	*grp	= va_arg(ap, struct group *);
   1640       1.49     lukem 	char		*buffer	= va_arg(ap, char *);
   1641       1.49     lukem 	size_t		 buflen	= va_arg(ap, size_t);
   1642       1.49     lukem 	struct group   **result	= va_arg(ap, struct group **);
   1643       1.49     lukem 
   1644       1.54     lukem 	struct __grstate_compat	state;
   1645       1.49     lukem 	int		rv;
   1646       1.49     lukem 
   1647       1.49     lukem 	_DIAGASSERT(retval != NULL);
   1648       1.49     lukem 	_DIAGASSERT(grp != NULL);
   1649       1.49     lukem 	_DIAGASSERT(buffer != NULL);
   1650       1.49     lukem 	_DIAGASSERT(result != NULL);
   1651       1.49     lukem 
   1652       1.49     lukem 	*result = NULL;
   1653       1.49     lukem 	memset(&state, 0, sizeof(state));
   1654       1.54     lukem 	rv = __grscan_compat(retval, grp, buffer, buflen, &state,
   1655       1.54     lukem 	    1, NULL, gid, NULL, NULL);
   1656       1.54     lukem 	__grend_compat(&state);
   1657       1.49     lukem 	if (rv == NS_SUCCESS)
   1658       1.49     lukem 		*result = grp;
   1659       1.49     lukem 	return rv;
   1660       1.49     lukem }
   1661       1.49     lukem 
   1662       1.49     lukem /*ARGSUSED*/
   1663       1.49     lukem static int
   1664       1.49     lukem _compat_getgrnam(void *nsrv, void *nscb, va_list ap)
   1665       1.49     lukem {
   1666       1.49     lukem 	struct group	**retval = va_arg(ap, struct group **);
   1667       1.49     lukem 	const char	*name	= va_arg(ap, const char *);
   1668       1.49     lukem 
   1669       1.49     lukem 	int	rv, rerror;
   1670       1.49     lukem 
   1671       1.49     lukem 	_DIAGASSERT(retval != NULL);
   1672       1.49     lukem 
   1673       1.49     lukem 	*retval = NULL;
   1674       1.54     lukem 	rv = __grstart_compat(&_compat_state);
   1675       1.49     lukem 	if (rv != NS_SUCCESS)
   1676       1.49     lukem 		return rv;
   1677       1.54     lukem 	rv = __grscan_compat(&rerror, &_compat_group,
   1678       1.49     lukem 	    _compat_groupbuf, sizeof(_compat_groupbuf),
   1679       1.54     lukem 	    &_compat_state, 1, name, 0, NULL, NULL);
   1680       1.49     lukem 	if (!_compat_state.stayopen)
   1681       1.54     lukem 		__grend_compat(&_compat_state);
   1682       1.49     lukem 	if (rv == NS_SUCCESS)
   1683       1.49     lukem 		*retval = &_compat_group;
   1684       1.49     lukem 	return rv;
   1685       1.49     lukem }
   1686       1.49     lukem 
   1687       1.49     lukem /*ARGSUSED*/
   1688       1.49     lukem static int
   1689       1.49     lukem _compat_getgrnam_r(void *nsrv, void *nscb, va_list ap)
   1690       1.49     lukem {
   1691       1.49     lukem 	int		*retval	= va_arg(ap, int *);
   1692       1.49     lukem 	const char	*name	= va_arg(ap, const char *);
   1693       1.49     lukem 	struct group	*grp	= va_arg(ap, struct group *);
   1694       1.49     lukem 	char		*buffer	= va_arg(ap, char *);
   1695       1.49     lukem 	size_t		 buflen	= va_arg(ap, size_t);
   1696       1.49     lukem 	struct group   **result	= va_arg(ap, struct group **);
   1697       1.49     lukem 
   1698       1.54     lukem 	struct __grstate_compat	state;
   1699       1.49     lukem 	int		rv;
   1700       1.49     lukem 
   1701       1.49     lukem 	_DIAGASSERT(retval != NULL);
   1702       1.49     lukem 	_DIAGASSERT(grp != NULL);
   1703       1.49     lukem 	_DIAGASSERT(buffer != NULL);
   1704       1.49     lukem 	_DIAGASSERT(result != NULL);
   1705       1.49     lukem 
   1706       1.49     lukem 	*result = NULL;
   1707       1.49     lukem 	memset(&state, 0, sizeof(state));
   1708       1.54     lukem 	rv = __grscan_compat(retval, grp, buffer, buflen, &state,
   1709       1.54     lukem 	    1, name, 0, NULL, NULL);
   1710       1.54     lukem 	__grend_compat(&state);
   1711       1.49     lukem 	if (rv == NS_SUCCESS)
   1712       1.49     lukem 		*result = grp;
   1713       1.49     lukem 	return rv;
   1714       1.49     lukem }
   1715       1.49     lukem 
   1716       1.49     lukem #endif	/* _GROUP_COMPAT */
   1717       1.49     lukem 
   1718       1.49     lukem 
   1719       1.49     lukem 		/*
   1720       1.49     lukem 		 *	public functions
   1721       1.49     lukem 		 */
   1722       1.49     lukem 
   1723       1.49     lukem struct group *
   1724       1.49     lukem getgrent(void)
   1725       1.27     lukem {
   1726       1.49     lukem 	int		rv;
   1727       1.49     lukem 	struct group	*retval;
   1728       1.49     lukem 
   1729       1.49     lukem 	static const ns_dtab dtab[] = {
   1730       1.49     lukem 		NS_FILES_CB(_files_getgrent, NULL)
   1731       1.49     lukem 		NS_DNS_CB(_dns_getgrent, NULL)
   1732       1.49     lukem 		NS_NIS_CB(_nis_getgrent, NULL)
   1733       1.49     lukem 		NS_COMPAT_CB(_compat_getgrent, NULL)
   1734       1.60  christos 		NS_NULL_CB
   1735       1.49     lukem 	};
   1736       1.49     lukem 
   1737       1.54     lukem 	mutex_lock(&__grmutex);
   1738       1.53     lukem 	rv = nsdispatch(NULL, dtab, NSDB_GROUP, "getgrent", __nsdefaultcompat,
   1739       1.49     lukem 	    &retval);
   1740       1.54     lukem 	mutex_unlock(&__grmutex);
   1741       1.57     lukem 	return (rv == NS_SUCCESS) ? retval : NULL;
   1742       1.56  christos }
   1743       1.56  christos 
   1744       1.56  christos int
   1745       1.56  christos getgrent_r(struct group *grp, char *buffer, size_t buflen,
   1746       1.56  christos     struct group **result)
   1747       1.56  christos {
   1748       1.56  christos 	int		rv, retval;
   1749       1.56  christos 
   1750       1.56  christos 	static const ns_dtab dtab[] = {
   1751       1.56  christos 		NS_FILES_CB(_files_getgrent_r, NULL)
   1752       1.56  christos 		NS_DNS_CB(_dns_getgrent_r, NULL)
   1753       1.56  christos 		NS_NIS_CB(_nis_getgrent_r, NULL)
   1754       1.56  christos 		NS_COMPAT_CB(_compat_getgrent_r, NULL)
   1755       1.60  christos 		NS_NULL_CB
   1756       1.56  christos 	};
   1757       1.56  christos 
   1758       1.56  christos 	mutex_lock(&__grmutex);
   1759       1.56  christos 	rv = nsdispatch(NULL, dtab, NSDB_GROUP, "getgrent_r", __nsdefaultcompat,
   1760       1.56  christos 	    &retval, grp, buffer, buflen, result);
   1761       1.56  christos 	mutex_unlock(&__grmutex);
   1762       1.57     lukem 	switch (rv) {
   1763       1.57     lukem 	case NS_SUCCESS:
   1764       1.57     lukem 	case NS_NOTFOUND:
   1765       1.57     lukem 		return 0;
   1766       1.57     lukem 	default:
   1767       1.57     lukem 		return retval;
   1768       1.57     lukem 	}
   1769       1.49     lukem }
   1770       1.49     lukem 
   1771       1.56  christos 
   1772       1.49     lukem struct group *
   1773       1.49     lukem getgrgid(gid_t gid)
   1774       1.49     lukem {
   1775       1.49     lukem 	int		rv;
   1776       1.49     lukem 	struct group	*retval;
   1777       1.49     lukem 
   1778       1.49     lukem 	static const ns_dtab dtab[] = {
   1779       1.49     lukem 		NS_FILES_CB(_files_getgrgid, NULL)
   1780       1.49     lukem 		NS_DNS_CB(_dns_getgrgid, NULL)
   1781       1.49     lukem 		NS_NIS_CB(_nis_getgrgid, NULL)
   1782       1.49     lukem 		NS_COMPAT_CB(_compat_getgrgid, NULL)
   1783       1.60  christos 		NS_NULL_CB
   1784       1.49     lukem 	};
   1785       1.49     lukem 
   1786       1.54     lukem 	mutex_lock(&__grmutex);
   1787       1.53     lukem 	rv = nsdispatch(NULL, dtab, NSDB_GROUP, "getgrgid", __nsdefaultcompat,
   1788       1.49     lukem 	    &retval, gid);
   1789       1.54     lukem 	mutex_unlock(&__grmutex);
   1790       1.49     lukem 	return (rv == NS_SUCCESS) ? retval : NULL;
   1791       1.49     lukem }
   1792       1.49     lukem 
   1793       1.49     lukem int
   1794       1.49     lukem getgrgid_r(gid_t gid, struct group *grp, char *buffer, size_t buflen,
   1795       1.49     lukem 	struct group **result)
   1796       1.49     lukem {
   1797       1.49     lukem 	int	rv, retval;
   1798       1.49     lukem 
   1799       1.49     lukem 	static const ns_dtab dtab[] = {
   1800       1.49     lukem 		NS_FILES_CB(_files_getgrgid_r, NULL)
   1801       1.49     lukem 		NS_DNS_CB(_dns_getgrgid_r, NULL)
   1802       1.49     lukem 		NS_NIS_CB(_nis_getgrgid_r, NULL)
   1803       1.49     lukem 		NS_COMPAT_CB(_compat_getgrgid_r, NULL)
   1804       1.60  christos 		NS_NULL_CB
   1805       1.49     lukem 	};
   1806       1.49     lukem 
   1807       1.49     lukem 	_DIAGASSERT(grp != NULL);
   1808       1.49     lukem 	_DIAGASSERT(buffer != NULL);
   1809       1.49     lukem 	_DIAGASSERT(result != NULL);
   1810       1.49     lukem 
   1811       1.49     lukem 	*result = NULL;
   1812       1.49     lukem 	retval = 0;
   1813       1.54     lukem 	mutex_lock(&__grmutex);
   1814       1.53     lukem 	rv = nsdispatch(NULL, dtab, NSDB_GROUP, "getgrgid_r", __nsdefaultcompat,
   1815       1.49     lukem 	    &retval, gid, grp, buffer, buflen, result);
   1816       1.54     lukem 	mutex_unlock(&__grmutex);
   1817       1.57     lukem 	switch (rv) {
   1818       1.57     lukem 	case NS_SUCCESS:
   1819       1.57     lukem 	case NS_NOTFOUND:
   1820       1.57     lukem 		return 0;
   1821       1.57     lukem 	default:
   1822       1.57     lukem 		return retval;
   1823       1.57     lukem 	}
   1824       1.49     lukem }
   1825       1.49     lukem 
   1826       1.49     lukem struct group *
   1827       1.49     lukem getgrnam(const char *name)
   1828       1.49     lukem {
   1829       1.49     lukem 	int		rv;
   1830       1.49     lukem 	struct group	*retval;
   1831       1.49     lukem 
   1832       1.49     lukem 	static const ns_dtab dtab[] = {
   1833       1.49     lukem 		NS_FILES_CB(_files_getgrnam, NULL)
   1834       1.49     lukem 		NS_DNS_CB(_dns_getgrnam, NULL)
   1835       1.49     lukem 		NS_NIS_CB(_nis_getgrnam, NULL)
   1836       1.49     lukem 		NS_COMPAT_CB(_compat_getgrnam, NULL)
   1837       1.60  christos 		NS_NULL_CB
   1838       1.49     lukem 	};
   1839       1.49     lukem 
   1840       1.54     lukem 	mutex_lock(&__grmutex);
   1841       1.53     lukem 	rv = nsdispatch(NULL, dtab, NSDB_GROUP, "getgrnam", __nsdefaultcompat,
   1842       1.49     lukem 	    &retval, name);
   1843       1.54     lukem 	mutex_unlock(&__grmutex);
   1844       1.49     lukem 	return (rv == NS_SUCCESS) ? retval : NULL;
   1845       1.49     lukem }
   1846       1.49     lukem 
   1847       1.49     lukem int
   1848       1.49     lukem getgrnam_r(const char *name, struct group *grp, char *buffer, size_t buflen,
   1849       1.49     lukem 	struct group **result)
   1850       1.49     lukem {
   1851       1.49     lukem 	int	rv, retval;
   1852       1.49     lukem 
   1853       1.49     lukem 	static const ns_dtab dtab[] = {
   1854       1.49     lukem 		NS_FILES_CB(_files_getgrnam_r, NULL)
   1855       1.49     lukem 		NS_DNS_CB(_dns_getgrnam_r, NULL)
   1856       1.49     lukem 		NS_NIS_CB(_nis_getgrnam_r, NULL)
   1857       1.49     lukem 		NS_COMPAT_CB(_compat_getgrnam_r, NULL)
   1858       1.60  christos 		NS_NULL_CB
   1859       1.49     lukem 	};
   1860       1.49     lukem 
   1861       1.49     lukem 	_DIAGASSERT(name != NULL);
   1862       1.49     lukem 	_DIAGASSERT(grp != NULL);
   1863       1.49     lukem 	_DIAGASSERT(buffer != NULL);
   1864       1.49     lukem 	_DIAGASSERT(result != NULL);
   1865       1.49     lukem 
   1866       1.49     lukem 	*result = NULL;
   1867       1.49     lukem 	retval = 0;
   1868       1.54     lukem 	mutex_lock(&__grmutex);
   1869       1.53     lukem 	rv = nsdispatch(NULL, dtab, NSDB_GROUP, "getgrnam_r", __nsdefaultcompat,
   1870       1.49     lukem 	    &retval, name, grp, buffer, buflen, result);
   1871       1.54     lukem 	mutex_unlock(&__grmutex);
   1872       1.57     lukem 	switch (rv) {
   1873       1.57     lukem 	case NS_SUCCESS:
   1874       1.57     lukem 	case NS_NOTFOUND:
   1875       1.57     lukem 		return 0;
   1876       1.57     lukem 	default:
   1877       1.57     lukem 		return retval;
   1878       1.57     lukem 	}
   1879       1.49     lukem }
   1880       1.49     lukem 
   1881       1.49     lukem void
   1882       1.49     lukem endgrent(void)
   1883       1.49     lukem {
   1884       1.49     lukem 	static const ns_dtab dtab[] = {
   1885       1.49     lukem 		NS_FILES_CB(_files_endgrent, NULL)
   1886       1.49     lukem 		NS_DNS_CB(_dns_endgrent, NULL)
   1887       1.49     lukem 		NS_NIS_CB(_nis_endgrent, NULL)
   1888       1.49     lukem 		NS_COMPAT_CB(_compat_endgrent, NULL)
   1889       1.60  christos 		NS_NULL_CB
   1890       1.49     lukem 	};
   1891       1.49     lukem 
   1892       1.54     lukem 	mutex_lock(&__grmutex);
   1893       1.49     lukem 					/* force all endgrent() methods */
   1894       1.49     lukem 	(void) nsdispatch(NULL, dtab, NSDB_GROUP, "endgrent",
   1895       1.53     lukem 	    __nsdefaultcompat_forceall);
   1896       1.54     lukem 	mutex_unlock(&__grmutex);
   1897       1.49     lukem }
   1898       1.49     lukem 
   1899       1.49     lukem int
   1900       1.49     lukem setgroupent(int stayopen)
   1901       1.49     lukem {
   1902       1.49     lukem 	static const ns_dtab dtab[] = {
   1903       1.49     lukem 		NS_FILES_CB(_files_setgroupent, NULL)
   1904       1.49     lukem 		NS_DNS_CB(_dns_setgroupent, NULL)
   1905       1.49     lukem 		NS_NIS_CB(_nis_setgroupent, NULL)
   1906       1.49     lukem 		NS_COMPAT_CB(_compat_setgroupent, NULL)
   1907       1.60  christos 		NS_NULL_CB
   1908       1.49     lukem 	};
   1909       1.49     lukem 	int	rv, retval;
   1910       1.49     lukem 
   1911       1.54     lukem 	mutex_lock(&__grmutex);
   1912       1.49     lukem 					/* force all setgroupent() methods */
   1913       1.49     lukem 	rv = nsdispatch(NULL, dtab, NSDB_GROUP, "setgroupent",
   1914       1.53     lukem 	    __nsdefaultcompat_forceall, &retval, stayopen);
   1915       1.54     lukem 	mutex_unlock(&__grmutex);
   1916       1.49     lukem 	return (rv == NS_SUCCESS) ? retval : 0;
   1917       1.49     lukem }
   1918       1.37     lukem 
   1919       1.49     lukem void
   1920       1.49     lukem setgrent(void)
   1921       1.49     lukem {
   1922       1.49     lukem 	static const ns_dtab dtab[] = {
   1923       1.49     lukem 		NS_FILES_CB(_files_setgrent, NULL)
   1924       1.49     lukem 		NS_DNS_CB(_dns_setgrent, NULL)
   1925       1.49     lukem 		NS_NIS_CB(_nis_setgrent, NULL)
   1926       1.49     lukem 		NS_COMPAT_CB(_compat_setgrent, NULL)
   1927       1.60  christos 		NS_NULL_CB
   1928       1.49     lukem 	};
   1929       1.27     lukem 
   1930       1.54     lukem 	mutex_lock(&__grmutex);
   1931       1.49     lukem 					/* force all setgrent() methods */
   1932       1.49     lukem 	(void) nsdispatch(NULL, dtab, NSDB_GROUP, "setgrent",
   1933       1.53     lukem 	    __nsdefaultcompat_forceall);
   1934       1.54     lukem 	mutex_unlock(&__grmutex);
   1935        1.1       cgd }
   1936