| 1 | #include "pwf.h" |
| 2 | #include <pthread.h> |
| 3 | |
| 4 | static unsigned atou(char **s) |
| 5 | { |
| 6 | 	unsigned x; |
| 7 | 	for (x=0; **s-'0'<10U; ++*s) x=10*x+(**s-'0'); |
| 8 | 	return x; |
| 9 | } |
| 10 | |
| 11 | int __getgrent_a(FILE *f, struct group *gr, char **line, size_t *size, char ***mem, size_t *nmem, struct group **res) |
| 12 | { |
| 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; |
| 26 | 		} |
| 27 | 		line[0][l-1] = 0; |
| 28 | |
| 29 | 		s = line[0]; |
| 30 | 		gr->gr_name = s++; |
| 31 | 		if (!(s = strchr(s, ':'))) continue; |
| 32 | |
| 33 | 		*s++ = 0; gr->gr_passwd = s; |
| 34 | 		if (!(s = strchr(s, ':'))) continue; |
| 35 | |
| 36 | 		*s++ = 0; gr->gr_gid = atou(&s); |
| 37 | 		if (*s != ':') continue; |
| 38 | |
| 39 | 		*s++ = 0; mems = s; |
| 40 | 		break; |
| 41 | 	} |
| 42 | |
| 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; |
| 53 | 	} |
| 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; |
| 61 | 	} |
| 62 | 	gr->gr_mem = *mem; |
| 63 | end: |
| 64 | 	pthread_setcancelstate(cs, 0); |
| 65 | 	*res = gr; |
| 66 | 	if(rv) errno = rv; |
| 67 | 	return rv; |
| 68 | } |