log-writes: Add support to output human readable flags
[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         char **cmd;
52         gid_t sgids[SUP_MAX];
53         int sup_cnt = 0;
54         char *p;
55
56         prog = basename(argv[0]);
57         for (p = prog; *p; p++) {
58                 if (*p == '/') {
59                         prog = p + 1;
60                 }
61         }
62
63
64         while ((c = getopt(argc, argv, "u:g:s:")) != -1) {
65                 switch (c) {
66                 case 'u':
67                         uid = atoi(optarg);
68                         break;
69                 case 'g':
70                         gid = atoi(optarg);
71                         break;
72                 case 's':
73                         if (sup_cnt+1 > SUP_MAX) {
74                             fprintf(stderr, "%s: too many sup groups\n", prog);
75                             exit(1);
76                         }
77                         sgids[sup_cnt++] = atoi(optarg);
78                         break;
79                 case '?':
80                         usage();
81                         exit(1);
82                 }
83         }
84
85         /* build up the cmd */
86         if (optind == argc) {
87             usage();
88             exit(1);
89         }
90         else {
91             char **p;
92             p = cmd = (char **)malloc(sizeof(char *) * (argc - optind + 1));
93             for ( ; optind < argc; optind++, p++) {
94                 *p = strdup(argv[optind]);
95             }
96             *p = NULL;
97         } 
98
99         if (gid != -1) {
100             if (setgid(gid) == -1) {
101                 fprintf(stderr, "%s: setgid(%d) failed: %s\n",
102                         prog, (int)gid, strerror(errno));
103                 exit(1);
104             }
105         }
106
107         if (gid != -1 || sup_cnt != 0) {
108             if (setgroups(sup_cnt, sgids) == -1) {
109                 fprintf(stderr, "%s: setgroups() failed: %s\n",
110                         prog, strerror(errno));
111                 exit(1);
112             }
113         }
114
115         if (uid != -1) {
116             if (setuid(uid) == -1) {
117                 fprintf(stderr, "%s: setuid(%d) failed: %s\n",
118                         prog, (int)uid, strerror(errno));
119                 exit(1);
120             }
121         }
122
123         execvp(cmd[0], cmd);
124         fprintf(stderr, "%s: %s\n", cmd[0], strerror(errno));
125         exit(1);
126 }