summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDimitri John Ledkov <xnox@ubuntu.com>2018-09-12 18:19:13 +0100
committerSven Eden <sven.eden@prydeworx.com>2018-10-29 10:18:26 +0100
commit3ddb90ae3fa7d2c93c12a7d623fd720b12a29d16 (patch)
tree102b8246489a5a0e67e6f7b4b7d65d4493e91be4
parent3d5dc0215f7acc752e0ff5904361b86e6bc78695 (diff)
exec-util: in execute_directories, support initial exec environment
(cherry picked from commit 78ec1bb436fb18df3b56212c442cc4775a136d1a)
-rw-r--r--src/basic/exec-util.c13
-rw-r--r--src/basic/exec-util.h3
-rw-r--r--src/sleep/sleep.c4
-rw-r--r--src/test/test-exec-util.c43
4 files changed, 49 insertions, 14 deletions
diff --git a/src/basic/exec-util.c b/src/basic/exec-util.c
index 7896f9369..cfb082a03 100644
--- a/src/basic/exec-util.c
+++ b/src/basic/exec-util.c
@@ -71,11 +71,12 @@ static int do_execute(
gather_stdout_callback_t const callbacks[_STDOUT_CONSUME_MAX],
void* const callback_args[_STDOUT_CONSUME_MAX],
int output_fd,
- char *argv[]) {
+ char *argv[],
+ char *envp[]) {
_cleanup_hashmap_free_free_ Hashmap *pids = NULL;
_cleanup_strv_free_ char **paths = NULL;
- char **path;
+ char **path, **e;
int r;
/* We fork this all off from a child process so that we can somewhat cleanly make
@@ -100,6 +101,9 @@ static int do_execute(
if (timeout != USEC_INFINITY)
alarm(DIV_ROUND_UP(timeout, USEC_PER_SEC));
+ STRV_FOREACH(e, envp)
+ putenv(*e);
+
STRV_FOREACH(path, paths) {
_cleanup_free_ char *t = NULL;
_cleanup_close_ int fd = -1;
@@ -170,7 +174,8 @@ int execute_directories(
usec_t timeout,
gather_stdout_callback_t const callbacks[_STDOUT_CONSUME_MAX],
void* const callback_args[_STDOUT_CONSUME_MAX],
- char *argv[]) {
+ char *argv[],
+ char *envp[]) {
char **dirs = (char**) directories;
_cleanup_close_ int fd = -1;
@@ -201,7 +206,7 @@ int execute_directories(
if (r < 0)
return r;
if (r == 0) {
- r = do_execute(dirs, timeout, callbacks, callback_args, fd, argv);
+ r = do_execute(dirs, timeout, callbacks, callback_args, fd, argv, envp);
_exit(r < 0 ? EXIT_FAILURE : EXIT_SUCCESS);
}
diff --git a/src/basic/exec-util.h b/src/basic/exec-util.h
index f81019f86..2c745d501 100644
--- a/src/basic/exec-util.h
+++ b/src/basic/exec-util.h
@@ -18,7 +18,8 @@ int execute_directories(
usec_t timeout,
gather_stdout_callback_t const callbacks[_STDOUT_CONSUME_MAX],
void* const callback_args[_STDOUT_CONSUME_MAX],
- char *argv[]);
+ char *argv[],
+ char *envp[]);
#if 0 /// UNNEEDED by elogind
extern const gather_stdout_callback_t gather_environment[_STDOUT_CONSUME_MAX];
diff --git a/src/sleep/sleep.c b/src/sleep/sleep.c
index 87efd0ac7..f104e5dac 100644
--- a/src/sleep/sleep.c
+++ b/src/sleep/sleep.c
@@ -180,7 +180,7 @@ static int execute(Manager *m, const char *verb) {
return log_error_errno(r, "Failed to write mode to /sys/power/disk: %m");;
}
- execute_directories(dirs, DEFAULT_TIMEOUT_USEC, NULL, NULL, arguments);
+ execute_directories(dirs, DEFAULT_TIMEOUT_USEC, NULL, NULL, arguments, NULL);
log_struct(LOG_INFO,
"MESSAGE_ID=" SD_MESSAGE_SLEEP_START_STR,
@@ -197,7 +197,7 @@ static int execute(Manager *m, const char *verb) {
"SLEEP=%s", arg_verb);
arguments[1] = (char*) "post";
- execute_directories(dirs, DEFAULT_TIMEOUT_USEC, NULL, NULL, arguments);
+ execute_directories(dirs, DEFAULT_TIMEOUT_USEC, NULL, NULL, arguments, NULL);
return r;
}
diff --git a/src/test/test-exec-util.c b/src/test/test-exec-util.c
index 030328391..24f8cd36e 100644
--- a/src/test/test-exec-util.c
+++ b/src/test/test-exec-util.c
@@ -16,6 +16,7 @@
#include "fs-util.h"
#include "log.h"
#include "macro.h"
+//#include "path-util.h"
#include "rm-rf.h"
#include "string-util.h"
#include "strv.h"
@@ -115,9 +116,9 @@ static void test_execute_directory(bool gather_stdout) {
assert_se(chmod(mask2e, 0755) == 0);
if (gather_stdout)
- execute_directories(dirs, DEFAULT_TIMEOUT_USEC, ignore_stdout, ignore_stdout_args, NULL);
+ execute_directories(dirs, DEFAULT_TIMEOUT_USEC, ignore_stdout, ignore_stdout_args, NULL, NULL);
else
- execute_directories(dirs, DEFAULT_TIMEOUT_USEC, NULL, NULL, NULL);
+ execute_directories(dirs, DEFAULT_TIMEOUT_USEC, NULL, NULL, NULL, NULL);
assert_se(chdir(template_lo) == 0);
assert_se(access("it_works", F_OK) >= 0);
@@ -182,7 +183,7 @@ static void test_execution_order(void) {
assert_se(chmod(override, 0755) == 0);
assert_se(chmod(masked, 0755) == 0);
- execute_directories(dirs, DEFAULT_TIMEOUT_USEC, ignore_stdout, ignore_stdout_args, NULL);
+ execute_directories(dirs, DEFAULT_TIMEOUT_USEC, ignore_stdout, ignore_stdout_args, NULL, NULL);
assert_se(read_full_file(output, &contents, NULL) >= 0);
assert_se(streq(contents, "30-override\n80-foo\n90-bar\nlast\n"));
@@ -264,7 +265,7 @@ static void test_stdout_gathering(void) {
assert_se(chmod(name2, 0755) == 0);
assert_se(chmod(name3, 0755) == 0);
- r = execute_directories(dirs, DEFAULT_TIMEOUT_USEC, gather_stdout, args, NULL);
+ r = execute_directories(dirs, DEFAULT_TIMEOUT_USEC, gather_stdout, args, NULL, NULL);
assert_se(r >= 0);
log_info("got: %s", output);
@@ -276,7 +277,7 @@ static void test_stdout_gathering(void) {
static void test_environment_gathering(void) {
char template[] = "/tmp/test-exec-util.XXXXXXX", **p;
const char *dirs[] = {template, NULL};
- const char *name, *name2, *name3;
+ const char *name, *name2, *name3, *old;
int r;
char **tmp = NULL; /* this is only used in the forked process, no cleanup here */
@@ -322,7 +323,32 @@ static void test_environment_gathering(void) {
assert_se(chmod(name2, 0755) == 0);
assert_se(chmod(name3, 0755) == 0);
- r = execute_directories(dirs, DEFAULT_TIMEOUT_USEC, gather_environment, args, NULL);
+ /* When booting in containers or without initramfs there might not be
+ * any PATH in the environ and if there is no PATH /bin/sh built-in
+ * PATH may leak and override systemd's DEFAULT_PATH which is not
+ * good. Force our own PATH in environment, to prevent expansion of sh
+ * built-in $PATH */
+ old = getenv("PATH");
+ r = setenv("PATH", "no-sh-built-in-path", 1);
+ assert_se(r >= 0);
+
+ r = execute_directories(dirs, DEFAULT_TIMEOUT_USEC, gather_environment, args, NULL, NULL);
+ assert_se(r >= 0);
+
+ STRV_FOREACH(p, env)
+ log_info("got env: \"%s\"", *p);
+
+ assert_se(streq(strv_env_get(env, "A"), "22:23:24"));
+ assert_se(streq(strv_env_get(env, "B"), "12"));
+ assert_se(streq(strv_env_get(env, "C"), "001"));
+ assert_se(streq(strv_env_get(env, "PATH"), "no-sh-built-in-path:/no/such/file"));
+
+ /* now retest with "default" path passed in, as created by
+ * manager_default_environment */
+ env = strv_free(env);
+ env = strv_new("PATH=" DEFAULT_PATH, NULL);
+
+ r = execute_directories(dirs, DEFAULT_TIMEOUT_USEC, gather_environment, args, NULL, env);
assert_se(r >= 0);
STRV_FOREACH(p, env)
@@ -331,7 +357,10 @@ static void test_environment_gathering(void) {
assert_se(streq(strv_env_get(env, "A"), "22:23:24"));
assert_se(streq(strv_env_get(env, "B"), "12"));
assert_se(streq(strv_env_get(env, "C"), "001"));
- assert_se(endswith(strv_env_get(env, "PATH"), ":/no/such/file"));
+ assert_se(streq(strv_env_get(env, "PATH"), DEFAULT_PATH ":/no/such/file"));
+
+ /* reset environ PATH */
+ (void) setenv("PATH", old, 1);
}
#endif // 0