From 445aca62277ebc2aa5e57726a211f4949a31a81c Mon Sep 17 00:00:00 2001 From: Christian Speich Date: Sun, 4 Sep 2022 10:20:11 +0200 Subject: [PATCH] Keep environment in shell subprocesses Currently we replace the environment of subprocesses with our own, primarily only consisting of METER_* entries. Besides clearing some very useful system dependent variables (like PATH, LDPATH, etc.) with also prevent the user from passing environment variables to invoked commands. This patch will now copy the current environment and extends it with the variables we want to set. Signed-off-by: Christian Speich --- src/shell.cc | 63 +++++++++++++++++++++++------------------ test.sh | 3 ++ tests/test_shell_env.sh | 29 +++++++++++++++++++ 3 files changed, 68 insertions(+), 27 deletions(-) create mode 100755 tests/test_shell_env.sh diff --git a/src/shell.cc b/src/shell.cc index 24720cd..57f16f4 100644 --- a/src/shell.cc +++ b/src/shell.cc @@ -26,6 +26,39 @@ #include #include +// Posix says that this variable just exists. +// (On some systems this is also declared in unistd.h) +extern char **environ; + +// Not the result borrows memory from env and thus it's lifetime. +vector prepareEnv(vector& envs) +{ + map env_map; + int i; + + for (i = 0; environ[i]; i++) { + string e = environ[i]; + vector parts = splitString(e, '='); + env_map[parts[0]] = environ[i]; + } + + for (auto &e : envs) { + vector parts = splitString(e, '='); + env_map[parts[0]] = e.c_str(); + debug("(shell) env \"%s\"\n", e.c_str()); + } + + vector env(env_map.size()+1); + i = 0; + for (auto &e : env_map) { + env[i] = e.second; + i++; + } + env[i] = NULL; + + return env; +} + void invokeShell(string program, vector args, vector envs) { vector argv(args.size()+2); @@ -41,15 +74,7 @@ void invokeShell(string program, vector args, vector envs) } argv[i] = NULL; - vector env(envs.size()+1); - env[0] = p; - i = 0; - for (auto &e : envs) { - env[i] = e.c_str(); - i++; - debug("(shell) env \"%s\"\n", e.c_str()); - } - env[i] = NULL; + vector env = prepareEnv(envs); pid_t pid = fork(); int status; @@ -99,15 +124,7 @@ bool invokeBackgroundShell(string program, vector args, vector e } argv[i] = NULL; - vector env(envs.size()+1); - env[0] = p; - i = 0; - for (auto &e : envs) { - env[i] = e.c_str(); - i++; - debug("(bgshell) env \"%s\"\n", e.c_str()); - } - env[i] = NULL; + vector env = prepareEnv(envs); if (pipe(link) == -1) { error("(bgshell) could not create pipe!\n"); @@ -241,15 +258,7 @@ int invokeShellCaptureOutput(string program, vector args, vector } argv[i] = NULL; - vector env(envs.size()+1); - env[0] = p; - i = 0; - for (auto &e : envs) { - env[i] = e.c_str(); - i++; - debug("(shell) env \"%s\"\n", e.c_str()); - } - env[i] = NULL; + vector env = prepareEnv(envs); if (pipe(link) == -1) { error("(shell) could not create pipe!\n"); diff --git a/test.sh b/test.sh index 25e4409..9368a53 100755 --- a/test.sh +++ b/test.sh @@ -57,6 +57,9 @@ if [ "$?" != "0" ]; then RC="1"; fi tests/test_shell2.sh $PROG if [ "$?" != "0" ]; then RC="1"; fi +tests/test_shell_env.sh $PROG +if [ "$?" != "0" ]; then RC="1"; fi + tests/test_meterfiles.sh $PROG if [ "$?" != "0" ]; then RC="1"; fi diff --git a/tests/test_shell_env.sh b/tests/test_shell_env.sh new file mode 100755 index 0000000..7e20824 --- /dev/null +++ b/tests/test_shell_env.sh @@ -0,0 +1,29 @@ +#!/bin/sh + +PROG="$1" + +mkdir -p testoutput +TEST=testoutput + +TESTNAME="Test shell environment" +TESTRESULT="ERROR" + +export MY_ENV_TEST="hello world" + +$PROG --shell='echo MY_ENV_TEST="$MY_ENV_TEST"' simulations/simulation_shell.txt MWW supercom587 12345678 "" > $TEST/test_output.txt 2> $TEST/test_stderr.txt +if [ "$?" = "0" ] +then + echo 'MY_ENV_TEST=hello world' > $TEST/test_expected.txt + diff $TEST/test_expected.txt $TEST/test_output.txt + if [ "$?" = "0" ] + then + echo OK: $TESTNAME + TESTRESULT="OK" + fi +fi + +if [ "$TESTRESULT" = "ERROR" ] +then + echo ERROR: $TESTNAME + exit 1 +fi