-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathprocess.cpp
More file actions
95 lines (84 loc) · 2.72 KB
/
process.cpp
File metadata and controls
95 lines (84 loc) · 2.72 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
#include "process.hpp"
#include <stdexcept>
#include <streambuf>
#include <initializer_list>
#include <sys/wait.h>
#include <cstring>
#include <unistd.h>
#include "utils.hpp"
namespace detail {
// ==========================================
// iopipes::PipeFds
// ==========================================
iopipes::PipeFds::PipeFds() { pipe(fds); }
void iopipes::PipeFds::close() { ::close(readEnd); ::close(writeEnd); }
iopipes::PipeFds::~PipeFds() { close(); }
// ==========================================
// iopipes
// ==========================================
iopipes::iopipes() : std::iostream(this) { setg(buffer, buffer, buffer); }
void iopipes::sendEOF() { opipe.close(); }
void iopipes::close() { ipipe.close(); opipe.close(); }
void iopipes::closeUnneded() { ::close(ipipe.writeEnd); ::close(opipe.readEnd); }
void iopipes::dup() {
dup2(ipipe.writeEnd, STDOUT_FILENO);
dup2(opipe.readEnd, STDIN_FILENO);
close();
}
iopipes::traits::int_type iopipes::overflow(traits::int_type c) {
if (c == traits::eof()) return traits::eof();
if (::write(opipe.writeEnd, &c, 1) != 1) return traits::eof();
return c;
}
std::streamsize iopipes::xsputn(const char* data, std::streamsize len) {
ssize_t writeret = ::write(opipe.writeEnd, data, len);
return writeret == -1 ? traits::eof() : writeret;
}
int iopipes::underflow() {
if (gptr() == egptr()) {
ssize_t readCount = ::read(ipipe.readEnd, gptr(), sizeof buffer);
if (readCount <= 0) return traits::eof();
setg(buffer, buffer, buffer + readCount);
}
return traits::to_int_type(*gptr());
}
// ==========================================
// StringList
// ==========================================
StringList::StringList(std::vector<std::string_view> args) : strings(args) {
cstrings.reserve(strings.size() + 1);
for (int i = 0; i < strings.size(); i++) cstrings.push_back(strings[i].data());
cstrings.push_back(nullptr);
}
const char** StringList::carray() { return cstrings.data(); }
}
// ==========================================
// Process
// ==========================================
Process::Process(std::string_view file, std::string_view arg0, std::vector<std::string_view> args) :
file(file), argv(prepend(args, arg0)) {}
Process::Process(std::string_view file, std::vector<std::string_view> args) :
file(file), argv(prepend(args, file)) {}
void Process::run() {
int exitCode;
pid = fork();
if (pid == 0) {
pipes.dup();
int ret = execvp(file.c_str(), (char**)argv.carray());
exit(1);
}
pipes.closeUnneded();
}
void Process::exec() {
execvp(file.c_str(), (char**)argv.carray());
throw std::runtime_error("Cannot exec process");
}
detail::iopipes& Process::stream() {
return pipes;
}
int Process::join() {
int exitCode;
pipes.close();
waitpid(pid, &exitCode, 0);
return exitCode;
}