1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
|
.\"
.\" This file and its contents are supplied under the terms of the
.\" Common Development and Distribution License ("CDDL"), version 1.0.
.\" You may only use this file in accordance with the terms of version
.\" 1.0 of the CDDL.
.\"
.\" A full copy of the text of the CDDL should have accompanied this
.\" source. A copy of the CDDL is also available via the Internet at
.\" http://www.illumos.org/license/CDDL.
.\"
.\"
.\" Copyright 2020 Joyent, Inc.
.\"
.Dd January 17, 2022
.Dt GETGROUPLIST 3C
.Os
.Sh NAME
.Nm getgrouplist
.Nd calculate group access list
.Sh SYNOPSIS
.In grp.h
.Ft int
.Fo getgrouplist
.Fa "const char *user"
.Fa "gid_t agroup"
.Fa "gid_t *groups"
.Fa "int *ngroups"
.Fc
.Sh DESCRIPTION
The
.Fn getgrouplist
function queries the group database to obtain the list of groups that
.Fa user
belongs to.
The
.Fa agroup
group is always added to the resulting group list.
This value is typically the primary gid of the user from the
.Sy passwd
database.
.Pp
When calling
.Fn getgrouplist ,
the caller should set the maximum number of groups that
.Fa groups
can hold in
.Fa *ngroups .
The value of
.Dv NGROUPS_MAX
can be used to size
.Fa groups
to ensure it can hold any number of groups supported by the system.
.Pp
Upon return,
.Fn getgrouplist
stores the list of groups that
.Fa user
belongs to in
.Fa groups
and stores the number of groups
.Fa user
belongs to in
.Fa *ngroups
.Po
this may be a smaller than the value passed in when
calling
.Fn getgrouplist
.Pc .
If
.Fa groups
is too small to hold all of the groups
.Fa user
belongs to,
.Fn getgrouplist
fails and sets
.Fa *ngroups
to a value large enough to hold the full result.
.Sh RETURN VALUES
On success,
.Fn getgrouplist
returns the number of groups
.Fa user
belongs to, fills in
.Fa groups
with the gids of the groups
.Fa user
belongs to, and also sets
.Fa *ngroups
to the number of groups
.Fa user
belongs to.
.Pp
On failure,
.Fn getgrouplist
returns -1 and
.Va errno
is set.
.Pp
The behavior of
.Fn getgrouplist
is undefined if the total number of groups a user belongs to exceeds
.Dv NGROUPS_MAX .
.Pp
Note that on
.Fx ,
.Fn getgrouplist
always returns -1 on failure or 0 on success.
A caller must rely on the value set in
.Fa *ngroups
upon return to determine the number of entries in
.Fa groups .
.Pp
On Linux, both glibc and musl return the number of groups
.Fa user
belongs to on success and return -1 on failure.
.Pp
None of these other implementations document any
.Va errno
values on failure, however their implementations show that
.Va errno
may be set on failure.
Software using
.Fn getgrouplist
should be aware of these differences when attempting to write portable
software.
.Sh EXAMPLES
.Sy Example 1
Print all the groups for a user.
.Bd -literal
#include <pwd.h>
#include <grp.h>
#include <stdlib.h>
#include <stdio.h>
#include <limits.h>
#include <err.h>
void
printgroups(const char *user)
{
struct passwd *pw;
gid_t *groups;
int ngroups, ret;
if ((groups = calloc(NGROUPS_MAX, sizeof (gid_t))) == NULL)
err(EXIT_FAILURE, "calloc");
if ((pw = getpwnam(user)) == NULL)
err(EXIT_FAILURE, "getpwnam");
ngroups = NGROUPS_MAX;
ret = getgrouplist(user, pw->pw_gid, groups, &ngroups);
if (ret < 0)
err(EXIT_FAILURE, "getgrouplist");
for (int i = 0; i < ret; i++) {
struct group *gr = getgrgid(groups[i]);
(void) printf("%s ", gr->gr_name);
}
(void) fputc('\\n', stdout);
free(groups);
}
.Ed
.Sh ERRORS
On failure,
.Fn getgrouplist
returns -1, and will set errno to one of the following values:
.Bl -tag -width Dv
.It Er ENOMEM
Not enough memory to complete the request.
.It Er EINVAL
One of the parameters is invalid
.Po
for example,
.Fa ngroups
is
.Dv NULL
.Pc .
.It Dv ERANGE
The supplied value of
.Fa *ngroups
is too small to hold the results.
.Fa *ngroups
is set
.Po
upon return
.Pc
to a value large enough to hold the results, and a partial set of
results is written to
.Fa groups .
The value written to
.Fa *ngroups
may be larger than the value returned by a successful call to
.Fn getgrouplist .
.El
.Sh INTERFACE STABILITY
.Sy Uncommitted
.Sh MT-LEVEL
.Sy MT-Safe
.Sh SEE ALSO
.Xr groups 1 ,
.Xr getgroups 2 ,
.Xr getuid 2 ,
.Xr getgrnam 3C ,
.Xr initgroups 3C ,
.Xr limits.h 3HEAD
|