fsstress: translate flags in fiemap_f
[xfstests-dev.git] / src / runas.c
1 /*
2  * Copyright (c) 2000-2001 Silicon Graphics, Inc.
3  * All Rights Reserved.
4  *
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU General Public License as
7  * published by the Free Software Foundation.
8  *
9  * This program is distributed in the hope that it would be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write the Free Software Foundation,
16  * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
17  */
18
19 /*
20  * Run a command with a particular 
21  *    - effective user id
22  *    - effective group id
23  *    - supplementary group list
24  */
25  
26 #include "global.h"
27 #include <grp.h>
28
29
30
31 char *prog;
32
33 void usage(void)
34 {
35     fprintf(stderr, "usage: %s [-u uid] [-g gid] [-s gid] cmd\n"
36            "flags:\n"
37            "    -u - effective user-id\n"
38            "    -g - effective group-id\n"
39            "    -s - supplementary group-id\n", prog);
40            
41 }
42
43 #define SUP_MAX 20
44
45 int
46 main(int argc, char **argv)
47 {
48         int c;
49         uid_t uid = -1;
50         gid_t gid = -1;
51         int pid;
52         char **cmd;
53         gid_t sgids[SUP_MAX];
54         int sup_cnt = 0;
55         int status;
56         char *p;
57
58         prog = basename(argv[0]);
59         for (p = prog; *p; p++) {
60                 if (*p == '/') {
61                         prog = p + 1;
62                 }
63         }
64
65
66         while ((c = getopt(argc, argv, "u:g:s:")) != -1) {
67                 switch (c) {
68                 case 'u':
69                         uid = atoi(optarg);
70                         break;
71                 case 'g':
72                         gid = atoi(optarg);
73                         break;
74                 case 's':
75                         if (sup_cnt+1 > SUP_MAX) {
76                             fprintf(stderr, "%s: too many sup groups\n", prog);
77                             exit(1);
78                         }
79                         sgids[sup_cnt++] = atoi(optarg);
80                         break;
81                 case '?':
82                         usage();
83                         exit(1);
84                 }
85         }
86
87         /* build up the cmd */
88         if (optind == argc) {
89             usage();
90             exit(1);
91         }
92         else {
93             char **p;
94             p = cmd = (char **)malloc(sizeof(char *) * (argc - optind + 1));
95             for ( ; optind < argc; optind++, p++) {
96                 *p = strdup(argv[optind]);
97             }
98             *p = NULL;
99         } 
100
101         if (gid != -1) {
102             if (setegid(gid) == -1) {
103                 fprintf(stderr, "%s: setegid(%d) failed: %s\n",
104                         prog, (int)gid, strerror(errno));
105                 exit(1);
106             }   
107         }
108
109         if (sup_cnt > 0) {
110             if (setgroups(sup_cnt, sgids) == -1) {
111                 fprintf(stderr, "%s: setgroups() failed: %s\n",
112                         prog, strerror(errno));
113                 exit(1);
114             }   
115         }
116
117         if (uid != -1) {
118             if (seteuid(uid) == -1) {
119                 fprintf(stderr, "%s: seteuid(%d) failed: %s\n",
120                         prog, (int)uid, strerror(errno));
121                 exit(1);
122             }   
123         }
124
125         pid = fork();
126         if (pid == -1) {
127             fprintf(stderr, "%s: fork failed: %s\n",
128                     prog, strerror(errno));
129             exit(1);
130         }
131         if (pid == 0) {
132             execv(cmd[0], cmd);
133             fprintf(stderr, "%s: %s\n", cmd[0], strerror(errno));
134             exit(errno);
135         }
136
137         wait(&status);
138         if (WIFSIGNALED(status)) {
139             fprintf(stderr, "%s: command terminated with signal %d\n", 
140                  prog, WTERMSIG(status));
141             exit(1);
142         }
143         else if (WIFEXITED(status)) {
144             exit(WEXITSTATUS(status));
145         }
146         else {
147             fprintf(stderr, "%s: command bizarre wait status 0x%x\n", 
148                prog, status);
149             exit(1);
150         }
151
152         exit(0);
153         /* NOTREACHED */
154 }