From 85b5fd3682295abd932fd602026a66af5c118d8d Mon Sep 17 00:00:00 2001 From: Neil Henning Date: Tue, 9 Jan 2018 22:25:51 +0000 Subject: [PATCH] Allow environment to be inherited from the parent or not. --- process.h | 21 ++++++-- test/CMakeLists.txt | 1 + test/main.c | 82 ++++++++++++++++++++++++++++++ test/process_inherit_environment.c | 44 ++++++++++++++++ 4 files changed, 145 insertions(+), 3 deletions(-) create mode 100644 test/process_inherit_environment.c diff --git a/process.h b/process.h index 5719f20..52f6bd0 100644 --- a/process.h +++ b/process.h @@ -151,7 +151,10 @@ struct process_s { enum process_option_e { // stdout and stderr are the same FILE. - process_option_combined_stdout_stderr = 0x1 + process_option_combined_stdout_stderr = 0x1, + + // The child process should inherit the environment variables of the parent. + process_option_inherit_environment = 0x2 }; /// @brief Create a process. @@ -221,12 +224,18 @@ int process_create(const char *const commandLine[], int options, const unsigned long handleFlagInherit = 0x00000001; struct process_process_information_s processInfo; struct process_security_attributes_s saAttr = {sizeof(saAttr), 0, 1}; + char *environment = 0; struct process_startup_info_s startInfo = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; startInfo.cb = sizeof(startInfo); startInfo.dwFlags = startFUseStdHandles; + if (process_option_inherit_environment != + (options & process_option_inherit_environment)) { + environment = "\0\0"; + } + if (!CreatePipe(&rd, &wr, (LPSECURITY_ATTRIBUTES)&saAttr, 0)) { return -1; } @@ -331,7 +340,7 @@ int process_create(const char *const commandLine[], int options, NULL, // primary thread security attributes 1, // handles are inherited 0, // creation flags - NULL, // use parent's environment + environment, // use parent's environment NULL, // use parent's current directory (LPSTARTUPINFOA)&startInfo, // STARTUPINFO pointer (LPPROCESS_INFORMATION)&processInfo)) { @@ -397,7 +406,13 @@ int process_create(const char *const commandLine[], int options, #pragma clang diagnostic ignored "-Wcast-qual" #pragma clang diagnostic ignored "-Wold-style-cast" #endif - exit(execvp(commandLine[0], (char *const *)commandLine)); + if (process_option_inherit_environment != + (options & process_option_inherit_environment)) { + char *const environment[1] = {0}; + exit(execve(commandLine[0], (char *const *)commandLine, environment)); + } else { + exit(execvp(commandLine[0], (char *const *)commandLine)); + } #ifdef __clang__ #pragma clang diagnostic pop #endif diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index ffd563c..81ff22a 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -39,6 +39,7 @@ add_executable(process_stdout_argv process_stdout_argv.c) add_executable(process_stderr_argc process_stderr_argc.c) add_executable(process_stderr_argv process_stderr_argv.c) add_executable(process_combined_stdout_stderr process_combined_stdout_stderr.c) +add_executable(process_inherit_environment process_inherit_environment.c) add_executable(process_test ../process.h diff --git a/test/main.c b/test/main.c index abadb25..59150d3 100644 --- a/test/main.c +++ b/test/main.c @@ -266,4 +266,86 @@ UTEST(create, process_combined_stdout_stderr) { ASSERT_EQ(0, process_destroy(&process)); } +UTEST(create, process_not_inherit_environment) { + const char *const commandLine[] = {"./process_inherit_environment", 0}; + struct process_s process; + int ret = -1; + +#ifdef _MSC_VER + ASSERT_TRUE(SetEnvironmentVariable("PROCESS_ENV_TEST", "1")); +#else + ASSERT_FALSE(putenv("PROCESS_ENV_TEST=1")); +#endif + + ASSERT_EQ(0, process_create(commandLine, 0, &process)); + + ASSERT_EQ(0, process_join(&process, &ret)); + + ASSERT_EQ(0, ret); + + ASSERT_EQ(0, process_destroy(&process)); +} + +UTEST(create, process_inherit_environment) { + const char *const commandLine[] = {"./process_inherit_environment", 0}; + struct process_s process; + int ret = -1; + +#ifdef _MSC_VER + ASSERT_TRUE(SetEnvironmentVariable("PROCESS_ENV_TEST", "42")); +#else + ASSERT_FALSE(putenv("PROCESS_ENV_TEST=42")); +#endif + + ASSERT_EQ(0, process_create(commandLine, process_option_inherit_environment, + &process)); + + ASSERT_EQ(0, process_join(&process, &ret)); + + ASSERT_EQ(42, ret); + + ASSERT_EQ(0, process_destroy(&process)); +} + +UTEST(create, process_not_inherit_all_environment) { + const char *const commandLine[] = {"./process_inherit_environment", "all", 0}; + struct process_s process; + int ret = -1; + +#ifdef _MSC_VER + ASSERT_TRUE(SetEnvironmentVariable("PROCESS_ENV_TEST", "42")); +#else + ASSERT_FALSE(putenv("PROCESS_ENV_TEST=42")); +#endif + + ASSERT_EQ(0, process_create(commandLine, 0, &process)); + + ASSERT_EQ(0, process_join(&process, &ret)); + + ASSERT_EQ(0, ret); + + ASSERT_EQ(0, process_destroy(&process)); +} + +UTEST(create, process_inherit_all_environment) { + const char *const commandLine[] = {"./process_inherit_environment", "all", 0}; + struct process_s process; + int ret = -1; + +#ifdef _MSC_VER + ASSERT_TRUE(SetEnvironmentVariable("PROCESS_ENV_TEST", "42")); +#else + ASSERT_FALSE(putenv("PROCESS_ENV_TEST=42")); +#endif + + ASSERT_EQ(0, process_create(commandLine, process_option_inherit_environment, + &process)); + + ASSERT_EQ(0, process_join(&process, &ret)); + + ASSERT_EQ(1, ret); + + ASSERT_EQ(0, process_destroy(&process)); +} + UTEST_MAIN() diff --git a/test/process_inherit_environment.c b/test/process_inherit_environment.c new file mode 100644 index 0000000..7fd113e --- /dev/null +++ b/test/process_inherit_environment.c @@ -0,0 +1,44 @@ +// This is free and unencumbered software released into the public domain. +// +// Anyone is free to copy, modify, publish, use, compile, sell, or +// distribute this software, either in source code form or as a compiled +// binary, for any purpose, commercial or non-commercial, and by any +// means. +// +// In jurisdictions that recognize copyright laws, the author or authors +// of this software dedicate any and all copyright interest in the +// software to the public domain. We make this dedication for the benefit +// of the public at large and to the detriment of our heirs and +// successors. We intend this dedication to be an overt act of +// relinquishment in perpetuity of all present and future rights to this +// software under copyright law. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +// IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR +// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// +// For more information, please refer to + +#include +#include + +int main(int argc, const char *const argv[], const char *const envp[]) { + if ((1 < argc) && (0 == strcmp(argv[1], "all"))) { + if (0 == *envp) { + return 0; + } else { + return 1; + } + } else { + const char *const str = getenv("PROCESS_ENV_TEST"); + if (str) { + return atoi(str); + } else { + return 0; + } + } +}