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