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