1 /* $NetBSD: getgrent_r.c,v 1.1.1.1 2009/04/12 15:33:36 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 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