Whamcloud - gitweb
Branch HEAD
[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 #include <stdio.h>
5 #include <stdlib.h>
6 #include <unistd.h>
7 #include <string.h>
8 #include <errno.h>
9 #include <ctype.h>
10 #include <sys/types.h>
11 #include <pwd.h>
12 #include <grp.h>
13 #include <sys/wait.h>
14
15 #define DEBUG 0
16
17 #ifndef NGROUPS_MAX
18 #define NGROUPS_MAX 32
19 #endif
20
21 static const char usage[] =
22 "Usage: %s -u user_id [-g grp_id] [-v euid] [-j egid] [-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 "  -v euid              switch euid to UID\n"
26 "  -j egid              switch egid to GID\n"
27 "  -G[gid0,gid1,...]    set supplementary groups\n";
28
29 void Usage_and_abort(const char *name)
30 {
31         fprintf(stderr, usage, name);
32         exit(-1);
33 }
34
35 int main(int argc, char **argv)
36 {
37         char **my_argv, *name = argv[0], *grp;
38         int status, c, i;
39         int gid_is_set = 0, uid_is_set = 0, num_supp = -1;
40         uid_t user_id = 0;
41         gid_t grp_id = 0, supp_groups[NGROUPS_MAX] = { 0 };
42         int euid_is_set = 0, egid_is_set = 0;
43         uid_t euid = 0;
44         gid_t egid = 0;
45
46         if (argc == 1) {
47                 fprintf(stderr, "No parameter count\n");
48                 Usage_and_abort(name);
49         }
50
51         // get UID and GID
52         while ((c = getopt(argc, argv, "+u:g:v:j:hG::")) != -1) {
53                 switch (c) {
54                 case 'u':
55                         if (!isdigit(optarg[0])) {
56                                 struct passwd *pw = getpwnam(optarg);
57                                 if (pw == NULL) {
58                                         fprintf(stderr, "parameter '%s' bad\n",
59                                                 optarg);
60                                         Usage_and_abort(name);
61                                 }
62                                 user_id = pw->pw_uid;
63                         } else {
64                                 user_id = (uid_t)atoi(optarg);
65                         }
66                         uid_is_set = 1;
67                         if (!gid_is_set)
68                                 grp_id = user_id;
69                         break;
70
71                 case 'g':
72                         if (!isdigit(optarg[0])) {
73                                 struct group *gr = getgrnam(optarg);
74                                 if (gr == NULL) {
75                                         fprintf(stderr, "getgrname %s failed\n",
76                                                 optarg);
77                                         Usage_and_abort(name);
78                                 }
79                                 grp_id = gr->gr_gid;
80                         } else {
81                                 grp_id = (gid_t)atoi(optarg);
82                         }
83                         gid_is_set = 1;
84                         break;
85
86                 case 'v':
87                         if (!isdigit(optarg[0])) {
88                                 struct passwd *pw = getpwnam(optarg);
89                                 if (pw == NULL) {
90                                         fprintf(stderr, "parameter '%s' bad\n",
91                                                 optarg);
92                                         Usage_and_abort(name);
93                                 }
94                                 euid = pw->pw_uid;
95                         } else {
96                                 euid = (uid_t)atoi(optarg);
97                         }
98                         euid_is_set = 1;
99                         break;
100
101                 case 'j':
102                         if (!isdigit(optarg[0])) {
103                                 struct group *gr = getgrnam(optarg);
104                                 if (gr == NULL) {
105                                         fprintf(stderr, "getgrname %s failed\n",
106                                                 optarg);
107                                         Usage_and_abort(name);
108                                 }
109                                 egid = gr->gr_gid;
110                         } else {
111                                 egid = (gid_t)atoi(optarg);
112                         }
113                         egid_is_set = 1;
114                         break;
115
116                 case 'G':
117                         num_supp = 0;
118                         if (optarg == NULL || !isdigit(optarg[0]))
119                                 break;
120                         while ((grp = strsep(&optarg, ",")) != NULL) {
121                                 printf("adding supp group %d\n", atoi(grp));
122                                 supp_groups[num_supp++] = atoi(grp);
123                                 if (num_supp >= NGROUPS_MAX)
124                                         break;
125                         }
126                         break;
127
128                 default:
129                 case 'h':
130                         Usage_and_abort(name);
131                         break;
132                 }
133         }
134
135         if (!uid_is_set) {
136                 fprintf(stderr, "Must specify uid to run.\n");
137                 Usage_and_abort(name);
138         }
139
140         if (optind == argc) {
141                 fprintf(stderr, "Must specify command to run.\n");
142                 Usage_and_abort(name);
143         }
144
145         // assemble the command
146         my_argv = (char**)malloc(sizeof(char*)*(argc+1-optind));
147         if (my_argv == NULL) {
148                 fprintf(stderr, "Error in allocating memory. (%s)\n",
149                         strerror(errno));
150                 exit(-1);
151         }
152
153         for (i = optind; i < argc; i++) {
154                 my_argv[i-optind] = argv[i];
155                 //printf("%s\n",my_argv[i-optind]);
156         }
157         my_argv[i-optind] = NULL;
158
159 #if DEBUG
160         system("whoami");
161 #endif
162
163         // set GID
164         if (!egid_is_set)
165                 egid = grp_id;
166         status = setregid(grp_id, egid);
167         if (status == -1) {
168                  fprintf(stderr, "Cannot change gid to %d/%d, errno=%d (%s)\n",
169                          grp_id, egid, errno, strerror(errno) );
170                  exit(-1);
171         }
172
173         if (num_supp >= 0) {
174                 status = setgroups(num_supp, supp_groups);
175                 if (status == -1) {
176                         perror("setting supplementary groups");
177                         exit(-1);
178                 }
179         }
180
181         // set UID
182         if (!euid_is_set)
183                 euid = user_id;
184         status = setreuid(user_id, euid);
185         if(status == -1) {
186                   fprintf(stderr,"Cannot change uid to %d/%d, errno=%d (%s)\n",
187                            user_id, euid, errno, strerror(errno) );
188                   exit(-1);
189         }
190
191         fprintf(stderr, "running as uid/gid/euid/egid %d/%d/%d/%d, groups:",
192                 user_id, grp_id, euid, egid);
193         for (i = 0; i < num_supp; i++)
194                 fprintf(stderr, " %d", supp_groups[i]);
195         fprintf(stderr, "\n");
196
197         for (i = 0; i < argc - optind; i++)
198                  fprintf(stderr, " [%s]", my_argv[i]);
199
200         fprintf(stderr, "\n");
201         fflush(stderr);
202
203         // The command to be run
204         execvp(my_argv[0], my_argv);
205         fprintf(stderr, "execvp fails running %s (%d): %s\n", my_argv[0],
206                 errno, strerror(errno));
207         exit(-1);
208 }
209