getgrouplist(3)

๐Ÿ’– getgrouplist(3) ๐Ÿ’–

okay so we're in the Library Functions Manual section, and bestie, this is your one-stop shop for finding out every group a user is in. no cap. let's go ๐Ÿฆ‹


โœจ NAME โœจ

getgrouplist โ€” get list of groups to which a user belongs

๐Ÿ“š LIBRARY ๐Ÿ“š

Standard C library (libc, -lc) โ€” the classic, the icon, the one you already linked against ๐Ÿ’…

๐Ÿซถ SYNOPSIS ๐Ÿซถ

#include <grp.h>

int getgrouplist(const char *user, gid_t group,
                 gid_t *groups, int *ngroups);

๐ŸŒธ Feature Test Macro Requirements for glibc (see feature_test_macros(7)):

getgrouplist():
    Since glibc 2.19:
        _DEFAULT_SOURCE
    glibc 2.19 and earlier:
        _BSD_SOURCE

๐Ÿ’… DESCRIPTION ๐Ÿ’…

The getgrouplist() function scans the group database (see group(5)) to obtain the list of groups that user belongs to. Up to *ngroups of these groups are returned in the array groups. (yes it's giving "here's your little buffer, hope it's big enough" ๐Ÿ˜ญ)

If it was not among the groups defined for user in the group database, then group is included in the list of groups returned by getgrouplist(); typically this argument is specified as the group ID from the password record for user. so like, the group you pass in is your safety net โ€” it will be in there even if the group database forgot to mention it. periodt. ๐Ÿ‘‘

The ngroups argument is a value-result argument: on return it always contains the number of groups found for user, including group; this value may be greater than the number of groups stored in groups. read that again bestie, because it's the plot twist of this whole function โ€” the number it hands back isn't necessarily the number it actually wrote. ๐Ÿซ 


๐ŸŽ€ RETURN VALUE ๐ŸŽ€

If the number of groups of which user is a member is less than or equal to *ngroups, then the value *ngroups is returned. slay โœ…

If the user is a member of more than *ngroups groups, then getgrouplist() returns -1. In this case, the value returned in *ngroups can be used to resize the buffer passed to a further call to getgrouplist(). so you call again with a bigger buffer โ€” that's the whole trick, iykyk ๐ŸŒˆ

not you getting -1 and panicking. bestie. it's literally telling you how big your buffer should be. it's being helpful. it's serving. ๐Ÿ’€

๐ŸŒŸ ATTRIBUTES ๐ŸŒŸ

For an explanation of the terms used in this section, see attributes(7).

  • Interface: getgrouplist()
  • Attribute: Thread safety
  • Value: MT-Safe locale

so she's thread safe, just keep an eye on your locale, okay? ๐Ÿงš


๐Ÿ‘‘ STANDARDS ๐Ÿ‘‘

None.

(not a single one. she's unstandardized. she's independent. she's THAT girl ๐Ÿ’…)


๐Ÿ•ฐ๏ธ HISTORY ๐Ÿ•ฐ๏ธ

glibc 2.2.4. ancient. vintage. iconic for her time ๐ŸŽ€


๐Ÿ’€ BUGS ๐Ÿ’€

Before glibc 2.3.3, the implementation of this function contains a buffer-overrun bug: it returns the complete list of groups for user in the array groups, even when the number of groups exceeds *ngroups.

๐Ÿšจ BESTIE. THIS IS THE SCARY ONE. ๐Ÿšจ if you are on a pre-2.3.3 glibc, it will happily write past the end of your array like it's got no survival instincts whatsoever. do not pass go. upgrade. ๐Ÿ™ˆ

๐Ÿ“ EXAMPLES ๐Ÿ“

The program below displays the group list for the user named in its first command-line argument. The second command-line argument specifies the ngroups value to be supplied to getgrouplist(). The following shell session shows examples of the use of this program:

$ ./a.out cecilia 0
getgrouplist() returned -1
ngroups = 3
$ ./a.out cecilia 3
ngroups = 3
16 (dialout)
33 (video)
100 (users)

look at that first run like ๐Ÿ‘€ 0 groups?? obviously -1, obviously it tells you ngroups = 3, and then you come back with 3 and get your little trio of groups with their names attached. the glow up is real. โœจ

๐ŸŒธ Program source ๐ŸŒธ

#include <errno.h>
#include <grp.h>
#include <pwd.h>
#include <stdio.h>
#include <stdlib.h>

int
main(int argc, char *argv[])
{
    int            ngroups;
    gid_t          *groups;
    struct group   *gr;
    struct passwd  *pw;

    if (argc != 3) {
        fprintf(stderr, "Usage: %s <user> <ngroups>\n", argv[0]);
        exit(EXIT_FAILURE);
    }

    ngroups = atoi(argv[2]);

    groups = malloc(sizeof(*groups) * ngroups);
    if (groups == NULL) {
        perror("malloc");
        exit(EXIT_FAILURE);
    }

    /* Fetch passwd structure (contains first group ID for user).  */

    errno = 0;
    pw = getpwnam(argv[1]);
    if (pw == NULL) {
        if (errno)
            perror("getpwnam");
        else
            fprintf(stderr, "no such user\n");
        exit(EXIT_FAILURE);
    }

    /* Retrieve group list.  */

    if (getgrouplist(argv[1], pw->pw_gid, groups, &ngroups) == -1) {
        fprintf(stderr, "getgrouplist() returned -1\n");
        fprintf(stderr, "ngroups = %d\n", ngroups);
        exit(EXIT_FAILURE);
    }

    /* Display list of retrieved groups, along with group names.  */

    fprintf(stderr, "ngroups = %d\n", ngroups);
    for (int j = 0; j < ngroups; j++) {
        printf("%d", groups[j]);
        gr = getgrgid(groups[j]);
        if (gr != NULL)
            printf(" (%s)", gr->gr_name);
        printf("\n");
    }

    exit(EXIT_SUCCESS);
}

copy it exactly, bestie, don't get creative in the middle of a C file ๐Ÿ˜ญ


๐Ÿ” SEE ALSO ๐Ÿ”


and that's the whole page!! ๐Ÿซถ this little legend comes to you courtesy of Linux man-pages 6.20, dated 2025-09-21 โ€” go forth and populate your group arrays responsibly, okay?? 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: Linux-man-pages-copyleft
  • ๐Ÿ’– girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms