copyright : (C) 2001 by Intra2net AG
***************************************************************************/
+#include <errno.h>
#include <stdio.h>
+#include <string.h>
#include <sys/wait.h>
+#include <unistd.h>
-#include <string>
#include <streambuf>
#include <istream>
#include <ostream>
#include <cstdio>
+#include <boost/foreach.hpp>
+#include <boost/shared_array.hpp>
#include "exception.hxx"
+#include "stringfunc.hxx"
#include "pipestream.hxx"
/** @brief runs command and returns it's output as string
* @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)
+template <typename CmdT>
+std::string capture_exec(CmdT command, ExecResult &rescode)
{
std::string output;
return output;
}
+std::string capture_exec (const std::string &command, ExecResult &res)
+{ return capture_exec<const std::string &>(command, res); }
+
+std::string capture_exec (const char *const *command, ExecResult &res)
+{ return capture_exec<const char *const *>(command, res); }
+
+#define PIPE_CTOR_FAIL(where) \
+ do { \
+ throw EXCEPTION (pipestream_error, \
+ std::string (where) + ": error " \
+ + I2n::to_string (errno) \
+ + " (" + std::string (strerror (errno)) + ")"); \
+ } while (0)
+
+static boost::shared_array <char *>
+mk_argv (const std::vector<std::string> &command)
+{
+ char **ret = NULL;
+
+ try {
+ ret = new char *[command.size () * sizeof (ret[0]) + 1];
+ } catch (std::bad_alloc &) {
+ return boost::shared_array<char *> ();
+ }
+
+ size_t cur = 0;
+ BOOST_FOREACH(const std::string &arg, command) {
+ /*
+ * Casting away constness is safe since the data is always
+ * kept alive until after exec().
+ */
+ ret [cur++] = const_cast<char *> (arg.c_str ());
+ }
+
+ ret [cur] = NULL;
+
+ return boost::shared_array<char *> (ret);
+}
+
+
+FILE *
+inpipebuf::init_without_shell (const char *const *argv) const
+{
+ FILE *pipeobj = NULL;
+ int pipefd [2];
+
+ errno = 0;
+ if (::pipe (pipefd) == -1) {
+ PIPE_CTOR_FAIL("pipe");
+ }
+
+ errno = 0;
+ pid_t childpid = fork ();
+ switch (childpid) {
+ case -1: {
+ PIPE_CTOR_FAIL("fork");
+ break;
+ }
+ case 0: {
+ close (pipefd [0]);
+
+ if (dup2 (pipefd[1], STDOUT_FILENO) == -1) {
+ PIPE_CTOR_FAIL("dup2");
+ }
+
+ if (dup2 (pipefd[1], STDERR_FILENO) == -1) {
+ PIPE_CTOR_FAIL("dup2");
+ }
+
+ errno = 0;
+ if (execve (argv [0], const_cast <char *const *>(argv), NULL) == -1) {
+ PIPE_CTOR_FAIL("exec");
+ }
+ break;
+ }
+ default: {
+ close (pipefd [1]);
+
+ errno = 0;
+ if ((pipeobj = fdopen (pipefd [0], "r")) == NULL) {
+ PIPE_CTOR_FAIL("fdopen");
+ }
+ break;
+ }
+ }
+
+ return pipeobj;
+}
+
+inpipebuf::inpipebuf(const char *const *command)
+ : pipe (NULL) /* brr: shadowing global ident */
+ , status_set (NULL)
+ , exit_status (NULL)
+{
+ if (command == NULL || command [0] == NULL) {
+ PIPE_CTOR_FAIL("command");
+ }
+
+ this->pipe = this->init_without_shell (command);
+
+ setg (&buffer, &buffer, &buffer);
+}
+
inpipebuf::inpipebuf(const std::string& command)
{
status_set = NULL;
typedef struct ExecResult ExecResult;
std::string capture_exec(const std::string& command, ExecResult &rescode);
+std::string capture_exec(const char *const *command, ExecResult &rescode);
-inline std::string capture_exec(const std::string& command)
+inline std::string capture_exec (const std::string &command)
+{
+ ExecResult r;
+ return capture_exec(command,r);
+}
+
+inline std::string capture_exec(const char *const *command)
{
ExecResult r;
return capture_exec(command,r);
{
protected:
char buffer;
+
FILE *pipe;
// "callback" variables for destructor to store exit status
public:
inpipebuf(const std::string& command);
+ inpipebuf(const char *const *command);
~inpipebuf();
protected:
virtual int_type underflow();
+
+private:
+ FILE *init_without_shell (const char *const *argv) const;
};
/** @brief stream around inpipebuf -- see comment there */
inpipestream(const std::string& command)
: std::istream(&buf), buf(command)
{}
+ inpipestream(const char *const command[])
+ : std::istream(&buf), buf(command)
+ {}
void store_exit_status(bool *_status_set, int *_exit_status)
{ buf.store_exit_status(_status_set, _exit_status); }