[BACK]Return to getgrent.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / lib / libc / gen

Annotation of src/lib/libc/gen/getgrent.c, Revision 1.54.2.4

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

CVSweb <webmaster@jp.NetBSD.org>