mirror of
https://github.com/arun11299/cpp-subprocess.git
synced 2025-08-06 21:36:19 -04:00
Merge pull request #7 from mirror3000/master
Make library usable from multiple object files
This commit is contained in:
commit
09ee99a282
@ -171,13 +171,12 @@ namespace util
|
|||||||
* Function: join
|
* Function: join
|
||||||
* Parameters:
|
* Parameters:
|
||||||
* [in] vec : Vector of strings which needs to be joined to form
|
* [in] vec : Vector of strings which needs to be joined to form
|
||||||
* a single string with words seperated by
|
* a single string with words seperated by a seperator char.
|
||||||
* a seperator char.
|
|
||||||
* [in] sep : String used to seperate 2 words in the joined string.
|
* [in] sep : String used to seperate 2 words in the joined string.
|
||||||
* Default constructed to ' ' (space).
|
* Default constructed to ' ' (space).
|
||||||
* [out] string: Joined string.
|
* [out] string: Joined string.
|
||||||
*/
|
*/
|
||||||
static
|
static inline
|
||||||
std::string join(const std::vector<std::string>& vec,
|
std::string join(const std::vector<std::string>& vec,
|
||||||
const std::string& sep = " ")
|
const std::string& sep = " ")
|
||||||
{
|
{
|
||||||
@ -197,7 +196,7 @@ namespace util
|
|||||||
* [in] set : If 'true', set FD_CLOEXEC.
|
* [in] set : If 'true', set FD_CLOEXEC.
|
||||||
* If 'false' unset FD_CLOEXEC.
|
* If 'false' unset FD_CLOEXEC.
|
||||||
*/
|
*/
|
||||||
static
|
static inline
|
||||||
void set_clo_on_exec(int fd, bool set = true)
|
void set_clo_on_exec(int fd, bool set = true)
|
||||||
{
|
{
|
||||||
int flags = fcntl(fd, F_GETFD, 0);
|
int flags = fcntl(fd, F_GETFD, 0);
|
||||||
@ -217,7 +216,7 @@ namespace util
|
|||||||
* First element of pair is the read descriptor of pipe.
|
* First element of pair is the read descriptor of pipe.
|
||||||
* Second element is the write descriptor of pipe.
|
* Second element is the write descriptor of pipe.
|
||||||
*/
|
*/
|
||||||
static
|
static inline
|
||||||
std::pair<int, int> pipe_cloexec() throw (OSError)
|
std::pair<int, int> pipe_cloexec() throw (OSError)
|
||||||
{
|
{
|
||||||
int pipe_fds[2];
|
int pipe_fds[2];
|
||||||
@ -244,7 +243,7 @@ namespace util
|
|||||||
* `buf` to `fd`.
|
* `buf` to `fd`.
|
||||||
* [out] int : Number of bytes written or -1 in case of failure.
|
* [out] int : Number of bytes written or -1 in case of failure.
|
||||||
*/
|
*/
|
||||||
static
|
static inline
|
||||||
int write_n(int fd, const char* buf, size_t length)
|
int write_n(int fd, const char* buf, size_t length)
|
||||||
{
|
{
|
||||||
int nwritten = 0;
|
int nwritten = 0;
|
||||||
@ -271,7 +270,7 @@ namespace util
|
|||||||
* will retry to read from `fd`, but only till the EINTR counter
|
* will retry to read from `fd`, but only till the EINTR counter
|
||||||
* reaches 50 after which it will return with whatever data it read.
|
* reaches 50 after which it will return with whatever data it read.
|
||||||
*/
|
*/
|
||||||
static
|
static inline
|
||||||
int read_atmost_n(int fd, char* buf, size_t read_upto)
|
int read_atmost_n(int fd, char* buf, size_t read_upto)
|
||||||
{
|
{
|
||||||
int rbytes = 0;
|
int rbytes = 0;
|
||||||
@ -309,7 +308,7 @@ namespace util
|
|||||||
*/
|
*/
|
||||||
template <typename Buffer>
|
template <typename Buffer>
|
||||||
// Requires Buffer to be of type class Buffer
|
// Requires Buffer to be of type class Buffer
|
||||||
static int read_all(int fd, Buffer& buf)
|
static inline int read_all(int fd, Buffer& buf)
|
||||||
{
|
{
|
||||||
size_t orig_size = buf.size();
|
size_t orig_size = buf.size();
|
||||||
size_t increment = orig_size;
|
size_t increment = orig_size;
|
||||||
@ -350,7 +349,7 @@ namespace util
|
|||||||
* NOTE: This is a blocking call as in, it will loop
|
* NOTE: This is a blocking call as in, it will loop
|
||||||
* till the child is exited.
|
* till the child is exited.
|
||||||
*/
|
*/
|
||||||
static
|
static inline
|
||||||
std::pair<int, int> wait_for_child_exit(int pid)
|
std::pair<int, int> wait_for_child_exit(int pid)
|
||||||
{
|
{
|
||||||
int status = 0;
|
int status = 0;
|
||||||
@ -1041,19 +1040,19 @@ private:
|
|||||||
int retcode_ = -1;
|
int retcode_ = -1;
|
||||||
};
|
};
|
||||||
|
|
||||||
void Popen::init_args() {
|
inline void Popen::init_args() {
|
||||||
populate_c_argv();
|
populate_c_argv();
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename F, typename... Args>
|
template <typename F, typename... Args>
|
||||||
void Popen::init_args(F&& farg, Args&&... args)
|
inline void Popen::init_args(F&& farg, Args&&... args)
|
||||||
{
|
{
|
||||||
detail::ArgumentDeducer argd(this);
|
detail::ArgumentDeducer argd(this);
|
||||||
argd.set_option(std::forward<F>(farg));
|
argd.set_option(std::forward<F>(farg));
|
||||||
init_args(std::forward<Args>(args)...);
|
init_args(std::forward<Args>(args)...);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Popen::populate_c_argv()
|
inline void Popen::populate_c_argv()
|
||||||
{
|
{
|
||||||
cargv_.clear();
|
cargv_.clear();
|
||||||
cargv_.reserve(vargs_.size() + 1);
|
cargv_.reserve(vargs_.size() + 1);
|
||||||
@ -1061,7 +1060,7 @@ void Popen::populate_c_argv()
|
|||||||
cargv_.push_back(nullptr);
|
cargv_.push_back(nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Popen::start_process() throw (CalledProcessError, OSError)
|
inline void Popen::start_process() throw (CalledProcessError, OSError)
|
||||||
{
|
{
|
||||||
// The process was started/tried to be started
|
// The process was started/tried to be started
|
||||||
// in the constructor itself.
|
// in the constructor itself.
|
||||||
@ -1075,7 +1074,7 @@ void Popen::start_process() throw (CalledProcessError, OSError)
|
|||||||
execute_process();
|
execute_process();
|
||||||
}
|
}
|
||||||
|
|
||||||
int Popen::wait() throw (OSError)
|
inline int Popen::wait() throw (OSError)
|
||||||
{
|
{
|
||||||
int ret, status;
|
int ret, status;
|
||||||
std::tie(ret, status) = util::wait_for_child_exit(pid());
|
std::tie(ret, status) = util::wait_for_child_exit(pid());
|
||||||
@ -1090,7 +1089,7 @@ int Popen::wait() throw (OSError)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int Popen::poll() throw (OSError)
|
inline int Popen::poll() throw (OSError)
|
||||||
{
|
{
|
||||||
int status;
|
int status;
|
||||||
if (!child_created_) return -1; // TODO: ??
|
if (!child_created_) return -1; // TODO: ??
|
||||||
@ -1125,14 +1124,14 @@ int Popen::poll() throw (OSError)
|
|||||||
return retcode_;
|
return retcode_;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Popen::kill(int sig_num)
|
inline void Popen::kill(int sig_num)
|
||||||
{
|
{
|
||||||
if (session_leader_) killpg(child_pid_, sig_num);
|
if (session_leader_) killpg(child_pid_, sig_num);
|
||||||
else ::kill(child_pid_, sig_num);
|
else ::kill(child_pid_, sig_num);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Popen::execute_process() throw (CalledProcessError, OSError)
|
inline void Popen::execute_process() throw (CalledProcessError, OSError)
|
||||||
{
|
{
|
||||||
int err_rd_pipe, err_wr_pipe;
|
int err_rd_pipe, err_wr_pipe;
|
||||||
std::tie(err_rd_pipe, err_wr_pipe) = util::pipe_cloexec();
|
std::tie(err_rd_pipe, err_wr_pipe) = util::pipe_cloexec();
|
||||||
@ -1211,45 +1210,45 @@ void Popen::execute_process() throw (CalledProcessError, OSError)
|
|||||||
|
|
||||||
namespace detail {
|
namespace detail {
|
||||||
|
|
||||||
void ArgumentDeducer::set_option(executable&& exe) {
|
inline void ArgumentDeducer::set_option(executable&& exe) {
|
||||||
popen_->exe_name_ = std::move(exe.arg_value);
|
popen_->exe_name_ = std::move(exe.arg_value);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ArgumentDeducer::set_option(cwd&& cwdir) {
|
inline void ArgumentDeducer::set_option(cwd&& cwdir) {
|
||||||
popen_->cwd_ = std::move(cwdir.arg_value);
|
popen_->cwd_ = std::move(cwdir.arg_value);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ArgumentDeducer::set_option(bufsize&& bsiz) {
|
inline void ArgumentDeducer::set_option(bufsize&& bsiz) {
|
||||||
popen_->stream_.bufsiz_ = bsiz.bufsiz;
|
popen_->stream_.bufsiz_ = bsiz.bufsiz;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ArgumentDeducer::set_option(environment&& env) {
|
inline void ArgumentDeducer::set_option(environment&& env) {
|
||||||
popen_->env_ = std::move(env.env_);
|
popen_->env_ = std::move(env.env_);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ArgumentDeducer::set_option(defer_spawn&& defer) {
|
inline void ArgumentDeducer::set_option(defer_spawn&& defer) {
|
||||||
popen_->defer_process_start_ = defer.defer;
|
popen_->defer_process_start_ = defer.defer;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ArgumentDeducer::set_option(shell&& sh) {
|
inline void ArgumentDeducer::set_option(shell&& sh) {
|
||||||
popen_->shell_ = sh.shell_;
|
popen_->shell_ = sh.shell_;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ArgumentDeducer::set_option(session_leader&& sleader) {
|
inline void ArgumentDeducer::set_option(session_leader&& sleader) {
|
||||||
popen_->session_leader_ = sleader.leader_;
|
popen_->session_leader_ = sleader.leader_;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ArgumentDeducer::set_option(input&& inp) {
|
inline void ArgumentDeducer::set_option(input&& inp) {
|
||||||
if (inp.rd_ch_ != -1) popen_->stream_.read_from_parent_ = inp.rd_ch_;
|
if (inp.rd_ch_ != -1) popen_->stream_.read_from_parent_ = inp.rd_ch_;
|
||||||
if (inp.wr_ch_ != -1) popen_->stream_.write_to_child_ = inp.wr_ch_;
|
if (inp.wr_ch_ != -1) popen_->stream_.write_to_child_ = inp.wr_ch_;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ArgumentDeducer::set_option(output&& out) {
|
inline void ArgumentDeducer::set_option(output&& out) {
|
||||||
if (out.wr_ch_ != -1) popen_->stream_.write_to_parent_ = out.wr_ch_;
|
if (out.wr_ch_ != -1) popen_->stream_.write_to_parent_ = out.wr_ch_;
|
||||||
if (out.rd_ch_ != -1) popen_->stream_.read_from_child_ = out.rd_ch_;
|
if (out.rd_ch_ != -1) popen_->stream_.read_from_child_ = out.rd_ch_;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ArgumentDeducer::set_option(error&& err) {
|
inline void ArgumentDeducer::set_option(error&& err) {
|
||||||
if (err.deferred_) {
|
if (err.deferred_) {
|
||||||
if (popen_->stream_.write_to_parent_) {
|
if (popen_->stream_.write_to_parent_) {
|
||||||
popen_->stream_.err_write_ = popen_->stream_.write_to_parent_;
|
popen_->stream_.err_write_ = popen_->stream_.write_to_parent_;
|
||||||
@ -1261,17 +1260,17 @@ namespace detail {
|
|||||||
if (err.rd_ch_ != -1) popen_->stream_.err_read_ = err.rd_ch_;
|
if (err.rd_ch_ != -1) popen_->stream_.err_read_ = err.rd_ch_;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ArgumentDeducer::set_option(close_fds&& cfds) {
|
inline void ArgumentDeducer::set_option(close_fds&& cfds) {
|
||||||
popen_->close_fds_ = cfds.close_all;
|
popen_->close_fds_ = cfds.close_all;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ArgumentDeducer::set_option(preexec_func&& prefunc) {
|
inline void ArgumentDeducer::set_option(preexec_func&& prefunc) {
|
||||||
popen_->preexec_fn_ = std::move(prefunc);
|
popen_->preexec_fn_ = std::move(prefunc);
|
||||||
popen_->has_preexec_fn_ = true;
|
popen_->has_preexec_fn_ = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Child::execute_child() {
|
inline void Child::execute_child() {
|
||||||
int sys_ret = -1;
|
int sys_ret = -1;
|
||||||
auto& stream = parent_->stream_;
|
auto& stream = parent_->stream_;
|
||||||
|
|
||||||
@ -1368,7 +1367,7 @@ namespace detail {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Streams::setup_comm_channels()
|
inline void Streams::setup_comm_channels()
|
||||||
{
|
{
|
||||||
if (write_to_child_ != -1) input(fdopen(write_to_child_, "wb"));
|
if (write_to_child_ != -1) input(fdopen(write_to_child_, "wb"));
|
||||||
if (read_from_child_ != -1) output(fdopen(read_from_child_, "rb"));
|
if (read_from_child_ != -1) output(fdopen(read_from_child_, "rb"));
|
||||||
@ -1391,18 +1390,18 @@ namespace detail {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int Communication::send(const char* msg, size_t length)
|
inline int Communication::send(const char* msg, size_t length)
|
||||||
{
|
{
|
||||||
if (stream_->input() == nullptr) return -1;
|
if (stream_->input() == nullptr) return -1;
|
||||||
return std::fwrite(msg, sizeof(char), length, stream_->input());
|
return std::fwrite(msg, sizeof(char), length, stream_->input());
|
||||||
}
|
}
|
||||||
|
|
||||||
int Communication::send(const std::vector<char>& msg)
|
inline int Communication::send(const std::vector<char>& msg)
|
||||||
{
|
{
|
||||||
return send(msg.data(), msg.size());
|
return send(msg.data(), msg.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
std::pair<OutBuffer, ErrBuffer>
|
inline std::pair<OutBuffer, ErrBuffer>
|
||||||
Communication::communicate(const char* msg, size_t length)
|
Communication::communicate(const char* msg, size_t length)
|
||||||
{
|
{
|
||||||
// Optimization from subprocess.py
|
// Optimization from subprocess.py
|
||||||
@ -1467,7 +1466,7 @@ namespace detail {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
std::pair<OutBuffer, ErrBuffer>
|
inline std::pair<OutBuffer, ErrBuffer>
|
||||||
Communication::communicate_threaded(const char* msg, size_t length)
|
Communication::communicate_threaded(const char* msg, size_t length)
|
||||||
{
|
{
|
||||||
OutBuffer obuf;
|
OutBuffer obuf;
|
||||||
@ -1544,10 +1543,13 @@ namespace detail
|
|||||||
return Popen(std::forward<F>(farg), std::forward<Args>(args)...).wait();
|
return Popen(std::forward<F>(farg), std::forward<Args>(args)...).wait();
|
||||||
}
|
}
|
||||||
|
|
||||||
void pipeline_impl(std::vector<Popen>& cmds) { /* EMPTY IMPL */ }
|
static inline void pipeline_impl(std::vector<Popen>& cmds)
|
||||||
|
{
|
||||||
|
/* EMPTY IMPL */
|
||||||
|
}
|
||||||
|
|
||||||
template<typename... Args>
|
template<typename... Args>
|
||||||
void pipeline_impl(std::vector<Popen>& cmds,
|
static inline void pipeline_impl(std::vector<Popen>& cmds,
|
||||||
const std::string& cmd,
|
const std::string& cmd,
|
||||||
Args&&... args)
|
Args&&... args)
|
||||||
{
|
{
|
||||||
|
Loading…
x
Reference in New Issue
Block a user