1 /* $NetBSD: getgrent.c,v 1.19 1997/05/22 10:38:07 lukem 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 #if defined(LIBC_SCCS) && !defined(lint) 38 #if 0 39 static char sccsid[] = "@(#)getgrent.c 8.2 (Berkeley) 3/21/94"; 40 #else 41 static char rcsid[] = "$NetBSD: getgrent.c,v 1.19 1997/05/22 10:38:07 lukem Exp $"; 42 #endif 43 #endif /* LIBC_SCCS and not lint */ 44 45 #include <sys/types.h> 46 #include <limits.h> 47 #include <stdio.h> 48 #include <stdlib.h> 49 #include <string.h> 50 #include <grp.h> 51 #ifdef YP 52 #include <rpc/rpc.h> 53 #include <rpcsvc/yp_prot.h> 54 #include <rpcsvc/ypclnt.h> 55 #endif 56 57 static FILE *_gr_fp; 58 static struct group _gr_group; 59 static int _gr_stayopen; 60 static int grscan(), start_gr(); 61 62 #define MAXGRP 200 63 static char *members[MAXGRP]; 64 #define MAXLINELENGTH 1024 65 static char line[MAXLINELENGTH]; 66 67 #ifdef YP 68 enum _ypmode { YPMODE_NONE, YPMODE_FULL, YPMODE_NAME }; 69 static enum _ypmode __ypmode; 70 static char *__ypcurrent, *__ypdomain; 71 static int __ypcurrentlen; 72 #endif 73 74 struct group * 75 getgrent() 76 { 77 if (!_gr_fp && !start_gr() || !grscan(0, 0, NULL)) 78 return(NULL); 79 return(&_gr_group); 80 } 81 82 struct group * 83 getgrnam(name) 84 const char *name; 85 { 86 int rval; 87 88 if (!start_gr()) 89 return(NULL); 90 rval = grscan(1, 0, name); 91 if (!_gr_stayopen) 92 endgrent(); 93 return(rval ? &_gr_group : NULL); 94 } 95 96 struct group * 97 #ifdef __STDC__ 98 getgrgid(gid_t gid) 99 #else 100 getgrgid(gid) 101 gid_t gid; 102 #endif 103 { 104 int rval; 105 106 if (!start_gr()) 107 return(NULL); 108 rval = grscan(1, gid, NULL); 109 if (!_gr_stayopen) 110 endgrent(); 111 return(rval ? &_gr_group : NULL); 112 } 113 114 static int 115 start_gr() 116 { 117 if (_gr_fp) { 118 rewind(_gr_fp); 119 #ifdef YP 120 __ypmode = YPMODE_NONE; 121 if (__ypcurrent) 122 free(__ypcurrent); 123 __ypcurrent = NULL; 124 #endif 125 return(1); 126 } 127 return((_gr_fp = fopen(_PATH_GROUP, "r")) ? 1 : 0); 128 } 129 130 void 131 setgrent() 132 { 133 (void) setgroupent(0); 134 } 135 136 int 137 setgroupent(stayopen) 138 int stayopen; 139 { 140 if (!start_gr()) 141 return(0); 142 _gr_stayopen = stayopen; 143 return(1); 144 } 145 146 void 147 endgrent() 148 { 149 if (_gr_fp) { 150 (void)fclose(_gr_fp); 151 _gr_fp = NULL; 152 #ifdef YP 153 __ypmode = YPMODE_NONE; 154 if (__ypcurrent) 155 free(__ypcurrent); 156 __ypcurrent = NULL; 157 #endif 158 } 159 } 160 161 static int 162 grscan(search, gid, name) 163 int search; 164 gid_t gid; 165 const char *name; 166 { 167 char *cp, **m; 168 char *bp, *ep; 169 unsigned long id; 170 #ifdef YP 171 char *key, *data; 172 int keylen, datalen; 173 int r; 174 char *grname = (char *)NULL; 175 #endif 176 177 for (;;) { 178 #ifdef YP 179 if (__ypmode != YPMODE_NONE) { 180 181 if (!__ypdomain) { 182 if (yp_get_default_domain(&__ypdomain)) { 183 __ypmode = YPMODE_NONE; 184 if (grname != (char *)NULL) { 185 free(grname); 186 grname = (char *)NULL; 187 } 188 continue; 189 } 190 } 191 switch(__ypmode) { 192 case YPMODE_FULL: 193 data = NULL; 194 if (__ypcurrent) { 195 key = NULL; 196 r = yp_next(__ypdomain, "group.byname", 197 __ypcurrent, __ypcurrentlen, 198 &key, &keylen, &data, &datalen); 199 free(__ypcurrent); 200 if (r != 0) { 201 __ypcurrent = NULL; 202 if (key) 203 free(key); 204 } 205 else { 206 __ypcurrent = key; 207 __ypcurrentlen = keylen; 208 } 209 } else { 210 r = yp_first(__ypdomain, "group.byname", 211 &__ypcurrent, &__ypcurrentlen, 212 &data, &datalen); 213 } 214 if (r != 0) { 215 __ypmode = YPMODE_NONE; 216 if (data) 217 free(data); 218 continue; 219 } 220 bcopy(data, line, datalen); 221 free(data); 222 break; 223 case YPMODE_NAME: 224 if (grname != (char *)NULL) { 225 data = NULL; 226 r = yp_match(__ypdomain, "group.byname", 227 grname, strlen(grname), 228 &data, &datalen); 229 __ypmode = YPMODE_NONE; 230 free(grname); 231 grname = (char *)NULL; 232 if (r != 0) { 233 if (data) 234 free(data); 235 continue; 236 } 237 bcopy(data, line, datalen); 238 free(data); 239 } else { 240 /* YP not available? */ 241 __ypmode = YPMODE_NONE; 242 continue; 243 } 244 break; 245 } 246 line[datalen] = '\0'; 247 bp = line; 248 goto parse; 249 } 250 #endif /* YP */ 251 if (!fgets(line, sizeof(line), _gr_fp)) 252 return(0); 253 bp = line; 254 /* skip lines that are too big */ 255 if (!strchr(line, '\n')) { 256 int ch; 257 258 while ((ch = getc(_gr_fp)) != '\n' && ch != EOF) 259 ; 260 continue; 261 } 262 #ifdef YP 263 if (line[0] == '+') { 264 switch(line[1]) { 265 case ':': 266 case '\0': 267 case '\n': 268 if (_yp_check(NULL)) { 269 if (!search) { 270 __ypmode = YPMODE_FULL; 271 continue; 272 } 273 if (!__ypdomain && 274 yp_get_default_domain(&__ypdomain)) 275 continue; 276 data = NULL; 277 if (name) { 278 r = yp_match(__ypdomain, 279 "group.byname", 280 name, strlen(name), 281 &data, &datalen); 282 } else { 283 char buf[20]; 284 snprintf(buf, sizeof(buf), 285 "%u", gid); 286 r = yp_match(__ypdomain, 287 "group.bygid", 288 buf, strlen(buf), 289 &data, &datalen); 290 } 291 if (r != 0) { 292 if (data) 293 free(data); 294 continue; 295 } 296 bcopy(data, line, datalen); 297 free(data); 298 line[datalen] = '\0'; 299 bp = line; 300 _gr_group.gr_name = strsep(&bp, ":\n"); 301 _gr_group.gr_passwd = 302 strsep(&bp, ":\n"); 303 if (!(cp = strsep(&bp, ":\n"))) 304 continue; 305 if (name) { 306 id = strtoul(cp, &ep, 10); 307 if (id > GID_MAX || *ep != '\0') 308 continue; 309 _gr_group.gr_gid = (gid_t)id; 310 } else 311 _gr_group.gr_gid = gid; 312 goto found_it; 313 } 314 break; 315 default: 316 if (_yp_check(NULL)) { 317 char *tptr; 318 319 tptr = strsep(&bp, ":\n"); 320 if (search && name && 321 strcmp(tptr, name)) 322 continue; 323 __ypmode = YPMODE_NAME; 324 grname = strdup(tptr + 1); 325 continue; 326 } 327 break; 328 } 329 } 330 parse: 331 #endif /* YP */ 332 _gr_group.gr_name = strsep(&bp, ":\n"); 333 if (search && name && strcmp(_gr_group.gr_name, name)) 334 continue; 335 _gr_group.gr_passwd = strsep(&bp, ":\n"); 336 if (!(cp = strsep(&bp, ":\n"))) 337 continue; 338 id = strtoul(cp, &ep, 10); 339 if (id > GID_MAX || *ep != '\0') 340 continue; 341 _gr_group.gr_gid = (gid_t)id; 342 if (search && name == NULL && _gr_group.gr_gid != gid) 343 continue; 344 found_it: 345 cp = NULL; 346 if (bp == NULL) 347 continue; 348 for (m = _gr_group.gr_mem = members;; bp++) { 349 if (m == &members[MAXGRP - 1]) 350 break; 351 if (*bp == ',') { 352 if (cp) { 353 *bp = '\0'; 354 *m++ = cp; 355 cp = NULL; 356 } 357 } else if (*bp == '\0' || *bp == '\n' || *bp == ' ') { 358 if (cp) { 359 *bp = '\0'; 360 *m++ = cp; 361 } 362 break; 363 } else if (cp == NULL) 364 cp = bp; 365 } 366 *m = NULL; 367 return(1); 368 } 369 /* NOTREACHED */ 370 } 371