source: trunk/coreutils/src/setuidgid.c@ 2603

Last change on this file since 2603 was 2554, checked in by bird, 20 years ago

coretuils-5.94

File size: 3.6 KB
Line 
1/* setuidgid - run a command with the UID and GID of a specified user
2 Copyright (C) 2003, 2004, 2005 Free Software Foundation, Inc.
3
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2, or (at your option)
7 any later version.
8
9 This program is distributed in the hope that it will 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 to the Free Software Foundation,
16 Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
17
18/* Written by Jim Meyering */
19
20#include <config.h>
21#include <getopt.h>
22#include <stdio.h>
23#include <sys/types.h>
24#include <pwd.h>
25#include <grp.h>
26
27#include "system.h"
28
29#include "error.h"
30#include "long-options.h"
31#include "quote.h"
32
33#define PROGRAM_NAME "setuidgid"
34
35/* I wrote this program from scratch, based on the description of
36 D.J. Bernstein's program: http://cr.yp.to/daemontools/setuidgid.html. */
37#define AUTHORS "Jim Meyering"
38
39#define SETUIDGID_FAILURE 111
40
41char *program_name;
42
43void
44usage (int status)
45{
46 if (status != EXIT_SUCCESS)
47 fprintf (stderr, _("Try `%s --help' for more information.\n"),
48 program_name);
49 else
50 {
51 printf (_("\
52Usage: %s USERNAME COMMAND [ARGUMENT]...\n\
53 or: %s OPTION\n\
54"),
55 program_name, program_name);
56
57 fputs (_("\
58Drop any supplemental groups, assume the user-ID and group-ID of\n\
59the specified USERNAME, and run COMMAND with any specified ARGUMENTs.\n\
60Exit with status 111 if unable to assume the required user and group ID.\n\
61Otherwise, exit with the exit status of COMMAND.\n\
62This program is useful only when run by root (user ID zero).\n\
63\n\
64"), stdout);
65 fputs (HELP_OPTION_DESCRIPTION, stdout);
66 fputs (VERSION_OPTION_DESCRIPTION, stdout);
67 printf (_("\nReport bugs to <%s>.\n"), PACKAGE_BUGREPORT);
68 }
69 exit (status);
70}
71
72int
73main (int argc, char **argv)
74{
75 char const *user_id;
76 struct passwd *pwd;
77
78 initialize_main (&argc, &argv);
79 program_name = argv[0];
80 setlocale (LC_ALL, "");
81 bindtextdomain (PACKAGE, LOCALEDIR);
82 textdomain (PACKAGE);
83
84 initialize_exit_failure (SETUIDGID_FAILURE);
85 atexit (close_stdout);
86
87 parse_long_options (argc, argv, PROGRAM_NAME, GNU_PACKAGE, VERSION,
88 usage, AUTHORS, (char const *) NULL);
89 if (getopt_long (argc, argv, "+", NULL, NULL) != -1)
90 usage (SETUIDGID_FAILURE);
91
92 if (argc <= optind + 1)
93 {
94 if (argc < optind + 1)
95 error (0, 0, _("missing operand"));
96 else
97 error (0, 0, _("missing operand after %s"), quote (argv[optind]));
98 usage (SETUIDGID_FAILURE);
99 }
100
101 user_id = argv[optind];
102 pwd = getpwnam (user_id);
103 if (pwd == NULL)
104 error (SETUIDGID_FAILURE, errno,
105 _("unknown user-ID: %s"), quote (user_id));
106
107 if (setgroups (1, &pwd->pw_gid))
108 error (SETUIDGID_FAILURE, errno, _("cannot set supplemental group"));
109
110 if (setgid (pwd->pw_gid))
111 error (SETUIDGID_FAILURE, errno,
112 _("cannot set group-ID to %lu"), (unsigned long int) pwd->pw_gid);
113
114 if (setuid (pwd->pw_uid))
115 error (SETUIDGID_FAILURE, errno,
116 _("cannot set user-ID to %lu"), (unsigned long int) pwd->pw_uid);
117
118 {
119 char **cmd = argv + optind + 1;
120 int exit_status;
121 execvp (*cmd, cmd);
122 exit_status = (errno == ENOENT ? EXIT_ENOENT : EXIT_CANNOT_INVOKE);
123
124 error (0, errno, _("cannot run command %s"), quote (*cmd));
125 exit (exit_status);
126 }
127}
Note: See