1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2 * vim:expandtab:shiftwidth=8:tabstop=8:
10 #include <sys/types.h>
18 #define NGROUPS_MAX 32
21 static const char usage[] =
22 "Usage: %s -u user_id [-g grp_id] [-v euid] [-j egid] [-G[gid0,gid1,...]] command\n"
23 " -u user_id switch to UID user_id\n"
24 " -g grp_id switch to GID grp_id\n"
25 " -v euid switch euid to UID\n"
26 " -j egid switch egid to GID\n"
27 " -G[gid0,gid1,...] set supplementary groups\n";
29 void Usage_and_abort(const char *name)
31 fprintf(stderr, usage, name);
35 int main(int argc, char **argv)
37 char **my_argv, *name = argv[0], *grp;
39 int gid_is_set = 0, uid_is_set = 0, num_supp = -1;
41 gid_t grp_id = 0, supp_groups[NGROUPS_MAX] = { 0 };
42 int euid_is_set = 0, egid_is_set = 0;
47 fprintf(stderr, "No parameter count\n");
48 Usage_and_abort(name);
52 while ((c = getopt(argc, argv, "+u:g:v:j:hG::")) != -1) {
55 if (!isdigit(optarg[0])) {
56 struct passwd *pw = getpwnam(optarg);
58 fprintf(stderr, "parameter '%s' bad\n",
60 Usage_and_abort(name);
64 user_id = (uid_t)atoi(optarg);
72 if (!isdigit(optarg[0])) {
73 struct group *gr = getgrnam(optarg);
75 fprintf(stderr, "getgrname %s failed\n",
77 Usage_and_abort(name);
81 grp_id = (gid_t)atoi(optarg);
87 if (!isdigit(optarg[0])) {
88 struct passwd *pw = getpwnam(optarg);
90 fprintf(stderr, "parameter '%s' bad\n",
92 Usage_and_abort(name);
96 euid = (uid_t)atoi(optarg);
102 if (!isdigit(optarg[0])) {
103 struct group *gr = getgrnam(optarg);
105 fprintf(stderr, "getgrname %s failed\n",
107 Usage_and_abort(name);
111 egid = (gid_t)atoi(optarg);
118 if (optarg == NULL || !isdigit(optarg[0]))
120 while ((grp = strsep(&optarg, ",")) != NULL) {
121 printf("adding supp group %d\n", atoi(grp));
122 supp_groups[num_supp++] = atoi(grp);
123 if (num_supp >= NGROUPS_MAX)
130 Usage_and_abort(name);
136 fprintf(stderr, "Must specify uid to run.\n");
137 Usage_and_abort(name);
140 if (optind == argc) {
141 fprintf(stderr, "Must specify command to run.\n");
142 Usage_and_abort(name);
145 // assemble the command
146 my_argv = (char**)malloc(sizeof(char*)*(argc+1-optind));
147 if (my_argv == NULL) {
148 fprintf(stderr, "Error in allocating memory. (%s)\n",
153 for (i = optind; i < argc; i++) {
154 my_argv[i-optind] = argv[i];
155 //printf("%s\n",my_argv[i-optind]);
157 my_argv[i-optind] = NULL;
166 status = setregid(grp_id, egid);
168 fprintf(stderr, "Cannot change gid to %d/%d, errno=%d (%s)\n",
169 grp_id, egid, errno, strerror(errno) );
174 status = setgroups(num_supp, supp_groups);
176 perror("setting supplementary groups");
184 status = setreuid(user_id, euid);
186 fprintf(stderr,"Cannot change uid to %d/%d, errno=%d (%s)\n",
187 user_id, euid, errno, strerror(errno) );
191 fprintf(stderr, "running as uid/gid/euid/egid %d/%d/%d/%d, groups:",
192 user_id, grp_id, euid, egid);
193 for (i = 0; i < num_supp; i++)
194 fprintf(stderr, " %d", supp_groups[i]);
195 fprintf(stderr, "\n");
197 for (i = 0; i < argc - optind; i++)
198 fprintf(stderr, " [%s]", my_argv[i]);
200 fprintf(stderr, "\n");
203 // The command to be run
204 execvp(my_argv[0], my_argv);
205 fprintf(stderr, "execvp fails running %s (%d): %s\n", my_argv[0],
206 errno, strerror(errno));