# getgroups

## NAME



           getgroups, setgroups - get/set list of supplementary group IDs
    


## LIBRARY



           Standard C library (_libc_ , _-lc_)
    


## SYNOPSIS



           **#include <unistd.h>**
    
           **int getgroups(int** _size_**, gid_t** _list_**[_Nullable** _size_**]);**
    
           **#include <grp.h>**
    
           **int setgroups(size_t** _size_**, const gid_t** _list_**[_Nullable** _size_**]);**
    
       Feature Test Macro Requirements for glibc (see
       feature_test_macros(7)):
    
           **setgroups**():
               Since glibc 2.19:
                   _DEFAULT_SOURCE
               glibc 2.19 and earlier:
                   _BSD_SOURCE
    


## DESCRIPTION



           **getgroups**() returns the supplementary group IDs of the calling
           process in _list_.  The argument _size_ should be set to the maximum
           number of items that can be stored in the buffer pointed to by
           _list_.  If the calling process is a member of more than _size_
           supplementary groups, then an error results.
    
           It is unspecified whether the effective group ID of the calling
           process is included in the returned list.  (Thus, an application
           should also call getegid(2) and add or remove the resulting
           value.)
    
           If _size_ is zero, _list_ is not modified, but the total number of
           supplementary group IDs for the process is returned.  This allows
           the caller to determine the size of a dynamically allocated _list_
           to be used in a further call to **getgroups**().
    
           **setgroups**() sets the supplementary group IDs for the calling
           process.  Appropriate privileges are required (see the description
           of the **EPERM** error, below).  The _size_ argument specifies the
           number of supplementary group IDs in the buffer pointed to by
           _list_.  A process can drop all of its supplementary groups with the
           call:
    
               setgroups(0, NULL);
    


## RETURN VALUE



           On success, **getgroups**() returns the number of supplementary group
           IDs.  On error, -1 is returned, and _errno_ is set to indicate the
           error.
    
           On success, **setgroups**() returns 0.  On error, -1 is returned, and
           _errno_ is set to indicate the error.
    


## ERRORS



           **EFAULT** _list_ has an invalid address.
    
           **getgroups**() can additionally fail with the following error:
    
           **EINVAL** _size_ is less than the number of supplementary group IDs,
                  but is not zero.
    
           **setgroups**() can additionally fail with the following errors:
    
           **EINVAL** _size_ is greater than **NGROUPS_MAX**(32 before Linux 2.6.4;
                  65536 since Linux 2.6.4).
    
           **ENOMEM** Out of memory.
    
           **EPERM** The calling process has insufficient privilege (the caller
                  does not have the **CAP_SETGID** capability in the user
                  namespace in which it resides).
    
           **EPERM**(since Linux 3.19)
                  The use of **setgroups**() is denied in this user namespace.
                  See the description of _/proc/_ pid _/setgroups_ in
                  user_namespaces(7).
    


## VERSIONS



       **C library/kernel differences**
           At the kernel level, user IDs and group IDs are a per-thread
           attribute.  However, POSIX requires that all threads in a process
           share the same credentials.  The NPTL threading implementation
           handles the POSIX requirements by providing wrapper functions for
           the various system calls that change process UIDs and GIDs.  These
           wrapper functions (including the one for **setgroups**()) employ a
           signal-based technique to ensure that when one thread changes
           credentials, all of the other threads in the process also change
           their credentials.  For details, see nptl(7).
    


## STANDARDS



           **getgroups**()
                  POSIX.1-2008.
    
           **setgroups**()
                  None.
    


## NOTES



           A process can have up to **NGROUPS_MAX** supplementary group IDs in
           addition to the effective group ID.  The constant **NGROUPS_MAX** is
           defined in _< limits.h>_.  The set of supplementary group IDs is
           inherited from the parent process, and preserved across an
           execve(2).
    
           The maximum number of supplementary group IDs can be found at run
           time using sysconf(3):
    
               long ngroups_max;
               ngroups_max = sysconf(_SC_NGROUPS_MAX);
    
           The maximum return value of **getgroups**() cannot be larger than one
           more than this value.  Since Linux 2.6.4, the maximum number of
           supplementary group IDs is also exposed via the Linux-specific
           read-only file, _/proc/sys/kernel/ngroups_max_.
    


## EXAMPLES



           #include <err.h>
           #include <stddef.h>
           #include <stdint.h>
           #include <stdio.h>
           #include <stdlib.h>
           #include <sys/types.h>
           #include <unistd.h>
    
           #define MALLOC(n, T)  ((T *) reallocarray(NULL, n, sizeof(T)))
    
           static gid_t *agetgroups(size_t *ngids);
    
           int
           main(void)
           {
               gid_t   *gids;
               size_t  n;
    
               gids = agetgroups(&n);
               if (gids == NULL)
                   err(EXIT_FAILURE, "agetgroups");
    
               if (n != 0) {
                   printf("%jd", (intmax_t) gids[0]);
                   for (size_t i = 1; i < n; i++)
                       printf(" %jd", (intmax_t) gids[i]);
               }
               puts("");
    
               free(gids);
               exit(EXIT_SUCCESS);
           }
    
           static gid_t *
           agetgroups(size_t *ngids)
           {
               int    n;
               gid_t  *gids;
    
               n = getgroups(0, NULL);
               if (n == -1)
                   return NULL;
    
               gids = MALLOC(n, gid_t);
               if (gids == NULL)
                   return NULL;
    
               n = getgroups(n, gids);
               if (n == -1) {
                   free(gids);
                   return NULL;
               }
    
               *ngids = n;
               return gids;
           }
    


* * *