rvm 1.08
|
00001 #include "config.h" 00002 00003 #include <iostream> 00004 00005 #ifdef HAVE_STDLIB_H 00006 #include <stdlib.h> 00007 #endif 00008 #ifdef HAVE_SYS_TYPES_H 00009 #include <sys/types.h> 00010 #endif 00011 #ifdef HAVE_SYS_WAIT_H 00012 #include <sys/wait.h> 00013 #endif 00014 #ifdef HAVE_UNISTD_H 00015 #include <unistd.h> 00016 #endif 00017 #ifdef HAVE_SIGNAL_H 00018 #include <signal.h> 00019 #endif 00020 #ifdef HAVE_SYS_SELECT_H 00021 #include <sys/select.h> 00022 #endif 00023 #include <sys/time.h> 00024 00025 #include <cerrno> 00026 00027 #include "asserts.h" 00028 #include "error.h" 00029 #include "fs.h" 00030 #include "exec.h" 00031 00032 /** C'tor */ 00033 execute::execute() 00034 { 00035 clear(); 00036 } 00037 00038 /** D'tor */ 00039 execute::~execute() 00040 { 00041 clear(); 00042 } 00043 00044 /** Reset the execute class to default values, kill the child processif one is 00045 * running */ 00046 void execute::clear(void) 00047 { 00048 if (child_running() && is_parent()) 00049 signal_child(SIGKILL); 00050 00051 m_fd1[0] = 0; 00052 m_fd1[1] = 0; 00053 m_fd2[0] = 0; 00054 m_fd2[1] = 0; 00055 m_fd3[0] = 0; 00056 m_fd3[1] = 0; 00057 m_pid = 0; 00058 m_status = 0; 00059 m_in_eof = false; 00060 m_out_eof = false; 00061 m_err_eof = false; 00062 m_child_started = false; 00063 } 00064 00065 /** Generic signal handler */ 00066 static void _signal_handler(int signo) 00067 { 00068 throw(ERROR(0,"Tried to write to a read-only pipe")); 00069 } 00070 00071 /** Fork a child process */ 00072 void execute::fork(void) 00073 { 00074 clear(); 00075 if (signal(SIGPIPE, _signal_handler) == SIG_ERR) 00076 throw(ERROR(errno,"Could not catch SIGPIPIE signal")); 00077 if (pipe(m_fd1) < 0) 00078 throw(ERROR(errno,"Could not create pipe for in")); 00079 if (pipe(m_fd2) < 0) 00080 throw(ERROR(errno,"Could not create pipe for out")); 00081 if (pipe(m_fd3) < 0) 00082 throw(ERROR(errno,"Could not create pipe for err")); 00083 if ((m_pid = ::fork()) < 0) 00084 throw(ERROR(errno,"Could not fork")); 00085 if (m_pid > 0) { 00086 // Parent process 00087 close(m_fd1[0]); 00088 close(m_fd2[1]); 00089 close(m_fd3[1]); 00090 m_child_started = true; 00091 } 00092 else { 00093 // Child process 00094 close(m_fd1[1]); 00095 close(m_fd2[0]); 00096 close(m_fd3[0]); 00097 } 00098 } 00099 00100 /** Returns true if called by the child */ 00101 bool execute::is_child(void) 00102 { 00103 if (m_pid == 0) { 00104 return(true); 00105 } 00106 return(false); 00107 } 00108 00109 /** Returns true if called by the parent */ 00110 bool execute::is_parent(void) 00111 { 00112 bool value; 00113 00114 value = !is_child(); 00115 00116 return(value); 00117 } 00118 00119 /** Returns the PID */ 00120 pid_t execute::my_pid(void) 00121 { 00122 pid_t value; 00123 00124 value = pid(); 00125 00126 return(value); 00127 } 00128 00129 /** Called by the child to exit with a particular code */ 00130 void execute::exit(int code) 00131 { 00132 if (is_child()) 00133 ::exit(code); 00134 } 00135 00136 /** Called by the child to reroute the child's stdin, stdout, and stderr to 00137 * the parent */ 00138 void execute::reroute_stdio(void) 00139 { 00140 if (!is_child()) 00141 return; 00142 00143 if (m_fd1[0] != STDIN_FILENO) { 00144 if (dup2(m_fd1[0], STDIN_FILENO) != STDIN_FILENO) { 00145 error e(errno,ERROR_INSTANCE("dup2() failed for stdin")); 00146 std::cerr << e << std::endl; 00147 exit(127); 00148 } 00149 close(m_fd1[0]); 00150 } 00151 if (m_fd2[1] != STDOUT_FILENO) { 00152 if (dup2(m_fd2[1], STDOUT_FILENO) != STDOUT_FILENO) { 00153 error e(errno,ERROR_INSTANCE("dup2() failed for stdout")); 00154 std::cerr << e << std::endl; 00155 exit(127); 00156 } 00157 close(m_fd2[1]); 00158 } 00159 if (m_fd3[1] != STDERR_FILENO) { 00160 if (dup2(m_fd3[1], STDERR_FILENO) != STDERR_FILENO) { 00161 error e(errno,ERROR_INSTANCE("dup2() failed for stderr")); 00162 std::cerr << e << std::endl; 00163 exit(127); 00164 } 00165 close(m_fd3[1]); 00166 } 00167 } 00168 00169 /** Returns the child's PID */ 00170 pid_t execute::child_pid(void) 00171 { 00172 return(m_pid); 00173 } 00174 00175 /** Send a signal to the child */ 00176 void execute::signal_child(int signal_no) 00177 { 00178 kill(m_pid, signal_no); 00179 } 00180 00181 /** Send a HUP signal to the child */ 00182 void execute::hup_child(void) 00183 { 00184 signal_child(SIGHUP); 00185 } 00186 00187 /** Send a KILL signal to the child */ 00188 void execute::kill_child(void) 00189 { 00190 signal_child(SIGKILL); 00191 } 00192 00193 /** Wait for the child to exit */ 00194 void execute::wait(void) 00195 { 00196 if (is_parent()) { 00197 pid_t value; 00198 value = waitpid(m_pid, &m_status, 0); 00199 } 00200 } 00201 00202 /** Check the child's status */ 00203 pid_t execute::check_child_(void) 00204 { 00205 pid_t value; 00206 00207 errno = 0; 00208 value = waitpid(m_pid, &m_status, WNOHANG|WUNTRACED); 00209 00210 return(value); 00211 } 00212 00213 /** Returns true if the child has been started */ 00214 bool execute::child_started(void) const 00215 { 00216 return(m_child_started); 00217 } 00218 00219 /** Returns true if the child is running */ 00220 bool execute::child_running(void) 00221 { 00222 pid_t pid; 00223 00224 pid = check_child_(); 00225 if (pid > 0) return(false); // The child has exited 00226 if ((pid < 0) && (errno == ECHILD)) return(false); // No such child exists 00227 return(true); 00228 } 00229 00230 /** Returns true of the child has existed */ 00231 bool execute::child_exited(void) 00232 { 00233 pid_t pid; 00234 00235 pid = check_child_(); 00236 if (pid > 0) return(true); 00237 if ((pid < 0) && (errno == ECHILD)) return(true); 00238 return(false); 00239 } 00240 00241 /** Returns true if the child has exited normally */ 00242 bool execute::child_exited_normally(void) 00243 { 00244 bool value; 00245 00246 value = (child_exited() && (child_exit_code() == 0)); 00247 00248 return(value); 00249 } 00250 00251 /** Returns true if the child was signaled */ 00252 bool execute::child_signaled(void) 00253 { 00254 bool value; 00255 00256 check_child_(); 00257 value = WIFSIGNALED(m_status); 00258 00259 return(value); 00260 } 00261 00262 /** Returns true if the child returned exit code 0 and no caught signals */ 00263 bool execute::child_exited_success(void) 00264 { 00265 bool value; 00266 00267 value = (child_exited() && (child_exit_code() == 0) && !child_signaled()); 00268 00269 return(value); 00270 } 00271 00272 /** Return the child's exit code */ 00273 int execute::child_exit_code(void) 00274 { 00275 int value; 00276 00277 check_child_(); 00278 value = WEXITSTATUS(m_status); 00279 00280 return(value); 00281 } 00282 00283 /** If the child was signaled, return the signal number */ 00284 int execute::child_signal_no(void) 00285 { 00286 int value; 00287 00288 check_child_(); 00289 if (child_exited()) { 00290 value = WTERMSIG(m_status); 00291 return(value); 00292 } 00293 else { 00294 value = WSTOPSIG(m_status); 00295 return(value); 00296 } 00297 } 00298 00299 /** Return a file descriptor for I/O between parent and child 00300 00301 If called by the parent, a writeable file descriptor is returned. 00302 If called by the child, a readable file descriptor is returned. 00303 00304 If retroute_stdio() was called by the child, then the returned file 00305 descriptor is the same as that used by the child for stdin. 00306 */ 00307 int execute::in_fd(void) 00308 { 00309 if (is_parent()) { 00310 // Return write end of input pipe 00311 return(m_fd1[1]); 00312 } 00313 else { 00314 // Return read end of input pipe 00315 return(m_fd1[0]); 00316 } 00317 } 00318 00319 /** Return a file descriptor for I/O between parent a child. 00320 00321 If called by the parent, a readable file descriptor is returned. 00322 If called by the child, a writable file descriptor is returned. 00323 00324 If reroute_stdio() was called by the child, then the returned file 00325 descriptor is the same as that used by the child for stdout. 00326 */ 00327 int execute::out_fd(void) 00328 { 00329 if (is_parent()) { 00330 // Return read end of output pipe 00331 return(m_fd2[0]); 00332 } 00333 else { 00334 // Return write end of output pipe 00335 return(m_fd2[1]); 00336 } 00337 } 00338 00339 /** Return a file descriptor for I/O between parent and child. 00340 00341 If called by the parent, a readable file descriptor is returned. 00342 If called by the child, a writeable file descriptor is returned. 00343 00344 If reroute_stdio() was called by the child, then the returned file 00345 descriptior is the same as that used by the child for stderr. 00346 */ 00347 int execute::err_fd(void) 00348 { 00349 if (is_parent()) { 00350 // return read end of error pipe 00351 return(m_fd3[0]); 00352 } 00353 else { 00354 // return write end of error pipe 00355 return(m_fd3[1]); 00356 } 00357 } 00358 00359 /** Return true if the file descriptor is ready to be written to */ 00360 bool execute::check_write_ready_(int fd) 00361 { 00362 struct timeval timeout = { 0, 0 }; 00363 fd_set wset; 00364 00365 FD_ZERO(&wset); 00366 FD_SET(fd, &wset); 00367 select(fd+1, 0, &wset, 0, &timeout); 00368 if (FD_ISSET(fd, &wset)) { 00369 return(true); 00370 } 00371 return(false); 00372 } 00373 00374 /** Return true if the file descriptor has input ready to be read */ 00375 bool execute::check_read_ready_(int fd) 00376 { 00377 struct timeval timeout = { 0, 0 }; 00378 fd_set rset; 00379 00380 FD_ZERO(&rset); 00381 FD_SET(fd, &rset); 00382 select(fd+1, &rset, 0, 0, &timeout); 00383 if (FD_ISSET(fd, &rset)) { 00384 return(true); 00385 } 00386 return(false); 00387 } 00388 00389 /** Execute a command, rerouting stdin, stdout, and stderr to parent */ 00390 void execute::exec(const std::string command) 00391 { 00392 fork(); 00393 if (is_parent()) 00394 return; 00395 00396 /* 00397 { 00398 bool wait_for_debugger = true; 00399 00400 std::cerr << "Waiting for debugger to attach..." << std::endl; 00401 while (wait_for_debugger); 00402 std::cerr << "Debugger attached." << std::endl; 00403 } 00404 */ 00405 reroute_stdio(); 00406 00407 execl("/bin/sh", "sh", "-c", command.c_str(), (char *)0); 00408 exit(127); 00409 } 00410 00411 /** Execute a command, rerouting stdin, stdout, and stderr to parent */ 00412 void execute::exec(const std::string binary, const std::vector<std::string> argv) 00413 { 00414 char *bin = 0; 00415 char *base = 0; 00416 char **args = 0; 00417 uint16 c; 00418 size_t size; 00419 00420 fork(); 00421 if (is_parent()) 00422 return; 00423 00424 /* 00425 { 00426 bool wait_for_debugger = true; 00427 00428 std::cerr << "Waiting for debugger to attach..." << std::endl; 00429 while (wait_for_debugger); 00430 std::cerr << "Debugger attached." << std::endl; 00431 } 00432 */ 00433 00434 reroute_stdio(); 00435 00436 bin = (char *)binary.c_str(); 00437 base = bin+strlen(bin); 00438 while ((base > bin) && (*base != '/')) { 00439 base--; 00440 } 00441 if (*base == '/') { 00442 base++; 00443 } 00444 size = (argv.size() + 2) * sizeof(char *); 00445 args = (char **)malloc(size); 00446 memset((void *)args, 0, size); 00447 if (args == 0) { 00448 exit(127); 00449 } 00450 args[0] = base; 00451 for (c = 0; c < argv.size(); c++) { 00452 args[c+1] = (char *)argv[c].c_str(); 00453 } 00454 args[c+1] = 0; 00455 00456 execv(bin, args); 00457 exit(127); 00458 } 00459 00460 /** Check I/O for input 00461 00462 If called by the parent, check if ready to write to child's input. 00463 If called by the child, check if input is ready to be read. 00464 00465 If reroute_stdio() was called by the child, then this pipe is the same as 00466 used by the child for stdin. 00467 */ 00468 bool execute::in_ready(void) 00469 { 00470 bool value; 00471 00472 if (is_parent()) 00473 value = check_write_ready_(in_fd()); 00474 else 00475 value = check_read_ready_(in_fd()); 00476 00477 return(value); 00478 } 00479 00480 /** Check I/O for output 00481 00482 If called by the parent, check if output from child is ready to be read. 00483 If called by the child, check if output to parent is ready to be written to. 00484 00485 If reroute_stdio() was called by the child, then this pipe is the same as 00486 used by the child for stdout. 00487 */ 00488 bool execute::out_ready(void) 00489 { 00490 bool value; 00491 00492 if (is_parent()) 00493 value = check_read_ready_(out_fd()); 00494 else 00495 value = check_write_ready_(out_fd()); 00496 00497 return(value); 00498 } 00499 00500 /** Check I/O for output 00501 00502 If called by the parent, check if output from child is ready to be read. 00503 If called by the child, check if output to parent is ready to be written to. 00504 00505 If reroute_stdio() was called by the child, then this pipe is the same as 00506 used by the child for stderr. 00507 */ 00508 bool execute::err_ready(void) 00509 { 00510 bool value; 00511 00512 if (is_parent()) 00513 value = check_read_ready_(err_fd()); 00514 else 00515 value = check_write_ready_(err_fd()); 00516 00517 return(value); 00518 } 00519 00520 /** Check for input EOF */ 00521 bool execute::in_eof(void) 00522 { 00523 return(m_in_eof); 00524 } 00525 00526 /** Check for output EOF */ 00527 bool execute::out_eof(void) 00528 { 00529 return(m_out_eof); 00530 } 00531 00532 /** Check for err EOF */ 00533 bool execute::err_eof(void) 00534 { 00535 return(m_err_eof); 00536 } 00537 00538 /** Allow child to read input from in_fd() */ 00539 int execute::in_read(char* buf, const int len) 00540 { 00541 int n; 00542 int err; 00543 00544 n = read(in_fd(), buf, len); 00545 err = errno; 00546 errno = 0; 00547 if (n > 0) { 00548 return(n); 00549 } 00550 if (child_started() && !child_running() && (err != EAGAIN)) 00551 m_in_eof = true; 00552 return(0); 00553 } 00554 00555 /** Allow parent to write output to in_fd() */ 00556 int execute::in_write(const char* buf, const int len) 00557 { 00558 int n; 00559 int err; 00560 00561 n = write(in_fd(), buf, len); 00562 err = errno; 00563 errno = 0; 00564 if (n > 0) { 00565 return(n); 00566 } 00567 if (child_started() && !child_running() && (err != EAGAIN)) 00568 m_in_eof = true; 00569 return(0); 00570 } 00571 00572 /** Allow parent to read out_fd() */ 00573 int execute::out_read(char* buf, const int len) 00574 { 00575 int n; 00576 int err; 00577 00578 n = read(out_fd(), buf, len); 00579 err = errno; 00580 errno = 0; 00581 if (n > 0) { 00582 return(n); 00583 } 00584 if (child_started() && !child_running() && (err != EAGAIN)) 00585 m_out_eof = true; 00586 return(0); 00587 } 00588 00589 /** Allow child to write to out_fd() */ 00590 int execute::out_write(const char* buf, const int len) 00591 { 00592 int n; 00593 int err; 00594 00595 n = write(out_fd(), buf, len); 00596 err = errno; 00597 errno = 0; 00598 if (n > 0) { 00599 return(n); 00600 } 00601 if (child_started() && !child_running() && (err != EAGAIN)) 00602 m_out_eof = true; 00603 return(0); 00604 } 00605 00606 /** Allow parent to read from err_fd() */ 00607 int execute::err_read(char* buf, const int len) 00608 { 00609 int n; 00610 int err; 00611 00612 n = read(err_fd(), buf, len); 00613 err = errno; 00614 errno = 0; 00615 if (n > 0) { 00616 return(n); 00617 } 00618 if (child_started() && !child_running() && (err != EAGAIN)) 00619 m_err_eof = true; 00620 return(0); 00621 } 00622 00623 /** Allow child to write to err_fd() */ 00624 int execute::err_write(const char* buf, const int len) 00625 { 00626 int n; 00627 int err; 00628 00629 n = write(err_fd(), buf, len); 00630 err = errno; 00631 errno = 0; 00632 if (n > 0) { 00633 return(n); 00634 } 00635 if (child_started() && !child_running() && (err != EAGAIN)) 00636 m_err_eof = true; 00637 return(0); 00638 } 00639 00640 /** Dump execute object information -- used for debugging */ 00641 void execute::print(std::ostream& out) 00642 { 00643 out << "execute::is_child() = " << is_child() << std::endl; 00644 out << "execute::is_parent() = " << is_parent() << std::endl; 00645 out << "execute::my_pid() = " << my_pid() << std::endl; 00646 out << "execute::child_running() = " << child_running() << std::endl; 00647 out << "execute::child_exited() = " << child_exited() << std::endl; 00648 out << "execute::child_exited_normally() = " << child_exited_normally() 00649 << std::endl; 00650 out << "execute::child_exited_success() = " << child_exited_success() 00651 << std::endl; 00652 out << "execute::child_signaled() = " << child_signaled() << std::endl; 00653 out << "execute::child_exit_code() = " << child_exit_code() << std::endl; 00654 out << "execute::child_signal_no() = " << child_signal_no() << std::endl; 00655 out << "execute::in_fd() = " << in_fd() << std::endl; 00656 out << "execute::out_fd() = " << out_fd() << std::endl; 00657 out << "execute::err_fd() = " << err_fd() << std::endl; 00658 out << "execute::in_ready() = " << in_ready() << std::endl; 00659 out << "execute::out_ready() = " << out_ready() << std::endl; 00660 out << "execute::err_ready() = " << err_ready() << std::endl; 00661 } 00662 00663 /** Convenience function to call execute::print() */ 00664 std::ostream& operator << (std::ostream& out, execute& exe) 00665 { 00666 exe.print(out); 00667 00668 return(out); 00669 } 00670