LCOV - code coverage report
Current view: top level - cppprocess/cppprocess - process.cpp (source / functions) Hit Total Coverage
Test: coverage.info Lines: 246 546 45.1 %
Date: 2021-09-19 09:06:58 Functions: 51 87 58.6 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : // Copyright (c) 2013-2021  Made to Order Software Corp.  All Rights Reserved
       2             : //
       3             : // https://snapwebsites.org/project/eventdispatcher
       4             : // contact@m2osw.com
       5             : //
       6             : // This program is free software; you can redistribute it and/or modify
       7             : // it under the terms of the GNU General Public License as published by
       8             : // the Free Software Foundation; either version 2 of the License, or
       9             : // (at your option) any later version.
      10             : //
      11             : // This program is distributed in the hope that it will be useful,
      12             : // but WITHOUT ANY WARRANTY; without even the implied warranty of
      13             : // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      14             : // GNU General Public License for more details.
      15             : //
      16             : // You should have received a copy of the GNU General Public License along
      17             : // with this program; if not, write to the Free Software Foundation, Inc.,
      18             : // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
      19             : 
      20             : 
      21             : // self
      22             : //
      23             : #include    "cppprocess/process.h"
      24             : 
      25             : #include    "cppprocess/exception.h"
      26             : 
      27             : 
      28             : // eventdispatcher lib
      29             : //
      30             : 
      31             : 
      32             : // snaplogger lib
      33             : //
      34             : #include    <snaplogger/message.h>
      35             : 
      36             : 
      37             : // snapdev lib
      38             : //
      39             : #include    <snapdev/glob_to_list.h>
      40             : #include    <snapdev/join_strings.h>
      41             : #include    <snapdev/trim_string.h>
      42             : #include    <snapdev/not_reached.h>
      43             : 
      44             : 
      45             : // C lib
      46             : //
      47             : #include    <fcntl.h>
      48             : #include    <string.h>
      49             : #include    <signal.h>
      50             : 
      51             : 
      52             : // last include
      53             : //
      54             : #include    <snapdev/poison.h>
      55             : 
      56             : 
      57             : 
      58             : 
      59             : 
      60             : extern char ** environ;
      61             : 
      62             : namespace cppprocess
      63             : {
      64             : 
      65             : 
      66             : 
      67             : namespace
      68             : {
      69             : 
      70             : 
      71             : 
      72             : 
      73           3 : class direct_input_data
      74             :     : public ed::pipe_connection
      75             : {
      76             : public:
      77             :                             direct_input_data(process * p, buffer_t const & input);
      78             :                             direct_input_data(direct_input_data const &) = delete;
      79             :     direct_input_data &     operator = (direct_input_data const &) = delete;
      80             : 
      81             :     // pipe_connection implementation
      82             :     //
      83             :     virtual bool            is_writer() const override;
      84             :     virtual void            process_write() override;
      85             : 
      86             :     virtual void            process_error() override;
      87             :     virtual void            process_invalid() override;
      88             :     virtual void            process_hup() override;
      89             : 
      90             : private:
      91             :     process *               f_process = nullptr;
      92             :     buffer_t const &        f_input;
      93             :     std::size_t             f_pos = 0;
      94             : };
      95             : 
      96             : 
      97           3 : direct_input_data::direct_input_data(process * p, buffer_t const & input)
      98             :     : pipe_connection(ed::pipe_t::PIPE_CHILD_INPUT)
      99             :     , f_process(p)
     100           3 :     , f_input(input)
     101             : {
     102           3 :     set_name("direct_input_data");
     103           3 : }
     104             : 
     105             : 
     106           3 : bool direct_input_data::is_writer() const
     107             : {
     108           3 :     return f_pos < f_input.size();
     109             : }
     110             : 
     111             : 
     112           3 : void direct_input_data::process_write()
     113             : {
     114           3 :     std::size_t const size(f_input.size() - f_pos);
     115           3 :     if(size > 0)
     116             :     {
     117           3 :         ssize_t const r(write(f_input.data() + f_pos, size));
     118           3 :         if(r > 0)
     119             :         {
     120           3 :             f_pos += r;
     121             : 
     122           3 :             if(f_pos >= f_input.size())
     123             :             {
     124           3 :                 f_process->input_pipe_done();
     125             :             }
     126             :         }
     127             :     }
     128           3 : }
     129             : 
     130             : 
     131           0 : void direct_input_data::process_error()
     132             : {
     133           0 :     f_process->input_pipe_done();
     134           0 : }
     135             : 
     136             : 
     137           0 : void direct_input_data::process_invalid()
     138             : {
     139           0 :     f_process->input_pipe_done();
     140           0 : }
     141             : 
     142             : 
     143           0 : void direct_input_data::process_hup()
     144             : {
     145           0 :     f_process->input_pipe_done();
     146           0 : }
     147             : 
     148             : 
     149             : 
     150             : 
     151             : 
     152             : 
     153             : 
     154             : 
     155             : 
     156             : /** \brief A direct output to input pipe.
     157             :  *
     158             :  * When piping one command to another, then this pipe object gets used.
     159             :  * This pipe directly sends the output of the previous command to the
     160             :  * input of the next command.
     161             :  *
     162             :  * Internally, we may also use the tee_pipe which sends the output of
     163             :  * the previous command to the input of all the next commands.
     164             :  */
     165           2 : class direct_output_to_input_pipe
     166             :     : public ed::pipe_connection
     167             : {
     168             : public:
     169             :                     direct_output_to_input_pipe();
     170             : 
     171             :     // pipe_connection implementation
     172             :     //
     173             :     virtual void                forked() override;
     174             : 
     175             : private:
     176             : };
     177             : 
     178             : 
     179           2 : direct_output_to_input_pipe::direct_output_to_input_pipe()
     180           2 :     : pipe_connection(ed::pipe_t::PIPE_CHILD_OUTPUT)
     181             : {
     182           2 :     set_name("direct_output_to_input_pipe");
     183           2 : }
     184             : 
     185             : 
     186           2 : void direct_output_to_input_pipe::forked()
     187             : {
     188             :     // force a full close in this case
     189             :     //
     190           2 :     close();
     191           2 : }
     192             : 
     193             : 
     194             : 
     195             : 
     196             : 
     197             : 
     198             : 
     199           4 : class capture_output_pipe
     200             :     : public ed::pipe_connection
     201             : {
     202             : public:
     203             :                                 capture_output_pipe(process * p, buffer_t & output);
     204             :                                 capture_output_pipe(capture_output_pipe const &) = delete;
     205             :     capture_output_pipe &       operator = (capture_output_pipe const &) = delete;
     206             : 
     207             :     // pipe_connection implementation
     208             :     //
     209             :     virtual void                process_read() override;
     210             : 
     211             :     virtual void                process_error() override;
     212             :     virtual void                process_invalid() override;
     213             :     virtual void                process_hup() override;
     214             : 
     215             : private:
     216             :     process *                   f_process = nullptr;
     217             :     buffer_t &                  f_output;
     218             : };
     219             : 
     220             : 
     221           4 : capture_output_pipe::capture_output_pipe(process * p, buffer_t & output)
     222             :     : pipe_connection(ed::pipe_t::PIPE_CHILD_OUTPUT)
     223             :     , f_process(p)
     224           4 :     , f_output(output)
     225             : {
     226           4 :     set_name("capture_output_pipe");
     227           4 : }
     228             : 
     229             : 
     230           5 : void capture_output_pipe::process_read()
     231             : {
     232           5 :     if(get_socket() != -1)
     233             :     {
     234             :         // handle up to 64Kb at once
     235             :         //
     236           5 :         char buffer[1'024 * 64];
     237           5 :         errno = 0;
     238           5 :         ssize_t const r(read(&buffer[0], sizeof(buffer)));
     239           5 :         if(r < 0
     240           0 :         && errno != 0
     241           0 :         && errno != EAGAIN
     242           0 :         && errno != EWOULDBLOCK)
     243             :         {
     244           0 :             int const e(errno);
     245           0 :             SNAP_LOG_ERROR
     246           0 :                 << "an error occurred while reading from pipe (errno: "
     247             :                 << e
     248             :                 << " -- "
     249           0 :                 << strerror(e)
     250             :                 << ")."
     251             :                 << SNAP_LOG_SEND;
     252           0 :             process_error();
     253           0 :             return;
     254             :         }
     255             : 
     256           5 :         if(r > 0)
     257             :         {
     258             :             // append to output buffer
     259             :             //
     260           5 :             f_output.insert(f_output.end(), buffer, buffer + r);
     261             :         }
     262             :     }
     263             : 
     264             :     // process the next level
     265             :     //
     266           5 :     pipe_connection::process_read();
     267             : }
     268             : 
     269             : 
     270           0 : void capture_output_pipe::process_error()
     271             : {
     272           0 :     f_process->output_pipe_done(this);
     273           0 : }
     274             : 
     275             : 
     276           0 : void capture_output_pipe::process_invalid()
     277             : {
     278           0 :     f_process->output_pipe_done(this);
     279           0 : }
     280             : 
     281             : 
     282           4 : void capture_output_pipe::process_hup()
     283             : {
     284           4 :     f_process->output_pipe_done(this);
     285           4 : }
     286             : 
     287             : 
     288             : 
     289             : 
     290             : 
     291             : 
     292             : 
     293           0 : class buffered_pipe
     294             :     : public ed::pipe_connection
     295             : {
     296             : public:
     297             :                                 buffered_pipe();
     298             : 
     299             :     // connection
     300             :     virtual bool                is_writer() const override;
     301             : 
     302             :     // pipe implementation
     303             :     virtual ssize_t             write(void const * data, size_t length) override;
     304             :     virtual void                process_write() override;
     305             :     virtual void                process_hup() override;
     306             : 
     307             : private:
     308             :     std::vector<char>           f_output = std::vector<char>();
     309             :     size_t                      f_position = 0;
     310             : };
     311             : 
     312             : 
     313           0 : buffered_pipe::buffered_pipe()
     314           0 :     : pipe_connection(ed::pipe_t::PIPE_CHILD_OUTPUT)
     315             : {
     316           0 :     set_name("buffered_pipe");
     317           0 : }
     318             : 
     319             : 
     320           0 : bool buffered_pipe::is_writer() const
     321             : {
     322           0 :     return get_socket() != -1 && !f_output.empty();
     323             : }
     324             : 
     325             : 
     326           0 : ssize_t buffered_pipe::write(void const * data, size_t length)
     327             : {
     328           0 :     if(get_socket() == -1)
     329             :     {
     330           0 :         errno = EBADF;
     331           0 :         return -1;
     332             :     }
     333             : 
     334           0 :     if(data != nullptr && length > 0)
     335             :     {
     336           0 :         char const * d(reinterpret_cast<char const *>(data));
     337           0 :         f_output.insert(f_output.end(), d, d + length);
     338           0 :         return length;
     339             :     }
     340             : 
     341           0 :     return 0;
     342             : }
     343             : 
     344             : 
     345           0 : void buffered_pipe::process_write()
     346             : {
     347           0 :     if(get_socket() != -1)
     348             :     {
     349           0 :         errno = 0;
     350           0 :         ssize_t const r(pipe_connection::write(&f_output[f_position], f_output.size() - f_position));
     351           0 :         if(r > 0)
     352             :         {
     353             :             // some data was written
     354             :             //
     355           0 :             f_position += r;
     356           0 :             if(f_position >= f_output.size())
     357             :             {
     358           0 :                 f_output.clear();
     359           0 :                 f_position = 0;
     360           0 :                 process_empty_buffer();
     361             :             }
     362             :         }
     363           0 :         else if(r != 0 && errno != 0 && errno != EAGAIN && errno != EWOULDBLOCK)
     364             :         {
     365             :             // connection is considered bad, get rid of it
     366             :             //
     367           0 :             int const e(errno);
     368           0 :             SNAP_LOG_ERROR
     369           0 :                 << "an error occurred while writing to socket of \""
     370           0 :                 << get_name()
     371           0 :                 << "\" (errno: "
     372             :                 << e
     373             :                 << " -- "
     374           0 :                 << strerror(e)
     375             :                 << ")."
     376             :                 << SNAP_LOG_SEND;
     377           0 :             process_error();
     378           0 :             return;
     379             :         }
     380             :     }
     381             :     //else -- TBD: should we generate an error when the socket is not valid?
     382             : 
     383             :     // process next level too
     384             :     //
     385           0 :     pipe_connection::process_write();
     386             : }
     387             : 
     388             : 
     389           0 : void buffered_pipe::process_hup()
     390             : {
     391           0 :     close();
     392             : 
     393           0 :     pipe_connection::process_hup();
     394           0 : }
     395             : 
     396             : 
     397             : 
     398             : 
     399             : 
     400             : 
     401             : 
     402           0 : class tee_pipe
     403             :     : public ed::pipe_connection
     404             : {
     405             : public:
     406             :                                     tee_pipe(std::size_t const size);
     407             : 
     408             :     ed::pipe_connection::pointer_t  get_output_pipe(std::size_t idx);
     409             : 
     410             :     // pipe_connection
     411             :     //
     412             :     virtual void                    process_read() override;
     413             :     virtual void                    connection_added() override;
     414             :     virtual void                    connection_removed() override;
     415             : 
     416             : private:
     417             :     ed::communicator::pointer_t     f_communicator = ed::communicator::pointer_t();
     418             :     ed::pipe_connection::vector_t   f_output = ed::pipe_connection::vector_t();
     419             : };
     420             : 
     421             : 
     422           0 : tee_pipe::tee_pipe(std::size_t const size)
     423             :     : pipe_connection(ed::pipe_t::PIPE_CHILD_INPUT)
     424             :     , f_communicator(ed::communicator::instance())
     425           0 :     , f_output(size)
     426             : {
     427           0 :     set_name("tee_pipe");
     428             : 
     429           0 :     if(size == 0)
     430             :     {
     431           0 :         throw cppprocess_logic_error("tee_pipe constructor called with a size of zero is not supported");
     432             :     }
     433             : 
     434           0 :     for(std::size_t idx(0); idx < size; ++idx)
     435             :     {
     436           0 :         f_output[idx] = std::make_shared<buffered_pipe>();
     437             :     }
     438           0 : }
     439             : 
     440             : 
     441           0 : ed::pipe_connection::pointer_t tee_pipe::get_output_pipe(std::size_t idx)
     442             : {
     443           0 :     if(idx >= f_output.size())
     444             :     {
     445             :         throw cppprocess_out_of_range(
     446             :               "get_output_pipe() called with index "
     447           0 :             + std::to_string(idx)
     448           0 :             + ", which is out of allowed range: [0.."
     449           0 :             + std::to_string(f_output.size())
     450           0 :             + ").");
     451             :     }
     452             : 
     453           0 :     return f_output[idx];
     454             : }
     455             : 
     456             : 
     457           0 : void tee_pipe::process_read()
     458             : {
     459           0 :     if(get_socket() != -1)
     460             :     {
     461             :         // handle up to 64Kb at once
     462             :         //
     463           0 :         char buffer[1'024 * 64];
     464           0 :         errno = 0;
     465           0 :         ssize_t const r(read(&buffer[0], sizeof(buffer)));
     466           0 :         if(r < 0
     467           0 :         && errno != 0
     468           0 :         && errno != EAGAIN
     469           0 :         && errno != EWOULDBLOCK)
     470             :         {
     471             :             // this happens all the time (i.e. another process quits)
     472             :             // so we make it a debug and not a warning or an error...
     473             :             //
     474           0 :             int const e(errno);
     475           0 :             SNAP_LOG_DEBUG
     476           0 :                 << "an error occurred while reading from socket (errno: "
     477             :                 << e
     478             :                 << " -- "
     479           0 :                 << strerror(e)
     480             :                 << ")."
     481             :                 << SNAP_LOG_SEND;
     482           0 :             process_error();
     483           0 :             return;
     484             :         }
     485             : 
     486           0 :         if(r > 0)
     487             :         {
     488             :             // this is the T functionality, where we duplicate the data in
     489             :             // the input of each of the succeeded processes
     490             :             //
     491           0 :             for(auto & out : f_output)
     492             :             {
     493           0 :                 out->write(&buffer[0], r);
     494             :             }
     495             :         }
     496             :     }
     497             : 
     498             :     // process the next level
     499             :     //
     500           0 :     pipe_connection::process_read();
     501             : }
     502             : 
     503             : 
     504           0 : void tee_pipe::connection_added()
     505             : {
     506           0 :     for(auto & out : f_output)
     507             :     {
     508           0 :         f_communicator->add_connection(out);
     509             :     }
     510           0 : }
     511             : 
     512             : 
     513           0 : void tee_pipe::connection_removed()
     514             : {
     515           0 :     for(auto & out : f_output)
     516             :     {
     517           0 :         f_communicator->remove_connection(out);
     518             :     }
     519           0 : }
     520             : 
     521             : 
     522             : 
     523             : } // no name namespace
     524             : 
     525             : 
     526             : 
     527             : 
     528             : /** \class process
     529             :  * \brief A process class to run a process and get information about the results.
     530             :  *
     531             :  * This class is used to run processes. Especially, it can run with in and
     532             :  * out capabilities (i.e. piping) although this is generally not recommanded
     533             :  * because piping can block (if you do not send enough data, or do not read
     534             :  * enough data, then the pipes can get stuck.) We use a thread to read the
     535             :  * results. We do not currently expect that the use of this class will require
     536             :  * the input read to be necessary to know what needs to be written (i.e. in
     537             :  * most cases all we want is to convert a file [input] from one format to
     538             :  * another [output] avoiding reading/writing on disk.)
     539             :  *
     540             :  * The whole process, when using the interactive mode, is quite complicated
     541             :  * so I wrote the following diagram. As you can see, the loop of sending
     542             :  * and receiving data from the child process is fairly simple. Note that the
     543             :  * callback is called from the Output Thread, not the main process. This does
     544             :  * not make much of a difference because no other function can be running on
     545             :  * the main process when that happens. The output is blocked and thus the
     546             :  * output variable is safe. The input is not blocked but adding input was
     547             :  * made safe internally.
     548             :  *
     549             :  * \msc
     550             :  * hscale = "2";
     551             :  * a [label="Function"],b [label="Process"],c [label="Input Thread"],d [label="Output Thread"],e [label="Child Process"];
     552             :  *
     553             :  * a=>b [label="run()"];
     554             :  * b=>e [label="fork()"];
     555             :  * e->e [label="execvpe()"];
     556             :  * b=>c [label="pthread_create()"];
     557             :  * b=>d [label="pthread_create()"];
     558             :  * b=>e [label="wait() child's death"];
     559             :  *
     560             :  * --- [label="start repeat"];
     561             :  * c->e [label="write() (Input Data)"];
     562             :  * d<-e [label="read() (Output Data)"];
     563             :  * b<:d [label="output shared"];
     564             :  * a<<=d [label="output callback"];
     565             :  * a=>b [label="set_input()"];
     566             :  * b=>c [label="add input"];
     567             :  * --- [label="end repeat"];
     568             :  *
     569             :  * b<-e [label="child died"];
     570             :  * b->c [label="stop()"];
     571             :  * b<-c [label="stopped"];
     572             :  * b->d [label="stop()"];
     573             :  * b<-d [label="stopped"];
     574             :  * a<\<b [label="run()"];
     575             :  * \endmsc
     576             :  *
     577             :  * Using the add_next_process function, it is possible to pipe the output
     578             :  * of one process as the input of the next process. In other words, this
     579             :  * class allows you to pipe any number of processes between each other.
     580             :  *
     581             :  * \code
     582             :  *     cppprocess:process a;
     583             :  *     cppprocess:process b;
     584             :  *     cppprocess:process c;
     585             :  *
     586             :  *     a.set_next_process(b);
     587             :  *     b.set_next_process(c);
     588             :  *
     589             :  *     a.start();       // runs `a | b | c`
     590             :  * \endcode
     591             :  *
     592             :  * When piping processes in this way, pipes are used and the more powerful
     593             :  * scheme is used (fork() + execvpe() instead of a simpler popen() or even
     594             :  * a system() call).
     595             :  *
     596             :  * Also, when piping processes, you can only add one input pipe to the
     597             :  * very first process and one output pipe to the very last process. You
     598             :  * can, however, add one error pipe to each process (i.e. so you can know
     599             :  * which process output such and such errors).
     600             :  *
     601             :  * When piping processes, you only call the start() function of
     602             :  * the first process. That will have the side effect of starting all the
     603             :  * following processes as expected.
     604             :  *
     605             :  * The feature includes a "tee" feature, which allows you to pipe the
     606             :  * output of one process as the input of any number of processes. This
     607             :  * is done by adding multiple processes as the next process of one
     608             :  * proces.
     609             :  *
     610             :  * \code
     611             :  *     cppprocess:process a;
     612             :  *     cppprocess:process b;
     613             :  *     cppprocess:process c;
     614             :  *     cppprocess:process c;
     615             :  *
     616             :  *     a.set_next_process(b);
     617             :  *     a.set_next_process(c);
     618             :  *     a.set_next_process(d);
     619             :  *
     620             :  *     a.start();
     621             :  *
     622             :  *     // equivalent to:
     623             :  *     //    a > data.tmp
     624             :  *     //    b < data.tmp
     625             :  *     //    c < data.tmp
     626             :  *     //    d < data.tmp
     627             :  *     // only we avoid the temporary file and b, c, d are run in parallel
     628             :  *     // note that b, c, d could be the same process with different args
     629             :  * \endcode
     630             :  */
     631             : 
     632             : 
     633             : /** \brief Initialize the process object.
     634             :  *
     635             :  * This function saves the name of the process. The name is generally a
     636             :  * static string and it is used to distinguish between processes when
     637             :  * managing several at once. The function makes a copy of the name.
     638             :  *
     639             :  * \note
     640             :  * The name of the process is not the command. See set_command().
     641             :  *
     642             :  * \param[in] name  The name of the process.
     643             :  *
     644             :  * \sa set_command()
     645             :  * \sa get_name()
     646             :  */
     647           8 : process::process(std::string const & name)
     648             :     : f_communicator(ed::communicator::instance())
     649           8 :     , f_name(name)
     650             : {
     651           8 : }
     652             : 
     653             : 
     654             : /** \brief Retrieve the name of this process object.
     655             :  *
     656             :  * This process object is given a name on creation. In most cases this is
     657             :  * a static name that is used to determine which process is which.
     658             :  *
     659             :  * \return The name of the process.
     660             :  */
     661           4 : std::string const & process::get_name() const
     662             : {
     663           4 :     return f_name;
     664             : }
     665             : 
     666             : 
     667             : /** \brief Set how the environment variables are defined in the process.
     668             :  *
     669             :  * By default all of the current process environment variables are
     670             :  * passed to the child process. If the child process is not 100% trustworthy,
     671             :  * it may be preferable to only pass a specific set of environment variables
     672             :  * (as added by the add_environ() function) to the child process.
     673             :  *
     674             :  * This function sets a flag to determine whether we want to force the
     675             :  * environment (true) to the list of variables added with the
     676             :  * add_environ() function or let our current process variables
     677             :  * flow through (false, the default).
     678             :  *
     679             :  * \param[in] forced  Whether the environment will be forced.
     680             :  *
     681             :  * \sa add_environ()
     682             :  * \sa get_forced_environment()
     683             :  */
     684           4 : void process::set_forced_environment(bool forced)
     685             : {
     686           4 :     f_forced_environment = forced;
     687           4 : }
     688             : 
     689             : 
     690             : /** \brief Check the current status of the forced environment flag.
     691             :  *
     692             :  * This function returns a copy of the forced environment flag. If true,
     693             :  * then the run() function will force the environment variables as
     694             :  * defined by add_environ() function instead of all the environment
     695             :  * variables of the calling process.
     696             :  *
     697             :  * \return The status of the forced environment flag.
     698             :  *
     699             :  * \sa add_environ()
     700             :  * \sa set_forced_environment()
     701             :  */
     702           6 : bool process::get_forced_environment() const
     703             : {
     704           6 :     return f_forced_environment;
     705             : }
     706             : 
     707             : 
     708             : /** \brief Define the command to run.
     709             :  *
     710             :  * The command name may be a full path or just the command filename.
     711             :  * (i.e. the `execvp()` function makes use of the PATH variable to find
     712             :  * the command on disk unless the \p command parameter includes a
     713             :  * slash character.)
     714             :  *
     715             :  * \warning
     716             :  * Do not add any arguments here. Instead, make sure to use the
     717             :  * add_argument() to add any number of arguments.
     718             :  *
     719             :  * If the process cannot be found, an error is generated at the time you
     720             :  * call the run() function.
     721             :  *
     722             :  * \param[in] command  The command to start the new process.
     723             :  *
     724             :  * \sa add_argument()
     725             :  * \sa get_command()
     726             :  */
     727           8 : void process::set_command(std::string const & command)
     728             : {
     729           8 :     f_command = command;
     730           8 : }
     731             : 
     732             : 
     733             : /** \brief Retrieve the command name & path.
     734             :  *
     735             :  * This function returns the command as set with the set_command() function.
     736             :  *
     737             :  * If the set_command() was never called, then the command is the
     738             :  * empty string at this point.
     739             :  *
     740             :  * \return The command name and path (the path is optional).
     741             :  *
     742             :  * \sa set_command()
     743             :  */
     744           7 : std::string const & process::get_command() const
     745             : {
     746           7 :     return f_command;
     747             : }
     748             : 
     749             : 
     750             : /** \brief Add an argument to the command line.
     751             :  *
     752             :  * This function adds one individual arguement to the command line.
     753             :  *
     754             :  * You have to add all the arguments in the right order.
     755             :  *
     756             :  * If you set the \p expand flag to true, then the function transforms the
     757             :  * argument into a list of file names and add those instead. If the
     758             :  * argument does not match any filename, then it is added as is.
     759             :  *
     760             :  * If the expansion fails, then the function prints out an error message
     761             :  * in the log and it returns false.
     762             :  *
     763             :  * \param[in] arg  The argument to be added.
     764             :  * \param[in] expand  Whether this argument includes glob characters to expand.
     765             :  *
     766             :  * \return true if the argument was added without issue.
     767             :  *
     768             :  * \sa get_arguments()
     769             :  */
     770          11 : bool process::add_argument(std::string const & arg, bool expand)
     771             : {
     772          11 :     if(!expand)
     773             :     {
     774          11 :         f_arguments.push_back(arg);
     775          11 :         return true;
     776             :     }
     777             : 
     778           0 :     if(!f_arguments.read_path<
     779             :               snap::glob_to_list_flag_t::GLOB_FLAG_BRACE
     780             :             , snap::glob_to_list_flag_t::GLOB_FLAG_PERIOD
     781           0 :             , snap::glob_to_list_flag_t::GLOB_FLAG_TILDE>(arg))
     782             :     {
     783           0 :         SNAP_LOG_ERROR
     784           0 :             << "an error occurred reading argument filenames from pattern \""
     785             :             << arg
     786             :             << "\": "
     787           0 :             << f_arguments.get_last_error_message()
     788           0 :             << " (errno: "
     789             :             << f_arguments.get_last_error_errno()
     790             :             << ", "
     791           0 :             << strerror(f_arguments.get_last_error_errno())
     792             :             << ")."
     793             :             << SNAP_LOG_SEND;
     794           0 :         return false;
     795             :     }
     796             : 
     797           0 :     return true;
     798             : }
     799             : 
     800             : 
     801             : /** \brief Return the current list of updatable arguments.
     802             :  *
     803             :  * This function returns a non-constant reference to the list of arguments
     804             :  * currently available in this process.
     805             :  *
     806             :  * This gives you the ability to go through the list and make changes.
     807             :  * This is often used when you want to run the same command with different
     808             :  * parameters (i.e. maybe a filename that changes between runs).
     809             :  *
     810             :  * It is important to keep in mind that if you expanded an argument, the
     811             :  * list may now include from 0 to any number of arguments as a replacement
     812             :  * to that one expanded argument.
     813             :  *
     814             :  * \return The list of arguments attached to this process.
     815             :  *
     816             :  * \sa add_argument()
     817             :  */
     818           6 : process::argument_list_t & process::get_arguments()
     819             : {
     820           6 :     return f_arguments;
     821             : }
     822             : 
     823             : 
     824             : /** \brief Return the current list of arguments.
     825             :  *
     826             :  * This function returns a constant reference to the list of arguments
     827             :  * currently available in this process.
     828             :  *
     829             :  * The list is grown by calling the add_argument() function. It can be
     830             :  * edited by calling the non-constant get_argument() and keeping a
     831             :  * reference to the list.
     832             :  *
     833             :  * If you asked for some arguments to be expanded, then they will be
     834             :  * in the expanded state (you will have lost the original pattern).
     835             :  *
     836             :  * \return The list of arguments attached to this process.
     837             :  *
     838             :  * \sa add_argument()
     839             :  */
     840           0 : process::argument_list_t const & process::get_arguments() const
     841             : {
     842           0 :     return f_arguments;
     843             : }
     844             : 
     845             : 
     846             : /** \brief Add an environment to the command line.
     847             :  *
     848             :  * This function adds a new environment variable for the child process to
     849             :  * use. In most cases this function doesn't get used.
     850             :  *
     851             :  * By default all the parent process (this current process) environment
     852             :  * variables are passed down to the child process. To avoid this behavior,
     853             :  * call the set_forced_environment() function before the run() function.
     854             :  *
     855             :  * An environment variable is defined as a name and a value as in:
     856             :  *
     857             :  * \code
     858             :  * add_environ("HOME", "/home/cppprocess");
     859             :  * \endcode
     860             :  *
     861             :  * If the value is set to the empty string, then the environment variable
     862             :  * is removed from the list.
     863             :  *
     864             :  * \param[in] name  The name of the environment variable to add.
     865             :  * \param[in] value  The new value of that environment variable.
     866             :  *
     867             :  * \sa get_environ()
     868             :  */
     869           0 : void process::add_environ(std::string const & name, std::string const & value)
     870             : {
     871           0 :     if(value.empty())
     872             :     {
     873           0 :         auto it(f_environment.find(name));
     874           0 :         if(it != f_environment.end())
     875             :         {
     876           0 :             f_environment.erase(it);
     877             :         }
     878             :     }
     879             :     else
     880             :     {
     881           0 :         f_environment[name] = value;
     882             :     }
     883           0 : }
     884             : 
     885             : 
     886             : /** \brief Get a reference to the current environment.
     887             :  *
     888             :  * This parameter is generally empty since the run() function will use the
     889             :  * calling process environment variables.
     890             :  *
     891             :  * It is possible, however, to hide the calling process environment and
     892             :  * use these variables instead. This is very good for all sorts of safety
     893             :  * reasons (i.e. not leak a secret key saved in a variable, for example).
     894             :  *
     895             :  * \return A constant reference to the map of environment parameters.
     896             :  *
     897             :  * \sa add_environ()
     898             :  */
     899           4 : process::environment_map_t const & process::get_environ() const
     900             : {
     901           4 :     return f_environment;
     902             : }
     903             : 
     904             : 
     905             : /** \brief Set the input filename.
     906             :  *
     907             :  * Instead of a pipe or capturing the input, you can also specify
     908             :  * a filename. This is similar to using the `< filename` syntax on
     909             :  * a shell command line.
     910             :  *
     911             :  * \param[in] filename  The name of the input file.
     912             :  */
     913           1 : void process::set_input_filename(std::string const & filename)
     914             : {
     915           1 :     f_input_filename = filename;
     916           1 : }
     917             : 
     918             : 
     919             : /** \brief Retrieve the input filename.
     920             :  *
     921             :  * This function returns a copy of the input filename. This is used
     922             :  * when you don't define an input pipe.
     923             :  *
     924             :  * \return The input filename.
     925             :  */
     926           0 : std::string const & process::get_input_filename() const
     927             : {
     928           0 :     return f_input_filename;
     929             : }
     930             : 
     931             : 
     932             : /** \brief The input to be sent to stdin.
     933             :  *
     934             :  * Add the input data to be written to the stdin pipe. Note that the input
     935             :  * cannot be modified once the run() command was called unless the mode
     936             :  * is PROCESS_MODE_INOUT_INTERACTIVE.
     937             :  *
     938             :  * Note that in all case, calling this function multiple times adds more
     939             :  * data to the input. It does not erase what was added before. The thread
     940             :  * may eat some of the input in which case it gets removed from the internal
     941             :  * variable.
     942             :  *
     943             :  * \note
     944             :  * The function is safe and adding new input from the output thread
     945             :  * (which happens in interactive mode) is protected.
     946             :  *
     947             :  * \param[in] input  The input of the process (stdin).
     948             :  *
     949             :  * \sa add_input(buffer_t const & input)
     950             :  */
     951           3 : void process::add_input(std::string const & input)
     952             : {
     953             :     // this is additive!
     954             :     //
     955           3 :     add_input(buffer_t(input.begin(), input.end()));
     956           3 : }
     957             : 
     958             : 
     959             : /** \brief Binary data to be sent to stdin.
     960             :  *
     961             :  * When the input data is binary, use the QByteArray instead of a std::string
     962             :  * so you are sure it gets properly added.
     963             :  *
     964             :  * Calling this function multiple times appends the new data to the
     965             :  * existing data.
     966             :  *
     967             :  * Please, see the other set_input() function for additional information.
     968             :  *
     969             :  * \note
     970             :  * When sending a std::string, remember that these are converted to UTF-8
     971             :  * which is not compatible with purely binary data (i.e. UTF-8, for example,
     972             :  * does not allow for 0xFE and 0xFF.)
     973             :  *
     974             :  * \param[in] input  The input of the process (stdin).
     975             :  *
     976             :  * \sa add_input(std::string const & input)
     977             :  */
     978           3 : void process::add_input(buffer_t const & input)
     979             : {
     980             :     // this is additive!
     981             :     //
     982           3 :     f_input.insert(f_input.end(), input.begin(), input.end());
     983           3 : }
     984             : 
     985             : 
     986             : /** \brief Retrieve a copy of the input buffer as a string.
     987             :  *
     988             :  * This function returns the contents of the input buffer as a string.
     989             :  *
     990             :  * \return A copy of the input.
     991             :  *
     992             :  * \sa get_binary_input()
     993             :  */
     994           6 : std::string process::get_input(bool reset) const
     995             : {
     996           6 :     std::string input(reinterpret_cast<char const *>(f_input.data()), f_input.size());
     997           6 :     if(reset)
     998             :     {
     999           0 :         const_cast<process *>(this)->f_input.clear();
    1000             :     }
    1001           6 :     return input;
    1002             : }
    1003             : 
    1004             : 
    1005             : /** \brief Retrieve a copy of the input buffer.
    1006             :  *
    1007             :  * This function returns the contents of the input buffer. In most cases,
    1008             :  * you'll never need this function (you should know what you add to your
    1009             :  * command input).
    1010             :  *
    1011             :  * \return A copy of the input.
    1012             :  *
    1013             :  * \sa get_input()
    1014             :  */
    1015           6 : buffer_t process::get_binary_input(bool reset) const
    1016             : {
    1017           6 :     buffer_t const input(f_input);
    1018           6 :     if(reset)
    1019             :     {
    1020           0 :         const_cast<process *>(this)->f_input.clear();
    1021             :     }
    1022           6 :     return input;
    1023             : }
    1024             : 
    1025             : 
    1026             : /** \brief Setup a pipe to send the child input to.
    1027             :  *
    1028             :  * This function is used to setup a pipe to replace stdin of the process.
    1029             :  * You are expected to send data to that pipe and the child is expected
    1030             :  * to read from this pipe and process the data as expected.
    1031             :  *
    1032             :  * \warning
    1033             :  * Only the very first process in a list of processes can be assigned
    1034             :  * an input pipe. If other processes are given an input pipe, then
    1035             :  * the start() function will throw an error.
    1036             :  *
    1037             :  * \param[in] pipe  The pipe used to send data to the child process.
    1038             :  *
    1039             :  * \sa get_input_pipe()
    1040             :  */
    1041           0 : void process::set_input_pipe(ed::pipe_connection::pointer_t pipe)
    1042             : {
    1043           0 :     if(pipe->type() != ed::pipe_t::PIPE_CHILD_INPUT)
    1044             :     {
    1045           0 :         throw cppprocess_incorrect_pipe_type("incorrect pipe type, expected a PIPE_CHILD_INPUT type of pipe for the input.");
    1046             :     }
    1047             : 
    1048           0 :     f_input_pipe = pipe;
    1049           0 : }
    1050             : 
    1051             : 
    1052             : /** \brief Retrieve the child input pipe.
    1053             :  *
    1054             :  * This function returns a pointer to the input pipe. This pipe can be used
    1055             :  * to send data to the child process while it runs. It will send the data
    1056             :  * to the child's stdin stream.
    1057             :  *
    1058             :  * This pipe works with the eventdispatcher communicator so it is non-blocking
    1059             :  * and you can add data as space becomes available in the pipe without getting
    1060             :  * stuck doing so. This means you can also handle the output and error pipes
    1061             :  * as they get filled up.
    1062             :  *
    1063             :  * \return A pointer to the pipe connection used for the process input.
    1064             :  *
    1065             :  * \sa set_input_pipe()
    1066             :  */
    1067           6 : ed::pipe_connection::pointer_t process::get_input_pipe() const
    1068             : {
    1069           6 :     return f_input_pipe;
    1070             : }
    1071             : 
    1072             : 
    1073             : /** \brief Set the output filename.
    1074             :  *
    1075             :  * Instead of a pipe or capturing the output, you can also specify
    1076             :  * a filename. This is similar to using the `> filename` syntax on
    1077             :  * a shell command line.
    1078             :  *
    1079             :  * \param[in] filename  The name of the output file.
    1080             :  */
    1081           1 : void process::set_output_filename(std::string const & filename)
    1082             : {
    1083           1 :     f_output_filename = filename;
    1084           1 : }
    1085             : 
    1086             : 
    1087             : /** \brief Retrieve the output filename.
    1088             :  *
    1089             :  * This function returns a copy of the output filename. This is used
    1090             :  * when you don't define an output pipe.
    1091             :  *
    1092             :  * \return The output filename.
    1093             :  */
    1094           0 : std::string const & process::get_output_filename() const
    1095             : {
    1096           0 :     return f_output_filename;
    1097             : }
    1098             : 
    1099             : 
    1100             : /** \brief Setup capture of output.
    1101             :  *
    1102             :  * By default, the output is set to stdout or an output pipe. You can also
    1103             :  * request that the process class capture the output to a buffer by calling
    1104             :  * this function with true.
    1105             :  *
    1106             :  * If you setup an output pipe, this flag is ignored.
    1107             :  *
    1108             :  * \param[in] capture  Whether to capture the output (true) or not (false).
    1109             :  */
    1110           3 : void process::set_capture_output(bool capture)
    1111             : {
    1112           3 :     f_capture_output = capture;
    1113           3 : }
    1114             : 
    1115             : 
    1116             : /** \brief Check whether the output will be captured or not.
    1117             :  *
    1118             :  * This function returns the capture flag.
    1119             :  *
    1120             :  * When the capture flag is true, the process output will be captured in an
    1121             :  * internal buffer.
    1122             :  *
    1123             :  * \return true if the output is to be captured by the process object.
    1124             :  */
    1125           5 : bool process::get_capture_output() const
    1126             : {
    1127           5 :     return f_capture_output;
    1128             : }
    1129             : 
    1130             : 
    1131             : /** \brief Set output capture done callback.
    1132             :  *
    1133             :  * This function lets you define a callback which gets called whenever the
    1134             :  * whole output is received.
    1135             :  *
    1136             :  * \warning
    1137             :  * You cannot use this function when you use your own output pipe.
    1138             :  *
    1139             :  * \param[in] callback  The callback to call when SIGCHLD is received.
    1140             :  */
    1141           0 : void process::set_output_capture_done(capture_done_t callback)
    1142             : {
    1143           0 :     f_output_done_callback = callback;
    1144           0 : }
    1145             : 
    1146             : 
    1147             : /** \brief Read the output of the command.
    1148             :  *
    1149             :  * This function reads the output of the process. This function converts
    1150             :  * the output to UTF-8. Note that if some bytes are missing this function
    1151             :  * is likely to fail. If you are reading the data little by little as it
    1152             :  * comes in, you may want to use the get_binary_output() function
    1153             :  * instead. That way you can detect characters such as the "\n" and at
    1154             :  * that point convert the data from the previous "\n" you found in the
    1155             :  * buffer to that new "\n". This will generate valid UTF-8 strings.
    1156             :  *
    1157             :  * This function is most often used by users of commands that process
    1158             :  * one given input and generate one given output all at once.
    1159             :  *
    1160             :  * \param[in] reset  Whether the output so far should be cleared.
    1161             :  *
    1162             :  * \return The current output buffer.
    1163             :  *
    1164             :  * \sa get_binary_output()
    1165             :  */
    1166           9 : std::string process::get_output(bool reset) const
    1167             : {
    1168           9 :     std::string const output(reinterpret_cast<char const *>(f_output.data()), f_output.size());
    1169           9 :     if(reset)
    1170             :     {
    1171           0 :         const_cast<process *>(this)->f_output.clear();
    1172             :     }
    1173           9 :     return output;
    1174             : }
    1175             : 
    1176             : 
    1177             : /** \brief Get the trimmed output.
    1178             :  *
    1179             :  * The get_output() function returns the output as is, with all the
    1180             :  * characters. Quite often, though, you do not want the ending `'\n'`,
    1181             :  * introductory spaces or tabs, or even multiple spaces when aligned
    1182             :  * column output is used by the process.
    1183             :  *
    1184             :  * This function can be used to trimmed all of that junk for you. It
    1185             :  * will always remove the starting and ending spaces and new line,
    1186             :  * carriage return characters.
    1187             :  *
    1188             :  * When \p inside is true, it also replaces multiple spaces within
    1189             :  * the string in a single space. This feature also replaces all spaces
    1190             :  * with 0x20 (`' '`).
    1191             :  *
    1192             :  * \param[in] inside  Whether to remove double, triple, etc. spaces inside
    1193             :  * the string.
    1194             :  * \param[in] reset  Whether to reset the value after this call.
    1195             :  *
    1196             :  * \return The trimmed output string.
    1197             :  *
    1198             :  * \sa snap::trim_string() (in snapdev)
    1199             :  */
    1200           2 : std::string process::get_trimmed_output(bool inside, bool reset) const
    1201             : {
    1202           2 :     return snap::trim_string(get_output(reset), true, true, inside);
    1203             : }
    1204             : 
    1205             : 
    1206             : /** \brief Read the output of the command as a binary buffer.
    1207             :  *
    1208             :  * This function reads the output of the process in binary (untouched).
    1209             :  *
    1210             :  * This function does not fail like the get_output() which attempts to
    1211             :  * convert the output of the function to UTF-8. Also the output of the
    1212             :  * command may not be UTF-8 in which case you would have to use the
    1213             :  * binary version and use a different conversion.
    1214             :  *
    1215             :  * \param[in] reset  Whether the output so far should be cleared.
    1216             :  *
    1217             :  * \return The current output buffer.
    1218             :  *
    1219             :  * \sa get_output()
    1220             :  */
    1221           5 : buffer_t process::get_binary_output(bool reset) const
    1222             : {
    1223           5 :     buffer_t const output(f_output);
    1224           5 :     if(reset)
    1225             :     {
    1226           0 :         const_cast<process *>(this)->f_output.clear();
    1227             :     }
    1228           5 :     return output;
    1229             : }
    1230             : 
    1231             : 
    1232             : /** \brief Setup a pipe where the process output is to be written.
    1233             :  *
    1234             :  * This function is used to setup a pipe which will receive data from
    1235             :  * the stdout of the command being started by the process object.
    1236             :  *
    1237             :  * The pipe is going to be setup as non-blocking, which means you can
    1238             :  * attempt a very large read (pipes on Linux are generally supporting
    1239             :  * about 64Kb of data) and your process won't be blocked if the amount
    1240             :  * of data is smaller that what you requested.
    1241             :  *
    1242             :  * \warning
    1243             :  * Only the very last process or a list of piped processes can be
    1244             :  * assigned an output pipe.
    1245             :  *
    1246             :  * \param[in] pipe  The pipe to attach to this process output.
    1247             :  *
    1248             :  * \sa get_output_pipe()
    1249             :  */
    1250           0 : void process::set_output_pipe(ed::pipe_connection::pointer_t pipe)
    1251             : {
    1252           0 :     if(pipe->type() != ed::pipe_t::PIPE_CHILD_OUTPUT)
    1253             :     {
    1254           0 :         throw cppprocess_incorrect_pipe_type("incorrect pipe type, expected a PIPE_CHILD_OUTPUT type of pipe for the output.");
    1255             :     }
    1256             : 
    1257           0 :     f_output_pipe = pipe;
    1258           0 : }
    1259             : 
    1260             : 
    1261             : /** \brief Retrieve the pointer to the output pipe.
    1262             :  *
    1263             :  * This function retrieves the pointer of the current output pipe.
    1264             :  * By default, this is a null pointer.
    1265             :  *
    1266             :  * \return The callback interface pointer.
    1267             :  *
    1268             :  * \sa set_output_pipe()
    1269             :  */
    1270           3 : ed::pipe_connection::pointer_t process::get_output_pipe() const
    1271             : {
    1272           3 :     return f_output_pipe;
    1273             : }
    1274             : 
    1275             : 
    1276             : /** \brief Pipe the output of this process to the next process.
    1277             :  *
    1278             :  * This function is used to pipe processes one after the other.
    1279             :  *
    1280             :  * The next process receives as input the output of this process,
    1281             :  * in effect creating a pipeline of Unix processes.
    1282             :  *
    1283             :  * The function is called "add" (next process) because you can
    1284             :  * pipe the output of one process to any number of processes'
    1285             :  * input pipe. This is done by one of our internal pipe object
    1286             :  * which is capable of such a feat.
    1287             :  *
    1288             :  * \note
    1289             :  * The pipes created in this case are created internally and you
    1290             :  * have no direct or indirect access to them except from within
    1291             :  * the processes added here.
    1292             :  *
    1293             :  * \param[in] next  A process that will receive the output of this
    1294             :  * process as input.
    1295             :  */
    1296           2 : void process::add_next_process(pointer_t next)
    1297             : {
    1298           2 :     f_next.push_back(next);
    1299           2 : }
    1300             : 
    1301             : 
    1302             : /** \brief Clear the list of next processes.
    1303             :  *
    1304             :  * This function clears the list of all the next processes defined
    1305             :  * in this process, cutting off the pipeline.
    1306             :  */
    1307           0 : void process::clear_next_process()
    1308             : {
    1309           0 :     f_next.clear();
    1310           0 : }
    1311             : 
    1312             : 
    1313             : /** \brief Retrieve the list of next processes.
    1314             :  *
    1315             :  * This function returns the list of next processes as created by the
    1316             :  * add_next_process() function.
    1317             :  *
    1318             :  * A next process receives as input the output of this process--i.e.
    1319             :  * if creates a pair of piped processes. Any number of processes
    1320             :  * can be piped in this manner.
    1321             :  *
    1322             :  * When the list is empty, the output is instead sent to the output
    1323             :  * pipe connection or, if not such pipe is defined, to the output
    1324             :  * buffer which you can retrieve later.
    1325             :  *
    1326             :  * If there is more than one next process, then the process creates
    1327             :  * a process_tee class which is used to send the output of this
    1328             :  * process to all the following processes.
    1329             :  *
    1330             :  * \return The list of processes to run after this one.
    1331             :  */
    1332           3 : process::list_t process::get_next_processes() const
    1333             : {
    1334           3 :     return f_next;
    1335             : }
    1336             : 
    1337             : 
    1338             : /** \brief Set the error filename.
    1339             :  *
    1340             :  * Instead of a pipe or capturing the error, you can also specify
    1341             :  * a filename. This is similar to using the `2> filename` syntax on
    1342             :  * a shell command line.
    1343             :  *
    1344             :  * \param[in] filename  The name of the error file.
    1345             :  */
    1346           0 : void process::set_error_filename(std::string const & filename)
    1347             : {
    1348           0 :     f_error_filename = filename;
    1349           0 : }
    1350             : 
    1351             : 
    1352             : /** \brief Retrieve the error filename.
    1353             :  *
    1354             :  * This function returns a copy of the error filename. This is used
    1355             :  * when you don't define an error pipe.
    1356             :  *
    1357             :  * \return The error filename.
    1358             :  */
    1359           0 : std::string const & process::get_error_filename() const
    1360             : {
    1361           0 :     return f_error_filename;
    1362             : }
    1363             : 
    1364             : 
    1365             : /** \brief Setup capture of the error stream.
    1366             :  *
    1367             :  * By default, the error stream is set to stderr. You can also request that
    1368             :  * the process object captures the error stream to a buffer by calling
    1369             :  * this function with true.
    1370             :  *
    1371             :  * If you setup an error pipe, this flag is ignored.
    1372             :  *
    1373             :  * \param[in] capture  Whether to capture the error stream (true) or not (false).
    1374             :  */
    1375           1 : void process::set_capture_error(bool capture)
    1376             : {
    1377           1 :     f_capture_error = capture;
    1378           1 : }
    1379             : 
    1380             : 
    1381             : /** \brief Check whether the error stream will be captured or not.
    1382             :  *
    1383             :  * This function returns the capture flag for the error stream.
    1384             :  *
    1385             :  * When the capture flag is true, the process error stream will be captured
    1386             :  * in an internal buffer.
    1387             :  *
    1388             :  * \return true if the error stream is to be captured by the process object.
    1389             :  */
    1390           2 : bool process::get_capture_error() const
    1391             : {
    1392           2 :     return f_capture_error;
    1393             : }
    1394             : 
    1395             : 
    1396             : /** \brief Read the error output of the command.
    1397             :  *
    1398             :  * This function reads the error output stream of the process. This
    1399             :  * function converts the output to UTF-8. Note that if some bytes are
    1400             :  * missing this function is likely to fail. If you are reading the
    1401             :  * data little by little as it comes in, you may want to use the
    1402             :  * get_binary_output() function instead. That way you can detect
    1403             :  * characters such as the "\n" and at that point convert the data
    1404             :  * from the previous "\n" you found in the buffer to that new "\n".
    1405             :  * This will generate valid UTF-8 strings.
    1406             :  *
    1407             :  * This function is most often used when stderr is to be saved
    1408             :  * in a different file than the default.
    1409             :  *
    1410             :  * \todo
    1411             :  * Look at validating the UTF-8 data.
    1412             :  *
    1413             :  * \param[in] reset  Whether the error output so far should be cleared.
    1414             :  *
    1415             :  * \return The current error output buffer.
    1416             :  *
    1417             :  * \sa get_binary_error()
    1418             :  */
    1419           6 : std::string process::get_error(bool reset) const
    1420             : {
    1421           6 :     std::string const error(reinterpret_cast<char const *>(f_error.data()), f_error.size());
    1422           6 :     if(reset)
    1423             :     {
    1424           0 :         const_cast<process *>(this)->f_error.clear();
    1425             :     }
    1426           6 :     return error;
    1427             : }
    1428             : 
    1429             : 
    1430             : /** \brief Read the error output of the command as a binary buffer.
    1431             :  *
    1432             :  * This function reads the error output of the process in binary (untouched).
    1433             :  *
    1434             :  * This function does not fail like get_error() which attempts to
    1435             :  * convert the output of the function to UTF-8. Also the error output
    1436             :  * of the command may not be UTF-8 in which case you would have to use
    1437             :  * the binary version and use a different conversion.
    1438             :  *
    1439             :  * \param[in] reset  Whether the error output so far should be cleared.
    1440             :  *
    1441             :  * \return The current error output buffer.
    1442             :  *
    1443             :  * \sa get_error()
    1444             :  */
    1445           5 : buffer_t process::get_binary_error(bool reset) const
    1446             : {
    1447           5 :     buffer_t const error(f_error);
    1448           5 :     if(reset)
    1449             :     {
    1450           0 :         const_cast<process *>(this)->f_error.clear();
    1451             :     }
    1452           5 :     return error;
    1453             : }
    1454             : 
    1455             : 
    1456             : /** \brief Setup a pipe where the process errors are to be written.
    1457             :  *
    1458             :  * This function is used to setup a pipe which will receive data from
    1459             :  * the stderr of the command being started by the process object.
    1460             :  *
    1461             :  * The pipe is going to be setup as non-blocking, which means you can
    1462             :  * attempt a very large read (pipes on Linux are generally supporting
    1463             :  * about 64Kb of data) and your process won't be blocked if the amount
    1464             :  * of data is smaller than what you requested.
    1465             :  *
    1466             :  * \param[in] callback  The callback class that is called on output arrival.
    1467             :  *
    1468             :  * \sa get_error_pipe()
    1469             :  */
    1470           0 : void process::set_error_pipe(ed::pipe_connection::pointer_t pipe)
    1471             : {
    1472           0 :     if(pipe->type() != ed::pipe_t::PIPE_CHILD_OUTPUT)
    1473             :     {
    1474           0 :         throw cppprocess_incorrect_pipe_type("incorrect pipe type, expected a PIPE_CHILD_OUTPUT type of pipe for the error.");
    1475             :     }
    1476             : 
    1477           0 :     f_error_pipe = pipe;
    1478           0 : }
    1479             : 
    1480             : 
    1481             : /** \brief Retrieve the pointer to the error pipe.
    1482             :  *
    1483             :  * This function retrieves the pointer of the current error pipe.
    1484             :  * By default, this is a null pointer.
    1485             :  *
    1486             :  * \return The callback interface pointer.
    1487             :  *
    1488             :  * \sa set_error_pipe()
    1489             :  */
    1490           5 : ed::pipe_connection::pointer_t process::get_error_pipe() const
    1491             : {
    1492           5 :     return f_error_pipe;
    1493             : }
    1494             : 
    1495             : 
    1496             : /** \brief Start the process.
    1497             :  *
    1498             :  * This function creates all the necessary things that the process requires
    1499             :  * and start the command.
    1500             :  *
    1501             :  * If the function encounters problems before it can run the child process,
    1502             :  * it returns -1 instead.
    1503             :  *
    1504             :  * The function always uses `fork()` and `execvpe()`. That way we handle
    1505             :  * one single case, which is much easier to maintain. The process is started
    1506             :  * in the background. This function doesn't wait for the process to be done.
    1507             :  *
    1508             :  * The input can be a buffer where you add data using add_input(). It can
    1509             :  * also be setup with your own pipe_connection object. If neither is
    1510             :  * specified, the process is given your stdin as a default.
    1511             :  *
    1512             :  * The output can automatically be captured or you can setup your own
    1513             :  * pipe_connection object to receive the output. If neither is specified,
    1514             :  * the process is given your stdout as a default.
    1515             :  *
    1516             :  * Like the output, the error stream can be captured or sent to your own
    1517             :  * pipe. It otherwise defaults to stderr.
    1518             :  *
    1519             :  * If you are not using ed::communicator (or at least you did not call the
    1520             :  * ed::communicator::run() function), you can wait on the process with
    1521             :  * the wait() function. This function will call the ed::communicator::run()
    1522             :  * loop. If you supplied your own pipes, you'll want to make sure to close
    1523             :  * them and remove them from the ed::communicator once done with them
    1524             :  * otherwise the wait() function will be stuck forever. The SIGCHLD signal
    1525             :  * is also automatically handled by the wait() function.
    1526             :  *
    1527             :  * \return 0 on success or -1 if an error occurs.
    1528             :  *
    1529             :  * \sa wait()
    1530             :  * \sa add_input()
    1531             :  * \sa set_input_pipe()
    1532             :  * \sa set_capture_output()
    1533             :  * \sa get_output()
    1534             :  * \sa set_capture_error()
    1535             :  * \sa get_error()
    1536             :  */
    1537           6 : int process::start()
    1538             : {
    1539          12 :     if(start_process(
    1540          12 :               ed::pipe_connection::pointer_t()
    1541             :             , 0
    1542          18 :             , ed::pipe_connection::pointer_t()) != 0)
    1543             :     {
    1544           0 :         return -1;
    1545             :     }
    1546             : 
    1547           6 :     if(!f_next.empty())
    1548             :     {
    1549           2 :         if(f_next.size() != f_prepared_output.size())
    1550             :         {
    1551             :             // the prepare_output() should have generated an error already
    1552             :             // so we should never get here, hence the logic error
    1553             :             //
    1554             :             throw cppprocess_logic_error(
    1555             :                       "incorrect number of output pipes (expected "
    1556           0 :                     + std::to_string(f_next.size())
    1557           0 :                     + ", found "
    1558           0 :                     + std::to_string(f_prepared_output.size())
    1559           0 :                     + ")");
    1560             :         }
    1561             : 
    1562           2 :         int idx(0);
    1563           4 :         for(auto & n : f_next)
    1564             :         {
    1565           8 :             if(n->start_process(
    1566             :                       f_intermediate_output_pipe
    1567             :                     , idx
    1568           6 :                     , f_internal_input_pipe) != 0)
    1569             :             {
    1570           0 :                 return -1;
    1571             :             }
    1572           2 :             ++idx;
    1573             :         }
    1574             :     }
    1575             : 
    1576           6 :     if(f_intermediate_output_pipe != nullptr)
    1577             :     {
    1578           4 :         f_intermediate_output_pipe->forked();
    1579             :     }
    1580             : 
    1581           6 :     if(f_next.size() == 1)
    1582             :     {
    1583           4 :         pointer_t n(*f_next.begin());
    1584           2 :         while(n->f_next.size() == 1)
    1585             :         {
    1586           0 :             n = *n->f_next.begin();
    1587             :         }
    1588             : 
    1589           2 :         if(n->f_next.empty())
    1590             :         {
    1591             :             // we found the last item and no tee_pipe
    1592             :             //
    1593           2 :             if(n->f_intermediate_output_pipe != nullptr)
    1594             :             {
    1595           1 :                 n->f_intermediate_output_pipe->forked();
    1596             :             }
    1597             :         }
    1598             :     }
    1599             : 
    1600           6 :     return 0;
    1601             : }
    1602             : 
    1603             : 
    1604             : /** \brief Wait for the command to be done.
    1605             :  *
    1606             :  * If you are using the ed::communicator and start a command, you will
    1607             :  * receive an event whenever the command is done. However, if you are
    1608             :  * not using ed::comminocator, this function helps you in hiding the
    1609             :  * grueling details on how to handle the event loop just to wait for
    1610             :  * a command to run.
    1611             :  *
    1612             :  * \exception cppprocess_recursive_call
    1613             :  * However, if you use ed::communicator and are already in the run()
    1614             :  * function, you can't call this function. It will raise this exception
    1615             :  * if you tried to do so. Of course, it is assumed that you also called
    1616             :  * the start() function to actually start the process.
    1617             :  *
    1618             :  * \exception cppprocess_not_started
    1619             :  * If one of the processes was not started (this process or one of its
    1620             :  * next processes) then this exception is raised.
    1621             :  *
    1622             :  * \return The exit code from the command.
    1623             :  */
    1624           6 : int process::wait()
    1625             : {
    1626           6 :     if(f_communicator->is_running())
    1627             :     {
    1628           0 :         throw cppprocess_recursive_call("you already are in the communicator::run() function, you cannot call process::wait().");
    1629             :     }
    1630             : 
    1631           6 :     if(f_child == -1
    1632           6 :     || !f_running)
    1633             :     {
    1634           0 :         throw cppprocess_not_started("the process was not started or already died.");
    1635             :     }
    1636             : 
    1637          12 :     list_t n(f_next);
    1638           8 :     for(auto & it : n)
    1639             :     {
    1640           4 :         if(it->f_child == -1
    1641           2 :         || !it->f_running)
    1642             :         {
    1643           0 :             throw cppprocess_not_started("one of the next processes was not started or already died.");
    1644             :         }
    1645             : 
    1646           2 :         n.insert(n.end(), it->f_next.begin(), it->f_next.end());
    1647             :     }
    1648             : 
    1649          12 :     ed::signal_child::pointer_t child_signal(ed::signal_child::get_instance());
    1650             : 
    1651             :     // this object may not have a shared pointer so we can't add it to the
    1652             :     // `n` list; for this reason we have to have a special case, unfortunately
    1653             :     //
    1654          12 :     child_signal->add_listener(
    1655             :               f_child
    1656          12 :             , std::bind(&process::child_done, this, std::placeholders::_1));
    1657             : 
    1658           8 :     for(auto & it : n)
    1659             :     {
    1660           6 :         child_signal->add_listener(
    1661           2 :                   it->f_child
    1662           4 :                 , std::bind(&process::child_done, it.get(), std::placeholders::_1));
    1663             :     }
    1664             : 
    1665           6 :     f_communicator->run();
    1666             : 
    1667          12 :     return f_exit_code;
    1668             : }
    1669             : 
    1670             : 
    1671           8 : void process::child_done(ed::child_status status)
    1672             : {
    1673             :     // note that all the child_done() callbacks get called because the
    1674             :     // communicator does not (currently) have any idea of which one needs
    1675             :     // to be called so here we make sure we only handle the correct one
    1676             :     //
    1677             : #ifdef _DEBUG
    1678           8 :     if(status.child_pid() != f_child)
    1679             :     {
    1680             :         throw cppprocess_logic_error(
    1681             :             "child pid mismatch in process::child_done(),"
    1682             :             " please check that you used the correct PID when binding"
    1683           0 :             " this function.");
    1684             :     }
    1685             : #endif
    1686             : 
    1687           8 :     f_exit_code = status.exit_code();
    1688             : 
    1689           8 :     if(f_process_done != nullptr)
    1690             :     {
    1691           0 :         f_process_done(status);
    1692             :     }
    1693           8 : }
    1694             : 
    1695             : 
    1696           8 : int process::start_process(
    1697             :           ed::pipe_connection::pointer_t output_fifo
    1698             :         , int output_index
    1699             :         , ed::pipe_connection::pointer_t input_fifo)
    1700             : {
    1701           8 :     if(f_running)
    1702             :     {
    1703             :         // already running
    1704           0 :         return -1;
    1705             :     }
    1706             : 
    1707             :     // prepare the pipes
    1708             :     //
    1709           8 :     prepare_input(output_fifo);
    1710           8 :     prepare_output();
    1711           8 :     prepare_error();
    1712             : 
    1713           8 :     f_child = fork();
    1714           8 :     switch(f_child)
    1715             :     {
    1716           0 :     case -1:
    1717             :         // an error occurred
    1718             :         //
    1719           0 :         return -1;
    1720             : 
    1721           0 :     case 0:
    1722             :         // child
    1723             :         //
    1724             :         // we want to run the execvpe() command
    1725             :         //
    1726           0 :         execute_command(output_fifo, output_index, input_fifo);
    1727             : 
    1728             :         // the child can't safely return so just exit now
    1729             :         //
    1730           0 :         exit(1);
    1731             :         snap::NOT_REACHED();
    1732             :         return -1;
    1733             : 
    1734           8 :     default:
    1735             :         // parent
    1736             :         //
    1737           8 :         if(f_input_pipe != nullptr)
    1738             :         {
    1739           0 :             f_input_pipe->forked();
    1740             :         }
    1741           8 :         if(f_internal_input_pipe != nullptr)
    1742             :         {
    1743           3 :             f_internal_input_pipe->forked();
    1744             :         }
    1745           8 :         if(f_output_pipe != nullptr)
    1746             :         {
    1747           0 :             f_output_pipe->forked();
    1748             :         }
    1749             : 
    1750             : // this one is done outside, here it's too soon in the case of a pipeline
    1751             : // since we need both sides to create the next process
    1752             : //
    1753             : //        if(f_intermediate_output_pipe != nullptr)
    1754             : //        {
    1755             : //std::cerr << "--- intermediate output pipe forked()\n";
    1756             : //            f_intermediate_output_pipe->forked();
    1757             : //        }
    1758             : //
    1759           8 :         if(f_error_pipe != nullptr)
    1760             :         {
    1761           0 :             f_error_pipe->forked();
    1762             :         }
    1763           8 :         if(f_internal_error_pipe != nullptr)
    1764             :         {
    1765           1 :             f_internal_error_pipe->forked();
    1766             :         }
    1767             : 
    1768           8 :         f_running = true;
    1769             : 
    1770           8 :         return 0;
    1771             : 
    1772             :     }
    1773             :     snap::NOT_REACHED();
    1774             : }
    1775             : 
    1776             : 
    1777           0 : void process::execute_command(
    1778             :           ed::pipe_connection::pointer_t output_fifo
    1779             :         , int output_index
    1780             :         , ed::pipe_connection::pointer_t input_fifo)
    1781             : {
    1782             :     // child
    1783             :     //
    1784             :     try
    1785             :     {
    1786             :         // convert arguments so we can use them with execvpe()
    1787             :         //
    1788           0 :         std::vector<char const *> args_strings;
    1789           0 :         args_strings.reserve(1 + f_arguments.size() + 1);
    1790           0 :         args_strings.push_back(f_command.c_str());
    1791           0 :         for(auto const & a : f_arguments)
    1792             :         {
    1793           0 :             args_strings.push_back(a.c_str());
    1794             :         }
    1795           0 :         args_strings.push_back(nullptr); // NULL terminated
    1796             : 
    1797             :         // convert the environment variables so we can use them with execvpe()
    1798             :         //
    1799           0 :         environment_map_t src_envs(f_environment);
    1800           0 :         if(!f_forced_environment)
    1801             :         {
    1802             :             // since we do not limit the child to only the specified
    1803             :             // environment, add ours but do not overwrite anything
    1804             :             //
    1805           0 :             for(char ** env(environ); *env != nullptr; ++env)
    1806             :             {
    1807           0 :                 char const * s(*env);
    1808           0 :                 char const * n(s);
    1809           0 :                 while(*s != '\0')
    1810             :                 {
    1811           0 :                     if(*s == '=')
    1812             :                     {
    1813           0 :                         std::string const name(n, s - n);
    1814             : 
    1815             :                         // do not overwrite user overridden values
    1816             :                         //
    1817           0 :                         if(src_envs.find(name) == src_envs.end())
    1818             :                         {
    1819             :                             // in Linux all is UTF-8 so we are already good here
    1820             :                             //
    1821           0 :                             src_envs[name] = s + 1;
    1822             :                         }
    1823           0 :                         break;
    1824             :                     }
    1825           0 :                     ++s;
    1826             :                 }
    1827             :             }
    1828             :         }
    1829           0 :         std::vector<char const *> envs_strings;
    1830           0 :         for(auto const & it : src_envs)
    1831             :         {
    1832           0 :             envs_strings.push_back(strdup((it.first + "=" + it.second).c_str()));
    1833             :         }
    1834           0 :         envs_strings.push_back(nullptr); // NULL terminated
    1835             : 
    1836             :         // replace the stdin and stdout (and optionally stderr)
    1837             :         // with their respective pipes
    1838             :         //
    1839           0 :         if(f_prepared_input != -1)
    1840             :         {
    1841           0 :             if(dup2(f_prepared_input, STDIN_FILENO) < 0)  // stdin
    1842             :             {
    1843           0 :                 throw cppprocess_initialization_failed("dup2() of the stdin pipe failed");
    1844             :             }
    1845             :         }
    1846           0 :         if(f_prepared_output[output_index] != -1)
    1847             :         {
    1848           0 :             if(dup2(f_prepared_output[output_index], STDOUT_FILENO) < 0)  // stdout
    1849             :             {
    1850           0 :                 if(f_prepared_input != -1)
    1851             :                 {
    1852           0 :                     close(f_prepared_input);
    1853             :                 }
    1854           0 :                 throw cppprocess_initialization_failed("dup2() of the stdout pipe failed");
    1855             :             }
    1856             :         }
    1857           0 :         if(f_prepared_error != -1)
    1858             :         {
    1859           0 :             if(dup2(f_prepared_error, STDERR_FILENO) < 0)  // stderr
    1860             :             {
    1861           0 :                 if(f_prepared_input != -1)
    1862             :                 {
    1863           0 :                     close(f_prepared_input);
    1864             :                 }
    1865           0 :                 if(f_prepared_output[output_index] != -1)
    1866             :                 {
    1867           0 :                     close(f_prepared_output[output_index]);
    1868             :                 }
    1869           0 :                 throw cppprocess_initialization_failed("dup2() of the stderr pipe failed");
    1870             :             }
    1871             :         }
    1872             : 
    1873             :         // we duplicated the files we were interested in as required,
    1874             :         // now close all the other pipes
    1875             :         //
    1876           0 :         if(input_fifo != nullptr)
    1877             :         {
    1878           0 :             input_fifo->close();
    1879             :         }
    1880           0 :         if(f_input_pipe != nullptr)
    1881             :         {
    1882           0 :             f_input_pipe->close();
    1883             :         }
    1884           0 :         if(f_internal_input_pipe != nullptr)
    1885             :         {
    1886           0 :             f_internal_input_pipe->close();
    1887             :         }
    1888           0 :         if(f_output_pipe != nullptr)
    1889             :         {
    1890           0 :             f_output_pipe->close();
    1891             :         }
    1892           0 :         if(output_fifo != nullptr)
    1893             :         {
    1894           0 :             output_fifo->close();
    1895             :         }
    1896           0 :         if(f_intermediate_output_pipe != nullptr)
    1897             :         {
    1898           0 :             f_intermediate_output_pipe->close();
    1899             :         }
    1900           0 :         if(f_error_pipe != nullptr)
    1901             :         {
    1902           0 :             f_error_pipe->close();
    1903             :         }
    1904           0 :         if(f_internal_error_pipe != nullptr)
    1905             :         {
    1906           0 :             f_internal_error_pipe->close();
    1907             :         }
    1908             : 
    1909           0 :         execvpe(
    1910             :             f_command.c_str(),
    1911           0 :             const_cast<char * const *>(&args_strings[0]),
    1912           0 :             const_cast<char * const *>(&envs_strings[0])
    1913             :         );
    1914             : 
    1915             :         // the child returns only if execvp() fails, which is possible
    1916             :         //
    1917           0 :         int const e(errno);
    1918           0 :         SNAP_LOG_FATAL
    1919           0 :             << "Starting child process \""
    1920             :             << f_command
    1921             :             << " "
    1922           0 :             << snap::join_strings(f_arguments, " ")
    1923           0 :             << "\" failed. (errno: "
    1924             :             << e
    1925             :             << " -- "
    1926           0 :             << strerror(e)
    1927             :             << ")"
    1928             :             << SNAP_LOG_SEND;
    1929             :     }
    1930           0 :     catch(libexcept::exception_t const & e)
    1931             :     {
    1932           0 :         SNAP_LOG_FATAL
    1933           0 :             << "process::run(): snap_exception caught: "
    1934           0 :             << e.what()
    1935             :             << SNAP_LOG_SEND;
    1936             :     }
    1937           0 :     catch(std::exception const & e)
    1938             :     {
    1939             :         // the snap_logic_exception is not a snap_exception
    1940             :         // and other libraries may generate other exceptions
    1941             :         // (i.e. libtld, libQtCassandra...)
    1942             :         //
    1943           0 :         SNAP_LOG_FATAL
    1944           0 :             << "process::run(): std::exception caught: "
    1945           0 :             << e.what()
    1946             :             << SNAP_LOG_SEND;
    1947             :     }
    1948           0 :     catch(...)
    1949             :     {
    1950           0 :         SNAP_LOG_FATAL
    1951           0 :             << "process::run(): unknown exception caught!"
    1952             :             << SNAP_LOG_SEND;
    1953             :     }
    1954           0 : }
    1955             : 
    1956             : 
    1957             : /** \brief Setup the input pipe.
    1958             :  *
    1959             :  * This function prepare the input pipe. If this process is a \em next
    1960             :  * process, then the output_fifo will be set to the output of the previous
    1961             :  * process. In effect, this allows us to pipe any number of commands
    1962             :  * automatically and with just one pipe object.
    1963             :  *
    1964             :  * The output_fifo is that pipe file descriptor.
    1965             :  *
    1966             :  * The last process should instead setup an output fifo with the
    1967             :  * set_output_pipe() function.
    1968             :  *
    1969             :  * \note
    1970             :  * If an output fifo gets set in a process other than a last process
    1971             :  * (i.e. a process with at least one next() process), then the function
    1972             :  * throws an error (i.t. invalid setup).
    1973             :  */
    1974           8 : void process::prepare_input(ed::pipe_connection::pointer_t output_fifo)
    1975             : {
    1976             :     // piping between process objects
    1977             :     //
    1978           8 :     if(output_fifo != nullptr)
    1979             :     {
    1980             :         // we are being piped from a previous command, we must be
    1981             :         // using this output_fifo as our input
    1982             :         //
    1983           2 :         if(f_input_pipe != nullptr)
    1984             :         {
    1985           0 :             throw cppprocess_invalid_parameters("you cannot pipe a command (add_next()) and define your own input pipe.");
    1986             :         }
    1987           2 :         if(!f_input.empty())
    1988             :         {
    1989           0 :             throw cppprocess_invalid_parameters("you cannot pipe a command (add_next()) and define your own input data.");
    1990             :         }
    1991             : 
    1992             :         //f_prepared_input = output_fifo->get_other_socket();
    1993           2 :         f_prepared_input = output_fifo->get_socket();
    1994           2 :         return;
    1995             :     }
    1996             : 
    1997             :     // user specified pipe
    1998             :     //
    1999           6 :     if(f_input_pipe != nullptr)
    2000             :     {
    2001           0 :         if(!f_input.empty())
    2002             :         {
    2003           0 :             throw cppprocess_invalid_parameters("you cannot define pipe and input data in the same process.");
    2004             :         }
    2005             : 
    2006           0 :         f_prepared_input = f_input_pipe->get_other_socket();
    2007           0 :         return;
    2008             :     }
    2009             : 
    2010           6 :     if(!f_input_filename.empty())
    2011             :     {
    2012           1 :         f_input_file.reset(open(
    2013             :                   f_input_filename.c_str()
    2014             :                 , O_RDONLY));
    2015           1 :         f_prepared_input = f_input_file.get();
    2016           1 :         return;
    2017             :     }
    2018             : 
    2019           5 :     if(!f_input.empty())
    2020             :     {
    2021             :         // the user supplied a buffer instead of a pipe, we create a pipe
    2022             :         // to send that buffer which will be pretty much automatic
    2023             :         //
    2024           3 :         f_internal_input_pipe = std::make_shared<direct_input_data>(this, f_input);
    2025           3 :         f_prepared_input = f_internal_input_pipe->get_other_socket();
    2026           3 :         f_communicator->add_connection(f_internal_input_pipe);
    2027           3 :         return;
    2028             :     }
    2029             : 
    2030             :     // as a fallback, pass our stdin
    2031             :     //
    2032           2 :     f_prepared_input = STDIN_FILENO;
    2033             : }
    2034             : 
    2035             : 
    2036             : /** \brief Prepare the output pipes.
    2037             :  *
    2038             :  * The output can be unique (99% of the time) or it can be duplicated
    2039             :  * with a tee pipe.
    2040             :  *
    2041             :  * The tee pipe is an internal feature used when a process is piped to
    2042             :  * two or more other processes. Each one of the following processes
    2043             :  * receives a copy of the previous process output.
    2044             :  *
    2045             :  * If there are no output processes, then the output is expected to
    2046             :  * use a pipe that you define with set_output_pipe(). If you don't
    2047             :  * define an output pipe, then stdout is used.
    2048             :  */
    2049           8 : void process::prepare_output()
    2050             : {
    2051             :     // the output has four cases
    2052             :     //
    2053             :     // 1. there is exactly one process following this one
    2054             :     //
    2055             :     //     we need a simple FIFO between the two processes; this is handled
    2056             :     //     internally
    2057             :     //
    2058             :     //     in this case it is illegal for the user to define an output FIFO
    2059             :     //
    2060             :     // 2. there is more than one process following this one (tee-feature)
    2061             :     //
    2062             :     //     we create one output FIFO and each of the following processes
    2063             :     //     will receive a specific input FIFO; our output FIFO will
    2064             :     //     duplicate all the data it receives in all the input FIFOs
    2065             :     //
    2066             :     //     in this case it is illegal for the user to define an output FIFO
    2067             :     //
    2068             :     // 3. no following processes & a user defined output FIFO
    2069             :     //
    2070             :     //     the user output FIFO is used for our stdout
    2071             :     //
    2072             :     // 4. no following processes, no user defined output FIFO, capture is true
    2073             :     //
    2074             :     //     create an internal FIFO and save output in process
    2075             :     //
    2076             :     // 5. no following processes & no user defined output FIFO
    2077             :     //
    2078             :     //     we use the default stdout
    2079             :     //
    2080             : 
    2081           8 :     switch(f_next.size())
    2082             :     {
    2083           6 :     case 0:
    2084             :         // no piping to another process:
    2085             :         //   1. use the user output if defined (f_output_pipe)
    2086             :         //   2. use internal output if f_capture_output is true
    2087             :         //   3. use stdout
    2088             :         //
    2089           6 :         if(f_output_pipe != nullptr)
    2090             :         {
    2091           0 :             f_prepared_output.push_back(f_output_pipe->get_socket());
    2092             :         }
    2093           6 :         else if(!f_output_filename.empty())
    2094             :         {
    2095           1 :             f_output_file.reset(open(
    2096             :                       f_output_filename.c_str()
    2097             :                     , O_WRONLY | O_CREAT | O_TRUNC
    2098             :                     , S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IRGRP));
    2099           1 :             f_prepared_output.push_back(f_output_file.get());
    2100             :         }
    2101           5 :         else if(f_capture_output)
    2102             :         {
    2103           3 :             f_intermediate_output_pipe = std::make_shared<capture_output_pipe>(this, f_output);
    2104           3 :             f_prepared_output.push_back(f_intermediate_output_pipe->get_other_socket());
    2105           3 :             f_communicator->add_connection(f_intermediate_output_pipe);
    2106             :         }
    2107             :         else
    2108             :         {
    2109             :             // as a fallback, pass our stdout
    2110             :             //
    2111           2 :             f_prepared_output.push_back(STDOUT_FILENO);
    2112             :         }
    2113           6 :         break;
    2114             : 
    2115           2 :     case 1:
    2116             :         // normal case where there is a one to one match
    2117             :         // (i.e. not tee-feature required)
    2118             :         //
    2119           2 :         if(f_output_pipe != nullptr)
    2120             :         {
    2121           0 :             throw cppprocess_invalid_parameters("you cannot pipe a command (add_next()) and define your own output pipe in the sender.");
    2122             :         }
    2123           2 :         f_intermediate_output_pipe = std::make_shared<direct_output_to_input_pipe>();
    2124           2 :         f_prepared_output.push_back(f_intermediate_output_pipe->get_other_socket());
    2125             : 
    2126             :         // in this one case, the FIFO works automatically, our communicator
    2127             :         // does not have to intervene -- so no add required
    2128             :         //
    2129             :         //f_communicator->add_connection(f_intermediate_output_pipe);
    2130           2 :         break;
    2131             : 
    2132           0 :     default:
    2133             :         // special case where we create one output pipe that
    2134             :         // distribute the output to N input pipes for the next
    2135             :         // N processes
    2136             :         //
    2137           0 :         if(f_output_pipe != nullptr)
    2138             :         {
    2139           0 :             throw cppprocess_invalid_parameters("you cannot pipe the output of a command (add_next()) to many other commands and define your own output pipe in the sender.");
    2140             :         }
    2141           0 :         f_intermediate_output_pipe = std::make_shared<tee_pipe>(f_next.size());
    2142           0 :         for(std::size_t idx(0); idx < f_next.size(); ++idx)
    2143             :         {
    2144           0 :             f_prepared_output.push_back(std::dynamic_pointer_cast<tee_pipe>(f_intermediate_output_pipe)->get_output_pipe(idx)->get_other_socket());
    2145           0 :         }
    2146           0 :         f_communicator->add_connection(f_intermediate_output_pipe);
    2147           0 :         break;
    2148             : 
    2149             :     }
    2150           8 : }
    2151             : 
    2152             : 
    2153             : /** \brief Prepare the error file descriptor.
    2154             :  *
    2155             :  * This function prepares the error file descriptor.
    2156             :  *
    2157             :  * The error pipe is set to stderr if you did not setup an error pipe with
    2158             :  * the set_error_pipe() function.
    2159             :  */
    2160           8 : void process::prepare_error()
    2161             : {
    2162             :     // user specified pipe
    2163             :     //
    2164           8 :     if(f_error_pipe != nullptr)
    2165             :     {
    2166           0 :         f_prepared_error = f_error_pipe->get_other_socket();
    2167           0 :         return;
    2168             :     }
    2169             : 
    2170           8 :     if(!f_error_filename.empty())
    2171             :     {
    2172           0 :         f_error_file.reset(open(
    2173             :                   f_error_filename.c_str()
    2174             :                 , O_WRONLY | O_CREAT | O_TRUNC
    2175             :                 , S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IRGRP));
    2176           0 :         f_prepared_error = f_error_file.get();
    2177           0 :         return;
    2178             :     }
    2179             : 
    2180           8 :     if(f_capture_error)
    2181             :     {
    2182           1 :         f_internal_error_pipe = std::make_shared<capture_output_pipe>(this, f_error);
    2183           1 :         f_prepared_error = f_internal_error_pipe->get_other_socket();
    2184           1 :         f_communicator->add_connection(f_internal_error_pipe);
    2185           1 :         return;
    2186             :     }
    2187             : 
    2188             :     // as a fallback, pass our stderr
    2189             :     //
    2190           7 :     f_prepared_error = STDERR_FILENO;
    2191             : }
    2192             : 
    2193             : 
    2194             : 
    2195             : /** \brief Send the specified signal to this process.
    2196             :  *
    2197             :  * When the process is running, it is possible to send it a signal using
    2198             :  * this function. The signal is sent immediately.
    2199             :  *
    2200             :  * \param[in] sig  The signal to send to the child process.
    2201             :  *
    2202             :  * \return 0 if the signal was sent, -1 on error and errno is set.
    2203             :  */
    2204           0 : int process::kill(int sig)
    2205             : {
    2206           0 :     if(f_child != -1
    2207           0 :     && f_running)
    2208             :     {
    2209           0 :         return ::kill(f_child, sig);
    2210             :     }
    2211             : 
    2212           0 :     errno = ESRCH;
    2213           0 :     return -1;
    2214             : }
    2215             : 
    2216             : 
    2217             : /** \brief Set process done callback.
    2218             :  *
    2219             :  * This function lets you define a callback which gets called whenever the
    2220             :  * SIGCHLD happens on that process.
    2221             :  *
    2222             :  * \warning
    2223             :  * At the time this function is called, the output is not likely to be
    2224             :  * ready. In most cases, the output buffer gets flushed only at the time
    2225             :  * the process exits and therefore the output on our end not yet ready.
    2226             :  * If you are interested in the output, make sure to use the
    2227             :  * set_output_capture_done() function when you want to get the final
    2228             :  * output.
    2229             :  *
    2230             :  * \param[in] callback  The callback to call when SIGCHLD is received.
    2231             :  */
    2232           0 : void process::set_process_done(process_done_t callback)
    2233             : {
    2234           0 :     f_process_done = callback;
    2235           0 : }
    2236             : 
    2237             : 
    2238             : /** \brief Call this function once down with the output pipe.
    2239             :  *
    2240             :  * This function will remove the intermediate output pipe from the
    2241             :  * communicator. This pipe is an internal pipe created when you don't
    2242             :  * specify your own.
    2243             :  *
    2244             :  * We call this function as soon as we get an error or HUP in the
    2245             :  * pipe managed internally.
    2246             :  */
    2247           3 : void process::input_pipe_done()
    2248             : {
    2249           3 :     if(f_internal_input_pipe != nullptr)
    2250             :     {
    2251           3 :         f_communicator->remove_connection(f_internal_input_pipe);
    2252           3 :         f_internal_input_pipe->close();
    2253           3 :         f_internal_input_pipe.reset();
    2254             :     }
    2255           3 : }
    2256             : 
    2257             : 
    2258             : /** \brief Call this function once down with the output or error pipe.
    2259             :  *
    2260             :  * This function will remove the intermediate output pipe from the
    2261             :  * communicator. This pipe is an internal pipe created when you don't
    2262             :  * specify your own.
    2263             :  *
    2264             :  * We call this function as soon as we get an error or HUP in the
    2265             :  * pipe managed internally.
    2266             :  *
    2267             :  * \param[in] p  The pipe being closed.
    2268             :  */
    2269           4 : void process::output_pipe_done(ed::pipe_connection * p)
    2270             : {
    2271           4 :     if(f_intermediate_output_pipe.get() == p)
    2272             :     {
    2273           3 :         f_communicator->remove_connection(f_intermediate_output_pipe);
    2274           3 :         f_intermediate_output_pipe->close();
    2275           3 :         f_intermediate_output_pipe.reset();
    2276             : 
    2277           3 :         if(f_output_done_callback != nullptr)
    2278             :         {
    2279           0 :             f_output_done_callback(get_output());
    2280             :         }
    2281             :     }
    2282           1 :     else if(f_internal_error_pipe.get() == p)
    2283             :     {
    2284           1 :         f_communicator->remove_connection(f_internal_error_pipe);
    2285           1 :         f_internal_error_pipe->close();
    2286           1 :         f_internal_error_pipe.reset();
    2287             : 
    2288           1 :         if(f_output_done_callback != nullptr)
    2289             :         {
    2290           0 :             f_error_done_callback(get_error());
    2291             :         }
    2292             :     }
    2293           0 :     else if(f_next.size() == 1)
    2294             :     {
    2295             :         // for the tee, we're not internally responsible for final output
    2296             :         // pipes, but when only one we want to take care of it here
    2297             :         //
    2298           0 :         pointer_t n(*f_next.begin());
    2299           0 :         while(n->f_next.size() != 0)
    2300             :         {
    2301           0 :             if(n->f_next.size() != 1)
    2302             :             {
    2303           0 :                 return;
    2304             :             }
    2305           0 :             n = *n->f_next.begin();
    2306             :         }
    2307           0 :         if(n->f_intermediate_output_pipe.get() == p)
    2308             :         {
    2309           0 :             f_communicator->remove_connection(n->f_intermediate_output_pipe);
    2310           0 :             n->f_intermediate_output_pipe->close();
    2311           0 :             n->f_intermediate_output_pipe.reset();
    2312             :         }
    2313             :     }
    2314             : }
    2315             : 
    2316             : 
    2317             : 
    2318           6 : } // namespace cppprocess
    2319             : // vim: ts=4 sw=4 et

Generated by: LCOV version 1.13