1 /* $NetBSD: getgrent.c,v 1.22 1998/02/26 03:01:12 perry Exp $ */ 2 3 /* 4 * Copyright (c) 1989, 1993 5 * The Regents of the University of California. All rights reserved. 6 * Portions Copyright (c) 1994, Jason Downs. All Rights Reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 3. All advertising materials mentioning features or use of this software 17 * must display the following acknowledgement: 18 * This product includes software developed by the University of 19 * California, Berkeley and its contributors. 20 * 4. Neither the name of the University nor the names of its contributors 21 * may be used to endorse or promote products derived from this software 22 * without specific prior written permission. 23 * 24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 34 * SUCH DAMAGE. 35 */ 36 37 #include <sys/cdefs.h> 38 #if defined(LIBC_SCCS) && !defined(lint) 39 #if 0 40 static char sccsid[] = "@(#)getgrent.c 8.2 (Berkeley) 3/21/94"; 41 #else 42 __RCSID("$NetBSD: getgrent.c,v 1.22 1998/02/26 03:01:12 perry Exp $"); 43 #endif 44 #endif /* LIBC_SCCS and not lint */ 45 46 #include "namespace.h" 47 #include <sys/types.h> 48 #include <limits.h> 49 #include <stdio.h> 50 #include <stdlib.h> 51 #include <string.h> 52 #include <grp.h> 53 #ifdef YP 54 #include <rpc/rpc.h> 55 #include <rpcsvc/yp_prot.h> 56 #include <rpcsvc/ypclnt.h> 57 #endif 58 59 #ifdef __weak_alias 60 __weak_alias(endgrent,_endgrent); 61 __weak_alias(getgrent,_getgrent); 62 __weak_alias(getgrgid,_getgrgid); 63 __weak_alias(getgrnam,_getgrnam); 64 __weak_alias(setgrent,_setgrent); 65 __weak_alias(setgroupent,_setgroupent); 66 #endif 67 68 static FILE *_gr_fp; 69 static struct group _gr_group; 70 static int _gr_stayopen; 71 static int grscan __P((int, gid_t, const char *)); 72 static int start_gr __P((void)); 73 74 #define MAXGRP 200 75 static char *members[MAXGRP]; 76 #define MAXLINELENGTH 1024 77 static char line[MAXLINELENGTH]; 78 79 #ifdef YP 80 enum _ypmode { YPMODE_NONE, YPMODE_FULL, YPMODE_NAME }; 81 static enum _ypmode __ypmode; 82 static char *__ypcurrent, *__ypdomain; 83 static int __ypcurrentlen; 84 #endif 85 86 struct group * 87 getgrent() 88 { 89 if ((!_gr_fp && !start_gr()) || !grscan(0, 0, NULL)) 90 return(NULL); 91 return(&_gr_group); 92 } 93 94 struct group * 95 getgrnam(name) 96 const char *name; 97 { 98 int rval; 99 100 if (!start_gr()) 101 return(NULL); 102 rval = grscan(1, 0, name); 103 if (!_gr_stayopen) 104 endgrent(); 105 return(rval ? &_gr_group : NULL); 106 } 107 108 struct group * 109 #ifdef __STDC__ 110 getgrgid(gid_t gid) 111 #else 112 getgrgid(gid) 113 gid_t gid; 114 #endif 115 { 116 int rval; 117 118 if (!start_gr()) 119 return(NULL); 120 rval = grscan(1, gid, NULL); 121 if (!_gr_stayopen) 122 endgrent(); 123 return(rval ? &_gr_group : NULL); 124 } 125 126 static int 127 start_gr() 128 { 129 if (_gr_fp) { 130 rewind(_gr_fp); 131 #ifdef YP 132 __ypmode = YPMODE_NONE; 133 if (__ypcurrent) 134 free(__ypcurrent); 135 __ypcurrent = NULL; 136 #endif 137 return(1); 138 } 139 return((_gr_fp = fopen(_PATH_GROUP, "r")) ? 1 : 0); 140 } 141 142 void 143 setgrent() 144 { 145 (void) setgroupent(0); 146 } 147 148 int 149 setgroupent(stayopen) 150 int stayopen; 151 { 152 if (!start_gr()) 153 return(0); 154 _gr_stayopen = stayopen; 155 return(1); 156 } 157 158 void 159 endgrent() 160 { 161 if (_gr_fp) { 162 (void)fclose(_gr_fp); 163 _gr_fp = NULL; 164 #ifdef YP 165 __ypmode = YPMODE_NONE; 166 if (__ypcurrent) 167 free(__ypcurrent); 168 __ypcurrent = NULL; 169 #endif 170 } 171 } 172 173 static int 174 grscan(search, gid, name) 175 int search; 176 gid_t gid; 177 const char *name; 178 { 179 char *cp, **m; 180 char *bp, *ep; 181 unsigned long id; 182 #ifdef YP 183 char *key, *data; 184 int keylen, datalen; 185 int r; 186 char *grname = (char *)NULL; 187 #endif 188 189 for (;;) { 190 #ifdef YP 191 if (__ypmode != YPMODE_NONE) { 192 193 if (!__ypdomain) { 194 if (yp_get_default_domain(&__ypdomain)) { 195 __ypmode = YPMODE_NONE; 196 if (grname != (char *)NULL) { 197 free(grname); 198 grname = (char *)NULL; 199 } 200 continue; 201 } 202 } 203 switch(__ypmode) { 204 case YPMODE_FULL: 205 data = NULL; 206 if (__ypcurrent) { 207 key = NULL; 208 r = yp_next(__ypdomain, "group.byname", 209 __ypcurrent, __ypcurrentlen, 210 &key, &keylen, &data, &datalen); 211 free(__ypcurrent); 212 if (r != 0) { 213 __ypcurrent = NULL; 214 if (key) 215 free(key); 216 } 217 else { 218 __ypcurrent = key; 219 __ypcurrentlen = keylen; 220 } 221 } else { 222 r = yp_first(__ypdomain, "group.byname", 223 &__ypcurrent, &__ypcurrentlen, 224 &data, &datalen); 225 } 226 if (r != 0) { 227 __ypmode = YPMODE_NONE; 228 if (data) 229 free(data); 230 continue; 231 } 232 bcopy(data, line, (size_t)datalen); 233 free(data); 234 break; 235 case YPMODE_NAME: 236 if (grname != (char *)NULL) { 237 data = NULL; 238 r = yp_match(__ypdomain, "group.byname", 239 grname, (int)strlen(grname), 240 &data, &datalen); 241 __ypmode = YPMODE_NONE; 242 free(grname); 243 grname = (char *)NULL; 244 if (r != 0) { 245 if (data) 246 free(data); 247 continue; 248 } 249 bcopy(data, line, (size_t)datalen); 250 free(data); 251 } else { 252 /* YP not available? */ 253 __ypmode = YPMODE_NONE; 254 continue; 255 } 256 break; 257 case YPMODE_NONE: 258 abort(); /* Cannot happen */ 259 break; 260 } 261 line[datalen] = '\0'; 262 bp = line; 263 goto parse; 264 } 265 #endif /* YP */ 266 if (!fgets(line, sizeof(line), _gr_fp)) 267 return(0); 268 bp = line; 269 /* skip lines that are too big */ 270 if (!strchr(line, '\n')) { 271 int ch; 272 273 while ((ch = getc(_gr_fp)) != '\n' && ch != EOF) 274 ; 275 continue; 276 } 277 #ifdef YP 278 if (line[0] == '+') { 279 switch(line[1]) { 280 case ':': 281 case '\0': 282 case '\n': 283 if (_yp_check(NULL)) { 284 if (!search) { 285 __ypmode = YPMODE_FULL; 286 continue; 287 } 288 if (!__ypdomain && 289 yp_get_default_domain(&__ypdomain)) 290 continue; 291 data = NULL; 292 if (name) { 293 r = yp_match(__ypdomain, 294 "group.byname", 295 name, 296 (int)strlen(name), 297 &data, &datalen); 298 } else { 299 char buf[20]; 300 snprintf(buf, sizeof(buf), 301 "%u", gid); 302 r = yp_match(__ypdomain, 303 "group.bygid", 304 buf, 305 (int)strlen(buf), 306 &data, &datalen); 307 } 308 if (r != 0) { 309 if (data) 310 free(data); 311 continue; 312 } 313 bcopy(data, line, (size_t)datalen); 314 free(data); 315 line[datalen] = '\0'; 316 bp = line; 317 _gr_group.gr_name = strsep(&bp, ":\n"); 318 _gr_group.gr_passwd = 319 strsep(&bp, ":\n"); 320 if (!(cp = strsep(&bp, ":\n"))) 321 continue; 322 if (name) { 323 id = strtoul(cp, &ep, 10); 324 if (id > GID_MAX || *ep != '\0') 325 continue; 326 _gr_group.gr_gid = (gid_t)id; 327 } else 328 _gr_group.gr_gid = gid; 329 goto found_it; 330 } 331 break; 332 default: 333 if (_yp_check(NULL)) { 334 char *tptr; 335 336 tptr = strsep(&bp, ":\n"); 337 if (search && name && 338 strcmp(tptr, name)) 339 continue; 340 __ypmode = YPMODE_NAME; 341 grname = strdup(tptr + 1); 342 continue; 343 } 344 break; 345 } 346 } 347 parse: 348 #endif /* YP */ 349 _gr_group.gr_name = strsep(&bp, ":\n"); 350 if (search && name && strcmp(_gr_group.gr_name, name)) 351 continue; 352 _gr_group.gr_passwd = strsep(&bp, ":\n"); 353 if (!(cp = strsep(&bp, ":\n"))) 354 continue; 355 id = strtoul(cp, &ep, 10); 356 if (id > GID_MAX || *ep != '\0') 357 continue; 358 _gr_group.gr_gid = (gid_t)id; 359 if (search && name == NULL && _gr_group.gr_gid != gid) 360 continue; 361 found_it: 362 cp = NULL; 363 if (bp == NULL) 364 continue; 365 for (m = _gr_group.gr_mem = members;; bp++) { 366 if (m == &members[MAXGRP - 1]) 367 break; 368 if (*bp == ',') { 369 if (cp) { 370 *bp = '\0'; 371 *m++ = cp; 372 cp = NULL; 373 } 374 } else if (*bp == '\0' || *bp == '\n' || *bp == ' ') { 375 if (cp) { 376 *bp = '\0'; 377 *m++ = cp; 378 } 379 break; 380 } else if (cp == NULL) 381 cp = bp; 382 } 383 *m = NULL; 384 return(1); 385 } 386 /* NOTREACHED */ 387 } 388