36#ifndef BITCOIN_UTIL_SUBPROCESS_H 
   37#define BITCOIN_UTIL_SUBPROCESS_H 
   49#include <initializer_list> 
   58#if (defined _MSC_VER) || (defined __MINGW32__) 
   59  #define __USING_WINDOWS__ 
   62#ifdef __USING_WINDOWS__ 
   67#ifdef __USING_WINDOWS__ 
   77  #include <sys/types.h> 
   85  #define subprocess_close _close 
   86  #define subprocess_fileno _fileno 
   87  #define subprocess_open _open 
   88  #define subprocess_write _write 
   90  #define subprocess_close close 
   91  #define subprocess_fileno fileno 
   92  #define subprocess_open open 
   93  #define subprocess_write write 
  166  OSError(
const std::string& err_msg, 
int err_code):
 
  174#ifdef __USING_WINDOWS__ 
  175  inline void quote_argument(
const std::wstring &argument, std::wstring &command_line,
 
  184    if (force == 
false && argument.empty() == 
false &&
 
  185        argument.find_first_of(L
" \t\n\v") == argument.npos) {
 
  186      command_line.append(argument);
 
  189      command_line.push_back(L
'"');
 
  191      for (
auto it = argument.begin();; ++it) {
 
  192        unsigned number_backslashes = 0;
 
  194        while (it != argument.end() && *it == L
'\\') {
 
  196          ++number_backslashes;
 
  199        if (it == argument.end()) {
 
  207          command_line.append(number_backslashes * 2, L
'\\');
 
  210        else if (*it == L
'"') {
 
  217          command_line.append(number_backslashes * 2 + 1, L
'\\');
 
  218          command_line.push_back(*it);
 
  226          command_line.append(number_backslashes, L
'\\');
 
  227          command_line.push_back(*it);
 
  231      command_line.push_back(L
'"');
 
  235  inline std::string get_last_error(DWORD errorMessageID)
 
  237    if (errorMessageID == 0)
 
  238      return std::string();
 
  240    LPSTR messageBuffer = 
nullptr;
 
  241    size_t size = FormatMessageA(
 
  242        FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |
 
  243            FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_MAX_WIDTH_MASK,
 
  244        NULL, errorMessageID, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
 
  245        (LPSTR)&messageBuffer, 0, NULL);
 
  247    std::string message(messageBuffer, size);
 
  249    LocalFree(messageBuffer);
 
  254  inline FILE *file_from_handle(HANDLE h, 
const char *mode)
 
  258      throw OSError(
"invalid_mode", 0);
 
  261    if (mode[0] == 
'w') {
 
  264    else if (mode[0] == 
'r') {
 
  268      throw OSError(
"file_from_handle", 0);
 
  271    int os_fhandle = _open_osfhandle((intptr_t)h, md);
 
  272    if (os_fhandle == -1) {
 
  274      throw OSError(
"_open_osfhandle", 0);
 
  277    FILE *fp = _fdopen(os_fhandle, mode);
 
  286  inline void configure_pipe(HANDLE* read_handle, HANDLE* write_handle, HANDLE* child_handle)
 
  288    SECURITY_ATTRIBUTES saAttr;
 
  291    saAttr.nLength = 
sizeof(SECURITY_ATTRIBUTES);
 
  292    saAttr.bInheritHandle = TRUE;
 
  293    saAttr.lpSecurityDescriptor = NULL;
 
  296    if (!CreatePipe(read_handle, write_handle, &saAttr,0))
 
  297      throw OSError(
"CreatePipe", 0);
 
  300    if (!SetHandleInformation(*child_handle, HANDLE_FLAG_INHERIT, 0))
 
  301      throw OSError(
"SetHandleInformation", 0);
 
  314  static inline std::vector<std::string>
 
  315  split(
const std::string& str, 
const std::string& delims=
" \t")
 
  317    std::vector<std::string> res;
 
  321      auto pos = str.find_first_of(delims, 
init);
 
  322      if (pos == std::string::npos) {
 
  323        res.emplace_back(str.substr(
init, str.length()));
 
  326      res.emplace_back(str.substr(
init, pos - 
init));
 
  335#ifndef __USING_WINDOWS__ 
  348    int flags = fcntl(fd, F_GETFD, 0);
 
  350        throw OSError(
"fcntl F_GETFD failed", errno);
 
  352    if (set) 
flags |= FD_CLOEXEC;
 
  353    else flags &= ~FD_CLOEXEC;
 
  354    if (fcntl(fd, F_SETFD, 
flags) == -1) {
 
  355        throw OSError(
"fcntl F_SETFD failed", errno);
 
  373    int res = pipe(pipe_fds);
 
  375      throw OSError(
"pipe failure", errno);
 
  381    return std::make_pair(pipe_fds[0], pipe_fds[1]);
 
  398  int write_n(
int fd, 
const char* buf, 
size_t length)
 
  401    while (nwritten < length) {
 
  403      if (written == -1) 
return -1;
 
  427#ifdef __USING_WINDOWS__ 
  428    return (
int)fread(buf, 1, read_upto, fp);
 
  435      int read_bytes = read(fd, buf + rbytes, read_upto - rbytes);
 
  436      if (read_bytes == -1) {
 
  437        if (errno == EINTR) {
 
  438          if (eintr_cnter >= 50) 
return -1;
 
  444      if (read_bytes == 0) 
return rbytes;
 
  446      rbytes += read_bytes;
 
  466  static inline int read_all(FILE* fp, std::vector<char>& buf)
 
  468    auto buffer = buf.data();
 
  469    int total_bytes_read = 0;
 
  470    int fill_sz = buf.size();
 
  475      if (rd_bytes == -1) { 
 
  476        if (total_bytes_read == 0) 
return -1;
 
  479      } 
else if (rd_bytes == fill_sz) { 
 
  480        const auto orig_sz = buf.size();
 
  481        const auto new_sz = orig_sz * 2;
 
  483        fill_sz = new_sz - orig_sz;
 
  487        total_bytes_read += rd_bytes;
 
  488        buffer += total_bytes_read;
 
  491        total_bytes_read += rd_bytes;
 
  496    buf.erase(buf.begin()+total_bytes_read, buf.end()); 
 
  497    return total_bytes_read;
 
  500#ifndef __USING_WINDOWS__ 
  520      ret = waitpid(pid, &status, 0);
 
  521      if (
ret == -1) 
break;
 
  522      if (
ret == 0) 
continue;
 
  523      return std::make_pair(
ret, status);
 
  526    return std::make_pair(
ret, status);
 
  560  template <
typename T>
 
  594  explicit input(
const char* filename) {
 
  596    if (fd == -1) 
throw OSError(
"File not found: ", errno);
 
  600    assert (typ == 
PIPE && 
"STDOUT/STDERR not allowed");
 
  601#ifndef __USING_WINDOWS__ 
  629    if (fd == -1) 
throw OSError(
"File not found: ", errno);
 
  633    assert (typ == 
PIPE && 
"STDOUT/STDERR not allowed");
 
  634#ifndef __USING_WINDOWS__ 
  658  explicit error(
const char* filename) {
 
  660    if (fd == -1) 
throw OSError(
"File not found: ", errno);
 
  666#ifndef __USING_WINDOWS__ 
  782  int send(
const char* 
msg, 
size_t length);
 
  783  int send(
const std::vector<char>& 
msg);
 
  785  std::pair<OutBuffer, ErrBuffer> 
communicate(
const char* 
msg, 
size_t length);
 
  794      const char* 
msg, 
size_t length);
 
  883#ifdef __USING_WINDOWS__ 
  884  HANDLE g_hChildStd_IN_Rd = 
nullptr;
 
  885  HANDLE g_hChildStd_IN_Wr = 
nullptr;
 
  886  HANDLE g_hChildStd_OUT_Rd = 
nullptr;
 
  887  HANDLE g_hChildStd_OUT_Wr = 
nullptr;
 
  888  HANDLE g_hChildStd_ERR_Rd = 
nullptr;
 
  889  HANDLE g_hChildStd_ERR_Wr = 
nullptr;
 
  937  template <
typename... Args>
 
  950  template <
typename... Args>
 
  951  Popen(std::initializer_list<const char*> cmd_args, Args&& ...
args)
 
  953    vargs_.insert(
vargs_.end(), cmd_args.begin(), cmd_args.end());
 
  962  template <
typename... Args>
 
  975  int wait() noexcept(false);
 
 1015  template <
typename F, 
typename... Args>
 
 1024#ifdef __USING_WINDOWS__ 
 1025  HANDLE process_handle_;
 
 1026  std::future<void> cleanup_future_;
 
 1047template <
typename F, 
typename... Args>
 
 1060  cargv_.push_back(
nullptr);
 
 1065#ifdef __USING_WINDOWS__ 
 1066  int ret = WaitForSingleObject(process_handle_, INFINITE);
 
 1069  if (
ret != WAIT_OBJECT_0) {
 
 1070    throw OSError(
"Unexpected return code from WaitForSingleObject", 0);
 
 1075  if (FALSE == GetExitCodeProcess(process_handle_, &dretcode_))
 
 1076      throw OSError(
"Failed during call to GetExitCodeProcess", 0);
 
 1078  CloseHandle(process_handle_);
 
 1080  return (
int)dretcode_;
 
 1085    if (errno != ECHILD) 
throw OSError(
"waitpid failed", errno);
 
 1088  if (WIFEXITED(status)) 
return WEXITSTATUS(status);
 
 1089  if (WIFSIGNALED(status)) 
return WTERMSIG(status);
 
 1098#ifdef __USING_WINDOWS__ 
 1100    this->
vargs_.insert(this->
vargs_.begin(), this->exe_name_);
 
 1105  std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> converter;
 
 1106  std::wstring argument;
 
 1107  std::wstring command_line;
 
 1108  bool first_arg = 
true;
 
 1110  for (
auto arg : this->
vargs_) {
 
 1112      command_line += L
" ";
 
 1116    argument = converter.from_bytes(arg);
 
 1117    util::quote_argument(argument, command_line, 
false);
 
 1121  wchar_t *szCmdline = 
new wchar_t[command_line.size() + 1];
 
 1122  wcscpy_s(szCmdline, command_line.size() + 1, command_line.c_str());
 
 1123  PROCESS_INFORMATION piProcInfo;
 
 1124  STARTUPINFOW siStartInfo;
 
 1125  BOOL bSuccess = FALSE;
 
 1126  DWORD creation_flags = CREATE_UNICODE_ENVIRONMENT | CREATE_NO_WINDOW;
 
 1129  ZeroMemory(&piProcInfo, 
sizeof(PROCESS_INFORMATION));
 
 1134  ZeroMemory(&siStartInfo, 
sizeof(STARTUPINFOW));
 
 1135  siStartInfo.cb = 
sizeof(STARTUPINFOW);
 
 1137  siStartInfo.hStdError = this->
stream_.g_hChildStd_ERR_Wr;
 
 1138  siStartInfo.hStdOutput = this->
stream_.g_hChildStd_OUT_Wr;
 
 1139  siStartInfo.hStdInput = this->
stream_.g_hChildStd_IN_Rd;
 
 1141  siStartInfo.dwFlags |= STARTF_USESTDHANDLES;
 
 1144  bSuccess = CreateProcessW(NULL,
 
 1157    DWORD errorMessageID = ::GetLastError();
 
 1158    throw CalledProcessError(
"CreateProcess failed: " + util::get_last_error(errorMessageID), errorMessageID);
 
 1161  CloseHandle(piProcInfo.hThread);
 
 1167  this->process_handle_ = piProcInfo.hProcess;
 
 1169  this->cleanup_future_ = std::async(std::launch::async, [
this] {
 
 1170    WaitForSingleObject(this->process_handle_, INFINITE);
 
 1172    CloseHandle(this->
stream_.g_hChildStd_ERR_Wr);
 
 1173    CloseHandle(this->
stream_.g_hChildStd_OUT_Wr);
 
 1174    CloseHandle(this->
stream_.g_hChildStd_IN_Rd);
 
 1186  int err_rd_pipe, err_wr_pipe;
 
 1200    throw OSError(
"fork failed", errno);
 
 1223      FILE* err_fp = fdopen(err_rd_pipe, 
"r");
 
 1226          throw OSError(
"fdopen failed", errno);
 
 1231      if (read_bytes || strlen(err_buf)) {
 
 1240    } 
catch (std::exception& exp) {
 
 1266    if (err.deferred_) {
 
 1270        throw std::runtime_error(
"Set output before redirecting error to output");
 
 1279#ifndef __USING_WINDOWS__ 
 1284      if (stream.write_to_parent_ == 0)
 
 1287      if (stream.err_write_ == 0 || stream.err_write_ == 1)
 
 1288        stream.err_write_ = dup(stream.err_write_);
 
 1292      auto _dup2_ = [](
int fd, 
int to_fd) {
 
 1302        } 
else if(fd != -1) {
 
 1303          int res = dup2(fd, to_fd);
 
 1304          if (res == -1) 
throw OSError(
"dup2 failed", errno);
 
 1309      _dup2_(stream.read_from_parent_, 0); 
 
 1310      _dup2_(stream.write_to_parent_,  1); 
 
 1311      _dup2_(stream.err_write_,        2); 
 
 1314      if (stream.read_from_parent_ != -1 && stream.read_from_parent_ > 2)
 
 1317      if (stream.write_to_parent_ != -1 && stream.write_to_parent_ > 2)
 
 1320      if (stream.err_write_ != -1 && stream.err_write_ > 2)
 
 1326      if (sys_ret == -1) 
throw OSError(
"execve failed", errno);
 
 1328    } 
catch (
const OSError& exp) {
 
 1331      std::string err_msg(exp.what());
 
 1338    _exit (EXIT_FAILURE);
 
 1345#ifdef __USING_WINDOWS__ 
 1346    util::configure_pipe(&this->g_hChildStd_IN_Rd, &this->g_hChildStd_IN_Wr, &this->g_hChildStd_IN_Wr);
 
 1347    this->
input(util::file_from_handle(this->g_hChildStd_IN_Wr, 
"w"));
 
 1350    util::configure_pipe(&this->g_hChildStd_OUT_Rd, &this->g_hChildStd_OUT_Wr, &this->g_hChildStd_OUT_Rd);
 
 1351    this->
output(util::file_from_handle(this->g_hChildStd_OUT_Rd, 
"r"));
 
 1354    util::configure_pipe(&this->g_hChildStd_ERR_Rd, &this->g_hChildStd_ERR_Wr, &this->g_hChildStd_ERR_Rd);
 
 1355    this->
error(util::file_from_handle(this->g_hChildStd_ERR_Rd, 
"r"));
 
 1365    for (
auto& h : handles) {
 
 1366      if (h == 
nullptr) 
continue;
 
 1367      setvbuf(h, 
nullptr, _IONBF, BUFSIZ);
 
 1383  inline std::pair<OutBuffer, ErrBuffer>
 
 1391    const int len_conv = length;
 
 1398          int wbytes = std::fwrite(
msg, 
sizeof(
char), length, 
stream_->
input());
 
 1399          if (wbytes < len_conv) {
 
 1400            if (errno != EPIPE && errno != EINVAL) {
 
 1401              throw OSError(
"fwrite error", errno);
 
 1418          throw OSError(
"read to obuf failed", errno);
 
 1435          throw OSError(
"read to ebuf failed", errno);
 
 1442      return std::make_pair(std::move(obuf), std::move(ebuf));
 
 1449  inline std::pair<OutBuffer, ErrBuffer>
 
 1454    std::future<int> out_fut, err_fut;
 
 1455    const int length_conv = length;
 
 1460      out_fut = std::async(std::launch::async,
 
 1468      err_fut = std::async(std::launch::async,
 
 1475        int wbytes = std::fwrite(
msg, 
sizeof(
char), length, 
stream_->
input());
 
 1476        if (wbytes < length_conv) {
 
 1477          if (errno != EPIPE && errno != EINVAL) {
 
 1478            throw OSError(
"fwrite error", errno);
 
 1485    if (out_fut.valid()) {
 
 1486      int res = out_fut.get();
 
 1487      if (res != -1) obuf.
length = res;
 
 1490    if (err_fut.valid()) {
 
 1491      int res = err_fut.get();
 
 1492      if (res != -1) ebuf.
length = res;
 
 1496    return std::make_pair(std::move(obuf), std::move(ebuf));
 
CalledProcessError(const std::string &error_msg, int retcode)
 
OSError(const std::string &err_msg, int err_code)
 
std::pair< OutBuffer, ErrBuffer > communicate(const char *msg, size_t length)
 
std::pair< OutBuffer, ErrBuffer > communicate(const std::string &msg)
 
void set_out_buf_cap(size_t cap)
 
Popen(std::initializer_list< const char * > cmd_args, Args &&...args)
 
std::vector< char * > cargv_
 
Popen(std::vector< std::string > vargs_, Args &&... args)
 
void execute_process() noexcept(false)
 
std::vector< std::string > vargs_
 
int send(const std::vector< char > &msg)
 
int send(const std::string &msg)
 
std::pair< OutBuffer, ErrBuffer > communicate()
 
std::pair< OutBuffer, ErrBuffer > communicate(const std::vector< char > &msg)
 
int retcode() const noexcept
 
Popen(const std::string &cmd_args, Args &&...args)
 
int wait() noexcept(false)
 
void set_err_buf_cap(size_t cap)
 
int send(const char *msg, size_t length)
 
Child(Popen *p, int err_wr_pipe)
 
void set_err_buf_cap(size_t cap)
 
Communication(Streams *stream)
 
Communication(Communication &&)=default
 
void set_out_buf_cap(size_t cap)
 
int send(const char *msg, size_t length)
 
std::pair< OutBuffer, ErrBuffer > communicate(const char *msg, size_t length)
 
std::pair< OutBuffer, ErrBuffer > communicate_threaded(const char *msg, size_t length)
 
Communication & operator=(const Communication &)=delete
 
Communication(const Communication &)=delete
 
Communication & operator=(Communication &&)=default
 
std::pair< OutBuffer, ErrBuffer > communicate(const std::vector< char > &msg)
 
std::pair< OutBuffer, ErrBuffer > communicate(const std::vector< char > &msg)
 
int send(const std::vector< char > &msg)
 
void set_out_buf_cap(size_t cap)
 
void setup_comm_channels()
 
Streams(Streams &&)=default
 
std::pair< OutBuffer, ErrBuffer > communicate(const char *msg, size_t length)
 
void set_err_buf_cap(size_t cap)
 
std::shared_ptr< FILE > output_
 
std::shared_ptr< FILE > error_
 
Streams & operator=(const Streams &)=delete
 
int send(const char *msg, size_t length)
 
Streams(const Streams &)=delete
 
Streams & operator=(Streams &&)=default
 
std::shared_ptr< FILE > input_
 
#define T(expected, seed, data)
 
static int read_all(FILE *fp, std::vector< char > &buf)
 
static int read_atmost_n(FILE *fp, char *buf, size_t read_upto)
 
static void set_clo_on_exec(int fd, bool set=true)
 
static std::vector< std::string > split(const std::string &str, const std::string &delims=" \t")
 
static std::pair< int, int > wait_for_child_exit(int pid)
 
static std::pair< int, int > pipe_cloexec() noexcept(false)
 
static int write_n(int fd, const char *buf, size_t length)
 
static const size_t SP_MAX_ERR_BUF_SIZ
 
static const size_t DEFAULT_BUF_CAP_BYTES
 
void set_option(executable &&exe)
 
ArgumentDeducer(Popen *p)
 
error(const char *filename)
 
output(const char *filename)
 
string_arg(const char *arg)
 
string_arg(std::string &&arg)
 
string_arg(const std::string &arg)
 
#define subprocess_fileno
 
std::string SysErrorString(int err)
Return system error string from errno value.