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