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
00033 execute::execute()
00034 {
00035 clear();
00036 }
00037
00038
00039 execute::~execute()
00040 {
00041 clear();
00042 }
00043
00044
00045
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
00066 static void _signal_handler(int signo)
00067 {
00068 throw(ERROR(0,"Tried to write to a read-only pipe"));
00069 }
00070
00071
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
00087 close(m_fd1[0]);
00088 close(m_fd2[1]);
00089 close(m_fd3[1]);
00090 m_child_started = true;
00091 }
00092 else {
00093
00094 close(m_fd1[1]);
00095 close(m_fd2[0]);
00096 close(m_fd3[0]);
00097 }
00098 }
00099
00100
00101 bool execute::is_child(void)
00102 {
00103 if (m_pid == 0) {
00104 return(true);
00105 }
00106 return(false);
00107 }
00108
00109
00110 bool execute::is_parent(void)
00111 {
00112 bool value;
00113
00114 value = !is_child();
00115
00116 return(value);
00117 }
00118
00119
00120 pid_t execute::my_pid(void)
00121 {
00122 pid_t value;
00123
00124 value = pid();
00125
00126 return(value);
00127 }
00128
00129
00130 void execute::exit(int code)
00131 {
00132 if (is_child())
00133 ::exit(code);
00134 }
00135
00136
00137
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
00170 pid_t execute::child_pid(void)
00171 {
00172 return(m_pid);
00173 }
00174
00175
00176 void execute::signal_child(int signal_no)
00177 {
00178 kill(m_pid, signal_no);
00179 }
00180
00181
00182 void execute::hup_child(void)
00183 {
00184 signal_child(SIGHUP);
00185 }
00186
00187
00188 void execute::kill_child(void)
00189 {
00190 signal_child(SIGKILL);
00191 }
00192
00193
00194 void execute::wait(void)
00195 {
00196 if (is_parent())
00197 ::wait(&m_status);
00198 }
00199
00200
00201 pid_t execute::check_child_(void)
00202 {
00203 pid_t value;
00204
00205 value = waitpid(m_pid, &m_status, WNOHANG|WUNTRACED);
00206
00207 return(value);
00208 }
00209
00210
00211 bool execute::child_started(void) const
00212 {
00213 return(m_child_started);
00214 }
00215
00216
00217 bool execute::child_running(void)
00218 {
00219 bool value;
00220
00221
00222 value = (check_child_() != -1);
00223
00224 return(value);
00225 }
00226
00227
00228 bool execute::child_exited(void)
00229 {
00230 bool value;
00231
00232 value = (check_child_() == -1);
00233
00234 return(value);
00235 }
00236
00237
00238 bool execute::child_exited_normally(void)
00239 {
00240 bool value;
00241
00242
00243
00244 value = (child_exited() && (child_exit_code() == 0));
00245
00246 return(value);
00247 }
00248
00249
00250 bool execute::child_signaled(void)
00251 {
00252 bool value;
00253
00254 check_child_();
00255 value = WIFSIGNALED(m_status);
00256
00257 return(value);
00258 }
00259
00260
00261 int execute::child_exit_code(void)
00262 {
00263 int value;
00264
00265
00266 check_child_();
00267 value = WEXITSTATUS(m_status);
00268
00269 return(value);
00270 }
00271
00272
00273 int execute::child_signal_no(void)
00274 {
00275 int value;
00276
00277 check_child_();
00278 if (child_exited()) {
00279 value = WTERMSIG(m_status);
00280 return(value);
00281 }
00282 else {
00283 value = WSTOPSIG(m_status);
00284 return(value);
00285 }
00286 }
00287
00288
00289
00290
00291
00292
00293
00294
00295
00296 int execute::in_fd(void)
00297 {
00298 if (is_parent()) {
00299
00300 return(m_fd1[1]);
00301 }
00302 else {
00303
00304 return(m_fd1[0]);
00305 }
00306 }
00307
00308
00309
00310
00311
00312
00313
00314
00315
00316 int execute::out_fd(void)
00317 {
00318 if (is_parent()) {
00319
00320 return(m_fd2[0]);
00321 }
00322 else {
00323
00324 return(m_fd2[1]);
00325 }
00326 }
00327
00328
00329
00330
00331
00332
00333
00334
00335
00336 int execute::err_fd(void)
00337 {
00338 if (is_parent()) {
00339
00340 return(m_fd3[0]);
00341 }
00342 else {
00343
00344 return(m_fd3[1]);
00345 }
00346 }
00347
00348
00349 bool execute::check_write_ready_(int fd)
00350 {
00351 struct timeval timeout = { 0, 0 };
00352 fd_set wset;
00353
00354 FD_ZERO(&wset);
00355 FD_SET(fd, &wset);
00356 select(fd+1, 0, &wset, 0, &timeout);
00357 if (FD_ISSET(fd, &wset)) {
00358 return(true);
00359 }
00360 return(false);
00361 }
00362
00363
00364 bool execute::check_read_ready_(int fd)
00365 {
00366 struct timeval timeout = { 0, 0 };
00367 fd_set rset;
00368
00369 FD_ZERO(&rset);
00370 FD_SET(fd, &rset);
00371 select(fd+1, &rset, 0, 0, &timeout);
00372 if (FD_ISSET(fd, &rset)) {
00373 return(true);
00374 }
00375 return(false);
00376 }
00377
00378
00379 void execute::exec(const std::string command)
00380 {
00381 fork();
00382 if (is_parent())
00383 return;
00384
00385 reroute_stdio();
00386
00387 execl("/bin/sh", "sh", "-c", command.c_str(), (char *)0);
00388 exit(127);
00389 }
00390
00391
00392
00393
00394
00395
00396
00397
00398
00399 bool execute::in_ready(void)
00400 {
00401 bool value;
00402
00403 if (is_parent())
00404 value = check_write_ready_(in_fd());
00405 else
00406 value = check_read_ready_(in_fd());
00407
00408 return(value);
00409 }
00410
00411
00412
00413
00414
00415
00416
00417
00418
00419 bool execute::out_ready(void)
00420 {
00421 bool value;
00422
00423 if (is_parent())
00424 value = check_read_ready_(out_fd());
00425 else
00426 value = check_write_ready_(out_fd());
00427
00428 return(value);
00429 }
00430
00431
00432
00433
00434
00435
00436
00437
00438
00439 bool execute::err_ready(void)
00440 {
00441 bool value;
00442
00443 if (is_parent())
00444 value = check_read_ready_(err_fd());
00445 else
00446 value = check_write_ready_(err_fd());
00447
00448 return(value);
00449 }
00450
00451
00452 bool execute::in_eof(void)
00453 {
00454 return(m_in_eof);
00455 }
00456
00457
00458 bool execute::out_eof(void)
00459 {
00460 return(m_out_eof);
00461 }
00462
00463
00464 bool execute::err_eof(void)
00465 {
00466 return(m_err_eof);
00467 }
00468
00469
00470 int execute::in_read(char* buf, const int len)
00471 {
00472 int n;
00473 int err;
00474
00475 n = read(in_fd(), buf, len);
00476 err = errno;
00477 errno = 0;
00478 if (n > 0) {
00479 return(n);
00480 }
00481 if (child_started() && !child_running() && (err != EAGAIN))
00482 m_in_eof = true;
00483 return(0);
00484 }
00485
00486
00487 int execute::in_write(const char* buf, const int len)
00488 {
00489 int n;
00490 int err;
00491
00492 n = write(in_fd(), buf, len);
00493 err = errno;
00494 errno = 0;
00495 if (n > 0) {
00496 return(n);
00497 }
00498 if (child_started() && !child_running() && (err != EAGAIN))
00499 m_in_eof = true;
00500 return(0);
00501 }
00502
00503
00504 int execute::out_read(char* buf, const int len)
00505 {
00506 int n;
00507 int err;
00508
00509 n = read(out_fd(), buf, len);
00510 err = errno;
00511 errno = 0;
00512 if (n > 0) {
00513 return(n);
00514 }
00515 if (child_started() && !child_running() && (err != EAGAIN))
00516 m_out_eof = true;
00517 return(0);
00518 }
00519
00520
00521 int execute::out_write(const char* buf, const int len)
00522 {
00523 int n;
00524 int err;
00525
00526 n = write(out_fd(), buf, len);
00527 err = errno;
00528 errno = 0;
00529 if (n > 0) {
00530 return(n);
00531 }
00532 if (child_started() && !child_running() && (err != EAGAIN))
00533 m_out_eof = true;
00534 return(0);
00535 }
00536
00537
00538 int execute::err_read(char* buf, const int len)
00539 {
00540 int n;
00541 int err;
00542
00543 n = read(err_fd(), buf, len);
00544 err = errno;
00545 errno = 0;
00546 if (n > 0) {
00547 return(n);
00548 }
00549 if (child_started() && !child_running() && (err != EAGAIN))
00550 m_err_eof = true;
00551 return(0);
00552 }
00553
00554
00555 int execute::err_write(const char* buf, const int len)
00556 {
00557 int n;
00558 int err;
00559
00560 n = write(err_fd(), buf, len);
00561 err = errno;
00562 errno = 0;
00563 if (n > 0) {
00564 return(n);
00565 }
00566 if (child_started() && !child_running() && (err != EAGAIN))
00567 m_err_eof = true;
00568 return(0);
00569 }
00570
00571
00572 void execute::print(std::ostream& out)
00573 {
00574 out << "execute::is_child() = " << is_child() << std::endl;
00575 out << "execute::is_parent() = " << is_parent() << std::endl;
00576 out << "execute::my_pid() = " << my_pid() << std::endl;
00577 out << "execute::child_running() = " << child_running() << std::endl;
00578 out << "execute::child_exited() = " << child_exited() << std::endl;
00579 out << "execute::child_exited_normally() = " << child_exited_normally()
00580 << std::endl;
00581 out << "execute::child_signaled() = " << child_signaled() << std::endl;
00582 out << "execute::child_exit_code() = " << child_exit_code() << std::endl;
00583 out << "execute::child_signal_no() = " << child_signal_no() << std::endl;
00584 out << "execute::in_fd() = " << in_fd() << std::endl;
00585 out << "execute::out_fd() = " << out_fd() << std::endl;
00586 out << "execute::err_fd() = " << err_fd() << std::endl;
00587 out << "execute::in_ready() = " << in_ready() << std::endl;
00588 out << "execute::out_ready() = " << out_ready() << std::endl;
00589 out << "execute::err_ready() = " << err_ready() << std::endl;
00590 }
00591
00592
00593 std::ostream& operator << (std::ostream& out, execute& exe)
00594 {
00595 exe.print(out);
00596
00597 return(out);
00598 }
00599