forked from ntrrgc/right-window
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathsubprocess.cpp
88 lines (73 loc) · 2.08 KB
/
subprocess.cpp
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
//
// Created by ntrrgc on 24/01/16.
//
#include "subprocess.h"
#include <stdexcept>
#include <unistd.h>
#include <sstream>
#include <sys/wait.h>
// NOTE: This implementation is UNIX specific but it's currently only needed for BSPWM.
using namespace std;
namespace subprocess {
string check_output(std::vector<string> args) {
int pipe_fd[2];
if (pipe(pipe_fd) != 0) {
perror("pipe");
exit(2);
}
int pid = fork();
if (pid < 0) {
perror("fork");
exit(2);
}
if (pid == 0) {
// I'm the child
close(pipe_fd[0]);
char **args_raw = new char *[args.size() + 1];
for (size_t i = 0; i < args.size(); ++i) {
args_raw[i] = const_cast<char *>(args[i].c_str());
}
args_raw[args.size()] = nullptr;
// Close parent files and substitute stdout with an end of the pipe
close(STDIN_FILENO);
close(STDERR_FILENO);
close(STDOUT_FILENO);
dup2(pipe_fd[1], STDOUT_FILENO);
close(pipe_fd[1]);
execvp(args[0].c_str(), args_raw);
throw std::runtime_error("Could not launch subprocess");
} else {
// I'm the parent
close(pipe_fd[1]);
vector<char> output;
char buf[4096];
ssize_t ret;
while (0 != (ret = read(pipe_fd[0], buf, sizeof(buf)))) {
if (ret < 0 && errno != EINTR) {
perror("read");
exit(2);
} else if (ret > 0) {
// Append to output
output.insert(output.end(), buf, buf + ret);
}
}
close(pipe_fd[0]);
close(pipe_fd[1]);
int status;
if (waitpid(pid, &status, 0) < 0) {
perror("waitpid");
exit(2);
}
if (WEXITSTATUS(status) == 0) {
// Successful exit
output.push_back('\0');
return string(output.begin(), output.end());
} else {
throw std::runtime_error("Subprocess failed");
}
}
}
void call(std::vector<std::string> args) {
check_output(args);
}
}