little clarification
[hband-tools.git] / compiled-tools / setgroups.c
blob929f56ab9c7a620c0224868830d12c82007e630a
1 /*
2 Compile-time config options:
3 ONLY_ALLOWED_GID
4 If you set a gid, then what 'setgroups' does is only add this
5 group to the supplementary group list. So you call it like:
7 ./setgroups some command
9 If you don't set, then you have to pass group IDs you wish to
10 take on, and command argument you wish to execute with the new
11 supplementary group set, separated by '--', like:
13 ./setgroups 199 1000 4256 -- some command
15 Set file capabilities after compiled:
16 setcaps cap_setgid+ep ./setgroups
19 #include <stdlib.h>
20 #include <sys/types.h>
21 #include <unistd.h>
22 #include <errno.h>
23 #include <err.h>
24 #include <string.h>
27 int main(int argc, char ** argv)
29 gid_t * gidlist;
30 int sz_gidlist;
31 int aux1;
32 int aux2;
33 int backshift;
34 int n_groups;
35 char ** endptr;
36 int n_set_groups;
37 int n_removed_groups;
38 long set_gid;
39 char ** execargs;
41 if(argc < 2) errx(-1, "No command given.");
43 n_removed_groups = 0;
44 sz_gidlist = 4;
45 gidlist = malloc(sz_gidlist * sizeof(gid_t));
46 if(gidlist == NULL) abort();
48 while((n_groups = getgroups(sz_gidlist, gidlist)) == -1)
50 if(errno == EINVAL)
52 sz_gidlist *= 2;
53 gidlist = realloc(gidlist, sz_gidlist * sizeof(gid_t));
54 if(gidlist == NULL) abort();
56 else
58 err(errno, "getgroups");
62 #ifndef ONLY_ALLOWED_GID
63 n_set_groups = 0;
65 for(aux1 = 1; aux1 < argc; aux1++)
67 if(strcmp(argv[aux1], "--") == 0) { aux1++; break; }
68 n_set_groups += 1;
71 if(aux1 >= argc) errx(-1, "No command given.");
72 execargs = &argv[aux1];
73 #else
74 n_set_groups = 1;
75 execargs = &argv[1];
76 #endif
78 if(n_groups + n_set_groups /* TODO: don't allocate memory for gids which will be removed */ > sz_gidlist)
80 sz_gidlist += n_set_groups;
81 gidlist = realloc(gidlist, sz_gidlist * sizeof(gid_t));
82 if(gidlist == NULL) abort();
85 #ifndef ONLY_ALLOWED_GID
86 for(aux1 = 0; aux1 < n_set_groups; aux1++)
88 errno = 0;
89 set_gid = strtol(argv[1+aux1], endptr, 0);
90 if(*endptr == argv[1+aux1] || **endptr != '\0') errx(-1, "Can not parse '%s' as GID", argv[1+aux1]);
91 if(errno != 0) err(errno, "Can not parse '%s' as GID", argv[1+aux1]);
93 if(set_gid > 0)
95 gidlist[n_groups - 2*n_removed_groups + aux1] = (gid_t)set_gid;
97 else
99 backshift = 0;
100 for(aux2 = 0; aux2 < n_groups - n_removed_groups - backshift + aux1; aux2++)
102 if(gidlist[aux2] == -set_gid) backshift += 1;
103 gidlist[aux2] = gidlist[aux2 + backshift];
105 n_removed_groups += backshift;
108 #else
109 gidlist[n_groups] = ONLY_ALLOWED_GID;
110 #endif
112 if(setgroups(n_groups + n_set_groups - 2*n_removed_groups, gidlist) != 0)
114 err(errno, "setgroups");
117 execvp(execargs[0], execargs);
118 err(errno, "exec: %s", execargs[0]);