1 /* $NetBSD: getgrent.c,v 1.67 2012/08/29 18:50:35 dholland Exp $ */
4 * Copyright (c) 1999-2000, 2004-2005 The NetBSD Foundation, Inc.
7 * This code is derived from software contributed to The NetBSD Foundation
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
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.
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
33 * Copyright (c) 1989, 1993
34 * The Regents of the University of California. All rights reserved.
36 * Redistribution and use in source and binary forms, with or without
37 * modification, are permitted provided that the following conditions
39 * 1. Redistributions of source code must retain the above copyright
40 * notice, this list of conditions and the following disclaimer.
41 * 2. Redistributions in binary form must reproduce the above copyright
42 * notice, this list of conditions and the following disclaimer in the
43 * documentation and/or other materials provided with the distribution.
44 * 3. Neither the name of the University nor the names of its contributors
45 * may be used to endorse or promote products derived from this software
46 * without specific prior written permission.
48 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
49 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
50 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
51 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
52 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
53 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
54 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
55 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
56 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
57 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
62 * Portions Copyright (c) 1994, Jason Downs. All Rights Reserved.
64 * Redistribution and use in source and binary forms, with or without
65 * modification, are permitted provided that the following conditions
67 * 1. Redistributions of source code must retain the above copyright
68 * notice, this list of conditions and the following disclaimer.
69 * 2. Redistributions in binary form must reproduce the above copyright
70 * notice, this list of conditions and the following disclaimer in the
71 * documentation and/or other materials provided with the distribution.
73 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS
74 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
75 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
76 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT,
77 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
78 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
79 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
80 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
81 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
82 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
86 #include <sys/cdefs.h>
87 #if defined(LIBC_SCCS) && !defined(lint)
89 static char sccsid
[] = "@(#)getgrent.c 8.2 (Berkeley) 3/21/94";
91 __RCSID("$NetBSD: getgrent.c,v 1.67 2012/08/29 18:50:35 dholland Exp $");
93 #endif /* LIBC_SCCS and not lint */
95 #include "namespace.h"
96 #include "reentrant.h"
98 #include <sys/param.h>
104 #include <nsswitch.h>
117 #include <rpcsvc/yp_prot.h>
118 #include <rpcsvc/ypclnt.h>
121 #include "gr_private.h"
124 __weak_alias(endgrent
,_endgrent
)
125 __weak_alias(getgrent
,_getgrent
)
126 __weak_alias(getgrent_r
,_getgrent_r
)
127 __weak_alias(getgrgid
,_getgrgid
)
128 __weak_alias(getgrgid_r
,_getgrgid_r
)
129 __weak_alias(getgrnam
,_getgrnam
)
130 __weak_alias(getgrnam_r
,_getgrnam_r
)
131 __weak_alias(setgrent
,_setgrent
)
132 __weak_alias(setgroupent
,_setgroupent
)
136 mutex_t __grmutex
= MUTEX_INITIALIZER
;
141 * Obtain want bytes from buffer (of size buflen) and return a pointer
142 * to the available memory after adjusting buffer/buflen.
143 * Returns NULL if there is insufficient space.
146 _gr_memfrombuf(size_t want
, char **buffer
, size_t *buflen
)
150 if (want
> *buflen
) {
162 * Parses entry as a line per group(5) (without the trailing \n)
163 * and fills in grp with corresponding values; memory for strings
164 * and arrays will be allocated from buf (of size buflen).
165 * Returns 1 if parsed successfully, 0 on parse failure.
168 _gr_parse(const char *entry
, struct group
*grp
, char *buf
, size_t buflen
)
176 _DIAGASSERT(entry
!= NULL
);
177 _DIAGASSERT(grp
!= NULL
);
178 _DIAGASSERT(buf
!= NULL
);
180 #define COPYTOBUF(to) \
182 (to) = _gr_memfrombuf(count+1, &buf, &buflen); \
185 memmove((to), entry, count); \
187 } while (0) /* LINTED */
190 if (*entry
== '+') /* fail on compat `+' token */
194 count
= strcspn(entry
, ":"); /* parse gr_name */
195 if (entry
[count
] == '\0')
197 COPYTOBUF(grp
->gr_name
);
200 count
= strcspn(entry
, ":"); /* parse gr_passwd */
201 if (entry
[count
] == '\0')
203 COPYTOBUF(grp
->gr_passwd
);
206 count
= strcspn(entry
, ":"); /* parse gr_gid */
207 if (entry
[count
] == '\0')
209 id
= strtoul(entry
, &ep
, 10);
210 if (id
> GID_MAX
|| *ep
!= ':')
212 grp
->gr_gid
= (gid_t
)id
;
215 memc
= 1; /* for final NULL */
217 memc
++; /* for first item */
218 for (bp
= entry
; *bp
!= '\0'; bp
++) {
222 /* grab ALIGNed char **gr_mem from buf */
223 ep
= _gr_memfrombuf(memc
* sizeof(char *) + ALIGNBYTES
, &buf
, &buflen
);
226 grp
->gr_mem
= (char **)ALIGN(ep
);
228 for (memc
= 0; *entry
!= '\0'; memc
++) {
229 count
= strcspn(entry
, ","); /* parse member */
230 COPYTOBUF(grp
->gr_mem
[memc
]);
238 grp
->gr_mem
[memc
] = NULL
;
244 * Copy the contents of fromgrp to grp; memory for strings
245 * and arrays will be allocated from buf (of size buflen).
246 * Returns 1 if copied successfully, 0 on copy failure.
247 * NOTE: fromgrp must not use buf for its own pointers.
250 _gr_copy(struct group
*fromgrp
, struct group
*grp
, char *buf
, size_t buflen
)
255 _DIAGASSERT(fromgrp
!= NULL
);
256 _DIAGASSERT(grp
!= NULL
);
257 _DIAGASSERT(buf
!= NULL
);
259 #define COPYSTR(to, from) \
261 size_t count = strlen((from)); \
262 (to) = _gr_memfrombuf(count+1, &buf, &buflen); \
265 memmove((to), (from), count); \
267 } while (0) /* LINTED */
269 COPYSTR(grp
->gr_name
, fromgrp
->gr_name
);
270 COPYSTR(grp
->gr_passwd
, fromgrp
->gr_passwd
);
271 grp
->gr_gid
= fromgrp
->gr_gid
;
273 if (fromgrp
->gr_mem
== NULL
)
276 for (memc
= 0; fromgrp
->gr_mem
[memc
]; memc
++)
278 memc
++; /* for final NULL */
280 /* grab ALIGNed char **gr_mem from buf */
281 ep
= _gr_memfrombuf(memc
* sizeof(char *) + ALIGNBYTES
, &buf
, &buflen
);
282 grp
->gr_mem
= (char **)ALIGN(ep
);
283 if (grp
->gr_mem
== NULL
)
286 for (memc
= 0; fromgrp
->gr_mem
[memc
]; memc
++) {
287 COPYSTR(grp
->gr_mem
[memc
], fromgrp
->gr_mem
[memc
]);
292 grp
->gr_mem
[memc
] = NULL
;
301 __grstart_files(struct __grstate_files
*state
)
304 _DIAGASSERT(state
!= NULL
);
306 if (state
->fp
== NULL
) {
307 state
->fp
= fopen(_PATH_GROUP
, "re");
308 if (state
->fp
== NULL
)
317 __grend_files(struct __grstate_files
*state
)
320 _DIAGASSERT(state
!= NULL
);
323 (void) fclose(state
->fp
);
331 * Scan state->fp for the next desired entry.
332 * If search is zero, return the next entry.
333 * If search is non-zero, look for a specific name (if name != NULL),
334 * or a specific gid (if name == NULL).
335 * Sets *retval to the errno if the result is not NS_SUCCESS
339 __grscan_files(int *retval
, struct group
*grp
, char *buffer
, size_t buflen
,
340 struct __grstate_files
*state
, int search
, const char *name
, gid_t gid
)
343 char filebuf
[_GETGR_R_SIZE_MAX
], *ep
;
345 _DIAGASSERT(retval
!= NULL
);
346 _DIAGASSERT(grp
!= NULL
);
347 _DIAGASSERT(buffer
!= NULL
);
348 _DIAGASSERT(state
!= NULL
);
349 /* name is NULL to indicate searching for gid */
353 if (state
->fp
== NULL
) { /* only start if file not open yet */
354 rv
= __grstart_files(state
);
355 if (rv
!= NS_SUCCESS
)
356 goto filesgrscan_out
;
361 /* scan line by line */
362 while (fgets(filebuf
, (int)sizeof(filebuf
), state
->fp
) != NULL
) {
363 ep
= strchr(filebuf
, '\n');
364 if (ep
== NULL
) { /* skip lines that are too big */
367 while ((ch
= getc(state
->fp
)) != '\n' && ch
!= EOF
)
371 *ep
= '\0'; /* clear trailing \n */
373 if (filebuf
[0] == '+') /* skip compat line */
377 if (! _gr_parse(filebuf
, grp
, buffer
, buflen
)) {
378 continue; /* skip bad lines */
380 if (! search
) { /* just want this one */
385 if ((name
&& strcmp(name
, grp
->gr_name
) == 0) ||
386 (!name
&& gid
== grp
->gr_gid
)) {
393 if (rv
!= NS_SUCCESS
&& rv
!= NS_NOTFOUND
)
399 static struct __grstate_files _files_state
;
400 /* storage for non _r functions */
401 static struct group _files_group
;
402 static char _files_groupbuf
[_GETGR_R_SIZE_MAX
];
406 _files_setgrent(void *nsrv
, void *nscb
, va_list ap
)
409 _files_state
.stayopen
= 0;
410 return __grstart_files(&_files_state
);
415 _files_setgroupent(void *nsrv
, void *nscb
, va_list ap
)
417 int *retval
= va_arg(ap
, int *);
418 int stayopen
= va_arg(ap
, int);
422 _files_state
.stayopen
= stayopen
;
423 rv
= __grstart_files(&_files_state
);
424 *retval
= (rv
== NS_SUCCESS
);
430 _files_endgrent(void *nsrv
, void *nscb
, va_list ap
)
433 _files_state
.stayopen
= 0;
434 return __grend_files(&_files_state
);
439 _files_getgrent(void *nsrv
, void *nscb
, va_list ap
)
441 struct group
**retval
= va_arg(ap
, struct group
**);
445 _DIAGASSERT(retval
!= NULL
);
448 rv
= __grscan_files(&rerror
, &_files_group
,
449 _files_groupbuf
, sizeof(_files_groupbuf
),
450 &_files_state
, 0, NULL
, 0);
451 if (rv
== NS_SUCCESS
)
452 *retval
= &_files_group
;
458 _files_getgrent_r(void *nsrv
, void *nscb
, va_list ap
)
460 int *retval
= va_arg(ap
, int *);
461 struct group
*grp
= va_arg(ap
, struct group
*);
462 char *buffer
= va_arg(ap
, char *);
463 size_t buflen
= va_arg(ap
, size_t);
464 struct group
**result
= va_arg(ap
, struct group
**);
468 _DIAGASSERT(retval
!= NULL
);
469 _DIAGASSERT(grp
!= NULL
);
470 _DIAGASSERT(buffer
!= NULL
);
471 _DIAGASSERT(result
!= NULL
);
473 rv
= __grscan_files(retval
, grp
, buffer
, buflen
,
474 &_files_state
, 0, NULL
, 0);
475 if (rv
== NS_SUCCESS
)
484 _files_getgrgid(void *nsrv
, void *nscb
, va_list ap
)
486 struct group
**retval
= va_arg(ap
, struct group
**);
487 gid_t gid
= va_arg(ap
, gid_t
);
491 _DIAGASSERT(retval
!= NULL
);
494 rv
= __grstart_files(&_files_state
);
495 if (rv
!= NS_SUCCESS
)
497 rv
= __grscan_files(&rerror
, &_files_group
,
498 _files_groupbuf
, sizeof(_files_groupbuf
),
499 &_files_state
, 1, NULL
, gid
);
500 if (!_files_state
.stayopen
)
501 __grend_files(&_files_state
);
502 if (rv
== NS_SUCCESS
)
503 *retval
= &_files_group
;
509 _files_getgrgid_r(void *nsrv
, void *nscb
, va_list ap
)
511 int *retval
= va_arg(ap
, int *);
512 gid_t gid
= va_arg(ap
, gid_t
);
513 struct group
*grp
= va_arg(ap
, struct group
*);
514 char *buffer
= va_arg(ap
, char *);
515 size_t buflen
= va_arg(ap
, size_t);
516 struct group
**result
= va_arg(ap
, struct group
**);
518 struct __grstate_files state
;
521 _DIAGASSERT(retval
!= NULL
);
522 _DIAGASSERT(grp
!= NULL
);
523 _DIAGASSERT(buffer
!= NULL
);
524 _DIAGASSERT(result
!= NULL
);
527 memset(&state
, 0, sizeof(state
));
528 rv
= __grscan_files(retval
, grp
, buffer
, buflen
, &state
, 1, NULL
, gid
);
529 __grend_files(&state
);
530 if (rv
== NS_SUCCESS
)
537 _files_getgrnam(void *nsrv
, void *nscb
, va_list ap
)
539 struct group
**retval
= va_arg(ap
, struct group
**);
540 const char *name
= va_arg(ap
, const char *);
544 _DIAGASSERT(retval
!= NULL
);
547 rv
= __grstart_files(&_files_state
);
548 if (rv
!= NS_SUCCESS
)
550 rv
= __grscan_files(&rerror
, &_files_group
,
551 _files_groupbuf
, sizeof(_files_groupbuf
),
552 &_files_state
, 1, name
, 0);
553 if (!_files_state
.stayopen
)
554 __grend_files(&_files_state
);
555 if (rv
== NS_SUCCESS
)
556 *retval
= &_files_group
;
562 _files_getgrnam_r(void *nsrv
, void *nscb
, va_list ap
)
564 int *retval
= va_arg(ap
, int *);
565 const char *name
= va_arg(ap
, const char *);
566 struct group
*grp
= va_arg(ap
, struct group
*);
567 char *buffer
= va_arg(ap
, char *);
568 size_t buflen
= va_arg(ap
, size_t);
569 struct group
**result
= va_arg(ap
, struct group
**);
571 struct __grstate_files state
;
574 _DIAGASSERT(retval
!= NULL
);
575 _DIAGASSERT(grp
!= NULL
);
576 _DIAGASSERT(buffer
!= NULL
);
577 _DIAGASSERT(result
!= NULL
);
580 memset(&state
, 0, sizeof(state
));
581 rv
= __grscan_files(retval
, grp
, buffer
, buflen
, &state
, 1, name
, 0);
582 __grend_files(&state
);
583 if (rv
== NS_SUCCESS
)
595 __grstart_dns(struct __grstate_dns
*state
)
598 _DIAGASSERT(state
!= NULL
);
601 if (state
->context
== NULL
) { /* setup Hesiod */
602 if (hesiod_init(&state
->context
) == -1)
610 __grend_dns(struct __grstate_dns
*state
)
613 _DIAGASSERT(state
!= NULL
);
616 if (state
->context
) {
617 hesiod_end(state
->context
);
618 state
->context
= NULL
;
625 * Search Hesiod for the next desired entry.
626 * If search is zero, return the next entry.
627 * If search is non-zero, look for a specific name (if name != NULL),
628 * or a specific gid (if name == NULL).
631 __grscan_dns(int *retval
, struct group
*grp
, char *buffer
, size_t buflen
,
632 struct __grstate_dns
*state
, int search
, const char *name
, gid_t gid
)
634 const char **curzone
;
638 static const char *zones_gid_group
[] = {
644 static const char *zones_group
[] = {
649 _DIAGASSERT(retval
!= NULL
);
650 _DIAGASSERT(grp
!= NULL
);
651 _DIAGASSERT(buffer
!= NULL
);
652 _DIAGASSERT(state
!= NULL
);
653 /* name is NULL to indicate searching for gid */
657 if (state
->context
== NULL
) { /* only start if Hesiod not setup */
658 rv
= __grstart_dns(state
);
659 if (rv
!= NS_SUCCESS
)
667 if (! search
) { /* find next entry */
668 if (state
->num
== -1) /* exhausted search */
671 snprintf(buffer
, buflen
, "group-%u", state
->num
);
673 curzone
= zones_group
;
674 } else if (name
) { /* find group name */
675 snprintf(buffer
, buflen
, "%s", name
);
676 curzone
= zones_group
;
677 } else { /* find gid */
678 snprintf(buffer
, buflen
, "%u", (unsigned int)gid
);
679 curzone
= zones_gid_group
;
682 for (; *curzone
; curzone
++) { /* search zones */
683 hp
= hesiod_resolve(state
->context
, buffer
, *curzone
);
686 if (errno
!= ENOENT
) {
691 if (*curzone
== NULL
) {
697 if ((ep
= strchr(hp
[0], '\n')) != NULL
)
698 *ep
= '\0'; /* clear trailing \n */
699 if (_gr_parse(hp
[0], grp
, buffer
, buflen
)) { /* validate line */
700 if (! search
) { /* just want this one */
702 } else if ((name
&& strcmp(name
, grp
->gr_name
) == 0) ||
703 (!name
&& gid
== grp
->gr_gid
)) { /* want specific */
706 } else { /* dodgy entry */
707 if (!search
) { /* try again if ! searching */
708 hesiod_free_list(state
->context
, hp
);
714 if (rv
!= NS_SUCCESS
&& rv
!= NS_NOTFOUND
)
717 hesiod_free_list(state
->context
, hp
);
721 static struct __grstate_dns _dns_state
;
722 /* storage for non _r functions */
723 static struct group _dns_group
;
724 static char _dns_groupbuf
[_GETGR_R_SIZE_MAX
];
728 _dns_setgrent(void *nsrv
, void *nscb
, va_list ap
)
731 _dns_state
.stayopen
= 0;
732 return __grstart_dns(&_dns_state
);
737 _dns_setgroupent(void *nsrv
, void *nscb
, va_list ap
)
739 int *retval
= va_arg(ap
, int *);
740 int stayopen
= va_arg(ap
, int);
744 _dns_state
.stayopen
= stayopen
;
745 rv
= __grstart_dns(&_dns_state
);
746 *retval
= (rv
== NS_SUCCESS
);
752 _dns_endgrent(void *nsrv
, void *nscb
, va_list ap
)
755 _dns_state
.stayopen
= 0;
756 return __grend_dns(&_dns_state
);
761 _dns_getgrent(void *nsrv
, void *nscb
, va_list ap
)
763 struct group
**retval
= va_arg(ap
, struct group
**);
767 _DIAGASSERT(retval
!= NULL
);
770 rv
= __grscan_dns(&rerror
, &_dns_group
,
771 _dns_groupbuf
, sizeof(_dns_groupbuf
), &_dns_state
, 0, NULL
, 0);
772 if (rv
== NS_SUCCESS
)
773 *retval
= &_dns_group
;
779 _dns_getgrent_r(void *nsrv
, void *nscb
, va_list ap
)
781 int *retval
= va_arg(ap
, int *);
782 struct group
*grp
= va_arg(ap
, struct group
*);
783 char *buffer
= va_arg(ap
, char *);
784 size_t buflen
= va_arg(ap
, size_t);
785 struct group
**result
= va_arg(ap
, struct group
**);
789 _DIAGASSERT(retval
!= NULL
);
790 _DIAGASSERT(grp
!= NULL
);
791 _DIAGASSERT(buffer
!= NULL
);
792 _DIAGASSERT(result
!= NULL
);
794 rv
= __grscan_dns(retval
, grp
, buffer
, buflen
,
795 &_dns_state
, 0, NULL
, 0);
796 if (rv
== NS_SUCCESS
)
804 _dns_getgrgid(void *nsrv
, void *nscb
, va_list ap
)
806 struct group
**retval
= va_arg(ap
, struct group
**);
807 gid_t gid
= va_arg(ap
, gid_t
);
811 _DIAGASSERT(retval
!= NULL
);
814 rv
= __grstart_dns(&_dns_state
);
815 if (rv
!= NS_SUCCESS
)
817 rv
= __grscan_dns(&rerror
, &_dns_group
,
818 _dns_groupbuf
, sizeof(_dns_groupbuf
), &_dns_state
, 1, NULL
, gid
);
819 if (!_dns_state
.stayopen
)
820 __grend_dns(&_dns_state
);
821 if (rv
== NS_SUCCESS
)
822 *retval
= &_dns_group
;
828 _dns_getgrgid_r(void *nsrv
, void *nscb
, va_list ap
)
830 int *retval
= va_arg(ap
, int *);
831 gid_t gid
= va_arg(ap
, gid_t
);
832 struct group
*grp
= va_arg(ap
, struct group
*);
833 char *buffer
= va_arg(ap
, char *);
834 size_t buflen
= va_arg(ap
, size_t);
835 struct group
**result
= va_arg(ap
, struct group
**);
837 struct __grstate_dns state
;
840 _DIAGASSERT(retval
!= NULL
);
841 _DIAGASSERT(grp
!= NULL
);
842 _DIAGASSERT(buffer
!= NULL
);
843 _DIAGASSERT(result
!= NULL
);
846 memset(&state
, 0, sizeof(state
));
847 rv
= __grscan_dns(retval
, grp
, buffer
, buflen
, &state
, 1, NULL
, gid
);
849 if (rv
== NS_SUCCESS
)
856 _dns_getgrnam(void *nsrv
, void *nscb
, va_list ap
)
858 struct group
**retval
= va_arg(ap
, struct group
**);
859 const char *name
= va_arg(ap
, const char *);
863 _DIAGASSERT(retval
!= NULL
);
866 rv
= __grstart_dns(&_dns_state
);
867 if (rv
!= NS_SUCCESS
)
869 rv
= __grscan_dns(&rerror
, &_dns_group
,
870 _dns_groupbuf
, sizeof(_dns_groupbuf
), &_dns_state
, 1, name
, 0);
871 if (!_dns_state
.stayopen
)
872 __grend_dns(&_dns_state
);
873 if (rv
== NS_SUCCESS
)
874 *retval
= &_dns_group
;
880 _dns_getgrnam_r(void *nsrv
, void *nscb
, va_list ap
)
882 int *retval
= va_arg(ap
, int *);
883 const char *name
= va_arg(ap
, const char *);
884 struct group
*grp
= va_arg(ap
, struct group
*);
885 char *buffer
= va_arg(ap
, char *);
886 size_t buflen
= va_arg(ap
, size_t);
887 struct group
**result
= va_arg(ap
, struct group
**);
889 struct __grstate_dns state
;
892 _DIAGASSERT(retval
!= NULL
);
893 _DIAGASSERT(grp
!= NULL
);
894 _DIAGASSERT(buffer
!= NULL
);
895 _DIAGASSERT(result
!= NULL
);
898 memset(&state
, 0, sizeof(state
));
899 rv
= __grscan_dns(retval
, grp
, buffer
, buflen
, &state
, 1, name
, 0);
901 if (rv
== NS_SUCCESS
)
915 __grstart_nis(struct __grstate_nis
*state
)
918 _DIAGASSERT(state
!= NULL
);
921 if (state
->current
) {
922 free(state
->current
);
923 state
->current
= NULL
;
925 if (state
->domain
== NULL
) { /* setup NIS */
926 switch (yp_get_default_domain(&state
->domain
)) {
939 __grend_nis(struct __grstate_nis
*state
)
942 _DIAGASSERT(state
!= NULL
);
945 state
->domain
= NULL
;
948 if (state
->current
) {
949 free(state
->current
);
950 state
->current
= NULL
;
957 * Search NIS for the next desired entry.
958 * If search is zero, return the next entry.
959 * If search is non-zero, look for a specific name (if name != NULL),
960 * or a specific gid (if name == NULL).
963 __grscan_nis(int *retval
, struct group
*grp
, char *buffer
, size_t buflen
,
964 struct __grstate_nis
*state
, int search
, const char *name
, gid_t gid
)
968 int nisr
, rv
, keylen
, datalen
;
970 _DIAGASSERT(retval
!= NULL
);
971 _DIAGASSERT(grp
!= NULL
);
972 _DIAGASSERT(buffer
!= NULL
);
973 _DIAGASSERT(state
!= NULL
);
974 /* name is NULL to indicate searching for gid */
978 if (state
->domain
== NULL
) { /* only start if NIS not setup */
979 rv
= __grstart_nis(state
);
980 if (rv
!= NS_SUCCESS
)
989 if (! search
) { /* find next entry */
990 if (state
->done
) /* exhausted search */
992 map
= "group.byname";
993 if (state
->current
) { /* already searching */
994 nisr
= yp_next(state
->domain
, map
,
995 state
->current
, state
->currentlen
,
996 &key
, &keylen
, &data
, &datalen
);
997 free(state
->current
);
998 state
->current
= NULL
;
1001 state
->current
= key
;
1002 state
->currentlen
= keylen
;
1013 } else { /* new search */
1014 if (yp_first(state
->domain
, map
,
1015 &state
->current
, &state
->currentlen
,
1020 } else { /* search for specific item */
1021 if (name
) { /* find group name */
1022 snprintf(buffer
, buflen
, "%s", name
);
1023 map
= "group.byname";
1024 } else { /* find gid */
1025 snprintf(buffer
, buflen
, "%u", (unsigned int)gid
);
1026 map
= "group.bygid";
1028 nisr
= yp_match(state
->domain
, map
, buffer
, (int)strlen(buffer
),
1041 if (rv
== NS_SUCCESS
) { /* validate data */
1042 data
[datalen
] = '\0'; /* clear trailing \n */
1043 if (_gr_parse(data
, grp
, buffer
, buflen
)) {
1044 if (! search
) { /* just want this one */
1046 } else if ((name
&& strcmp(name
, grp
->gr_name
) == 0) ||
1047 (!name
&& gid
== grp
->gr_gid
)) {
1051 } else { /* dodgy entry */
1052 if (!search
) { /* try again if ! searching */
1054 goto next_nis_entry
;
1059 if (rv
!= NS_SUCCESS
&& rv
!= NS_NOTFOUND
)
1068 static struct __grstate_nis _nis_state
;
1069 /* storage for non _r functions */
1070 static struct group _nis_group
;
1071 static char _nis_groupbuf
[_GETGR_R_SIZE_MAX
];
1075 _nis_setgrent(void *nsrv
, void *nscb
, va_list ap
)
1078 _nis_state
.stayopen
= 0;
1079 return __grstart_nis(&_nis_state
);
1084 _nis_setgroupent(void *nsrv
, void *nscb
, va_list ap
)
1086 int *retval
= va_arg(ap
, int *);
1087 int stayopen
= va_arg(ap
, int);
1091 _nis_state
.stayopen
= stayopen
;
1092 rv
= __grstart_nis(&_nis_state
);
1093 *retval
= (rv
== NS_SUCCESS
);
1099 _nis_endgrent(void *nsrv
, void *nscb
, va_list ap
)
1102 return __grend_nis(&_nis_state
);
1107 _nis_getgrent(void *nsrv
, void *nscb
, va_list ap
)
1109 struct group
**retval
= va_arg(ap
, struct group
**);
1113 _DIAGASSERT(retval
!= NULL
);
1116 rv
= __grscan_nis(&rerror
, &_nis_group
,
1117 _nis_groupbuf
, sizeof(_nis_groupbuf
), &_nis_state
, 0, NULL
, 0);
1118 if (rv
== NS_SUCCESS
)
1119 *retval
= &_nis_group
;
1125 _nis_getgrent_r(void *nsrv
, void *nscb
, va_list ap
)
1127 int *retval
= va_arg(ap
, int *);
1128 struct group
*grp
= va_arg(ap
, struct group
*);
1129 char *buffer
= va_arg(ap
, char *);
1130 size_t buflen
= va_arg(ap
, size_t);
1131 struct group
**result
= va_arg(ap
, struct group
**);
1135 _DIAGASSERT(retval
!= NULL
);
1136 _DIAGASSERT(grp
!= NULL
);
1137 _DIAGASSERT(buffer
!= NULL
);
1138 _DIAGASSERT(result
!= NULL
);
1140 rv
= __grscan_nis(retval
, grp
, buffer
, buflen
,
1141 &_nis_state
, 0, NULL
, 0);
1142 if (rv
== NS_SUCCESS
)
1151 _nis_getgrgid(void *nsrv
, void *nscb
, va_list ap
)
1153 struct group
**retval
= va_arg(ap
, struct group
**);
1154 gid_t gid
= va_arg(ap
, gid_t
);
1158 _DIAGASSERT(retval
!= NULL
);
1161 rv
= __grstart_nis(&_nis_state
);
1162 if (rv
!= NS_SUCCESS
)
1164 rv
= __grscan_nis(&rerror
, &_nis_group
,
1165 _nis_groupbuf
, sizeof(_nis_groupbuf
), &_nis_state
, 1, NULL
, gid
);
1166 if (!_nis_state
.stayopen
)
1167 __grend_nis(&_nis_state
);
1168 if (rv
== NS_SUCCESS
)
1169 *retval
= &_nis_group
;
1175 _nis_getgrgid_r(void *nsrv
, void *nscb
, va_list ap
)
1177 int *retval
= va_arg(ap
, int *);
1178 gid_t gid
= va_arg(ap
, gid_t
);
1179 struct group
*grp
= va_arg(ap
, struct group
*);
1180 char *buffer
= va_arg(ap
, char *);
1181 size_t buflen
= va_arg(ap
, size_t);
1182 struct group
**result
= va_arg(ap
, struct group
**);
1184 struct __grstate_nis state
;
1187 _DIAGASSERT(retval
!= NULL
);
1188 _DIAGASSERT(grp
!= NULL
);
1189 _DIAGASSERT(buffer
!= NULL
);
1190 _DIAGASSERT(result
!= NULL
);
1193 /* remark: we run under a global mutex inside of this module ... */
1194 if (_nis_state
.stayopen
)
1195 { /* use global state only if stayopen is set - otherwiese we would blow up getgrent_r() ... */
1196 rv
= __grscan_nis(retval
, grp
, buffer
, buflen
, &_nis_state
, 1, NULL
, gid
);
1200 memset(&state
, 0, sizeof(state
));
1201 rv
= __grscan_nis(retval
, grp
, buffer
, buflen
, &state
, 1, NULL
, gid
);
1202 __grend_nis(&state
);
1204 if (rv
== NS_SUCCESS
)
1211 _nis_getgrnam(void *nsrv
, void *nscb
, va_list ap
)
1213 struct group
**retval
= va_arg(ap
, struct group
**);
1214 const char *name
= va_arg(ap
, const char *);
1218 _DIAGASSERT(retval
!= NULL
);
1221 rv
= __grstart_nis(&_nis_state
);
1222 if (rv
!= NS_SUCCESS
)
1224 rv
= __grscan_nis(&rerror
, &_nis_group
,
1225 _nis_groupbuf
, sizeof(_nis_groupbuf
), &_nis_state
, 1, name
, 0);
1226 if (!_nis_state
.stayopen
)
1227 __grend_nis(&_nis_state
);
1228 if (rv
== NS_SUCCESS
)
1229 *retval
= &_nis_group
;
1235 _nis_getgrnam_r(void *nsrv
, void *nscb
, va_list ap
)
1237 int *retval
= va_arg(ap
, int *);
1238 const char *name
= va_arg(ap
, const char *);
1239 struct group
*grp
= va_arg(ap
, struct group
*);
1240 char *buffer
= va_arg(ap
, char *);
1241 size_t buflen
= va_arg(ap
, size_t);
1242 struct group
**result
= va_arg(ap
, struct group
**);
1244 struct __grstate_nis state
;
1247 _DIAGASSERT(retval
!= NULL
);
1248 _DIAGASSERT(grp
!= NULL
);
1249 _DIAGASSERT(buffer
!= NULL
);
1250 _DIAGASSERT(result
!= NULL
);
1253 /* remark: we run under a global mutex inside of this module ... */
1254 if (_nis_state
.stayopen
)
1255 { /* use global state only if stayopen is set - otherwiese we would blow up getgrent_r() ... */
1256 rv
= __grscan_nis(retval
, grp
, buffer
, buflen
, &_nis_state
, 1, name
, 0);
1260 memset(&state
, 0, sizeof(state
));
1261 rv
= __grscan_nis(retval
, grp
, buffer
, buflen
, &state
, 1, name
, 0);
1262 __grend_nis(&state
);
1264 if (rv
== NS_SUCCESS
)
1272 #ifdef _GROUP_COMPAT
1278 __grstart_compat(struct __grstate_compat
*state
)
1281 _DIAGASSERT(state
!= NULL
);
1283 if (state
->fp
== NULL
) {
1284 state
->fp
= fopen(_PATH_GROUP
, "re");
1285 if (state
->fp
== NULL
)
1294 __grend_compat(struct __grstate_compat
*state
)
1297 _DIAGASSERT(state
!= NULL
);
1304 (void) fclose(state
->fp
);
1313 * log an error if "files" or "compat" is specified in
1314 * group_compat database
1318 __grbad_compat(void *nsrv
, void *nscb
, va_list ap
)
1322 _DIAGASSERT(nsrv
!= NULL
);
1323 _DIAGASSERT(nscb
!= NULL
);
1327 "nsswitch.conf group_compat database can't use '%s'",
1328 (const char *)nscb
);
1336 * Scan state->fp for the next desired entry.
1337 * If search is zero, return the next entry.
1338 * If search is non-zero, look for a specific name (if name != NULL),
1339 * or a specific gid (if name == NULL).
1340 * Sets *retval to the errno if the result is not NS_SUCCESS or
1343 * searchfunc is invoked when a compat "+" lookup is required;
1344 * searchcookie is passed as the first argument to searchfunc,
1345 * the second argument is the group result.
1346 * This should return NS_NOTFOUND when "no more groups" from compat src.
1347 * If searchfunc is NULL then nsdispatch of getgrent is used.
1348 * This is primarily intended for getgroupmembership(3)'s compat backend.
1351 __grscan_compat(int *retval
, struct group
*grp
, char *buffer
, size_t buflen
,
1352 struct __grstate_compat
*state
, int search
, const char *name
, gid_t gid
,
1353 int (*searchfunc
)(void *, struct group
**), void *searchcookie
)
1356 char filebuf
[_GETGR_R_SIZE_MAX
], *ep
;
1358 static const ns_dtab compatentdtab
[] = {
1359 NS_FILES_CB(__grbad_compat
, "files")
1360 NS_DNS_CB(_dns_getgrent_r
, NULL
)
1361 NS_NIS_CB(_nis_getgrent_r
, NULL
)
1362 NS_COMPAT_CB(__grbad_compat
, "compat")
1365 static const ns_dtab compatgiddtab
[] = {
1366 NS_FILES_CB(__grbad_compat
, "files")
1367 NS_DNS_CB(_dns_getgrgid_r
, NULL
)
1368 NS_NIS_CB(_nis_getgrgid_r
, NULL
)
1369 NS_COMPAT_CB(__grbad_compat
, "compat")
1372 static const ns_dtab compatnamdtab
[] = {
1373 NS_FILES_CB(__grbad_compat
, "files")
1374 NS_DNS_CB(_dns_getgrnam_r
, NULL
)
1375 NS_NIS_CB(_nis_getgrnam_r
, NULL
)
1376 NS_COMPAT_CB(__grbad_compat
, "compat")
1380 _DIAGASSERT(retval
!= NULL
);
1381 _DIAGASSERT(grp
!= NULL
);
1382 _DIAGASSERT(buffer
!= NULL
);
1383 _DIAGASSERT(state
!= NULL
);
1384 /* name is NULL to indicate searching for gid */
1388 if (state
->fp
== NULL
) { /* only start if file not open yet */
1389 rv
= __grstart_compat(state
);
1390 if (rv
!= NS_SUCCESS
)
1391 goto compatgrscan_out
;
1395 for (;;) { /* loop through file */
1396 if (state
->name
!= NULL
) {
1397 /* processing compat entry */
1399 struct group cgrp
, *cgrpres
;
1401 if (state
->name
[0]) { /* specific +group: */
1402 crv
= nsdispatch(NULL
, compatnamdtab
,
1403 NSDB_GROUP_COMPAT
, "getgrnam_r",
1405 &cretval
, state
->name
,
1406 &cgrp
, filebuf
, sizeof(filebuf
), &cgrpres
);
1407 free(state
->name
); /* (only check 1 grp) */
1409 } else if (!search
) { /* any group */
1411 crv
= searchfunc(searchcookie
,
1414 crv
= nsdispatch(NULL
, compatentdtab
,
1415 NSDB_GROUP_COMPAT
, "getgrent_r",
1417 &cretval
, &cgrp
, filebuf
,
1418 sizeof(filebuf
), &cgrpres
);
1420 } else if (name
) { /* specific group */
1421 crv
= nsdispatch(NULL
, compatnamdtab
,
1422 NSDB_GROUP_COMPAT
, "getgrnam_r",
1425 &cgrp
, filebuf
, sizeof(filebuf
), &cgrpres
);
1426 } else { /* specific gid */
1427 crv
= nsdispatch(NULL
, compatgiddtab
,
1428 NSDB_GROUP_COMPAT
, "getgrgid_r",
1431 &cgrp
, filebuf
, sizeof(filebuf
), &cgrpres
);
1433 if (crv
!= NS_SUCCESS
) { /* not found */
1436 continue; /* try next line */
1438 if (!_gr_copy(cgrpres
, grp
, buffer
, buflen
)) {
1442 goto compatgrscan_cmpgrp
; /* skip to grp test */
1445 /* get next file line */
1446 if (fgets(filebuf
, (int)sizeof(filebuf
), state
->fp
) == NULL
)
1449 ep
= strchr(filebuf
, '\n');
1450 if (ep
== NULL
) { /* skip lines that are too big */
1453 while ((ch
= getc(state
->fp
)) != '\n' && ch
!= EOF
)
1457 *ep
= '\0'; /* clear trailing \n */
1459 if (filebuf
[0] == '+') { /* parse compat line */
1463 switch(filebuf
[1]) {
1466 state
->name
= strdup("");
1469 ep
= strchr(filebuf
+ 1, ':');
1473 state
->name
= strdup(filebuf
+ 1);
1476 if (state
->name
== NULL
) {
1484 if (! _gr_parse(filebuf
, grp
, buffer
, buflen
)) {
1485 continue; /* skip bad lines */
1488 compatgrscan_cmpgrp
:
1489 if (! search
) { /* just want this one */
1494 if ((name
&& strcmp(name
, grp
->gr_name
) == 0) ||
1495 (!name
&& gid
== grp
->gr_gid
)) {
1503 if (rv
!= NS_SUCCESS
&& rv
!= NS_NOTFOUND
)
1508 static struct __grstate_compat _compat_state
;
1509 /* storage for non _r functions */
1510 static struct group _compat_group
;
1511 static char _compat_groupbuf
[_GETGR_R_SIZE_MAX
];
1515 _compat_setgrent(void *nsrv
, void *nscb
, va_list ap
)
1517 static const ns_dtab dtab
[] = {
1518 NS_FILES_CB(__grbad_compat
, "files")
1519 NS_DNS_CB(_dns_setgrent
, NULL
)
1520 NS_NIS_CB(_nis_setgrent
, NULL
)
1521 NS_COMPAT_CB(__grbad_compat
, "compat")
1525 /* force group_compat setgrent() */
1526 (void) nsdispatch(NULL
, dtab
, NSDB_GROUP_COMPAT
, "setgrent",
1527 __nsdefaultnis_forceall
);
1529 /* reset state, keep fp open */
1530 _compat_state
.stayopen
= 0;
1531 return __grstart_compat(&_compat_state
);
1536 _compat_setgroupent(void *nsrv
, void *nscb
, va_list ap
)
1538 int *retval
= va_arg(ap
, int *);
1539 int stayopen
= va_arg(ap
, int);
1543 static const ns_dtab dtab
[] = {
1544 NS_FILES_CB(__grbad_compat
, "files")
1545 NS_DNS_CB(_dns_setgroupent
, NULL
)
1546 NS_NIS_CB(_nis_setgroupent
, NULL
)
1547 NS_COMPAT_CB(__grbad_compat
, "compat")
1551 /* force group_compat setgroupent() */
1552 (void) nsdispatch(NULL
, dtab
, NSDB_GROUP_COMPAT
, "setgroupent",
1553 __nsdefaultnis_forceall
, &rv
, stayopen
);
1555 _compat_state
.stayopen
= stayopen
;
1556 rv
= __grstart_compat(&_compat_state
);
1557 *retval
= (rv
== NS_SUCCESS
);
1563 _compat_endgrent(void *nsrv
, void *nscb
, va_list ap
)
1565 static const ns_dtab dtab
[] = {
1566 NS_FILES_CB(__grbad_compat
, "files")
1567 NS_DNS_CB(_dns_endgrent
, NULL
)
1568 NS_NIS_CB(_nis_endgrent
, NULL
)
1569 NS_COMPAT_CB(__grbad_compat
, "compat")
1573 /* force group_compat endgrent() */
1574 (void) nsdispatch(NULL
, dtab
, NSDB_GROUP_COMPAT
, "endgrent",
1575 __nsdefaultnis_forceall
);
1577 /* reset state, close fp */
1578 _compat_state
.stayopen
= 0;
1579 return __grend_compat(&_compat_state
);
1584 _compat_getgrent(void *nsrv
, void *nscb
, va_list ap
)
1586 struct group
**retval
= va_arg(ap
, struct group
**);
1590 _DIAGASSERT(retval
!= NULL
);
1593 rv
= __grscan_compat(&rerror
, &_compat_group
,
1594 _compat_groupbuf
, sizeof(_compat_groupbuf
),
1595 &_compat_state
, 0, NULL
, 0, NULL
, NULL
);
1596 if (rv
== NS_SUCCESS
)
1597 *retval
= &_compat_group
;
1603 _compat_getgrent_r(void *nsrv
, void *nscb
, va_list ap
)
1605 int *retval
= va_arg(ap
, int *);
1606 struct group
*grp
= va_arg(ap
, struct group
*);
1607 char *buffer
= va_arg(ap
, char *);
1608 size_t buflen
= va_arg(ap
, size_t);
1609 struct group
**result
= va_arg(ap
, struct group
**);
1613 _DIAGASSERT(retval
!= NULL
);
1614 _DIAGASSERT(grp
!= NULL
);
1615 _DIAGASSERT(buffer
!= NULL
);
1616 _DIAGASSERT(result
!= NULL
);
1618 rv
= __grscan_compat(retval
, grp
, buffer
, buflen
,
1619 &_compat_state
, 0, NULL
, 0, NULL
, NULL
);
1620 if (rv
== NS_SUCCESS
)
1629 _compat_getgrgid(void *nsrv
, void *nscb
, va_list ap
)
1631 struct group
**retval
= va_arg(ap
, struct group
**);
1632 gid_t gid
= va_arg(ap
, gid_t
);
1636 _DIAGASSERT(retval
!= NULL
);
1639 rv
= __grstart_compat(&_compat_state
);
1640 if (rv
!= NS_SUCCESS
)
1642 rv
= __grscan_compat(&rerror
, &_compat_group
,
1643 _compat_groupbuf
, sizeof(_compat_groupbuf
),
1644 &_compat_state
, 1, NULL
, gid
, NULL
, NULL
);
1645 if (!_compat_state
.stayopen
)
1646 __grend_compat(&_compat_state
);
1647 if (rv
== NS_SUCCESS
)
1648 *retval
= &_compat_group
;
1654 _compat_getgrgid_r(void *nsrv
, void *nscb
, va_list ap
)
1656 int *retval
= va_arg(ap
, int *);
1657 gid_t gid
= va_arg(ap
, gid_t
);
1658 struct group
*grp
= va_arg(ap
, struct group
*);
1659 char *buffer
= va_arg(ap
, char *);
1660 size_t buflen
= va_arg(ap
, size_t);
1661 struct group
**result
= va_arg(ap
, struct group
**);
1663 struct __grstate_compat state
;
1666 _DIAGASSERT(retval
!= NULL
);
1667 _DIAGASSERT(grp
!= NULL
);
1668 _DIAGASSERT(buffer
!= NULL
);
1669 _DIAGASSERT(result
!= NULL
);
1672 memset(&state
, 0, sizeof(state
));
1673 rv
= __grscan_compat(retval
, grp
, buffer
, buflen
, &state
,
1674 1, NULL
, gid
, NULL
, NULL
);
1675 __grend_compat(&state
);
1676 if (rv
== NS_SUCCESS
)
1683 _compat_getgrnam(void *nsrv
, void *nscb
, va_list ap
)
1685 struct group
**retval
= va_arg(ap
, struct group
**);
1686 const char *name
= va_arg(ap
, const char *);
1690 _DIAGASSERT(retval
!= NULL
);
1693 rv
= __grstart_compat(&_compat_state
);
1694 if (rv
!= NS_SUCCESS
)
1696 rv
= __grscan_compat(&rerror
, &_compat_group
,
1697 _compat_groupbuf
, sizeof(_compat_groupbuf
),
1698 &_compat_state
, 1, name
, 0, NULL
, NULL
);
1699 if (!_compat_state
.stayopen
)
1700 __grend_compat(&_compat_state
);
1701 if (rv
== NS_SUCCESS
)
1702 *retval
= &_compat_group
;
1708 _compat_getgrnam_r(void *nsrv
, void *nscb
, va_list ap
)
1710 int *retval
= va_arg(ap
, int *);
1711 const char *name
= va_arg(ap
, const char *);
1712 struct group
*grp
= va_arg(ap
, struct group
*);
1713 char *buffer
= va_arg(ap
, char *);
1714 size_t buflen
= va_arg(ap
, size_t);
1715 struct group
**result
= va_arg(ap
, struct group
**);
1717 struct __grstate_compat state
;
1720 _DIAGASSERT(retval
!= NULL
);
1721 _DIAGASSERT(grp
!= NULL
);
1722 _DIAGASSERT(buffer
!= NULL
);
1723 _DIAGASSERT(result
!= NULL
);
1726 memset(&state
, 0, sizeof(state
));
1727 rv
= __grscan_compat(retval
, grp
, buffer
, buflen
, &state
,
1728 1, name
, 0, NULL
, NULL
);
1729 __grend_compat(&state
);
1730 if (rv
== NS_SUCCESS
)
1735 #endif /* _GROUP_COMPAT */
1746 struct group
*retval
;
1748 static const ns_dtab dtab
[] = {
1749 NS_FILES_CB(_files_getgrent
, NULL
)
1750 NS_DNS_CB(_dns_getgrent
, NULL
)
1751 NS_NIS_CB(_nis_getgrent
, NULL
)
1752 NS_COMPAT_CB(_compat_getgrent
, NULL
)
1756 mutex_lock(&__grmutex
);
1757 rv
= nsdispatch(NULL
, dtab
, NSDB_GROUP
, "getgrent", __nsdefaultcompat
,
1759 mutex_unlock(&__grmutex
);
1760 return (rv
== NS_SUCCESS
) ? retval
: NULL
;
1764 getgrent_r(struct group
*grp
, char *buffer
, size_t buflen
,
1765 struct group
**result
)
1769 static const ns_dtab dtab
[] = {
1770 NS_FILES_CB(_files_getgrent_r
, NULL
)
1771 NS_DNS_CB(_dns_getgrent_r
, NULL
)
1772 NS_NIS_CB(_nis_getgrent_r
, NULL
)
1773 NS_COMPAT_CB(_compat_getgrent_r
, NULL
)
1777 mutex_lock(&__grmutex
);
1778 rv
= nsdispatch(NULL
, dtab
, NSDB_GROUP
, "getgrent_r", __nsdefaultcompat
,
1779 &retval
, grp
, buffer
, buflen
, result
);
1780 mutex_unlock(&__grmutex
);
1795 struct group
*retval
;
1797 static const ns_dtab dtab
[] = {
1798 NS_FILES_CB(_files_getgrgid
, NULL
)
1799 NS_DNS_CB(_dns_getgrgid
, NULL
)
1800 NS_NIS_CB(_nis_getgrgid
, NULL
)
1801 NS_COMPAT_CB(_compat_getgrgid
, NULL
)
1805 mutex_lock(&__grmutex
);
1806 rv
= nsdispatch(NULL
, dtab
, NSDB_GROUP
, "getgrgid", __nsdefaultcompat
,
1808 mutex_unlock(&__grmutex
);
1809 return (rv
== NS_SUCCESS
) ? retval
: NULL
;
1813 getgrgid_r(gid_t gid
, struct group
*grp
, char *buffer
, size_t buflen
,
1814 struct group
**result
)
1818 static const ns_dtab dtab
[] = {
1819 NS_FILES_CB(_files_getgrgid_r
, NULL
)
1820 NS_DNS_CB(_dns_getgrgid_r
, NULL
)
1821 NS_NIS_CB(_nis_getgrgid_r
, NULL
)
1822 NS_COMPAT_CB(_compat_getgrgid_r
, NULL
)
1826 _DIAGASSERT(grp
!= NULL
);
1827 _DIAGASSERT(buffer
!= NULL
);
1828 _DIAGASSERT(result
!= NULL
);
1832 mutex_lock(&__grmutex
);
1833 rv
= nsdispatch(NULL
, dtab
, NSDB_GROUP
, "getgrgid_r", __nsdefaultcompat
,
1834 &retval
, gid
, grp
, buffer
, buflen
, result
);
1835 mutex_unlock(&__grmutex
);
1846 getgrnam(const char *name
)
1849 struct group
*retval
;
1851 static const ns_dtab dtab
[] = {
1852 NS_FILES_CB(_files_getgrnam
, NULL
)
1853 NS_DNS_CB(_dns_getgrnam
, NULL
)
1854 NS_NIS_CB(_nis_getgrnam
, NULL
)
1855 NS_COMPAT_CB(_compat_getgrnam
, NULL
)
1859 mutex_lock(&__grmutex
);
1860 rv
= nsdispatch(NULL
, dtab
, NSDB_GROUP
, "getgrnam", __nsdefaultcompat
,
1862 mutex_unlock(&__grmutex
);
1863 return (rv
== NS_SUCCESS
) ? retval
: NULL
;
1867 getgrnam_r(const char *name
, struct group
*grp
, char *buffer
, size_t buflen
,
1868 struct group
**result
)
1872 static const ns_dtab dtab
[] = {
1873 NS_FILES_CB(_files_getgrnam_r
, NULL
)
1874 NS_DNS_CB(_dns_getgrnam_r
, NULL
)
1875 NS_NIS_CB(_nis_getgrnam_r
, NULL
)
1876 NS_COMPAT_CB(_compat_getgrnam_r
, NULL
)
1880 _DIAGASSERT(name
!= NULL
);
1881 _DIAGASSERT(grp
!= NULL
);
1882 _DIAGASSERT(buffer
!= NULL
);
1883 _DIAGASSERT(result
!= NULL
);
1887 mutex_lock(&__grmutex
);
1888 rv
= nsdispatch(NULL
, dtab
, NSDB_GROUP
, "getgrnam_r", __nsdefaultcompat
,
1889 &retval
, name
, grp
, buffer
, buflen
, result
);
1890 mutex_unlock(&__grmutex
);
1903 static const ns_dtab dtab
[] = {
1904 NS_FILES_CB(_files_endgrent
, NULL
)
1905 NS_DNS_CB(_dns_endgrent
, NULL
)
1906 NS_NIS_CB(_nis_endgrent
, NULL
)
1907 NS_COMPAT_CB(_compat_endgrent
, NULL
)
1911 mutex_lock(&__grmutex
);
1912 /* force all endgrent() methods */
1913 (void) nsdispatch(NULL
, dtab
, NSDB_GROUP
, "endgrent",
1914 __nsdefaultcompat_forceall
);
1915 mutex_unlock(&__grmutex
);
1919 setgroupent(int stayopen
)
1921 static const ns_dtab dtab
[] = {
1922 NS_FILES_CB(_files_setgroupent
, NULL
)
1923 NS_DNS_CB(_dns_setgroupent
, NULL
)
1924 NS_NIS_CB(_nis_setgroupent
, NULL
)
1925 NS_COMPAT_CB(_compat_setgroupent
, NULL
)
1930 mutex_lock(&__grmutex
);
1931 /* force all setgroupent() methods */
1932 rv
= nsdispatch(NULL
, dtab
, NSDB_GROUP
, "setgroupent",
1933 __nsdefaultcompat_forceall
, &retval
, stayopen
);
1934 mutex_unlock(&__grmutex
);
1935 return (rv
== NS_SUCCESS
) ? retval
: 0;
1941 static const ns_dtab dtab
[] = {
1942 NS_FILES_CB(_files_setgrent
, NULL
)
1943 NS_DNS_CB(_dns_setgrent
, NULL
)
1944 NS_NIS_CB(_nis_setgrent
, NULL
)
1945 NS_COMPAT_CB(_compat_setgrent
, NULL
)
1949 mutex_lock(&__grmutex
);
1950 /* force all setgrent() methods */
1951 (void) nsdispatch(NULL
, dtab
, NSDB_GROUP
, "setgrent",
1952 __nsdefaultcompat_forceall
);
1953 mutex_unlock(&__grmutex
);