run: allow non-absolute paths as command
This commit is contained in:
parent
116cc02874
commit
c9d954b27e
2
TODO
2
TODO
|
@ -715,6 +715,8 @@ Features:
|
||||||
- document initcall_debug
|
- document initcall_debug
|
||||||
- kernel cmdline "bootchart" option for simplicity?
|
- kernel cmdline "bootchart" option for simplicity?
|
||||||
|
|
||||||
|
* systemd-run is missing completion scripts
|
||||||
|
|
||||||
External:
|
External:
|
||||||
|
|
||||||
* dbus:
|
* dbus:
|
||||||
|
|
|
@ -187,6 +187,23 @@ along with systemd; If not, see <http://www.gnu.org/licenses/>.
|
||||||
code otherwise.</para>
|
code otherwise.</para>
|
||||||
</refsect1>
|
</refsect1>
|
||||||
|
|
||||||
|
<refsect1>
|
||||||
|
<title>Example</title>
|
||||||
|
|
||||||
|
<para>The following command will log the environment variables
|
||||||
|
provided by systemd to services:</para>
|
||||||
|
|
||||||
|
<programlisting># systemd-run env
|
||||||
|
Running as unit run-19945.service.
|
||||||
|
# journalctl -u run-19945.service
|
||||||
|
Sep 08 07:37:21 bupkis systemd[1]: Starting /usr/bin/env...
|
||||||
|
Sep 08 07:37:21 bupkis systemd[1]: Started /usr/bin/env.
|
||||||
|
Sep 08 07:37:21 bupkis env[19948]: PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin
|
||||||
|
Sep 08 07:37:21 bupkis env[19948]: LANG=en_US.UTF-8
|
||||||
|
Sep 08 07:37:21 bupkis env[19948]: BOOT_IMAGE=/vmlinuz-3.11.0-0.rc5.git6.2.fc20.x86_64
|
||||||
|
</programlisting>
|
||||||
|
</refsect1>
|
||||||
|
|
||||||
<refsect1>
|
<refsect1>
|
||||||
<title>See Also</title>
|
<title>See Also</title>
|
||||||
<para>
|
<para>
|
||||||
|
|
|
@ -456,11 +456,7 @@ static int manager_setup_signals(Manager *m) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static int manager_default_environment(Manager *m) {
|
static int manager_default_environment(Manager *m) {
|
||||||
#ifdef HAVE_SPLIT_USR
|
const char *path = "PATH=" DEFAULT_PATH;
|
||||||
const char *path = "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin";
|
|
||||||
#else
|
|
||||||
const char *path = "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin";
|
|
||||||
#endif
|
|
||||||
|
|
||||||
assert(m);
|
assert(m);
|
||||||
|
|
||||||
|
|
|
@ -39,7 +39,7 @@ static bool arg_send_sighup = false;
|
||||||
|
|
||||||
static int help(void) {
|
static int help(void) {
|
||||||
|
|
||||||
printf("%s [OPTIONS...] [COMMAND LINE...]\n\n"
|
printf("%s [OPTIONS...] COMMAND [ARGS...]\n\n"
|
||||||
"Run the specified command in a transient scope or service unit.\n\n"
|
"Run the specified command in a transient scope or service unit.\n\n"
|
||||||
" -h --help Show this help\n"
|
" -h --help Show this help\n"
|
||||||
" --version Show package version\n"
|
" --version Show package version\n"
|
||||||
|
@ -324,7 +324,7 @@ static int start_transient_scope(
|
||||||
int main(int argc, char* argv[]) {
|
int main(int argc, char* argv[]) {
|
||||||
sd_bus_error error = SD_BUS_ERROR_NULL;
|
sd_bus_error error = SD_BUS_ERROR_NULL;
|
||||||
_cleanup_bus_unref_ sd_bus *bus = NULL;
|
_cleanup_bus_unref_ sd_bus *bus = NULL;
|
||||||
_cleanup_free_ char *description = NULL;
|
_cleanup_free_ char *description = NULL, *command = NULL;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
log_parse_environment();
|
log_parse_environment();
|
||||||
|
@ -334,6 +334,13 @@ int main(int argc, char* argv[]) {
|
||||||
if (r <= 0)
|
if (r <= 0)
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
|
r = find_binary(argv[optind], &command);
|
||||||
|
if (r < 0) {
|
||||||
|
log_error("Failed to find executable %s: %s", argv[optind], strerror(-r));
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
argv[optind] = command;
|
||||||
|
|
||||||
if (!arg_description) {
|
if (!arg_description) {
|
||||||
description = strv_join(argv + optind, " ");
|
description = strv_join(argv + optind, " ");
|
||||||
if (!description) {
|
if (!description) {
|
||||||
|
|
|
@ -425,3 +425,51 @@ int path_is_os_tree(const char *path) {
|
||||||
|
|
||||||
return r < 0 ? 0 : 1;
|
return r < 0 ? 0 : 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int find_binary(const char *name, char **filename) {
|
||||||
|
assert(name);
|
||||||
|
if (strchr(name, '/')) {
|
||||||
|
char *p;
|
||||||
|
|
||||||
|
if (path_is_absolute(name))
|
||||||
|
p = strdup(name);
|
||||||
|
else
|
||||||
|
p = path_make_absolute_cwd(name);
|
||||||
|
if (!p)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
*filename = p;
|
||||||
|
return 0;
|
||||||
|
} else {
|
||||||
|
const char *path;
|
||||||
|
char *state, *w;
|
||||||
|
size_t l;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Plain getenv, not secure_getenv, because we want
|
||||||
|
* to actually allow the user to pick the binary.
|
||||||
|
*/
|
||||||
|
path = getenv("PATH");
|
||||||
|
if (!path)
|
||||||
|
path = DEFAULT_PATH;
|
||||||
|
|
||||||
|
FOREACH_WORD_SEPARATOR(w, l, path, ":", state) {
|
||||||
|
char *p;
|
||||||
|
|
||||||
|
if (asprintf(&p, "%.*s/%s", l, w, name) < 0)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
if (access(p, X_OK) < 0) {
|
||||||
|
free(p);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
path_kill_slashes(p);
|
||||||
|
*filename = p;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return -ENOENT;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -25,6 +25,12 @@
|
||||||
|
|
||||||
#include "macro.h"
|
#include "macro.h"
|
||||||
|
|
||||||
|
#ifdef HAVE_SPLIT_USR
|
||||||
|
# define DEFAULT_PATH "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
|
||||||
|
#else
|
||||||
|
# define DEFAULT_PATH "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin"
|
||||||
|
#endif
|
||||||
|
|
||||||
bool is_path(const char *p) _pure_;
|
bool is_path(const char *p) _pure_;
|
||||||
char** path_split_and_make_absolute(const char *p);
|
char** path_split_and_make_absolute(const char *p);
|
||||||
char* path_get_file_name(const char *p) _pure_;
|
char* path_get_file_name(const char *p) _pure_;
|
||||||
|
@ -43,3 +49,5 @@ char** path_strv_canonicalize_uniq(char **l);
|
||||||
int path_is_mount_point(const char *path, bool allow_symlink);
|
int path_is_mount_point(const char *path, bool allow_symlink);
|
||||||
int path_is_read_only_fs(const char *path);
|
int path_is_read_only_fs(const char *path);
|
||||||
int path_is_os_tree(const char *path);
|
int path_is_os_tree(const char *path);
|
||||||
|
|
||||||
|
int find_binary(const char *name, char **filename);
|
||||||
|
|
|
@ -83,7 +83,31 @@ static void test_path(void) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void test_find_binary(void) {
|
||||||
|
char *p;
|
||||||
|
|
||||||
|
assert(find_binary("/bin/sh", &p) == 0);
|
||||||
|
puts(p);
|
||||||
|
assert(streq(p, "/bin/sh"));
|
||||||
|
free(p);
|
||||||
|
|
||||||
|
assert(find_binary("./test-path-util", &p) == 0);
|
||||||
|
puts(p);
|
||||||
|
assert(endswith(p, "/test-path-util"));
|
||||||
|
assert(path_is_absolute(p));
|
||||||
|
free(p);
|
||||||
|
|
||||||
|
assert(find_binary("sh", &p) == 0);
|
||||||
|
puts(p);
|
||||||
|
assert(endswith(p, "/sh"));
|
||||||
|
assert(path_is_absolute(p));
|
||||||
|
free(p);
|
||||||
|
|
||||||
|
assert(find_binary("xxxx-xxxx", &p) == -ENOENT);
|
||||||
|
}
|
||||||
|
|
||||||
int main(void) {
|
int main(void) {
|
||||||
test_path();
|
test_path();
|
||||||
|
test_find_binary();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue