1#include "pwf.h"
2#include <pthread.h>
3
4static unsigned atou(char **s)
5{
6	unsigned x;
7	for (x=0; **s-'0'<10U; ++*s) x=10*x+(**s-'0');
8	return x;
9}
10
11int __getgrent_a(FILE *f, struct group *gr, char **line, size_t *size, char ***mem, size_t *nmem, struct group **res)
12{
13	ssize_t l;
14	char *s, *mems;
15	size_t i;
16	int rv = 0;
17	int cs;
18	pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cs);
19	for (;;) {
20		if ((l=getline(line, size, f)) < 0) {
21			rv = ferror(f) ? errno : 0;
22			free(*line);
23			*line = 0;
24			gr = 0;
25			goto end;
26		}
27		line[0][l-1] = 0;
28
29		s = line[0];
30		gr->gr_name = s++;
31		if (!(s = strchr(s, ':'))) continue;
32
33		*s++ = 0; gr->gr_passwd = s;
34		if (!(s = strchr(s, ':'))) continue;
35
36		*s++ = 0; gr->gr_gid = atou(&s);
37		if (*s != ':') continue;
38
39		*s++ = 0; mems = s;
40		break;
41	}
42
43	for (*nmem=!!*s; *s; s++)
44		if (*s==',') ++*nmem;
45	free(*mem);
46	*mem = calloc(sizeof(char *), *nmem+1);
47	if (!*mem) {
48		rv = errno;
49		free(*line);
50		*line = 0;
51		gr = 0;
52		goto end;
53	}
54	if (*mems) {
55		mem[0][0] = mems;
56		for (s=mems, i=0; *s; s++)
57			if (*s==',') *s++ = 0, mem[0][++i] = s;
58		mem[0][++i] = 0;
59	} else {
60		mem[0][0] = 0;
61	}
62	gr->gr_mem = *mem;
63end:
64	pthread_setcancelstate(cs, 0);
65	*res = gr;
66	if(rv) errno = rv;
67	return rv;
68}
69