hmbdc
simplify-high-performance-messaging-programming
 All Classes Namespaces Functions Variables Friends Pages
ExecutionIo.hpp
1 #include "hmbdc/Copyright.hpp"
2 #pragma once
3 
4 #include "hmbdc/Exception.hpp"
5 
6 #include <iostream>
7 #include <memory>
8 #include <algorithm>
9 #include <stdexcept>
10 
11 // #include <ext/stdio_filebuf.h>
12 #include <string.h>
13 #include <unistd.h>
14 
15 namespace hmbdc { namespace os {
16 /**
17  * @brief execute a program as a child and capture its stdin stdout and/or stderr
18  * @details IO are exposed in the fd form
19  */
20 struct ExecutionIo {
21  /**
22  * @brief execute a program as a child and capture its stdin stdout and/or stderr
23  *
24  * @param argv ullptr terminated command line args array,
25  * for example, {"/usr/bin/bc", "-q", nullptr}
26  * @param captureStderr optionally capture
27  */
28  ExecutionIo(const char* const argv[]
29  , bool captureStderr = false);
30 
31  ~ExecutionIo();
32 
33  /**
34  * @brief child stdin fd, use write on it - not read
35  * @details blocking by default
36  */
38 
39  /**
40  * @brief child stdout fd, use read on it - not write
41  * @details blocking by default
42  */
44 
45  /**
46  * @brief if captured, child stderr fd, use read on it - not write
47  * @details blocking by default
48  */
50 
51  /**
52  * @brief process id of the started child process
53  */
54  pid_t exePid;
55 
56 
57  // ostream exeCin;
58  // istream exeCout;
59  // istream exeCerr;
60 
61  ExecutionIo& operator << (char const* input) {
62  auto s = write(exeStdinFd, input, strlen(input));
63  if ((size_t)s != strlen(input)) {
64  HMBDC_THROW(std::runtime_error, "write failed, bytes written=" << s);
65  }
66  return *this;
67  }
68 
69  ExecutionIo& operator << (std::string const& input) {
70  auto s = write(exeStdinFd, input.c_str(), input.size());
71  if ((size_t)s != input.size()) {
72  HMBDC_THROW(std::runtime_error, "write failed, bytes written=" << s);
73  }
74  return *this;
75  }
76 
77  ExecutionIo& operator >> (std::string& output) {
78  for (;;) {
79  auto l = std::find(buf_, buf_ + bufLen_, '\n');
80  //is no \n in 4096 char buffer, just treat the last char as \n
81  if (l == buf_ + sizeof(buf_)) l--;
82  if (l != buf_ + bufLen_) {
83  output = std::string(buf_, l + 1);
84  bufLen_ -= output.size();
85  memmove(buf_, l + 1, bufLen_);
86  return *this;
87  }
88  int s = read(exeStdoutFd, buf_ + bufLen_, sizeof(buf_) - bufLen_);
89  bufLen_ += s;
90  }
91  }
92 
93  ExecutionIo& readErr(std::string& output) {
94  char buf[1024];
95  int s = read(exeStderrFd, buf, sizeof(buf));
96  output = std::string(buf, s);
97  return *this;
98  }
99 
100 private:
101  char buf_[4096];
102  size_t bufLen_;
103 
104 // private:
105 // unique_ptr<__gnu_cxx::stdio_filebuf<char>> exeCinBuf_;
106 // unique_ptr<__gnu_cxx::stdio_filebuf<char>> exeCoutBuf_;
107 // unique_ptr<__gnu_cxx::stdio_filebuf<char>> exeCerrBuf_;
108 };
109 }}
ExecutionIo(const char *const argv[], bool captureStderr=false)
execute a program as a child and capture its stdin stdout and/or stderr
pid_t exePid
process id of the started child process
Definition: ExecutionIo.hpp:54
int exeStderrFd
if captured, child stderr fd, use read on it - not write
Definition: ExecutionIo.hpp:49
int exeStdoutFd
child stdout fd, use read on it - not write
Definition: ExecutionIo.hpp:43
execute a program as a child and capture its stdin stdout and/or stderr
Definition: ExecutionIo.hpp:20
int exeStdinFd
child stdin fd, use write on it - not read
Definition: ExecutionIo.hpp:37