getgrent.c revision 11286
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 49#include <rpc/rpc.h> 50#include <rpcsvc/yp_prot.h> 51#include <rpcsvc/ypclnt.h> 52static int _gr_stepping_yp; 53static int _gr_yp_enabled; 54static int _getypgroup(struct group *, const char *, char *); 55static int _nextypgroup(struct group *); 56#endif 57 58#define MAXGRP 200 59static char *members[MAXGRP]; 60#define MAXLINELENGTH 1024 61static char line[MAXLINELENGTH]; 62 63struct group * 64getgrent() 65{ 66 if (!_gr_fp && !start_gr()) { 67 return NULL; 68 } 69 70#ifdef YP 71 if (_gr_stepping_yp) { 72 if (_nextypgroup(&_gr_group)) 73 return(&_gr_group); 74 } 75tryagain: 76#endif 77 78 if (!grscan(0, 0, NULL)) 79 return(NULL); 80#ifdef YP 81 if(_gr_group.gr_name[0] == '+' && _gr_group.gr_name[1]) { 82 _getypgroup(&_gr_group, &_gr_group.gr_name[1], 83 "group.byname"); 84 } else if(_gr_group.gr_name[0] == '+') { 85 if (!_nextypgroup(&_gr_group)) 86 goto tryagain; 87 else 88 return(&_gr_group); 89 } 90#endif 91 return(&_gr_group); 92} 93 94struct group * 95getgrnam(name) 96 const char *name; 97{ 98 int rval; 99 100 if (!start_gr()) 101 return(NULL); 102#ifdef YP 103 tryagain: 104#endif 105 rval = grscan(1, 0, name); 106#ifdef YP 107 if(rval == -1 && (_gr_yp_enabled < 0 || (_gr_yp_enabled && 108 _gr_group.gr_name[0] == '+'))) { 109 if (!(rval = _getypgroup(&_gr_group, name, "group.byname"))) 110 goto tryagain; 111 } 112#endif 113 if (!_gr_stayopen) 114 endgrent(); 115 return(rval ? &_gr_group : NULL); 116} 117 118struct group * 119#ifdef __STDC__ 120getgrgid(gid_t gid) 121#else 122getgrgid(gid) 123 gid_t gid; 124#endif 125{ 126 int rval; 127 128 if (!start_gr()) 129 return(NULL); 130#ifdef YP 131 tryagain: 132#endif 133 rval = grscan(1, gid, NULL); 134#ifdef YP 135 if(rval == -1 && _gr_yp_enabled) { 136 char buf[16]; 137 snprintf(buf, sizeof buf, "%d", (unsigned)gid); 138 if (!(rval = _getypgroup(&_gr_group, buf, "group.bygid"))) 139 goto tryagain; 140 } 141#endif 142 if (!_gr_stayopen) 143 endgrent(); 144 return(rval ? &_gr_group : NULL); 145} 146 147static int 148start_gr() 149{ 150 if (_gr_fp) { 151 rewind(_gr_fp); 152 return(1); 153 } 154 _gr_fp = fopen(_PATH_GROUP, "r"); 155 if(!_gr_fp) return 0; 156#ifdef YP 157 /* 158 * This is a disgusting hack, used to determine when YP is enabled. 159 * This would be easier if we had a group database to go along with 160 * the password database. 161 */ 162 { 163 char *line; 164 size_t linelen; 165 _gr_yp_enabled = 0; 166 while(line = fgetln(_gr_fp, &linelen)) { 167 if(line[0] == '+') { 168 if(line[1] && !_gr_yp_enabled) { 169 _gr_yp_enabled = 1; 170 } else { 171 _gr_yp_enabled = -1; 172 break; 173 } 174 } 175 } 176 rewind(_gr_fp); 177 } 178#endif 179 return 1; 180} 181 182int 183setgrent() 184{ 185 return(setgroupent(0)); 186} 187 188int 189setgroupent(stayopen) 190 int stayopen; 191{ 192 if (!start_gr()) 193 return(0); 194 _gr_stayopen = stayopen; 195#ifdef YP 196 _gr_stepping_yp = 0; 197#endif 198 return(1); 199} 200 201void 202endgrent() 203{ 204#ifdef YP 205 _gr_stepping_yp = 0; 206#endif 207 if (_gr_fp) { 208 (void)fclose(_gr_fp); 209 _gr_fp = NULL; 210 } 211} 212 213static int 214grscan(search, gid, name) 215 register int search, gid; 216 register char *name; 217{ 218 register char *cp, **m; 219 char *bp; 220#ifdef YP 221 int _ypfound = 0; 222#endif; 223 for (;;) { 224 if (!fgets(line, sizeof(line), _gr_fp)) 225 return(0); 226 bp = line; 227 /* skip lines that are too big */ 228 if (!index(line, '\n')) { 229 int ch; 230 231 while ((ch = getc(_gr_fp)) != '\n' && ch != EOF) 232 ; 233 continue; 234 } 235 if ((_gr_group.gr_name = strsep(&bp, ":\n")) == NULL) 236 break; 237#ifdef YP 238 /* 239 * XXX We need to be careful to avoid proceeding 240 * past this point under certain circumstances or 241 * we risk dereferencing null pointers down below. 242 */ 243 if (_gr_group.gr_name[0] == '+') { 244 if (strlen(_gr_group.gr_name) == 1) { 245 switch(search) { 246 case 0: 247 return(1); 248 case 1: 249 return(-1); 250 default: 251 return(0); 252 } 253 } else { 254 if (!_getypgroup(&_gr_group, &_gr_group.gr_name[1], 255 "group.byname")) 256 continue; 257 /* We're going to override -- tell the world. */ 258 members[0] = NULL; 259 _ypfound++; 260 } 261 } 262#else 263 if (_gr_group.gr_name[0] == '+') 264 continue; 265#endif /* YP */ 266 if (search && name) { 267 if(strcmp(_gr_group.gr_name, name)) { 268 continue; 269 } 270 } 271 if ((_gr_group.gr_passwd = strsep(&bp, ":\n")) == NULL) 272 break;; 273 if (!(cp = strsep(&bp, ":\n"))) 274 continue; 275#ifdef YP 276 if (!_ypfound) 277#endif 278 _gr_group.gr_gid = atoi(cp); 279 if (search && name == NULL && _gr_group.gr_gid != gid) 280 continue; 281 cp = NULL; 282 for (m = _gr_group.gr_mem = members;; bp++) { 283 if (m == &members[MAXGRP - 1]) 284 break; 285 if (*bp == ',') { 286 if (cp) { 287 *bp = '\0'; 288 *m++ = cp; 289 cp = NULL; 290 } 291 } else if (*bp == '\0' || *bp == '\n' || *bp == ' ') { 292 if (cp) { 293 *bp = '\0'; 294 *m++ = cp; 295 } 296 break; 297 } else if (cp == NULL) 298 cp = bp; 299 } 300 *m = NULL; 301 return(1); 302 } 303 /* NOTREACHED */ 304} 305 306#ifdef YP 307 308static int 309_gr_breakout_yp(struct group *gr, char *result) 310{ 311 char *s, *cp; 312 char **m; 313 314 /* 315 * XXX If 's' ends up being a NULL pointer, punt on this group. 316 * It means the NIS group entry is badly formatted and should 317 * be skipped. 318 */ 319 if ((s = strsep(&result, ":")) == NULL) return 0; /* name */ 320 gr->gr_name = s; 321 322 if ((s = strsep(&result, ":")) == NULL) return 0; /* password */ 323 gr->gr_passwd = s; 324 325 if ((s = strsep(&result, ":")) == NULL) return 0; /* gid */ 326 gr->gr_gid = atoi(s); 327 328 if ((s = result) == NULL) return 0; 329 cp = 0; 330 331 for (m = _gr_group.gr_mem = members; /**/; s++) { 332 if (m == &members[MAXGRP - 1]) { 333 break; 334 } 335 if (*s == ',') { 336 if (cp) { 337 *s = '\0'; 338 *m++ = cp; 339 cp = NULL; 340 } 341 } else if (*s == '\0' || *s == '\n' || *s == ' ') { 342 if (cp) { 343 *s = '\0'; 344 *m++ = cp; 345 } 346 break; 347 } else if (cp == NULL) { 348 cp = s; 349 } 350 } 351 *m = NULL; 352 353 return 1; 354} 355 356static char *_gr_yp_domain; 357 358static int 359_getypgroup(struct group *gr, const char *name, char *map) 360{ 361 char *result, *s; 362 static char resultbuf[1024]; 363 int resultlen; 364 365 if(!_gr_yp_domain) { 366 if(yp_get_default_domain(&_gr_yp_domain)) 367 return 0; 368 } 369 370 if(yp_match(_gr_yp_domain, map, name, strlen(name), 371 &result, &resultlen)) 372 return 0; 373 374 s = strchr(result, '\n'); 375 if(s) *s = '\0'; 376 377 if(resultlen >= sizeof resultbuf) return 0; 378 strcpy(resultbuf, result); 379 result = resultbuf; 380 return(_gr_breakout_yp(gr, resultbuf)); 381 382} 383 384 385static int 386_nextypgroup(struct group *gr) 387{ 388 static char *key; 389 static int keylen; 390 char *lastkey, *result; 391 static char resultbuf[1024]; 392 int resultlen; 393 int rv; 394 395 if(!_gr_yp_domain) { 396 if(yp_get_default_domain(&_gr_yp_domain)) 397 return 0; 398 } 399 400 if(!_gr_stepping_yp) { 401 if(key) free(key); 402 rv = yp_first(_gr_yp_domain, "group.byname", 403 &key, &keylen, &result, &resultlen); 404 if(rv) { 405 return 0; 406 } 407 _gr_stepping_yp = 1; 408 goto unpack; 409 } else { 410tryagain: 411 lastkey = key; 412 rv = yp_next(_gr_yp_domain, "group.byname", key, keylen, 413 &key, &keylen, &result, &resultlen); 414 free(lastkey); 415unpack: 416 if(rv) { 417 _gr_stepping_yp = 0; 418 return 0; 419 } 420 421 if(resultlen > sizeof(resultbuf)) { 422 free(result); 423 goto tryagain; 424 } 425 426 strcpy(resultbuf, result); 427 free(result); 428 if(result = strchr(resultbuf, '\n')) *result = '\0'; 429 if (_gr_breakout_yp(gr, resultbuf)) 430 return(1); 431 else 432 goto tryagain; 433 } 434} 435 436#endif /* YP */ 437