update FSF address in copyright
[gnulib.git] / lib / group-member.c
1 /* group-member.c -- determine whether group id is in calling user's group list
2    Copyright (C) 1994 Free Software Foundation, Inc.
3
4    This program is free software; you can redistribute it and/or modify
5    it under the terms of the GNU General Public License as published by
6    the Free Software Foundation; either version 2, or (at your option)
7    any later version.
8
9    This program 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
12    GNU General Public License for more details.
13
14    You should have received a copy of the GNU General Public License
15    along with this program; if not, write to the Free Software Foundation,
16    Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
17
18 #ifdef HAVE_CONFIG_H
19 #include <config.h>
20 #endif
21
22 #include <stdio.h>
23 #include <sys/types.h>
24
25 #ifdef STDC_HEADERS
26 #include <stdlib.h>
27 #endif
28
29 #ifdef HAVE_UNISTD_H
30 #include <unistd.h>
31 #endif
32
33 #include "group-member.h"
34
35 char *xmalloc ();
36 char *xrealloc ();
37
38 struct group_info
39   {
40     int n_groups;
41     GETGROUPS_T *group;
42   };
43
44 #ifdef HAVE_GETGROUPS
45
46 static void
47 free_group_info (g)
48      struct group_info *g;
49 {
50   free (g->group);
51   free (g);
52 }
53
54 static struct group_info *
55 get_group_info ()
56 {
57   int n_groups;
58   int n_group_slots;
59   struct group_info *gi;
60   GETGROUPS_T *group;
61
62   /* getgroups () returns the number of elements that it was able to
63      place into the array.  We simply continue to call getgroups ()
64      until the number of elements placed into the array is smaller than
65      the physical size of the array. */
66
67   group = NULL;
68   n_groups = 0;
69   n_group_slots = 0;
70   while (n_groups == n_group_slots)
71     {
72       n_group_slots += 64;
73       group = (GETGROUPS_T *) xrealloc (group,
74                                         n_group_slots * sizeof (GETGROUPS_T));
75       n_groups = getgroups (n_group_slots, group);
76     }
77
78   /* In case of error, the user loses. */
79   if (n_groups < 0)
80     {
81       free (group);
82       return NULL;
83     }
84
85   gi = (struct group_info *) xmalloc (sizeof (*gi));
86   gi->n_groups = n_groups;
87   gi->group = group;
88
89   return gi;
90 }
91
92 #endif /* not HAVE_GETGROUPS */
93
94 /* Return non-zero if GID is one that we have in our groups list.
95    If there is no getgroups function, return non-zero if GID matches
96    either of the current or effective group IDs.  */
97
98 int
99 group_member (gid)
100      gid_t gid;
101 {
102 #ifndef HAVE_GETGROUPS
103   return ((gid == getgid ()) || (gid == getegid ()));
104 #else
105   int i;
106   int found;
107   struct group_info *gi;
108
109   gi = get_group_info ();
110   if (gi == NULL)
111     return 0;
112
113   /* Search through the list looking for GID. */
114   found = 0;
115   for (i = 0; i < gi->n_groups; i++)
116     {
117       if (gid == gi->group[i])
118         {
119           found = 1;
120           break;
121         }
122     }
123   
124   free_group_info (gi);
125
126   return found;
127 #endif /* HAVE_GETGROUPS */
128 }
129
130 #ifdef TEST
131
132 char *program_name;
133
134 int
135 main (int argc, char** argv)
136 {
137   int i;
138
139   program_name = argv[0];
140
141   for (i=1; i<argc; i++)
142     {
143       gid_t gid;
144
145       gid = atoi (argv[i]);
146       printf ("%d: %s\n", gid, group_member (gid) ? "yes" : "no");
147     }
148   exit (0);
149 }
150
151 #endif /* TEST */