From f8f119bfa90c1db029210a2b362f871076b992ce Mon Sep 17 00:00:00 2001 From: Gerd von Egidy Date: Thu, 17 Dec 2015 10:56:27 +0100 Subject: [PATCH] rename pipe_to_string() to capture_exec() and improve it's interface --- src/pipestream.cpp | 90 ++++++++++++++++++++++++++++-------------------- src/pipestream.hxx | 29 ++++++++++++++- test/test_filefunc.cpp | 4 +- 3 files changed, 82 insertions(+), 41 deletions(-) diff --git a/src/pipestream.cpp b/src/pipestream.cpp index c475a50..b29ec70 100644 --- a/src/pipestream.cpp +++ b/src/pipestream.cpp @@ -25,6 +25,7 @@ on this file might be covered by the GNU General Public License. ***************************************************************************/ #include +#include #include #include @@ -35,6 +36,58 @@ on this file might be covered by the GNU General Public License. #include "exception.hxx" #include "pipestream.hxx" +/** @brief runs command and returns it's output as string + * @param command the full command with all parameters + * @param rescode struct containing the return code, if the program exited normally and so on + * @returns the output (stdout) of the called program + */ +std::string capture_exec(const std::string& command, ExecResult &rescode) +{ + std::string output; + + bool exit_set; + int exit_status_waitpid; + + // set the results to false until we are sure we have proper values + rescode.normal_exit = false; + rescode.terminated_by_signal = false; + + try + { + { + inpipestream ips(command); + + ips.store_exit_status(&exit_set, &exit_status_waitpid); + + char buffer[2048]; + while (ips.good()) + { + ips.read(buffer, sizeof(buffer)); + output.append(buffer, ips.gcount()); + } + } + + // exit_status_waitpid only valid after destruction of the inpipestream + + if (exit_set) + { + rescode.normal_exit = WIFEXITED(exit_status_waitpid); + if (rescode.normal_exit) + rescode.return_code = WEXITSTATUS(exit_status_waitpid); + + rescode.terminated_by_signal = WIFSIGNALED(exit_status_waitpid); + if (rescode.terminated_by_signal) + rescode.signal = WTERMSIG(exit_status_waitpid); + } + } + catch (pipestream_error &e) + { + rescode.error_message = e.what(); + } + + return output; +} + inpipebuf::inpipebuf(const std::string& command) { status_set = NULL; @@ -88,43 +141,6 @@ inpipebuf::int_type inpipebuf::underflow() return traits_type::to_int_type(*gptr()); } -/** @brief runs command and returns it's output as string - * @param command the full command with all parameters - * @param exit_status the full exit status, use WEXITSTATUS to get the "regular" return code - * @returns the output (stderr) of the called program - */ -std::string pipe_to_string(const std::string& command, std::string *error, int *_exit_status) -{ - std::string result; - bool exit_set; - - try - { - inpipestream ips(command); - - ips.store_exit_status(&exit_set, _exit_status); - - char buffer[2048]; - while (ips.good()) - { - ips.read(buffer, sizeof(buffer)); - result.append(buffer, ips.gcount()); - } - } - catch (pipestream_error &e) - { - if (error) - *error=e.what(); - return ""; - } - catch(...) - { - throw; - } - - return result; -} - outpipebuf::outpipebuf(const std::string& command) { status_set = NULL; diff --git a/src/pipestream.hxx b/src/pipestream.hxx index f0cf87b..83244ed 100644 --- a/src/pipestream.hxx +++ b/src/pipestream.hxx @@ -32,6 +32,33 @@ on this file might be covered by the GNU General Public License. #include #include +struct ExecResult +{ + /** if the program exited normally and returned a return code */ + bool normal_exit; + + /** the real return code of the program, only set when normal_exit true */ + char return_code; + + /** if the program was terminated by a signal */ + bool terminated_by_signal; + + /** number of the signal that terminated the program, only valid when terminated_by_signal true */ + int signal; + + /** errormessage if we have one */ + std::string error_message; +}; +typedef struct ExecResult ExecResult; + +std::string capture_exec(const std::string& command, ExecResult &rescode); + +std::string capture_exec(const std::string& command) +{ + ExecResult r; + return capture_exec(command,r); +} + /** @brief runs command and provides buffered input for it through pipe * * opens pipe to command using popen; exit status available after destruction @@ -77,8 +104,6 @@ public: { buf.store_exit_status(_status_set, _exit_status); } }; -std::string pipe_to_string(const std::string& command, std::string *error=NULL, int *_exit_status=NULL); - /** @brief runs command and provides buffered ouptput from it through pipe * * opens pipe to command using popen; exit status available after destruction diff --git a/test/test_filefunc.cpp b/test/test_filefunc.cpp index d982b5a..3d74a9d 100644 --- a/test/test_filefunc.cpp +++ b/test/test_filefunc.cpp @@ -592,7 +592,7 @@ BOOST_AUTO_TEST_CASE(FileContentDiffersEqualSize) BOOST_AUTO_TEST_CASE(FreeDiskSpace1) { - string dfstr=pipe_to_string("df -B 1 --output=avail /tmp | tail -n 1"); + string dfstr=capture_exec("df -B 1 --output=avail /tmp | tail -n 1"); long long dfout=-1; string_to(dfstr,dfout); @@ -620,7 +620,7 @@ BOOST_AUTO_TEST_CASE(TestDu) BOOST_CHECK_EQUAL(true, I2n::mkdir(sub_dir)); BOOST_CHECK_EQUAL(true, write_file(some_file, "foobar and some more data, even more that Tom would like to see in one line without linebreak but I still want to have it all here")); - string dustr=pipe_to_string(string("du --block-size=1 --sum ")+unique_dir+" | cut -f 1"); + string dustr=capture_exec(string("du --block-size=1 --sum ")+unique_dir+" | cut -f 1"); long long duout=-1; string_to(dustr,duout); -- 1.7.1