1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2 * vim:expandtab:shiftwidth=8:tabstop=8:
10 #include <sys/types.h>
17 #define NGROUPS_MAX 32
20 static const char usage[] =
21 "Usage: %s -u user_id [-g grp_id] [-G[gid0,gid1,...]] command\n"
22 " -u user_id switch to UID user_id\n"
23 " -g grp_id switch to GID grp_id\n"
24 " -G[gid0,gid1,...] set supplementary groups\n";
26 void Usage_and_abort(const char *name)
28 fprintf(stderr, usage, name);
32 int main(int argc, char **argv)
34 char **my_argv, *name = argv[0], *grp;
36 int gid_is_set = 0, uid_is_set = 0, num_supp = -1;
38 gid_t grp_id = 0, supp_groups[NGROUPS_MAX] = { 0 };
41 Usage_and_abort(name);
44 while ((c = getopt(argc, argv, "+u:g:hG::")) != -1) {
47 user_id = (uid_t)atoi(optarg);
54 grp_id = (gid_t)atoi(optarg);
60 if (optarg == NULL || !isdigit(optarg[0]))
62 while ((grp = strsep(&optarg, ",")) != NULL) {
63 printf("adding supp group %d\n", atoi(grp));
64 supp_groups[num_supp++] = atoi(grp);
65 if (num_supp >= NGROUPS_MAX)
72 Usage_and_abort(name);
78 Usage_and_abort(name);
81 fputs("Must specify command to run.\n", stderr);
82 Usage_and_abort(name);
85 // assemble the command
86 my_argv = (char**)malloc(sizeof(char*)*(argc+1-optind));
87 if (my_argv == NULL) {
88 fprintf(stderr, "Error in allocating memory. (%s)\n",
93 for (i = optind; i < argc; i++) {
94 my_argv[i-optind] = argv[i];
95 //printf("%s\n",my_argv[i-optind]);
97 my_argv[i-optind] = NULL;
104 status = setregid(grp_id, grp_id);
106 fprintf(stderr, "Cannot change grp_ID to %d, errno=%d (%s)\n",
107 grp_id, errno, strerror(errno) );
112 status = setgroups(num_supp, supp_groups);
114 perror("setting supplementary groups");
120 status = setreuid(user_id, user_id );
122 fprintf(stderr,"Cannot change user_ID to %d, errno=%d (%s)\n",
123 user_id, errno, strerror(errno) );
127 fprintf(stderr, "running as UID %d, GID %d", user_id, grp_id);
128 for (i = 0; i < num_supp; i++)
129 fprintf(stderr, ":%d", supp_groups[i]);
130 fprintf(stderr, "\n");
132 for (i = 0; i < argc - optind; i++)
133 fprintf(stderr, " [%s]", my_argv[i]);
135 fprintf(stderr, "\n");
138 // The command to be run
139 execvp(my_argv[0], my_argv);
140 fprintf(stderr, "execvp fails running %s\n", my_argv[0]);