xref: /netbsd-src/external/bsd/libbind/dist/irs/getgrent_r.c (revision 5bbd2a12505d72a8177929a37b5cee489d0a1cfd)
1 /*	$NetBSD: getgrent_r.c,v 1.1.1.2 2012/09/09 16:07:51 christos Exp $	*/
2 
3 /*
4  * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
5  * Copyright (c) 1998-1999 by Internet Software Consortium.
6  *
7  * Permission to use, copy, modify, and distribute this software for any
8  * purpose with or without fee is hereby granted, provided that the above
9  * copyright notice and this permission notice appear in all copies.
10  *
11  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
12  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13  * MERCHANTABILITY AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR
14  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
17  * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18  */
19 
20 #if defined(LIBC_SCCS) && !defined(lint)
21 static const char rcsid[] = "Id: getgrent_r.c,v 1.7 2005/04/27 04:56:24 sra Exp ";
22 #endif /* LIBC_SCCS and not lint */
23 
24 #include <port_before.h>
25 #if !defined(_REENTRANT) || !defined(DO_PTHREADS) || !defined(WANT_IRS_PW)
26 	static int getgrent_r_not_required = 0;
27 #else
28 #include <errno.h>
29 #include <string.h>
30 #include <stdio.h>
31 #include <sys/types.h>
32 #if (defined(POSIX_GETGRNAM_R) || defined(POSIX_GETGRGID_R)) && \
33     defined(_POSIX_PTHREAD_SEMANTICS)
34 	/* turn off solaris remapping in <grp.h> */
35 #define _UNIX95
36 #undef _POSIX_PTHREAD_SEMANTICS
37 #include <grp.h>
38 #define _POSIX_PTHREAD_SEMANTICS 1
39 #else
40 #include <grp.h>
41 #endif
42 #include <sys/param.h>
43 #include <port_after.h>
44 
45 #ifdef GROUP_R_RETURN
46 
47 static int
48 copy_group(struct group *, struct group *, char *buf, int buflen);
49 
50 /* POSIX 1003.1c */
51 #ifdef POSIX_GETGRNAM_R
52 int
__posix_getgrnam_r(const char * name,struct group * gptr,char * buf,int buflen,struct group ** result)53 __posix_getgrnam_r(const char *name,  struct group *gptr,
54 		char *buf, int buflen, struct group **result) {
55 #else
56 int
57 getgrnam_r(const char *name,  struct group *gptr,
58 		char *buf, size_t buflen, struct group **result) {
59 #endif
60 	struct group *ge = getgrnam(name);
61 	int res;
62 
63 	if (ge == NULL) {
64 		*result = NULL;
65 		return (0);
66 	}
67 
68 	res = copy_group(ge, gptr, buf, buflen);
69 	*result = res ? NULL : gptr;
70 	return (res);
71 }
72 
73 #ifdef POSIX_GETGRNAM_R
74 struct group *
75 getgrnam_r(const char *name,  struct group *gptr,
76 		char *buf, int buflen) {
77 	struct group *ge = getgrnam(name);
78 	int res;
79 
80 	if (ge == NULL)
81 		return (NULL);
82 	res = copy_group(ge, gptr, buf, buflen);
83 	return (res ? NULL : gptr);
84 }
85 #endif /* POSIX_GETGRNAM_R */
86 
87 /* POSIX 1003.1c */
88 #ifdef POSIX_GETGRGID_R
89 int
90 __posix_getgrgid_r(gid_t gid, struct group *gptr,
91 		char *buf, int buflen, struct group **result) {
92 #else /* POSIX_GETGRGID_R */
93 int
94 getgrgid_r(gid_t gid, struct group *gptr,
95 		char *buf, size_t buflen, struct group **result) {
96 #endif /* POSIX_GETGRGID_R */
97 	struct group *ge = getgrgid(gid);
98 	int res;
99 
100 	if (ge == NULL) {
101 		*result = NULL;
102 		return (0);
103 	}
104 
105 	res = copy_group(ge, gptr, buf, buflen);
106 	*result = res ? NULL : gptr;
107 	return (res);
108 }
109 
110 #ifdef POSIX_GETGRGID_R
111 struct group *
112 getgrgid_r(gid_t gid, struct group *gptr,
113 		char *buf, int buflen) {
114 	struct group *ge = getgrgid(gid);
115 	int res;
116 
117 	if (ge == NULL)
118 		return (NULL);
119 
120 	res = copy_group(ge, gptr, buf, buflen);
121 	return (res ? NULL : gptr);
122 }
123 #endif
124 
125 /*%
126  *	These assume a single context is in operation per thread.
127  *	If this is not the case we will need to call irs directly
128  *	rather than through the base functions.
129  */
130 
131 GROUP_R_RETURN
132 getgrent_r(struct group *gptr, GROUP_R_ARGS) {
133 	struct group *ge = getgrent();
134 	int res;
135 
136 	if (ge == NULL) {
137 		return (GROUP_R_BAD);
138 	}
139 
140 	res = copy_group(ge, gptr, buf, buflen);
141 	return (res ? GROUP_R_BAD : GROUP_R_OK);
142 }
143 
144 GROUP_R_SET_RETURN
145 setgrent_r(GROUP_R_ENT_ARGS) {
146 
147 	setgrent();
148 #ifdef GROUP_R_SET_RESULT
149 	return (GROUP_R_SET_RESULT);
150 #endif
151 }
152 
153 GROUP_R_END_RETURN
154 endgrent_r(GROUP_R_ENT_ARGS) {
155 
156 	endgrent();
157 	GROUP_R_END_RESULT(GROUP_R_OK);
158 }
159 
160 
161 #if 0
162 	/* XXX irs does not have a fgetgrent() */
163 GROUP_R_RETURN
164 fgetgrent_r(FILE *f, struct group *gptr, GROUP_R_ARGS) {
165 	struct group *ge = fgetgrent(f);
166 	int res;
167 
168 	if (ge == NULL)
169 		return (GROUP_R_BAD);
170 
171 	res = copy_group(ge, gptr, buf, buflen);
172 	return (res ? GROUP_R_BAD : GROUP_R_OK);
173 }
174 #endif
175 
176 /* Private */
177 
178 static int
179 copy_group(struct group *ge, struct group *gptr, char *buf, int buflen) {
180 	char *cp;
181 	int i, n;
182 	int numptr, len;
183 
184 	/* Find out the amount of space required to store the answer. */
185 	numptr = 1; /*%< NULL ptr */
186 	len = (char *)ALIGN(buf) - buf;
187 	for (i = 0; ge->gr_mem[i]; i++, numptr++) {
188 		len += strlen(ge->gr_mem[i]) + 1;
189 	}
190 	len += strlen(ge->gr_name) + 1;
191 	len += strlen(ge->gr_passwd) + 1;
192 	len += numptr * sizeof(char*);
193 
194 	if (len > buflen) {
195 		errno = ERANGE;
196 		return (ERANGE);
197 	}
198 
199 	/* copy group id */
200 	gptr->gr_gid = ge->gr_gid;
201 
202 	cp = (char *)ALIGN(buf) + numptr * sizeof(char *);
203 
204 	/* copy official name */
205 	n = strlen(ge->gr_name) + 1;
206 	strcpy(cp, ge->gr_name);
207 	gptr->gr_name = cp;
208 	cp += n;
209 
210 	/* copy member list */
211 	gptr->gr_mem = (char **)ALIGN(buf);
212 	for (i = 0 ; ge->gr_mem[i]; i++) {
213 		n = strlen(ge->gr_mem[i]) + 1;
214 		strcpy(cp, ge->gr_mem[i]);
215 		gptr->gr_mem[i] = cp;
216 		cp += n;
217 	}
218 	gptr->gr_mem[i] = NULL;
219 
220 	/* copy password */
221 	n = strlen(ge->gr_passwd) + 1;
222 	strcpy(cp, ge->gr_passwd);
223 	gptr->gr_passwd = cp;
224 	cp += n;
225 
226 	return (0);
227 }
228 #else /* GROUP_R_RETURN */
229 	static int getgrent_r_unknown_system = 0;
230 #endif /* GROUP_R_RETURN */
231 #endif /* !def(_REENTRANT) || !def(DO_PTHREADS) || !def(WANT_IRS_PW) */
232 /*! \file */
233