2 Simple wrapper to run a command with different uid/gid.
4 Based on the implementation in freedt:
5 Copyright (C) 2003 Adam Sampson <azz@gnu.org>
7 2010-05-07 – Jacek Konieczny <jajcus> updated for standalone compilation
8 and included in PLD rc-scripts
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.
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.
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
26 #include <sys/param.h>
28 #include <sys/types.h>
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";
41 void die(const char *msg) {
42 fprintf(stderr, "%s: %s\n", progname, msg);
45 void die2(const char *msg1, const char *msg2) {
46 fprintf(stderr, "%s: %s: %s\n", progname, msg1, msg2);
50 fprintf(stderr, "%s $Rev$ (TLD Linux rc-scripts)\n", progname);
56 void help(int retval) {
58 fprintf(stderr, "\n%s"
59 "-V Show version information\n"
60 "-h Show usage information\n", proghelp);
64 int main(int argc, char **argv) {
69 int c = getopt(argc, argv, "+V?hs");
87 if ((argc - optind) < 2)
90 p = getpwnam(argv[optind]);
92 die("no such account");
93 if (setgid(p->pw_gid) < 0)
94 die("unable to setgid");
97 gid_t groups[NGROUPS_MAX];
103 struct group *g = getgrent();
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;
116 if (setgroups(n, groups) < 0)
117 die("unable to setgroups");
119 if (setgroups(1, &p->pw_gid) < 0)
120 die("unable to setgroups");
123 if (setuid(p->pw_uid) < 0)
124 die("unable to setuid");
127 execvp(argv[optind], &argv[optind]);
128 die2(argv[optind], "unable to exec");
130 return 0; /* NOTREACHED */