forked from OctaForge/libostd
rename to subprocess_stream/error
This commit is contained in:
parent
5fc674e4d3
commit
005485f6a6
|
@ -84,7 +84,7 @@ Sink &&split_args(Sink &&out, string_range str) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @brief Thrown on errors in ostd::subprocess. */
|
/** @brief Thrown on errors in ostd::subprocess. */
|
||||||
struct process_error: std::runtime_error {
|
struct subprocess_error: std::runtime_error {
|
||||||
using std::runtime_error::runtime_error;
|
using std::runtime_error::runtime_error;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -97,7 +97,7 @@ struct process_error: std::runtime_error {
|
||||||
*
|
*
|
||||||
* Only use the `STDOUT` value for stderr stream.
|
* Only use the `STDOUT` value for stderr stream.
|
||||||
*/
|
*/
|
||||||
enum class process_stream {
|
enum class subprocess_stream {
|
||||||
DEFAULT = 0, ///< Do not perform any redirection.
|
DEFAULT = 0, ///< Do not perform any redirection.
|
||||||
PIPE, ///< Capture the stream as an ostd::file_stream.
|
PIPE, ///< Capture the stream as an ostd::file_stream.
|
||||||
STDOUT ///< Writes to stderr will be written to stdout.
|
STDOUT ///< Writes to stderr will be written to stdout.
|
||||||
|
@ -114,7 +114,7 @@ enum class process_stream {
|
||||||
struct OSTD_EXPORT subprocess {
|
struct OSTD_EXPORT subprocess {
|
||||||
/** @brief The standard input redirection mode.
|
/** @brief The standard input redirection mode.
|
||||||
*
|
*
|
||||||
* The value is one of ostd::process_stream. Set this before opening
|
* The value is one of ostd::subprocess_stream. Set this before opening
|
||||||
* the subprocess. If it's set to `PIPE`, you will be able to write
|
* the subprocess. If it's set to `PIPE`, you will be able to write
|
||||||
* into the standard input of the child process using the `in` member,
|
* into the standard input of the child process using the `in` member,
|
||||||
* which is a standard ostd::file_stream. Never set it to `STDOUT`
|
* which is a standard ostd::file_stream. Never set it to `STDOUT`
|
||||||
|
@ -124,11 +124,11 @@ struct OSTD_EXPORT subprocess {
|
||||||
* @see ostd::subprocess::in, ostd::subprocess::use_out,
|
* @see ostd::subprocess::in, ostd::subprocess::use_out,
|
||||||
* ostd::subprocess::use_err
|
* ostd::subprocess::use_err
|
||||||
*/
|
*/
|
||||||
process_stream use_in = process_stream::DEFAULT;
|
subprocess_stream use_in = subprocess_stream::DEFAULT;
|
||||||
|
|
||||||
/** @brief The standard output redirection mode.
|
/** @brief The standard output redirection mode.
|
||||||
*
|
*
|
||||||
* The value is one of ostd::process_stream. Set this before opening
|
* The value is one of ostd::subprocess_stream. Set this before opening
|
||||||
* the subprocess. If it's set to `PIPE`, you will be able to read
|
* the subprocess. If it's set to `PIPE`, you will be able to read
|
||||||
* from the standard output of the child process using the `out` member,
|
* from the standard output of the child process using the `out` member,
|
||||||
* which is a standard ostd::file_stream. Setting this to `STDOUT` has
|
* which is a standard ostd::file_stream. Setting this to `STDOUT` has
|
||||||
|
@ -137,11 +137,11 @@ struct OSTD_EXPORT subprocess {
|
||||||
* @see ostd::subprocess::out, ostd::subprocess::use_in,
|
* @see ostd::subprocess::out, ostd::subprocess::use_in,
|
||||||
* ostd::subprocess::use_err
|
* ostd::subprocess::use_err
|
||||||
*/
|
*/
|
||||||
process_stream use_out = process_stream::DEFAULT;
|
subprocess_stream use_out = subprocess_stream::DEFAULT;
|
||||||
|
|
||||||
/** @brief The standard error redirection mode.
|
/** @brief The standard error redirection mode.
|
||||||
*
|
*
|
||||||
* The value is one of ostd::process_stream. Set this before opening
|
* The value is one of ostd::subprocess_stream. Set this before opening
|
||||||
* the subprocess. If it's set to `PIPE`, you will be able to read
|
* the subprocess. If it's set to `PIPE`, you will be able to read
|
||||||
* from the standard error of the child process using the `err` member,
|
* from the standard error of the child process using the `err` member,
|
||||||
* which is a standard ostd::file_stream. Setting this to `STDOUT`
|
* which is a standard ostd::file_stream. Setting this to `STDOUT`
|
||||||
|
@ -153,7 +153,7 @@ struct OSTD_EXPORT subprocess {
|
||||||
* @see ostd::subprocess::err, ostd::subprocess::use_in,
|
* @see ostd::subprocess::err, ostd::subprocess::use_in,
|
||||||
* ostd::subprocess::use_out
|
* ostd::subprocess::use_out
|
||||||
*/
|
*/
|
||||||
process_stream use_err = process_stream::DEFAULT;
|
subprocess_stream use_err = subprocess_stream::DEFAULT;
|
||||||
|
|
||||||
/** @brief The standard input stream when redirected.
|
/** @brief The standard input stream when redirected.
|
||||||
*
|
*
|
||||||
|
@ -184,9 +184,9 @@ struct OSTD_EXPORT subprocess {
|
||||||
|
|
||||||
/** @brief Initializes the structure with the given stream redirections. */
|
/** @brief Initializes the structure with the given stream redirections. */
|
||||||
subprocess(
|
subprocess(
|
||||||
process_stream in_use = process_stream::DEFAULT,
|
subprocess_stream in_use = subprocess_stream::DEFAULT,
|
||||||
process_stream out_use = process_stream::DEFAULT,
|
subprocess_stream out_use = subprocess_stream::DEFAULT,
|
||||||
process_stream err_use = process_stream::DEFAULT
|
subprocess_stream err_use = subprocess_stream::DEFAULT
|
||||||
) noexcept:
|
) noexcept:
|
||||||
use_in(in_use), use_out(out_use), use_err(err_use)
|
use_in(in_use), use_out(out_use), use_err(err_use)
|
||||||
{}
|
{}
|
||||||
|
@ -200,9 +200,9 @@ struct OSTD_EXPORT subprocess {
|
||||||
template<typename InputRange>
|
template<typename InputRange>
|
||||||
subprocess(
|
subprocess(
|
||||||
string_range cmd, InputRange &&args, bool use_path = true,
|
string_range cmd, InputRange &&args, bool use_path = true,
|
||||||
process_stream in_use = process_stream::DEFAULT,
|
subprocess_stream in_use = subprocess_stream::DEFAULT,
|
||||||
process_stream out_use = process_stream::DEFAULT,
|
subprocess_stream out_use = subprocess_stream::DEFAULT,
|
||||||
process_stream err_use = process_stream::DEFAULT,
|
subprocess_stream err_use = subprocess_stream::DEFAULT,
|
||||||
std::enable_if_t<
|
std::enable_if_t<
|
||||||
is_input_range<InputRange>, bool
|
is_input_range<InputRange>, bool
|
||||||
> = true
|
> = true
|
||||||
|
@ -221,9 +221,9 @@ struct OSTD_EXPORT subprocess {
|
||||||
template<typename InputRange>
|
template<typename InputRange>
|
||||||
subprocess(
|
subprocess(
|
||||||
InputRange &&args, bool use_path = true,
|
InputRange &&args, bool use_path = true,
|
||||||
process_stream in_use = process_stream::DEFAULT,
|
subprocess_stream in_use = subprocess_stream::DEFAULT,
|
||||||
process_stream out_use = process_stream::DEFAULT,
|
subprocess_stream out_use = subprocess_stream::DEFAULT,
|
||||||
process_stream err_use = process_stream::DEFAULT,
|
subprocess_stream err_use = subprocess_stream::DEFAULT,
|
||||||
std::enable_if_t<
|
std::enable_if_t<
|
||||||
is_input_range<InputRange>, bool
|
is_input_range<InputRange>, bool
|
||||||
> = true
|
> = true
|
||||||
|
@ -273,21 +273,21 @@ struct OSTD_EXPORT subprocess {
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
close();
|
close();
|
||||||
} catch (process_error const &) {}
|
} catch (subprocess_error const &) {}
|
||||||
reset();
|
reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @brief Waits for a currently running child process to be done.
|
/** @brief Waits for a currently running child process to be done.
|
||||||
*
|
*
|
||||||
* If there isn't any child process assigned to this, it will throw
|
* If there isn't any child process assigned to this, it will throw
|
||||||
* ostd::process_error. It will also throw the same exception if some
|
* ostd::subprocess_error. It will also throw the same exception if
|
||||||
* other error has occured. It will not throw if the command has
|
* some other error has occured. It will not throw if the command has
|
||||||
* executed but exited with a non-zero code. This code will be
|
* executed but exited with a non-zero code. This code will be
|
||||||
* returned instead.
|
* returned instead.
|
||||||
*
|
*
|
||||||
* @returns The child process return code on success.
|
* @returns The child process return code on success.
|
||||||
*
|
*
|
||||||
* @throws ostd::process_error on failure of any kind.
|
* @throws ostd::subprocess_error on failure of any kind.
|
||||||
*
|
*
|
||||||
* @see open_path(), open_command()
|
* @see open_path(), open_command()
|
||||||
*/
|
*/
|
||||||
|
@ -302,13 +302,13 @@ struct OSTD_EXPORT subprocess {
|
||||||
*
|
*
|
||||||
* If `path` is empty, the first element of `args` is used.
|
* If `path` is empty, the first element of `args` is used.
|
||||||
*
|
*
|
||||||
* If this fails, ostd::process_error will be thrown.
|
* If this fails, ostd::subprocess_error will be thrown.
|
||||||
*
|
*
|
||||||
* On success, a new subprocess will be created and this will return
|
* On success, a new subprocess will be created and this will return
|
||||||
* without waiting for it to finish. Use close() to wait and get the
|
* without waiting for it to finish. Use close() to wait and get the
|
||||||
* return code.
|
* return code.
|
||||||
*
|
*
|
||||||
* @throws ostd::process_error on failure of any kind.
|
* @throws ostd::subprocess_error on failure of any kind.
|
||||||
*
|
*
|
||||||
* @see open_command(), close()
|
* @see open_command(), close()
|
||||||
*/
|
*/
|
||||||
|
@ -334,13 +334,13 @@ struct OSTD_EXPORT subprocess {
|
||||||
*
|
*
|
||||||
* If `cmd` is empty, the first element of `args` is used.
|
* If `cmd` is empty, the first element of `args` is used.
|
||||||
*
|
*
|
||||||
* If this fails, ostd::process_error will be thrown.
|
* If this fails, ostd::subprocess_error will be thrown.
|
||||||
*
|
*
|
||||||
* On success, a new subprocess will be created and this will return
|
* On success, a new subprocess will be created and this will return
|
||||||
* without waiting for it to finish. Use close() to wait and get the
|
* without waiting for it to finish. Use close() to wait and get the
|
||||||
* return code.
|
* return code.
|
||||||
*
|
*
|
||||||
* @throws ostd::process_error on failure of any kind.
|
* @throws ostd::subprocess_error on failure of any kind.
|
||||||
*
|
*
|
||||||
* @see open_path(), close()
|
* @see open_path(), close()
|
||||||
*/
|
*/
|
||||||
|
@ -367,12 +367,12 @@ private:
|
||||||
argv.emplace_back(args.front());
|
argv.emplace_back(args.front());
|
||||||
}
|
}
|
||||||
if (argv.empty()) {
|
if (argv.empty()) {
|
||||||
throw process_error{"no arguments given"};
|
throw subprocess_error{"no arguments given"};
|
||||||
}
|
}
|
||||||
if (cmd.empty()) {
|
if (cmd.empty()) {
|
||||||
cmd = argv[0];
|
cmd = argv[0];
|
||||||
if (cmd.empty()) {
|
if (cmd.empty()) {
|
||||||
throw process_error{"no command given"};
|
throw subprocess_error{"no command given"};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
open_impl(std::string{cmd}, argv, use_path);
|
open_impl(std::string{cmd}, argv, use_path);
|
||||||
|
|
|
@ -88,12 +88,12 @@ struct pipe {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void open(process_stream use) {
|
void open(subprocess_stream use) {
|
||||||
if (use != process_stream::PIPE) {
|
if (use != subprocess_stream::PIPE) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (::pipe(fd) < 0) {
|
if (::pipe(fd) < 0) {
|
||||||
throw process_error{"could not open pipe"};
|
throw subprocess_error{"could not open pipe"};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -104,7 +104,7 @@ struct pipe {
|
||||||
void fdopen(file_stream &s, bool write) {
|
void fdopen(file_stream &s, bool write) {
|
||||||
FILE *p = ::fdopen(fd[std::size_t(write)], write ? "w" : "r");
|
FILE *p = ::fdopen(fd[std::size_t(write)], write ? "w" : "r");
|
||||||
if (!p) {
|
if (!p) {
|
||||||
throw process_error{"could not open redirected stream"};
|
throw subprocess_error{"could not open redirected stream"};
|
||||||
}
|
}
|
||||||
/* do not close twice, the stream will close it */
|
/* do not close twice, the stream will close it */
|
||||||
fd[std::size_t(write)] = -1;
|
fd[std::size_t(write)] = -1;
|
||||||
|
@ -135,8 +135,8 @@ OSTD_EXPORT void subprocess::open_impl(
|
||||||
std::string const &cmd, std::vector<std::string> const &args,
|
std::string const &cmd, std::vector<std::string> const &args,
|
||||||
bool use_path
|
bool use_path
|
||||||
) {
|
) {
|
||||||
if (use_in == process_stream::STDOUT) {
|
if (use_in == subprocess_stream::STDOUT) {
|
||||||
throw process_error{"could not redirect stdin to stdout"};
|
throw subprocess_error{"could not redirect stdin to stdout"};
|
||||||
}
|
}
|
||||||
|
|
||||||
auto argp = std::make_unique<char *[]>(args.size() + 1);
|
auto argp = std::make_unique<char *[]>(args.size() + 1);
|
||||||
|
@ -148,14 +148,14 @@ OSTD_EXPORT void subprocess::open_impl(
|
||||||
/* fd_errno used to detect if exec failed */
|
/* fd_errno used to detect if exec failed */
|
||||||
pipe fd_errno, fd_stdin, fd_stdout, fd_stderr;
|
pipe fd_errno, fd_stdin, fd_stdout, fd_stderr;
|
||||||
|
|
||||||
fd_errno.open(process_stream::PIPE);
|
fd_errno.open(subprocess_stream::PIPE);
|
||||||
fd_stdin.open(use_in);
|
fd_stdin.open(use_in);
|
||||||
fd_stdout.open(use_out);
|
fd_stdout.open(use_out);
|
||||||
fd_stderr.open(use_err);
|
fd_stderr.open(use_err);
|
||||||
|
|
||||||
auto cpid = fork();
|
auto cpid = fork();
|
||||||
if (cpid == -1) {
|
if (cpid == -1) {
|
||||||
throw process_error{"fork failed"};
|
throw subprocess_error{"fork failed"};
|
||||||
} else if (!cpid) {
|
} else if (!cpid) {
|
||||||
/* child process */
|
/* child process */
|
||||||
fd_errno.close(false);
|
fd_errno.close(false);
|
||||||
|
@ -165,24 +165,24 @@ OSTD_EXPORT void subprocess::open_impl(
|
||||||
std::exit(1);
|
std::exit(1);
|
||||||
}
|
}
|
||||||
/* prepare standard streams */
|
/* prepare standard streams */
|
||||||
if (use_in == process_stream::PIPE) {
|
if (use_in == subprocess_stream::PIPE) {
|
||||||
fd_stdin.close(true);
|
fd_stdin.close(true);
|
||||||
if (!fd_stdin.dup2(STDIN_FILENO, fd_errno, false)) {
|
if (!fd_stdin.dup2(STDIN_FILENO, fd_errno, false)) {
|
||||||
std::exit(1);
|
std::exit(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (use_out == process_stream::PIPE) {
|
if (use_out == subprocess_stream::PIPE) {
|
||||||
fd_stdout.close(false);
|
fd_stdout.close(false);
|
||||||
if (!fd_stdout.dup2(STDOUT_FILENO, fd_errno, true)) {
|
if (!fd_stdout.dup2(STDOUT_FILENO, fd_errno, true)) {
|
||||||
std::exit(1);
|
std::exit(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (use_err == process_stream::PIPE) {
|
if (use_err == subprocess_stream::PIPE) {
|
||||||
fd_stderr.close(false);
|
fd_stderr.close(false);
|
||||||
if (!fd_stderr.dup2(STDERR_FILENO, fd_errno, true)) {
|
if (!fd_stderr.dup2(STDERR_FILENO, fd_errno, true)) {
|
||||||
std::exit(1);
|
std::exit(1);
|
||||||
}
|
}
|
||||||
} else if (use_err == process_stream::STDOUT) {
|
} else if (use_err == subprocess_stream::STDOUT) {
|
||||||
if (dup2(STDOUT_FILENO, STDERR_FILENO) < 0) {
|
if (dup2(STDOUT_FILENO, STDERR_FILENO) < 0) {
|
||||||
fd_errno.write_errno();
|
fd_errno.write_errno();
|
||||||
std::exit(1);
|
std::exit(1);
|
||||||
|
@ -199,15 +199,15 @@ OSTD_EXPORT void subprocess::open_impl(
|
||||||
} else {
|
} else {
|
||||||
/* parent process */
|
/* parent process */
|
||||||
fd_errno.close(true);
|
fd_errno.close(true);
|
||||||
if (use_in == process_stream::PIPE) {
|
if (use_in == subprocess_stream::PIPE) {
|
||||||
fd_stdin.close(false);
|
fd_stdin.close(false);
|
||||||
fd_stdin.fdopen(in, true);
|
fd_stdin.fdopen(in, true);
|
||||||
}
|
}
|
||||||
if (use_out == process_stream::PIPE) {
|
if (use_out == subprocess_stream::PIPE) {
|
||||||
fd_stdout.close(true);
|
fd_stdout.close(true);
|
||||||
fd_stdout.fdopen(out, false);
|
fd_stdout.fdopen(out, false);
|
||||||
}
|
}
|
||||||
if (use_err == process_stream::PIPE) {
|
if (use_err == subprocess_stream::PIPE) {
|
||||||
fd_stderr.close(true);
|
fd_stderr.close(true);
|
||||||
fd_stderr.fdopen(err, false);
|
fd_stderr.fdopen(err, false);
|
||||||
}
|
}
|
||||||
|
@ -230,25 +230,25 @@ OSTD_EXPORT void subprocess::reset() {
|
||||||
|
|
||||||
OSTD_EXPORT int subprocess::close() {
|
OSTD_EXPORT int subprocess::close() {
|
||||||
if (!p_current) {
|
if (!p_current) {
|
||||||
throw process_error{"no child process"};
|
throw subprocess_error{"no child process"};
|
||||||
}
|
}
|
||||||
data *pd = static_cast<data *>(p_current);
|
data *pd = static_cast<data *>(p_current);
|
||||||
int retc = 0;
|
int retc = 0;
|
||||||
if (pid_t wp; (wp = waitpid(pd->pid, &retc, 0)) < 0) {
|
if (pid_t wp; (wp = waitpid(pd->pid, &retc, 0)) < 0) {
|
||||||
reset();
|
reset();
|
||||||
throw process_error{"child process wait failed"};
|
throw subprocess_error{"child process wait failed"};
|
||||||
}
|
}
|
||||||
if (retc) {
|
if (retc) {
|
||||||
int eno;
|
int eno;
|
||||||
auto r = read(pd->errno_fd, &eno, sizeof(int));
|
auto r = read(pd->errno_fd, &eno, sizeof(int));
|
||||||
reset();
|
reset();
|
||||||
if (r < 0) {
|
if (r < 0) {
|
||||||
throw process_error{"could not read from pipe"};
|
throw subprocess_error{"could not read from pipe"};
|
||||||
} else if (r == sizeof(int)) {
|
} else if (r == sizeof(int)) {
|
||||||
auto ec = std::system_category().default_error_condition(eno);
|
auto ec = std::system_category().default_error_condition(eno);
|
||||||
auto app = appender<std::string>();
|
auto app = appender<std::string>();
|
||||||
format(app, "could not execute subprocess (%s)", ec.message());
|
format(app, "could not execute subprocess (%s)", ec.message());
|
||||||
throw process_error{std::move(app.get())};
|
throw subprocess_error{std::move(app.get())};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
reset();
|
reset();
|
||||||
|
|
|
@ -101,15 +101,15 @@ struct pipe {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void open(process_stream use, SECURITY_ATTRIBUTES &sa, bool read) {
|
void open(subprocess_stream use, SECURITY_ATTRIBUTES &sa, bool read) {
|
||||||
if (use != process_stream::PIPE) {
|
if (use != subprocess_stream::PIPE) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!CreatePipe(&p_r, &p_w, &sa, 0)) {
|
if (!CreatePipe(&p_r, &p_w, &sa, 0)) {
|
||||||
throw process_error{"could not open pipe"};
|
throw subprocess_error{"could not open pipe"};
|
||||||
}
|
}
|
||||||
if (!SetHandleInformation(read ? p_r : p_w, HANDLE_FLAG_INHERIT, 0)) {
|
if (!SetHandleInformation(read ? p_r : p_w, HANDLE_FLAG_INHERIT, 0)) {
|
||||||
throw process_error{"could not set pipe parameters"};
|
throw subprocess_error{"could not set pipe parameters"};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -119,7 +119,7 @@ struct pipe {
|
||||||
read ? _O_RDONLY : 0
|
read ? _O_RDONLY : 0
|
||||||
);
|
);
|
||||||
if (fd < 0) {
|
if (fd < 0) {
|
||||||
throw process_error{"could not open redirected stream"};
|
throw subprocess_error{"could not open redirected stream"};
|
||||||
}
|
}
|
||||||
if (read) {
|
if (read) {
|
||||||
p_r = nullptr;
|
p_r = nullptr;
|
||||||
|
@ -129,7 +129,7 @@ struct pipe {
|
||||||
auto p = _fdopen(fd, read ? "r" : "w");
|
auto p = _fdopen(fd, read ? "r" : "w");
|
||||||
if (!p) {
|
if (!p) {
|
||||||
_close(fd);
|
_close(fd);
|
||||||
throw process_error{"could not open redirected stream"};
|
throw subprocess_error{"could not open redirected stream"};
|
||||||
}
|
}
|
||||||
s.open(p, [](FILE *f) {
|
s.open(p, [](FILE *f) {
|
||||||
std::fclose(f);
|
std::fclose(f);
|
||||||
|
@ -283,8 +283,8 @@ static std::string concat_args(std::vector<std::string> const &args) {
|
||||||
OSTD_EXPORT void subprocess::open_impl(
|
OSTD_EXPORT void subprocess::open_impl(
|
||||||
std::string const &cmd, std::vector<std::string> const &args, bool use_path
|
std::string const &cmd, std::vector<std::string> const &args, bool use_path
|
||||||
) {
|
) {
|
||||||
if (use_in == process_stream::STDOUT) {
|
if (use_in == subprocess_stream::STDOUT) {
|
||||||
throw process_error{"could not redirect stdin to stdout"};
|
throw subprocess_error{"could not redirect stdin to stdout"};
|
||||||
}
|
}
|
||||||
|
|
||||||
/* pipes */
|
/* pipes */
|
||||||
|
@ -310,33 +310,33 @@ OSTD_EXPORT void subprocess::open_impl(
|
||||||
|
|
||||||
si.cb = sizeof(STARTUPINFOW);
|
si.cb = sizeof(STARTUPINFOW);
|
||||||
|
|
||||||
if (use_in == process_stream::PIPE) {
|
if (use_in == subprocess_stream::PIPE) {
|
||||||
si.hStdInput = pipe_in.p_r;
|
si.hStdInput = pipe_in.p_r;
|
||||||
pipe_in.fdopen(in, false);
|
pipe_in.fdopen(in, false);
|
||||||
} else {
|
} else {
|
||||||
si.hStdInput = GetStdHandle(STD_INPUT_HANDLE);
|
si.hStdInput = GetStdHandle(STD_INPUT_HANDLE);
|
||||||
if (si.hStdInput == INVALID_HANDLE_VALUE) {
|
if (si.hStdInput == INVALID_HANDLE_VALUE) {
|
||||||
throw process_error{"could not get standard input handle"};
|
throw subprocess_error{"could not get standard input handle"};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (use_out == process_stream::PIPE) {
|
if (use_out == subprocess_stream::PIPE) {
|
||||||
si.hStdOutput = pipe_out.p_w;
|
si.hStdOutput = pipe_out.p_w;
|
||||||
pipe_out.fdopen(out, true);
|
pipe_out.fdopen(out, true);
|
||||||
} else {
|
} else {
|
||||||
si.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE);
|
si.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||||
if (si.hStdOutput == INVALID_HANDLE_VALUE) {
|
if (si.hStdOutput == INVALID_HANDLE_VALUE) {
|
||||||
throw process_error{"could not get standard output handle"};
|
throw subprocess_error{"could not get standard output handle"};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (use_err == process_stream::PIPE) {
|
if (use_err == subprocess_stream::PIPE) {
|
||||||
si.hStdError = pipe_err.p_w;
|
si.hStdError = pipe_err.p_w;
|
||||||
pipe_err.fdopen(err, true);
|
pipe_err.fdopen(err, true);
|
||||||
} else if (use_err == process_stream::STDOUT) {
|
} else if (use_err == subprocess_stream::STDOUT) {
|
||||||
si.hStdError = si.hStdOutput;
|
si.hStdError = si.hStdOutput;
|
||||||
} else {
|
} else {
|
||||||
si.hStdError = GetStdHandle(STD_ERROR_HANDLE);
|
si.hStdError = GetStdHandle(STD_ERROR_HANDLE);
|
||||||
if (si.hStdError == INVALID_HANDLE_VALUE) {
|
if (si.hStdError == INVALID_HANDLE_VALUE) {
|
||||||
throw process_error{"could not get standard error handle"};
|
throw subprocess_error{"could not get standard error handle"};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
si.dwFlags |= STARTF_USESTDHANDLES;
|
si.dwFlags |= STARTF_USESTDHANDLES;
|
||||||
|
@ -348,7 +348,7 @@ OSTD_EXPORT void subprocess::open_impl(
|
||||||
if (!MultiByteToWideChar(
|
if (!MultiByteToWideChar(
|
||||||
CP_UTF8, 0, cmd.data(), cmd.size() + 1, wcmd.get(), cmd.size() + 1
|
CP_UTF8, 0, cmd.data(), cmd.size() + 1, wcmd.get(), cmd.size() + 1
|
||||||
)) {
|
)) {
|
||||||
throw process_error{"unicode conversion failed"};
|
throw subprocess_error{"unicode conversion failed"};
|
||||||
}
|
}
|
||||||
if (!use_path) {
|
if (!use_path) {
|
||||||
cmdpath = wcmd.get();
|
cmdpath = wcmd.get();
|
||||||
|
@ -364,7 +364,7 @@ OSTD_EXPORT void subprocess::open_impl(
|
||||||
if (!MultiByteToWideChar(
|
if (!MultiByteToWideChar(
|
||||||
CP_UTF8, 0, astr.data(), astr.size() + 1, cmdline.get(), astr.size() + 1
|
CP_UTF8, 0, astr.data(), astr.size() + 1, cmdline.get(), astr.size() + 1
|
||||||
)) {
|
)) {
|
||||||
throw process_error{"unicode conversion failed"};
|
throw subprocess_error{"unicode conversion failed"};
|
||||||
}
|
}
|
||||||
|
|
||||||
/* owned by CreateProcess, do not close explicitly */
|
/* owned by CreateProcess, do not close explicitly */
|
||||||
|
@ -390,7 +390,7 @@ OSTD_EXPORT void subprocess::open_impl(
|
||||||
};
|
};
|
||||||
|
|
||||||
if (!success) {
|
if (!success) {
|
||||||
throw process_error{"could not execute subprocess"};
|
throw subprocess_error{"could not execute subprocess"};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -400,7 +400,7 @@ OSTD_EXPORT void subprocess::reset() {
|
||||||
|
|
||||||
OSTD_EXPORT int subprocess::close() {
|
OSTD_EXPORT int subprocess::close() {
|
||||||
if (!p_current) {
|
if (!p_current) {
|
||||||
throw process_error{"no child process"};
|
throw subprocess_error{"no child process"};
|
||||||
}
|
}
|
||||||
|
|
||||||
data *pd = static_cast<data *>(p_current);
|
data *pd = static_cast<data *>(p_current);
|
||||||
|
@ -409,7 +409,7 @@ OSTD_EXPORT int subprocess::close() {
|
||||||
CloseHandle(pd->process);
|
CloseHandle(pd->process);
|
||||||
CloseHandle(pd->thread);
|
CloseHandle(pd->thread);
|
||||||
reset();
|
reset();
|
||||||
throw process_error{"child process wait failed"};
|
throw subprocess_error{"child process wait failed"};
|
||||||
}
|
}
|
||||||
|
|
||||||
DWORD ec = 0;
|
DWORD ec = 0;
|
||||||
|
@ -417,7 +417,7 @@ OSTD_EXPORT int subprocess::close() {
|
||||||
CloseHandle(pd->process);
|
CloseHandle(pd->process);
|
||||||
CloseHandle(pd->thread);
|
CloseHandle(pd->thread);
|
||||||
reset();
|
reset();
|
||||||
throw process_error{"could not retrieve exit code"};
|
throw subprocess_error{"could not retrieve exit code"};
|
||||||
}
|
}
|
||||||
|
|
||||||
CloseHandle(pd->process);
|
CloseHandle(pd->process);
|
||||||
|
|
Loading…
Reference in a new issue