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] [-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 " -G[gid0,gid1,...] set supplementary groups\n";
27 void Usage_and_abort(const char *name)
29 fprintf(stderr, usage, name);
33 int main(int argc, char **argv)
35 char **my_argv, *name = argv[0], *grp;
37 int gid_is_set = 0, uid_is_set = 0, num_supp = -1;
39 gid_t grp_id = 0, supp_groups[NGROUPS_MAX] = { 0 };
42 fprintf(stderr, "No parameter count\n");
43 Usage_and_abort(name);
47 while ((c = getopt(argc, argv, "+u:g:hG::")) != -1) {
50 if (!isdigit(optarg[0])) {
51 struct passwd *pw = getpwnam(optarg);
53 fprintf(stderr, "parameter '%s' bad\n",
55 Usage_and_abort(name);
59 user_id = (uid_t)atoi(optarg);
67 if (!isdigit(optarg[0])) {
68 struct group *gr = getgrnam(optarg);
70 fprintf(stderr, "getgrname %s failed\n",
72 Usage_and_abort(name);
76 grp_id = (gid_t)atoi(optarg);
83 if (optarg == NULL || !isdigit(optarg[0]))
85 while ((grp = strsep(&optarg, ",")) != NULL) {
86 printf("adding supp group %d\n", atoi(grp));
87 supp_groups[num_supp++] = atoi(grp);
88 if (num_supp >= NGROUPS_MAX)
95 Usage_and_abort(name);
101 fprintf(stderr, "Must specify uid to run.\n");
102 Usage_and_abort(name);
105 if (optind == argc) {
106 fprintf(stderr, "Must specify command to run.\n");
107 Usage_and_abort(name);
110 // assemble the command
111 my_argv = (char**)malloc(sizeof(char*)*(argc+1-optind));
112 if (my_argv == NULL) {
113 fprintf(stderr, "Error in allocating memory. (%s)\n",
118 for (i = optind; i < argc; i++) {
119 my_argv[i-optind] = argv[i];
120 //printf("%s\n",my_argv[i-optind]);
122 my_argv[i-optind] = NULL;
129 status = setregid(grp_id, grp_id);
131 fprintf(stderr, "Cannot change grp_ID to %d, errno=%d (%s)\n",
132 grp_id, errno, strerror(errno) );
137 status = setgroups(num_supp, supp_groups);
139 perror("setting supplementary groups");
145 status = setreuid(user_id, user_id );
147 fprintf(stderr,"Cannot change user_ID to %d, errno=%d (%s)\n",
148 user_id, errno, strerror(errno) );
152 fprintf(stderr, "running as UID %d, GID %d", user_id, grp_id);
153 for (i = 0; i < num_supp; i++)
154 fprintf(stderr, ":%d", supp_groups[i]);
155 fprintf(stderr, "\n");
157 for (i = 0; i < argc - optind; i++)
158 fprintf(stderr, " [%s]", my_argv[i]);
160 fprintf(stderr, "\n");
163 // The command to be run
164 execvp(my_argv[0], my_argv);
165 fprintf(stderr, "execvp fails running %s (%d): %s\n", my_argv[0],
166 errno, strerror(errno));