2 The software in this package is distributed under the GNU General
3 Public License version 2 (with a special exception described below).
5 A copy of GNU General Public License (GPL) is included in this distribution,
6 in the file COPYING.GPL.
8 As a special exception, if other files instantiate templates or use macros
9 or inline functions from this file, or you compile this file and link it
10 with other works to produce a work based on this file, this file
11 does not by itself cause the resulting work to be covered
12 by the GNU General Public License.
14 However the source code for this file must still be made available
15 in accordance with section (3) of the GNU General Public License.
17 This exception does not invalidate any other reasons why a work based
18 on this file might be covered by the GNU General Public License.
20 /***************************************************************************
21 inpipestream.cpp - C++ streambuffer wrapper
23 begin : Thu Dec 27 2001
24 copyright : (C) 2001 by Intra2net AG
25 ***************************************************************************/
38 #include <boost/foreach.hpp>
39 #include <boost/shared_array.hpp>
41 #include "exception.hxx"
42 #include "stringfunc.hxx"
43 #include "pipestream.hxx"
45 /** @brief runs command and returns it's output as string
46 * @param command the full command with all parameters
47 * @param rescode struct containing the return code, if the program exited normally and so on
48 * @param flags runtime control flags (stdio streams, environment, path lookup).
49 * @returns the output (stdout) of the called program
51 template <typename CmdT>
52 std::string capture_exec(CmdT command, ExecResult &rescode,
57 bool exit_set = false;
58 int exit_status_waitpid;
60 // set the results to false until we are sure we have proper values
61 rescode.normal_exit = false;
62 rescode.terminated_by_signal = false;
67 inpipestream ips(command, flags);
69 ips.store_exit_status(&exit_set, &exit_status_waitpid);
74 ips.read(buffer, sizeof(buffer));
75 output.append(buffer, ips.gcount());
79 // exit_status_waitpid only valid after destruction of the inpipestream
83 rescode.normal_exit = WIFEXITED(exit_status_waitpid);
84 if (rescode.normal_exit)
85 rescode.return_code = WEXITSTATUS(exit_status_waitpid);
87 rescode.terminated_by_signal = WIFSIGNALED(exit_status_waitpid);
88 if (rescode.terminated_by_signal)
89 rescode.signal = WTERMSIG(exit_status_waitpid);
92 catch (pipestream_error &e)
94 rescode.error_message = e.what();
100 /** @brief Instantiation of \c capture_exec for STL string arguments.
101 * Caveat emptor: this will cause the backing stream to use \c
102 * popen(3). To avoid shelling out, please refer to one of the
103 * variants that allow passing an argument list.
105 * @param command String specifying the shell expression to be executed.
106 * @param res (Out parameter) Store information about the termination
107 * state in this struct.
109 * @returns Result of \c stdout. Note that due to the use of \c
110 * popen, the correct way to collect stderr output as
111 * well is to use shell redirection inside the expression
114 std::string capture_exec (const std::string &command, ExecResult &res)
115 { return capture_exec<const std::string &>(command, res, capture_flag::dflt); }
117 /** @brief Instantiation of \c capture_exec for argument lists. The
118 * pipestream used to run the command will not shell out.
119 * One of \c out or \c err must be set.
121 * @param command List of \c char* specifying the \c argv array of the
122 * command to run. Note that the binary to executed is
123 * assumed to be present at index 0 and that the input
124 * is properly \c NULL terminated.
125 * @param res (Out parameter) Store information about the termination
126 * state in this struct.
127 * @param flags Runtime control flags (stdio streams, environment, path
130 * @returns Captured output, combined into one string.
132 std::string capture_exec (const char *const *command, ExecResult &res,
134 { return capture_exec<const char *const *>(command, res, flags); }
136 /** @brief Instantiation of \c capture_exec for argument lists. The
137 * pipestream used to run the command will not shell out.
138 * One of \c out or \c err must be set.
140 * @param command String vector specifying the \c argv array of the
141 * command to run. Note that the binary to executed is
142 * assumed to be present at index 0.
143 * @param res (Out parameter) Store information about the termination
144 * state in this struct.
145 * @param flags Runtime control flags (stdio streams, environment, path
148 * @returns Captured output, combined into one string.
150 std::string capture_exec (const std::vector<std::string> &command, ExecResult &res,
152 { return capture_exec<const std::vector<std::string> &> (command, res, flags); }
154 #define PIPE_CTOR_FAIL(where) \
156 throw EXCEPTION (pipestream_error, \
157 std::string (where) + ": error " \
158 + I2n::to_string (errno) \
159 + " (" + std::string (strerror (errno)) + ")"); \
162 /** @brief Convert a string vector to a refcounted \c char**
163 * that is \c NULL terminated for use with e. g. \c execve(2).
165 * @param command List of arguments including the binary at index 0.
167 * @returns A \c boost::shared_array of pointers to the
168 * arguments plus a trailing \c NULL. Note that
169 * while the array itself is refcounted, the
170 * pointees are assumed owned by the caller and
171 * *not copyied*. I. e. they lose validity if the
172 * original strings are freed.
174 static boost::shared_array <char *>
175 mk_argv (const std::vector<std::string> &command)
180 ret = new char *[command.size () * sizeof (ret[0]) + 1];
181 } catch (std::bad_alloc &) {
182 return boost::shared_array<char *> ();
186 BOOST_FOREACH(const std::string &arg, command) {
188 * Casting away constness is safe since the data is always
189 * kept alive until after exec().
191 ret [cur++] = const_cast<char *> (arg.c_str ());
196 return boost::shared_array<char *> (ret);
199 /** @brief Helper for redirecting a file descriptor to \c /dev/null.
200 * This will only acquire an fd the first time it is called
201 * or if it is called after unsuccessfully attempting to
204 * @param fd The open file descriptor to operate on.
205 * @param save_errno Out parameter: stores errno here after a syscall failure.
207 * @returns \c true on success, \c false otherwise (the call to
208 * either \c open(2) or \c dup2(2) failed), with errno
209 * communicated through saved_errno.
212 redirect_devnull (const int fd, int &save_errno)
214 static int nullfd = -1;
217 if (nullfd == -1 && (nullfd = open ("/dev/null", O_RDWR)) == -1) {
223 if (dup2 (nullfd, fd) == -1) {
231 /** @brief Helper aggregating common code for the shell-free ctors.
233 * @param argv Argument list prepared for \c execve(2).
234 * @param flags Control the runtime behavior wrt. stdio streams, \c
235 * *envp, and path search. One of \c collect_out or
236 * \c collect_err is mandatory. All other flags are
237 * optional. Pipebuf creation with fail with \c EINVAL
238 * if that constraint is violated.
240 * @returns A \c FILE* handle for streaming if successful, \c NULL
243 * Error handling strategy:
245 * - receive all errors from child as ints through a cloexec pipe;
246 * - in the child, write error conditions always to pipe first,
247 * then try to emit a more verbose log message;
248 * - in the parent, throw on error indicating the child errno.
250 * Note that the error-pipe approach is robust due to guarantees by both
251 * standard (POSIX) and implementation (Linux) of pipes: The read(2) from
252 * the error channel will block until the pipe is either closed or written to;
253 * hence no need to check for EAGAIN. Those writes are guaranteed to be atomic
254 * because sizeof(errno) is less than PIPE_BUF; hence we can disregard EINTR. A
255 * pipe whose write end (i.e. in the child) has been closed (by the kernel
256 * because execve(2) was successful) will always indicate EOF by returning
257 * zero, hence we know precisely whether everything went well or not. Cf.
258 * pipe(7), sections “I/O on pipes and FIFOs” and “PIPE_BUF”, as well as
259 * Kerrisk (2010), section 44.10, p. 917f.
261 std::pair <pid_t, FILE *>
262 inpipebuf::init_without_shell (const char *const *argv,
263 const int flags) const
265 FILE *pipeobj = NULL;
266 int pipefd [2]; /* for reading output from the child */
267 int errfd [2]; /* for determining a successful exec() */
268 sigset_t oldmask, newmask;
269 char *const *envp = flags & capture_flag::env_passthru ? environ : NULL;
271 if (!(flags & capture_flag::collect_any))
274 PIPE_CTOR_FAIL("ctor");
278 * The error pipe must be openend with *O_CLOEXEC* set. We also open
279 * the data pipe with close-on-exec and remove that bit only in the child.
280 * The rationale is preventing the read fd from passed on if the parent
281 * later re-forks another child: we intend it to be read from this (master)
285 if ( ::pipe2 (pipefd, O_CLOEXEC) == -1
286 || ::pipe2 (errfd , O_CLOEXEC) == -1) {
287 PIPE_CTOR_FAIL("pipe2");
290 sigfillset (&newmask);
291 sigprocmask (SIG_SETMASK, &newmask, &oldmask);
294 pid_t childpid = fork ();
297 sigprocmask (SIG_SETMASK, &oldmask, NULL);
298 PIPE_CTOR_FAIL("fork");
303 * Close read ends of error and data channels: the child is assumed
304 * to write exclusively.
310 * Remove cloexec bit from the write end of the pipe (this is the
311 * only flag with F_SETFD).
313 fcntl (pipefd [1], F_SETFD, 0);
318 * Assign /dev/null if asked to close one of the streams, else
319 * dup() it onto the pipe.
321 if (!(flags & capture_flag::collect_out))
323 if (!redirect_devnull (STDOUT_FILENO, save_errno))
325 (void)write (errfd [1], (char *)&save_errno, sizeof(save_errno));
329 else if (dup2 (pipefd[1], STDOUT_FILENO) == -1)
331 (void)write (errfd [1], (char *)&save_errno, sizeof(save_errno));
335 if (!(flags & capture_flag::collect_err))
337 if (!redirect_devnull (STDERR_FILENO, save_errno))
339 (void)write (errfd [1], (char *)&save_errno, sizeof(save_errno));
343 else if (dup2 (pipefd[1], STDERR_FILENO) == -1)
345 (void)write (errfd [1], (char *)&save_errno, sizeof(save_errno));
350 * Close the write end of the pipe now that we have dup()’ed it
351 * onto the stdio fds. The parent will now receive EOF on the pipe
352 * when these fds are both closed.
357 * Stop blocking signals so the child starts out with a sane
360 sigprocmask (SIG_SETMASK, &oldmask, NULL);
363 if (flags & capture_flag::search_path) {
364 execvpe (argv [0], const_cast <char *const *>(argv), envp);
366 execve (argv [0], const_cast <char *const *>(argv), envp);
370 * At this point, the call to execv[p]e() failed. Thus the error
371 * pipe is still opened and we forward the errno through it.
373 (void)write (errfd [1], (char *)&errno, sizeof(errno));
383 * The parent is assumed to only consume data from either pipe, never
390 * Check whether the child exec()’ed by reading from the error pipe.
391 * The call to read(2) will block, uninterruptible due to signals being
392 * blocked. If all went well, the read(2) will return zero bytes and we can
393 * ditch the error channel.
395 * Otherwise either the read(2) failed or we actually received something
396 * through the error pipe. Both cases are treated as errors and cause an
397 * exit from the ctor.
399 char buf [sizeof (errno)];
401 memset (buf, 0, sizeof (buf));
403 if ((ret = read (errfd [0], buf, sizeof (buf))) != 0) {
406 sigprocmask (SIG_SETMASK, &oldmask, NULL);
409 PIPE_CTOR_FAIL("read");
412 * We received data on the error channel indicating the child
413 * process never successfully exec()’ed. We grab the error code
414 * from the buffer and bail.
416 errno = *((int *)&buf[0]);
417 PIPE_CTOR_FAIL("child failed to exec()");
422 * read(2) yielded zero bytes; it’s safe to use the pipe so close our end
427 sigprocmask (SIG_SETMASK, &oldmask, NULL);
430 if ((pipeobj = fdopen (pipefd [0], "r")) == NULL) {
432 PIPE_CTOR_FAIL("fdopen");
435 return std::make_pair (childpid, pipeobj);
438 inpipebuf::inpipebuf(const char *const *command,
440 : pipe (NULL) /* brr: shadowing global ident */
445 if (command == NULL || command [0] == NULL) {
446 PIPE_CTOR_FAIL("command");
449 std::pair <pid_t, FILE *> tmp = this->init_without_shell (command, flags);
450 this->pid = tmp.first; /* no std::tie :/ */
451 this->pipe = tmp.second;
453 setg (&buffer, &buffer, &buffer);
456 inpipebuf::inpipebuf(const std::vector<std::string> &command,
458 : pipe (NULL) /* brr: shadowing global ident */
463 if (command.empty ()) {
464 PIPE_CTOR_FAIL("command");
467 const boost::shared_array <char *> argv = mk_argv (command);
469 PIPE_CTOR_FAIL("malloc");
472 std::pair <pid_t, FILE *> tmp =
473 this->init_without_shell (argv.get (), flags);
474 this->pid = tmp.first;
475 this->pipe = tmp.second;
477 setg (&buffer, &buffer, &buffer);
480 inpipebuf::inpipebuf(const std::string& command,
481 const int _ignored_flags)
486 pipe = popen (command.c_str(), "r");
488 throw EXCEPTION (pipestream_error, "can't open program or permission denied");
491 setg (&buffer, &buffer, &buffer);
494 inpipebuf::~inpipebuf()
502 status = pclose (pipe);
504 if (exit_status != NULL) {
505 *exit_status = status;
506 if (status_set != NULL) {
515 status = fclose (pipe);
517 if (exit_status != NULL) {
518 *exit_status = status; /* might be overwritten below */
519 if (status_set != NULL) {
526 while (waitpid (this->pid, &status, 0) == -1) {
527 if (errno != EINTR) {
532 if (status != 0 && exit_status != NULL) {
533 *exit_status = status; /* might overwrite pipe status above */
534 if (status_set != NULL) {
544 /** note: exit status only available after destruction */
545 void inpipebuf::store_exit_status(bool *_status_set, int *_exit_status)
547 status_set = _status_set;
548 exit_status = _exit_status;
551 inpipebuf::int_type inpipebuf::underflow()
553 if (gptr() < egptr())
554 return traits_type::to_int_type(*gptr());
556 buffer = fgetc (pipe);
563 setg (&buffer, &buffer, &buffer+sizeof(char));
565 return traits_type::to_int_type(*gptr());
568 outpipebuf::outpipebuf(const std::string& command)
573 pipe = popen (command.c_str(), "w");
575 throw EXCEPTION (pipestream_error, "can't open program or permission denied");
578 outpipebuf::~outpipebuf()
581 int pclose_exit = pclose (pipe);
583 if (exit_status && pclose_exit != -1)
587 *exit_status = pclose_exit;
594 /** note: exit status only available after destruction */
595 void outpipebuf::store_exit_status(bool *_status_set, int *_exit_status)
597 status_set = _status_set;
598 exit_status = _exit_status;
601 outpipebuf::int_type outpipebuf::overflow(int_type c)
605 if (fputc(c,pipe)==EOF)
611 std::streamsize outpipebuf::xsputn(const char* s, std::streamsize num)
613 return fwrite(s,num,1,pipe);