---
name: "initgroups"
section: "3"
platform: "freebsd"
package: "base"
version: "16.0-CURRENT-20261027-61c70dc16a79"
release: "FreeBSD 16.0-CURRENT (2026-10-27)"
platforms: ["linux", "freebsd", "macos"]
url: "https://new.carta.tech/initgroups"
---

# initgroups(3)

initialize supplementary groups as per the group database

## NAME

**initgroups** – initialize supplementary groups as per the group database

## LIBRARY

Standard C Library (libc, -lc)

## SYNOPSIS

**#include \<unistd.h\>**

*int*\

**initgroups**(*const char \*name*, *gid\_t basegid*);

## DESCRIPTION

The **initgroups**() function initializes the current process' supplementary groups as prescribed by its arguments and the system's group database.

It first uses the **getgrouplist**() function to compute a list of groups containing the passed *basegid*, which typically is the user's initial numerical group ID from the password database, and the supplementary groups in the group database for the user named *name*. It then installs this list as the current process' supplementary groups using **setgroups**().

## RETURN VALUES

The **initgroups()** function returns the value 0 if successful; otherwise the value -1 is returned and the global variable errno is set to indicate the error.

## ERRORS

The **initgroups**() function may fail and set *errno* to any of the errors specified for the [setgroups(2)](/setgroups/2.md) system call, or to:

- \[ENOMEM\]

  The **initgroups**() function was unable to allocate temporary storage.

## SEE ALSO

[setgroups(2)](/setgroups/2.md), [getgrouplist(3)](/getgrouplist/3.md)

## HISTORY

The **initgroups**() function appeared in 4.2BSD.

The **initgroups**() function changed semantics in FreeBSD 15, following that of [setgroups(2)](/setgroups/2.md) in the same release. Before that, it would also set the effective group ID to *basegid*, and would not include the latter in the supplementary groups except before FreeBSD 8. Its current behavior in these respects is known to be compatible with that of the following systems up to the specified versions that are current at time of this writing:

- Linux (up to 6.6) with the GNU libc (up to 2.42)

- NetBSD 1.1

- OpenBSD (up

- Systems based on illumos (up to August 2025 sources)

## SECURITY CONSIDERATIONS

As *basegid* is typically the user's initial numerical group ID, to which the current process' effective group ID is generally initialized, processes using functions to change their effective group ID (via [setgid(2)](/setgid/2.md) or similar) or that are spawned from executables with the set-group-ID mode bit set will not be able to relinquish the access rights deriving from being a member of *basegid*, as these functions do not change the supplementary groups.

This behavior is generally desirable in order to paper over the difference of treatment between the effective group and supplementary ones in this situation, as they are all in the end indiscriminately used in traditional UNIX discretionary access checks. It blends well with the practice of allocating each user its own private group, as processes launched from a set-group-ID executable keep the same user and consistently stay also in the same user's group. Finally, it was also chosen for compatibility with other systems( see the HISTORY section).

This convention of including *basegid* in the supplementary groups is however only enforced by the **initgroups**() function, and not by the [setgroups(2)](/setgroups/2.md) system call, so applications expressly wanting to include in the supplementary groups only those specified by the group database can themselves call **getgrouplist**() and then **setgroups**() on the result with the first element skipped (see [getgrouplist(3)](/getgrouplist/3.md)).
