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