1/*
2 * __getgrent.c - This file is part of the libc-8086/grp package for ELKS,
3 * Copyright (C) 1995, 1996 Nat Friedman <ndf@linux.mit.edu>.
4 *
5 *  This library is free software; you can redistribute it and/or
6 *  modify it under the terms of the GNU Library General Public
7 *  License as published by the Free Software Foundation; either
8 *  version 2 of the License, or (at your option) any later version.
9 *
10 *  This library is distributed in the hope that it will be useful,
11 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13 *  Library General Public License for more details.
14 *
15 *  You should have received a copy of the GNU Library General Public
16 *  License along with this library; if not, write to the Free
17 *  Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 *
19 */
20
21#include <unistd.h>
22#include <stdlib.h>
23#include <string.h>
24#include "grp.h"
25#include "config.h"
26
27/*
28 * This is the core group-file read function.  It behaves exactly like
29 * getgrent() except that it is passed a file descriptor.  getgrent()
30 * is just a wrapper for this function.
31 */
32struct group *__getgrent(int grp_fd)
33{
34#ifndef GR_SCALE_DYNAMIC
35	static char line_buff[GR_MAX_LINE_LEN];
36	static char *members[GR_MAX_MEMBERS];
37#else
38	static char *line_buff = NULL;
39	static char **members = NULL;
40	short line_index;
41	short buff_size;
42#endif
43	static struct group group;
44	register char *ptr;
45	char *field_begin;
46	short member_num;
47	char *endptr;
48	int line_len;
49
50
51	/* We use the restart label to handle malformatted lines */
52  restart:
53#ifdef GR_SCALE_DYNAMIC
54	line_index = 0;
55	buff_size = 256;
56#endif
57
58#ifndef GR_SCALE_DYNAMIC
59	/* Read the line into the static buffer */
60	if ((line_len = read(grp_fd, line_buff, GR_MAX_LINE_LEN)) <= 0)
61		return NULL;
62	field_begin = strchr(line_buff, '\n');
63	if (field_begin != NULL)
64		lseek(grp_fd, (long) (1 + field_begin - (line_buff + line_len)),
65			  SEEK_CUR);
66	else {						/* The line is too long - skip it :-\ */
67
68		do {
69			if ((line_len = read(grp_fd, line_buff, GR_MAX_LINE_LEN)) <= 0)
70				return NULL;
71		} while (!(field_begin = strchr(line_buff, '\n')));
72		lseek(grp_fd, (long) ((field_begin - line_buff) - line_len + 1),
73			  SEEK_CUR);
74		goto restart;
75	}
76	if (*line_buff == '#' || *line_buff == ' ' || *line_buff == '\n' ||
77		*line_buff == '\t')
78		goto restart;
79	*field_begin = '\0';
80
81#else							/* !GR_SCALE_DYNAMIC */
82	line_buff = realloc(line_buff, buff_size);
83	while (1) {
84		if ((line_len = read(grp_fd, line_buff + line_index,
85							 buff_size - line_index)) <= 0)
86			return NULL;
87		field_begin = strchr(line_buff, '\n');
88		if (field_begin != NULL) {
89			lseek(grp_fd,
90				  (long) (1 + field_begin -
91						  (line_len + line_index + line_buff)), SEEK_CUR);
92			*field_begin = '\0';
93			if (*line_buff == '#' || *line_buff == ' '
94				|| *line_buff == '\n' || *line_buff == '\t')
95				goto restart;
96			break;
97		} else {				/* Allocate some more space */
98
99			line_index = buff_size;
100			buff_size += 256;
101			line_buff = realloc(line_buff, buff_size);
102		}
103	}
104#endif							/* GR_SCALE_DYNAMIC */
105
106	/* Now parse the line */
107	group.gr_name = line_buff;
108	ptr = strchr(line_buff, ':');
109	if (ptr == NULL)
110		goto restart;
111	*ptr++ = '\0';
112
113	group.gr_passwd = ptr;
114	ptr = strchr(ptr, ':');
115	if (ptr == NULL)
116		goto restart;
117	*ptr++ = '\0';
118
119	field_begin = ptr;
120	ptr = strchr(ptr, ':');
121	if (ptr == NULL)
122		goto restart;
123	*ptr++ = '\0';
124
125	group.gr_gid = (gid_t) strtoul(field_begin, &endptr, 10);
126	if (*endptr != '\0')
127		goto restart;
128
129	member_num = 0;
130	field_begin = ptr;
131
132#ifndef GR_SCALE_DYNAMIC
133	while ((ptr = strchr(ptr, ',')) != NULL) {
134		*ptr = '\0';
135		ptr++;
136		members[member_num] = field_begin;
137		field_begin = ptr;
138		member_num++;
139	}
140	if (*field_begin == '\0')
141		members[member_num] = NULL;
142	else {
143		members[member_num] = field_begin;
144		members[member_num + 1] = NULL;
145	}
146#else							/* !GR_SCALE_DYNAMIC */
147	if (members != NULL)
148		free(members);
149	members = (char **) malloc(1 * sizeof(char *));
150
151	while ((ptr = strchr(ptr, ',')) != NULL) {
152		*ptr = '\0';
153		ptr++;
154		members[member_num] = field_begin;
155		field_begin = ptr;
156		member_num++;
157		members =
158			(char **) realloc((void *) members,
159
160							  (member_num + 1) * sizeof(char *));
161	}
162	if (*field_begin == '\0')
163		members[member_num] = NULL;
164	else {
165		members[member_num] = field_begin;
166		members[member_num + 1] = NULL;
167	}
168#endif							/* GR_SCALE_DYNAMIC */
169
170	group.gr_mem = members;
171	return &group;
172}
173