4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 only,
8 * as published by the Free Software Foundation.
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License version 2 for more details (a copy is included
14 * in the LICENSE file that accompanied this code).
16 * You should have received a copy of the GNU General Public License
17 * version 2 along with this program; If not, see
18 * http://www.gnu.org/licenses/gpl-2.0.html
23 * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
24 * Use is subject to license terms.
27 * This file is part of Lustre, http://www.lustre.org/
28 * Lustre is a trademark of Sun Microsystems, Inc.
37 #include <sys/types.h>
45 #define NGROUPS_MAX 32
48 static const char usage[] =
49 "Usage: %s -u user_id [-g grp_id] [-v euid] [-j egid] [-G[gid0,gid1,...]] command\n"
50 " -u user_id switch to UID user_id\n"
51 " -g grp_id switch to GID grp_id\n"
52 " -v euid switch euid to UID\n"
53 " -j egid switch egid to GID\n"
54 " -G[gid0,gid1,...] set supplementary groups\n";
56 void Usage_and_abort(const char *name)
58 fprintf(stderr, usage, name);
62 int main(int argc, char **argv)
64 char **my_argv, *name = argv[0], *grp;
66 int gid_is_set = 0, uid_is_set = 0, num_supp = -1;
68 gid_t grp_id = 0, supp_groups[NGROUPS_MAX] = { 0 };
69 int euid_is_set = 0, egid_is_set = 0;
74 fprintf(stderr, "No parameter count\n");
75 Usage_and_abort(name);
79 while ((c = getopt(argc, argv, "+u:g:v:j:hG::")) != -1) {
82 if (!isdigit(optarg[0])) {
83 struct passwd *pw = getpwnam(optarg);
86 fprintf(stderr, "parameter '%s' bad\n",
88 Usage_and_abort(name);
92 user_id = (uid_t)atoi(optarg);
100 if (!isdigit(optarg[0])) {
101 struct group *gr = getgrnam(optarg);
104 fprintf(stderr, "getgrname %s failed\n",
106 Usage_and_abort(name);
110 grp_id = (gid_t)atoi(optarg);
116 if (!isdigit(optarg[0])) {
117 struct passwd *pw = getpwnam(optarg);
120 fprintf(stderr, "parameter '%s' bad\n",
122 Usage_and_abort(name);
126 euid = (uid_t)atoi(optarg);
132 if (!isdigit(optarg[0])) {
133 struct group *gr = getgrnam(optarg);
136 fprintf(stderr, "getgrname %s failed\n",
138 Usage_and_abort(name);
142 egid = (gid_t)atoi(optarg);
149 if (!optarg || !isdigit(optarg[0]))
151 while ((grp = strsep(&optarg, ",")) != NULL) {
152 printf("adding supp group %d\n", atoi(grp));
153 supp_groups[num_supp++] = atoi(grp);
154 if (num_supp >= NGROUPS_MAX)
161 Usage_and_abort(name);
167 fprintf(stderr, "Must specify uid to run.\n");
168 Usage_and_abort(name);
171 if (optind == argc) {
172 fprintf(stderr, "Must specify command to run.\n");
173 Usage_and_abort(name);
176 /* assemble the command */
177 my_argv = (char **)malloc(sizeof(char *) * (argc + 1 - optind));
179 fprintf(stderr, "Error in allocating memory. (%s)\n",
184 for (i = optind; i < argc; i++)
185 my_argv[i - optind] = argv[i];
187 my_argv[i - optind] = NULL;
196 status = setregid(grp_id, egid);
198 fprintf(stderr, "Cannot change gid to %d/%d, errno=%d (%s)\n",
199 grp_id, egid, errno, strerror(errno));
204 status = setgroups(num_supp, supp_groups);
206 perror("setting supplementary groups");
214 status = setreuid(user_id, euid);
216 fprintf(stderr, "Cannot change uid to %d/%d, errno=%d (%s)\n",
217 user_id, euid, errno, strerror(errno));
221 fprintf(stderr, "running as uid/gid/euid/egid %d/%d/%d/%d, groups:",
222 user_id, grp_id, euid, egid);
223 for (i = 0; i < num_supp; i++)
224 fprintf(stderr, " %d", supp_groups[i]);
225 fprintf(stderr, "\n");
227 for (i = 0; i < argc - optind; i++)
228 fprintf(stderr, " [%s]", my_argv[i]);
230 fprintf(stderr, "\n");
233 /* The command to be run */
234 execvp(my_argv[0], my_argv);
235 fprintf(stderr, "execvp fails running %s (%d): %s\n", my_argv[0],
236 errno, strerror(errno));