#include <grp.h> int getgrent_r(struct group *gbuf, char *buf,
size_t buflen, struct group **gbufp); int fgetgrent_r(FILE *fp, struct group *gbuf, char *buf,
size_t buflen, struct group **gbufp);
Feature Test Macro Requirements for glibc (see feature_test_macros(7)):
getgrent_r():
_GNU_SOURCE
fgetgrent_r():
_SVID_SOURCE
The group structure is defined in <grp.h> as follows:
struct group { char *gr_name; /* group name */ char *gr_passwd; /* group password */ gid_t gr_gid; /* group ID */ char **gr_mem; /* group members */ };
The non-reentrant functions return a pointer to static storage, where this static storage contains further pointers to group name, password and members. The reentrant functions described here return all of that in caller-provided buffers. First of all there is the buffer gbuf that can hold a struct group. And next the buffer buf of size buflen that can hold additional strings. The result of these functions, the struct group read from the stream, is stored in the provided buffer *gbuf, and a pointer to this struct group is returned in *gbufp.
struct group *getgrent_r(struct group *grp, char *buf, int buflen);
or, better,
int getgrent_r(struct group *grp, char *buf, int buflen, FILE **gr_fp);
#define _GNU_SOURCE #include <grp.h> #include <stdio.h> #include <stdlib.h> #define BUFLEN 4096 int main(void) { struct group grp, *grpp; char buf[BUFLEN]; int i; setgrent(); while (1) { i = getgrent_r(&grp, buf, BUFLEN, &grpp); if (i) break; printf("%s (%d):", grpp->gr_name, grpp->gr_gid); for (i = 0; ; i++) { if (grpp->gr_mem[i] == NULL) break; printf(" %s", grpp->gr_mem[i]); } printf("\n"); } endgrent(); exit(EXIT_SUCCESS); }