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