| @@ -1,1271 +1,1274 @@ | | | @@ -1,1271 +1,1274 @@ |
1 | /* $NetBSD: getgrent.c,v 1.62 2008/04/28 20:22:59 martin Exp $ */ | | 1 | /* $NetBSD: getgrent.c,v 1.63 2011/06/09 05:11:17 sjg Exp $ */ |
2 | | | 2 | |
3 | /*- | | 3 | /*- |
4 | * Copyright (c) 1999-2000, 2004-2005 The NetBSD Foundation, Inc. | | 4 | * Copyright (c) 1999-2000, 2004-2005 The NetBSD Foundation, Inc. |
5 | * All rights reserved. | | 5 | * All rights reserved. |
6 | * | | 6 | * |
7 | * This code is derived from software contributed to The NetBSD Foundation | | 7 | * This code is derived from software contributed to The NetBSD Foundation |
8 | * by Luke Mewburn. | | 8 | * by Luke Mewburn. |
9 | * | | 9 | * |
10 | * Redistribution and use in source and binary forms, with or without | | 10 | * Redistribution and use in source and binary forms, with or without |
11 | * modification, are permitted provided that the following conditions | | 11 | * modification, are permitted provided that the following conditions |
12 | * are met: | | 12 | * are met: |
13 | * 1. Redistributions of source code must retain the above copyright | | 13 | * 1. Redistributions of source code must retain the above copyright |
14 | * notice, this list of conditions and the following disclaimer. | | 14 | * notice, this list of conditions and the following disclaimer. |
15 | * 2. Redistributions in binary form must reproduce the above copyright | | 15 | * 2. Redistributions in binary form must reproduce the above copyright |
16 | * notice, this list of conditions and the following disclaimer in the | | 16 | * notice, this list of conditions and the following disclaimer in the |
17 | * documentation and/or other materials provided with the distribution. | | 17 | * documentation and/or other materials provided with the distribution. |
18 | * | | 18 | * |
19 | * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS | | 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 | | 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 | | 21 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
22 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS | | 22 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS |
23 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | | 23 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | | 24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | | 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 | | 26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | | 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 | | 28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
29 | * POSSIBILITY OF SUCH DAMAGE. | | 29 | * POSSIBILITY OF SUCH DAMAGE. |
30 | */ | | 30 | */ |
31 | | | 31 | |
32 | /* | | 32 | /* |
33 | * Copyright (c) 1989, 1993 | | 33 | * Copyright (c) 1989, 1993 |
34 | * The Regents of the University of California. All rights reserved. | | 34 | * The Regents of the University of California. All rights reserved. |
35 | * | | 35 | * |
36 | * Redistribution and use in source and binary forms, with or without | | 36 | * Redistribution and use in source and binary forms, with or without |
37 | * modification, are permitted provided that the following conditions | | 37 | * modification, are permitted provided that the following conditions |
38 | * are met: | | 38 | * are met: |
39 | * 1. Redistributions of source code must retain the above copyright | | 39 | * 1. Redistributions of source code must retain the above copyright |
40 | * notice, this list of conditions and the following disclaimer. | | 40 | * notice, this list of conditions and the following disclaimer. |
41 | * 2. Redistributions in binary form must reproduce the above copyright | | 41 | * 2. Redistributions in binary form must reproduce the above copyright |
42 | * notice, this list of conditions and the following disclaimer in the | | 42 | * notice, this list of conditions and the following disclaimer in the |
43 | * documentation and/or other materials provided with the distribution. | | 43 | * documentation and/or other materials provided with the distribution. |
44 | * 3. Neither the name of the University nor the names of its contributors | | 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 | | 45 | * may be used to endorse or promote products derived from this software |
46 | * without specific prior written permission. | | 46 | * without specific prior written permission. |
47 | * | | 47 | * |
48 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND | | 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 | | 49 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
50 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | | 50 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
51 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE | | 51 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE |
52 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | | 52 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
53 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | | 53 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
54 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | | 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 | | 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 | | 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 | | 57 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
58 | * SUCH DAMAGE. | | 58 | * SUCH DAMAGE. |
59 | */ | | 59 | */ |
60 | | | 60 | |
61 | /* | | 61 | /* |
62 | * Portions Copyright (c) 1994, Jason Downs. All Rights Reserved. | | 62 | * Portions Copyright (c) 1994, Jason Downs. All Rights Reserved. |
63 | * | | 63 | * |
64 | * Redistribution and use in source and binary forms, with or without | | 64 | * Redistribution and use in source and binary forms, with or without |
65 | * modification, are permitted provided that the following conditions | | 65 | * modification, are permitted provided that the following conditions |
66 | * are met: | | 66 | * are met: |
67 | * 1. Redistributions of source code must retain the above copyright | | 67 | * 1. Redistributions of source code must retain the above copyright |
68 | * notice, this list of conditions and the following disclaimer. | | 68 | * notice, this list of conditions and the following disclaimer. |
69 | * 2. Redistributions in binary form must reproduce the above copyright | | 69 | * 2. Redistributions in binary form must reproduce the above copyright |
70 | * notice, this list of conditions and the following disclaimer in the | | 70 | * notice, this list of conditions and the following disclaimer in the |
71 | * documentation and/or other materials provided with the distribution. | | 71 | * documentation and/or other materials provided with the distribution. |
72 | * | | 72 | * |
73 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS | | 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 | | 74 | * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
75 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | | 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, | | 76 | * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, |
77 | * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | | 77 | * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
78 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR | | 78 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR |
79 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER | | 79 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER |
80 | * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | | 80 | * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
81 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | | 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 | | 82 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
83 | * SUCH DAMAGE. | | 83 | * SUCH DAMAGE. |
84 | */ | | 84 | */ |
85 | | | 85 | |
86 | #include <sys/cdefs.h> | | 86 | #include <sys/cdefs.h> |
87 | #if defined(LIBC_SCCS) && !defined(lint) | | 87 | #if defined(LIBC_SCCS) && !defined(lint) |
88 | #if 0 | | 88 | #if 0 |
89 | static char sccsid[] = "@(#)getgrent.c 8.2 (Berkeley) 3/21/94"; | | 89 | static char sccsid[] = "@(#)getgrent.c 8.2 (Berkeley) 3/21/94"; |
90 | #else | | 90 | #else |
91 | __RCSID("$NetBSD: getgrent.c,v 1.62 2008/04/28 20:22:59 martin Exp $"); | | 91 | __RCSID("$NetBSD: getgrent.c,v 1.63 2011/06/09 05:11:17 sjg Exp $"); |
92 | #endif | | 92 | #endif |
93 | #endif /* LIBC_SCCS and not lint */ | | 93 | #endif /* LIBC_SCCS and not lint */ |
94 | | | 94 | |
95 | #include "namespace.h" | | 95 | #include "namespace.h" |
96 | #include "reentrant.h" | | 96 | #include "reentrant.h" |
97 | | | 97 | |
98 | #include <sys/param.h> | | 98 | #include <sys/param.h> |
99 | | | 99 | |
100 | #include <assert.h> | | 100 | #include <assert.h> |
101 | #include <errno.h> | | 101 | #include <errno.h> |
102 | #include <grp.h> | | 102 | #include <grp.h> |
103 | #include <limits.h> | | 103 | #include <limits.h> |
104 | #include <nsswitch.h> | | 104 | #include <nsswitch.h> |
105 | #include <stdarg.h> | | 105 | #include <stdarg.h> |
106 | #include <stdio.h> | | 106 | #include <stdio.h> |
107 | #include <stdlib.h> | | 107 | #include <stdlib.h> |
108 | #include <string.h> | | 108 | #include <string.h> |
109 | #include <syslog.h> | | 109 | #include <syslog.h> |
110 | | | 110 | |
111 | #ifdef HESIOD | | 111 | #ifdef HESIOD |
112 | #include <hesiod.h> | | 112 | #include <hesiod.h> |
113 | #endif | | 113 | #endif |
114 | | | 114 | |
115 | #ifdef YP | | 115 | #ifdef YP |
116 | #include <rpc/rpc.h> | | 116 | #include <rpc/rpc.h> |
117 | #include <rpcsvc/yp_prot.h> | | 117 | #include <rpcsvc/yp_prot.h> |
118 | #include <rpcsvc/ypclnt.h> | | 118 | #include <rpcsvc/ypclnt.h> |
119 | #endif | | 119 | #endif |
120 | | | 120 | |
121 | #include "gr_private.h" | | 121 | #include "gr_private.h" |
122 | | | 122 | |
123 | #ifdef __weak_alias | | 123 | #ifdef __weak_alias |
124 | __weak_alias(endgrent,_endgrent) | | 124 | __weak_alias(endgrent,_endgrent) |
125 | __weak_alias(getgrent,_getgrent) | | 125 | __weak_alias(getgrent,_getgrent) |
126 | __weak_alias(getgrent_r,_getgrent_r) | | 126 | __weak_alias(getgrent_r,_getgrent_r) |
127 | __weak_alias(getgrgid,_getgrgid) | | 127 | __weak_alias(getgrgid,_getgrgid) |
128 | __weak_alias(getgrgid_r,_getgrgid_r) | | 128 | __weak_alias(getgrgid_r,_getgrgid_r) |
129 | __weak_alias(getgrnam,_getgrnam) | | 129 | __weak_alias(getgrnam,_getgrnam) |
130 | __weak_alias(getgrnam_r,_getgrnam_r) | | 130 | __weak_alias(getgrnam_r,_getgrnam_r) |
131 | __weak_alias(setgrent,_setgrent) | | 131 | __weak_alias(setgrent,_setgrent) |
132 | __weak_alias(setgroupent,_setgroupent) | | 132 | __weak_alias(setgroupent,_setgroupent) |
133 | #endif | | 133 | #endif |
134 | | | 134 | |
135 | #ifdef _REENTRANT | | 135 | #ifdef _REENTRANT |
136 | mutex_t __grmutex = MUTEX_INITIALIZER; | | 136 | mutex_t __grmutex = MUTEX_INITIALIZER; |
137 | #endif | | 137 | #endif |
138 | | | 138 | |
139 | /* | | 139 | /* |
140 | * _gr_memfrombuf | | 140 | * _gr_memfrombuf |
141 | * Obtain want bytes from buffer (of size buflen) and return a pointer | | 141 | * Obtain want bytes from buffer (of size buflen) and return a pointer |
142 | * to the available memory after adjusting buffer/buflen. | | 142 | * to the available memory after adjusting buffer/buflen. |
143 | * Returns NULL if there is insufficient space. | | 143 | * Returns NULL if there is insufficient space. |
144 | */ | | 144 | */ |
145 | static char * | | 145 | static char * |
146 | _gr_memfrombuf(size_t want, char **buffer, size_t *buflen) | | 146 | _gr_memfrombuf(size_t want, char **buffer, size_t *buflen) |
147 | { | | 147 | { |
148 | char *rv; | | 148 | char *rv; |
149 | | | 149 | |
150 | if (want > *buflen) { | | 150 | if (want > *buflen) { |
151 | errno = ERANGE; | | 151 | errno = ERANGE; |
152 | return NULL; | | 152 | return NULL; |
153 | } | | 153 | } |
154 | rv = *buffer; | | 154 | rv = *buffer; |
155 | *buffer += want; | | 155 | *buffer += want; |
156 | *buflen -= want; | | 156 | *buflen -= want; |
157 | return rv; | | 157 | return rv; |
158 | } | | 158 | } |
159 | | | 159 | |
160 | /* | | 160 | /* |
161 | * _gr_parse | | 161 | * _gr_parse |
162 | * Parses entry as a line per group(5) (without the trailing \n) | | 162 | * Parses entry as a line per group(5) (without the trailing \n) |
163 | * and fills in grp with corresponding values; memory for strings | | 163 | * and fills in grp with corresponding values; memory for strings |
164 | * and arrays will be allocated from buf (of size buflen). | | 164 | * and arrays will be allocated from buf (of size buflen). |
165 | * Returns 1 if parsed successfully, 0 on parse failure. | | 165 | * Returns 1 if parsed successfully, 0 on parse failure. |
166 | */ | | 166 | */ |
167 | static int | | 167 | static int |
168 | _gr_parse(const char *entry, struct group *grp, char *buf, size_t buflen) | | 168 | _gr_parse(const char *entry, struct group *grp, char *buf, size_t buflen) |
169 | { | | 169 | { |
170 | unsigned long id; | | 170 | unsigned long id; |
171 | const char *bp; | | 171 | const char *bp; |
172 | char *ep; | | 172 | char *ep; |
173 | size_t count; | | 173 | size_t count; |
174 | int memc; | | 174 | int memc; |
175 | | | 175 | |
176 | _DIAGASSERT(entry != NULL); | | 176 | _DIAGASSERT(entry != NULL); |
177 | _DIAGASSERT(grp != NULL); | | 177 | _DIAGASSERT(grp != NULL); |
178 | _DIAGASSERT(buf != NULL); | | 178 | _DIAGASSERT(buf != NULL); |
179 | | | 179 | |
180 | #define COPYTOBUF(to) \ | | 180 | #define COPYTOBUF(to) \ |
181 | do { \ | | 181 | do { \ |
182 | (to) = _gr_memfrombuf(count+1, &buf, &buflen); \ | | 182 | (to) = _gr_memfrombuf(count+1, &buf, &buflen); \ |
183 | if ((to) == NULL) \ | | 183 | if ((to) == NULL) \ |
184 | return 0; \ | | 184 | return 0; \ |
185 | memmove((to), entry, count); \ | | 185 | memmove((to), entry, count); \ |
186 | to[count] = '\0'; \ | | 186 | to[count] = '\0'; \ |
187 | } while (0) /* LINTED */ | | 187 | } while (0) /* LINTED */ |
188 | | | 188 | |
189 | #if 0 | | 189 | #if 0 |
190 | if (*entry == '+') /* fail on compat `+' token */ | | 190 | if (*entry == '+') /* fail on compat `+' token */ |
191 | return 0; | | 191 | return 0; |
192 | #endif | | 192 | #endif |
193 | | | 193 | |
194 | count = strcspn(entry, ":"); /* parse gr_name */ | | 194 | count = strcspn(entry, ":"); /* parse gr_name */ |
195 | if (entry[count] == '\0') | | 195 | if (entry[count] == '\0') |
196 | return 0; | | 196 | return 0; |
197 | COPYTOBUF(grp->gr_name); | | 197 | COPYTOBUF(grp->gr_name); |
198 | entry += count + 1; | | 198 | entry += count + 1; |
199 | | | 199 | |
200 | count = strcspn(entry, ":"); /* parse gr_passwd */ | | 200 | count = strcspn(entry, ":"); /* parse gr_passwd */ |
201 | if (entry[count] == '\0') | | 201 | if (entry[count] == '\0') |
202 | return 0; | | 202 | return 0; |
203 | COPYTOBUF(grp->gr_passwd); | | 203 | COPYTOBUF(grp->gr_passwd); |
204 | entry += count + 1; | | 204 | entry += count + 1; |
205 | | | 205 | |
206 | count = strcspn(entry, ":"); /* parse gr_gid */ | | 206 | count = strcspn(entry, ":"); /* parse gr_gid */ |
207 | if (entry[count] == '\0') | | 207 | if (entry[count] == '\0') |
208 | return 0; | | 208 | return 0; |
209 | id = strtoul(entry, &ep, 10); | | 209 | id = strtoul(entry, &ep, 10); |
210 | if (id > GID_MAX || *ep != ':') | | 210 | if (id > GID_MAX || *ep != ':') |
211 | return 0; | | 211 | return 0; |
212 | grp->gr_gid = (gid_t)id; | | 212 | grp->gr_gid = (gid_t)id; |
213 | entry += count + 1; | | 213 | entry += count + 1; |
214 | | | 214 | |
215 | memc = 1; /* for final NULL */ | | 215 | memc = 1; /* for final NULL */ |
216 | if (*entry != '\0') | | 216 | if (*entry != '\0') |
217 | memc++; /* for first item */ | | 217 | memc++; /* for first item */ |
218 | for (bp = entry; *bp != '\0'; bp++) { | | 218 | for (bp = entry; *bp != '\0'; bp++) { |
219 | if (*bp == ',') | | 219 | if (*bp == ',') |
220 | memc++; | | 220 | memc++; |
221 | } | | 221 | } |
222 | /* grab ALIGNed char **gr_mem from buf */ | | 222 | /* grab ALIGNed char **gr_mem from buf */ |
223 | ep = _gr_memfrombuf(memc * sizeof(char *) + ALIGNBYTES, &buf, &buflen); | | 223 | ep = _gr_memfrombuf(memc * sizeof(char *) + ALIGNBYTES, &buf, &buflen); |
224 | grp->gr_mem = (char **)ALIGN(ep); | | 224 | grp->gr_mem = (char **)ALIGN(ep); |
225 | if (grp->gr_mem == NULL) | | 225 | if (grp->gr_mem == NULL) |
226 | return 0; | | 226 | return 0; |
227 | | | 227 | |
228 | for (memc = 0; *entry != '\0'; memc++) { | | 228 | for (memc = 0; *entry != '\0'; memc++) { |
229 | count = strcspn(entry, ","); /* parse member */ | | 229 | count = strcspn(entry, ","); /* parse member */ |
230 | COPYTOBUF(grp->gr_mem[memc]); | | 230 | COPYTOBUF(grp->gr_mem[memc]); |
231 | entry += count; | | 231 | entry += count; |
232 | if (*entry == ',') | | 232 | if (*entry == ',') |
233 | entry++; | | 233 | entry++; |
234 | } | | 234 | } |
235 | | | 235 | |
236 | #undef COPYTOBUF | | 236 | #undef COPYTOBUF |
237 | | | 237 | |
238 | grp->gr_mem[memc] = NULL; | | 238 | grp->gr_mem[memc] = NULL; |
239 | return 1; | | 239 | return 1; |
240 | } | | 240 | } |
241 | | | 241 | |
242 | /* | | 242 | /* |
243 | * _gr_copy | | 243 | * _gr_copy |
244 | * Copy the contents of fromgrp to grp; memory for strings | | 244 | * Copy the contents of fromgrp to grp; memory for strings |
245 | * and arrays will be allocated from buf (of size buflen). | | 245 | * and arrays will be allocated from buf (of size buflen). |
246 | * Returns 1 if copied successfully, 0 on copy failure. | | 246 | * Returns 1 if copied successfully, 0 on copy failure. |
247 | * NOTE: fromgrp must not use buf for its own pointers. | | 247 | * NOTE: fromgrp must not use buf for its own pointers. |
248 | */ | | 248 | */ |
249 | static int | | 249 | static int |
250 | _gr_copy(struct group *fromgrp, struct group *grp, char *buf, size_t buflen) | | 250 | _gr_copy(struct group *fromgrp, struct group *grp, char *buf, size_t buflen) |
251 | { | | 251 | { |
252 | char *ep; | | 252 | char *ep; |
253 | int memc; | | 253 | int memc; |
254 | | | 254 | |
255 | _DIAGASSERT(fromgrp != NULL); | | 255 | _DIAGASSERT(fromgrp != NULL); |
256 | _DIAGASSERT(grp != NULL); | | 256 | _DIAGASSERT(grp != NULL); |
257 | _DIAGASSERT(buf != NULL); | | 257 | _DIAGASSERT(buf != NULL); |
258 | | | 258 | |
259 | #define COPYSTR(to, from) \ | | 259 | #define COPYSTR(to, from) \ |
260 | do { \ | | 260 | do { \ |
261 | size_t count = strlen((from)); \ | | 261 | size_t count = strlen((from)); \ |
262 | (to) = _gr_memfrombuf(count+1, &buf, &buflen); \ | | 262 | (to) = _gr_memfrombuf(count+1, &buf, &buflen); \ |
263 | if ((to) == NULL) \ | | 263 | if ((to) == NULL) \ |
264 | return 0; \ | | 264 | return 0; \ |
265 | memmove((to), (from), count); \ | | 265 | memmove((to), (from), count); \ |
266 | to[count] = '\0'; \ | | 266 | to[count] = '\0'; \ |
267 | } while (0) /* LINTED */ | | 267 | } while (0) /* LINTED */ |
268 | | | 268 | |
269 | COPYSTR(grp->gr_name, fromgrp->gr_name); | | 269 | COPYSTR(grp->gr_name, fromgrp->gr_name); |
270 | COPYSTR(grp->gr_passwd, fromgrp->gr_passwd); | | 270 | COPYSTR(grp->gr_passwd, fromgrp->gr_passwd); |
271 | grp->gr_gid = fromgrp->gr_gid; | | 271 | grp->gr_gid = fromgrp->gr_gid; |
272 | | | 272 | |
| | | 273 | if (fromgrp->gr_mem == NULL) |
| | | 274 | return 0; |
| | | 275 | |
273 | for (memc = 0; fromgrp->gr_mem[memc]; memc++) | | 276 | for (memc = 0; fromgrp->gr_mem[memc]; memc++) |
274 | continue; | | 277 | continue; |
275 | memc++; /* for final NULL */ | | 278 | memc++; /* for final NULL */ |
276 | | | 279 | |
277 | /* grab ALIGNed char **gr_mem from buf */ | | 280 | /* grab ALIGNed char **gr_mem from buf */ |
278 | ep = _gr_memfrombuf(memc * sizeof(char *) + ALIGNBYTES, &buf, &buflen); | | 281 | ep = _gr_memfrombuf(memc * sizeof(char *) + ALIGNBYTES, &buf, &buflen); |
279 | grp->gr_mem = (char **)ALIGN(ep); | | 282 | grp->gr_mem = (char **)ALIGN(ep); |
280 | if (grp->gr_mem == NULL) | | 283 | if (grp->gr_mem == NULL) |
281 | return 0; | | 284 | return 0; |
282 | | | 285 | |
283 | for (memc = 0; fromgrp->gr_mem[memc]; memc++) { | | 286 | for (memc = 0; fromgrp->gr_mem[memc]; memc++) { |
284 | COPYSTR(grp->gr_mem[memc], fromgrp->gr_mem[memc]); | | 287 | COPYSTR(grp->gr_mem[memc], fromgrp->gr_mem[memc]); |
285 | } | | 288 | } |
286 | | | 289 | |
287 | #undef COPYSTR | | 290 | #undef COPYSTR |
288 | | | 291 | |
289 | grp->gr_mem[memc] = NULL; | | 292 | grp->gr_mem[memc] = NULL; |
290 | return 1; | | 293 | return 1; |
291 | } | | 294 | } |
292 | | | 295 | |
293 | /* | | 296 | /* |
294 | * files methods | | 297 | * files methods |
295 | */ | | 298 | */ |
296 | | | 299 | |
297 | int | | 300 | int |
298 | __grstart_files(struct __grstate_files *state) | | 301 | __grstart_files(struct __grstate_files *state) |
299 | { | | 302 | { |
300 | | | 303 | |
301 | _DIAGASSERT(state != NULL); | | 304 | _DIAGASSERT(state != NULL); |
302 | | | 305 | |
303 | if (state->fp == NULL) { | | 306 | if (state->fp == NULL) { |
304 | state->fp = fopen(_PATH_GROUP, "r"); | | 307 | state->fp = fopen(_PATH_GROUP, "r"); |
305 | if (state->fp == NULL) | | 308 | if (state->fp == NULL) |
306 | return NS_UNAVAIL; | | 309 | return NS_UNAVAIL; |
307 | } else { | | 310 | } else { |
308 | rewind(state->fp); | | 311 | rewind(state->fp); |
309 | } | | 312 | } |
310 | return NS_SUCCESS; | | 313 | return NS_SUCCESS; |
311 | } | | 314 | } |
312 | | | 315 | |
313 | int | | 316 | int |
314 | __grend_files(struct __grstate_files *state) | | 317 | __grend_files(struct __grstate_files *state) |
315 | { | | 318 | { |
316 | | | 319 | |
317 | _DIAGASSERT(state != NULL); | | 320 | _DIAGASSERT(state != NULL); |
318 | | | 321 | |
319 | if (state->fp) { | | 322 | if (state->fp) { |
320 | (void) fclose(state->fp); | | 323 | (void) fclose(state->fp); |
321 | state->fp = NULL; | | 324 | state->fp = NULL; |
322 | } | | 325 | } |
323 | return NS_SUCCESS; | | 326 | return NS_SUCCESS; |
324 | } | | 327 | } |
325 | | | 328 | |
326 | /* | | 329 | /* |
327 | * __grscan_files | | 330 | * __grscan_files |
328 | * Scan state->fp for the next desired entry. | | 331 | * Scan state->fp for the next desired entry. |
329 | * If search is zero, return the next entry. | | 332 | * If search is zero, return the next entry. |
330 | * If search is non-zero, look for a specific name (if name != NULL), | | 333 | * If search is non-zero, look for a specific name (if name != NULL), |
331 | * or a specific gid (if name == NULL). | | 334 | * or a specific gid (if name == NULL). |
332 | * Sets *retval to the errno if the result is not NS_SUCCESS | | 335 | * Sets *retval to the errno if the result is not NS_SUCCESS |
333 | * or NS_NOTFOUND. | | 336 | * or NS_NOTFOUND. |
334 | */ | | 337 | */ |
335 | int | | 338 | int |
336 | __grscan_files(int *retval, struct group *grp, char *buffer, size_t buflen, | | 339 | __grscan_files(int *retval, struct group *grp, char *buffer, size_t buflen, |
337 | struct __grstate_files *state, int search, const char *name, gid_t gid) | | 340 | struct __grstate_files *state, int search, const char *name, gid_t gid) |
338 | { | | 341 | { |
339 | int rv; | | 342 | int rv; |
340 | char filebuf[_GETGR_R_SIZE_MAX], *ep; | | 343 | char filebuf[_GETGR_R_SIZE_MAX], *ep; |
341 | | | 344 | |
342 | _DIAGASSERT(retval != NULL); | | 345 | _DIAGASSERT(retval != NULL); |
343 | _DIAGASSERT(grp != NULL); | | 346 | _DIAGASSERT(grp != NULL); |
344 | _DIAGASSERT(buffer != NULL); | | 347 | _DIAGASSERT(buffer != NULL); |
345 | _DIAGASSERT(state != NULL); | | 348 | _DIAGASSERT(state != NULL); |
346 | /* name is NULL to indicate searching for gid */ | | 349 | /* name is NULL to indicate searching for gid */ |
347 | | | 350 | |
348 | *retval = 0; | | 351 | *retval = 0; |
349 | | | 352 | |
350 | if (state->fp == NULL) { /* only start if file not open yet */ | | 353 | if (state->fp == NULL) { /* only start if file not open yet */ |
351 | rv = __grstart_files(state); | | 354 | rv = __grstart_files(state); |
352 | if (rv != NS_SUCCESS) | | 355 | if (rv != NS_SUCCESS) |
353 | goto filesgrscan_out; | | 356 | goto filesgrscan_out; |
354 | } | | 357 | } |
355 | | | 358 | |
356 | rv = NS_NOTFOUND; | | 359 | rv = NS_NOTFOUND; |
357 | | | 360 | |
358 | /* scan line by line */ | | 361 | /* scan line by line */ |
359 | while (fgets(filebuf, sizeof(filebuf), state->fp) != NULL) { | | 362 | while (fgets(filebuf, sizeof(filebuf), state->fp) != NULL) { |
360 | ep = strchr(filebuf, '\n'); | | 363 | ep = strchr(filebuf, '\n'); |
361 | if (ep == NULL) { /* skip lines that are too big */ | | 364 | if (ep == NULL) { /* skip lines that are too big */ |
362 | int ch; | | 365 | int ch; |
363 | | | 366 | |
364 | while ((ch = getc(state->fp)) != '\n' && ch != EOF) | | 367 | while ((ch = getc(state->fp)) != '\n' && ch != EOF) |
365 | continue; | | 368 | continue; |
366 | continue; | | 369 | continue; |
367 | } | | 370 | } |
368 | *ep = '\0'; /* clear trailing \n */ | | 371 | *ep = '\0'; /* clear trailing \n */ |
369 | | | 372 | |
370 | if (filebuf[0] == '+') /* skip compat line */ | | 373 | if (filebuf[0] == '+') /* skip compat line */ |
371 | continue; | | 374 | continue; |
372 | | | 375 | |
373 | /* validate line */ | | 376 | /* validate line */ |
374 | if (! _gr_parse(filebuf, grp, buffer, buflen)) { | | 377 | if (! _gr_parse(filebuf, grp, buffer, buflen)) { |
375 | continue; /* skip bad lines */ | | 378 | continue; /* skip bad lines */ |
376 | } | | 379 | } |
377 | if (! search) { /* just want this one */ | | 380 | if (! search) { /* just want this one */ |
378 | rv = NS_SUCCESS; | | 381 | rv = NS_SUCCESS; |
379 | break; | | 382 | break; |
380 | } | | 383 | } |
381 | /* want specific */ | | 384 | /* want specific */ |
382 | if ((name && strcmp(name, grp->gr_name) == 0) || | | 385 | if ((name && strcmp(name, grp->gr_name) == 0) || |
383 | (!name && gid == grp->gr_gid)) { | | 386 | (!name && gid == grp->gr_gid)) { |
384 | rv = NS_SUCCESS; | | 387 | rv = NS_SUCCESS; |
385 | break; | | 388 | break; |
386 | } | | 389 | } |
387 | } | | 390 | } |
388 | | | 391 | |
389 | filesgrscan_out: | | 392 | filesgrscan_out: |
390 | if (rv != NS_SUCCESS && rv != NS_NOTFOUND) | | 393 | if (rv != NS_SUCCESS && rv != NS_NOTFOUND) |
391 | *retval = errno; | | 394 | *retval = errno; |
392 | return rv; | | 395 | return rv; |
393 | } | | 396 | } |
394 | | | 397 | |
395 | | | 398 | |
396 | static struct __grstate_files _files_state; | | 399 | static struct __grstate_files _files_state; |
397 | /* storage for non _r functions */ | | 400 | /* storage for non _r functions */ |
398 | static struct group _files_group; | | 401 | static struct group _files_group; |
399 | static char _files_groupbuf[_GETGR_R_SIZE_MAX]; | | 402 | static char _files_groupbuf[_GETGR_R_SIZE_MAX]; |
400 | | | 403 | |
401 | /*ARGSUSED*/ | | 404 | /*ARGSUSED*/ |
402 | static int | | 405 | static int |
403 | _files_setgrent(void *nsrv, void *nscb, va_list ap) | | 406 | _files_setgrent(void *nsrv, void *nscb, va_list ap) |
404 | { | | 407 | { |
405 | | | 408 | |
406 | _files_state.stayopen = 0; | | 409 | _files_state.stayopen = 0; |
407 | return __grstart_files(&_files_state); | | 410 | return __grstart_files(&_files_state); |
408 | } | | 411 | } |
409 | | | 412 | |
410 | /*ARGSUSED*/ | | 413 | /*ARGSUSED*/ |
411 | static int | | 414 | static int |
412 | _files_setgroupent(void *nsrv, void *nscb, va_list ap) | | 415 | _files_setgroupent(void *nsrv, void *nscb, va_list ap) |
413 | { | | 416 | { |
414 | int *retval = va_arg(ap, int *); | | 417 | int *retval = va_arg(ap, int *); |
415 | int stayopen = va_arg(ap, int); | | 418 | int stayopen = va_arg(ap, int); |
416 | | | 419 | |
417 | int rv; | | 420 | int rv; |
418 | | | 421 | |
419 | _files_state.stayopen = stayopen; | | 422 | _files_state.stayopen = stayopen; |
420 | rv = __grstart_files(&_files_state); | | 423 | rv = __grstart_files(&_files_state); |
421 | *retval = (rv == NS_SUCCESS); | | 424 | *retval = (rv == NS_SUCCESS); |
422 | return rv; | | 425 | return rv; |
423 | } | | 426 | } |
424 | | | 427 | |
425 | /*ARGSUSED*/ | | 428 | /*ARGSUSED*/ |
426 | static int | | 429 | static int |
427 | _files_endgrent(void *nsrv, void *nscb, va_list ap) | | 430 | _files_endgrent(void *nsrv, void *nscb, va_list ap) |
428 | { | | 431 | { |
429 | | | 432 | |
430 | _files_state.stayopen = 0; | | 433 | _files_state.stayopen = 0; |
431 | return __grend_files(&_files_state); | | 434 | return __grend_files(&_files_state); |
432 | } | | 435 | } |
433 | | | 436 | |
434 | /*ARGSUSED*/ | | 437 | /*ARGSUSED*/ |
435 | static int | | 438 | static int |
436 | _files_getgrent(void *nsrv, void *nscb, va_list ap) | | 439 | _files_getgrent(void *nsrv, void *nscb, va_list ap) |
437 | { | | 440 | { |
438 | struct group **retval = va_arg(ap, struct group **); | | 441 | struct group **retval = va_arg(ap, struct group **); |
439 | | | 442 | |
440 | int rv, rerror; | | 443 | int rv, rerror; |
441 | | | 444 | |
442 | _DIAGASSERT(retval != NULL); | | 445 | _DIAGASSERT(retval != NULL); |
443 | | | 446 | |
444 | *retval = NULL; | | 447 | *retval = NULL; |
445 | rv = __grscan_files(&rerror, &_files_group, | | 448 | rv = __grscan_files(&rerror, &_files_group, |
446 | _files_groupbuf, sizeof(_files_groupbuf), | | 449 | _files_groupbuf, sizeof(_files_groupbuf), |
447 | &_files_state, 0, NULL, 0); | | 450 | &_files_state, 0, NULL, 0); |
448 | if (rv == NS_SUCCESS) | | 451 | if (rv == NS_SUCCESS) |
449 | *retval = &_files_group; | | 452 | *retval = &_files_group; |
450 | return rv; | | 453 | return rv; |
451 | } | | 454 | } |
452 | | | 455 | |
453 | /*ARGSUSED*/ | | 456 | /*ARGSUSED*/ |
454 | static int | | 457 | static int |
455 | _files_getgrent_r(void *nsrv, void *nscb, va_list ap) | | 458 | _files_getgrent_r(void *nsrv, void *nscb, va_list ap) |
456 | { | | 459 | { |
457 | int *retval = va_arg(ap, int *); | | 460 | int *retval = va_arg(ap, int *); |
458 | struct group *grp = va_arg(ap, struct group *); | | 461 | struct group *grp = va_arg(ap, struct group *); |
459 | char *buffer = va_arg(ap, char *); | | 462 | char *buffer = va_arg(ap, char *); |
460 | size_t buflen = va_arg(ap, size_t); | | 463 | size_t buflen = va_arg(ap, size_t); |
461 | struct group **result = va_arg(ap, struct group **); | | 464 | struct group **result = va_arg(ap, struct group **); |
462 | | | 465 | |
463 | int rv; | | 466 | int rv; |
464 | | | 467 | |
465 | _DIAGASSERT(retval != NULL); | | 468 | _DIAGASSERT(retval != NULL); |
466 | _DIAGASSERT(grp != NULL); | | 469 | _DIAGASSERT(grp != NULL); |
467 | _DIAGASSERT(buffer != NULL); | | 470 | _DIAGASSERT(buffer != NULL); |
468 | _DIAGASSERT(result != NULL); | | 471 | _DIAGASSERT(result != NULL); |
469 | | | 472 | |
470 | rv = __grscan_files(retval, grp, buffer, buflen, | | 473 | rv = __grscan_files(retval, grp, buffer, buflen, |
471 | &_files_state, 0, NULL, 0); | | 474 | &_files_state, 0, NULL, 0); |
472 | if (rv == NS_SUCCESS) | | 475 | if (rv == NS_SUCCESS) |
473 | *result = grp; | | 476 | *result = grp; |
474 | else | | 477 | else |
475 | *result = NULL; | | 478 | *result = NULL; |
476 | return rv; | | 479 | return rv; |
477 | } | | 480 | } |
478 | | | 481 | |
479 | /*ARGSUSED*/ | | 482 | /*ARGSUSED*/ |
480 | static int | | 483 | static int |
481 | _files_getgrgid(void *nsrv, void *nscb, va_list ap) | | 484 | _files_getgrgid(void *nsrv, void *nscb, va_list ap) |
482 | { | | 485 | { |
483 | struct group **retval = va_arg(ap, struct group **); | | 486 | struct group **retval = va_arg(ap, struct group **); |
484 | gid_t gid = va_arg(ap, gid_t); | | 487 | gid_t gid = va_arg(ap, gid_t); |
485 | | | 488 | |
486 | int rv, rerror; | | 489 | int rv, rerror; |
487 | | | 490 | |
488 | _DIAGASSERT(retval != NULL); | | 491 | _DIAGASSERT(retval != NULL); |
489 | | | 492 | |
490 | *retval = NULL; | | 493 | *retval = NULL; |
491 | rv = __grstart_files(&_files_state); | | 494 | rv = __grstart_files(&_files_state); |
492 | if (rv != NS_SUCCESS) | | 495 | if (rv != NS_SUCCESS) |
493 | return rv; | | 496 | return rv; |
494 | rv = __grscan_files(&rerror, &_files_group, | | 497 | rv = __grscan_files(&rerror, &_files_group, |
495 | _files_groupbuf, sizeof(_files_groupbuf), | | 498 | _files_groupbuf, sizeof(_files_groupbuf), |
496 | &_files_state, 1, NULL, gid); | | 499 | &_files_state, 1, NULL, gid); |
497 | if (!_files_state.stayopen) | | 500 | if (!_files_state.stayopen) |
498 | __grend_files(&_files_state); | | 501 | __grend_files(&_files_state); |
499 | if (rv == NS_SUCCESS) | | 502 | if (rv == NS_SUCCESS) |
500 | *retval = &_files_group; | | 503 | *retval = &_files_group; |
501 | return rv; | | 504 | return rv; |
502 | } | | 505 | } |
503 | | | 506 | |
504 | /*ARGSUSED*/ | | 507 | /*ARGSUSED*/ |
505 | static int | | 508 | static int |
506 | _files_getgrgid_r(void *nsrv, void *nscb, va_list ap) | | 509 | _files_getgrgid_r(void *nsrv, void *nscb, va_list ap) |
507 | { | | 510 | { |
508 | int *retval = va_arg(ap, int *); | | 511 | int *retval = va_arg(ap, int *); |
509 | gid_t gid = va_arg(ap, gid_t); | | 512 | gid_t gid = va_arg(ap, gid_t); |
510 | struct group *grp = va_arg(ap, struct group *); | | 513 | struct group *grp = va_arg(ap, struct group *); |
511 | char *buffer = va_arg(ap, char *); | | 514 | char *buffer = va_arg(ap, char *); |
512 | size_t buflen = va_arg(ap, size_t); | | 515 | size_t buflen = va_arg(ap, size_t); |
513 | struct group **result = va_arg(ap, struct group **); | | 516 | struct group **result = va_arg(ap, struct group **); |
514 | | | 517 | |
515 | struct __grstate_files state; | | 518 | struct __grstate_files state; |
516 | int rv; | | 519 | int rv; |
517 | | | 520 | |
518 | _DIAGASSERT(retval != NULL); | | 521 | _DIAGASSERT(retval != NULL); |
519 | _DIAGASSERT(grp != NULL); | | 522 | _DIAGASSERT(grp != NULL); |
520 | _DIAGASSERT(buffer != NULL); | | 523 | _DIAGASSERT(buffer != NULL); |
521 | _DIAGASSERT(result != NULL); | | 524 | _DIAGASSERT(result != NULL); |
522 | | | 525 | |
523 | *result = NULL; | | 526 | *result = NULL; |
524 | memset(&state, 0, sizeof(state)); | | 527 | memset(&state, 0, sizeof(state)); |
525 | rv = __grscan_files(retval, grp, buffer, buflen, &state, 1, NULL, gid); | | 528 | rv = __grscan_files(retval, grp, buffer, buflen, &state, 1, NULL, gid); |
526 | __grend_files(&state); | | 529 | __grend_files(&state); |
527 | if (rv == NS_SUCCESS) | | 530 | if (rv == NS_SUCCESS) |
528 | *result = grp; | | 531 | *result = grp; |
529 | return rv; | | 532 | return rv; |
530 | } | | 533 | } |
531 | | | 534 | |
532 | /*ARGSUSED*/ | | 535 | /*ARGSUSED*/ |
533 | static int | | 536 | static int |
534 | _files_getgrnam(void *nsrv, void *nscb, va_list ap) | | 537 | _files_getgrnam(void *nsrv, void *nscb, va_list ap) |
535 | { | | 538 | { |
536 | struct group **retval = va_arg(ap, struct group **); | | 539 | struct group **retval = va_arg(ap, struct group **); |
537 | const char *name = va_arg(ap, const char *); | | 540 | const char *name = va_arg(ap, const char *); |
538 | | | 541 | |
539 | int rv, rerror; | | 542 | int rv, rerror; |
540 | | | 543 | |
541 | _DIAGASSERT(retval != NULL); | | 544 | _DIAGASSERT(retval != NULL); |
542 | | | 545 | |
543 | *retval = NULL; | | 546 | *retval = NULL; |
544 | rv = __grstart_files(&_files_state); | | 547 | rv = __grstart_files(&_files_state); |
545 | if (rv != NS_SUCCESS) | | 548 | if (rv != NS_SUCCESS) |
546 | return rv; | | 549 | return rv; |
547 | rv = __grscan_files(&rerror, &_files_group, | | 550 | rv = __grscan_files(&rerror, &_files_group, |
548 | _files_groupbuf, sizeof(_files_groupbuf), | | 551 | _files_groupbuf, sizeof(_files_groupbuf), |
549 | &_files_state, 1, name, 0); | | 552 | &_files_state, 1, name, 0); |
550 | if (!_files_state.stayopen) | | 553 | if (!_files_state.stayopen) |
551 | __grend_files(&_files_state); | | 554 | __grend_files(&_files_state); |
552 | if (rv == NS_SUCCESS) | | 555 | if (rv == NS_SUCCESS) |
553 | *retval = &_files_group; | | 556 | *retval = &_files_group; |
554 | return rv; | | 557 | return rv; |
555 | } | | 558 | } |
556 | | | 559 | |
557 | /*ARGSUSED*/ | | 560 | /*ARGSUSED*/ |
558 | static int | | 561 | static int |
559 | _files_getgrnam_r(void *nsrv, void *nscb, va_list ap) | | 562 | _files_getgrnam_r(void *nsrv, void *nscb, va_list ap) |
560 | { | | 563 | { |
561 | int *retval = va_arg(ap, int *); | | 564 | int *retval = va_arg(ap, int *); |
562 | const char *name = va_arg(ap, const char *); | | 565 | const char *name = va_arg(ap, const char *); |
563 | struct group *grp = va_arg(ap, struct group *); | | 566 | struct group *grp = va_arg(ap, struct group *); |
564 | char *buffer = va_arg(ap, char *); | | 567 | char *buffer = va_arg(ap, char *); |
565 | size_t buflen = va_arg(ap, size_t); | | 568 | size_t buflen = va_arg(ap, size_t); |
566 | struct group **result = va_arg(ap, struct group **); | | 569 | struct group **result = va_arg(ap, struct group **); |
567 | | | 570 | |
568 | struct __grstate_files state; | | 571 | struct __grstate_files state; |
569 | int rv; | | 572 | int rv; |
570 | | | 573 | |
571 | _DIAGASSERT(retval != NULL); | | 574 | _DIAGASSERT(retval != NULL); |
572 | _DIAGASSERT(grp != NULL); | | 575 | _DIAGASSERT(grp != NULL); |
573 | _DIAGASSERT(buffer != NULL); | | 576 | _DIAGASSERT(buffer != NULL); |
574 | _DIAGASSERT(result != NULL); | | 577 | _DIAGASSERT(result != NULL); |
575 | | | 578 | |
576 | *result = NULL; | | 579 | *result = NULL; |
577 | memset(&state, 0, sizeof(state)); | | 580 | memset(&state, 0, sizeof(state)); |
578 | rv = __grscan_files(retval, grp, buffer, buflen, &state, 1, name, 0); | | 581 | rv = __grscan_files(retval, grp, buffer, buflen, &state, 1, name, 0); |
579 | __grend_files(&state); | | 582 | __grend_files(&state); |
580 | if (rv == NS_SUCCESS) | | 583 | if (rv == NS_SUCCESS) |
581 | *result = grp; | | 584 | *result = grp; |
582 | return rv; | | 585 | return rv; |
583 | } | | 586 | } |
584 | | | 587 | |
585 | | | 588 | |
586 | #ifdef HESIOD | | 589 | #ifdef HESIOD |
587 | /* | | 590 | /* |
588 | * dns methods | | 591 | * dns methods |
589 | */ | | 592 | */ |
590 | | | 593 | |
591 | int | | 594 | int |
592 | __grstart_dns(struct __grstate_dns *state) | | 595 | __grstart_dns(struct __grstate_dns *state) |
593 | { | | 596 | { |
594 | | | 597 | |
595 | _DIAGASSERT(state != NULL); | | 598 | _DIAGASSERT(state != NULL); |
596 | | | 599 | |
597 | state->num = 0; | | 600 | state->num = 0; |
598 | if (state->context == NULL) { /* setup Hesiod */ | | 601 | if (state->context == NULL) { /* setup Hesiod */ |
599 | if (hesiod_init(&state->context) == -1) | | 602 | if (hesiod_init(&state->context) == -1) |
600 | return NS_UNAVAIL; | | 603 | return NS_UNAVAIL; |
601 | } | | 604 | } |
602 | | | 605 | |
603 | return NS_SUCCESS; | | 606 | return NS_SUCCESS; |
604 | } | | 607 | } |
605 | | | 608 | |
606 | int | | 609 | int |
607 | __grend_dns(struct __grstate_dns *state) | | 610 | __grend_dns(struct __grstate_dns *state) |
608 | { | | 611 | { |
609 | | | 612 | |
610 | _DIAGASSERT(state != NULL); | | 613 | _DIAGASSERT(state != NULL); |
611 | | | 614 | |
612 | state->num = 0; | | 615 | state->num = 0; |
613 | if (state->context) { | | 616 | if (state->context) { |
614 | hesiod_end(state->context); | | 617 | hesiod_end(state->context); |
615 | state->context = NULL; | | 618 | state->context = NULL; |
616 | } | | 619 | } |
617 | return NS_SUCCESS; | | 620 | return NS_SUCCESS; |
618 | } | | 621 | } |
619 | | | 622 | |
620 | /* | | 623 | /* |
621 | * __grscan_dns | | 624 | * __grscan_dns |
622 | * Search Hesiod for the next desired entry. | | 625 | * Search Hesiod for the next desired entry. |
623 | * If search is zero, return the next entry. | | 626 | * If search is zero, return the next entry. |
624 | * If search is non-zero, look for a specific name (if name != NULL), | | 627 | * If search is non-zero, look for a specific name (if name != NULL), |
625 | * or a specific gid (if name == NULL). | | 628 | * or a specific gid (if name == NULL). |
626 | */ | | 629 | */ |
627 | int | | 630 | int |
628 | __grscan_dns(int *retval, struct group *grp, char *buffer, size_t buflen, | | 631 | __grscan_dns(int *retval, struct group *grp, char *buffer, size_t buflen, |
629 | struct __grstate_dns *state, int search, const char *name, gid_t gid) | | 632 | struct __grstate_dns *state, int search, const char *name, gid_t gid) |
630 | { | | 633 | { |
631 | const char **curzone; | | 634 | const char **curzone; |
632 | char **hp, *ep; | | 635 | char **hp, *ep; |
633 | int rv; | | 636 | int rv; |
634 | | | 637 | |
635 | static const char *zones_gid_group[] = { | | 638 | static const char *zones_gid_group[] = { |
636 | "gid", | | 639 | "gid", |
637 | "group", | | 640 | "group", |
638 | NULL | | 641 | NULL |
639 | }; | | 642 | }; |
640 | | | 643 | |
641 | static const char *zones_group[] = { | | 644 | static const char *zones_group[] = { |
642 | "group", | | 645 | "group", |
643 | NULL | | 646 | NULL |
644 | }; | | 647 | }; |
645 | | | 648 | |
646 | _DIAGASSERT(retval != NULL); | | 649 | _DIAGASSERT(retval != NULL); |
647 | _DIAGASSERT(grp != NULL); | | 650 | _DIAGASSERT(grp != NULL); |
648 | _DIAGASSERT(buffer != NULL); | | 651 | _DIAGASSERT(buffer != NULL); |
649 | _DIAGASSERT(state != NULL); | | 652 | _DIAGASSERT(state != NULL); |
650 | /* name is NULL to indicate searching for gid */ | | 653 | /* name is NULL to indicate searching for gid */ |
651 | | | 654 | |
652 | *retval = 0; | | 655 | *retval = 0; |
653 | | | 656 | |
654 | if (state->context == NULL) { /* only start if Hesiod not setup */ | | 657 | if (state->context == NULL) { /* only start if Hesiod not setup */ |
655 | rv = __grstart_dns(state); | | 658 | rv = __grstart_dns(state); |
656 | if (rv != NS_SUCCESS) | | 659 | if (rv != NS_SUCCESS) |
657 | return rv; | | 660 | return rv; |
658 | } | | 661 | } |
659 | | | 662 | |
660 | next_dns_entry: | | 663 | next_dns_entry: |
661 | hp = NULL; | | 664 | hp = NULL; |
662 | rv = NS_NOTFOUND; | | 665 | rv = NS_NOTFOUND; |
663 | | | 666 | |
664 | if (! search) { /* find next entry */ | | 667 | if (! search) { /* find next entry */ |
665 | if (state->num == -1) /* exhausted search */ | | 668 | if (state->num == -1) /* exhausted search */ |
666 | return NS_NOTFOUND; | | 669 | return NS_NOTFOUND; |
667 | /* find group-NNN */ | | 670 | /* find group-NNN */ |
668 | snprintf(buffer, buflen, "group-%u", state->num); | | 671 | snprintf(buffer, buflen, "group-%u", state->num); |
669 | state->num++; | | 672 | state->num++; |
670 | curzone = zones_group; | | 673 | curzone = zones_group; |
671 | } else if (name) { /* find group name */ | | 674 | } else if (name) { /* find group name */ |
672 | snprintf(buffer, buflen, "%s", name); | | 675 | snprintf(buffer, buflen, "%s", name); |
673 | curzone = zones_group; | | 676 | curzone = zones_group; |
674 | } else { /* find gid */ | | 677 | } else { /* find gid */ |
675 | snprintf(buffer, buflen, "%u", (unsigned int)gid); | | 678 | snprintf(buffer, buflen, "%u", (unsigned int)gid); |
676 | curzone = zones_gid_group; | | 679 | curzone = zones_gid_group; |
677 | } | | 680 | } |
678 | | | 681 | |
679 | for (; *curzone; curzone++) { /* search zones */ | | 682 | for (; *curzone; curzone++) { /* search zones */ |
680 | hp = hesiod_resolve(state->context, buffer, *curzone); | | 683 | hp = hesiod_resolve(state->context, buffer, *curzone); |
681 | if (hp != NULL) | | 684 | if (hp != NULL) |
682 | break; | | 685 | break; |
683 | if (errno != ENOENT) { | | 686 | if (errno != ENOENT) { |
684 | rv = NS_UNAVAIL; | | 687 | rv = NS_UNAVAIL; |
685 | goto dnsgrscan_out; | | 688 | goto dnsgrscan_out; |
686 | } | | 689 | } |
687 | } | | 690 | } |
688 | if (*curzone == NULL) { | | 691 | if (*curzone == NULL) { |
689 | if (! search) | | 692 | if (! search) |
690 | state->num = -1; | | 693 | state->num = -1; |
691 | goto dnsgrscan_out; | | 694 | goto dnsgrscan_out; |
692 | } | | 695 | } |
693 | | | 696 | |
694 | if ((ep = strchr(hp[0], '\n')) != NULL) | | 697 | if ((ep = strchr(hp[0], '\n')) != NULL) |
695 | *ep = '\0'; /* clear trailing \n */ | | 698 | *ep = '\0'; /* clear trailing \n */ |
696 | if (_gr_parse(hp[0], grp, buffer, buflen)) { /* validate line */ | | 699 | if (_gr_parse(hp[0], grp, buffer, buflen)) { /* validate line */ |
697 | if (! search) { /* just want this one */ | | 700 | if (! search) { /* just want this one */ |
698 | rv = NS_SUCCESS; | | 701 | rv = NS_SUCCESS; |
699 | } else if ((name && strcmp(name, grp->gr_name) == 0) || | | 702 | } else if ((name && strcmp(name, grp->gr_name) == 0) || |
700 | (!name && gid == grp->gr_gid)) { /* want specific */ | | 703 | (!name && gid == grp->gr_gid)) { /* want specific */ |
701 | rv = NS_SUCCESS; | | 704 | rv = NS_SUCCESS; |
702 | } | | 705 | } |
703 | } else { /* dodgy entry */ | | 706 | } else { /* dodgy entry */ |
704 | if (!search) { /* try again if ! searching */ | | 707 | if (!search) { /* try again if ! searching */ |
705 | hesiod_free_list(state->context, hp); | | 708 | hesiod_free_list(state->context, hp); |
706 | goto next_dns_entry; | | 709 | goto next_dns_entry; |
707 | } | | 710 | } |
708 | } | | 711 | } |
709 | | | 712 | |
710 | dnsgrscan_out: | | 713 | dnsgrscan_out: |
711 | if (rv != NS_SUCCESS && rv != NS_NOTFOUND) | | 714 | if (rv != NS_SUCCESS && rv != NS_NOTFOUND) |
712 | *retval = errno; | | 715 | *retval = errno; |
713 | if (hp) | | 716 | if (hp) |
714 | hesiod_free_list(state->context, hp); | | 717 | hesiod_free_list(state->context, hp); |
715 | return rv; | | 718 | return rv; |
716 | } | | 719 | } |
717 | | | 720 | |
718 | static struct __grstate_dns _dns_state; | | 721 | static struct __grstate_dns _dns_state; |
719 | /* storage for non _r functions */ | | 722 | /* storage for non _r functions */ |
720 | static struct group _dns_group; | | 723 | static struct group _dns_group; |
721 | static char _dns_groupbuf[_GETGR_R_SIZE_MAX]; | | 724 | static char _dns_groupbuf[_GETGR_R_SIZE_MAX]; |
722 | | | 725 | |
723 | /*ARGSUSED*/ | | 726 | /*ARGSUSED*/ |
724 | static int | | 727 | static int |
725 | _dns_setgrent(void *nsrv, void *nscb, va_list ap) | | 728 | _dns_setgrent(void *nsrv, void *nscb, va_list ap) |
726 | { | | 729 | { |
727 | | | 730 | |
728 | _dns_state.stayopen = 0; | | 731 | _dns_state.stayopen = 0; |
729 | return __grstart_dns(&_dns_state); | | 732 | return __grstart_dns(&_dns_state); |
730 | } | | 733 | } |
731 | | | 734 | |
732 | /*ARGSUSED*/ | | 735 | /*ARGSUSED*/ |
733 | static int | | 736 | static int |
734 | _dns_setgroupent(void *nsrv, void *nscb, va_list ap) | | 737 | _dns_setgroupent(void *nsrv, void *nscb, va_list ap) |
735 | { | | 738 | { |
736 | int *retval = va_arg(ap, int *); | | 739 | int *retval = va_arg(ap, int *); |
737 | int stayopen = va_arg(ap, int); | | 740 | int stayopen = va_arg(ap, int); |
738 | | | 741 | |
739 | int rv; | | 742 | int rv; |
740 | | | 743 | |
741 | _dns_state.stayopen = stayopen; | | 744 | _dns_state.stayopen = stayopen; |
742 | rv = __grstart_dns(&_dns_state); | | 745 | rv = __grstart_dns(&_dns_state); |
743 | *retval = (rv == NS_SUCCESS); | | 746 | *retval = (rv == NS_SUCCESS); |
744 | return rv; | | 747 | return rv; |
745 | } | | 748 | } |
746 | | | 749 | |
747 | /*ARGSUSED*/ | | 750 | /*ARGSUSED*/ |
748 | static int | | 751 | static int |
749 | _dns_endgrent(void *nsrv, void *nscb, va_list ap) | | 752 | _dns_endgrent(void *nsrv, void *nscb, va_list ap) |
750 | { | | 753 | { |
751 | | | 754 | |
752 | _dns_state.stayopen = 0; | | 755 | _dns_state.stayopen = 0; |
753 | return __grend_dns(&_dns_state); | | 756 | return __grend_dns(&_dns_state); |
754 | } | | 757 | } |
755 | | | 758 | |
756 | /*ARGSUSED*/ | | 759 | /*ARGSUSED*/ |
757 | static int | | 760 | static int |
758 | _dns_getgrent(void *nsrv, void *nscb, va_list ap) | | 761 | _dns_getgrent(void *nsrv, void *nscb, va_list ap) |
759 | { | | 762 | { |
760 | struct group **retval = va_arg(ap, struct group **); | | 763 | struct group **retval = va_arg(ap, struct group **); |
761 | | | 764 | |
762 | int rv, rerror; | | 765 | int rv, rerror; |
763 | | | 766 | |
764 | _DIAGASSERT(retval != NULL); | | 767 | _DIAGASSERT(retval != NULL); |
765 | | | 768 | |
766 | *retval = NULL; | | 769 | *retval = NULL; |
767 | rv = __grscan_dns(&rerror, &_dns_group, | | 770 | rv = __grscan_dns(&rerror, &_dns_group, |
768 | _dns_groupbuf, sizeof(_dns_groupbuf), &_dns_state, 0, NULL, 0); | | 771 | _dns_groupbuf, sizeof(_dns_groupbuf), &_dns_state, 0, NULL, 0); |
769 | if (rv == NS_SUCCESS) | | 772 | if (rv == NS_SUCCESS) |
770 | *retval = &_dns_group; | | 773 | *retval = &_dns_group; |
771 | return rv; | | 774 | return rv; |
772 | } | | 775 | } |
773 | | | 776 | |
774 | /*ARGSUSED*/ | | 777 | /*ARGSUSED*/ |
775 | static int | | 778 | static int |
776 | _dns_getgrent_r(void *nsrv, void *nscb, va_list ap) | | 779 | _dns_getgrent_r(void *nsrv, void *nscb, va_list ap) |
777 | { | | 780 | { |
778 | int *retval = va_arg(ap, int *); | | 781 | int *retval = va_arg(ap, int *); |
779 | struct group *grp = va_arg(ap, struct group *); | | 782 | struct group *grp = va_arg(ap, struct group *); |
780 | char *buffer = va_arg(ap, char *); | | 783 | char *buffer = va_arg(ap, char *); |
781 | size_t buflen = va_arg(ap, size_t); | | 784 | size_t buflen = va_arg(ap, size_t); |
782 | struct group **result = va_arg(ap, struct group **); | | 785 | struct group **result = va_arg(ap, struct group **); |
783 | | | 786 | |
784 | int rv; | | 787 | int rv; |
785 | | | 788 | |
786 | _DIAGASSERT(retval != NULL); | | 789 | _DIAGASSERT(retval != NULL); |
787 | _DIAGASSERT(grp != NULL); | | 790 | _DIAGASSERT(grp != NULL); |
788 | _DIAGASSERT(buffer != NULL); | | 791 | _DIAGASSERT(buffer != NULL); |
789 | _DIAGASSERT(result != NULL); | | 792 | _DIAGASSERT(result != NULL); |
790 | | | 793 | |
791 | rv = __grscan_dns(retval, grp, buffer, buflen, | | 794 | rv = __grscan_dns(retval, grp, buffer, buflen, |
792 | &_dns_state, 0, NULL, 0); | | 795 | &_dns_state, 0, NULL, 0); |
793 | if (rv == NS_SUCCESS) | | 796 | if (rv == NS_SUCCESS) |
794 | *result = grp; | | 797 | *result = grp; |
795 | else | | 798 | else |
796 | *result = NULL; | | 799 | *result = NULL; |
797 | return rv; | | 800 | return rv; |
798 | } | | 801 | } |
799 | /*ARGSUSED*/ | | 802 | /*ARGSUSED*/ |
800 | static int | | 803 | static int |
801 | _dns_getgrgid(void *nsrv, void *nscb, va_list ap) | | 804 | _dns_getgrgid(void *nsrv, void *nscb, va_list ap) |
802 | { | | 805 | { |
803 | struct group **retval = va_arg(ap, struct group **); | | 806 | struct group **retval = va_arg(ap, struct group **); |
804 | gid_t gid = va_arg(ap, gid_t); | | 807 | gid_t gid = va_arg(ap, gid_t); |
805 | | | 808 | |
806 | int rv, rerror; | | 809 | int rv, rerror; |
807 | | | 810 | |
808 | _DIAGASSERT(retval != NULL); | | 811 | _DIAGASSERT(retval != NULL); |
809 | | | 812 | |
810 | *retval = NULL; | | 813 | *retval = NULL; |
811 | rv = __grstart_dns(&_dns_state); | | 814 | rv = __grstart_dns(&_dns_state); |
812 | if (rv != NS_SUCCESS) | | 815 | if (rv != NS_SUCCESS) |
813 | return rv; | | 816 | return rv; |
814 | rv = __grscan_dns(&rerror, &_dns_group, | | 817 | rv = __grscan_dns(&rerror, &_dns_group, |
815 | _dns_groupbuf, sizeof(_dns_groupbuf), &_dns_state, 1, NULL, gid); | | 818 | _dns_groupbuf, sizeof(_dns_groupbuf), &_dns_state, 1, NULL, gid); |
816 | if (!_dns_state.stayopen) | | 819 | if (!_dns_state.stayopen) |
817 | __grend_dns(&_dns_state); | | 820 | __grend_dns(&_dns_state); |
818 | if (rv == NS_SUCCESS) | | 821 | if (rv == NS_SUCCESS) |
819 | *retval = &_dns_group; | | 822 | *retval = &_dns_group; |
820 | return rv; | | 823 | return rv; |
821 | } | | 824 | } |
822 | | | 825 | |
823 | /*ARGSUSED*/ | | 826 | /*ARGSUSED*/ |
824 | static int | | 827 | static int |
825 | _dns_getgrgid_r(void *nsrv, void *nscb, va_list ap) | | 828 | _dns_getgrgid_r(void *nsrv, void *nscb, va_list ap) |
826 | { | | 829 | { |
827 | int *retval = va_arg(ap, int *); | | 830 | int *retval = va_arg(ap, int *); |
828 | gid_t gid = va_arg(ap, gid_t); | | 831 | gid_t gid = va_arg(ap, gid_t); |
829 | struct group *grp = va_arg(ap, struct group *); | | 832 | struct group *grp = va_arg(ap, struct group *); |
830 | char *buffer = va_arg(ap, char *); | | 833 | char *buffer = va_arg(ap, char *); |
831 | size_t buflen = va_arg(ap, size_t); | | 834 | size_t buflen = va_arg(ap, size_t); |
832 | struct group **result = va_arg(ap, struct group **); | | 835 | struct group **result = va_arg(ap, struct group **); |
833 | | | 836 | |
834 | struct __grstate_dns state; | | 837 | struct __grstate_dns state; |
835 | int rv; | | 838 | int rv; |
836 | | | 839 | |
837 | _DIAGASSERT(retval != NULL); | | 840 | _DIAGASSERT(retval != NULL); |
838 | _DIAGASSERT(grp != NULL); | | 841 | _DIAGASSERT(grp != NULL); |
839 | _DIAGASSERT(buffer != NULL); | | 842 | _DIAGASSERT(buffer != NULL); |
840 | _DIAGASSERT(result != NULL); | | 843 | _DIAGASSERT(result != NULL); |
841 | | | 844 | |
842 | *result = NULL; | | 845 | *result = NULL; |
843 | memset(&state, 0, sizeof(state)); | | 846 | memset(&state, 0, sizeof(state)); |
844 | rv = __grscan_dns(retval, grp, buffer, buflen, &state, 1, NULL, gid); | | 847 | rv = __grscan_dns(retval, grp, buffer, buflen, &state, 1, NULL, gid); |
845 | __grend_dns(&state); | | 848 | __grend_dns(&state); |
846 | if (rv == NS_SUCCESS) | | 849 | if (rv == NS_SUCCESS) |
847 | *result = grp; | | 850 | *result = grp; |
848 | return rv; | | 851 | return rv; |
849 | } | | 852 | } |
850 | | | 853 | |
851 | /*ARGSUSED*/ | | 854 | /*ARGSUSED*/ |
852 | static int | | 855 | static int |
853 | _dns_getgrnam(void *nsrv, void *nscb, va_list ap) | | 856 | _dns_getgrnam(void *nsrv, void *nscb, va_list ap) |
854 | { | | 857 | { |
855 | struct group **retval = va_arg(ap, struct group **); | | 858 | struct group **retval = va_arg(ap, struct group **); |
856 | const char *name = va_arg(ap, const char *); | | 859 | const char *name = va_arg(ap, const char *); |
857 | | | 860 | |
858 | int rv, rerror; | | 861 | int rv, rerror; |
859 | | | 862 | |
860 | _DIAGASSERT(retval != NULL); | | 863 | _DIAGASSERT(retval != NULL); |
861 | | | 864 | |
862 | *retval = NULL; | | 865 | *retval = NULL; |
863 | rv = __grstart_dns(&_dns_state); | | 866 | rv = __grstart_dns(&_dns_state); |
864 | if (rv != NS_SUCCESS) | | 867 | if (rv != NS_SUCCESS) |
865 | return rv; | | 868 | return rv; |
866 | rv = __grscan_dns(&rerror, &_dns_group, | | 869 | rv = __grscan_dns(&rerror, &_dns_group, |
867 | _dns_groupbuf, sizeof(_dns_groupbuf), &_dns_state, 1, name, 0); | | 870 | _dns_groupbuf, sizeof(_dns_groupbuf), &_dns_state, 1, name, 0); |
868 | if (!_dns_state.stayopen) | | 871 | if (!_dns_state.stayopen) |
869 | __grend_dns(&_dns_state); | | 872 | __grend_dns(&_dns_state); |
870 | if (rv == NS_SUCCESS) | | 873 | if (rv == NS_SUCCESS) |
871 | *retval = &_dns_group; | | 874 | *retval = &_dns_group; |
872 | return rv; | | 875 | return rv; |
873 | } | | 876 | } |
874 | | | 877 | |
875 | /*ARGSUSED*/ | | 878 | /*ARGSUSED*/ |
876 | static int | | 879 | static int |
877 | _dns_getgrnam_r(void *nsrv, void *nscb, va_list ap) | | 880 | _dns_getgrnam_r(void *nsrv, void *nscb, va_list ap) |
878 | { | | 881 | { |
879 | int *retval = va_arg(ap, int *); | | 882 | int *retval = va_arg(ap, int *); |
880 | const char *name = va_arg(ap, const char *); | | 883 | const char *name = va_arg(ap, const char *); |
881 | struct group *grp = va_arg(ap, struct group *); | | 884 | struct group *grp = va_arg(ap, struct group *); |
882 | char *buffer = va_arg(ap, char *); | | 885 | char *buffer = va_arg(ap, char *); |
883 | size_t buflen = va_arg(ap, size_t); | | 886 | size_t buflen = va_arg(ap, size_t); |
884 | struct group **result = va_arg(ap, struct group **); | | 887 | struct group **result = va_arg(ap, struct group **); |
885 | | | 888 | |
886 | struct __grstate_dns state; | | 889 | struct __grstate_dns state; |
887 | int rv; | | 890 | int rv; |
888 | | | 891 | |
889 | _DIAGASSERT(retval != NULL); | | 892 | _DIAGASSERT(retval != NULL); |
890 | _DIAGASSERT(grp != NULL); | | 893 | _DIAGASSERT(grp != NULL); |
891 | _DIAGASSERT(buffer != NULL); | | 894 | _DIAGASSERT(buffer != NULL); |
892 | _DIAGASSERT(result != NULL); | | 895 | _DIAGASSERT(result != NULL); |
893 | | | 896 | |
894 | *result = NULL; | | 897 | *result = NULL; |
895 | memset(&state, 0, sizeof(state)); | | 898 | memset(&state, 0, sizeof(state)); |
896 | rv = __grscan_dns(retval, grp, buffer, buflen, &state, 1, name, 0); | | 899 | rv = __grscan_dns(retval, grp, buffer, buflen, &state, 1, name, 0); |
897 | __grend_dns(&state); | | 900 | __grend_dns(&state); |
898 | if (rv == NS_SUCCESS) | | 901 | if (rv == NS_SUCCESS) |
899 | *result = grp; | | 902 | *result = grp; |
900 | return rv; | | 903 | return rv; |
901 | } | | 904 | } |
902 | | | 905 | |
903 | #endif /* HESIOD */ | | 906 | #endif /* HESIOD */ |
904 | | | 907 | |
905 | | | 908 | |
906 | #ifdef YP | | 909 | #ifdef YP |
907 | /* | | 910 | /* |
908 | * nis methods | | 911 | * nis methods |
909 | */ | | 912 | */ |
910 | | | 913 | |
911 | int | | 914 | int |
912 | __grstart_nis(struct __grstate_nis *state) | | 915 | __grstart_nis(struct __grstate_nis *state) |
913 | { | | 916 | { |
914 | | | 917 | |
915 | _DIAGASSERT(state != NULL); | | 918 | _DIAGASSERT(state != NULL); |
916 | | | 919 | |
917 | state->done = 0; | | 920 | state->done = 0; |
918 | if (state->current) { | | 921 | if (state->current) { |
919 | free(state->current); | | 922 | free(state->current); |
920 | state->current = NULL; | | 923 | state->current = NULL; |
921 | } | | 924 | } |
922 | if (state->domain == NULL) { /* setup NIS */ | | 925 | if (state->domain == NULL) { /* setup NIS */ |
923 | switch (yp_get_default_domain(&state->domain)) { | | 926 | switch (yp_get_default_domain(&state->domain)) { |
924 | case 0: | | 927 | case 0: |
925 | break; | | 928 | break; |
926 | case YPERR_RESRC: | | 929 | case YPERR_RESRC: |
927 | return NS_TRYAGAIN; | | 930 | return NS_TRYAGAIN; |
928 | default: | | 931 | default: |
929 | return NS_UNAVAIL; | | 932 | return NS_UNAVAIL; |
930 | } | | 933 | } |
931 | } | | 934 | } |
932 | return NS_SUCCESS; | | 935 | return NS_SUCCESS; |
933 | } | | 936 | } |
934 | | | 937 | |
935 | int | | 938 | int |
936 | __grend_nis(struct __grstate_nis *state) | | 939 | __grend_nis(struct __grstate_nis *state) |
937 | { | | 940 | { |
938 | | | 941 | |
939 | _DIAGASSERT(state != NULL); | | 942 | _DIAGASSERT(state != NULL); |
940 | | | 943 | |
941 | if (state->domain) { | | 944 | if (state->domain) { |
942 | state->domain = NULL; | | 945 | state->domain = NULL; |
943 | } | | 946 | } |
944 | state->done = 0; | | 947 | state->done = 0; |
945 | if (state->current) { | | 948 | if (state->current) { |
946 | free(state->current); | | 949 | free(state->current); |
947 | state->current = NULL; | | 950 | state->current = NULL; |
948 | } | | 951 | } |
949 | return NS_SUCCESS; | | 952 | return NS_SUCCESS; |
950 | } | | 953 | } |
951 | | | 954 | |
952 | /* | | 955 | /* |
953 | * __grscan_nis | | 956 | * __grscan_nis |
954 | * Search NIS for the next desired entry. | | 957 | * Search NIS for the next desired entry. |
955 | * If search is zero, return the next entry. | | 958 | * If search is zero, return the next entry. |
956 | * If search is non-zero, look for a specific name (if name != NULL), | | 959 | * If search is non-zero, look for a specific name (if name != NULL), |
957 | * or a specific gid (if name == NULL). | | 960 | * or a specific gid (if name == NULL). |
958 | */ | | 961 | */ |
959 | int | | 962 | int |
960 | __grscan_nis(int *retval, struct group *grp, char *buffer, size_t buflen, | | 963 | __grscan_nis(int *retval, struct group *grp, char *buffer, size_t buflen, |
961 | struct __grstate_nis *state, int search, const char *name, gid_t gid) | | 964 | struct __grstate_nis *state, int search, const char *name, gid_t gid) |
962 | { | | 965 | { |
963 | const char *map; | | 966 | const char *map; |
964 | char *key, *data; | | 967 | char *key, *data; |
965 | int nisr, rv, keylen, datalen; | | 968 | int nisr, rv, keylen, datalen; |
966 | | | 969 | |
967 | _DIAGASSERT(retval != NULL); | | 970 | _DIAGASSERT(retval != NULL); |
968 | _DIAGASSERT(grp != NULL); | | 971 | _DIAGASSERT(grp != NULL); |
969 | _DIAGASSERT(buffer != NULL); | | 972 | _DIAGASSERT(buffer != NULL); |
970 | _DIAGASSERT(state != NULL); | | 973 | _DIAGASSERT(state != NULL); |
971 | /* name is NULL to indicate searching for gid */ | | 974 | /* name is NULL to indicate searching for gid */ |
972 | | | 975 | |
973 | *retval = 0; | | 976 | *retval = 0; |
974 | | | 977 | |
975 | if (state->domain == NULL) { /* only start if NIS not setup */ | | 978 | if (state->domain == NULL) { /* only start if NIS not setup */ |
976 | rv = __grstart_nis(state); | | 979 | rv = __grstart_nis(state); |
977 | if (rv != NS_SUCCESS) | | 980 | if (rv != NS_SUCCESS) |
978 | return rv; | | 981 | return rv; |
979 | } | | 982 | } |
980 | | | 983 | |
981 | next_nis_entry: | | 984 | next_nis_entry: |
982 | key = NULL; | | 985 | key = NULL; |
983 | data = NULL; | | 986 | data = NULL; |
984 | rv = NS_SUCCESS; | | 987 | rv = NS_SUCCESS; |
985 | | | 988 | |
986 | if (! search) { /* find next entry */ | | 989 | if (! search) { /* find next entry */ |
987 | if (state->done) /* exhausted search */ | | 990 | if (state->done) /* exhausted search */ |
988 | return NS_NOTFOUND; | | 991 | return NS_NOTFOUND; |
989 | map = "group.byname"; | | 992 | map = "group.byname"; |
990 | if (state->current) { /* already searching */ | | 993 | if (state->current) { /* already searching */ |
991 | nisr = yp_next(state->domain, map, | | 994 | nisr = yp_next(state->domain, map, |
992 | state->current, state->currentlen, | | 995 | state->current, state->currentlen, |
993 | &key, &keylen, &data, &datalen); | | 996 | &key, &keylen, &data, &datalen); |
994 | free(state->current); | | 997 | free(state->current); |
995 | state->current = NULL; | | 998 | state->current = NULL; |
996 | switch (nisr) { | | 999 | switch (nisr) { |
997 | case 0: | | 1000 | case 0: |
998 | state->current = key; | | 1001 | state->current = key; |
999 | state->currentlen = keylen; | | 1002 | state->currentlen = keylen; |
1000 | key = NULL; | | 1003 | key = NULL; |
1001 | break; | | 1004 | break; |
1002 | case YPERR_NOMORE: | | 1005 | case YPERR_NOMORE: |
1003 | rv = NS_NOTFOUND; | | 1006 | rv = NS_NOTFOUND; |
1004 | state->done = 1; | | 1007 | state->done = 1; |
1005 | break; | | 1008 | break; |
1006 | default: | | 1009 | default: |
1007 | rv = NS_UNAVAIL; | | 1010 | rv = NS_UNAVAIL; |
1008 | break; | | 1011 | break; |
1009 | } | | 1012 | } |
1010 | } else { /* new search */ | | 1013 | } else { /* new search */ |
1011 | if (yp_first(state->domain, map, | | 1014 | if (yp_first(state->domain, map, |
1012 | &state->current, &state->currentlen, | | 1015 | &state->current, &state->currentlen, |
1013 | &data, &datalen)) { | | 1016 | &data, &datalen)) { |
1014 | rv = NS_UNAVAIL; | | 1017 | rv = NS_UNAVAIL; |
1015 | } | | 1018 | } |
1016 | } | | 1019 | } |
1017 | } else { /* search for specific item */ | | 1020 | } else { /* search for specific item */ |
1018 | if (name) { /* find group name */ | | 1021 | if (name) { /* find group name */ |
1019 | snprintf(buffer, buflen, "%s", name); | | 1022 | snprintf(buffer, buflen, "%s", name); |
1020 | map = "group.byname"; | | 1023 | map = "group.byname"; |
1021 | } else { /* find gid */ | | 1024 | } else { /* find gid */ |
1022 | snprintf(buffer, buflen, "%u", (unsigned int)gid); | | 1025 | snprintf(buffer, buflen, "%u", (unsigned int)gid); |
1023 | map = "group.bygid"; | | 1026 | map = "group.bygid"; |
1024 | } | | 1027 | } |
1025 | nisr = yp_match(state->domain, map, buffer, (int)strlen(buffer), | | 1028 | nisr = yp_match(state->domain, map, buffer, (int)strlen(buffer), |
1026 | &data, &datalen); | | 1029 | &data, &datalen); |
1027 | switch (nisr) { | | 1030 | switch (nisr) { |
1028 | case 0: | | 1031 | case 0: |
1029 | break; | | 1032 | break; |
1030 | case YPERR_KEY: | | 1033 | case YPERR_KEY: |
1031 | rv = NS_NOTFOUND; | | 1034 | rv = NS_NOTFOUND; |
1032 | break; | | 1035 | break; |
1033 | default: | | 1036 | default: |
1034 | rv = NS_UNAVAIL; | | 1037 | rv = NS_UNAVAIL; |
1035 | break; | | 1038 | break; |
1036 | } | | 1039 | } |
1037 | } | | 1040 | } |
1038 | if (rv == NS_SUCCESS) { /* validate data */ | | 1041 | if (rv == NS_SUCCESS) { /* validate data */ |
1039 | data[datalen] = '\0'; /* clear trailing \n */ | | 1042 | data[datalen] = '\0'; /* clear trailing \n */ |
1040 | if (_gr_parse(data, grp, buffer, buflen)) { | | 1043 | if (_gr_parse(data, grp, buffer, buflen)) { |
1041 | if (! search) { /* just want this one */ | | 1044 | if (! search) { /* just want this one */ |
1042 | rv = NS_SUCCESS; | | 1045 | rv = NS_SUCCESS; |
1043 | } else if ((name && strcmp(name, grp->gr_name) == 0) || | | 1046 | } else if ((name && strcmp(name, grp->gr_name) == 0) || |
1044 | (!name && gid == grp->gr_gid)) { | | 1047 | (!name && gid == grp->gr_gid)) { |
1045 | /* want specific */ | | 1048 | /* want specific */ |
1046 | rv = NS_SUCCESS; | | 1049 | rv = NS_SUCCESS; |
1047 | } | | 1050 | } |
1048 | } else { /* dodgy entry */ | | 1051 | } else { /* dodgy entry */ |
1049 | if (!search) { /* try again if ! searching */ | | 1052 | if (!search) { /* try again if ! searching */ |
1050 | free(data); | | 1053 | free(data); |
1051 | goto next_nis_entry; | | 1054 | goto next_nis_entry; |
1052 | } | | 1055 | } |
1053 | } | | 1056 | } |
1054 | } | | 1057 | } |
1055 | | | 1058 | |
1056 | if (rv != NS_SUCCESS && rv != NS_NOTFOUND) | | 1059 | if (rv != NS_SUCCESS && rv != NS_NOTFOUND) |
1057 | *retval = errno; | | 1060 | *retval = errno; |
1058 | if (key) | | 1061 | if (key) |
1059 | free(key); | | 1062 | free(key); |
1060 | if (data) | | 1063 | if (data) |
1061 | free(data); | | 1064 | free(data); |
1062 | return rv; | | 1065 | return rv; |
1063 | } | | 1066 | } |
1064 | | | 1067 | |
1065 | static struct __grstate_nis _nis_state; | | 1068 | static struct __grstate_nis _nis_state; |
1066 | /* storage for non _r functions */ | | 1069 | /* storage for non _r functions */ |
1067 | static struct group _nis_group; | | 1070 | static struct group _nis_group; |
1068 | static char _nis_groupbuf[_GETGR_R_SIZE_MAX]; | | 1071 | static char _nis_groupbuf[_GETGR_R_SIZE_MAX]; |
1069 | | | 1072 | |
1070 | /*ARGSUSED*/ | | 1073 | /*ARGSUSED*/ |
1071 | static int | | 1074 | static int |
1072 | _nis_setgrent(void *nsrv, void *nscb, va_list ap) | | 1075 | _nis_setgrent(void *nsrv, void *nscb, va_list ap) |
1073 | { | | 1076 | { |
1074 | | | 1077 | |
1075 | _nis_state.stayopen = 0; | | 1078 | _nis_state.stayopen = 0; |
1076 | return __grstart_nis(&_nis_state); | | 1079 | return __grstart_nis(&_nis_state); |
1077 | } | | 1080 | } |
1078 | | | 1081 | |
1079 | /*ARGSUSED*/ | | 1082 | /*ARGSUSED*/ |
1080 | static int | | 1083 | static int |
1081 | _nis_setgroupent(void *nsrv, void *nscb, va_list ap) | | 1084 | _nis_setgroupent(void *nsrv, void *nscb, va_list ap) |
1082 | { | | 1085 | { |
1083 | int *retval = va_arg(ap, int *); | | 1086 | int *retval = va_arg(ap, int *); |
1084 | int stayopen = va_arg(ap, int); | | 1087 | int stayopen = va_arg(ap, int); |
1085 | | | 1088 | |
1086 | int rv; | | 1089 | int rv; |
1087 | | | 1090 | |
1088 | _nis_state.stayopen = stayopen; | | 1091 | _nis_state.stayopen = stayopen; |
1089 | rv = __grstart_nis(&_nis_state); | | 1092 | rv = __grstart_nis(&_nis_state); |
1090 | *retval = (rv == NS_SUCCESS); | | 1093 | *retval = (rv == NS_SUCCESS); |
1091 | return rv; | | 1094 | return rv; |
1092 | } | | 1095 | } |
1093 | | | 1096 | |
1094 | /*ARGSUSED*/ | | 1097 | /*ARGSUSED*/ |
1095 | static int | | 1098 | static int |
1096 | _nis_endgrent(void *nsrv, void *nscb, va_list ap) | | 1099 | _nis_endgrent(void *nsrv, void *nscb, va_list ap) |
1097 | { | | 1100 | { |
1098 | | | 1101 | |
1099 | return __grend_nis(&_nis_state); | | 1102 | return __grend_nis(&_nis_state); |
1100 | } | | 1103 | } |
1101 | | | 1104 | |
1102 | /*ARGSUSED*/ | | 1105 | /*ARGSUSED*/ |
1103 | static int | | 1106 | static int |
1104 | _nis_getgrent(void *nsrv, void *nscb, va_list ap) | | 1107 | _nis_getgrent(void *nsrv, void *nscb, va_list ap) |
1105 | { | | 1108 | { |
1106 | struct group **retval = va_arg(ap, struct group **); | | 1109 | struct group **retval = va_arg(ap, struct group **); |
1107 | | | 1110 | |
1108 | int rv, rerror; | | 1111 | int rv, rerror; |
1109 | | | 1112 | |
1110 | _DIAGASSERT(retval != NULL); | | 1113 | _DIAGASSERT(retval != NULL); |
1111 | | | 1114 | |
1112 | *retval = NULL; | | 1115 | *retval = NULL; |
1113 | rv = __grscan_nis(&rerror, &_nis_group, | | 1116 | rv = __grscan_nis(&rerror, &_nis_group, |
1114 | _nis_groupbuf, sizeof(_nis_groupbuf), &_nis_state, 0, NULL, 0); | | 1117 | _nis_groupbuf, sizeof(_nis_groupbuf), &_nis_state, 0, NULL, 0); |
1115 | if (rv == NS_SUCCESS) | | 1118 | if (rv == NS_SUCCESS) |
1116 | *retval = &_nis_group; | | 1119 | *retval = &_nis_group; |
1117 | return rv; | | 1120 | return rv; |
1118 | } | | 1121 | } |
1119 | | | 1122 | |
1120 | /*ARGSUSED*/ | | 1123 | /*ARGSUSED*/ |
1121 | static int | | 1124 | static int |
1122 | _nis_getgrent_r(void *nsrv, void *nscb, va_list ap) | | 1125 | _nis_getgrent_r(void *nsrv, void *nscb, va_list ap) |
1123 | { | | 1126 | { |
1124 | int *retval = va_arg(ap, int *); | | 1127 | int *retval = va_arg(ap, int *); |
1125 | struct group *grp = va_arg(ap, struct group *); | | 1128 | struct group *grp = va_arg(ap, struct group *); |
1126 | char *buffer = va_arg(ap, char *); | | 1129 | char *buffer = va_arg(ap, char *); |
1127 | size_t buflen = va_arg(ap, size_t); | | 1130 | size_t buflen = va_arg(ap, size_t); |
1128 | struct group **result = va_arg(ap, struct group **); | | 1131 | struct group **result = va_arg(ap, struct group **); |
1129 | | | 1132 | |
1130 | int rv; | | 1133 | int rv; |
1131 | | | 1134 | |
1132 | _DIAGASSERT(retval != NULL); | | 1135 | _DIAGASSERT(retval != NULL); |
1133 | _DIAGASSERT(grp != NULL); | | 1136 | _DIAGASSERT(grp != NULL); |
1134 | _DIAGASSERT(buffer != NULL); | | 1137 | _DIAGASSERT(buffer != NULL); |
1135 | _DIAGASSERT(result != NULL); | | 1138 | _DIAGASSERT(result != NULL); |
1136 | | | 1139 | |
1137 | rv = __grscan_nis(retval, grp, buffer, buflen, | | 1140 | rv = __grscan_nis(retval, grp, buffer, buflen, |
1138 | &_nis_state, 0, NULL, 0); | | 1141 | &_nis_state, 0, NULL, 0); |
1139 | if (rv == NS_SUCCESS) | | 1142 | if (rv == NS_SUCCESS) |
1140 | *result = grp; | | 1143 | *result = grp; |
1141 | else | | 1144 | else |
1142 | *result = NULL; | | 1145 | *result = NULL; |
1143 | return rv; | | 1146 | return rv; |
1144 | } | | 1147 | } |
1145 | | | 1148 | |
1146 | /*ARGSUSED*/ | | 1149 | /*ARGSUSED*/ |
1147 | static int | | 1150 | static int |
1148 | _nis_getgrgid(void *nsrv, void *nscb, va_list ap) | | 1151 | _nis_getgrgid(void *nsrv, void *nscb, va_list ap) |
1149 | { | | 1152 | { |
1150 | struct group **retval = va_arg(ap, struct group **); | | 1153 | struct group **retval = va_arg(ap, struct group **); |
1151 | gid_t gid = va_arg(ap, gid_t); | | 1154 | gid_t gid = va_arg(ap, gid_t); |
1152 | | | 1155 | |
1153 | int rv, rerror; | | 1156 | int rv, rerror; |
1154 | | | 1157 | |
1155 | _DIAGASSERT(retval != NULL); | | 1158 | _DIAGASSERT(retval != NULL); |
1156 | | | 1159 | |
1157 | *retval = NULL; | | 1160 | *retval = NULL; |
1158 | rv = __grstart_nis(&_nis_state); | | 1161 | rv = __grstart_nis(&_nis_state); |
1159 | if (rv != NS_SUCCESS) | | 1162 | if (rv != NS_SUCCESS) |
1160 | return rv; | | 1163 | return rv; |
1161 | rv = __grscan_nis(&rerror, &_nis_group, | | 1164 | rv = __grscan_nis(&rerror, &_nis_group, |
1162 | _nis_groupbuf, sizeof(_nis_groupbuf), &_nis_state, 1, NULL, gid); | | 1165 | _nis_groupbuf, sizeof(_nis_groupbuf), &_nis_state, 1, NULL, gid); |
1163 | if (!_nis_state.stayopen) | | 1166 | if (!_nis_state.stayopen) |
1164 | __grend_nis(&_nis_state); | | 1167 | __grend_nis(&_nis_state); |
1165 | if (rv == NS_SUCCESS) | | 1168 | if (rv == NS_SUCCESS) |
1166 | *retval = &_nis_group; | | 1169 | *retval = &_nis_group; |
1167 | return rv; | | 1170 | return rv; |
1168 | } | | 1171 | } |
1169 | | | 1172 | |
1170 | /*ARGSUSED*/ | | 1173 | /*ARGSUSED*/ |
1171 | static int | | 1174 | static int |
1172 | _nis_getgrgid_r(void *nsrv, void *nscb, va_list ap) | | 1175 | _nis_getgrgid_r(void *nsrv, void *nscb, va_list ap) |
1173 | { | | 1176 | { |
1174 | int *retval = va_arg(ap, int *); | | 1177 | int *retval = va_arg(ap, int *); |
1175 | gid_t gid = va_arg(ap, gid_t); | | 1178 | gid_t gid = va_arg(ap, gid_t); |
1176 | struct group *grp = va_arg(ap, struct group *); | | 1179 | struct group *grp = va_arg(ap, struct group *); |
1177 | char *buffer = va_arg(ap, char *); | | 1180 | char *buffer = va_arg(ap, char *); |
1178 | size_t buflen = va_arg(ap, size_t); | | 1181 | size_t buflen = va_arg(ap, size_t); |
1179 | struct group **result = va_arg(ap, struct group **); | | 1182 | struct group **result = va_arg(ap, struct group **); |
1180 | | | 1183 | |
1181 | struct __grstate_nis state; | | 1184 | struct __grstate_nis state; |
1182 | int rv; | | 1185 | int rv; |
1183 | | | 1186 | |
1184 | _DIAGASSERT(retval != NULL); | | 1187 | _DIAGASSERT(retval != NULL); |
1185 | _DIAGASSERT(grp != NULL); | | 1188 | _DIAGASSERT(grp != NULL); |
1186 | _DIAGASSERT(buffer != NULL); | | 1189 | _DIAGASSERT(buffer != NULL); |
1187 | _DIAGASSERT(result != NULL); | | 1190 | _DIAGASSERT(result != NULL); |
1188 | | | 1191 | |
1189 | *result = NULL; | | 1192 | *result = NULL; |
1190 | memset(&state, 0, sizeof(state)); | | 1193 | memset(&state, 0, sizeof(state)); |
1191 | rv = __grscan_nis(retval, grp, buffer, buflen, &state, 1, NULL, gid); | | 1194 | rv = __grscan_nis(retval, grp, buffer, buflen, &state, 1, NULL, gid); |
1192 | __grend_nis(&state); | | 1195 | __grend_nis(&state); |
1193 | if (rv == NS_SUCCESS) | | 1196 | if (rv == NS_SUCCESS) |
1194 | *result = grp; | | 1197 | *result = grp; |
1195 | return rv; | | 1198 | return rv; |
1196 | } | | 1199 | } |
1197 | | | 1200 | |
1198 | /*ARGSUSED*/ | | 1201 | /*ARGSUSED*/ |
1199 | static int | | 1202 | static int |
1200 | _nis_getgrnam(void *nsrv, void *nscb, va_list ap) | | 1203 | _nis_getgrnam(void *nsrv, void *nscb, va_list ap) |
1201 | { | | 1204 | { |
1202 | struct group **retval = va_arg(ap, struct group **); | | 1205 | struct group **retval = va_arg(ap, struct group **); |
1203 | const char *name = va_arg(ap, const char *); | | 1206 | const char *name = va_arg(ap, const char *); |
1204 | | | 1207 | |
1205 | int rv, rerror; | | 1208 | int rv, rerror; |
1206 | | | 1209 | |
1207 | _DIAGASSERT(retval != NULL); | | 1210 | _DIAGASSERT(retval != NULL); |
1208 | | | 1211 | |
1209 | *retval = NULL; | | 1212 | *retval = NULL; |
1210 | rv = __grstart_nis(&_nis_state); | | 1213 | rv = __grstart_nis(&_nis_state); |
1211 | if (rv != NS_SUCCESS) | | 1214 | if (rv != NS_SUCCESS) |
1212 | return rv; | | 1215 | return rv; |
1213 | rv = __grscan_nis(&rerror, &_nis_group, | | 1216 | rv = __grscan_nis(&rerror, &_nis_group, |
1214 | _nis_groupbuf, sizeof(_nis_groupbuf), &_nis_state, 1, name, 0); | | 1217 | _nis_groupbuf, sizeof(_nis_groupbuf), &_nis_state, 1, name, 0); |
1215 | if (!_nis_state.stayopen) | | 1218 | if (!_nis_state.stayopen) |
1216 | __grend_nis(&_nis_state); | | 1219 | __grend_nis(&_nis_state); |
1217 | if (rv == NS_SUCCESS) | | 1220 | if (rv == NS_SUCCESS) |
1218 | *retval = &_nis_group; | | 1221 | *retval = &_nis_group; |
1219 | return rv; | | 1222 | return rv; |
1220 | } | | 1223 | } |
1221 | | | 1224 | |
1222 | /*ARGSUSED*/ | | 1225 | /*ARGSUSED*/ |
1223 | static int | | 1226 | static int |
1224 | _nis_getgrnam_r(void *nsrv, void *nscb, va_list ap) | | 1227 | _nis_getgrnam_r(void *nsrv, void *nscb, va_list ap) |
1225 | { | | 1228 | { |
1226 | int *retval = va_arg(ap, int *); | | 1229 | int *retval = va_arg(ap, int *); |
1227 | const char *name = va_arg(ap, const char *); | | 1230 | const char *name = va_arg(ap, const char *); |
1228 | struct group *grp = va_arg(ap, struct group *); | | 1231 | struct group *grp = va_arg(ap, struct group *); |
1229 | char *buffer = va_arg(ap, char *); | | 1232 | char *buffer = va_arg(ap, char *); |
1230 | size_t buflen = va_arg(ap, size_t); | | 1233 | size_t buflen = va_arg(ap, size_t); |
1231 | struct group **result = va_arg(ap, struct group **); | | 1234 | struct group **result = va_arg(ap, struct group **); |
1232 | | | 1235 | |
1233 | struct __grstate_nis state; | | 1236 | struct __grstate_nis state; |
1234 | int rv; | | 1237 | int rv; |
1235 | | | 1238 | |
1236 | _DIAGASSERT(retval != NULL); | | 1239 | _DIAGASSERT(retval != NULL); |
1237 | _DIAGASSERT(grp != NULL); | | 1240 | _DIAGASSERT(grp != NULL); |
1238 | _DIAGASSERT(buffer != NULL); | | 1241 | _DIAGASSERT(buffer != NULL); |
1239 | _DIAGASSERT(result != NULL); | | 1242 | _DIAGASSERT(result != NULL); |
1240 | | | 1243 | |
1241 | *result = NULL; | | 1244 | *result = NULL; |
1242 | memset(&state, 0, sizeof(state)); | | 1245 | memset(&state, 0, sizeof(state)); |
1243 | rv = __grscan_nis(retval, grp, buffer, buflen, &state, 1, name, 0); | | 1246 | rv = __grscan_nis(retval, grp, buffer, buflen, &state, 1, name, 0); |
1244 | __grend_nis(&state); | | 1247 | __grend_nis(&state); |
1245 | if (rv == NS_SUCCESS) | | 1248 | if (rv == NS_SUCCESS) |
1246 | *result = grp; | | 1249 | *result = grp; |
1247 | return rv; | | 1250 | return rv; |
1248 | } | | 1251 | } |
1249 | | | 1252 | |
1250 | #endif /* YP */ | | 1253 | #endif /* YP */ |
1251 | | | 1254 | |
1252 | | | 1255 | |
1253 | #ifdef _GROUP_COMPAT | | 1256 | #ifdef _GROUP_COMPAT |
1254 | /* | | 1257 | /* |
1255 | * compat methods | | 1258 | * compat methods |
1256 | */ | | 1259 | */ |
1257 | | | 1260 | |
1258 | int | | 1261 | int |
1259 | __grstart_compat(struct __grstate_compat *state) | | 1262 | __grstart_compat(struct __grstate_compat *state) |
1260 | { | | 1263 | { |
1261 | | | 1264 | |
1262 | _DIAGASSERT(state != NULL); | | 1265 | _DIAGASSERT(state != NULL); |
1263 | | | 1266 | |
1264 | if (state->fp == NULL) { | | 1267 | if (state->fp == NULL) { |
1265 | state->fp = fopen(_PATH_GROUP, "r"); | | 1268 | state->fp = fopen(_PATH_GROUP, "r"); |
1266 | if (state->fp == NULL) | | 1269 | if (state->fp == NULL) |
1267 | return NS_UNAVAIL; | | 1270 | return NS_UNAVAIL; |
1268 | } else { | | 1271 | } else { |
1269 | rewind(state->fp); | | 1272 | rewind(state->fp); |
1270 | } | | 1273 | } |
1271 | return NS_SUCCESS; | | 1274 | return NS_SUCCESS; |