diff --git a/main b/main index 69f273e..be9f84c 100755 Binary files a/main and b/main differ diff --git a/main.cc b/main.cc index 8bfcd31..9fbe22b 100755 --- a/main.cc +++ b/main.cc @@ -6,10 +6,10 @@ int main() { auto p = Popen({"./script.sh"}, output{"out.txt"}); - auto buf = check_output({"echo", "\"It works!\""}); + auto buf = check_output("echo Hello"); std::cout << buf.buf.data() << " :: " << buf.length << std::endl; - buf = check_output("cat subprocess.hpp"); + //buf = check_output("cat subprocess.hpp"); //std::cout << buf2.buf.data() << " :: " << buf2.length << std::endl; // diff --git a/subprocess.hpp b/subprocess.hpp index 85c4aad..c8d6774 100755 --- a/subprocess.hpp +++ b/subprocess.hpp @@ -142,6 +142,34 @@ namespace util return rbytes; } + template + static int read_all(int fd, Buffer& buf) + { + size_t orig_size = buf.size(); + size_t increment = orig_size; + auto buffer = buf.data(); + int total_bytes_read = 0; + + while (1) { + int rd_bytes = read_atmost_n(fd, buffer, buf.size()); + if (rd_bytes == increment) { + // Resize the buffer to accomodate more + orig_size = orig_size * 1.5; + increment = orig_size - buf.size(); + buf.resize(orig_size); + buffer += rd_bytes; + total_bytes_read += rd_bytes; + } else if (rd_bytes != -1){ + total_bytes_read += rd_bytes; + break; + } else { + if (total_bytes_read == 0) return -1; + break; + } + } + return total_bytes_read; + } + static std::pair wait_for_child_exit(int pid) { @@ -212,11 +240,14 @@ enum IOTYPE { PIPE, }; +//TODO: A common base/interface for below stream structures ?? struct input { input(int fd): rd_ch_(fd) {} + input (FILE* fp):input(fileno(fp)) { assert(fp); } + input(const char* filename) { int fd = open(filename, O_RDONLY); if (fd == -1) throw OSError("File not found: ", errno); @@ -235,6 +266,8 @@ struct output { output(int fd): wr_ch_(fd) {} + output (FILE* fp):output(fileno(fp)) { assert(fp); } + output(const char* filename) { int fd = open(filename, O_APPEND | O_CREAT | O_RDWR, 0640); if (fd == -1) throw OSError("File not found: ", errno); @@ -253,6 +286,8 @@ struct error { error(int fd): wr_ch_(fd) {} + error(FILE* fp):error(fileno(fp)) { assert(fp); } + error(const char* filename) { int fd = open(filename, O_APPEND | O_CREAT | O_RDWR, 0640); if (fd == -1) throw OSError("File not found: ", errno); @@ -558,6 +593,10 @@ public: return communicate(nullptr, 0); } + FILE* input() { return stream_.input(); } + FILE* output() { return stream_.output();} + FILE* error() { return stream_.error(); } + private: template void init_args(F&& farg, Args&&... args); @@ -932,10 +971,9 @@ namespace detail { // at the other end screws up, we get screwed up as well obuf.add_cap(out_buf_cap_); - int rbytes = util::read_atmost_n( + int rbytes = util::read_all( fileno(stream_->output()), - obuf.buf.data(), - obuf.buf.size()); + obuf.buf); if (rbytes == -1) { throw OSError("read to obuf failed", errno); @@ -1075,4 +1113,6 @@ OutBuffer check_output(const std::string& arg, Args&&... args) return (detail::check_output_impl(arg, std::forward(args)...)); } +// Piping Support + }; diff --git a/test/test_subprocess.cc b/test/test_subprocess.cc index 58ec7d8..2a2a8c3 100755 --- a/test/test_subprocess.cc +++ b/test/test_subprocess.cc @@ -12,7 +12,17 @@ void test_input() std::cout << res.first.buf.data() << std::endl; } +void test_piping() +{ + auto cat = Popen({"cat", "../subprocess.hpp"}, output{PIPE}); + auto grep = Popen({"grep", "template"}, input{cat.output()}, output{PIPE}); + auto cut = Popen({"cut", "-d,", "-f", "1"}, input{grep.output()}, output{PIPE}); + auto res = cut.communicate().first; + std::cout << res.buf.data() << std::endl; +} + int main() { test_input(); + test_piping(); return 0; }