00001 /** 00002 * @file child_reader.h 00003 * Facility for reading from child processes 00004 * 00005 * @remark Copyright 2002 OProfile authors 00006 * @remark Read the file COPYING 00007 * 00008 * @author Philippe Elie 00009 * @author John Levon 00010 */ 00011 00012 #ifndef CHILD_READER_H 00013 #define CHILD_READER_H 00014 00015 #include <sys/types.h> 00016 00017 #include <vector> 00018 #include <string> 00019 00020 /** 00021 * a class to read stdout / stderr from a child process. 00022 * 00023 * two interfaces are provided. read line by line: getline() or read all data 00024 * in one : get_data(). In all case get_data() must be called once to flush the 00025 * stderr child output 00026 */ 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: 00041 /** fork a process. use error() to get error code. Do not try to 00042 * use other public member interface if error() return non-zero */ 00043 child_reader(std::string const & cmd, 00044 std::vector<std::string> const & args); 00045 00046 /** wait for the termination of the child process if this have not 00047 * already occur. In this case return code of the child process is not 00048 * available. */ 00049 ~child_reader(); 00050 00051 /** fill result from on line of stdout of the child process. 00052 * must be used as: 00053 * child_reader reader(...); 00054 * while (reader.getline(line)) .... */ 00055 bool getline(std::string & result); 00056 00057 /** fill out / err with the stdout / stderr of the child process. 00058 * You can call this after calling one or more time getline(...). This 00059 * call is blocking until the child die and so on all subsequent 00060 * call will fail */ 00061 bool get_data(std::ostream & out, std::ostream & err); 00062 00063 /** rather to rely on dtor to wait for the termination of the child you 00064 * can use terminate_process() to get the return code of the child 00065 * process */ 00066 int terminate_process(); 00067 00068 /** return the status of the first error encoutered 00069 * != 0 : something feel wrong, use error_str() to get an error 00070 * message */ 00071 int error() const { return first_error; } 00072 00073 /** 00074 * return an error message if appropriate, if the process has 00075 * been successfully exec'ed and is not terminate the error message 00076 * is always empty. Error message is also empty if the child process 00077 * terminate successfully. Else three type of error message exist: 00078 * - "unable to fork" followed by sterror(errno) 00079 * - "process_name return xxx" xxx is return code 00080 * - "process_name terminated by signal xxx" xxx is signal number 00081 */ 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
1.6.1