Whamcloud - gitweb
land b1_5 onto 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] [-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 "  -G[gid0,gid1,...]    set supplementary groups\n";
26
27 void Usage_and_abort(const char *name)
28 {
29         fprintf(stderr, usage, name);
30         exit(-1);
31 }
32
33 int main(int argc, char **argv)
34 {
35         char **my_argv, *name = argv[0], *grp;
36         int status, c, i;
37         int gid_is_set = 0, uid_is_set = 0, num_supp = -1;
38         uid_t user_id = 0;
39         gid_t grp_id = 0, supp_groups[NGROUPS_MAX] = { 0 };
40
41         if (argc == 1) {
42                 fprintf(stderr, "No parameter count\n");
43                 Usage_and_abort(name);
44         }
45
46         // get UID and GID
47         while ((c = getopt(argc, argv, "+u:g:hG::")) != -1) {
48                 switch (c) {
49                 case 'u':
50                         if (!isdigit(optarg[0])) {
51                                 struct passwd *pw = getpwnam(optarg);
52                                 if (pw == NULL) {
53                                         fprintf(stderr, "parameter '%s' bad\n",
54                                                 optarg);
55                                         Usage_and_abort(name);
56                                 }
57                                 user_id = pw->pw_uid;
58                         } else {
59                                 user_id = (uid_t)atoi(optarg);
60                         }
61                         uid_is_set = 1;
62                         if (!gid_is_set)
63                                 grp_id = user_id;
64                         break;
65
66                 case 'g':
67                         if (!isdigit(optarg[0])) {
68                                 struct group *gr = getgrnam(optarg);
69                                 if (gr == NULL) {
70                                         fprintf(stderr, "getgrname %s failed\n",
71                                                 optarg);
72                                         Usage_and_abort(name);
73                                 }
74                                 grp_id = gr->gr_gid;
75                         } else {
76                                 grp_id = (gid_t)atoi(optarg);
77                         }
78                         gid_is_set = 1;
79                         break;
80
81                 case 'G':
82                         num_supp = 0;
83                         if (optarg == NULL || !isdigit(optarg[0]))
84                                 break;
85                         while ((grp = strsep(&optarg, ",")) != NULL) {
86                                 printf("adding supp group %d\n", atoi(grp));
87                                 supp_groups[num_supp++] = atoi(grp);
88                                 if (num_supp >= NGROUPS_MAX)
89                                         break;
90                         }
91                         break;
92
93                 default:
94                 case 'h':
95                         Usage_and_abort(name);
96                         break;
97                 }
98         }
99
100         if (!uid_is_set) {
101                 fprintf(stderr, "Must specify uid to run.\n");
102                 Usage_and_abort(name);
103         }
104
105         if (optind == argc) {
106                 fprintf(stderr, "Must specify command to run.\n");
107                 Usage_and_abort(name);
108         }
109
110         // assemble the command
111         my_argv = (char**)malloc(sizeof(char*)*(argc+1-optind));
112         if (my_argv == NULL) {
113                 fprintf(stderr, "Error in allocating memory. (%s)\n",
114                         strerror(errno));
115                 exit(-1);
116         }
117
118         for (i = optind; i < argc; i++) {
119                 my_argv[i-optind] = argv[i];
120                 //printf("%s\n",my_argv[i-optind]);
121         }
122         my_argv[i-optind] = NULL;
123
124 #if DEBUG
125         system("whoami");
126 #endif
127
128         // set GID
129         status = setregid(grp_id, grp_id);
130         if (status == -1) {
131                  fprintf(stderr, "Cannot change grp_ID to %d, errno=%d (%s)\n",
132                          grp_id, errno, strerror(errno) );
133                  exit(-1);
134         }
135
136         if (num_supp >= 0) {
137                 status = setgroups(num_supp, supp_groups);
138                 if (status == -1) {
139                         perror("setting supplementary groups");
140                         exit(-1);
141                 }
142         }
143
144         // set UID
145         status = setreuid(user_id, user_id );
146         if(status == -1) {
147                   fprintf(stderr,"Cannot change user_ID to %d, errno=%d (%s)\n",
148                            user_id, errno, strerror(errno) );
149                   exit(-1);
150         }
151
152         fprintf(stderr, "running as UID %d, GID %d", user_id, grp_id);
153         for (i = 0; i < num_supp; i++)
154                 fprintf(stderr, ":%d", supp_groups[i]);
155         fprintf(stderr, "\n");
156
157         for (i = 0; i < argc - optind; i++)
158                  fprintf(stderr, " [%s]", my_argv[i]);
159
160         fprintf(stderr, "\n");
161         fflush(stderr);
162
163         // The command to be run
164         execvp(my_argv[0], my_argv);
165         fprintf(stderr, "execvp fails running %s (%d): %s\n", my_argv[0],
166                 errno, strerror(errno));
167         exit(-1);
168 }
169