1 /* $NetBSD: getgrent.c,v 1.17 1997/05/21 01:51:39 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.17 1997/05/21 01:51:39 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 key = NULL; 193 r = yp_next(__ypdomain, "group.byname", 194 __ypcurrent, __ypcurrentlen, 195 &key, &keylen, &data, &datalen); 196 free(__ypcurrent); 197 if (r != 0) { 198 __ypcurrent = NULL; 199 if (key) 200 free(key); 201 } 202 else { 203 __ypcurrent = key; 204 __ypcurrentlen = keylen; 205 } 206 } else { 207 r = yp_first(__ypdomain, "group.byname", 208 &__ypcurrent, &__ypcurrentlen, 209 &data, &datalen); 210 } 211 if (r != 0) { 212 __ypmode = YPMODE_NONE; 213 if (data) 214 free(data); 215 continue; 216 } 217 bcopy(data, line, datalen); 218 free(data); 219 break; 220 case YPMODE_NAME: 221 if (grname != (char *)NULL) { 222 data = NULL; 223 r = yp_match(__ypdomain, "group.byname", 224 grname, strlen(grname), 225 &data, &datalen); 226 __ypmode = YPMODE_NONE; 227 free(grname); 228 grname = (char *)NULL; 229 if (r != 0) { 230 if (data) 231 free(data); 232 continue; 233 } 234 bcopy(data, line, datalen); 235 free(data); 236 } else { 237 /* YP not available? */ 238 __ypmode = YPMODE_NONE; 239 continue; 240 } 241 break; 242 } 243 line[datalen] = '\0'; 244 bp = line; 245 goto parse; 246 } 247 #endif /* YP */ 248 if (!fgets(line, sizeof(line), _gr_fp)) 249 return(0); 250 bp = line; 251 /* skip lines that are too big */ 252 if (!strchr(line, '\n')) { 253 int ch; 254 255 while ((ch = getc(_gr_fp)) != '\n' && ch != EOF) 256 ; 257 continue; 258 } 259 #ifdef YP 260 if (line[0] == '+') { 261 switch(line[1]) { 262 case ':': 263 case '\0': 264 case '\n': 265 if (_yp_check(NULL)) { 266 if (!search) { 267 __ypmode = YPMODE_FULL; 268 continue; 269 } 270 if (!__ypdomain && 271 yp_get_default_domain(&__ypdomain)) 272 continue; 273 data = NULL; 274 if (name) { 275 r = yp_match(__ypdomain, 276 "group.byname", 277 name, strlen(name), 278 &data, &datalen); 279 } else { 280 char buf[20]; 281 sprintf(buf, "%d", gid); 282 r = yp_match(__ypdomain, 283 "group.bygid", 284 buf, strlen(buf), 285 &data, &datalen); 286 } 287 if (r != 0) { 288 if (data) 289 free(data); 290 continue; 291 } 292 bcopy(data, line, datalen); 293 free(data); 294 line[datalen] = '\0'; 295 bp = line; 296 _gr_group.gr_name = strsep(&bp, ":\n"); 297 _gr_group.gr_passwd = 298 strsep(&bp, ":\n"); 299 if (!(cp = strsep(&bp, ":\n"))) 300 continue; 301 _gr_group.gr_gid = 302 name ? atoi(cp) : gid; 303 goto found_it; 304 } 305 break; 306 default: 307 if (_yp_check(NULL)) { 308 char *tptr; 309 310 tptr = strsep(&bp, ":\n"); 311 if (search && name && 312 strcmp(tptr, name)) 313 continue; 314 __ypmode = YPMODE_NAME; 315 grname = strdup(tptr + 1); 316 continue; 317 } 318 break; 319 } 320 } 321 parse: 322 #endif /* YP */ 323 _gr_group.gr_name = strsep(&bp, ":\n"); 324 if (search && name && strcmp(_gr_group.gr_name, name)) 325 continue; 326 _gr_group.gr_passwd = strsep(&bp, ":\n"); 327 if (!(cp = strsep(&bp, ":\n"))) 328 continue; 329 _gr_group.gr_gid = atoi(cp); 330 if (search && name == NULL && _gr_group.gr_gid != gid) 331 continue; 332 found_it: 333 cp = NULL; 334 if (bp == NULL) 335 continue; 336 for (m = _gr_group.gr_mem = members;; bp++) { 337 if (m == &members[MAXGRP - 1]) 338 break; 339 if (*bp == ',') { 340 if (cp) { 341 *bp = '\0'; 342 *m++ = cp; 343 cp = NULL; 344 } 345 } else if (*bp == '\0' || *bp == '\n' || *bp == ' ') { 346 if (cp) { 347 *bp = '\0'; 348 *m++ = cp; 349 } 350 break; 351 } else if (cp == NULL) 352 cp = bp; 353 } 354 *m = NULL; 355 return(1); 356 } 357 /* NOTREACHED */ 358 } 359