36#ifndef BITCOIN_UTIL_SUBPROCESS_H
37#define BITCOIN_UTIL_SUBPROCESS_H
49#include <initializer_list>
73 #include <sys/types.h>
81 #define subprocess_close _close
82 #define subprocess_fileno _fileno
83 #define subprocess_open _open
84 #define subprocess_write _write
86 #define subprocess_close close
87 #define subprocess_fileno fileno
88 #define subprocess_open open
89 #define subprocess_write write
187 for (
auto it =
argument.begin();; ++it) {
190 while (it !=
argument.end() && *it == L
'\\') {
206 else if (*it == L
'"') {
234 return std::string();
254 throw OSError(
"invalid_mode", 0);
257 if (mode[0] ==
'w') {
260 else if (mode[0] ==
'r') {
264 throw OSError(
"file_from_handle", 0);
270 throw OSError(
"_open_osfhandle", 0);
293 throw OSError(
"CreatePipe", 0);
297 throw OSError(
"SetHandleInformation", 0);
310 static inline std::vector<std::string>
313 std::vector<std::string>
res;
318 if (pos == std::string::npos) {
319 res.emplace_back(str.substr(
init, str.length()));
394 int write_n(
int fd,
const char* buf,
size_t length)
464 auto buffer = buf.data();
476 const auto orig_sz = buf.size();
517 if (
ret == -1)
break;
518 if (
ret == 0)
continue;
519 return std::make_pair(
ret, status);
522 return std::make_pair(
ret, status);
556 template <
typename T>
590 explicit input(
const char* filename) {
596 assert (typ ==
PIPE &&
"STDOUT/STDERR not allowed");
629 assert (typ ==
PIPE &&
"STDOUT/STDERR not allowed");
654 explicit error(
const char* filename) {
780 int send(
const char* msg,
size_t length);
781 int send(
const std::vector<char>& msg);
783 std::pair<OutBuffer, ErrBuffer>
communicate(
const char* msg,
size_t length);
784 std::pair<OutBuffer, ErrBuffer>
communicate(
const std::vector<char>& msg)
792 const char* msg,
size_t length);
862 int send(
const char* msg,
size_t length)
865 int send(
const std::vector<char>& msg)
868 std::pair<OutBuffer, ErrBuffer>
communicate(
const char* msg,
size_t length)
871 std::pair<OutBuffer, ErrBuffer>
communicate(
const std::vector<char>& msg)
935 template <
typename... Args>
947 template <
typename... Args>
966 int send(
const char* msg,
size_t length)
969 int send(
const std::string& msg)
970 {
return send(msg.c_str(), msg.size()); }
972 int send(
const std::vector<char>& msg)
975 std::pair<OutBuffer, ErrBuffer>
communicate(
const char* msg,
size_t length)
982 std::pair<OutBuffer, ErrBuffer>
communicate(
const std::string& msg)
987 std::pair<OutBuffer, ErrBuffer>
communicate(
const std::vector<char>& msg)
1000 template <
typename F,
typename... Args>
1030template <
typename F,
typename... Args>
1034 argd.set_option(std::forward<F>(
farg));
1043 cargv_.push_back(
nullptr);
1053 throw OSError(
"Unexpected return code from WaitForSingleObject", 0);
1059 throw OSError(
"Failed during call to GetExitCodeProcess", 0);
1088 std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>>
converter;
1121 siStartInfo.hStdOutput = this->
stream_.g_hChildStd_OUT_Wr;
1122 siStartInfo.hStdInput = this->
stream_.g_hChildStd_IN_Rd;
1195 chld.execute_child();
1223 }
catch (std::exception&
exp) {
1249 if (err.deferred_) {
1253 throw std::runtime_error(
"Set output before redirecting error to output");
1267 if (
stream.write_to_parent_ == 0)
1285 }
else if(fd != -1) {
1297 if (
stream.read_from_parent_ != -1 &&
stream.read_from_parent_ > 2)
1300 if (
stream.write_to_parent_ != -1 &&
stream.write_to_parent_ > 2)
1349 if (h ==
nullptr)
continue;
1358 return std::fwrite(msg,
sizeof(
char), length,
stream_->
input());
1363 return send(msg.data(), msg.size());
1366 inline std::pair<OutBuffer, ErrBuffer>
1425 return std::make_pair(std::move(
obuf), std::move(
ebuf));
1432 inline std::pair<OutBuffer, ErrBuffer>
1443 out_fut = std::async(std::launch::async,
1451 err_fut = std::async(std::launch::async,
1471 else obuf.length = 0;
1476 else ebuf.length = 0;
1479 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
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.
constexpr auto Ticks(Dur2 d)
Helper to count the seconds of a duration/time_point.