1570af302Sopenharmony_ci#include "pwf.h"
2570af302Sopenharmony_ci#include <pthread.h>
3570af302Sopenharmony_ci
4570af302Sopenharmony_cistatic unsigned atou(char **s)
5570af302Sopenharmony_ci{
6570af302Sopenharmony_ci	unsigned x;
7570af302Sopenharmony_ci	for (x=0; **s-'0'<10U; ++*s) x=10*x+(**s-'0');
8570af302Sopenharmony_ci	return x;
9570af302Sopenharmony_ci}
10570af302Sopenharmony_ci
11570af302Sopenharmony_ciint __getgrent_a(FILE *f, struct group *gr, char **line, size_t *size, char ***mem, size_t *nmem, struct group **res)
12570af302Sopenharmony_ci{
13570af302Sopenharmony_ci	ssize_t l;
14570af302Sopenharmony_ci	char *s, *mems;
15570af302Sopenharmony_ci	size_t i;
16570af302Sopenharmony_ci	int rv = 0;
17570af302Sopenharmony_ci	int cs;
18570af302Sopenharmony_ci	pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cs);
19570af302Sopenharmony_ci	for (;;) {
20570af302Sopenharmony_ci		if ((l=getline(line, size, f)) < 0) {
21570af302Sopenharmony_ci			rv = ferror(f) ? errno : 0;
22570af302Sopenharmony_ci			free(*line);
23570af302Sopenharmony_ci			*line = 0;
24570af302Sopenharmony_ci			gr = 0;
25570af302Sopenharmony_ci			goto end;
26570af302Sopenharmony_ci		}
27570af302Sopenharmony_ci		line[0][l-1] = 0;
28570af302Sopenharmony_ci
29570af302Sopenharmony_ci		s = line[0];
30570af302Sopenharmony_ci		gr->gr_name = s++;
31570af302Sopenharmony_ci		if (!(s = strchr(s, ':'))) continue;
32570af302Sopenharmony_ci
33570af302Sopenharmony_ci		*s++ = 0; gr->gr_passwd = s;
34570af302Sopenharmony_ci		if (!(s = strchr(s, ':'))) continue;
35570af302Sopenharmony_ci
36570af302Sopenharmony_ci		*s++ = 0; gr->gr_gid = atou(&s);
37570af302Sopenharmony_ci		if (*s != ':') continue;
38570af302Sopenharmony_ci
39570af302Sopenharmony_ci		*s++ = 0; mems = s;
40570af302Sopenharmony_ci		break;
41570af302Sopenharmony_ci	}
42570af302Sopenharmony_ci
43570af302Sopenharmony_ci	for (*nmem=!!*s; *s; s++)
44570af302Sopenharmony_ci		if (*s==',') ++*nmem;
45570af302Sopenharmony_ci	free(*mem);
46570af302Sopenharmony_ci	*mem = calloc(sizeof(char *), *nmem+1);
47570af302Sopenharmony_ci	if (!*mem) {
48570af302Sopenharmony_ci		rv = errno;
49570af302Sopenharmony_ci		free(*line);
50570af302Sopenharmony_ci		*line = 0;
51570af302Sopenharmony_ci		gr = 0;
52570af302Sopenharmony_ci		goto end;
53570af302Sopenharmony_ci	}
54570af302Sopenharmony_ci	if (*mems) {
55570af302Sopenharmony_ci		mem[0][0] = mems;
56570af302Sopenharmony_ci		for (s=mems, i=0; *s; s++)
57570af302Sopenharmony_ci			if (*s==',') *s++ = 0, mem[0][++i] = s;
58570af302Sopenharmony_ci		mem[0][++i] = 0;
59570af302Sopenharmony_ci	} else {
60570af302Sopenharmony_ci		mem[0][0] = 0;
61570af302Sopenharmony_ci	}
62570af302Sopenharmony_ci	gr->gr_mem = *mem;
63570af302Sopenharmony_ciend:
64570af302Sopenharmony_ci	pthread_setcancelstate(cs, 0);
65570af302Sopenharmony_ci	*res = gr;
66570af302Sopenharmony_ci	if(rv) errno = rv;
67570af302Sopenharmony_ci	return rv;
68570af302Sopenharmony_ci}
69