From: Daniel Karbach Date: Mon, 21 Nov 2016 16:42:45 +0000 (+0100) Subject: allow cloned env with child processes X-Git-Url: https://git.localhorst.tv/?a=commitdiff_plain;h=3b617c12da216c2d1744c5fbb62a7ef381e1e0b3;p=blank.git allow cloned env with child processes --- diff --git a/src/app/Process.hpp b/src/app/Process.hpp index 6f5a5ae..732fd2f 100644 --- a/src/app/Process.hpp +++ b/src/app/Process.hpp @@ -16,7 +16,12 @@ public: public: /// launch process executing the file at given path with - /// given arguments and environment + /// given arguments and environment of parent process + Process( + const std::string &path, + const Arguments &args); + /// launch process executing the file at given path with + /// given arguments and given environment Process( const std::string &path, const Arguments &args, diff --git a/src/app/proc.cpp b/src/app/proc.cpp index 876eefc..dff8dee 100644 --- a/src/app/proc.cpp +++ b/src/app/proc.cpp @@ -23,11 +23,16 @@ namespace blank { struct Process::Impl { Impl( - const string &path_in, + const string &path, const Arguments &args, - const Environment &env); + char *const env[]); ~Impl(); + static Impl *EnvHelper( + const string &path, + const Arguments &args, + const Environment &env); + size_t WriteIn(const void *buffer, size_t max_len); void CloseIn(); @@ -63,11 +68,18 @@ struct Process::Impl { }; +Process::Process( + const string &path, + const Arguments &args) +: impl(new Impl(path, args, nullptr)) { + +} + Process::Process( const string &path, const Arguments &args, const Environment &env) -: impl(new Impl(path, args, env)) { +: impl(Impl::EnvHelper(path, args, env)) { } @@ -112,22 +124,29 @@ int Process::Join() { return impl->Join(); } +Process::Impl *Process::Impl::EnvHelper( + const string &path, + const Arguments &args, + const Environment &env +) { + char *envp[env.size() + 1]; + for (size_t i = 0; i < env.size(); ++i) { + envp[i] = const_cast(env[i].c_str()); + } + envp[env.size()] = nullptr; + return new Impl(path, args, envp); +} Process::Impl::Impl( const string &path_in, const Arguments &args, - const Environment &env) + char *const envp[]) : joined(false) , status(0) , in_closed(false) , out_closed(false) , err_closed(false) { const char *path = path_in.c_str(); - char *envp[env.size() + 1]; - for (size_t i = 0; i < env.size(); ++i) { - envp[i] = const_cast(env[i].c_str()); - } - envp[env.size()] = nullptr; #ifdef _WIN32 string cmdline; for (const auto &arg : args) { @@ -222,7 +241,11 @@ Process::Impl::Impl( close(fd_err[0]); close(fd_err[1]); - execve(path, argv, envp); + if (envp) { + execve(path, argv, envp); + } else { + execv(path, argv); + } // if execve returns, something bad happened exit(EXIT_FAILURE); diff --git a/tst/app/ProcessTest.cpp b/tst/app/ProcessTest.cpp index a5d2cc5..a16bfb3 100644 --- a/tst/app/ProcessTest.cpp +++ b/tst/app/ProcessTest.cpp @@ -25,7 +25,7 @@ void ProcessTest::testExit() { #else { - Process proc("/usr/bin/env", { "env", "true" }, { }); + Process proc("/usr/bin/env", { "env", "true" }); int status = proc.Join(); CPPUNIT_ASSERT_EQUAL_MESSAGE( "exit status of true assumed 0", @@ -33,7 +33,7 @@ void ProcessTest::testExit() { } { - Process proc("/usr/bin/env", { "env", "false" }, { }); + Process proc("/usr/bin/env", { "env", "false" }); int status = proc.Join(); CPPUNIT_ASSERT_EQUAL_MESSAGE( "exit status of false assumed 1", @@ -45,13 +45,13 @@ void ProcessTest::testExit() { void ProcessTest::testStream() { #ifdef __WIN32 -# error "TODO: implemente Process tests for windows" +# error "TODO: implement Process tests for windows" #else { const string test_input("hello, world"); const string expected_output("hello, world\n"); - Process proc("/usr/bin/env", { "env", "echo", test_input.c_str() }, { }); + Process proc("/usr/bin/env", { "env", "echo", test_input.c_str() }); char buffer[expected_output.length() + 1]; size_t len = proc.ReadOut(buffer, sizeof(buffer)); const string output(buffer, len); @@ -90,7 +90,7 @@ void ProcessTest::testStream() { { const string test_input("dog"); const string expected_output("dog"); - Process proc("/usr/bin/env", { "env", "cat" }, { }); + Process proc("/usr/bin/env", { "env", "cat" }); size_t len = proc.WriteIn(test_input.c_str(), test_input.size()); CPPUNIT_ASSERT_EQUAL_MESSAGE( "unexpected length of input to cat", @@ -116,5 +116,32 @@ void ProcessTest::testStream() { #endif } + +void ProcessTest::testEnv() { +#ifdef __WIN32 +# error "TODO: implement Process tests for windows" +#else + { + const string test_input("Hello, environment"); + const string expected_output("Hello, environment\n"); + Process proc("/usr/bin/env", { "env", "sh", "-c", "echo $BLANK_ENV_TEST" }, { "BLANK_ENV_TEST=" + test_input }); + char buffer[expected_output.length() + 1]; + size_t len = proc.ReadOut(buffer, sizeof(buffer)); + const string output(buffer, len); + int status = proc.Join(); + CPPUNIT_ASSERT_EQUAL_MESSAGE( + "exit status of echo assumed 0", + 0, status); + CPPUNIT_ASSERT_EQUAL_MESSAGE( + "unexpected length of echo output", + expected_output.size(), len); + CPPUNIT_ASSERT_EQUAL_MESSAGE( + "unexpected error output of echo", + expected_output, output); + } + +#endif +} + } } diff --git a/tst/app/ProcessTest.hpp b/tst/app/ProcessTest.hpp index 972fbe5..95217e3 100644 --- a/tst/app/ProcessTest.hpp +++ b/tst/app/ProcessTest.hpp @@ -14,6 +14,7 @@ CPPUNIT_TEST_SUITE(ProcessTest); CPPUNIT_TEST(testExit); CPPUNIT_TEST(testStream); +CPPUNIT_TEST(testEnv); CPPUNIT_TEST_SUITE_END(); @@ -23,6 +24,7 @@ public: void testExit(); void testStream(); + void testEnv(); }; diff --git a/tst/integration/TestInstance.cpp b/tst/integration/TestInstance.cpp index 495ba6c..270c09c 100644 --- a/tst/integration/TestInstance.cpp +++ b/tst/integration/TestInstance.cpp @@ -28,10 +28,7 @@ Process::Arguments combine_args(const TempDir &dir, const Process::Arguments &in TestInstance::TestInstance(const Process::Arguments &args, bool cmd) : dir() -, proc( - "./blank" BLANK_SUFFIX, - combine_args(dir, args, cmd), - { }) +, proc("./blank" BLANK_SUFFIX, combine_args(dir, args, cmd)) , conn() , out_buf() , err_buf()