]> granicus.if.org Git - shadow/blob - libmisc/addgrps.c
(failcheck): The failed argument is a bool.
[shadow] / libmisc / addgrps.c
1 /*
2  * Copyright (c) 1989 - 1994, Julianne Frances Haugh
3  * Copyright (c) 1996 - 1998, 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 #ifdef HAVE_SETGROUPS
36
37 #include "prototypes.h"
38 #include "defines.h"
39
40 #include <stdio.h>
41 #include <grp.h>
42 #include <errno.h>
43
44 #ident "$Id$"
45
46 #define SEP ",:"
47 /*
48  * Add groups with names from LIST (separated by commas or colons)
49  * to the supplementary group set.  Silently ignore groups which are
50  * already there.  Warning: uses strtok().
51  */
52 int add_groups (const char *list)
53 {
54         GETGROUPS_T *grouplist, *tmp;
55         int i, ngroups;
56         bool added;
57         char *token;
58         char buf[1024];
59
60         if (strlen (list) >= sizeof (buf)) {
61                 errno = EINVAL;
62                 return -1;
63         }
64         strcpy (buf, list);
65
66         i = 16;
67         for (;;) {
68                 grouplist = (gid_t *) malloc (i * sizeof (GETGROUPS_T));
69                 if (!grouplist)
70                         return -1;
71                 ngroups = getgroups (i, grouplist);
72                 if (i > ngroups)
73                         break;
74                 /* not enough room, so try allocating a larger buffer */
75                 free (grouplist);
76                 i *= 2;
77         }
78         if (ngroups < 0) {
79                 free (grouplist);
80                 return -1;
81         }
82
83         added = false;
84         for (token = strtok (buf, SEP); NULL != token; token = strtok (NULL, SEP)) {
85                 struct group *grp;
86
87                 grp = getgrnam (token); /* local, no need for xgetgrnam */
88                 if (NULL == grp) {
89                         fprintf (stderr, _("Warning: unknown group %s\n"),
90                                  token);
91                         continue;
92                 }
93
94                 for (i = 0; i < ngroups && grouplist[i] != grp->gr_gid; i++);
95
96                 if (i < ngroups)
97                         continue;
98
99                 if (ngroups >= sysconf (_SC_NGROUPS_MAX)) {
100                         fputs (_("Warning: too many groups\n"), stderr);
101                         break;
102                 }
103                 tmp = (gid_t *) realloc (grouplist, (ngroups + 1) * sizeof (GETGROUPS_T));
104                 if (NULL == tmp) {
105                         free (grouplist);
106                         return -1;
107                 }
108                 tmp[ngroups++] = grp->gr_gid;
109                 grouplist = tmp;
110                 added = true;
111         }
112
113         if (added)
114                 return setgroups (ngroups, grouplist);
115
116         return 0;
117 }
118 #endif
119