]> granicus.if.org Git - shadow/blob - src/groups.c
* src/passwd.c: Overflow when computing the number of days based
[shadow] / src / groups.c
1 /*
2  * Copyright (c) 1991 - 1993, Julianne Frances Haugh
3  * Copyright (c) 1996 - 2000, Marek Michałkiewicz
4  * Copyright (c) 2001 - 2006, Tomasz Kłoczko
5  * Copyright (c) 2007 - 2008, Nicolas François
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  * 3. The name of the copyright holders or contributors may not be used to
17  *    endorse or promote products derived from this software without
18  *    specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
23  * PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT
24  * HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31  */
32
33 #include <config.h>
34
35 #ident "$Id$"
36
37 #include <grp.h>
38 #include <pwd.h>
39 #include <stdio.h>
40 #include "defines.h"
41 #include "prototypes.h"
42 /*
43  * Global variables
44  */
45 const char *Prog;
46
47 /* local function prototypes */
48 static void print_groups (const char *member);
49
50 /*
51  * print_groups - print the groups which the named user is a member of
52  *
53  *      print_groups() scans the groups file for the list of groups which
54  *      the user is listed as being a member of.
55  */
56 static void print_groups (const char *member)
57 {
58         int groups = 0;
59         struct group *grp;
60         struct passwd *pwd;
61         bool flag = false;
62
63         pwd = getpwnam (member); /* local, no need for xgetpwnam */
64         if (NULL == pwd) {
65                 (void) fprintf (stderr, _("%s: unknown user %s\n"),
66                                 Prog, member);
67                 exit (EXIT_FAILURE);
68         }
69
70         setgrent ();
71         while ((grp = getgrent ()) != NULL) {
72                 if (is_on_list (grp->gr_mem, member)) {
73                         if (0 != groups) {
74                                 (void) putchar (' ');
75                         }
76                         groups++;
77
78                         (void) printf ("%s", grp->gr_name);
79                         if (grp->gr_gid == pwd->pw_gid) {
80                                 flag = true;
81                         }
82                 }
83         }
84         endgrent ();
85
86         /* The user may not be in the list of members of its primary group */
87         if (!flag) {
88                 grp = getgrgid (pwd->pw_gid); /* local, no need for xgetgrgid */
89                 if (NULL != grp) {
90                         if (0 != groups) {
91                                 (void) putchar (' ');
92                         }
93                         groups++;
94
95                         (void) printf ("%s", grp->gr_name);
96                 }
97         }
98
99         if (0 != groups) {
100                 (void) putchar ('\n');
101         }
102 }
103
104 /*
105  * groups - print out the groups a process is a member of
106  */
107 int main (int argc, char **argv)
108 {
109 #ifdef HAVE_GETGROUPS
110         long sys_ngroups;
111         GETGROUPS_T *groups;
112 #else
113         char *logname;
114         char *getlogin ();
115 #endif
116
117 #ifdef HAVE_GETGROUPS
118         sys_ngroups = sysconf (_SC_NGROUPS_MAX);
119         groups = (GETGROUPS_T *) malloc (sizeof (GETGROUPS_T) * sys_ngroups);
120 #endif
121         (void) setlocale (LC_ALL, "");
122         (void) bindtextdomain (PACKAGE, LOCALEDIR);
123         (void) textdomain (PACKAGE);
124
125         /*
126          * Get the program name so that error messages can use it.
127          */
128         Prog = Basename (argv[0]);
129
130         if (argc == 1) {
131
132                 /*
133                  * Called with no arguments - give the group set for the
134                  * current user.
135                  */
136
137 #ifdef HAVE_GETGROUPS
138                 int i;
139                 int pri_grp; /* TODO: should be GETGROUPS_T */
140                 /*
141                  * This system supports concurrent group sets, so I can ask
142                  * the system to tell me which groups are currently set for
143                  * this process.
144                  */
145                 int ngroups = getgroups (sys_ngroups, groups);
146                 if (ngroups < 0) {
147                         perror ("getgroups");
148                         exit (EXIT_FAILURE);
149                 }
150
151                 /*
152                  * The groupset includes the primary group as well.
153                  */
154                 pri_grp = getegid ();
155                 for (i = 0; i < ngroups; i++) {
156                         if (pri_grp == (int) groups[i]) {
157                                 break;
158                         }
159                 }
160
161                 if (i != ngroups) {
162                         pri_grp = -1;
163                 }
164
165                 /*
166                  * Print out the name of every group in the current group
167                  * set. Unknown groups are printed as their decimal group ID
168                  * values.
169                  */
170                 if (-1 != pri_grp) {
171                         struct group *gr;
172                         /* local, no need for xgetgrgid */
173                         gr = getgrgid (pri_grp);
174                         if (NULL != gr) {
175                                 (void) printf ("%s", gr->gr_name);
176                         } else {
177                                 (void) printf ("%d", pri_grp);
178                         }
179                 }
180
181                 for (i = 0; i < ngroups; i++) {
182                         struct group *gr;
183                         if ((0 != i) || (-1 != pri_grp)) {
184                                 (void) putchar (' ');
185                         }
186
187                         /* local, no need for xgetgrgid */
188                         gr = getgrgid (groups[i]);
189                         if (NULL != gr) {
190                                 (void) printf ("%s", gr->gr_name);
191                         } else {
192                                 (void) printf ("%ld", (long) groups[i]);
193                         }
194                 }
195                 (void) putchar ('\n');
196 #else
197                 /*
198                  * This system does not have the getgroups() system call, so
199                  * I must check the groups file directly.
200                  */
201                 logname = getlogin ();
202                 if (NULL != logname) {
203                         print_groups (logname);
204                 } else {
205                         exit (EXIT_FAILURE);
206                 }
207 #endif
208         } else {
209
210                 /*
211                  * The invoker wanted to know about some other user. Use
212                  * that name to look up the groups instead.
213                  */
214                 print_groups (argv[1]);
215         }
216         return EXIT_SUCCESS;
217 }
218