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
|