#include "config.h" #ifdef HAVE_UNISTD_H #include #endif #include #include #include #include "asserts.h" #include "error.h" #include "fs.h" #include "exec.h" #include "fdstream.h" // static char confdir[4096] = { 0 }; /* void test1(void) { execute exe; bool thrown = false; try { exe.fork(); } catch (error &e) { thrown = true; } assert(!thrown); exe.wait(); if (exe.is_child()) exe.exit(0); } */ /* void test2(void) { execute exe; exe.fork(); if (exe.is_parent()) { char *msg_to_child = "Message from parent"; char msg_from_child[4096] = { 0 }; char msg_from_err[4096] = { 0 }; assert(exe.child_running()); assert(!exe.child_exited()); assert(!exe.child_exited_normally()); assert(!exe.child_signaled()); assert(exe.child_exit_code() == 0); assert(exe.child_signal_no() == 0); if (write(exe.in_fd(), msg_to_child, strlen(msg_to_child)) != (int)strlen(msg_to_child)) throw(ERROR(errno,"Error writing to child's input pipe")); if (read(exe.out_fd(), msg_from_child, 4096) == 0) throw(ERROR(errno,"Error reading from child's output pipe")); if (read(exe.err_fd(), msg_from_err, 4096) == 0) throw(ERROR(errno,"Error reading from child's error pipe")); exe.wait(); assert(static_cast(msg_from_child) == "Message from child"); assert(static_cast(msg_from_err) == "Message from child err"); assert(!exe.child_running()); assert(exe.child_exited()); assert(exe.child_exited_normally()); assert(!exe.child_signaled()); assert(exe.child_exit_code() == 0); assert(exe.child_signal_no() == 0); } if (exe.is_child()) { char msg_from_parent[4096] = { 0 }; char *msg_to_parent = "Message from child"; char *msg_to_err = "Message from child err"; if (read(exe.in_fd(), msg_from_parent, 4096) == 0) throw(ERROR(errno,"Error reading input from parent")); if (write(exe.out_fd(), msg_to_parent, strlen(msg_to_parent)) != (int)strlen(msg_to_parent)) throw(ERROR(errno,"Error writing output to parent")); if (write(exe.err_fd(), msg_to_err, strlen(msg_to_err)) != (int)strlen(msg_to_err)) throw(ERROR(errno,"Error writing error to parent")); assert(static_cast(msg_from_parent) == "Message from parent"); exe.exit(); } } */ /* void test3(void) { execute exe; exe.fork(); if (exe.is_parent()) { char *msg_to_child = "Message from parent"; char msg_from_child[4096] = { 0 }; char msg_from_err[4096] = { 0 }; char extra_msg[4096] = { 0 }; int extra_msg_length = 0; int i; assert(exe.child_running()); assert(!exe.child_exited()); assert(!exe.child_exited_normally()); assert(!exe.child_signaled()); assert(exe.child_exit_code() == 0); assert(exe.child_signal_no() == 0); assert(exe.in_ready()); assert(!exe.out_ready()); assert(!exe.err_ready()); sleep(1); assert(exe.in_ready()); assert(!exe.out_ready()); assert(!exe.err_ready()); if (write(exe.in_fd(), msg_to_child, strlen(msg_to_child)) != (int)strlen(msg_to_child)) throw(ERROR(errno,"Error writing to child's input pipe")); sleep(1); assert(exe.in_ready()); assert(exe.out_ready()); assert(exe.err_ready()); if (read(exe.out_fd(), msg_from_child, 4096) == 0) throw(ERROR(errno,"Error reading from child's output pipe")); sleep(1); assert(exe.in_ready()); assert(exe.out_ready()); assert(exe.err_ready()); if (read(exe.err_fd(), msg_from_err, 4096) == 0) throw(ERROR(errno,"Error reading from child's error pipe")); sleep(1); assert(exe.in_ready()); assert(exe.out_ready()); assert(exe.err_ready()); if (exe.out_ready()) { for (i = 0; i < 4096; extra_msg[i++] = 0); extra_msg_length = read(exe.out_fd(), extra_msg, 4096); } assert(extra_msg_length == 0); if (exe.err_ready()) { for (i = 0; i < 4096; extra_msg[i++] = 0); extra_msg_length = read(exe.err_fd(), extra_msg, 4096); } assert(extra_msg_length == 0); exe.wait(); assert(static_cast(msg_from_child) == "Message from child"); assert(static_cast(msg_from_err) == "Message from child err"); assert(!exe.child_running()); assert(exe.child_exited()); assert(exe.child_exited_normally()); assert(!exe.child_signaled()); assert(exe.child_exit_code() == 0); assert(exe.child_signal_no() == 0); } if (exe.is_child()) { char msg_from_parent[4096] = { 0 }; char *msg_to_parent = "Message from child"; char *msg_to_err = "Message from child err"; if (read(exe.in_fd(), msg_from_parent, 4096) == 0) throw(ERROR(errno,"Error reading input from parent")); if (write(exe.out_fd(), msg_to_parent, strlen(msg_to_parent)) != (int)strlen(msg_to_parent)) throw(ERROR(errno,"Error writing output to parent")); if (write(exe.err_fd(), msg_to_err, strlen(msg_to_err)) != (int)strlen(msg_to_err)) throw(ERROR(errno,"Error writing error to parent")); assert(static_cast(msg_from_parent) == "Message from parent"); exe.exit(); } } */ /* void test4(void) { execute exe; exe.fork(); if (exe.is_parent()) { assert(exe.child_running()); assert(!exe.child_exited()); assert(!exe.child_exited_normally()); assert(!exe.child_signaled()); assert(exe.child_exit_code() == 0); assert(exe.child_signal_no() == 0); exe.wait(); assert(!exe.child_running()); assert(exe.child_exited()); assert(exe.child_exited_normally()); assert(!exe.child_signaled()); assert(exe.child_exit_code() == 5); assert(exe.child_signal_no() == 0); } else { sleep(1); exe.exit(5); } } */ /* void test5(void) { execute exe; exe.fork(); if (exe.is_parent()) { assert(exe.child_running()); assert(!exe.child_exited()); assert(!exe.child_exited_normally()); assert(!exe.child_signaled()); assert(exe.child_exit_code() == 0); assert(exe.child_signal_no() == 0); exe.signal_child(SIGINT); exe.wait(); assert(!exe.child_running()); assert(exe.child_exited()); assert(!exe.child_exited_normally()); assert(exe.child_signaled()); assert(exe.child_exit_code() == 0); assert(exe.child_signal_no() == SIGINT); } else { sleep(5); exe.exit(5); } } */ /* void test6(void) { execute exe; std::string command = "/bin/ls -1 ./test-exec.cc"; char buffer[4096] = { 0 }; int num_bytes; exe.exec(command); assert(exe.child_running()); assert(!exe.child_exited()); assert(!exe.child_exited_normally()); assert(!exe.child_signaled()); assert(exe.child_exit_code() == 0); assert(exe.child_signal_no() == 0); assert(exe.in_ready()); assert(!exe.out_ready()); assert(!exe.err_ready()); for (num_bytes = 0; num_bytes < 4096; buffer[num_bytes++] = 0); num_bytes = read(exe.out_fd(), buffer, 4096); assert(num_bytes = 15); assert(static_cast(buffer) == static_cast("./test-exec.cc\n")); for (num_bytes = 0; num_bytes < 4096; buffer[num_bytes++] = 0); num_bytes = read(exe.err_fd(), buffer, 4096); assert(num_bytes == 0); assert(static_cast(buffer).size() == 0); exe.wait(); assert(!exe.child_running()); assert(exe.child_exited()); assert(exe.child_exited_normally()); assert(!exe.child_signaled()); assert(exe.child_exit_code() == 0); assert(exe.child_signal_no() == 0); assert(exe.in_ready()); assert(exe.out_ready()); assert(exe.err_ready()); } */ /* void test7(void) { execute exe; ofdstream fdout; exe.fork(); if (exe.is_parent()) { char *msg_to_child = "Message from parent"; char msg_from_child[4096] = { 0 }; char msg_from_err[4096] = { 0 }; assert(exe.child_running()); assert(!exe.child_exited()); assert(!exe.child_exited_normally()); assert(!exe.child_signaled()); assert(exe.child_exit_code() == 0); assert(exe.child_signal_no() == 0); assert(fdout.good()); fdout.attach(exe.in_fd()); fdout << msg_to_child; fdout.flush(); assert(fdout.good()); if (read(exe.out_fd(), msg_from_child, 4096) == 0) throw(ERROR(errno,"Error reading from child's output pipe")); if (read(exe.err_fd(), msg_from_err, 4096) == 0) throw(ERROR(errno,"Error reading from child's error pipe")); exe.wait(); assert(fdout.good()); assert(static_cast(msg_from_child) == "Message from child"); assert(static_cast(msg_from_err) == "Message from child err"); assert(!exe.child_running()); assert(exe.child_exited()); assert(exe.child_exited_normally()); assert(!exe.child_signaled()); assert(exe.child_exit_code() == 0); assert(exe.child_signal_no() == 0); } else { char msg_from_parent[4096] = { 0 }; char *msg_to_parent = "Message from child"; char *msg_to_err = "Message from child err"; if (read(exe.in_fd(), msg_from_parent, 4096) == 0) throw(ERROR(errno,"Error reading input from parent")); if (write(exe.out_fd(), msg_to_parent, strlen(msg_to_parent)) != (int)strlen(msg_to_parent)) throw(ERROR(errno,"Error writing output to parent")); if (write(exe.err_fd(), msg_to_err, strlen(msg_to_err)) != (int)strlen(msg_to_err)) throw(ERROR(errno,"Error writing error to parent")); assert(static_cast(msg_from_parent) == "Message from parent"); exe.exit(); } } */ /* void test8(void) { execute exe; ofdstream fdout; ifdstream fdin; exe.fork(); if (exe.is_parent()) { char *msg_to_child = "Message from parent"; char msg_from_child[4096] = { 0 }; char msg_from_err[4096] = { 0 }; assert(exe.child_running()); assert(!exe.child_exited()); assert(!exe.child_exited_normally()); assert(!exe.child_signaled()); assert(exe.child_exit_code() == 0); assert(exe.child_signal_no() == 0); fdout.attach(exe.in_fd()); fdout << msg_to_child; fdout.flush(); fdin.attach(exe.out_fd()); fdin.get(msg_from_child,4096); if (read(exe.err_fd(), msg_from_err, 4096) == 0) throw(ERROR(errno,"Error reading from child's error pipe")); exe.wait(); assert(static_cast(msg_from_child) == "Message from child"); assert(static_cast(msg_from_err) == "Message from child err"); assert(!exe.child_running()); assert(exe.child_exited()); assert(exe.child_exited_normally()); assert(!exe.child_signaled()); assert(exe.child_exit_code() == 0); assert(exe.child_signal_no() == 0); } else { char msg_from_parent[4096] = { 0 }; char *msg_to_parent = "Message from child"; char *msg_to_err = "Message from child err"; if (read(exe.in_fd(), msg_from_parent, 4096) == 0) throw(ERROR(errno,"Error reading input from parent")); if (write(exe.out_fd(), msg_to_parent, strlen(msg_to_parent)) != (int)strlen(msg_to_parent)) throw(ERROR(errno,"Error writing output to parent")); if (write(exe.err_fd(), msg_to_err, strlen(msg_to_err)) != (int)strlen(msg_to_err)) throw(ERROR(errno,"Error writing error to parent")); assert(static_cast(msg_from_parent) == "Message from parent"); exe.exit(); } } */ /* void test9(void) { execute exe; ofdstream fdout; ifdstream fdin; exe.fork(); if (exe.is_parent()) { char *msg_to_child = "Message from parent"; char msg_from_child[4096] = { 0 }; char msg_from_err[4096] = { 0 }; assert(exe.child_running()); assert(!exe.child_exited()); assert(!exe.child_exited_normally()); assert(!exe.child_signaled()); assert(exe.child_exit_code() == 0); assert(exe.child_signal_no() == 0); fdout.attach(exe.in_fd()); // fdout << msg_to_child; // fdout.flush(); if (write(exe.in_fd(), msg_to_child, strlen(msg_to_child)) != (int)strlen(msg_to_child)) throw(ERROR(errno,"Error writing to child's input pipe")); fdin.attach(exe.out_fd()); // fdin.get(msg_from_child,4096); if (read(exe.out_fd(), msg_from_child, 4096) == 0) throw(ERROR(errno,"Error reading from child's output pipe")); if (read(exe.err_fd(), msg_from_err, 4096) == 0) throw(ERROR(errno,"Error reading from child's error pipe")); exe.wait(); assert(static_cast(msg_from_child) == "Message from child"); assert(static_cast(msg_from_err) == "Message from child err"); assert(!exe.child_running()); assert(exe.child_exited()); assert(exe.child_exited_normally()); assert(!exe.child_signaled()); assert(exe.child_exit_code() == 0); assert(exe.child_signal_no() == 0); } else { char msg_from_parent[4096] = { 0 }; char *msg_to_parent = "Message from child"; char *msg_to_err = "Message from child err"; if (read(exe.in_fd(), msg_from_parent, 4096) == 0) throw(ERROR(errno,"Error reading input from parent")); if (write(exe.out_fd(), msg_to_parent, strlen(msg_to_parent)) != (int)strlen(msg_to_parent)) throw(ERROR(errno,"Error writing output to parent")); if (write(exe.err_fd(), msg_to_err, strlen(msg_to_err)) != (int)strlen(msg_to_err)) throw(ERROR(errno,"Error writing error to parent")); assert(static_cast(msg_from_parent) == "Message from parent"); exe.exit(); } } */ void test10(void) { execute exe; exe.fork(); if (exe.is_parent()) { char *msg_to_child = "Message from parent"; char msg_from_child[4096] = { 0 }; char msg_from_err[4096] = { 0 }; assert(exe.child_running()); assert(!exe.child_exited()); assert(!exe.child_exited_normally()); assert(!exe.child_signaled()); assert(exe.child_exit_code() == 0); assert(exe.child_signal_no() == 0); assert(exe.in_ready()); assert(!exe.out_ready()); assert(!exe.err_ready()); assert(!exe.in_eof()); assert(!exe.out_eof()); assert(!exe.err_eof()); if (exe.in_write(msg_to_child, strlen(msg_to_child)) != (int)strlen(msg_to_child)) throw(ERROR(errno,"Error writing to child's input pipe")); // Wait until input is ready from child while (!exe.out_ready() && !exe.err_ready()); assert(exe.in_ready()); assert(exe.out_ready()); assert(exe.err_ready()); assert(!exe.in_eof()); assert(!exe.out_eof()); assert(!exe.err_eof()); if (exe.out_read(msg_from_child, 4096) == 0) throw(ERROR(errno,"Error reading from child's output pipe")); assert(exe.in_ready()); assert(!exe.out_ready() || !exe.child_running()); assert(exe.err_ready()); assert(!exe.in_eof()); assert(!exe.out_eof()); assert(!exe.err_eof()); if (exe.err_read(msg_from_err, 4096) == 0) throw(ERROR(errno,"Error reading from child's error pipe")); while (!exe.out_ready() && !exe.err_ready()); assert(exe.in_ready()); assert(exe.out_ready()); assert(exe.err_ready()); assert(!exe.in_eof()); assert(!exe.out_eof()); assert(!exe.err_eof()); exe.wait(); assert(exe.in_ready()); assert(exe.out_ready()); assert(exe.err_ready()); assert(!exe.in_eof()); assert(!exe.out_eof()); assert(!exe.err_eof()); assert(static_cast(msg_from_child) == "Message from child"); assert(static_cast(msg_from_err) == "Message from child err"); assert(exe.out_read(msg_from_child, 4096) == 0); assert(exe.in_ready()); assert(exe.out_ready()); assert(exe.err_ready()); assert(!exe.in_eof()); assert(exe.out_eof()); assert(!exe.err_eof()); assert(!exe.child_running()); assert(exe.child_exited()); assert(exe.child_exited_normally()); assert(!exe.child_signaled()); assert(exe.child_exit_code() == 0); assert(exe.child_signal_no() == 0); } if (exe.is_child()) { char msg_from_parent[4096] = { 0 }; char *msg_to_parent = "Message from child"; char *msg_to_err = "Message from child err"; if (read(exe.in_fd(), msg_from_parent, 4096) == 0) throw(ERROR(errno,"Error reading input from parent")); if (write(exe.out_fd(), msg_to_parent, strlen(msg_to_parent)) != (int)strlen(msg_to_parent)) throw(ERROR(errno,"Error writing output to parent")); if (write(exe.err_fd(), msg_to_err, strlen(msg_to_err)) != (int)strlen(msg_to_err)) throw(ERROR(errno,"Error writing error to parent")); assert(static_cast(msg_from_parent) == "Message from parent"); sleep(5); exe.exit(); } } int main(int argc, char *argv[]) { try { /* test1(); test2(); test3(); test4(); test5(); test6(); test7(); test8(); test9(); */ test10(); } catch(error e) { std::cerr << e; assert(0); } catch(...) { std::cerr << err_unknown; assert(0); } return(0); }