Fix problem with getdate on mingw32 reported by Simon Josefsson
[gnulib.git] / lib / getugroups.c
1 /* getugroups.c -- return a list of the groups a user is in
2
3    Copyright (C) 1990, 1991, 1998-2000, 2003-2007 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 <stdio.h> /* grp.h on alpha OSF1 V2.0 uses "FILE *". */
25 #include <grp.h>
26
27 #include <unistd.h>
28
29 #include <errno.h>
30 #ifndef EOVERFLOW
31 # define EOVERFLOW EINVAL
32 #endif
33
34 /* Some old header files might not declare setgrent, getgrent, and endgrent.
35    If you don't have them at all, we can't implement this function.
36    You lose!  */
37 struct group *getgrent ();
38
39 #include <string.h>
40
41 #define STREQ(s1, s2) ((strcmp (s1, s2) == 0))
42
43 /* Like `getgroups', but for user USERNAME instead of for the current
44    process.  Store at most MAXCOUNT group IDs in the GROUPLIST array.
45    If GID is not -1, store it first (if possible).  GID should be the
46    group ID (pw_gid) obtained from getpwuid, in case USERNAME is not
47    listed in /etc/groups.  Upon failure, set errno and return -1.
48    Otherwise, return the number of IDs we've written into GROUPLIST.  */
49
50 int
51 getugroups (int maxcount, GETGROUPS_T *grouplist, char const *username,
52             gid_t gid)
53 {
54   int count = 0;
55
56   if (gid != (gid_t) -1)
57     {
58       if (maxcount != 0)
59         grouplist[count] = gid;
60       ++count;
61     }
62
63   setgrent ();
64   while (1)
65     {
66       char **cp;
67       struct group *grp;
68
69       errno = 0;
70       grp = getgrent ();
71       if (grp == NULL)
72         break;
73
74       for (cp = grp->gr_mem; *cp; ++cp)
75         {
76           int n;
77
78           if ( ! STREQ (username, *cp))
79             continue;
80
81           /* See if this group number is already on the list.  */
82           for (n = 0; n < count; ++n)
83             if (grouplist && grouplist[n] == grp->gr_gid)
84               break;
85
86           /* If it's a new group number, then try to add it to the list.  */
87           if (n == count)
88             {
89               if (maxcount != 0)
90                 {
91                   if (count >= maxcount)
92                     goto done;
93                   grouplist[count] = grp->gr_gid;
94                 }
95               count++;
96               if (count < 0)
97                 {
98                   errno = EOVERFLOW;
99                   goto done;
100                 }
101             }
102         }
103     }
104
105   if (errno != 0)
106     count = -1;
107
108  done:
109   {
110     int saved_errno = errno;
111     endgrent ();
112     errno = saved_errno;
113   }
114
115   return count;
116 }