00001 #include <sys/wait.h>
00002 #include <sys/types.h>
00003 #include <sys/stat.h>
00004 #include <dirent.h>
00005 #include <fcntl.h>
00006 #include <poll.h>
00007 #include <signal.h>
00008 #include <sys/ioctl.h>
00009 #include <errno.h>
00010 #include <string.h>
00011 #include "process.h"
00012
00013 Process::Process()
00014 {
00015 for(int i = 0; i < 3; i++)
00016 {
00017 if(pipe(pipes[i]) == -1)
00018 fprintf(stderr, "Unable to call pipe: %s\n", strerror(errno));
00019 }
00020 pid = 0;
00021 last_socket_read = 0;
00022 exit_code = -1;
00023
00024 memset(&sock_set, 0, sizeof(sock_set));
00025 FD_ZERO(&sock_set);
00026 };
00027
00028 Process::~Process()
00029 {
00030 for(std::map<int, int>::iterator it = output_sock_list.begin(); it != output_sock_list.end(); ++it)
00031 FD_CLR(it->first, &sock_set);
00032 FD_ZERO(&sock_set);
00033 close(pipes[0][1]);
00034 close(pipes[1][0]);
00035 close(pipes[2][0]);
00036 }
00037
00038 std::string Process::Start(char* file, char** argv)
00039 {
00040 if(pid != 0)
00041 return std::string("A process has already been started");
00042
00043 pid = fork();
00044 if(pid == -1)
00045 {
00046 pid = 0;
00047 return std::string("Fork failed: ") + std::string(strerror(errno));
00048 }
00049
00050 if (pid == 0)
00051 {
00052
00053 close(pipes[0][1]);
00054 close(pipes[1][0]);
00055 close(pipes[2][0]);
00056
00057 dup2(pipes[0][0], 0);
00058 dup2(pipes[1][1], 1);
00059 dup2(pipes[2][1], 2);
00060
00061 ChildOnFork();
00062
00063 if(execvp(file, argv) == -1)
00064 return std::string("Execvp failed: ") + std::string(strerror(errno));
00065 }
00066 else
00067 {
00068 close(pipes[0][0]);
00069 close(pipes[1][1]);
00070 close(pipes[2][1]);
00071 output_sock_list.insert(std::make_pair(pipes[1][0], 1));
00072 output_sock_list.insert(std::make_pair(pipes[2][0], 2));
00073 for(std::map<int, int>::iterator it = output_sock_list.begin(); it != output_sock_list.end(); ++it)
00074 FD_SET(it->first, &sock_set);
00075 ParentOnFork();
00076 }
00077 return "";
00078 }
00079
00080 std::string Process::Fork()
00081 {
00082 pid = fork();
00083 if(pid == -1)
00084 {
00085 pid = 0;
00086 return std::string("Fork failed: ") + std::string(strerror(errno));
00087 }
00088
00089 if (pid == 0)
00090 ChildOnFork();
00091 else
00092 ParentOnFork();
00093 return "";
00094 }
00095
00096 int Process::GetPID()
00097 {
00098 return pid;
00099 }
00100
00101 std::string Process::GetOutput(char* buf, unsigned int &len, int& active_socket)
00102 {
00103 if(!pid)
00104 return std::string("No process running");
00105
00106 std::string err = HandleEvents();
00107 if(err != "")
00108 return err;
00109
00110 active_socket = -1;
00111
00112 struct timeval timeout;
00113 memset(&timeout, 0, sizeof(struct timeval));
00114 timeout.tv_sec = 0;
00115 timeout.tv_usec = 1;
00116
00117 fd_set acting_socket = sock_set;
00118
00119 if ( select(FD_SETSIZE, &acting_socket, NULL, NULL, &timeout) < 0)
00120 {
00121 if(timeout.tv_sec != 0 && timeout.tv_usec != 0)
00122 return std::string("Select failed: ") + std::string(strerror(errno));
00123 }
00124
00125 for(std::map<int, int>::iterator it = output_sock_list.begin(); it != output_sock_list.end(); ++it)
00126 {
00127 if(FD_ISSET(it->first, &acting_socket))
00128 {
00129 active_socket = it->first;
00130 break;
00131 }
00132 }
00133
00134 if(active_socket == -1)
00135 {
00136 len = 0;
00137 return std::string("");
00138 }
00139
00140 ssize_t read_len;
00141 if((read_len = read(active_socket, buf, len)) == -1)
00142 {
00143 len = 0;
00144 std::string err = std::string("Read failed: ") + std::string(strerror(errno));
00145 FD_CLR(active_socket, &sock_set);
00146 std::map<int, int>::iterator sock_to_delete;
00147 sock_to_delete = output_sock_list.find(active_socket);
00148 output_sock_list.erase(sock_to_delete);
00149 active_socket = -1;
00150 return err;
00151 }
00152
00153 if(read_len == 0)
00154 {
00155 FD_CLR(active_socket, &sock_set);
00156 std::map<int, int>::iterator sock_to_delete;
00157 sock_to_delete = output_sock_list.find(active_socket);
00158 active_socket = sock_to_delete->second;
00159 output_sock_list.erase(sock_to_delete);
00160 }
00161 else
00162 {
00163 std::map<int, int>::iterator sock_active;
00164 sock_active = output_sock_list.find(active_socket);
00165 active_socket = sock_active->second;
00166 }
00167
00168 len = (unsigned int)read_len;
00169 return std::string("");
00170 }
00171
00172 int Process::GetExitCode()
00173 {
00174 return exit_code;
00175 }
00176
00177 std::string Process::SendStdin(char* buf, int len)
00178 {
00179 if(!pid)
00180 return std::string("No process running");
00181 std::string err = HandleEvents();
00182 if(err != "")
00183 return err;
00184 if(write(pipes[0][1], buf, len) == -1)
00185 return std::string("Error during write: ") + std::string(strerror(errno));
00186 return "";
00187 }
00188
00189 void Process::SendStdinClose()
00190 {
00191 close(pipes[0][1]);
00192 }
00193
00194 std::string Process::HandleEvents()
00195 {
00196 if(GetExitCode() != -1)
00197 return std::string("");
00198 int status = 0;
00199
00200 int r = waitpid(GetPID(), &status, WNOHANG);
00201 if(r == -1)
00202 return std::string("waitpid failed: ") + std::string(strerror(errno));
00203 if(r == 0)
00204 return std::string("");
00205
00206 if(WIFEXITED(status))
00207 exit_code = WEXITSTATUS(status);
00208 return "";
00209 }
00210