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