diff --git a/src/cmdstr.hpp b/src/cmdstr.hpp index 48d67c5e5534807d829cc37c5693105235736340..eeccc1bb0a34614837db055fa8b44bb307d10632 100644 --- a/src/cmdstr.hpp +++ b/src/cmdstr.hpp @@ -1,10 +1,7 @@ #ifndef cmdstr_hpp #define cmdstr_hpp -/*BINFMTCXX: -std=c++11 -Wall -Werror -*/ - -#include <spawn.h> // see manpages-posix-dev +#include <spawn.h> #include <poll.h> #include <stdio.h> #include <stdlib.h> @@ -14,19 +11,45 @@ #include <iostream> #include <string> #include <vector> -using namespace std; +#include <array> +using namespace std; static inline pair<string,int> command_to_string( const string& command) { auto ret=string(); int exit_code=0; - int cout_pipe[2]; - int cerr_pipe[2]; posix_spawn_file_actions_t action; - if(pipe(cout_pipe) || pipe(cerr_pipe)) - cout << "pipe returned an error.\n"; + + const auto pipe_closer = function<void(int*)>([](int *p_pipefd) -> void + { + const auto pipe = *p_pipefd; + close(pipe); + delete p_pipefd; + }); + using PipeFD_t = unique_ptr<int,decltype(pipe_closer)>; + + const auto pipe_opener = [&]() -> vector<PipeFD_t> + { + auto pipe_fds = array<int,2>(); + if(pipe( pipe_fds.data())) + { + const auto err_str = string(strerror(errno)); + throw runtime_error("Cannot open pipe: " + err_str); + } + auto ret = vector<PipeFD_t>(); +// PipeFD_t p(new int(pipe_fds[0]), pipe_closer); +// ret.push_back(move(p)); + ret.push_back({new int(pipe_fds[0]), pipe_closer}); + ret.push_back({new int(pipe_fds[1]), pipe_closer}); + return ret; + }; + + auto cout_pipe_vec = pipe_opener(); + auto cerr_pipe_vec = pipe_opener(); + const auto cout_pipe = vector<int>{*(cout_pipe_vec[0]), *(cout_pipe_vec[1])}; + const auto cerr_pipe = vector<int>{*(cerr_pipe_vec[0]), *(cerr_pipe_vec[1])}; posix_spawn_file_actions_init(&action); posix_spawn_file_actions_addclose(&action, cout_pipe[0]); @@ -37,8 +60,6 @@ static inline pair<string,int> command_to_string( const string& command) posix_spawn_file_actions_addclose(&action, cout_pipe[1]); posix_spawn_file_actions_addclose(&action, cerr_pipe[1]); - // string command = "echo bla"; // example #1 - // string command = "pgmcrater -width 64 -height 9 |pgmtopbm |pnmtoplainpnm"; vector<char> argsmem[] = {{'s', 'h', '\0'}, {'-', 'c', '\0'}}; // allows non-const access to literals char *args[] = {&argsmem[0][0], &argsmem[1][0],const_cast<char*>(command.c_str()),nullptr}; @@ -46,23 +67,23 @@ static inline pair<string,int> command_to_string( const string& command) if(posix_spawnp(&pid, args[0], &action, NULL, args, environ) != 0) cout << "posix_spawnp failed with error: " << strerror(errno) << "\n"; - close(cout_pipe[1]), close(cerr_pipe[1]); // close child-side of pipes + cout_pipe_vec[1].reset(); + cerr_pipe_vec[1].reset(); // close child-side of pipes + // Read from pipes string buffer(1024,' '); - std::vector<pollfd> plist = { {cout_pipe[0],POLLIN}, {cerr_pipe[0],POLLIN} }; + vector<pollfd> plist = { {cout_pipe[0],POLLIN}, {cerr_pipe[0],POLLIN} }; for ( int rval; (rval=poll(&plist[0],plist.size(),/*timeout*/-1))>0; ) { - if ( plist[0].revents&POLLIN) { + if ( plist[0].revents&POLLIN) + { const auto bytes_read = read(cout_pipe[0], &buffer[0], buffer.length()); - // cout << "read " << bytes_read << " bytes from stdout.\n"; - // cout << buffer.substr(0, static_cast<size_t>(bytes_read)) << "\n"; ret += buffer.substr(0, static_cast<size_t>(bytes_read)); } - else if ( plist[1].revents&POLLIN ) { + else if ( plist[1].revents&POLLIN ) + { const auto bytes_read = read(cerr_pipe[0], &buffer[0], buffer.length()); - // cout << "read " << bytes_read << " bytes from stderr.\n"; - // cout << buffer.substr(0, static_cast<size_t>(bytes_read)) << "\n"; ret += buffer.substr(0, static_cast<size_t>(bytes_read)); } else @@ -85,4 +106,5 @@ static inline int command_to_stream(const string& command, ostream& stream) return res.second; } + #endif