update from main archive 961201
[platform/upstream/glibc.git] / grp / initgroups.c
1 /* Copyright (C) 1989, 1991, 1993, 1996 Free Software Foundation, Inc.
2    This file is part of the GNU C Library.
3
4    The GNU C Library is free software; you can redistribute it and/or
5    modify it under the terms of the GNU Library General Public License as
6    published by the Free Software Foundation; either version 2 of the
7    License, or (at your option) any later version.
8
9    The GNU C Library is distributed in the hope that it will be useful,
10    but WITHOUT ANY WARRANTY; without even the implied warranty of
11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12    Library General Public License for more details.
13
14    You should have received a copy of the GNU Library General Public
15    License along with the GNU C Library; see the file COPYING.LIB.  If not,
16    write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17    Boston, MA 02111-1307, USA.  */
18
19 #include <alloca.h>
20 #include <unistd.h>
21 #include <string.h>
22 #include <grp.h>
23 #include <limits.h>
24 #include <sys/types.h>
25
26
27 /* Initialize the group set for the current user
28    by reading the group database and using all groups
29    of which USER is a member.  Also include GROUP.  */
30 int
31 initgroups (user, group)
32      const char *user;
33      gid_t group;
34 {
35 #if defined (NGROUPS_MAX) && NGROUPS_MAX == 0
36
37   /* No extra groups allowed.  */
38   return 0;
39
40 #else
41
42   struct group grpbuf, *g;
43   size_t buflen = sysconf (_SC_GETPW_R_SIZE_MAX);
44   char *tmpbuf;
45   register size_t n;
46   size_t ngroups;
47   gid_t *groups;
48 #ifdef NGROUPS_MAX
49 # define limit NGROUPS_MAX
50
51   ngroups = limit;
52 #else
53   long int limit = sysconf (_SC_NGROUPS_MAX);
54
55   if (limit > 0)
56     ngroups = limit;
57   else
58     /* No fixed limit on groups.  Pick a starting buffer size.  */
59     ngroups = 16;
60 #endif
61
62   groups = __alloca (ngroups * sizeof *groups);
63   tmpbuf = __alloca (buflen);
64
65   setgrent ();
66
67   n = 0;
68   groups[n++] = group;
69
70   while (__getgrent_r (&grpbuf, tmpbuf, buflen, &g) >= 0)
71     if (g->gr_gid != group)
72       {
73         register char **m;
74
75         for (m = g->gr_mem; *m != NULL; ++m)
76           if (strcmp (*m, user) == 0)
77             {
78               /* Matches user.  Insert this group.  */
79               if (n == ngroups && limit <= 0)
80                 {
81                   /* Need a bigger buffer.  */
82                   groups = memcpy (__alloca (ngroups * 2 * sizeof *groups),
83                                    groups, ngroups * sizeof *groups);
84                   ngroups *= 2;
85                 }
86
87               groups[n++] = g->gr_gid;
88
89               if (n == limit)
90                 /* Can't take any more groups; stop searching.  */
91                 goto done;
92
93               break;
94             }
95       }
96 done:
97   endgrent ();
98
99   return setgroups (n, groups);
100 #endif
101 }