d3f1d3bad556fd7e8e7f283a096908ecf1a276cc
[libi2ncommon] / src / pipestream.cpp
1  /*
2 The software in this package is distributed under the GNU General
3 Public License version 2 (with a special exception described below).
4
5 A copy of GNU General Public License (GPL) is included in this distribution,
6 in the file COPYING.GPL.
7
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.
13
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.
16
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.
19 */
20 /***************************************************************************
21               inpipestream.cpp  -  C++ streambuffer wrapper 
22                              -------------------
23     begin                : Thu Dec 27 2001
24     copyright            : (C) 2001 by Intra2net AG
25  ***************************************************************************/
26
27 #include <errno.h>
28 #include <stdio.h>
29 #include <string.h>
30 #include <fcntl.h>
31 #include <sys/wait.h>
32 #include <unistd.h>
33
34 #include <streambuf>
35 #include <istream>
36 #include <ostream>
37 #include <cstdio>
38 #include <boost/foreach.hpp>
39 #include <boost/shared_array.hpp>
40
41 #include "exception.hxx"
42 #include "stringfunc.hxx"
43 #include "pipestream.hxx"
44
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
50  */
51 template <typename CmdT>
52 std::string capture_exec(CmdT command, ExecResult &rescode,
53                          const int flags)
54 {
55     std::string output;
56
57     bool exit_set = false;
58     int exit_status_waitpid;
59
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;
63
64     try
65     {
66         {
67             inpipestream ips(command, flags);
68
69             ips.store_exit_status(&exit_set, &exit_status_waitpid);
70
71             char buffer[2048];
72             while (ips.good())
73             {
74                 ips.read(buffer, sizeof(buffer));
75                 output.append(buffer, ips.gcount());
76             }
77         }
78
79         // exit_status_waitpid only valid after destruction of the inpipestream
80
81         if (exit_set)
82         {
83             rescode.normal_exit = WIFEXITED(exit_status_waitpid);
84             if (rescode.normal_exit)
85                 rescode.return_code = WEXITSTATUS(exit_status_waitpid);
86
87             rescode.terminated_by_signal = WIFSIGNALED(exit_status_waitpid);
88             if (rescode.terminated_by_signal)
89                 rescode.signal = WTERMSIG(exit_status_waitpid);
90         }
91     }
92     catch (pipestream_error &e)
93     {
94         rescode.error_message = e.what();
95     }
96
97     return output;
98 }
99
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.
104  *
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.
108  *
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
112  *                    passed.
113  */
114 std::string capture_exec (const std::string &command, ExecResult &res)
115 { return capture_exec<const std::string &>(command, res, capture_flag::dflt); }
116
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.
120  *
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
128  *                    lookup).
129  *
130  *  @returns          Captured output, combined into one string.
131  */
132 std::string capture_exec (const char *const *command, ExecResult &res,
133                           const int flags)
134 { return capture_exec<const char *const *>(command, res, flags); }
135
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.
139  *
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
146  *                    lookup).
147  *
148  *  @returns          Captured output, combined into one string.
149  */
150 std::string capture_exec (const std::vector<std::string> &command, ExecResult &res,
151                           const int flags)
152 { return capture_exec<const std::vector<std::string> &> (command, res, flags); }
153
154 #define PIPE_CTOR_FAIL(where) \
155     do { \
156         throw EXCEPTION (pipestream_error, \
157                          std::string (where) + ": error " \
158                          + I2n::to_string (errno) \
159                          + " (" + std::string (strerror (errno)) + ")"); \
160     } while (0)
161
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).
164  *
165  *  @param command    List of arguments including the binary at index 0.
166  *
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.
173  */
174 static boost::shared_array <char *>
175 mk_argv (const std::vector<std::string> &command)
176 {
177     char **ret = NULL;
178
179     try {
180         ret = new char *[command.size () * sizeof (ret[0]) + 1];
181     } catch (std::bad_alloc &) {
182         return boost::shared_array<char *> ();
183     }
184
185     size_t cur = 0;
186     BOOST_FOREACH(const std::string &arg, command) {
187         /*
188          * Casting away constness is safe since the data is always
189          * kept alive until after exec().
190          */
191         ret [cur++] = const_cast<char *> (arg.c_str ());
192     }
193
194     ret [cur] = NULL;
195
196     return boost::shared_array<char *> (ret);
197 }
198
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
202  *              acquire one.
203  *
204  *  @param fd         The open file descriptor to operate on.
205  *  @param save_errno Out parameter: stores errno here after a syscall failure.
206  *
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.
210  */
211 static bool
212 redirect_devnull (const int fd, int &save_errno)
213 {
214     static int nullfd = -1;
215     
216     errno = 0;
217     if (nullfd == -1 && (nullfd = open ("/dev/null", O_RDWR)) == -1) {
218         save_errno = errno;
219         return false;
220     }
221
222     errno = 0;
223     if (dup2 (nullfd, fd) == -1) {
224         save_errno = errno;
225         return false;
226     }
227
228     return true;
229 }
230
231 /** @brief      Helper aggregating common code for the shell-free ctors.
232  *
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.
239  *
240  *  @returns          A \c FILE* handle for streaming if successful, \c NULL
241  *                    otherwise.
242  *
243  * Error handling strategy:
244  *
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.
249  *
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.
260  */
261 std::pair <pid_t, FILE *>
262 inpipebuf::init_without_shell (const char *const *argv,
263                                const int flags) const
264 {
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;
270
271     if (!(flags & capture_flag::collect_any))
272     {
273         errno = EINVAL;
274         PIPE_CTOR_FAIL("ctor");
275     }
276
277     /*
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)
282      * process alone.
283      */
284     errno = 0;
285     if (   ::pipe2 (pipefd, O_CLOEXEC) == -1
286         || ::pipe2 (errfd , O_CLOEXEC) == -1) {
287         PIPE_CTOR_FAIL("pipe2");
288     }
289
290     sigfillset (&newmask);
291     sigprocmask (SIG_SETMASK, &newmask, &oldmask);
292
293     errno = 0;
294     pid_t childpid = fork ();
295     switch (childpid) {
296         case -1: {
297             sigprocmask (SIG_SETMASK, &oldmask, NULL);
298             PIPE_CTOR_FAIL("fork");
299             break;
300         }
301         case 0: {
302             /*
303              * Close read ends of error and data channels: the child is assumed
304              * to write exclusively.
305              */
306             close (pipefd [0]);
307             close (errfd  [0]);
308
309             /*
310              * Remove cloexec bit from the write end of the pipe (this is the
311              * only flag with F_SETFD).
312              */
313             fcntl (pipefd [1], F_SETFD, 0);
314
315             int save_errno = 0;
316
317             /*
318              * Assign /dev/null if asked to close one of the streams, else
319              * dup() it onto the pipe.
320              */
321             if (!(flags & capture_flag::collect_out))
322             {
323                 if (!redirect_devnull (STDOUT_FILENO, save_errno))
324                 {
325                     (void)write (errfd [1], (char *)&save_errno, sizeof(save_errno));
326                     exit (EXIT_FAILURE);
327                 }
328             }
329             else if (dup2 (pipefd[1], STDOUT_FILENO) == -1)
330             {
331                 (void)write (errfd [1], (char *)&save_errno, sizeof(save_errno));
332                 exit (EXIT_FAILURE);
333             }
334
335             if (!(flags & capture_flag::collect_err))
336             {
337                 if (!redirect_devnull (STDERR_FILENO, save_errno))
338                 {
339                     (void)write (errfd [1], (char *)&save_errno, sizeof(save_errno));
340                     exit (EXIT_FAILURE);
341                 }
342             }
343             else if (dup2 (pipefd[1], STDERR_FILENO) == -1)
344             {
345                 (void)write (errfd [1], (char *)&save_errno, sizeof(save_errno));
346                 exit (EXIT_FAILURE);
347             }
348
349             /*
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.
353              */
354             close (pipefd [1]);
355
356             /*
357              * Stop blocking signals so the child starts out with a sane
358              * environment.
359              */
360             sigprocmask (SIG_SETMASK, &oldmask, NULL);
361
362             errno = 0;
363             if (flags & capture_flag::search_path) {
364                 execvpe (argv [0], const_cast <char *const *>(argv), envp);
365             } else {
366                 execve (argv [0], const_cast <char *const *>(argv), envp);
367             }
368
369             /*
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.
372              */
373             (void)write (errfd [1], (char *)&errno, sizeof(errno));
374             exit (EXIT_FAILURE);
375             break;
376         }
377         default: {
378             break;
379         }
380     }
381
382     /*
383      * The parent is assumed to only consume data from either pipe, never
384      * write.
385      */
386     close (pipefd [1]);
387     close (errfd  [1]);
388
389     /*
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.
394      *
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.
398      */
399     char buf [sizeof (errno)];
400     int ret;
401     memset (buf, 0, sizeof (buf));
402     errno = 0;
403     if ((ret = read (errfd [0], buf, sizeof (buf))) != 0) {
404         close (pipefd [0]);
405         close (errfd  [0]);
406         sigprocmask (SIG_SETMASK, &oldmask, NULL);
407         if (ret == - 1) {
408             /* read(2) failed */
409             PIPE_CTOR_FAIL("read");
410         } else {
411             /*
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.
415              */
416             errno = *((int *)&buf[0]);
417             PIPE_CTOR_FAIL("child failed to exec()");
418         }
419     }
420
421     /*
422      * read(2) yielded zero bytes; it’s safe to use the pipe so close our end
423      * and continue.
424      */
425     close (errfd [0]);
426
427     sigprocmask (SIG_SETMASK, &oldmask, NULL);
428
429     errno = 0;
430     if ((pipeobj = fdopen (pipefd [0], "r")) == NULL) {
431         close (pipefd [0]);
432         PIPE_CTOR_FAIL("fdopen");
433     }
434
435     return std::make_pair (childpid, pipeobj);
436 }
437
438 inpipebuf::inpipebuf(const char *const *command,
439                      const int flags)
440     : pipe (NULL) /* brr: shadowing global ident */
441     , pid (-1)
442     , status_set (NULL)
443     , exit_status (NULL)
444 {
445     if (command == NULL || command [0] == NULL) {
446         PIPE_CTOR_FAIL("command");
447     }
448
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;
452
453     setg (&buffer, &buffer, &buffer);
454 }
455
456 inpipebuf::inpipebuf(const std::vector<std::string> &command,
457                      const int flags)
458     : pipe (NULL) /* brr: shadowing global ident */
459     , pid (-1)
460     , status_set (NULL)
461     , exit_status (NULL)
462 {
463     if (command.empty ()) {
464         PIPE_CTOR_FAIL("command");
465     }
466
467     const boost::shared_array <char *> argv = mk_argv (command);
468     if (!argv) {
469         PIPE_CTOR_FAIL("malloc");
470     }
471
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;
476
477     setg (&buffer, &buffer, &buffer);
478 }
479
480 inpipebuf::inpipebuf(const std::string& command,
481                      const int _ignored_flags)
482     : pid (-1)
483     , status_set (NULL)
484     , exit_status (NULL)
485 {
486     pipe = popen (command.c_str(), "r");
487     if (pipe == NULL)
488         throw EXCEPTION (pipestream_error, "can't open program or permission denied");
489
490     // force underflow
491     setg (&buffer, &buffer, &buffer);
492 }
493
494 inpipebuf::~inpipebuf()
495 {
496     if (pipe != NULL) {
497         int status;
498
499         if (this->pid == -1)
500         {
501             errno = 0;
502             status = pclose (pipe);
503             if (status != -1) {
504                 if (exit_status != NULL) {
505                     *exit_status = status;
506                     if (status_set != NULL) {
507                         *status_set = true;
508                     }
509                 }
510             }
511         }
512         else
513         {
514             errno = 0;
515             status = fclose (pipe);
516             if (status != EOF) {
517                 if (exit_status != NULL) {
518                     *exit_status = status; /* might be overwritten below */
519                     if (status_set != NULL) {
520                         *status_set = true;
521                     }
522                 }
523             }
524
525             errno = 0;
526             while (waitpid (this->pid, &status, 0) == -1) {
527                 if (errno != EINTR) {
528                     status = -1;
529                     break;
530                 }
531             }
532             if (status != 0 && exit_status != NULL) {
533                 *exit_status = status; /* might overwrite pipe status above */
534                 if (status_set != NULL) {
535                     *status_set = true;
536                 }
537             }
538         }
539
540         pipe = NULL;
541     }
542 }
543
544 /** note: exit status only available after destruction */
545 void inpipebuf::store_exit_status(bool *_status_set, int *_exit_status)
546
547     status_set = _status_set; 
548     exit_status = _exit_status; 
549 }
550
551 inpipebuf::int_type inpipebuf::underflow()
552 {
553     if (gptr() < egptr())
554         return traits_type::to_int_type(*gptr());
555
556     buffer = fgetc (pipe);
557     if (feof (pipe))
558     {
559         // ERROR or EOF
560         return EOF;
561     }
562
563     setg (&buffer, &buffer, &buffer+sizeof(char));
564
565     return traits_type::to_int_type(*gptr());
566 }
567
568 outpipebuf::outpipebuf(const std::string& command)
569 {
570     status_set = NULL;
571     exit_status = NULL;
572
573     pipe = popen (command.c_str(), "w");
574     if (pipe == NULL)
575         throw EXCEPTION (pipestream_error, "can't open program or permission denied");
576 }
577
578 outpipebuf::~outpipebuf()
579 {
580     if (pipe != NULL) {
581         int pclose_exit = pclose (pipe);
582
583         if (exit_status && pclose_exit != -1)
584         {
585             if (status_set)
586                 *status_set = true;
587             *exit_status = pclose_exit;
588         }
589
590         pipe = NULL;
591     }
592 }
593
594 /** note: exit status only available after destruction */
595 void outpipebuf::store_exit_status(bool *_status_set, int *_exit_status)
596
597     status_set = _status_set; 
598     exit_status = _exit_status; 
599 }
600
601 outpipebuf::int_type outpipebuf::overflow(int_type c)
602 {
603     if (c != EOF)
604     {
605         if (fputc(c,pipe)==EOF)
606             return EOF;
607     }
608     return c;
609 }
610
611 std::streamsize outpipebuf::xsputn(const char* s, std::streamsize num)
612 {
613     return fwrite(s,num,1,pipe);
614 }