Whamcloud - gitweb
correctly send lsm on open replay
[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  2008 Sun Microsystems, Inc. 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] [-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 "  -G[gid0,gid1,...]    set supplementary groups\n";
59
60 void Usage_and_abort(const char *name)
61 {
62         fprintf(stderr, usage, name);
63         exit(-1);
64 }
65
66 int main(int argc, char **argv)
67 {
68         char **my_argv, *name = argv[0], *grp;
69         int status, c, i;
70         int gid_is_set = 0, uid_is_set = 0, num_supp = -1;
71         uid_t user_id = 0;
72         gid_t grp_id = 0, supp_groups[NGROUPS_MAX] = { 0 };
73
74         if (argc == 1) {
75                 fprintf(stderr, "No parameter count\n");
76                 Usage_and_abort(name);
77         }
78
79         // get UID and GID
80         while ((c = getopt(argc, argv, "+u:g:hG::")) != -1) {
81                 switch (c) {
82                 case 'u':
83                         if (!isdigit(optarg[0])) {
84                                 struct passwd *pw = getpwnam(optarg);
85                                 if (pw == NULL) {
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                                 if (gr == NULL) {
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 'G':
115                         num_supp = 0;
116                         if (optarg == NULL || !isdigit(optarg[0]))
117                                 break;
118                         while ((grp = strsep(&optarg, ",")) != NULL) {
119                                 printf("adding supp group %d\n", atoi(grp));
120                                 supp_groups[num_supp++] = atoi(grp);
121                                 if (num_supp >= NGROUPS_MAX)
122                                         break;
123                         }
124                         break;
125
126                 default:
127                 case 'h':
128                         Usage_and_abort(name);
129                         break;
130                 }
131         }
132
133         if (!uid_is_set) {
134                 fprintf(stderr, "Must specify uid to run.\n");
135                 Usage_and_abort(name);
136         }
137
138         if (optind == argc) {
139                 fprintf(stderr, "Must specify command to run.\n");
140                 Usage_and_abort(name);
141         }
142
143         // assemble the command
144         my_argv = (char**)malloc(sizeof(char*)*(argc+1-optind));
145         if (my_argv == NULL) {
146                 fprintf(stderr, "Error in allocating memory. (%s)\n",
147                         strerror(errno));
148                 exit(-1);
149         }
150
151         for (i = optind; i < argc; i++) {
152                 my_argv[i-optind] = argv[i];
153                 //printf("%s\n",my_argv[i-optind]);
154         }
155         my_argv[i-optind] = NULL;
156
157 #if DEBUG
158         system("whoami");
159 #endif
160
161         // set GID
162         status = setregid(grp_id, grp_id);
163         if (status == -1) {
164                  fprintf(stderr, "Cannot change grp_ID to %d, errno=%d (%s)\n",
165                          grp_id, errno, strerror(errno) );
166                  exit(-1);
167         }
168
169         if (num_supp >= 0) {
170                 status = setgroups(num_supp, supp_groups);
171                 if (status == -1) {
172                         perror("setting supplementary groups");
173                         exit(-1);
174                 }
175         }
176
177         // set UID
178         status = setreuid(user_id, user_id );
179         if(status == -1) {
180                   fprintf(stderr,"Cannot change user_ID to %d, errno=%d (%s)\n",
181                            user_id, errno, strerror(errno) );
182                   exit(-1);
183         }
184
185         fprintf(stderr, "running as UID %d, GID %d", user_id, grp_id);
186         for (i = 0; i < num_supp; i++)
187                 fprintf(stderr, ":%d", supp_groups[i]);
188         fprintf(stderr, "\n");
189
190         for (i = 0; i < argc - optind; i++)
191                  fprintf(stderr, " [%s]", my_argv[i]);
192
193         fprintf(stderr, "\n");
194         fflush(stderr);
195
196         // The command to be run
197         execvp(my_argv[0], my_argv);
198         fprintf(stderr, "execvp fails running %s (%d): %s\n", my_argv[0],
199                 errno, strerror(errno));
200         exit(-1);
201 }