mirror of
https://github.com/morgan9e/systemd
synced 2026-04-14 00:14:32 +09:00
run0: introduce --via-shell for invoking target user's shell, and -i shortcut
-i/--login has exact sudo semantics. But we only document the short option and advertise expressly specifying --via-shell --chdir='~' otherwise.
This commit is contained in:
27
man/run0.xml
27
man/run0.xml
@@ -167,6 +167,24 @@
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><option>--via-shell</option></term>
|
||||
|
||||
<listitem><para>Invokes the target user's login shell and runs the specified command (if any) via it.</para>
|
||||
|
||||
<xi:include href="version-info.xml" xpointer="v258"/>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><option>-i</option></term>
|
||||
|
||||
<listitem><para>Shortcut for <option>--via-shell --chdir='~'</option>.</para>
|
||||
|
||||
<xi:include href="version-info.xml" xpointer="v258"/>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><option>--setenv=<replaceable>NAME</replaceable>[=<replaceable>VALUE</replaceable>]</option></term>
|
||||
|
||||
@@ -290,9 +308,12 @@
|
||||
|
||||
<para>All command line arguments after the first non-option argument become part of the command line of
|
||||
the launched process. If no command line is specified an interactive shell is invoked. The shell to
|
||||
invoke may be controlled via <option>--setenv=SHELL=…</option> and currently defaults to the
|
||||
<emphasis>originating user's</emphasis> shell (i.e. not the target user's!) if operating locally, or
|
||||
<filename>/bin/sh</filename> when operating with <option>--machine=</option>.</para>
|
||||
invoke may be controlled through <option>--via-shell</option> - when specified the target user's shell
|
||||
is used - or <option>--setenv=SHELL=…</option>. By default, the <emphasis>originating user's</emphasis> shell
|
||||
is executed if operating locally, or <filename>/bin/sh</filename> when operating with <option>--machine=</option>.</para>
|
||||
|
||||
<para>Note that unlike <command>sudo</command>, <command>run0</command> always spawns shells with login shell
|
||||
semantics, regardless of <option>-i</option>.</para>
|
||||
</refsect1>
|
||||
|
||||
<refsect1>
|
||||
|
||||
@@ -104,6 +104,7 @@ static sd_json_format_flags_t arg_json_format_flags = SD_JSON_FORMAT_OFF;
|
||||
static char *arg_shell_prompt_prefix = NULL;
|
||||
static int arg_lightweight = -1;
|
||||
static char *arg_area = NULL;
|
||||
static bool arg_via_shell = false;
|
||||
|
||||
STATIC_DESTRUCTOR_REGISTER(arg_description, freep);
|
||||
STATIC_DESTRUCTOR_REGISTER(arg_environment, strv_freep);
|
||||
@@ -215,6 +216,8 @@ static int help_sudo_mode(void) {
|
||||
" -g --group=GROUP Run as system group\n"
|
||||
" --nice=NICE Nice level\n"
|
||||
" -D --chdir=PATH Set working directory\n"
|
||||
" --via-shell Invoke command via target user's login shell\n"
|
||||
" -i Shortcut for --via-shell --chdir='~'\n"
|
||||
" --setenv=NAME[=VALUE] Set environment variable\n"
|
||||
" --background=COLOR Set ANSI color for background\n"
|
||||
" --pty Request allocation of a pseudo TTY for stdio\n"
|
||||
@@ -257,7 +260,7 @@ static int add_timer_property(const char *name, const char *val) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static char **make_login_shell_cmdline(const char *shell) {
|
||||
static char** make_login_shell_cmdline(const char *shell) {
|
||||
_cleanup_free_ char *argv0 = NULL;
|
||||
|
||||
assert(shell);
|
||||
@@ -826,6 +829,7 @@ static int parse_argv_sudo_mode(int argc, char *argv[]) {
|
||||
ARG_PIPE,
|
||||
ARG_SHELL_PROMPT_PREFIX,
|
||||
ARG_LIGHTWEIGHT,
|
||||
ARG_VIA_SHELL,
|
||||
};
|
||||
|
||||
/* If invoked as "run0" binary, let's expose a more sudo-like interface. We add various extensions
|
||||
@@ -845,6 +849,8 @@ static int parse_argv_sudo_mode(int argc, char *argv[]) {
|
||||
{ "group", required_argument, NULL, 'g' },
|
||||
{ "nice", required_argument, NULL, ARG_NICE },
|
||||
{ "chdir", required_argument, NULL, 'D' },
|
||||
{ "via-shell", no_argument, NULL, ARG_VIA_SHELL },
|
||||
{ "login", no_argument, NULL, 'i' }, /* compat with sudo, --via-shell + --chdir='~' */
|
||||
{ "setenv", required_argument, NULL, ARG_SETENV },
|
||||
{ "background", required_argument, NULL, ARG_BACKGROUND },
|
||||
{ "pty", no_argument, NULL, ARG_PTY },
|
||||
@@ -864,7 +870,7 @@ static int parse_argv_sudo_mode(int argc, char *argv[]) {
|
||||
/* Resetting to 0 forces the invocation of an internal initialization routine of getopt_long()
|
||||
* that checks for GNU extensions in optstring ('-' or '+' at the beginning). */
|
||||
optind = 0;
|
||||
while ((c = getopt_long(argc, argv, "+hVu:g:D:a:", options, NULL)) >= 0)
|
||||
while ((c = getopt_long(argc, argv, "+hVu:g:D:a:i", options, NULL)) >= 0)
|
||||
|
||||
switch (c) {
|
||||
|
||||
@@ -981,6 +987,16 @@ static int parse_argv_sudo_mode(int argc, char *argv[]) {
|
||||
|
||||
break;
|
||||
|
||||
case 'i':
|
||||
r = free_and_strdup_warn(&arg_working_directory, "~");
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
_fallthrough_;
|
||||
case ARG_VIA_SHELL:
|
||||
arg_via_shell = true;
|
||||
break;
|
||||
|
||||
case '?':
|
||||
return -EINVAL;
|
||||
|
||||
@@ -1029,9 +1045,11 @@ static int parse_argv_sudo_mode(int argc, char *argv[]) {
|
||||
arg_send_sighup = true;
|
||||
|
||||
_cleanup_strv_free_ char **l = NULL;
|
||||
if (argc > optind)
|
||||
if (argc > optind) {
|
||||
l = strv_copy(argv + optind);
|
||||
else {
|
||||
if (!l)
|
||||
return log_oom();
|
||||
} else if (!arg_via_shell) {
|
||||
const char *e;
|
||||
|
||||
e = strv_env_get(arg_environment, "SHELL");
|
||||
@@ -1056,9 +1074,19 @@ static int parse_argv_sudo_mode(int argc, char *argv[]) {
|
||||
}
|
||||
|
||||
l = make_login_shell_cmdline(arg_exec_path);
|
||||
if (!l)
|
||||
return log_oom();
|
||||
}
|
||||
|
||||
if (arg_via_shell) {
|
||||
arg_exec_path = strdup(_PATH_BSHELL);
|
||||
if (!arg_exec_path)
|
||||
return log_oom();
|
||||
|
||||
r = strv_prepend(&l, "-sh");
|
||||
if (r < 0)
|
||||
return log_oom();
|
||||
}
|
||||
if (!l)
|
||||
return log_oom();
|
||||
|
||||
strv_free_and_replace(arg_cmdline, l);
|
||||
|
||||
@@ -1271,10 +1299,8 @@ static int transient_kill_set_properties(sd_bus_message *m) {
|
||||
static int transient_service_set_properties(sd_bus_message *m, const char *pty_path, int pty_fd) {
|
||||
int r, send_term; /* tri-state */
|
||||
|
||||
/* We disable environment expansion on the server side via ExecStartEx=:.
|
||||
* ExecStartEx was added relatively recently (v243), and some bugs were fixed only later.
|
||||
* So use that feature only if required. It will fail with older systemds. */
|
||||
bool use_ex_prop = !arg_expand_environment;
|
||||
/* Use ExecStartEx if new exec flags are required. */
|
||||
bool use_ex_prop = !arg_expand_environment || arg_via_shell;
|
||||
|
||||
assert(m);
|
||||
assert((!!pty_path) == (pty_fd >= 0));
|
||||
@@ -1461,7 +1487,9 @@ static int transient_service_set_properties(sd_bus_message *m, const char *pty_p
|
||||
_cleanup_strv_free_ char **opts = NULL;
|
||||
|
||||
r = exec_command_flags_to_strv(
|
||||
(arg_expand_environment ? 0 : EXEC_COMMAND_NO_ENV_EXPAND)|(arg_ignore_failure ? EXEC_COMMAND_IGNORE_FAILURE : 0),
|
||||
(arg_expand_environment ? 0 : EXEC_COMMAND_NO_ENV_EXPAND)|
|
||||
(arg_ignore_failure ? EXEC_COMMAND_IGNORE_FAILURE : 0)|
|
||||
(arg_via_shell ? EXEC_COMMAND_VIA_SHELL : 0),
|
||||
&opts);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to format execute flags: %m");
|
||||
@@ -2821,7 +2849,12 @@ static int run(int argc, char* argv[]) {
|
||||
|
||||
if (strv_isempty(arg_cmdline))
|
||||
t = strdup(arg_unit);
|
||||
else if (startswith(arg_cmdline[0], "-")) {
|
||||
else if (arg_via_shell) {
|
||||
if (arg_cmdline[1])
|
||||
t = quote_command_line(arg_cmdline + 1, SHELL_ESCAPE_EMPTY);
|
||||
else
|
||||
t = strjoin("LOGIN", arg_exec_user ? ": " : NULL, arg_exec_user);
|
||||
} else if (startswith(arg_cmdline[0], "-")) {
|
||||
/* Drop the login shell marker from the command line when generating the description,
|
||||
* in order to minimize user confusion. */
|
||||
_cleanup_strv_free_ char **l = strv_copy(arg_cmdline);
|
||||
|
||||
Reference in New Issue
Block a user