allow path lookup for pipestream
[libi2ncommon] / src / pipestream.cpp
index eeca4f2..66ee39b 100644 (file)
@@ -44,11 +44,15 @@ on this file might be covered by the GNU General Public License.
 /** @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
+ *  @param out Whether to collect \c stdout.
+ *  @param err Whether to collect \c stderr; combines with \c out.
+ *  @param path Wether to look up the executable in \c $PATH.
  *  @returns the output (stdout) of the called program
  */
 template <typename CmdT>
 std::string capture_exec(CmdT command, ExecResult &rescode,
-                         const bool out, const bool err)
+                         const bool out, const bool err,
+                         const bool path)
 {
     std::string output;
 
@@ -62,7 +66,7 @@ std::string capture_exec(CmdT command, ExecResult &rescode,
     try
     {
         {
-            inpipestream ips(command, out, err);
+            inpipestream ips(command, out, err, path);
 
             ips.store_exit_status(&exit_set, &exit_status_waitpid);
 
@@ -110,7 +114,7 @@ std::string capture_exec(CmdT command, ExecResult &rescode,
  *                    passed.
  */
 std::string capture_exec (const std::string &command, ExecResult &res)
-{ return capture_exec<const std::string &>(command, res, true, false); }
+{ return capture_exec<const std::string &>(command, res, true, false, false); }
 
 /** @brief      Instantiation of \c capture_exec for argument lists. The
  *              pipestream used to run the command will not shell out.
@@ -124,12 +128,13 @@ std::string capture_exec (const std::string &command, ExecResult &res)
  *                    state in this struct.
  *  @param out        Whether to collect \c stdout.
  *  @param err        Whether to collect \c stderr; combines with \c out.
+ *  @param path       Wether to look up the executable in \c $PATH.
  *
  *  @returns          Captured output, combined into one string.
  */
 std::string capture_exec (const char *const *command, ExecResult &res,
-                          const bool out, const bool err)
-{ return capture_exec<const char *const *>(command, res, out, err); }
+                          const bool out, const bool err, const bool path)
+{ return capture_exec<const char *const *>(command, res, out, err, path); }
 
 /** @brief      Instantiation of \c capture_exec for argument lists. The
  *              pipestream used to run the command will not shell out.
@@ -142,14 +147,15 @@ std::string capture_exec (const char *const *command, ExecResult &res,
  *                    state in this struct.
  *  @param out        Whether to collect \c stdout.
  *  @param err        Whether to collect \c stderr; combines with \c out.
+ *  @param path       Wether to look up the executable in \c $PATH.
  *
  *  @returns          Captured output, combined into one string.
  */
 std::string capture_exec (const std::vector<std::string> &command, ExecResult &res,
-                          const bool out, const bool err)
+                          const bool out, const bool err, const bool path)
 {
     return capture_exec<const std::vector<std::string> &>
-        (command, res, out, err);
+        (command, res, out, err, path);
 }
 
 #define PIPE_CTOR_FAIL(where) \
@@ -197,7 +203,6 @@ mk_argv (const std::vector<std::string> &command)
     return boost::shared_array<char *> (ret);
 }
 
-
 /** @brief      Helper aggregating common code for the shell-free ctors.
  *
  *  @param argv       Argument list prepared for \c execve(2).
@@ -210,7 +215,8 @@ mk_argv (const std::vector<std::string> &command)
 std::pair <pid_t, FILE *>
 inpipebuf::init_without_shell (const char *const *argv,
                                const bool out,
-                               const bool err) const
+                               const bool err,
+                               const bool path) const
 {
     FILE *pipeobj = NULL;
     int pipefd [2];
@@ -238,21 +244,26 @@ inpipebuf::init_without_shell (const char *const *argv,
             if (!out) {
                 close (STDOUT_FILENO);
             } else if (dup2 (pipefd[1], STDOUT_FILENO) == -1) {
-                PIPE_CTOR_FAIL("dup2/stdout");
+                fprintf(stderr, "dup2/stdout: %m\n");
+                exit(EXIT_FAILURE);
             }
 
             if (!err) {
                 close (STDERR_FILENO);
             } else if (dup2 (pipefd[1], STDERR_FILENO) == -1) {
-                PIPE_CTOR_FAIL("dup2/stderr");
+                fprintf(stderr, "dup2/stderr: %m\n");
+                exit(EXIT_FAILURE);
             }
 
             close (pipefd [1]);
 
             errno = 0;
-            if (execve (argv [0], const_cast <char *const *>(argv), NULL) == -1) {
-                PIPE_CTOR_FAIL("exec");
+            if (path) {
+                execvpe (argv [0], const_cast <char *const *>(argv), environ);
+            } else {
+                execve (argv [0], const_cast <char *const *>(argv), NULL);
             }
+            exit(EXIT_FAILURE);
             break;
         }
         default: {
@@ -271,7 +282,8 @@ inpipebuf::init_without_shell (const char *const *argv,
 
 inpipebuf::inpipebuf(const char *const *command,
                      const bool out,
-                     const bool err)
+                     const bool err,
+                     const bool path)
     : pipe (NULL) /* brr: shadowing global ident */
     , pid (-1)
     , status_set (NULL)
@@ -281,7 +293,8 @@ inpipebuf::inpipebuf(const char *const *command,
         PIPE_CTOR_FAIL("command");
     }
 
-    std::pair <pid_t, FILE *> tmp = this->init_without_shell (command, out, err);
+    std::pair <pid_t, FILE *> tmp =
+        this->init_without_shell (command, out, err, path);
     this->pid  = tmp.first; /* no std::tie :/ */
     this->pipe = tmp.second;
 
@@ -290,7 +303,8 @@ inpipebuf::inpipebuf(const char *const *command,
 
 inpipebuf::inpipebuf(const std::vector<std::string> &command,
                      const bool out,
-                     const bool err)
+                     const bool err,
+                     const bool path)
     : pipe (NULL) /* brr: shadowing global ident */
     , pid (-1)
     , status_set (NULL)
@@ -305,7 +319,8 @@ inpipebuf::inpipebuf(const std::vector<std::string> &command,
         PIPE_CTOR_FAIL("malloc");
     }
 
-    std::pair <pid_t, FILE *> tmp = this->init_without_shell (argv.get (), out, err);
+    std::pair <pid_t, FILE *> tmp =
+        this->init_without_shell (argv.get (), out, err, path);
     this->pid  = tmp.first;
     this->pipe = tmp.second;
 
@@ -314,7 +329,8 @@ inpipebuf::inpipebuf(const std::vector<std::string> &command,
 
 inpipebuf::inpipebuf(const std::string& command,
                      const bool _ignored_out,
-                     const bool _ignored_err)
+                     const bool _ignored_err,
+                     const bool _ignored_path)
     : pid (-1)
     , status_set (NULL)
     , exit_status (NULL)