/* The software in this package is distributed under the GNU General Public License version 2 (with a special exception described below). A copy of GNU General Public License (GPL) is included in this distribution, in the file COPYING.GPL. As a special exception, if other files instantiate templates or use macros or inline functions from this file, or you compile this file and link it with other works to produce a work based on this file, this file does not by itself cause the resulting work to be covered by the GNU General Public License. However the source code for this file must still be made available in accordance with section (3) of the GNU General Public License. This exception does not invalidate any other reasons why a work based on this file might be covered by the GNU General Public License. */ /*************************************************************************** inpipestream.cpp - C++ streambuffer wrapper ------------------- begin : Thu Dec 27 2001 copyright : (C) 2001 by Intra2net AG ***************************************************************************/ #include #include #include #include #include #include #include #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 = false; 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; exit_status = NULL; pipe = popen (command.c_str(), "r"); if (pipe == NULL) throw EXCEPTION (pipestream_error, "can't open program or permission denied"); // force underflow setg (&buffer, &buffer, &buffer); } inpipebuf::~inpipebuf() { if (pipe != NULL) { int pclose_exit = pclose (pipe); if (exit_status && pclose_exit != -1) { if (status_set) *status_set = true; *exit_status = pclose_exit; } pipe = NULL; } } /** note: exit status only available after destruction */ void inpipebuf::store_exit_status(bool *_status_set, int *_exit_status) { status_set = _status_set; exit_status = _exit_status; } inpipebuf::int_type inpipebuf::underflow() { if (gptr() < egptr()) return traits_type::to_int_type(*gptr()); buffer = fgetc (pipe); if (feof (pipe)) { // ERROR or EOF return EOF; } setg (&buffer, &buffer, &buffer+sizeof(char)); return traits_type::to_int_type(*gptr()); } outpipebuf::outpipebuf(const std::string& command) { status_set = NULL; exit_status = NULL; pipe = popen (command.c_str(), "w"); if (pipe == NULL) throw EXCEPTION (pipestream_error, "can't open program or permission denied"); } outpipebuf::~outpipebuf() { if (pipe != NULL) { int pclose_exit = pclose (pipe); if (exit_status && pclose_exit != -1) { if (status_set) *status_set = true; *exit_status = pclose_exit; } pipe = NULL; } } /** note: exit status only available after destruction */ void outpipebuf::store_exit_status(bool *_status_set, int *_exit_status) { status_set = _status_set; exit_status = _exit_status; } outpipebuf::int_type outpipebuf::overflow(int_type c) { if (c != EOF) { if (fputc(c,pipe)==EOF) return EOF; } return c; } std::streamsize outpipebuf::xsputn(const char* s, std::streamsize num) { return fwrite(s,num,1,pipe); }