mirror of
https://github.com/arun11299/cpp-subprocess.git
synced 2025-08-05 12:56:23 -04:00
overload stream arguments for file pointer and new pipeline test case
This commit is contained in:
parent
6a9f0aab51
commit
f409d50c8d
4
main.cc
4
main.cc
@ -6,10 +6,10 @@ int main() {
|
|||||||
auto p = Popen({"./script.sh"},
|
auto p = Popen({"./script.sh"},
|
||||||
output{"out.txt"});
|
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;
|
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;
|
//std::cout << buf2.buf.data() << " :: " << buf2.length << std::endl;
|
||||||
//
|
//
|
||||||
|
|
||||||
|
@ -142,6 +142,34 @@ namespace util
|
|||||||
return rbytes;
|
return rbytes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename Buffer>
|
||||||
|
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
|
static
|
||||||
std::pair<int, int> wait_for_child_exit(int pid)
|
std::pair<int, int> wait_for_child_exit(int pid)
|
||||||
{
|
{
|
||||||
@ -212,11 +240,14 @@ enum IOTYPE {
|
|||||||
PIPE,
|
PIPE,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
//TODO: A common base/interface for below stream structures ??
|
||||||
|
|
||||||
struct input
|
struct input
|
||||||
{
|
{
|
||||||
input(int fd): rd_ch_(fd) {}
|
input(int fd): rd_ch_(fd) {}
|
||||||
|
|
||||||
|
input (FILE* fp):input(fileno(fp)) { assert(fp); }
|
||||||
|
|
||||||
input(const char* filename) {
|
input(const char* filename) {
|
||||||
int fd = open(filename, O_RDONLY);
|
int fd = open(filename, O_RDONLY);
|
||||||
if (fd == -1) throw OSError("File not found: ", errno);
|
if (fd == -1) throw OSError("File not found: ", errno);
|
||||||
@ -235,6 +266,8 @@ struct output
|
|||||||
{
|
{
|
||||||
output(int fd): wr_ch_(fd) {}
|
output(int fd): wr_ch_(fd) {}
|
||||||
|
|
||||||
|
output (FILE* fp):output(fileno(fp)) { assert(fp); }
|
||||||
|
|
||||||
output(const char* filename) {
|
output(const char* filename) {
|
||||||
int fd = open(filename, O_APPEND | O_CREAT | O_RDWR, 0640);
|
int fd = open(filename, O_APPEND | O_CREAT | O_RDWR, 0640);
|
||||||
if (fd == -1) throw OSError("File not found: ", errno);
|
if (fd == -1) throw OSError("File not found: ", errno);
|
||||||
@ -253,6 +286,8 @@ struct error
|
|||||||
{
|
{
|
||||||
error(int fd): wr_ch_(fd) {}
|
error(int fd): wr_ch_(fd) {}
|
||||||
|
|
||||||
|
error(FILE* fp):error(fileno(fp)) { assert(fp); }
|
||||||
|
|
||||||
error(const char* filename) {
|
error(const char* filename) {
|
||||||
int fd = open(filename, O_APPEND | O_CREAT | O_RDWR, 0640);
|
int fd = open(filename, O_APPEND | O_CREAT | O_RDWR, 0640);
|
||||||
if (fd == -1) throw OSError("File not found: ", errno);
|
if (fd == -1) throw OSError("File not found: ", errno);
|
||||||
@ -558,6 +593,10 @@ public:
|
|||||||
return communicate(nullptr, 0);
|
return communicate(nullptr, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FILE* input() { return stream_.input(); }
|
||||||
|
FILE* output() { return stream_.output();}
|
||||||
|
FILE* error() { return stream_.error(); }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
template <typename F, typename... Args>
|
template <typename F, typename... Args>
|
||||||
void init_args(F&& farg, Args&&... args);
|
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
|
// at the other end screws up, we get screwed up as well
|
||||||
obuf.add_cap(out_buf_cap_);
|
obuf.add_cap(out_buf_cap_);
|
||||||
|
|
||||||
int rbytes = util::read_atmost_n(
|
int rbytes = util::read_all(
|
||||||
fileno(stream_->output()),
|
fileno(stream_->output()),
|
||||||
obuf.buf.data(),
|
obuf.buf);
|
||||||
obuf.buf.size());
|
|
||||||
|
|
||||||
if (rbytes == -1) {
|
if (rbytes == -1) {
|
||||||
throw OSError("read to obuf failed", errno);
|
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>(args)...));
|
return (detail::check_output_impl(arg, std::forward<Args>(args)...));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Piping Support
|
||||||
|
|
||||||
};
|
};
|
||||||
|
@ -12,7 +12,17 @@ void test_input()
|
|||||||
std::cout << res.first.buf.data() << std::endl;
|
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() {
|
int main() {
|
||||||
test_input();
|
test_input();
|
||||||
|
test_piping();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user