hmbdc
simplify-high-performance-messaging-programming
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  bool const writeStatus = true;
58  bool const readStatus = true;
59  bool const errStatus = true;
60 
61  // ostream exeCin;
62  // istream exeCout;
63  // istream exeCerr;
64 
65  ExecutionIo& operator << (char const* input) {
66  auto s = write(exeStdinFd, input, strlen(input));
67  if ((size_t)s != strlen(input)) {
68  const_cast<bool&>(writeStatus) = false;
69  }
70  return *this;
71  }
72 
73  ExecutionIo& operator << (std::string const& input) {
74  auto s = write(exeStdinFd, input.c_str(), input.size());
75  if ((size_t)s != input.size()) {
76  const_cast<bool&>(writeStatus) = false;
77  }
78  return *this;
79  }
80 
81  ExecutionIo& operator >> (std::string& output) {
82  return read(exeStdoutFd, output, buf_, sizeof(buf_), bufLen_, readStatus);
83  }
84 
85  ExecutionIo& readErr(std::string& output) {
86  return read(exeStderrFd, output, errbuf_, sizeof(errbuf_), errbufLen_, errStatus);
87 
88  // char buf[1024];
89  // int s = read(exeStderrFd, buf, sizeof(buf));
90  // output = std::string(buf, s);
91  // return *this;
92  }
93 
94 private:
95  ExecutionIo& read(int fd, std::string& output, char* buf, size_t bufCap, size_t& bufLen, const bool& status) {
96  for (;;) {
97  auto l = std::find(buf, buf + bufLen, '\n');
98  //is no \n in 4096 char buffer, just treat the last char as \n
99  if (l == buf + bufCap) l--;
100  if (l != buf + bufLen) {
101  output = std::string(buf, l + 1);
102  bufLen -= output.size();
103  memmove(buf, l + 1, bufLen);
104  return *this;
105  }
106  auto s = ::read(fd, buf + bufLen, bufCap - bufLen);
107  if (s > 0) {
108  bufLen += s;
109  } else {
110  output = std::string(buf, bufLen);
111  bufLen = 0;
112  const_cast<bool&>(status) = false;
113  return *this;
114  }
115  }
116  }
117  char buf_[4096];
118  size_t bufLen_ = 0;
119 
120  char errbuf_[4096];
121  size_t errbufLen_ = 0;
122 
123 
124 // private:
125 // unique_ptr<__gnu_cxx::stdio_filebuf<char>> exeCinBuf_;
126 // unique_ptr<__gnu_cxx::stdio_filebuf<char>> exeCoutBuf_;
127 // unique_ptr<__gnu_cxx::stdio_filebuf<char>> exeCerrBuf_;
128 };
129 }}
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
Definition: Base.hpp:12
int exeStdinFd
child stdin fd, use write on it - not read
Definition: ExecutionIo.hpp:37