#include "pwf.h" | |
#include <pthread.h> | |
static unsigned atou(char** s) { | |
unsigned x; | |
for (x = 0; **s - '0' < 10U; ++*s) | |
x = 10 * x + (**s - '0'); | |
return x; | |
} | |
int __getgrent_a(FILE* f, | |
struct group* gr, | |
char** line, | |
size_t* size, | |
char*** mem, | |
size_t* nmem, | |
struct group** res) { | |
ssize_t l; | |
char *s, *mems; | |
size_t i; | |
int rv = 0; | |
int cs; | |
pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cs); | |
for (;;) { | |
if ((l = getline(line, size, f)) < 0) { | |
rv = ferror(f) ? errno : 0; | |
free(*line); | |
*line = 0; | |
gr = 0; | |
goto end; | |
} | |
line[0][l - 1] = 0; | |
s = line[0]; | |
gr->gr_name = s++; | |
if (!(s = strchr(s, ':'))) | |
continue; | |
*s++ = 0; | |
gr->gr_passwd = s; | |
if (!(s = strchr(s, ':'))) | |
continue; | |
*s++ = 0; | |
gr->gr_gid = atou(&s); | |
if (*s != ':') | |
continue; | |
*s++ = 0; | |
mems = s; | |
break; | |
} | |
for (*nmem = !!*s; *s; s++) | |
if (*s == ',') | |
++*nmem; | |
free(*mem); | |
*mem = calloc(sizeof(char*), *nmem + 1); | |
if (!*mem) { | |
rv = errno; | |
free(*line); | |
*line = 0; | |
gr = 0; | |
goto end; | |
} | |
if (*mems) { | |
mem[0][0] = mems; | |
for (s = mems, i = 0; *s; s++) | |
if (*s == ',') | |
*s++ = 0, mem[0][++i] = s; | |
mem[0][++i] = 0; | |
} else { | |
mem[0][0] = 0; | |
} | |
gr->gr_mem = *mem; | |
end: | |
pthread_setcancelstate(cs, 0); | |
*res = gr; | |
if (rv) | |
errno = rv; | |
return rv; | |
} |