Line data Source code
1 : /* getugroups.c -- return a list of the groups a user is in
2 :
3 : Copyright (C) 1990, 1991, 1998-2000, 2003-2008 Free Software Foundation.
4 :
5 : This program is free software: you can redistribute it and/or modify
6 : it under the terms of the GNU General Public License as published by
7 : the Free Software Foundation; either version 3 of the License, or
8 : (at your option) any later version.
9 :
10 : This program is distributed in the hope that it will be useful,
11 : but WITHOUT ANY WARRANTY; without even the implied warranty of
12 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 : GNU General Public License for more details.
14 :
15 : You should have received a copy of the GNU General Public License
16 : along with this program. If not, see <http://www.gnu.org/licenses/>. */
17 :
18 : /* Written by David MacKenzie. */
19 :
20 : #include <config.h>
21 :
22 : #include "getugroups.h"
23 :
24 : #include <limits.h>
25 : #include <stdio.h> /* grp.h on alpha OSF1 V2.0 uses "FILE *". */
26 : #include <grp.h>
27 :
28 : #include <unistd.h>
29 :
30 : #include <errno.h>
31 :
32 : /* Some old header files might not declare setgrent, getgrent, and endgrent.
33 : If you don't have them at all, we can't implement this function.
34 : You lose! */
35 : struct group *getgrent ();
36 :
37 : #include <string.h>
38 :
39 : #define STREQ(s1, s2) ((strcmp (s1, s2) == 0))
40 :
41 : /* Like `getgroups', but for user USERNAME instead of for the current
42 : process. Store at most MAXCOUNT group IDs in the GROUPLIST array.
43 : If GID is not -1, store it first (if possible). GID should be the
44 : group ID (pw_gid) obtained from getpwuid, in case USERNAME is not
45 : listed in /etc/groups. Upon failure, set errno and return -1.
46 : Otherwise, return the number of IDs we've written into GROUPLIST. */
47 :
48 : int
49 0 : getugroups (int maxcount, GETGROUPS_T *grouplist, char const *username,
50 : gid_t gid)
51 : {
52 0 : int count = 0;
53 :
54 0 : if (gid != (gid_t) -1)
55 : {
56 0 : if (maxcount != 0)
57 0 : grouplist[count] = gid;
58 0 : ++count;
59 : }
60 :
61 0 : setgrent ();
62 : while (1)
63 0 : {
64 : char **cp;
65 : struct group *grp;
66 :
67 0 : errno = 0;
68 0 : grp = getgrent ();
69 0 : if (grp == NULL)
70 0 : break;
71 :
72 0 : for (cp = grp->gr_mem; *cp; ++cp)
73 : {
74 : int n;
75 :
76 0 : if ( ! STREQ (username, *cp))
77 0 : continue;
78 :
79 : /* See if this group number is already on the list. */
80 0 : for (n = 0; n < count; ++n)
81 0 : if (grouplist && grouplist[n] == grp->gr_gid)
82 0 : break;
83 :
84 : /* If it's a new group number, then try to add it to the list. */
85 0 : if (n == count)
86 : {
87 0 : if (maxcount != 0)
88 : {
89 0 : if (count >= maxcount)
90 0 : goto done;
91 0 : grouplist[count] = grp->gr_gid;
92 : }
93 0 : if (count == INT_MAX)
94 : {
95 0 : errno = EOVERFLOW;
96 0 : goto done;
97 : }
98 0 : count++;
99 : }
100 : }
101 : }
102 :
103 0 : if (errno != 0)
104 0 : count = -1;
105 :
106 0 : done:
107 : {
108 0 : int saved_errno = errno;
109 0 : endgrent ();
110 0 : errno = saved_errno;
111 : }
112 :
113 0 : return count;
114 : }
|