]> TLD Linux GIT Repositories - rc-scripts.git/blob - src/setuidgid.c
- merged TLDize patch
[rc-scripts.git] / src / setuidgid.c
1 /*
2     Simple wrapper to run a command with different uid/gid.
3
4     Based on the implementation in freedt:
5        Copyright (C) 2003  Adam Sampson <azz@gnu.org>
6
7     2010-05-07 – Jacek Konieczny <jajcus> updated for standalone compilation
8     and included in PLD rc-scripts
9
10     This program is free software; you can redistribute it and/or modify
11     it under the terms of the GNU General Public License as published by
12     the Free Software Foundation; either version 2 of the License, or
13     (at your option) any later version.
14
15     This program is distributed in the hope that it will be useful,
16     but WITHOUT ANY WARRANTY; without even the implied warranty of
17     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18     GNU General Public License for more details.
19
20     You should have received a copy of the GNU General Public License
21     along with this program; if not, write to the Free Software
22     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
23 */
24
25 #include <string.h>
26 #include <sys/param.h>
27 #include <pwd.h>
28 #include <sys/types.h>
29 #include <unistd.h>
30 #include <stdlib.h>
31 #include <stdio.h>
32 #include <grp.h>
33 #include <limits.h>
34
35 const char *progname = "setuidgid";
36 const char *proghelp =
37         "Usage: setuidgid [OPTIONS] account command ...\n"
38         "Run a command under the uid and gid of an account.\n\n"
39         "-s        Also set supplementary groups\n";
40
41 void die(const char *msg) {
42         fprintf(stderr, "%s: %s\n", progname, msg);
43         exit(1);
44 }
45 void die2(const char *msg1, const char *msg2) {
46         fprintf(stderr, "%s: %s: %s\n", progname, msg1, msg2);
47         exit(1);
48 }
49 void show_version() {
50         fprintf(stderr, "%s $Rev$ (TLD Linux rc-scripts)\n", progname);
51 }
52 void version() {
53         show_version();
54         exit(0);
55 }
56 void help(int retval) {
57         show_version();
58         fprintf(stderr, "\n%s"
59                 "-V        Show version information\n"
60                 "-h        Show usage information\n", proghelp);
61         exit(retval);
62 }
63
64 int main(int argc, char **argv) {
65         struct passwd *p;
66         int use_supp = 0;
67
68         while (1) {
69                 int c = getopt(argc, argv, "+V?hs");
70                 if (c == -1)
71                         break;
72
73                 switch (c) {
74                 case 's':
75                         use_supp = 1;
76                         break;
77                 case 'V':
78                         version();
79                 case 'h':
80                 case '?':
81                         help(0);
82                 default:
83                         help(1);
84                 }
85         }
86
87         if ((argc - optind) < 2)
88                 help(1);
89
90         p = getpwnam(argv[optind]);
91         if (!p)
92                 die("no such account");
93         if (setgid(p->pw_gid) < 0)
94                 die("unable to setgid");
95
96         if (use_supp) {
97                 gid_t groups[NGROUPS_MAX];
98                 size_t n = 0;
99
100                 setgrent();
101                 while (1) {
102                         char **p;
103                         struct group *g = getgrent();
104                         if (g == NULL)
105                                 break;
106
107                         for (p = g->gr_mem; *p != NULL; p++) {
108                                 if (strcmp(*p, argv[optind]) == 0) {
109                                         if (n >= NGROUPS_MAX)
110                                                 die("too many groups");
111                                         groups[n++] = g->gr_gid;
112                                 }
113                         }
114                 }
115
116                 if (setgroups(n, groups) < 0)
117                         die("unable to setgroups");
118         } else {
119                 if (setgroups(1, &p->pw_gid) < 0)
120                         die("unable to setgroups");
121         }
122
123         if (setuid(p->pw_uid) < 0)
124                 die("unable to setuid");
125
126         ++optind;
127         execvp(argv[optind], &argv[optind]);
128         die2(argv[optind], "unable to exec");
129
130         return 0; /* NOTREACHED */
131 }
132