00001 00012 #ifndef CHILD_READER_H 00013 #define CHILD_READER_H 00014 00015 #include <sys/types.h> 00016 00017 #include <vector> 00018 #include <string> 00019 00027 /* 00028 * FIXME: code review is needed: 00029 * - check the getline()/get_data()/block_read() interface. 00030 * the expected behavior is: 00031 * caller can call getline until nothing is available from the stdout of the 00032 * child. in this case child stderr is acumulated in buf2 and can be read 00033 * through get_data(). get_data() is blocking until the child close stderr / 00034 * stdout (even if the child die by a signal ?). The following corner case must 00035 * work but I'm unsure if the code reflect this behavior: the last line of the 00036 * child stdout have not necessarilly a LF terminator. the child can output any 00037 * size of data in stderr. 00038 */ 00039 class child_reader { 00040 public: 00043 child_reader(std::string const & cmd, 00044 std::vector<std::string> const & args); 00045 00049 ~child_reader(); 00050 00055 bool getline(std::string & result); 00056 00061 bool get_data(std::ostream & out, std::ostream & err); 00062 00066 int terminate_process(); 00067 00071 int error() const { return first_error; } 00072 00082 std::string error_str() const; 00083 00084 private: 00085 // ctor helper: create the child process. 00086 void exec_command(std::string const & cmd, 00087 std::vector<std::string> const & args); 00088 // return false when eof condition is reached on fd1. fd2 can have 00089 // already input in the pipe buffer or in buf2. 00090 bool block_read(); 00091 00092 int fd1; 00093 int fd2; 00094 ssize_t pos1; 00095 ssize_t end1; 00096 ssize_t pos2; 00097 ssize_t end2; 00098 pid_t pid; 00099 int first_error; 00100 // child stderr is handled especially, we need to retain data even 00101 // if caller read only stdout of the child. 00102 char * buf2; 00103 ssize_t sz_buf2; 00104 char * buf1; 00105 std::string process_name; 00106 bool is_terminated; 00107 bool terminate_on_exception; 00108 bool forked; 00109 }; 00110 00111 #endif // CHILD_READER_H