getgrent.c revision 1.5
1/*	$NetBSD: getgrent.c,v 1.5 2002/02/02 15:31:58 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/*
38 * Copied from:  lib/libc/gen/getgrent.c
39 *	NetBSD: getgrent.c,v 1.42 2002/02/02 15:21:29 lukem Exp
40 * and then gutted, leaving only /etc/group support.
41 */
42
43#include <sys/cdefs.h>
44
45#ifdef __weak_alias
46#define endgrent		_endgrent
47#define getgrent		_getgrent
48#define getgrgid		_getgrgid
49#define getgrnam		_getgrnam
50#define setgrent		_setgrent
51#define setgroupent		_setgroupent
52
53__weak_alias(endgrent,_endgrent)
54__weak_alias(getgrent,_getgrent)
55__weak_alias(getgrgid,_getgrgid)
56__weak_alias(getgrnam,_getgrnam)
57__weak_alias(setgrent,_setgrent)
58__weak_alias(setgroupent,_setgroupent)
59#endif
60
61#include <sys/types.h>
62
63#include <grp.h>
64#include <limits.h>
65#include <stdio.h>
66#include <stdlib.h>
67#include <string.h>
68
69static FILE		*_gr_fp;
70static struct group	_gr_group;
71static int		_gr_filesdone;
72static int		_gr_stayopen;
73
74static int grscan(int, gid_t, const char *);
75static int grstart(void);
76static int grmatchline(int, gid_t, const char *);
77
78#define	MAXGRP		200
79#define	MAXLINELENGTH	1024
80static char		*members[MAXGRP];
81static char		grline[MAXLINELENGTH];
82
83struct group *
84getgrent(void)
85{
86	if ((!_gr_fp && !grstart()) || !grscan(0, 0, NULL))
87		return (NULL);
88	return (&_gr_group);
89}
90
91struct group *
92getgrnam(const char *name)
93{
94	int rval;
95
96	if (!grstart())
97		return(NULL);
98	rval = grscan(1, 0, name);
99	if (!_gr_stayopen)
100		endgrent();
101	return(rval ? &_gr_group : NULL);
102}
103
104struct group *
105getgrgid(gid_t gid)
106{
107	int rval;
108
109	if (!grstart())
110		return(NULL);
111	rval = grscan(1, gid, NULL);
112	if (!_gr_stayopen)
113		endgrent();
114	return(rval ? &_gr_group : NULL);
115}
116
117static int
118grstart(void)
119{
120	_gr_filesdone = 0;
121	if (_gr_fp) {
122		rewind(_gr_fp);
123		return(1);
124	}
125	return((_gr_fp = fopen(_PATH_GROUP, "r")) ? 1 : 0);
126}
127
128void
129setgrent(void)
130{
131	(void) setgroupent(0);
132}
133
134int
135setgroupent(int stayopen)
136{
137	if (!grstart())
138		return(0);
139	_gr_stayopen = stayopen;
140	return(1);
141}
142
143void
144endgrent(void)
145{
146	_gr_filesdone = 0;
147	if (_gr_fp) {
148		(void)fclose(_gr_fp);
149		_gr_fp = NULL;
150	}
151}
152
153static int
154grscan(int search, gid_t gid, const char *name)
155{
156	if (_gr_filesdone)
157		return 0;
158	for (;;) {
159		if (!fgets(grline, sizeof(grline), _gr_fp)) {
160			if (!search)
161				_gr_filesdone = 1;
162			return 0;
163		}
164		/* skip lines that are too big */
165		if (!strchr(grline, '\n')) {
166			int ch;
167
168			while ((ch = getc(_gr_fp)) != '\n' && ch != EOF)
169				;
170			continue;
171		}
172		if (grmatchline(search, gid, name))
173			return 1;
174	}
175	/* NOTREACHED */
176}
177
178static int
179grmatchline(int search, gid_t gid, const char *name)
180{
181	unsigned long	id;
182	char		**m;
183	char		*cp, *bp, *ep;
184
185	/* name may be NULL if search is nonzero */
186
187	bp = grline;
188	memset(&_gr_group, 0, sizeof(_gr_group));
189	_gr_group.gr_name = strsep(&bp, ":\n");
190	if (search && name && strcmp(_gr_group.gr_name, name))
191		return 0;
192	_gr_group.gr_passwd = strsep(&bp, ":\n");
193	if (!(cp = strsep(&bp, ":\n")))
194		return 0;
195	id = strtoul(cp, &ep, 10);
196	if (id > GID_MAX || *ep != '\0')
197		return 0;
198	_gr_group.gr_gid = (gid_t)id;
199	if (search && name == NULL && _gr_group.gr_gid != gid)
200		return 0;
201	cp = NULL;
202	if (bp == NULL)
203		return 0;
204	for (_gr_group.gr_mem = m = members;; bp++) {
205		if (m == &members[MAXGRP - 1])
206			break;
207		if (*bp == ',') {
208			if (cp) {
209				*bp = '\0';
210				*m++ = cp;
211				cp = NULL;
212			}
213		} else if (*bp == '\0' || *bp == '\n' || *bp == ' ') {
214			if (cp) {
215				*bp = '\0';
216				*m++ = cp;
217			}
218			break;
219		} else if (cp == NULL)
220			cp = bp;
221	}
222	*m = NULL;
223	return 1;
224}
225