Home | History | Annotate | Download | only in libutil++
      1 /**
      2  * @file child_reader.h
      3  * Facility for reading from child processes
      4  *
      5  * @remark Copyright 2002 OProfile authors
      6  * @remark Read the file COPYING
      7  *
      8  * @author Philippe Elie
      9  * @author John Levon
     10  */
     11 
     12 #ifndef CHILD_READER_H
     13 #define CHILD_READER_H
     14 
     15 #include <sys/types.h>
     16 
     17 #include <vector>
     18 #include <string>
     19 
     20 /**
     21  * a class to read stdout / stderr from a child process.
     22  *
     23  * two interfaces are provided. read line by line: getline() or read all data
     24  * in one : get_data(). In all case get_data() must be called once to flush the
     25  * stderr child output
     26  */
     27 /*
     28  * FIXME: code review is needed:
     29  *  - check the getline()/get_data()/block_read() interface.
     30  *  the expected behavior is:
     31  *  caller can call getline until nothing is available from the stdout of the
     32  * child. in this case child stderr is acumulated in buf2 and can be read
     33  * through get_data(). get_data() is blocking until the child close stderr /
     34  * stdout (even if the child die by a signal ?). The following corner case must
     35  * work but I'm unsure if the code reflect this behavior: the last line of the
     36  * child stdout have not necessarilly a LF terminator. the child can output any
     37  * size of data in stderr.
     38  */
     39 class child_reader {
     40 public:
     41 	/** fork a process. use error() to get error code. Do not try to
     42 	 * use other public member interface if error() return non-zero */
     43 	child_reader(std::string const & cmd,
     44 		std::vector<std::string> const & args);
     45 
     46 	/** wait for the termination of the child process if this have not
     47 	 * already occur. In this case return code of the child process is not
     48 	 * available. */
     49 	~child_reader();
     50 
     51 	/** fill result from on line of stdout of the child process.
     52 	 * must be used as:
     53 	 * child_reader reader(...);
     54 	 * while (reader.getline(line)) .... */
     55 	bool getline(std::string & result);
     56 
     57 	/** fill out / err with the stdout / stderr of the child process.
     58 	 * You can call this after calling one or more time getline(...). This
     59 	 * call is blocking until the child die and so on all subsequent
     60 	 * call will fail */
     61 	bool get_data(std::ostream & out, std::ostream & err);
     62 
     63 	/** rather to rely on dtor to wait for the termination of the child you
     64 	 * can use terminate_process() to get the return code of the child
     65 	 * process */
     66 	int terminate_process();
     67 
     68 	/** return the status of the first error encoutered
     69 	 * != 0 : something feel wrong, use error_str() to get an error
     70 	 * message */
     71 	int error() const { return first_error; }
     72 
     73 	/**
     74 	 * return an error message if appropriate, if the process has
     75 	 * been successfully exec'ed and is not terminate the error message
     76 	 * is always empty. Error message is also empty if the child process
     77 	 * terminate successfully. Else three type of error message exist:
     78 	 *  - "unable to fork" followed by sterror(errno)
     79 	 *  - "process_name return xxx"  xxx is return code
     80 	 *  - "process_name terminated by signal xxx" xxx is signal number
     81 	 */
     82 	std::string error_str() const;
     83 
     84 private:
     85 	// ctor helper: create the child process.
     86 	void exec_command(std::string const & cmd,
     87 			  std::vector<std::string> const & args);
     88 	// return false when eof condition is reached on fd1. fd2 can have
     89 	// already input in the pipe buffer or in buf2.
     90 	bool block_read();
     91 
     92 	int fd1;
     93 	int fd2;
     94 	ssize_t pos1;
     95 	ssize_t end1;
     96 	ssize_t pos2;
     97 	ssize_t end2;
     98 	pid_t pid;
     99 	int first_error;
    100 	// child stderr is handled especially, we need to retain data even
    101 	// if caller read only stdout of the child.
    102 	char * buf2;
    103 	ssize_t sz_buf2;
    104 	char * buf1;
    105 	std::string process_name;
    106 	bool is_terminated;
    107 	bool terminate_on_exception;
    108 	bool forked;
    109 };
    110 
    111 #endif // CHILD_READER_H
    112