1/* $NetBSD$ */ 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) 21static 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 47static int 48copy_group(struct group *, struct group *, char *buf, int buflen); 49 50/* POSIX 1003.1c */ 51#ifdef POSIX_GETGRNAM_R 52int 53__posix_getgrnam_r(const char *name, struct group *gptr, 54 char *buf, int buflen, struct group **result) { 55#else 56int 57getgrnam_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 74struct group * 75getgrnam_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 89int 90__posix_getgrgid_r(gid_t gid, struct group *gptr, 91 char *buf, int buflen, struct group **result) { 92#else /* POSIX_GETGRGID_R */ 93int 94getgrgid_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 111struct group * 112getgrgid_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 131GROUP_R_RETURN 132getgrent_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 144GROUP_R_SET_RETURN 145setgrent_r(GROUP_R_ENT_ARGS) { 146 147 setgrent(); 148#ifdef GROUP_R_SET_RESULT 149 return (GROUP_R_SET_RESULT); 150#endif 151} 152 153GROUP_R_END_RETURN 154endgrent_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() */ 163GROUP_R_RETURN 164fgetgrent_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 178static int 179copy_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