getgrent_r(3)
β¨ getgrent_r(3) β the reentrant group-file getters, bestie edition β¨
okay so real talk: this is getgrent_r(3) from the Library Functions Manual, and if you've ever wanted to read group entries without the whole "everyone shares one static buffer and chaos ensues" thing, you are SO in the right place. π
πΈ NAME πΈ
getgrent_r, fgetgrent_r β get group file entry, but reentrantly, bestie π
π LIBRARY π
Standard C library (libc, -lc). the classic. the icon. π
β¨ SYNOPSIS β¨
#include <grp.h>
int getgrent_r(size_t size;
struct group *restrict gbuf,
char buf[restrict size], size_t size,
struct group **restrict gbufp);
int fgetgrent_r(size_t size;
FILE *restrict stream, struct group *restrict gbuf,
char buf[restrict size], size_t size,
struct group **restrict gbufp);
π§ Feature Test Macro Requirements for glibc π§
(peep feature_test_macros(7) for the lore, iykyk)
getgrent_r():_GNU_SOURCE
fgetgrent_r():- Since glibc 2.19:
_DEFAULT_SOURCE
- glibc 2.19 and earlier:
_SVID_SOURCE
- Since glibc 2.19:
π DESCRIPTION π
So. getgrent_r() and fgetgrent_r() are the reentrant versions of getgrent(3) and fgetgrent(3) β same energy, but you bring the storage. π«Ά
getgrent_r()reads the next group entry from the stream that got initialized bysetgrent(3).fgetgrent_r()reads the next group entry from stream.
The group structure lives in <grp.h> and it looks like this, no cap:
struct group {
char *gr_name; /* group name */
char *gr_passwd; /* group password */
gid_t gr_gid; /* group ID */
char **gr_mem; /* NULL-terminated array of pointers
to names of group members */
};
Wanna know more about those fields? group(5). go, read, slay. π
The nonreentrant functions hand you back a pointer to static storage β and that static storage is holding even more pointers to the group name, password, and members. π« The reentrant girlies described here though? They put ALL of that in buffers you provide. π
First up there's the buffer gbuf, which can hold a struct group. Then there's the buffer buf of size size that can hold the additional strings. The result β the struct group that got read from the stream β gets stored in your provided buffer *gbuf, and a pointer to that struct group is returned in *gbufp. β¨
π₯ RETURN VALUE π₯
- On success: these functions return
0, and*gbufpis a pointer to thestruct group. ate. π - On error: these functions return an error value, and
*gbufpisNULL. π
π ERRORS π
ENOENTβ No more entries. that's it, that's the whole stream. bye πERANGEβ Insufficient buffer space supplied. Try again with a larger buffer. lowkey the buffer said "not today" π
π ATTRIBUTES π
For an explanation of the terms used in this section, see attributes(7).
getgrent_r()β Thread safety:MT-Unsafe race:grent localefgetgrent_r()β Thread safety:MT-Safe
In the above table,grentinrace:grentsignifies that if any of the functionssetgrent(3),getgrent(3),endgrent(3), orgetgrent_r()are used in parallel in different threads of a program, then data races could occur. π pls be careful bestie.
π VERSIONS π
Other systems use the prototype
struct group *getgrent_r(struct group *grp, char buf[.size],
int size);
or, better,
int getgrent_r(struct group *grp, char buf[.size], int size,
FILE **gr_fp);
not us though. we're built different. β
π STANDARDS π
GNU. periodt. π
π¦ HISTORY π¦
These functions are done in a style resembling the POSIX version of functions like getpwnam_r(3). so if you know her, you know them. main character lineage fr fr. β¨
πΈ NOTES πΈ
getgrent_r() is not really reentrant since it shares the reading position in the stream with all other threads. the name is giving reentrant but the stream position is communal property, iykyk π
π EXAMPLES π
here's the whole thing, copy it, run it, obsess:
#define _GNU_SOURCE
#include <grp.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#define BUFLEN 4096
int
main(void)
{
struct group grp;
struct group *grpp;
char buf[BUFLEN];
int i;
setgrent();
for (;;) {
i = getgrent_r(&grp, buf, sizeof(buf), &grpp);
if (i)
break;
printf("%s (%jd):", grpp->gr_name, (intmax_t) grpp->gr_gid);
for (size_t j = 0; ; j++) {
if (grpp->gr_mem[j] == NULL)
break;
printf(" %s", grpp->gr_mem[j]);
}
printf("\n");
}
endgrent();
exit(EXIT_SUCCESS);
}
it walks every group, prints the group name and gid, then dumps all the members. iconic behavior. π
β SEE ALSO β
fgetgrent(3), getgrent(3), getgrgid(3), getgrnam(3), putgrent(3), group(5)
okay that's the whole page, bestie, you're officially fluent in reentrant group lookups π β¨
this was Linux man-pages 6.20, dated 2026-02-14. valentine's day drop, we love a romantic release schedule. mwah π«Άπ
π¦ where this page comes from
- arch rolling: man-pages 6.20-1 Β· BSD-2-Clause AND BSD-3-Clause AND BSD-4.3TAHOE AND BSD-4-Clause-UC AND GPL-1.0-or-later AND GPL-2.0-only AND GPL-2.0-or-later AND GPL-3.0-or-later AND LGPL-3.0-linking-exception AND LGPL-3.0-or-later AND LicenseRef-Public-Domain AND LicenseRef-UltraPermissive AND Linux-man-pages-1-para AND Linux-man-pages-copyleft AND Linux-man-pages-copyleft-2-para AND Linux-man-pages-copyleft-var AND MIT AND Spencer-94
- nixpkgs unstable: man-pages 6.20
- π the page's license: GPL-2.0-or-later
- Copyright 2003, Andries E. Brouwer <aeb@cwi.nl>
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms