Whamcloud - gitweb
LU-160 Reduce OST size requirement for test 155
[fs/lustre-release.git] / lustre / tests / runas.c
1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2  * vim:expandtab:shiftwidth=8:tabstop=8:
3  *
4  * GPL HEADER START
5  *
6  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License version 2 only,
10  * as published by the Free Software Foundation.
11  *
12  * This program is distributed in the hope that it will be useful, but
13  * WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * General Public License version 2 for more details (a copy is included
16  * in the LICENSE file that accompanied this code).
17  *
18  * You should have received a copy of the GNU General Public License
19  * version 2 along with this program; If not, see
20  * http://www.sun.com/software/products/lustre/docs/GPLv2.pdf
21  *
22  * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
23  * CA 95054 USA or visit www.sun.com if you need additional information or
24  * have any questions.
25  *
26  * GPL HEADER END
27  */
28 /*
29  * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
30  * Use is subject to license terms.
31  */
32 /*
33  * This file is part of Lustre, http://www.lustre.org/
34  * Lustre is a trademark of Sun Microsystems, Inc.
35  */
36
37 #include <stdio.h>
38 #include <stdlib.h>
39 #include <unistd.h>
40 #include <string.h>
41 #include <errno.h>
42 #include <ctype.h>
43 #include <sys/types.h>
44 #include <pwd.h>
45 #include <grp.h>
46 #include <sys/wait.h>
47
48 #define DEBUG 0
49
50 #ifndef NGROUPS_MAX
51 #define NGROUPS_MAX 32
52 #endif
53
54 static const char usage[] =
55 "Usage: %s -u user_id [-g grp_id] [-v euid] [-j egid] [-G[gid0,gid1,...]] command\n"
56 "  -u user_id           switch to UID user_id\n"
57 "  -g grp_id            switch to GID grp_id\n"
58 "  -v euid              switch euid to UID\n"
59 "  -j egid              switch egid to GID\n"
60 "  -G[gid0,gid1,...]    set supplementary groups\n";
61
62 void Usage_and_abort(const char *name)
63 {
64         fprintf(stderr, usage, name);
65         exit(-1);
66 }
67
68 int main(int argc, char **argv)
69 {
70         char **my_argv, *name = argv[0], *grp;
71         int status, c, i;
72         int gid_is_set = 0, uid_is_set = 0, num_supp = -1;
73         uid_t user_id = 0;
74         gid_t grp_id = 0, supp_groups[NGROUPS_MAX] = { 0 };
75         int euid_is_set = 0, egid_is_set = 0;
76         uid_t euid = 0;
77         gid_t egid = 0;
78
79         if (argc == 1) {
80                 fprintf(stderr, "No parameter count\n");
81                 Usage_and_abort(name);
82         }
83
84         // get UID and GID
85         while ((c = getopt(argc, argv, "+u:g:v:j:hG::")) != -1) {
86                 switch (c) {
87                 case 'u':
88                         if (!isdigit(optarg[0])) {
89                                 struct passwd *pw = getpwnam(optarg);
90                                 if (pw == NULL) {
91                                         fprintf(stderr, "parameter '%s' bad\n",
92                                                 optarg);
93                                         Usage_and_abort(name);
94                                 }
95                                 user_id = pw->pw_uid;
96                         } else {
97                                 user_id = (uid_t)atoi(optarg);
98                         }
99                         uid_is_set = 1;
100                         if (!gid_is_set)
101                                 grp_id = user_id;
102                         break;
103
104                 case 'g':
105                         if (!isdigit(optarg[0])) {
106                                 struct group *gr = getgrnam(optarg);
107                                 if (gr == NULL) {
108                                         fprintf(stderr, "getgrname %s failed\n",
109                                                 optarg);
110                                         Usage_and_abort(name);
111                                 }
112                                 grp_id = gr->gr_gid;
113                         } else {
114                                 grp_id = (gid_t)atoi(optarg);
115                         }
116                         gid_is_set = 1;
117                         break;
118
119                 case 'v':
120                         if (!isdigit(optarg[0])) {
121                                 struct passwd *pw = getpwnam(optarg);
122                                 if (pw == NULL) {
123                                         fprintf(stderr, "parameter '%s' bad\n",
124                                                 optarg);
125                                         Usage_and_abort(name);
126                                 }
127                                 euid = pw->pw_uid;
128                         } else {
129                                 euid = (uid_t)atoi(optarg);
130                         }
131                         euid_is_set = 1;
132                         break;
133
134                 case 'j':
135                         if (!isdigit(optarg[0])) {
136                                 struct group *gr = getgrnam(optarg);
137                                 if (gr == NULL) {
138                                         fprintf(stderr, "getgrname %s failed\n",
139                                                 optarg);
140                                         Usage_and_abort(name);
141                                 }
142                                 egid = gr->gr_gid;
143                         } else {
144                                 egid = (gid_t)atoi(optarg);
145                         }
146                         egid_is_set = 1;
147                         break;
148
149                 case 'G':
150                         num_supp = 0;
151                         if (optarg == NULL || !isdigit(optarg[0]))
152                                 break;
153                         while ((grp = strsep(&optarg, ",")) != NULL) {
154                                 printf("adding supp group %d\n", atoi(grp));
155                                 supp_groups[num_supp++] = atoi(grp);
156                                 if (num_supp >= NGROUPS_MAX)
157                                         break;
158                         }
159                         break;
160
161                 default:
162                 case 'h':
163                         Usage_and_abort(name);
164                         break;
165                 }
166         }
167
168         if (!uid_is_set) {
169                 fprintf(stderr, "Must specify uid to run.\n");
170                 Usage_and_abort(name);
171         }
172
173         if (optind == argc) {
174                 fprintf(stderr, "Must specify command to run.\n");
175                 Usage_and_abort(name);
176         }
177
178         // assemble the command
179         my_argv = (char**)malloc(sizeof(char*)*(argc+1-optind));
180         if (my_argv == NULL) {
181                 fprintf(stderr, "Error in allocating memory. (%s)\n",
182                         strerror(errno));
183                 exit(-1);
184         }
185
186         for (i = optind; i < argc; i++) {
187                 my_argv[i-optind] = argv[i];
188                 //printf("%s\n",my_argv[i-optind]);
189         }
190         my_argv[i-optind] = NULL;
191
192 #if DEBUG
193         system("whoami");
194 #endif
195
196         // set GID
197         if (!egid_is_set)
198                 egid = grp_id;
199         status = setregid(grp_id, egid);
200         if (status == -1) {
201                  fprintf(stderr, "Cannot change gid to %d/%d, errno=%d (%s)\n",
202                          grp_id, egid, errno, strerror(errno) );
203                  exit(-1);
204         }
205
206         if (num_supp >= 0) {
207                 status = setgroups(num_supp, supp_groups);
208                 if (status == -1) {
209                         perror("setting supplementary groups");
210                         exit(-1);
211                 }
212         }
213
214         // set UID
215         if (!euid_is_set)
216                 euid = user_id;
217         status = setreuid(user_id, euid);
218         if(status == -1) {
219                   fprintf(stderr,"Cannot change uid to %d/%d, errno=%d (%s)\n",
220                            user_id, euid, errno, strerror(errno) );
221                   exit(-1);
222         }
223
224         fprintf(stderr, "running as uid/gid/euid/egid %d/%d/%d/%d, groups:",
225                 user_id, grp_id, euid, egid);
226         for (i = 0; i < num_supp; i++)
227                 fprintf(stderr, " %d", supp_groups[i]);
228         fprintf(stderr, "\n");
229
230         for (i = 0; i < argc - optind; i++)
231                  fprintf(stderr, " [%s]", my_argv[i]);
232
233         fprintf(stderr, "\n");
234         fflush(stderr);
235
236         // The command to be run
237         execvp(my_argv[0], my_argv);
238         fprintf(stderr, "execvp fails running %s (%d): %s\n", my_argv[0],
239                 errno, strerror(errno));
240         exit(-1);
241 }