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