| #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; |
| } |