mirror of
https://github.com/AGWA/git-crypt.git
synced 2025-12-26 20:53:08 -08:00
Add Coprocess class
It provides a convenient way to spawn a process and read from/write to its stdin/stdout.
This commit is contained in:
113
util-unix.cpp
113
util-unix.cpp
@@ -162,119 +162,6 @@ std::string our_exe_path ()
|
||||
}
|
||||
}
|
||||
|
||||
static int execvp (const std::string& file, const std::vector<std::string>& args)
|
||||
{
|
||||
std::vector<const char*> args_c_str;
|
||||
args_c_str.reserve(args.size());
|
||||
for (std::vector<std::string>::const_iterator arg(args.begin()); arg != args.end(); ++arg) {
|
||||
args_c_str.push_back(arg->c_str());
|
||||
}
|
||||
args_c_str.push_back(NULL);
|
||||
return execvp(file.c_str(), const_cast<char**>(&args_c_str[0]));
|
||||
}
|
||||
|
||||
int exec_command (const std::vector<std::string>& command)
|
||||
{
|
||||
pid_t child = fork();
|
||||
if (child == -1) {
|
||||
throw System_error("fork", "", errno);
|
||||
}
|
||||
if (child == 0) {
|
||||
execvp(command[0], command);
|
||||
perror(command[0].c_str());
|
||||
_exit(-1);
|
||||
}
|
||||
int status = 0;
|
||||
if (waitpid(child, &status, 0) == -1) {
|
||||
throw System_error("waitpid", "", errno);
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
int exec_command (const std::vector<std::string>& command, std::ostream& output)
|
||||
{
|
||||
int pipefd[2];
|
||||
if (pipe(pipefd) == -1) {
|
||||
throw System_error("pipe", "", errno);
|
||||
}
|
||||
pid_t child = fork();
|
||||
if (child == -1) {
|
||||
int fork_errno = errno;
|
||||
close(pipefd[0]);
|
||||
close(pipefd[1]);
|
||||
throw System_error("fork", "", fork_errno);
|
||||
}
|
||||
if (child == 0) {
|
||||
close(pipefd[0]);
|
||||
if (pipefd[1] != 1) {
|
||||
dup2(pipefd[1], 1);
|
||||
close(pipefd[1]);
|
||||
}
|
||||
execvp(command[0], command);
|
||||
perror(command[0].c_str());
|
||||
_exit(-1);
|
||||
}
|
||||
close(pipefd[1]);
|
||||
char buffer[1024];
|
||||
ssize_t bytes_read;
|
||||
while ((bytes_read = read(pipefd[0], buffer, sizeof(buffer))) > 0) {
|
||||
output.write(buffer, bytes_read);
|
||||
}
|
||||
if (bytes_read == -1) {
|
||||
int read_errno = errno;
|
||||
close(pipefd[0]);
|
||||
throw System_error("read", "", read_errno);
|
||||
}
|
||||
close(pipefd[0]);
|
||||
int status = 0;
|
||||
if (waitpid(child, &status, 0) == -1) {
|
||||
throw System_error("waitpid", "", errno);
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
int exec_command_with_input (const std::vector<std::string>& command, const char* p, size_t len)
|
||||
{
|
||||
int pipefd[2];
|
||||
if (pipe(pipefd) == -1) {
|
||||
throw System_error("pipe", "", errno);
|
||||
}
|
||||
pid_t child = fork();
|
||||
if (child == -1) {
|
||||
int fork_errno = errno;
|
||||
close(pipefd[0]);
|
||||
close(pipefd[1]);
|
||||
throw System_error("fork", "", fork_errno);
|
||||
}
|
||||
if (child == 0) {
|
||||
close(pipefd[1]);
|
||||
if (pipefd[0] != 0) {
|
||||
dup2(pipefd[0], 0);
|
||||
close(pipefd[0]);
|
||||
}
|
||||
execvp(command[0], command);
|
||||
perror(command[0].c_str());
|
||||
_exit(-1);
|
||||
}
|
||||
close(pipefd[0]);
|
||||
while (len > 0) {
|
||||
ssize_t bytes_written = write(pipefd[1], p, len);
|
||||
if (bytes_written == -1) {
|
||||
int write_errno = errno;
|
||||
close(pipefd[1]);
|
||||
throw System_error("write", "", write_errno);
|
||||
}
|
||||
p += bytes_written;
|
||||
len -= bytes_written;
|
||||
}
|
||||
close(pipefd[1]);
|
||||
int status = 0;
|
||||
if (waitpid(child, &status, 0) == -1) {
|
||||
throw System_error("waitpid", "", errno);
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
int exit_status (int wait_status)
|
||||
{
|
||||
return wait_status != -1 && WIFEXITED(wait_status) ? WEXITSTATUS(wait_status) : -1;
|
||||
|
||||
Reference in New Issue
Block a user