mirror of
https://github.com/arun11299/cpp-subprocess.git
synced 2025-09-08 06:44:02 -04:00
Added check_output API
This commit is contained in:
parent
d9d132b22c
commit
6817d92533
7
main.cc
7
main.cc
@ -5,5 +5,12 @@ using namespace subprocess;
|
||||
int main() {
|
||||
auto p = Popen({"./script.sh"},
|
||||
output{"out.txt"});
|
||||
|
||||
auto buf = check_output({"echo", "\"It works!\""});
|
||||
std::cout << buf.buf.data() << " :: " << buf.length << std::endl;
|
||||
|
||||
auto buf2 = check_output("cat subprocess.hpp");
|
||||
std::cout << buf2.buf.data() << " :: " << buf2.length << std::endl;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -50,6 +50,7 @@ public:
|
||||
|
||||
namespace util
|
||||
{
|
||||
|
||||
static std::vector<std::string>
|
||||
split(const std::string& str, const std::string& delims=" \t")
|
||||
{
|
||||
@ -291,6 +292,31 @@ class Popen;
|
||||
|
||||
namespace detail {
|
||||
|
||||
// Type trait for searching a type within
|
||||
// a variadic parameter pack
|
||||
|
||||
template <typename... T> struct param_pack{};
|
||||
|
||||
template <typename F, typename T> struct has_type;
|
||||
|
||||
template <typename F>
|
||||
struct has_type<F, param_pack<>> {
|
||||
static constexpr bool value = false;
|
||||
};
|
||||
|
||||
template <typename F, typename... T>
|
||||
struct has_type<F, param_pack<F, T...>> {
|
||||
static constexpr bool value = true;
|
||||
};
|
||||
|
||||
template <typename F, typename H, typename... T>
|
||||
struct has_type<F, param_pack<H,T...>> {
|
||||
static constexpr bool value =
|
||||
std::is_same<F, typename std::decay<H>::type>::value ? true : has_type<F, param_pack<T...>>::value;
|
||||
};
|
||||
|
||||
//----
|
||||
|
||||
struct ArgumentDeducer
|
||||
{
|
||||
ArgumentDeducer(Popen* p): popen_(p) {}
|
||||
@ -478,7 +504,7 @@ public:
|
||||
|
||||
int retcode() const noexcept { return retcode_; }
|
||||
|
||||
bool wait() throw(OSError);
|
||||
int wait() throw(OSError);
|
||||
|
||||
int poll() throw(OSError);
|
||||
|
||||
@ -567,17 +593,19 @@ void Popen::start_process() throw (CalledProcessError, OSError)
|
||||
execute_process();
|
||||
}
|
||||
|
||||
bool Popen::wait() throw (OSError)
|
||||
int Popen::wait() throw (OSError)
|
||||
{
|
||||
int ret, status;
|
||||
std::tie(ret, status) = util::wait_for_child_exit(pid());
|
||||
if (ret == -1) {
|
||||
if (errno != ECHILD) throw OSError("waitpid failed", errno);
|
||||
return true;
|
||||
return 0;
|
||||
}
|
||||
if (!WIFEXITED(status)) return false;
|
||||
if (WIFEXITED(status)) return WEXITSTATUS(status);
|
||||
if (WIFSIGNALED(status)) return WTERMSIG(status);
|
||||
else return 255;
|
||||
|
||||
return true;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int Popen::poll() throw (OSError)
|
||||
@ -606,10 +634,10 @@ int Popen::poll() throw (OSError)
|
||||
// status.
|
||||
if (errno == ECHILD) retcode_ = 0;
|
||||
else throw OSError("waitpid failed", errno);
|
||||
} else {
|
||||
retcode_ = ret;
|
||||
}
|
||||
|
||||
retcode_ = ret;
|
||||
|
||||
return retcode_;
|
||||
}
|
||||
|
||||
@ -879,8 +907,11 @@ namespace detail {
|
||||
if (rbytes == -1) {
|
||||
throw OSError("read to obuf failed", errno);
|
||||
}
|
||||
|
||||
obuf.length = rbytes;
|
||||
// Close the output stream
|
||||
stream_->output_.reset();
|
||||
|
||||
} else if (stream_->error()) {
|
||||
// Same screwness applies here as well
|
||||
ebuf.add_cap(err_buf_cap_);
|
||||
@ -893,6 +924,8 @@ namespace detail {
|
||||
if (rbytes == -1) {
|
||||
throw OSError("read to ebuf failed", errno);
|
||||
}
|
||||
|
||||
ebuf.length = rbytes;
|
||||
// Close the error stream
|
||||
stream_->error_.reset();
|
||||
}
|
||||
@ -961,6 +994,40 @@ namespace detail {
|
||||
|
||||
// Convenience Functions
|
||||
//
|
||||
//
|
||||
namespace detail
|
||||
{
|
||||
template<typename F, typename... Args>
|
||||
OutBuffer check_output_impl(F& farg, Args&&... args)
|
||||
{
|
||||
static_assert(!detail::has_type<output, detail::param_pack<Args...>>::value, "output not allowed in args");
|
||||
auto p = Popen(farg, std::forward<Args>(args)..., output{PIPE});
|
||||
auto res = p.communicate(nullptr, 0);
|
||||
auto retcode = p.poll();
|
||||
if (retcode) {
|
||||
throw CalledProcessError("Command failed");
|
||||
}
|
||||
return (res.first);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
template<typename... Args>
|
||||
int call(Args&&... args)
|
||||
{
|
||||
return Popen(std::forward<Args>(args)...).wait();
|
||||
}
|
||||
|
||||
template <typename... Args>
|
||||
OutBuffer check_output(std::initializer_list<const char*> plist, Args&&... args)
|
||||
{
|
||||
return detail::check_output_impl(plist, std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template <typename... Args>
|
||||
OutBuffer check_output(const std::string& arg, Args&&... args)
|
||||
{
|
||||
return detail::check_output_impl(arg, std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
};
|
||||
|
Loading…
x
Reference in New Issue
Block a user