github.com/afumu/libc@v0.0.6/musl/src/passwd/getgrent_a.c (about)

     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  }