Whamcloud - gitweb
LU-6142 tests: Fix style issues for runas.c
[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  * Lustre is a trademark of Sun Microsystems, Inc.
29  */
30
31 #include <stdio.h>
32 #include <stdlib.h>
33 #include <unistd.h>
34 #include <string.h>
35 #include <errno.h>
36 #include <ctype.h>
37 #include <sys/types.h>
38 #include <pwd.h>
39 #include <grp.h>
40 #include <sys/wait.h>
41
42 #define DEBUG 0
43
44 #ifndef NGROUPS_MAX
45 #define NGROUPS_MAX 32
46 #endif
47
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";
55
56 void Usage_and_abort(const char *name)
57 {
58         fprintf(stderr, usage, name);
59         exit(-1);
60 }
61
62 int main(int argc, char **argv)
63 {
64         char **my_argv, *name = argv[0], *grp;
65         int status, c, i;
66         int gid_is_set = 0, uid_is_set = 0, num_supp = -1;
67         uid_t user_id = 0;
68         gid_t grp_id = 0, supp_groups[NGROUPS_MAX] = { 0 };
69         int euid_is_set = 0, egid_is_set = 0;
70         uid_t euid = 0;
71         gid_t egid = 0;
72
73         if (argc == 1) {
74                 fprintf(stderr, "No parameter count\n");
75                 Usage_and_abort(name);
76         }
77
78         /* get UID and GID */
79         while ((c = getopt(argc, argv, "+u:g:v:j:hG::")) != -1) {
80                 switch (c) {
81                 case 'u':
82                         if (!isdigit(optarg[0])) {
83                                 struct passwd *pw = getpwnam(optarg);
84
85                                 if (!pw) {
86                                         fprintf(stderr, "parameter '%s' bad\n",
87                                                 optarg);
88                                         Usage_and_abort(name);
89                                 }
90                                 user_id = pw->pw_uid;
91                         } else {
92                                 user_id = (uid_t)atoi(optarg);
93                         }
94                         uid_is_set = 1;
95                         if (!gid_is_set)
96                                 grp_id = user_id;
97                         break;
98
99                 case 'g':
100                         if (!isdigit(optarg[0])) {
101                                 struct group *gr = getgrnam(optarg);
102
103                                 if (!gr) {
104                                         fprintf(stderr, "getgrname %s failed\n",
105                                                 optarg);
106                                         Usage_and_abort(name);
107                                 }
108                                 grp_id = gr->gr_gid;
109                         } else {
110                                 grp_id = (gid_t)atoi(optarg);
111                         }
112                         gid_is_set = 1;
113                         break;
114
115                 case 'v':
116                         if (!isdigit(optarg[0])) {
117                                 struct passwd *pw = getpwnam(optarg);
118
119                                 if (!pw) {
120                                         fprintf(stderr, "parameter '%s' bad\n",
121                                                 optarg);
122                                         Usage_and_abort(name);
123                                 }
124                                 euid = pw->pw_uid;
125                         } else {
126                                 euid = (uid_t)atoi(optarg);
127                         }
128                         euid_is_set = 1;
129                         break;
130
131                 case 'j':
132                         if (!isdigit(optarg[0])) {
133                                 struct group *gr = getgrnam(optarg);
134
135                                 if (!gr) {
136                                         fprintf(stderr, "getgrname %s failed\n",
137                                                 optarg);
138                                         Usage_and_abort(name);
139                                 }
140                                 egid = gr->gr_gid;
141                         } else {
142                                 egid = (gid_t)atoi(optarg);
143                         }
144                         egid_is_set = 1;
145                         break;
146
147                 case 'G':
148                         num_supp = 0;
149                         if (!optarg || !isdigit(optarg[0]))
150                                 break;
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)
155                                         break;
156                         }
157                         break;
158
159                 default:
160                 case 'h':
161                         Usage_and_abort(name);
162                         break;
163                 }
164         }
165
166         if (!uid_is_set) {
167                 fprintf(stderr, "Must specify uid to run.\n");
168                 Usage_and_abort(name);
169         }
170
171         if (optind == argc) {
172                 fprintf(stderr, "Must specify command to run.\n");
173                 Usage_and_abort(name);
174         }
175
176         /* assemble the command */
177         my_argv = (char **)malloc(sizeof(char *) * (argc + 1 - optind));
178         if (!my_argv) {
179                 fprintf(stderr, "Error in allocating memory. (%s)\n",
180                         strerror(errno));
181                 exit(-1);
182         }
183
184         for (i = optind; i < argc; i++)
185                 my_argv[i - optind] = argv[i];
186
187         my_argv[i - optind] = NULL;
188
189 #if DEBUG
190         system("whoami");
191 #endif
192
193         /* set GID */
194         if (!egid_is_set)
195                 egid = grp_id;
196         status = setregid(grp_id, egid);
197         if (status == -1) {
198                 fprintf(stderr, "Cannot change gid to %d/%d, errno=%d (%s)\n",
199                         grp_id, egid, errno, strerror(errno));
200                 exit(-1);
201         }
202
203         if (num_supp >= 0) {
204                 status = setgroups(num_supp, supp_groups);
205                 if (status == -1) {
206                         perror("setting supplementary groups");
207                         exit(-1);
208                 }
209         }
210
211         /* set UID */
212         if (!euid_is_set)
213                 euid = user_id;
214         status = setreuid(user_id, euid);
215         if (status == -1) {
216                 fprintf(stderr, "Cannot change uid to %d/%d, errno=%d (%s)\n",
217                         user_id, euid, errno, strerror(errno));
218                 exit(-1);
219         }
220
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");
226
227         for (i = 0; i < argc - optind; i++)
228                 fprintf(stderr, " [%s]", my_argv[i]);
229
230         fprintf(stderr, "\n");
231         fflush(stderr);
232
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));
237         exit(-1);
238 }