LCOV - code coverage report
Current view: top level - cppprocess/cppprocess - process.cpp (source / functions) Hit Total Coverage
Test: coverage.info Lines: 143 416 34.4 %
Date: 2022-06-18 10:10:36 Functions: 29 57 50.9 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : // Copyright (c) 2013-2022  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             : /** \brief A direct output to input pipe.
      73             :  *
      74             :  * When piping one command to another, then this pipe object gets used.
      75             :  * This pipe directly sends the output of the previous command to the
      76             :  * input of the next command.
      77             :  *
      78             :  * Internally, we may also use the tee_pipe which sends the output of
      79             :  * the previous command to the input of all the next commands.
      80             :  */
      81           2 : class direct_output_to_input_pipe
      82             :     : public ed::pipe_connection
      83             : {
      84             : public:
      85             :                     direct_output_to_input_pipe();
      86             : 
      87             :     // pipe_connection implementation
      88             :     //
      89             :     virtual void                forked() override;
      90             : 
      91             : private:
      92             : };
      93             : 
      94             : 
      95           2 : direct_output_to_input_pipe::direct_output_to_input_pipe()
      96           2 :     : pipe_connection(ed::pipe_t::PIPE_CHILD_OUTPUT)
      97             : {
      98           2 :     set_name("direct_output_to_input_pipe");
      99           2 : }
     100             : 
     101             : 
     102           2 : void direct_output_to_input_pipe::forked()
     103             : {
     104             :     // force a full close in this case
     105             :     //
     106           2 :     close();
     107           2 : }
     108             : 
     109             : 
     110             : 
     111             : 
     112             : 
     113             : 
     114             : 
     115             : 
     116             : 
     117           0 : class buffered_pipe
     118             :     : public ed::pipe_connection
     119             : {
     120             : public:
     121             :                                 buffered_pipe();
     122             : 
     123             :     // connection
     124             :     virtual bool                is_writer() const override;
     125             : 
     126             :     // pipe implementation
     127             :     virtual ssize_t             write(void const * data, size_t length) override;
     128             :     virtual void                process_write() override;
     129             :     virtual void                process_hup() override;
     130             : 
     131             : private:
     132             :     std::vector<char>           f_output = std::vector<char>();
     133             :     size_t                      f_position = 0;
     134             : };
     135             : 
     136             : 
     137           0 : buffered_pipe::buffered_pipe()
     138           0 :     : pipe_connection(ed::pipe_t::PIPE_CHILD_OUTPUT)
     139             : {
     140           0 :     set_name("buffered_pipe");
     141           0 : }
     142             : 
     143             : 
     144           0 : bool buffered_pipe::is_writer() const
     145             : {
     146           0 :     return get_socket() != -1 && !f_output.empty();
     147             : }
     148             : 
     149             : 
     150           0 : ssize_t buffered_pipe::write(void const * data, size_t length)
     151             : {
     152           0 :     if(get_socket() == -1)
     153             :     {
     154           0 :         errno = EBADF;
     155           0 :         return -1;
     156             :     }
     157             : 
     158           0 :     if(data != nullptr && length > 0)
     159             :     {
     160           0 :         char const * d(reinterpret_cast<char const *>(data));
     161           0 :         f_output.insert(f_output.end(), d, d + length);
     162           0 :         return length;
     163             :     }
     164             : 
     165           0 :     return 0;
     166             : }
     167             : 
     168             : 
     169           0 : void buffered_pipe::process_write()
     170             : {
     171           0 :     if(get_socket() != -1)
     172             :     {
     173           0 :         errno = 0;
     174           0 :         ssize_t const r(pipe_connection::write(&f_output[f_position], f_output.size() - f_position));
     175           0 :         if(r > 0)
     176             :         {
     177             :             // some data was written
     178             :             //
     179           0 :             f_position += r;
     180           0 :             if(f_position >= f_output.size())
     181             :             {
     182           0 :                 f_output.clear();
     183           0 :                 f_position = 0;
     184           0 :                 process_empty_buffer();
     185             :             }
     186             :         }
     187           0 :         else if(r != 0 && errno != 0 && errno != EAGAIN && errno != EWOULDBLOCK)
     188             :         {
     189             :             // connection is considered bad, get rid of it
     190             :             //
     191           0 :             int const e(errno);
     192           0 :             SNAP_LOG_ERROR
     193             :                 << "an error occurred while writing to socket of \""
     194           0 :                 << get_name()
     195           0 :                 << "\" (errno: "
     196             :                 << e
     197             :                 << " -- "
     198           0 :                 << strerror(e)
     199             :                 << ")."
     200             :                 << SNAP_LOG_SEND;
     201           0 :             process_error();
     202           0 :             return;
     203             :         }
     204             :     }
     205             :     //else -- TBD: should we generate an error when the socket is not valid?
     206             : 
     207             :     // process next level too
     208             :     //
     209           0 :     pipe_connection::process_write();
     210             : }
     211             : 
     212             : 
     213           0 : void buffered_pipe::process_hup()
     214             : {
     215           0 :     close();
     216             : 
     217           0 :     pipe_connection::process_hup();
     218           0 : }
     219             : 
     220             : 
     221             : 
     222             : 
     223             : 
     224             : 
     225             : 
     226           0 : class tee_pipe
     227             :     : public ed::pipe_connection
     228             : {
     229             : public:
     230             :                                     tee_pipe(std::size_t const size);
     231             : 
     232             :     ed::pipe_connection::pointer_t  get_output_pipe(std::size_t idx);
     233             : 
     234             :     // pipe_connection
     235             :     //
     236             :     virtual void                    process_read() override;
     237             :     virtual void                    connection_added() override;
     238             :     virtual void                    connection_removed() override;
     239             : 
     240             : private:
     241             :     ed::communicator::pointer_t     f_communicator = ed::communicator::pointer_t();
     242             :     ed::pipe_connection::vector_t   f_output = ed::pipe_connection::vector_t();
     243             : };
     244             : 
     245             : 
     246           0 : tee_pipe::tee_pipe(std::size_t const size)
     247             :     : pipe_connection(ed::pipe_t::PIPE_CHILD_INPUT)
     248             :     , f_communicator(ed::communicator::instance())
     249           0 :     , f_output(size)
     250             : {
     251           0 :     set_name("tee_pipe");
     252             : 
     253           0 :     if(size == 0)
     254             :     {
     255           0 :         throw cppprocess_logic_error("tee_pipe constructor called with a size of zero is not supported");
     256             :     }
     257             : 
     258           0 :     for(std::size_t idx(0); idx < size; ++idx)
     259             :     {
     260           0 :         f_output[idx] = std::make_shared<buffered_pipe>();
     261             :     }
     262           0 : }
     263             : 
     264             : 
     265           0 : ed::pipe_connection::pointer_t tee_pipe::get_output_pipe(std::size_t idx)
     266             : {
     267           0 :     if(idx >= f_output.size())
     268             :     {
     269             :         throw cppprocess_out_of_range(
     270             :               "get_output_pipe() called with index "
     271           0 :             + std::to_string(idx)
     272           0 :             + ", which is out of allowed range: [0.."
     273           0 :             + std::to_string(f_output.size())
     274           0 :             + ").");
     275             :     }
     276             : 
     277           0 :     return f_output[idx];
     278             : }
     279             : 
     280             : 
     281           0 : void tee_pipe::process_read()
     282             : {
     283           0 :     if(get_socket() != -1)
     284             :     {
     285             :         // handle up to 64Kb at once
     286             :         //
     287           0 :         char buffer[1'024 * 64];
     288           0 :         errno = 0;
     289           0 :         ssize_t const r(read(&buffer[0], sizeof(buffer)));
     290           0 :         if(r < 0
     291           0 :         && errno != 0
     292           0 :         && errno != EAGAIN
     293           0 :         && errno != EWOULDBLOCK)
     294             :         {
     295             :             // this happens all the time (i.e. another process quits)
     296             :             // so we make it a debug and not a warning or an error...
     297             :             //
     298           0 :             int const e(errno);
     299           0 :             SNAP_LOG_DEBUG
     300           0 :                 << "an error occurred while reading from socket (errno: "
     301             :                 << e
     302             :                 << " -- "
     303           0 :                 << strerror(e)
     304             :                 << ")."
     305             :                 << SNAP_LOG_SEND;
     306           0 :             process_error();
     307           0 :             return;
     308             :         }
     309             : 
     310           0 :         if(r > 0)
     311             :         {
     312             :             // this is the T functionality, where we duplicate the data in
     313             :             // the input of each of the succeeded processes
     314             :             //
     315           0 :             for(auto & out : f_output)
     316             :             {
     317           0 :                 out->write(&buffer[0], r);
     318             :             }
     319             :         }
     320             :     }
     321             : 
     322             :     // process the next level
     323             :     //
     324           0 :     pipe_connection::process_read();
     325             : }
     326             : 
     327             : 
     328           0 : void tee_pipe::connection_added()
     329             : {
     330           0 :     for(auto & out : f_output)
     331             :     {
     332           0 :         f_communicator->add_connection(out);
     333             :     }
     334           0 : }
     335             : 
     336             : 
     337           0 : void tee_pipe::connection_removed()
     338             : {
     339           0 :     for(auto & out : f_output)
     340             :     {
     341           0 :         f_communicator->remove_connection(out);
     342             :     }
     343           0 : }
     344             : 
     345             : 
     346             : 
     347             : } // no name namespace
     348             : 
     349             : 
     350             : 
     351             : 
     352             : /** \class process
     353             :  * \brief A process class to run a process and get information about the results.
     354             :  *
     355             :  * This class is used to run processes. Especially, it can run with in and
     356             :  * out capabilities (i.e. piping) although this is generally not recommanded
     357             :  * because piping can block (if you do not send enough data, or do not read
     358             :  * enough data, then the pipes can get stuck.) We use a thread to read the
     359             :  * results. We do not currently expect that the use of this class will require
     360             :  * the input read to be necessary to know what needs to be written (i.e. in
     361             :  * most cases all we want is to convert a file [input] from one format to
     362             :  * another [output] avoiding reading/writing on disk.)
     363             :  *
     364             :  * The whole process, when using the interactive mode, is quite complicated
     365             :  * so I wrote the following diagram. As you can see, the loop of sending
     366             :  * and receiving data from the child process is fairly simple. Note that the
     367             :  * callback is called from the Output Thread, not the main process. This does
     368             :  * not make much of a difference because no other function can be running on
     369             :  * the main process when that happens. The output is blocked and thus the
     370             :  * output variable is safe. The input is not blocked but adding input was
     371             :  * made safe internally.
     372             :  *
     373             :  * \msc
     374             :  * hscale = "2";
     375             :  * a [label="Function"],b [label="Process"],c [label="Input Thread"],d [label="Output Thread"],e [label="Child Process"];
     376             :  *
     377             :  * a=>b [label="run()"];
     378             :  * b=>e [label="fork()"];
     379             :  * e->e [label="execvpe()"];
     380             :  * b=>c [label="pthread_create()"];
     381             :  * b=>d [label="pthread_create()"];
     382             :  * b=>e [label="wait() child's death"];
     383             :  *
     384             :  * --- [label="start repeat"];
     385             :  * c->e [label="write() (Input Data)"];
     386             :  * d<-e [label="read() (Output Data)"];
     387             :  * b<:d [label="output shared"];
     388             :  * a<<=d [label="output callback"];
     389             :  * a=>b [label="set_input()"];
     390             :  * b=>c [label="add input"];
     391             :  * --- [label="end repeat"];
     392             :  *
     393             :  * b<-e [label="child died"];
     394             :  * b->c [label="stop()"];
     395             :  * b<-c [label="stopped"];
     396             :  * b->d [label="stop()"];
     397             :  * b<-d [label="stopped"];
     398             :  * a<\<b [label="run()"];
     399             :  * \endmsc
     400             :  *
     401             :  * Using the add_next_process function, it is possible to pipe the output
     402             :  * of one process as the input of the next process. In other words, this
     403             :  * class allows you to pipe any number of processes between each other.
     404             :  *
     405             :  * \code
     406             :  *     cppprocess:process a;
     407             :  *     cppprocess:process b;
     408             :  *     cppprocess:process c;
     409             :  *
     410             :  *     a.set_next_process(b);
     411             :  *     b.set_next_process(c);
     412             :  *
     413             :  *     a.start();       // runs `a | b | c`
     414             :  * \endcode
     415             :  *
     416             :  * When piping processes in this way, intermediate pipes are used to send
     417             :  * the output of one process to the input of the next process.
     418             :  *
     419             :  * Also, when piping processes, you can only add one input pipe to the
     420             :  * very first process and one output pipe to the very last process. You
     421             :  * can, however, add one error pipe to each process (i.e. so you can know
     422             :  * which process output such and such errors).
     423             :  *
     424             :  * When piping processes, you only call the start() function of
     425             :  * the first process. That will have the side effect of starting all the
     426             :  * following processes as expected.
     427             :  *
     428             :  * The feature includes a "tee" feature, which allows you to pipe the
     429             :  * output of one process as the input of any number of processes. This
     430             :  * is done by adding multiple processes as the next process of one
     431             :  * proces.
     432             :  *
     433             :  * \code
     434             :  *     cppprocess:process a;
     435             :  *     cppprocess:process b;
     436             :  *     cppprocess:process c;
     437             :  *     cppprocess:process c;
     438             :  *
     439             :  *     a.set_next_process(b);
     440             :  *     a.set_next_process(c);
     441             :  *     a.set_next_process(d);
     442             :  *
     443             :  *     a.start();
     444             :  *
     445             :  *     // equivalent to:
     446             :  *     //    a > data.tmp
     447             :  *     //    b < data.tmp
     448             :  *     //    c < data.tmp
     449             :  *     //    d < data.tmp
     450             :  *     // only we avoid the temporary file and b, c, d are run in parallel
     451             :  *     // note that b, c, d could be the same process with different args
     452             :  * \endcode
     453             :  */
     454             : 
     455             : 
     456             : /** \brief Initialize the process object.
     457             :  *
     458             :  * This function saves the name of the process. The name is generally a
     459             :  * static string and it is used to distinguish between processes when
     460             :  * managing several at once. The function makes a copy of the name.
     461             :  *
     462             :  * \note
     463             :  * The name of the process is not the command. See set_command().
     464             :  *
     465             :  * \param[in] name  The name of the process.
     466             :  *
     467             :  * \sa set_command()
     468             :  * \sa get_name()
     469             :  */
     470           8 : process::process(std::string const & name)
     471             :     : f_communicator(ed::communicator::instance())
     472           8 :     , f_name(name)
     473             : {
     474           8 : }
     475             : 
     476             : 
     477             : /** \brief Retrieve the name of this process object.
     478             :  *
     479             :  * This process object is given a name on creation. In most cases this is
     480             :  * a static name that is used to determine which process is which.
     481             :  *
     482             :  * \return The name of the process.
     483             :  */
     484           4 : std::string const & process::get_name() const
     485             : {
     486           4 :     return f_name;
     487             : }
     488             : 
     489             : 
     490             : /** \brief Set how the environment variables are defined in the process.
     491             :  *
     492             :  * By default all of the current process environment variables are
     493             :  * passed to the child process. If the child process is not 100% trustworthy,
     494             :  * it may be preferable to only pass a specific set of environment variables
     495             :  * (as added by the add_environ() function) to the child process.
     496             :  *
     497             :  * This function sets a flag to determine whether we want to force the
     498             :  * environment (true) to the list of variables added with the
     499             :  * add_environ() function or let our current process variables
     500             :  * flow through (false, the default).
     501             :  *
     502             :  * \param[in] forced  Whether the environment will be forced.
     503             :  *
     504             :  * \sa add_environ()
     505             :  * \sa get_forced_environment()
     506             :  */
     507           4 : void process::set_forced_environment(bool forced)
     508             : {
     509           4 :     f_forced_environment = forced;
     510           4 : }
     511             : 
     512             : 
     513             : /** \brief Check the current status of the forced environment flag.
     514             :  *
     515             :  * This function returns a copy of the forced environment flag. If true,
     516             :  * then the run() function will force the environment variables as
     517             :  * defined by add_environ() function instead of all the environment
     518             :  * variables of the calling process.
     519             :  *
     520             :  * \return The status of the forced environment flag.
     521             :  *
     522             :  * \sa add_environ()
     523             :  * \sa set_forced_environment()
     524             :  */
     525           6 : bool process::get_forced_environment() const
     526             : {
     527           6 :     return f_forced_environment;
     528             : }
     529             : 
     530             : 
     531             : /** \brief Define the working directory for this command.
     532             :  *
     533             :  * With a system() call, you can have a complete script running your
     534             :  * command and that script can include a "cd /some/path" at the start
     535             :  * to force a current working directory.
     536             :  *
     537             :  * Our process does not allow for such. The command must be one executable
     538             :  * which can be run with execvpe().
     539             :  *
     540             :  * So to allow for the execution of a process in a directory other than
     541             :  * the current directory, you must assign a working directory before
     542             :  * calling the start() command.
     543             :  *
     544             :  * The directory must exist or the command will fail to start.
     545             :  *
     546             :  * \param[in] directory  The directory in this command will run.
     547             :  *
     548             :  * \sa start()
     549             :  */
     550           0 : void process::set_working_directory(std::string const & directory)
     551             : {
     552           0 :     f_working_directory = directory;
     553           0 : }
     554             : 
     555             : 
     556             : /** \brief Retrieve a reference to the working directory path.
     557             :  *
     558             :  * By default the working directory path is the empty path which is
     559             :  * interpreted as "do not change directory before execution".
     560             :  *
     561             :  * You can change the working directory of a child process by setting
     562             :  * the directory with the set_working_directory().
     563             :  *
     564             :  * \return The current working directory of this command.
     565             :  *
     566             :  * \sa set_working_directory()
     567             :  */
     568           0 : std::string const & process::get_working_directory() const
     569             : {
     570           0 :     return f_working_directory;
     571             : }
     572             : 
     573             : 
     574             : /** \brief Define the command to run.
     575             :  *
     576             :  * The command name may be a full path or just the command filename.
     577             :  * (i.e. the `execvp()` function makes use of the PATH variable to find
     578             :  * the command on disk unless the \p command parameter includes a
     579             :  * slash character.)
     580             :  *
     581             :  * \warning
     582             :  * Do not add any arguments here. Instead, make sure to use the
     583             :  * add_argument() to add any number of arguments.
     584             :  *
     585             :  * If the process cannot be found, an error is generated at the time you
     586             :  * call the run() function.
     587             :  *
     588             :  * \param[in] command  The command to start the new process.
     589             :  *
     590             :  * \sa add_argument()
     591             :  * \sa get_command()
     592             :  */
     593           8 : void process::set_command(std::string const & command)
     594             : {
     595           8 :     f_command = command;
     596           8 : }
     597             : 
     598             : 
     599             : /** \brief Retrieve the command name & path.
     600             :  *
     601             :  * This function returns the command as set with the set_command() function.
     602             :  *
     603             :  * If the set_command() was never called, then the command is the
     604             :  * empty string at this point.
     605             :  *
     606             :  * \return The command name and path (the path is optional).
     607             :  *
     608             :  * \sa set_command()
     609             :  */
     610           7 : std::string const & process::get_command() const
     611             : {
     612           7 :     return f_command;
     613             : }
     614             : 
     615             : 
     616             : /** \brief Generate the command line for display.
     617             :  *
     618             :  * This function builds the command line as it appears with its command
     619             :  * followed by its parameters quoted as required.
     620             :  *
     621             :  * Internally, we do not use such a string to run the process. Instead
     622             :  * the command line arguments are kept in a an array (argv) and the
     623             :  * command passed directly to the execvpe() function.
     624             :  *
     625             :  * \return The command line one can use for display.
     626             :  */
     627           0 : std::string process::get_command_line() const
     628             : {
     629           0 :     std::string result(f_command);
     630             : 
     631           0 :     for(auto a : f_arguments)
     632             :     {
     633           0 :         result += ' ';
     634           0 :         bool single_quote(a.find('\'') != std::string::npos);
     635           0 :         bool double_quote(a.find('"') != std::string::npos);
     636           0 :         bool special_char(a.find_first_of("&|;#*?!`()[]<>") != std::string::npos);
     637           0 :         if(single_quote && double_quote)
     638             :         {
     639           0 :             result += '\'';
     640           0 :             for(auto c : a)
     641             :             {
     642           0 :                 if(c == '\'')
     643             :                 {
     644           0 :                     result += '\\';
     645             :                 }
     646           0 :                 result += c;
     647             :             }
     648           0 :             result += '\'';
     649             :         }
     650           0 :         else if(single_quote)
     651             :         {
     652           0 :             result += '"';
     653           0 :             result += a;
     654           0 :             result += '"';
     655             :         }
     656           0 :         else if(double_quote || special_char)
     657             :         {
     658           0 :             result += '\'';
     659           0 :             result += a;
     660           0 :             result += '\'';
     661             :         }
     662             :         else
     663             :         {
     664           0 :             result += a;
     665             :         }
     666             :     }
     667             : 
     668           0 :     return result;
     669             : }
     670             : 
     671             : 
     672             : /** \brief Add an argument to the command line.
     673             :  *
     674             :  * This function adds one individual arguement to the command line.
     675             :  *
     676             :  * You have to add all the arguments in the right order.
     677             :  *
     678             :  * If you set the \p expand flag to true, then the function transforms the
     679             :  * argument into a list of file names and add those instead. If the
     680             :  * argument does not match any filename, then it is added as is.
     681             :  *
     682             :  * If the expansion fails, then the function prints out an error message
     683             :  * in the log and it returns false.
     684             :  *
     685             :  * \param[in] arg  The argument to be added.
     686             :  * \param[in] expand  Whether this argument includes glob characters to expand.
     687             :  *
     688             :  * \return true if the argument was added without issue.
     689             :  *
     690             :  * \sa get_arguments()
     691             :  */
     692          11 : bool process::add_argument(std::string const & arg, bool expand)
     693             : {
     694          11 :     if(!expand)
     695             :     {
     696          11 :         f_arguments.push_back(arg);
     697          11 :         return true;
     698             :     }
     699             : 
     700           0 :     if(!f_arguments.read_path<
     701             :               snapdev::glob_to_list_flag_t::GLOB_FLAG_BRACE
     702             :             , snapdev::glob_to_list_flag_t::GLOB_FLAG_PERIOD
     703           0 :             , snapdev::glob_to_list_flag_t::GLOB_FLAG_TILDE>(arg))
     704             :     {
     705           0 :         SNAP_LOG_ERROR
     706             :             << "an error occurred reading argument filenames from pattern \""
     707             :             << arg
     708             :             << "\": "
     709           0 :             << f_arguments.get_last_error_message()
     710           0 :             << " (errno: "
     711             :             << f_arguments.get_last_error_errno()
     712             :             << ", "
     713           0 :             << strerror(f_arguments.get_last_error_errno())
     714             :             << ")."
     715             :             << SNAP_LOG_SEND;
     716           0 :         return false;
     717             :     }
     718             : 
     719           0 :     return true;
     720             : }
     721             : 
     722             : 
     723             : /** \brief Return the current list of updatable arguments.
     724             :  *
     725             :  * This function returns a non-constant reference to the list of arguments
     726             :  * currently available in this process.
     727             :  *
     728             :  * This gives you the ability to go through the list and make changes.
     729             :  * This is often used when you want to run the same command with different
     730             :  * parameters (i.e. maybe a filename that changes between runs).
     731             :  *
     732             :  * It is important to keep in mind that if you expanded an argument, the
     733             :  * list may now include from 0 to any number of arguments as a replacement
     734             :  * to that one expanded argument.
     735             :  *
     736             :  * \return The list of arguments attached to this process.
     737             :  *
     738             :  * \sa add_argument()
     739             :  */
     740           6 : process::argument_list_t & process::get_arguments()
     741             : {
     742           6 :     return f_arguments;
     743             : }
     744             : 
     745             : 
     746             : /** \brief Return the current list of arguments.
     747             :  *
     748             :  * This function returns a constant reference to the list of arguments
     749             :  * currently available in this process.
     750             :  *
     751             :  * The list is grown by calling the add_argument() function. It can be
     752             :  * edited by calling the non-constant get_argument() and keeping a
     753             :  * reference to the list.
     754             :  *
     755             :  * If you asked for some arguments to be expanded, then they will be
     756             :  * in the expanded state (you will have lost the original pattern).
     757             :  *
     758             :  * \return The list of arguments attached to this process.
     759             :  *
     760             :  * \sa add_argument()
     761             :  */
     762           0 : process::argument_list_t const & process::get_arguments() const
     763             : {
     764           0 :     return f_arguments;
     765             : }
     766             : 
     767             : 
     768             : /** \brief Add an environment to the command line.
     769             :  *
     770             :  * This function adds a new environment variable for the child process to
     771             :  * use. In most cases this function doesn't get used.
     772             :  *
     773             :  * By default all the parent process (this current process) environment
     774             :  * variables are passed down to the child process. To avoid this behavior,
     775             :  * call the set_forced_environment() function before the run() function.
     776             :  *
     777             :  * An environment variable is defined as a name and a value as in:
     778             :  *
     779             :  * \code
     780             :  * add_environ("HOME", "/home/cppprocess");
     781             :  * \endcode
     782             :  *
     783             :  * If the value is set to the empty string, then the environment variable
     784             :  * is removed from the list.
     785             :  *
     786             :  * \param[in] name  The name of the environment variable to add.
     787             :  * \param[in] value  The new value of that environment variable.
     788             :  *
     789             :  * \sa get_environ()
     790             :  */
     791           0 : void process::add_environ(std::string const & name, std::string const & value)
     792             : {
     793           0 :     if(value.empty())
     794             :     {
     795           0 :         auto it(f_environment.find(name));
     796           0 :         if(it != f_environment.end())
     797             :         {
     798           0 :             f_environment.erase(it);
     799             :         }
     800             :     }
     801             :     else
     802             :     {
     803           0 :         f_environment[name] = value;
     804             :     }
     805           0 : }
     806             : 
     807             : 
     808             : /** \brief Get a reference to the current environment.
     809             :  *
     810             :  * This parameter is generally empty since the run() function will use the
     811             :  * calling process environment variables.
     812             :  *
     813             :  * It is possible, however, to hide the calling process environment and
     814             :  * use these variables instead. This is very good for all sorts of safety
     815             :  * reasons (i.e. not leak a secret key saved in a variable, for example).
     816             :  *
     817             :  * \return A constant reference to the map of environment parameters.
     818             :  *
     819             :  * \sa add_environ()
     820             :  */
     821           4 : process::environment_map_t const & process::get_environ() const
     822             : {
     823           4 :     return f_environment;
     824             : }
     825             : 
     826             : 
     827             : /** \brief Setup the input I/O to the process.
     828             :  *
     829             :  * This function defines the input pipe or file that is to be used as input
     830             :  * to the process. If this function never gets called, stdin is used.
     831             :  *
     832             :  * \param[in] input  The input I/O object to use as the process input.
     833             :  *
     834             :  * \sa get_input_io()
     835             :  */
     836           4 : void process::set_input_io(io::pointer_t input)
     837             : {
     838           4 :     if((input->get_flags() & IO_FLAG_INPUT) == 0)
     839             :     {
     840           0 :         throw cppprocess_incorrect_pipe_type("incorrect I/O type, expected an I/O object that supports INPUT.");
     841             :     }
     842             : 
     843           4 :     f_input = input;
     844           4 : }
     845             : 
     846             : 
     847             : /** \brief Get a copy of the input I/O pointer.
     848             :  *
     849             :  * This function returns a pointer to the input I/O object saved in
     850             :  * this cppprocess object. By default, this is a null pointer. A null
     851             :  * pointer is equivalent to stdin.
     852             :  *
     853             :  * \return The input input I/O object to use as the process input.
     854             :  *
     855             :  * \sa set_input_io()
     856             :  */
     857           7 : io::pointer_t process::get_input_io() const
     858             : {
     859           7 :     return f_input;
     860             : }
     861             : 
     862             : 
     863             : /** \brief Setup the output I/O to the process.
     864             :  *
     865             :  * This function defines the output pipe or file that is to be used as
     866             :  * the process output. If this function never gets called, stdout is used.
     867             :  *
     868             :  * \param[in] output  The output I/O object to use as the process output.
     869             :  *
     870             :  * \sa get_output_io()
     871             :  */
     872           4 : void process::set_output_io(io::pointer_t output)
     873             : {
     874           4 :     if((output->get_flags() & IO_FLAG_OUTPUT) == 0)
     875             :     {
     876           0 :         throw cppprocess_incorrect_pipe_type("incorrect I/O type, expected an I/O object that supports OUTPUT.");
     877             :     }
     878             : 
     879           4 :     f_output = output;
     880           4 : }
     881             : 
     882             : 
     883             : /** \brief Get a copy of the output I/O pointer.
     884             :  *
     885             :  * This function returns a pointer to the output I/O object saved in
     886             :  * this cppprocess object. By default, this is a null pointer. A null
     887             :  * pointer is equivalent to stdout.
     888             :  *
     889             :  * \return The output output I/O object to use as the process output.
     890             :  *
     891             :  * \sa set_output_io()
     892             :  */
     893           8 : io::pointer_t process::get_output_io() const
     894             : {
     895           8 :     return f_output;
     896             : }
     897             : 
     898             : 
     899             : /** \brief Setup the error I/O to the process.
     900             :  *
     901             :  * This function defines the error pipe or file that is to be used as
     902             :  * the process error stream. If this function never gets called, stderr
     903             :  * is used.
     904             :  *
     905             :  * \param[in] error  The error I/O object to use as the process error.
     906             :  *
     907             :  * \sa get_error_io()
     908             :  */
     909           1 : void process::set_error_io(io::pointer_t error)
     910             : {
     911           1 :     if((error->get_flags() & IO_FLAG_OUTPUT) == 0)
     912             :     {
     913           0 :         throw cppprocess_incorrect_pipe_type("incorrect I/O type, expected an I/O object that supports OUTPUT.");
     914             :     }
     915             : 
     916           1 :     f_error = error;
     917           1 : }
     918             : 
     919             : 
     920             : /** \brief Get a copy of the error I/O pointer.
     921             :  *
     922             :  * This function returns a pointer to the error I/O object saved in
     923             :  * this cppprocess object. By default, this is a null pointer. A null
     924             :  * pointer is equivalent to stdin.
     925             :  *
     926             :  * \return The error error I/O object to use as the process error.
     927             :  *
     928             :  * \sa set_error_io()
     929             :  */
     930           6 : io::pointer_t process::get_error_io() const
     931             : {
     932           6 :     return f_error;
     933             : }
     934             : 
     935             : 
     936             : /** \brief Pipe the output of this process to the next process.
     937             :  *
     938             :  * This function is used to pipe processes one after the other.
     939             :  *
     940             :  * The next process receives as input the output of this process,
     941             :  * in effect creating a pipeline of Unix processes.
     942             :  *
     943             :  * The function is called "add" (next process) because you can
     944             :  * pipe the output of one process to any number of processes'
     945             :  * input pipe. This is done by one of our internal pipe object
     946             :  * which is capable of such a feat.
     947             :  *
     948             :  * \note
     949             :  * The pipes created in this case are created internally and you
     950             :  * have no direct or indirect access to them except from within
     951             :  * the processes added here.
     952             :  *
     953             :  * \param[in] next  A process that will receive the output of this
     954             :  * process as input.
     955             :  */
     956           2 : void process::add_next_process(pointer_t next)
     957             : {
     958           2 :     f_next.push_back(next);
     959           2 : }
     960             : 
     961             : 
     962             : /** \brief Clear the list of next processes.
     963             :  *
     964             :  * This function clears the list of all the next processes defined
     965             :  * in this process, cutting off the pipeline.
     966             :  */
     967           0 : void process::clear_next_process()
     968             : {
     969           0 :     f_next.clear();
     970           0 : }
     971             : 
     972             : 
     973             : /** \brief Retrieve the list of next processes.
     974             :  *
     975             :  * This function returns the list of next processes as created by the
     976             :  * add_next_process() function.
     977             :  *
     978             :  * A next process receives as input the output of this process--i.e.
     979             :  * if creates a pair of piped processes. Any number of processes
     980             :  * can be piped in this manner.
     981             :  *
     982             :  * When the list is empty, the output is instead sent to the output
     983             :  * pipe connection or, if not such pipe is defined, to the output
     984             :  * buffer which you can retrieve later.
     985             :  *
     986             :  * If there is more than one next process, then the process creates
     987             :  * a process_tee class which is used to send the output of this
     988             :  * process to all the following processes.
     989             :  *
     990             :  * \return The list of processes to run after this one.
     991             :  */
     992           2 : process::list_t process::get_next_processes() const
     993             : {
     994           2 :     return f_next;
     995             : }
     996             : 
     997             : 
     998             : /** \brief Retrieve the child process identifier.
     999             :  *
    1000             :  * After you called the start() function, the process identifier is defined
    1001             :  * as whatever fork() returned to the parent process. This is the pid_t
    1002             :  * as it appears in the list of processes.
    1003             :  *
    1004             :  * Before start() is called and after done() returns, the process
    1005             :  * identifier is set to -1 (i.e. no process). This means the pid is
    1006             :  * first defined a little after the new process started and cleared
    1007             :  * back to -1 a little after it exited.
    1008             :  *
    1009             :  * \return The process PID.
    1010             :  */
    1011           0 : pid_t process::process_pid() const
    1012             : {
    1013           0 :     return f_child;
    1014             : }
    1015             : 
    1016             : 
    1017             : /** \brief Start the process.
    1018             :  *
    1019             :  * This function creates all the necessary things that the process requires
    1020             :  * and start the command or chain of commands.
    1021             :  *
    1022             :  * If the function encounters problems before it can run the child process,
    1023             :  * it returns -1.
    1024             :  *
    1025             :  * The function uses `fork()` and `execvpe()` to start each process. That
    1026             :  * way the processes are started in the background. This function doesn't
    1027             :  * wait for the processes to be done.
    1028             :  *
    1029             :  * The input can be set to your own io_data_pipe or io_input_file object. If
    1030             :  * neither is specified, the process is given your stdin.
    1031             :  *
    1032             :  * The output can be set your own io_capture_pipe or io_output_file object.
    1033             :  * If neither is specified, the process is given your stdout.
    1034             :  *
    1035             :  * Like the output, the error stream can be captured (io_capture_pipe) or
    1036             :  * sent to a file (io_error_file). It otherwise defaults to stderr. Note
    1037             :  * that an io_error_file is very much the same of an io_output_file (it
    1038             :  * derives from it). It allows you to distinguish the two type of object
    1039             :  * if such a need arise in your code.
    1040             :  *
    1041             :  * If you are not using ed::communicator (or at least you did not yet call
    1042             :  * the ed::communicator::run() function), you can wait on the process with
    1043             :  * the wait() function. This function will call the ed::communicator::run()
    1044             :  * loop. If you supplied your own pipes, you'll want to make sure to close
    1045             :  * them and remove them from the ed::communicator once done with them
    1046             :  * otherwise the wait() function will be stuck forever. The SIGCHLD signal
    1047             :  * is also automatically handled by the wait() function.
    1048             :  *
    1049             :  * If you are already using the ed::communicator loop, then you only want
    1050             :  * to respond to the events that you receive and the pipes get closed and
    1051             :  * the executables exit. The process can be assigned a callback using the
    1052             :  * set_process_done() function. The I/O objects (pipes, files) can be
    1053             :  * assigned a callback with the io::add_process_done_callback() function.
    1054             :  *
    1055             :  * If some of the process setup is considered invalid (a parameter is
    1056             :  * set when it is not expected), then the call may generate an exception.
    1057             :  * In that case, you will have to fix your initialization to make everything
    1058             :  * work. One possible issue, when you create a chained set of processes, is
    1059             :  * to add an output capture pipe on a process other than the very last one.
    1060             :  * Note that in case of a chain, some processes may have been created
    1061             :  * successfully and be running before an exception is raised.
    1062             :  *
    1063             :  * \note
    1064             :  * There is one callback per process. However, the pipes can be assigned
    1065             :  * any number of callbacks.
    1066             :  *
    1067             :  * \todo
    1068             :  * Verify all the data before we start any processes. If we are to raise
    1069             :  * an error, then we should do so before any fork() + execvpe().
    1070             :  *
    1071             :  * \return 0 on success or -1 if an error occurs.
    1072             :  *
    1073             :  * \sa wait()
    1074             :  * \sa set_input_io()
    1075             :  * \sa get_input_io()
    1076             :  * \sa set_output_io()
    1077             :  * \sa get_output_io()
    1078             :  * \sa set_error_io()
    1079             :  * \sa get_error_io()
    1080             :  * \sa set_working_directory()
    1081             :  * \sa set_process_done()
    1082             :  */
    1083           6 : int process::start()
    1084             : {
    1085          12 :     if(start_process(
    1086          12 :               ed::pipe_connection::pointer_t()
    1087             :             , 0
    1088          18 :             , io::pointer_t()) != 0)
    1089             :     {
    1090           0 :         return -1;
    1091             :     }
    1092             : 
    1093           6 :     if(!f_next.empty())
    1094             :     {
    1095           2 :         if(f_next.size() != f_prepared_output.size())
    1096             :         {
    1097             :             // the prepare_output() should have generated an error already
    1098             :             // so we should never get here, hence the logic error
    1099             :             //
    1100             :             throw cppprocess_logic_error(
    1101             :                       "incorrect number of output pipes (expected "
    1102           0 :                     + std::to_string(f_next.size())
    1103           0 :                     + ", found "
    1104           0 :                     + std::to_string(f_prepared_output.size())
    1105           0 :                     + ")");
    1106             :         }
    1107             : 
    1108           2 :         int idx(0);
    1109           4 :         for(auto & n : f_next)
    1110             :         {
    1111           8 :             if(n->start_process(
    1112             :                       f_intermediate_output_pipe
    1113             :                     , idx
    1114           6 :                     , f_input) != 0)
    1115             :             {
    1116           0 :                 return -1;
    1117             :             }
    1118           2 :             ++idx;
    1119             :         }
    1120             :     }
    1121             : 
    1122           6 :     if(f_intermediate_output_pipe != nullptr)
    1123             :     {
    1124           2 :         f_intermediate_output_pipe->forked();
    1125             :     }
    1126             : 
    1127           6 :     if(f_next.size() == 1)
    1128             :     {
    1129           4 :         pointer_t n(*f_next.begin());
    1130           2 :         while(n->f_next.size() == 1)
    1131             :         {
    1132           0 :             n = *n->f_next.begin();
    1133             :         }
    1134             : 
    1135           2 :         if(n->f_next.empty())
    1136             :         {
    1137             :             // we found the last item and no tee_pipe
    1138             :             //
    1139           2 :             if(n->f_intermediate_output_pipe != nullptr)
    1140             :             {
    1141           0 :                 n->f_intermediate_output_pipe->forked();
    1142             :             }
    1143             :         }
    1144             :     }
    1145             : 
    1146           6 :     return 0;
    1147             : }
    1148             : 
    1149             : 
    1150             : /** \brief Wait for the command to be done.
    1151             :  *
    1152             :  * If you are using the ed::communicator and start a command, you will
    1153             :  * receive an event whenever the command is done. However, if you are
    1154             :  * not using ed::comminocator, this function helps you in hiding the
    1155             :  * grueling details on how to handle the event loop just to wait for
    1156             :  * a command to run.
    1157             :  *
    1158             :  * \exception cppprocess_recursive_call
    1159             :  * However, if you use ed::communicator and are already in the run()
    1160             :  * function, you can't call this function. It will raise this exception
    1161             :  * if you tried to do so. Of course, it is assumed that you also called
    1162             :  * the start() function to actually start the process.
    1163             :  *
    1164             :  * \exception cppprocess_not_started
    1165             :  * If one of the processes was not started (this process or one of its
    1166             :  * next processes) then this exception is raised.
    1167             :  *
    1168             :  * \return The exit code from the command.
    1169             :  */
    1170           6 : int process::wait()
    1171             : {
    1172           6 :     if(f_communicator->is_running())
    1173             :     {
    1174           0 :         throw cppprocess_recursive_call("you already are in the communicator::run() function, you cannot call process::wait().");
    1175             :     }
    1176             : 
    1177           6 :     if(f_child == -1
    1178           6 :     || !f_running)
    1179             :     {
    1180           0 :         throw cppprocess_not_started("the process was not started or already died.");
    1181             :     }
    1182             : 
    1183          12 :     list_t n(f_next);
    1184           8 :     for(auto & it : n)
    1185             :     {
    1186           4 :         if(it->f_child == -1
    1187           2 :         || !it->f_running)
    1188             :         {
    1189           0 :             throw cppprocess_not_started("one of the next processes was not started or already died.");
    1190             :         }
    1191             : 
    1192           2 :         n.insert(n.end(), it->f_next.begin(), it->f_next.end());
    1193             :     }
    1194             : 
    1195          12 :     ed::signal_child::pointer_t child_signal(ed::signal_child::get_instance());
    1196             : 
    1197             :     // this object may not have a shared pointer so we can't add it to the
    1198             :     // `n` list; for this reason we have to have a special case, unfortunately
    1199             :     //
    1200          12 :     child_signal->add_listener(
    1201             :               f_child
    1202          12 :             , std::bind(&process::child_done, this, std::placeholders::_1));
    1203             : 
    1204           8 :     for(auto & it : n)
    1205             :     {
    1206           6 :         child_signal->add_listener(
    1207           2 :                   it->f_child
    1208           4 :                 , std::bind(&process::child_done, it.get(), std::placeholders::_1));
    1209             :     }
    1210             : 
    1211           6 :     f_communicator->run();
    1212             : 
    1213          12 :     return f_exit_code;
    1214             : }
    1215             : 
    1216             : 
    1217             : /** \brief Return the exit code of the command.
    1218             :  *
    1219             :  * This function returns the exit code of the command once it exited.
    1220             :  * Up until the exit code is know, this function returns -1.
    1221             :  *
    1222             :  * If you call the wait() function, then you also get the exit code
    1223             :  * returned unless an error occurs.
    1224             :  *
    1225             :  * \return The exit code of the process or -1 if still undefined.
    1226             :  */
    1227           0 : int process::exit_code() const
    1228             : {
    1229           0 :     return f_exit_code;
    1230             : }
    1231             : 
    1232             : 
    1233           8 : void process::child_done(ed::child_status status)
    1234             : {
    1235             :     // note that all the child_done() callbacks get called because the
    1236             :     // communicator does not (currently) have any idea of which one needs
    1237             :     // to be called so here we make sure we only handle the correct one
    1238             :     //
    1239             : #ifdef _DEBUG
    1240           8 :     if(status.child_pid() != f_child)
    1241             :     {
    1242             :         throw cppprocess_logic_error(
    1243             :             "child pid mismatch in process::child_done(),"
    1244             :             " please check that you used the correct PID when binding"
    1245           0 :             " this function.");
    1246             :     }
    1247             : #endif
    1248             : 
    1249           8 :     f_exit_code = status.exit_code();
    1250             : 
    1251           8 :     if(f_process_done != nullptr)
    1252             :     {
    1253           0 :         f_process_done(status);
    1254             :     }
    1255             : 
    1256           8 :     f_child = -1;
    1257           8 : }
    1258             : 
    1259             : 
    1260             : /** \brief Prepare the FIFOs and start the process.
    1261             :  *
    1262             :  * This function prepares the input and output FIFOs and then it starts
    1263             :  * the child process with the fork() and then a call to the
    1264             :  * execute_command() function is calls the execvpe() in the child process.
    1265             :  *
    1266             :  * The parent process also closses the other other side of the pipes so
    1267             :  * everything exits as expected.
    1268             :  *
    1269             :  * The call fails if (1) the process is already marked as running, (2) the
    1270             :  * fork command fails. It may also raise an exception if it detects an
    1271             :  * invalid parameter or the setup is considered invalid.
    1272             :  *
    1273             :  * \param[in] output_fifo  The output FIFO in a chain or nullptr.
    1274             :  * \param[in] output_index  The output index in the chain.
    1275             :  * \param[in] input_fifo  The input FIFO in a chain or nullptr.
    1276             :  *
    1277             :  * \return 0 in case the fork() happened successfully, -1 if the fork()
    1278             :  * failed or the function detected that the process was already running.
    1279             :  */
    1280           8 : int process::start_process(
    1281             :           ed::pipe_connection::pointer_t output_fifo
    1282             :         , int output_index
    1283             :         , io::pointer_t input_fifo)
    1284             : {
    1285           8 :     if(f_running)
    1286             :     {
    1287             :         // already running
    1288             :         //
    1289           0 :         return -1;
    1290             :     }
    1291             : 
    1292             :     // prepare the pipes
    1293             :     //
    1294           8 :     prepare_input(output_fifo);
    1295           8 :     prepare_output();
    1296           8 :     prepare_error();
    1297             : 
    1298           8 :     f_child = fork();
    1299           8 :     switch(f_child)
    1300             :     {
    1301           0 :     case -1:
    1302             :         // an error occurred
    1303             :         //
    1304           0 :         return -1;
    1305             : 
    1306           0 :     case 0:
    1307             :         // child
    1308             :         //
    1309             :         // we want to run the execvpe() command
    1310             :         //
    1311           0 :         execute_command(output_fifo, output_index, input_fifo);
    1312             : 
    1313             :         // the child can't safely return so just exit now
    1314             :         //
    1315           0 :         exit(1);
    1316             :         snapdev::NOT_REACHED();
    1317             :         return -1;
    1318             : 
    1319           8 :     default:
    1320             :         // parent
    1321             :         //
    1322           8 :         if(f_input != nullptr)
    1323             :         {
    1324           4 :             f_input->close_other();
    1325             :         }
    1326           8 :         if(f_output != nullptr)
    1327             :         {
    1328           4 :             f_output->close_other();
    1329             :         }
    1330             : 
    1331             : // this one is done outside, here it's too soon in the case of a pipeline
    1332             : // since we need both sides to create the next process
    1333             : //
    1334             : //        if(f_intermediate_output_pipe != nullptr)
    1335             : //        {
    1336             : //            f_intermediate_output_pipe->forked();
    1337             : //        }
    1338             : 
    1339           8 :         if(f_error != nullptr)
    1340             :         {
    1341           1 :             f_error->close_other();
    1342             :         }
    1343             : 
    1344           8 :         f_running = true;
    1345             : 
    1346           8 :         return 0;
    1347             : 
    1348             :     }
    1349             :     snapdev::NOT_REACHED();
    1350             : }
    1351             : 
    1352             : 
    1353             : /** \brief Execute the command.
    1354             :  *
    1355             :  * This function calls the execvpe() function after initializing all the
    1356             :  * pipes, the working directory, the arguments, the environment, etc.
    1357             :  *
    1358             :  * The function returns if an error occurs, otherwise it never returns
    1359             :  * since it calls the execvpe() function.
    1360             :  *
    1361             :  * The function accepts input and output FIFO pointers because of the
    1362             :  * piping capability of the class. The input and output FIFO may be
    1363             :  * intermediate pipes and not the pipes you defined as the input of
    1364             :  * the chain and the output of the chain.
    1365             :  *
    1366             :  * \param[in] output_fifo  The pipe to use as the output.
    1367             :  * \param[in] output_index  Index in the list of piped processes.
    1368             :  * \param[in] input_fifo  The pipe to use as the input.
    1369             :  */
    1370           0 : void process::execute_command(
    1371             :           ed::pipe_connection::pointer_t output_fifo
    1372             :         , int output_index
    1373             :         , io::pointer_t input_fifo)
    1374             : {
    1375             :     // child
    1376             :     //
    1377             :     try
    1378             :     {
    1379           0 :         if(!f_working_directory.empty())
    1380             :         {
    1381           0 :             int const r(chdir(f_working_directory.c_str()));
    1382           0 :             if(r != 0)
    1383             :             {
    1384           0 :                 int const e(errno);
    1385             :                 throw cppprocess_directory_not_found(
    1386             :                             "chdir() to \""
    1387           0 :                             + f_working_directory
    1388           0 :                             + "\" failed with: errno="
    1389           0 :                             + std::to_string(e)
    1390           0 :                             + ", "
    1391           0 :                             + strerror(e));
    1392             :             }
    1393             :         }
    1394             : 
    1395             :         // convert arguments so we can use them with execvpe()
    1396             :         //
    1397           0 :         std::vector<char const *> args_strings;
    1398           0 :         args_strings.reserve(1 + f_arguments.size() + 1);
    1399           0 :         args_strings.push_back(f_command.c_str());
    1400           0 :         for(auto const & a : f_arguments)
    1401             :         {
    1402           0 :             args_strings.push_back(a.c_str());
    1403             :         }
    1404           0 :         args_strings.push_back(nullptr); // NULL terminated
    1405             : 
    1406             :         // convert the environment variables so we can use them with execvpe()
    1407             :         //
    1408           0 :         environment_map_t src_envs(f_environment);
    1409           0 :         if(!f_forced_environment)
    1410             :         {
    1411             :             // since we do not limit the child to only the specified
    1412             :             // environment, add ours but do not overwrite anything
    1413             :             //
    1414           0 :             for(char ** env(environ); *env != nullptr; ++env)
    1415             :             {
    1416           0 :                 char const * s(*env);
    1417           0 :                 char const * n(s);
    1418           0 :                 while(*s != '\0')
    1419             :                 {
    1420           0 :                     if(*s == '=')
    1421             :                     {
    1422           0 :                         std::string const name(n, s - n);
    1423             : 
    1424             :                         // do not overwrite user overridden values
    1425             :                         //
    1426           0 :                         if(src_envs.find(name) == src_envs.end())
    1427             :                         {
    1428             :                             // in Linux all is UTF-8 so we are already good here
    1429             :                             //
    1430           0 :                             src_envs[name] = s + 1;
    1431             :                         }
    1432           0 :                         break;
    1433             :                     }
    1434           0 :                     ++s;
    1435             :                 }
    1436             :             }
    1437             :         }
    1438           0 :         std::vector<char const *> envs_strings;
    1439           0 :         for(auto const & it : src_envs)
    1440             :         {
    1441           0 :             envs_strings.push_back(strdup((it.first + "=" + it.second).c_str()));
    1442             :         }
    1443           0 :         envs_strings.push_back(nullptr); // NULL terminated
    1444             : 
    1445             :         // replace the stdin and stdout (and optionally stderr)
    1446             :         // with their respective pipes
    1447             :         //
    1448           0 :         if(f_prepared_input != -1)
    1449             :         {
    1450           0 :             if(dup2(f_prepared_input, STDIN_FILENO) < 0)  // stdin
    1451             :             {
    1452           0 :                 throw cppprocess_initialization_failed("dup2() of the stdin pipe failed");
    1453             :             }
    1454             :         }
    1455           0 :         if(f_prepared_output[output_index] != -1)
    1456             :         {
    1457           0 :             if(dup2(f_prepared_output[output_index], STDOUT_FILENO) < 0)  // stdout
    1458             :             {
    1459           0 :                 if(f_prepared_input != -1)
    1460             :                 {
    1461           0 :                     close(f_prepared_input);
    1462             :                 }
    1463           0 :                 throw cppprocess_initialization_failed("dup2() of the stdout pipe failed");
    1464             :             }
    1465             :         }
    1466           0 :         if(f_prepared_error != -1)
    1467             :         {
    1468           0 :             if(dup2(f_prepared_error, STDERR_FILENO) < 0)  // stderr
    1469             :             {
    1470           0 :                 if(f_prepared_input != -1)
    1471             :                 {
    1472           0 :                     close(f_prepared_input);
    1473             :                 }
    1474           0 :                 if(f_prepared_output[output_index] != -1)
    1475             :                 {
    1476           0 :                     close(f_prepared_output[output_index]);
    1477             :                 }
    1478           0 :                 throw cppprocess_initialization_failed("dup2() of the stderr pipe failed");
    1479             :             }
    1480             :         }
    1481             : 
    1482             :         // we duplicated the files we were interested in as required,
    1483             :         // now close all the other pipes
    1484             :         //
    1485           0 :         if(input_fifo != nullptr)
    1486             :         {
    1487           0 :             input_fifo->close_both();
    1488             :         }
    1489           0 :         if(f_input != nullptr)
    1490             :         {
    1491           0 :             f_input->close_both();
    1492             :         }
    1493           0 :         if(f_output != nullptr)
    1494             :         {
    1495           0 :             f_output->close_both();
    1496             :         }
    1497           0 :         if(output_fifo != nullptr)
    1498             :         {
    1499           0 :             output_fifo->close();
    1500             :         }
    1501           0 :         if(f_intermediate_output_pipe != nullptr)
    1502             :         {
    1503           0 :             f_intermediate_output_pipe->close();
    1504             :         }
    1505           0 :         if(f_error != nullptr)
    1506             :         {
    1507           0 :             f_error->close_both();
    1508             :         }
    1509             : 
    1510           0 :         execvpe(
    1511             :             f_command.c_str(),
    1512           0 :             const_cast<char * const *>(&args_strings[0]),
    1513           0 :             const_cast<char * const *>(&envs_strings[0])
    1514             :         );
    1515             : 
    1516             :         // the child returns only if execvp() fails, which is possible
    1517             :         //
    1518           0 :         int const e(errno);
    1519           0 :         SNAP_LOG_FATAL
    1520             :             << "Starting child process \""
    1521             :             << f_command
    1522             :             << " "
    1523           0 :             << snapdev::join_strings(f_arguments, " ")
    1524           0 :             << "\" failed. (errno: "
    1525             :             << e
    1526             :             << " -- "
    1527           0 :             << strerror(e)
    1528             :             << ")"
    1529             :             << SNAP_LOG_SEND;
    1530             :     }
    1531           0 :     catch(cppprocess::cppprocess_exception const & e)
    1532             :     {
    1533           0 :         SNAP_LOG_FATAL
    1534             :             << "process::execute_command(): cppprocess exception caught in child process: "
    1535           0 :             << e.what()
    1536             :             << SNAP_LOG_SEND;
    1537             :     }
    1538           0 :     catch(std::exception const & e)
    1539             :     {
    1540             :         // other libraries may generate other exceptions
    1541             :         //
    1542           0 :         SNAP_LOG_FATAL
    1543             :             << "process::execute_command(): std::exception caught in child process: "
    1544           0 :             << e.what()
    1545             :             << SNAP_LOG_SEND;
    1546             :     }
    1547           0 :     catch(...)
    1548             :     {
    1549           0 :         SNAP_LOG_FATAL
    1550             :             << "process::execute_command(): unknown exception caught in child process!"
    1551             :             << SNAP_LOG_SEND;
    1552             :     }
    1553           0 : }
    1554             : 
    1555             : 
    1556             : /** \brief Setup the input pipe.
    1557             :  *
    1558             :  * This function prepare the input pipe. If this process is a \em next
    1559             :  * process, then the output_fifo will be set to the output of the previous
    1560             :  * process. In effect, this allows us to pipe any number of commands
    1561             :  * automatically and with just one pipe object.
    1562             :  *
    1563             :  * The output_fifo is that pipe file descriptor.
    1564             :  *
    1565             :  * The last process should instead setup an output fifo with the
    1566             :  * set_output_pipe() function.
    1567             :  *
    1568             :  * \note
    1569             :  * If an output fifo gets set in a process other than a last process
    1570             :  * (i.e. a process with at least one next() process), then the function
    1571             :  * throws an error (i.t. invalid setup).
    1572             :  */
    1573           8 : void process::prepare_input(ed::pipe_connection::pointer_t output_fifo)
    1574             : {
    1575             :     // piping between process objects
    1576             :     //
    1577           8 :     if(output_fifo != nullptr)
    1578             :     {
    1579             :         // we are being piped from a previous command, we must be
    1580             :         // using this output_fifo as our input
    1581             :         //
    1582           2 :         if(f_input != nullptr)
    1583             :         {
    1584           0 :             throw cppprocess_invalid_parameters("you cannot pipe a command (add_next()) and define your own input pipe.");
    1585             :         }
    1586             : 
    1587           2 :         f_prepared_input = output_fifo->get_socket();
    1588           2 :         return;
    1589             :     }
    1590             : 
    1591           6 :     if(f_input != nullptr)
    1592             :     {
    1593           4 :         f_input->process_starting();
    1594           4 :         f_prepared_input = f_input->get_other_fd();
    1595             :     }
    1596             :     else
    1597             :     {
    1598           2 :         f_prepared_input = STDIN_FILENO;
    1599             :     }
    1600             : }
    1601             : 
    1602             : 
    1603             : /** \brief Prepare the output pipes.
    1604             :  *
    1605             :  * The output can be unique (99% of the time) or it can be duplicated
    1606             :  * with a tee pipe.
    1607             :  *
    1608             :  * The tee pipe is an internal feature used when a process is piped to
    1609             :  * two or more other processes. Each one of the following processes
    1610             :  * receives a copy of the previous process output.
    1611             :  *
    1612             :  * If there are no output processes, then the output is expected to
    1613             :  * use a pipe that you define with set_output_pipe(). If you don't
    1614             :  * define an output pipe, then stdout is used.
    1615             :  */
    1616           8 : void process::prepare_output()
    1617             : {
    1618             :     // the output has four cases
    1619             :     //
    1620             :     // 1. there is exactly one process following this one
    1621             :     //
    1622             :     //     we need a simple FIFO between the two processes; this is handled
    1623             :     //     internally
    1624             :     //
    1625             :     //     in this case it is illegal for the user to define an output FIFO
    1626             :     //
    1627             :     // 2. there is more than one process following this one (tee-feature)
    1628             :     //
    1629             :     //     we create one output FIFO and each of the following processes
    1630             :     //     will receive a specific input FIFO; our output FIFO will
    1631             :     //     duplicate all the data it receives in all the input FIFOs
    1632             :     //
    1633             :     //     in this case it is illegal for the user to define an output FIFO
    1634             :     //
    1635             :     // 3. no following processes & a user defined output FIFO
    1636             :     //
    1637             :     //     the user output FIFO is used for our stdout
    1638             :     //
    1639             :     // 4. no following processes, no user defined output FIFO, capture is true
    1640             :     //
    1641             :     //     create an internal FIFO and save output in process
    1642             :     //
    1643             :     // 5. no following processes & no user defined output FIFO
    1644             :     //
    1645             :     //     we use the default stdout
    1646             :     //
    1647             : 
    1648           8 :     switch(f_next.size())
    1649             :     {
    1650           6 :     case 0:
    1651             :         // no piping to another process:
    1652             :         //   1. use the user output if defined (f_output)
    1653             :         //   2. otherwise fallback on the use stdout
    1654             :         //
    1655           6 :         if(f_output != nullptr)
    1656             :         {
    1657           4 :             f_output->process_starting();
    1658           4 :             f_prepared_output.push_back(f_output->get_other_fd());
    1659             :         }
    1660             :         else
    1661             :         {
    1662           2 :             f_prepared_output.push_back(STDOUT_FILENO);
    1663             :         }
    1664           6 :         break;
    1665             : 
    1666           2 :     case 1:
    1667             :         // normal case where there is a one to one match
    1668             :         // (i.e. not tee-feature required)
    1669             :         //
    1670           2 :         if(f_output != nullptr)
    1671             :         {
    1672           0 :             throw cppprocess_invalid_parameters("you cannot pipe a command (add_next()) and define your own output pipe in the sender.");
    1673             :         }
    1674           2 :         f_intermediate_output_pipe = std::make_shared<direct_output_to_input_pipe>();
    1675           2 :         f_prepared_output.push_back(f_intermediate_output_pipe->get_other_socket());
    1676             : 
    1677             :         // in this one case, the FIFO works automatically, our communicator
    1678             :         // does not have to intervene -- so no add required
    1679             :         //
    1680             :         //f_communicator->add_connection(f_intermediate_output_pipe);
    1681           2 :         break;
    1682             : 
    1683           0 :     default:
    1684             :         // special case where we create one output pipe that
    1685             :         // distribute the output to N input pipes for the next
    1686             :         // N processes
    1687             :         //
    1688           0 :         if(f_output != nullptr)
    1689             :         {
    1690           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.");
    1691             :         }
    1692           0 :         f_intermediate_output_pipe = std::make_shared<tee_pipe>(f_next.size());
    1693           0 :         for(std::size_t idx(0); idx < f_next.size(); ++idx)
    1694             :         {
    1695           0 :             f_prepared_output.push_back(std::dynamic_pointer_cast<tee_pipe>(f_intermediate_output_pipe)->get_output_pipe(idx)->get_other_socket());
    1696           0 :         }
    1697           0 :         f_communicator->add_connection(f_intermediate_output_pipe);
    1698           0 :         break;
    1699             : 
    1700             :     }
    1701           8 : }
    1702             : 
    1703             : 
    1704             : /** \brief Prepare the error file descriptor.
    1705             :  *
    1706             :  * This function prepares the error file descriptor.
    1707             :  *
    1708             :  * The error pipe is set to stderr if you did not setup an error pipe with
    1709             :  * the set_error_pipe() function.
    1710             :  */
    1711           8 : void process::prepare_error()
    1712             : {
    1713           8 :     if(f_error != nullptr)
    1714             :     {
    1715           1 :         f_error->process_starting();
    1716           1 :         f_prepared_error = f_error->get_other_fd();
    1717             :     }
    1718             :     else
    1719             :     {
    1720           7 :         f_prepared_error = STDERR_FILENO;
    1721             :     }
    1722           8 : }
    1723             : 
    1724             : 
    1725             : 
    1726             : /** \brief Send the specified signal to this process.
    1727             :  *
    1728             :  * When the process is running, it is possible to send it a signal using
    1729             :  * this function. The signal is sent immediately.
    1730             :  *
    1731             :  * \param[in] sig  The signal to send to the child process.
    1732             :  *
    1733             :  * \return 0 if the signal was sent, -1 on error and errno is set.
    1734             :  */
    1735           0 : int process::kill(int sig)
    1736             : {
    1737           0 :     if(f_child != -1
    1738           0 :     && f_running)
    1739             :     {
    1740           0 :         return ::kill(f_child, sig);
    1741             :     }
    1742             : 
    1743           0 :     errno = ESRCH;
    1744           0 :     return -1;
    1745             : }
    1746             : 
    1747             : 
    1748             : /** \brief Set process done callback.
    1749             :  *
    1750             :  * This function lets you define a callback which gets called whenever the
    1751             :  * SIGCHLD happens on that process.
    1752             :  *
    1753             :  * \warning
    1754             :  * At the time this function is called, the output is not likely to be
    1755             :  * ready. In most cases, the output buffer gets flushed only at the time
    1756             :  * the process exits and therefore the output on our end not yet ready.
    1757             :  * If you are interested in the output, make sure to use the
    1758             :  * set_output_capture_done() function when you want to get the final
    1759             :  * output.
    1760             :  *
    1761             :  * \param[in] callback  The callback to call when SIGCHLD is received.
    1762             :  */
    1763           0 : void process::set_process_done(process_done_t callback)
    1764             : {
    1765           0 :     f_process_done = callback;
    1766           0 : }
    1767             : 
    1768             : 
    1769             : /** \brief Call this function once down with the output pipe.
    1770             :  *
    1771             :  * This function will remove the intermediate output pipe from the
    1772             :  * communicator. This pipe is an internal pipe created when you don't
    1773             :  * specify your own.
    1774             :  *
    1775             :  * We call this function as soon as we get an error or HUP in the
    1776             :  * pipe managed internally.
    1777             :  */
    1778           0 : void process::input_pipe_done()
    1779             : {
    1780           0 :     if(f_input != nullptr)
    1781             :     {
    1782           0 :         f_input->close_both();
    1783           0 :         f_input.reset();
    1784             :     }
    1785           0 : }
    1786             : 
    1787             : 
    1788             : /** \brief Call this function once down with the output or error pipe.
    1789             :  *
    1790             :  * This function will remove the intermediate output pipe from the
    1791             :  * communicator. This pipe is an internal pipe created when you don't
    1792             :  * specify your own.
    1793             :  *
    1794             :  * We call this function as soon as we get an error or HUP in the
    1795             :  * pipe managed internally.
    1796             :  *
    1797             :  * \param[in] p  The pipe being closed.
    1798             :  */
    1799           0 : void process::output_pipe_done(ed::pipe_connection * p)
    1800             : {
    1801           0 :     if(f_intermediate_output_pipe.get() == p)
    1802             :     {
    1803           0 :         f_communicator->remove_connection(f_intermediate_output_pipe);
    1804           0 :         f_intermediate_output_pipe->close();
    1805           0 :         f_intermediate_output_pipe.reset();
    1806             :     }
    1807             :     //else if(f_internal_error_pipe.get() == p)
    1808             :     //{
    1809             :     //    f_communicator->remove_connection(f_internal_error_pipe);
    1810             :     //    f_internal_error_pipe->close();
    1811             :     //    f_internal_error_pipe.reset();
    1812             : 
    1813             :     //    if(f_error_done_callback != nullptr)
    1814             :     //    {
    1815             :     //        f_error_done_callback(get_error());
    1816             :     //    }
    1817             :     //}
    1818           0 :     else if(f_next.size() == 1)
    1819             :     {
    1820             :         // for the tee, we're not internally responsible for final output
    1821             :         // pipes, but when only one we want to take care of it here
    1822             :         //
    1823           0 :         pointer_t n(*f_next.begin());
    1824           0 :         while(n->f_next.size() != 0)
    1825             :         {
    1826           0 :             if(n->f_next.size() != 1)
    1827             :             {
    1828           0 :                 return;
    1829             :             }
    1830           0 :             n = *n->f_next.begin();
    1831             :         }
    1832           0 :         if(n->f_intermediate_output_pipe.get() == p)
    1833             :         {
    1834           0 :             f_communicator->remove_connection(n->f_intermediate_output_pipe);
    1835           0 :             n->f_intermediate_output_pipe->close();
    1836           0 :             n->f_intermediate_output_pipe.reset();
    1837             :         }
    1838             :     }
    1839             : }
    1840             : 
    1841             : 
    1842             : 
    1843           6 : } // namespace cppprocess
    1844             : // vim: ts=4 sw=4 et

Generated by: LCOV version 1.13