fix fork of processes with active async io contexts
[musl.git] / src / passwd / getgrent_a.c
blob7fc389d46332a9ef408d29c67d853978a5dc5082
1 #include "pwf.h"
2 #include <pthread.h>
4 static unsigned atou(char **s)
6 unsigned x;
7 for (x=0; **s-'0'<10U; ++*s) x=10*x+(**s-'0');
8 return x;
11 int __getgrent_a(FILE *f, struct group *gr, char **line, size_t *size, char ***mem, size_t *nmem, struct group **res)
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;
27 line[0][l-1] = 0;
29 s = line[0];
30 gr->gr_name = s++;
31 if (!(s = strchr(s, ':'))) continue;
33 *s++ = 0; gr->gr_passwd = s;
34 if (!(s = strchr(s, ':'))) continue;
36 *s++ = 0; gr->gr_gid = atou(&s);
37 if (*s != ':') continue;
39 *s++ = 0; mems = s;
40 break;
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;
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;
62 gr->gr_mem = *mem;
63 end:
64 pthread_setcancelstate(cs, 0);
65 *res = gr;
66 if(rv) errno = rv;
67 return rv;