Whamcloud - gitweb
LU-15152 tests: auster reports wrong testsuite status
[fs/lustre-release.git] / lustre / tests / runas.c
1 /*
2  * GPL HEADER START
3  *
4  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5  *
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.
9  *
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).
15  *
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
19  *
20  * GPL HEADER END
21  */
22 /*
23  * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
24  * Use is subject to license terms.
25  */
26 /*
27  * This file is part of Lustre, http://www.lustre.org/
28  */
29
30 #include <stdio.h>
31 #include <stdlib.h>
32 #include <unistd.h>
33 #include <string.h>
34 #include <errno.h>
35 #include <ctype.h>
36 #include <sys/types.h>
37 #include <pwd.h>
38 #include <grp.h>
39 #include <sys/wait.h>
40
41 #define DEBUG 0
42
43 #ifndef NGROUPS_MAX
44 #define NGROUPS_MAX 32
45 #endif
46
47 static const char usage[] =
48 "Usage: %s -u user_id [-g grp_id] [-v euid] [-j egid] [-G[gid0,gid1,...]] command\n"
49 "  -u user_id           switch to UID user_id\n"
50 "  -g grp_id            switch to GID grp_id\n"
51 "  -v euid              switch euid to UID\n"
52 "  -j egid              switch egid to GID\n"
53 "  -G[gid0,gid1,...]    set supplementary groups\n";
54
55 void Usage_and_abort(const char *name)
56 {
57         fprintf(stderr, usage, name);
58         exit(-1);
59 }
60
61 int main(int argc, char **argv)
62 {
63         char **my_argv, *name = argv[0], *grp;
64         int status, c, i;
65         int gid_is_set = 0, uid_is_set = 0, num_supp = -1;
66         uid_t user_id = 0;
67         gid_t grp_id = 0, supp_groups[NGROUPS_MAX] = { 0 };
68         int euid_is_set = 0, egid_is_set = 0;
69         uid_t euid = 0;
70         gid_t egid = 0;
71
72         if (argc == 1) {
73                 fprintf(stderr, "No parameter count\n");
74                 Usage_and_abort(name);
75         }
76
77         /* get UID and GID */
78         while ((c = getopt(argc, argv, "+u:g:v:j:hG::")) != -1) {
79                 switch (c) {
80                 case 'u':
81                         if (!isdigit(optarg[0])) {
82                                 struct passwd *pw = getpwnam(optarg);
83
84                                 if (!pw) {
85                                         fprintf(stderr, "parameter '%s' bad\n",
86                                                 optarg);
87                                         Usage_and_abort(name);
88                                 }
89                                 user_id = pw->pw_uid;
90                         } else {
91                                 user_id = (uid_t)atoi(optarg);
92                         }
93                         uid_is_set = 1;
94                         if (!gid_is_set)
95                                 grp_id = user_id;
96                         break;
97
98                 case 'g':
99                         if (!isdigit(optarg[0])) {
100                                 struct group *gr = getgrnam(optarg);
101
102                                 if (!gr) {
103                                         fprintf(stderr, "getgrname %s failed\n",
104                                                 optarg);
105                                         Usage_and_abort(name);
106                                 }
107                                 grp_id = gr->gr_gid;
108                         } else {
109                                 grp_id = (gid_t)atoi(optarg);
110                         }
111                         gid_is_set = 1;
112                         break;
113
114                 case 'v':
115                         if (!isdigit(optarg[0])) {
116                                 struct passwd *pw = getpwnam(optarg);
117
118                                 if (!pw) {
119                                         fprintf(stderr, "parameter '%s' bad\n",
120                                                 optarg);
121                                         Usage_and_abort(name);
122                                 }
123                                 euid = pw->pw_uid;
124                         } else {
125                                 euid = (uid_t)atoi(optarg);
126                         }
127                         euid_is_set = 1;
128                         break;
129
130                 case 'j':
131                         if (!isdigit(optarg[0])) {
132                                 struct group *gr = getgrnam(optarg);
133
134                                 if (!gr) {
135                                         fprintf(stderr, "getgrname %s failed\n",
136                                                 optarg);
137                                         Usage_and_abort(name);
138                                 }
139                                 egid = gr->gr_gid;
140                         } else {
141                                 egid = (gid_t)atoi(optarg);
142                         }
143                         egid_is_set = 1;
144                         break;
145
146                 case 'G':
147                         num_supp = 0;
148                         if (!optarg || !isdigit(optarg[0]))
149                                 break;
150                         while ((grp = strsep(&optarg, ",")) != NULL) {
151                                 printf("adding supp group %d\n", atoi(grp));
152                                 supp_groups[num_supp++] = atoi(grp);
153                                 if (num_supp >= NGROUPS_MAX)
154                                         break;
155                         }
156                         break;
157
158                 default:
159                 case 'h':
160                         Usage_and_abort(name);
161                         break;
162                 }
163         }
164
165         if (!uid_is_set) {
166                 fprintf(stderr, "Must specify uid to run.\n");
167                 Usage_and_abort(name);
168         }
169
170         if (optind == argc) {
171                 fprintf(stderr, "Must specify command to run.\n");
172                 Usage_and_abort(name);
173         }
174
175         /* assemble the command */
176         my_argv = (char **)malloc(sizeof(char *) * (argc + 1 - optind));
177         if (!my_argv) {
178                 fprintf(stderr, "Error in allocating memory. (%s)\n",
179                         strerror(errno));
180                 exit(-1);
181         }
182
183         for (i = optind; i < argc; i++)
184                 my_argv[i - optind] = argv[i];
185
186         my_argv[i - optind] = NULL;
187
188 #if DEBUG
189         system("whoami");
190 #endif
191
192         /* set GID */
193         if (!egid_is_set)
194                 egid = grp_id;
195         status = setregid(grp_id, egid);
196         if (status == -1) {
197                 fprintf(stderr, "Cannot change gid to %d/%d, errno=%d (%s)\n",
198                         grp_id, egid, errno, strerror(errno));
199                 exit(-1);
200         }
201
202         if (num_supp >= 0) {
203                 status = setgroups(num_supp, supp_groups);
204                 if (status == -1) {
205                         perror("setting supplementary groups");
206                         exit(-1);
207                 }
208         }
209
210         /* set UID */
211         if (!euid_is_set)
212                 euid = user_id;
213         status = setreuid(user_id, euid);
214         if (status == -1) {
215                 fprintf(stderr, "Cannot change uid to %d/%d, errno=%d (%s)\n",
216                         user_id, euid, errno, strerror(errno));
217                 exit(-1);
218         }
219
220         fprintf(stderr, "running as uid/gid/euid/egid %d/%d/%d/%d, groups:",
221                 user_id, grp_id, euid, egid);
222         for (i = 0; i < num_supp; i++)
223                 fprintf(stderr, " %d", supp_groups[i]);
224         fprintf(stderr, "\n");
225
226         for (i = 0; i < argc - optind; i++)
227                 fprintf(stderr, " [%s]", my_argv[i]);
228
229         fprintf(stderr, "\n");
230         fflush(stderr);
231
232         /* The command to be run */
233         execvp(my_argv[0], my_argv);
234         fprintf(stderr, "execvp fails running %s (%d): %s\n", my_argv[0],
235                 errno, strerror(errno));
236         exit(-1);
237 }