New upstream version 0.7.0
This commit is contained in:
parent
9d364dec8b
commit
0586de081a
|
|
@ -50,7 +50,7 @@ target_include_directories(
|
||||||
PUBLIC "./include"
|
PUBLIC "./include"
|
||||||
PRIVATE "./src")
|
PRIVATE "./src")
|
||||||
set_target_properties(hyprutils PROPERTIES VERSION ${hyprutils_VERSION}
|
set_target_properties(hyprutils PROPERTIES VERSION ${hyprutils_VERSION}
|
||||||
SOVERSION 5)
|
SOVERSION 6)
|
||||||
target_link_libraries(hyprutils PkgConfig::deps)
|
target_link_libraries(hyprutils PkgConfig::deps)
|
||||||
|
|
||||||
# tests
|
# tests
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,7 @@ namespace Hyprutils {
|
||||||
public:
|
public:
|
||||||
/* Creates a process object, doesn't run yet */
|
/* Creates a process object, doesn't run yet */
|
||||||
CProcess(const std::string& binary_, const std::vector<std::string>& args_);
|
CProcess(const std::string& binary_, const std::vector<std::string>& args_);
|
||||||
|
~CProcess();
|
||||||
|
|
||||||
void addEnv(const std::string& name, const std::string& value);
|
void addEnv(const std::string& name, const std::string& value);
|
||||||
|
|
||||||
|
|
@ -29,14 +30,14 @@ namespace Hyprutils {
|
||||||
const std::string& stdOut();
|
const std::string& stdOut();
|
||||||
const std::string& stdErr();
|
const std::string& stdErr();
|
||||||
|
|
||||||
const pid_t pid();
|
pid_t pid();
|
||||||
|
|
||||||
|
// only for sync
|
||||||
|
int exitCode();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::string binary, out, err;
|
struct impl;
|
||||||
std::vector<std::string> args;
|
impl* m_impl;
|
||||||
std::vector<std::pair<std::string, std::string>> env;
|
|
||||||
pid_t grandchildPid = 0;
|
|
||||||
int stdoutFD = -1, stderrFD = -1;
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -12,12 +12,25 @@ using namespace Hyprutils::OS;
|
||||||
#include <sys/wait.h>
|
#include <sys/wait.h>
|
||||||
#include <sys/poll.h>
|
#include <sys/poll.h>
|
||||||
|
|
||||||
Hyprutils::OS::CProcess::CProcess(const std::string& binary_, const std::vector<std::string>& args_) : binary(binary_), args(args_) {
|
struct Hyprutils::OS::CProcess::impl {
|
||||||
;
|
std::string binary, out, err;
|
||||||
|
std::vector<std::string> args;
|
||||||
|
std::vector<std::pair<std::string, std::string>> env;
|
||||||
|
pid_t grandchildPid = 0;
|
||||||
|
int stdoutFD = -1, stderrFD = -1, exitCode = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
Hyprutils::OS::CProcess::CProcess(const std::string& binary, const std::vector<std::string>& args) : m_impl(new impl()) {
|
||||||
|
m_impl->binary = binary;
|
||||||
|
m_impl->args = args;
|
||||||
|
}
|
||||||
|
|
||||||
|
Hyprutils::OS::CProcess::~CProcess() {
|
||||||
|
delete m_impl;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Hyprutils::OS::CProcess::addEnv(const std::string& name, const std::string& value) {
|
void Hyprutils::OS::CProcess::addEnv(const std::string& name, const std::string& value) {
|
||||||
env.emplace_back(std::make_pair<>(name, value));
|
m_impl->env.emplace_back(std::make_pair<>(name, value));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Hyprutils::OS::CProcess::runSync() {
|
bool Hyprutils::OS::CProcess::runSync() {
|
||||||
|
|
@ -49,8 +62,8 @@ bool Hyprutils::OS::CProcess::runSync() {
|
||||||
|
|
||||||
// build argv
|
// build argv
|
||||||
std::vector<const char*> argsC;
|
std::vector<const char*> argsC;
|
||||||
argsC.emplace_back(strdup(binary.c_str()));
|
argsC.emplace_back(strdup(m_impl->binary.c_str()));
|
||||||
for (auto& arg : args) {
|
for (auto& arg : m_impl->args) {
|
||||||
// TODO: does this leak? Can we just pipe c_str() as the strings won't be realloc'd?
|
// TODO: does this leak? Can we just pipe c_str() as the strings won't be realloc'd?
|
||||||
argsC.emplace_back(strdup(arg.c_str()));
|
argsC.emplace_back(strdup(arg.c_str()));
|
||||||
}
|
}
|
||||||
|
|
@ -58,21 +71,21 @@ bool Hyprutils::OS::CProcess::runSync() {
|
||||||
argsC.emplace_back(nullptr);
|
argsC.emplace_back(nullptr);
|
||||||
|
|
||||||
// pass env
|
// pass env
|
||||||
for (auto& [n, v] : env) {
|
for (auto& [n, v] : m_impl->env) {
|
||||||
setenv(n.c_str(), v.c_str(), 1);
|
setenv(n.c_str(), v.c_str(), 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
execvp(binary.c_str(), (char* const*)argsC.data());
|
execvp(m_impl->binary.c_str(), (char* const*)argsC.data());
|
||||||
exit(1);
|
exit(1);
|
||||||
} else {
|
} else {
|
||||||
// parent
|
// parent
|
||||||
close(outPipe[1]);
|
close(outPipe[1]);
|
||||||
close(errPipe[1]);
|
close(errPipe[1]);
|
||||||
|
|
||||||
out = "";
|
m_impl->out = "";
|
||||||
err = "";
|
m_impl->err = "";
|
||||||
|
|
||||||
grandchildPid = pid;
|
m_impl->grandchildPid = pid;
|
||||||
|
|
||||||
std::array<char, 1024> buf;
|
std::array<char, 1024> buf;
|
||||||
buf.fill(0);
|
buf.fill(0);
|
||||||
|
|
@ -116,7 +129,7 @@ bool Hyprutils::OS::CProcess::runSync() {
|
||||||
|
|
||||||
if (pollfds[0].revents & POLLIN) {
|
if (pollfds[0].revents & POLLIN) {
|
||||||
while ((ret = read(outPipe[0], buf.data(), 1023)) > 0) {
|
while ((ret = read(outPipe[0], buf.data(), 1023)) > 0) {
|
||||||
out += std::string_view{(char*)buf.data(), (size_t)ret};
|
m_impl->out += std::string_view{(char*)buf.data(), (size_t)ret};
|
||||||
}
|
}
|
||||||
|
|
||||||
buf.fill(0);
|
buf.fill(0);
|
||||||
|
|
@ -124,7 +137,7 @@ bool Hyprutils::OS::CProcess::runSync() {
|
||||||
|
|
||||||
if (pollfds[1].revents & POLLIN) {
|
if (pollfds[1].revents & POLLIN) {
|
||||||
while ((ret = read(errPipe[0], buf.data(), 1023)) > 0) {
|
while ((ret = read(errPipe[0], buf.data(), 1023)) > 0) {
|
||||||
err += std::string_view{(char*)buf.data(), (size_t)ret};
|
m_impl->err += std::string_view{(char*)buf.data(), (size_t)ret};
|
||||||
}
|
}
|
||||||
|
|
||||||
buf.fill(0);
|
buf.fill(0);
|
||||||
|
|
@ -133,13 +146,13 @@ bool Hyprutils::OS::CProcess::runSync() {
|
||||||
|
|
||||||
// Final reads. Nonblock, so its ok.
|
// Final reads. Nonblock, so its ok.
|
||||||
while ((ret = read(outPipe[0], buf.data(), 1023)) > 0) {
|
while ((ret = read(outPipe[0], buf.data(), 1023)) > 0) {
|
||||||
out += std::string_view{(char*)buf.data(), (size_t)ret};
|
m_impl->out += std::string_view{(char*)buf.data(), (size_t)ret};
|
||||||
}
|
}
|
||||||
|
|
||||||
buf.fill(0);
|
buf.fill(0);
|
||||||
|
|
||||||
while ((ret = read(errPipe[0], buf.data(), 1023)) > 0) {
|
while ((ret = read(errPipe[0], buf.data(), 1023)) > 0) {
|
||||||
err += std::string_view{(char*)buf.data(), (size_t)ret};
|
m_impl->err += std::string_view{(char*)buf.data(), (size_t)ret};
|
||||||
}
|
}
|
||||||
|
|
||||||
buf.fill(0);
|
buf.fill(0);
|
||||||
|
|
@ -148,7 +161,11 @@ bool Hyprutils::OS::CProcess::runSync() {
|
||||||
close(errPipe[0]);
|
close(errPipe[0]);
|
||||||
|
|
||||||
// reap child
|
// reap child
|
||||||
waitpid(pid, nullptr, 0);
|
int status = 0;
|
||||||
|
waitpid(pid, &status, 0);
|
||||||
|
|
||||||
|
if (WIFEXITED(status))
|
||||||
|
m_impl->exitCode = WEXITSTATUS(status);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
@ -182,19 +199,19 @@ bool Hyprutils::OS::CProcess::runAsync() {
|
||||||
close(socket[1]);
|
close(socket[1]);
|
||||||
// build argv
|
// build argv
|
||||||
std::vector<const char*> argsC;
|
std::vector<const char*> argsC;
|
||||||
argsC.emplace_back(strdup(binary.c_str()));
|
argsC.emplace_back(strdup(m_impl->binary.c_str()));
|
||||||
for (auto& arg : args) {
|
for (auto& arg : m_impl->args) {
|
||||||
argsC.emplace_back(strdup(arg.c_str()));
|
argsC.emplace_back(strdup(arg.c_str()));
|
||||||
}
|
}
|
||||||
|
|
||||||
argsC.emplace_back(nullptr);
|
argsC.emplace_back(nullptr);
|
||||||
|
|
||||||
if (stdoutFD != -1)
|
if (m_impl->stdoutFD != -1)
|
||||||
dup2(stdoutFD, 1);
|
dup2(m_impl->stdoutFD, 1);
|
||||||
if (stderrFD != -1)
|
if (m_impl->stderrFD != -1)
|
||||||
dup2(stderrFD, 2);
|
dup2(m_impl->stderrFD, 2);
|
||||||
|
|
||||||
execvp(binary.c_str(), (char* const*)argsC.data());
|
execvp(m_impl->binary.c_str(), (char* const*)argsC.data());
|
||||||
_exit(0);
|
_exit(0);
|
||||||
}
|
}
|
||||||
close(socket[0]);
|
close(socket[0]);
|
||||||
|
|
@ -219,27 +236,31 @@ bool Hyprutils::OS::CProcess::runAsync() {
|
||||||
// clear child and leave grandchild to init
|
// clear child and leave grandchild to init
|
||||||
waitpid(child, nullptr, 0);
|
waitpid(child, nullptr, 0);
|
||||||
|
|
||||||
grandchildPid = grandchild;
|
m_impl->grandchildPid = grandchild;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::string& Hyprutils::OS::CProcess::stdOut() {
|
const std::string& Hyprutils::OS::CProcess::stdOut() {
|
||||||
return out;
|
return m_impl->out;
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::string& Hyprutils::OS::CProcess::stdErr() {
|
const std::string& Hyprutils::OS::CProcess::stdErr() {
|
||||||
return err;
|
return m_impl->err;
|
||||||
}
|
}
|
||||||
|
|
||||||
const pid_t Hyprutils::OS::CProcess::pid() {
|
pid_t Hyprutils::OS::CProcess::pid() {
|
||||||
return grandchildPid;
|
return m_impl->grandchildPid;
|
||||||
|
}
|
||||||
|
|
||||||
|
int Hyprutils::OS::CProcess::exitCode() {
|
||||||
|
return m_impl->exitCode;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Hyprutils::OS::CProcess::setStdoutFD(int fd) {
|
void Hyprutils::OS::CProcess::setStdoutFD(int fd) {
|
||||||
stdoutFD = fd;
|
m_impl->stdoutFD = fd;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Hyprutils::OS::CProcess::setStderrFD(int fd) {
|
void Hyprutils::OS::CProcess::setStderrFD(int fd) {
|
||||||
stderrFD = fd;
|
m_impl->stderrFD = fd;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,7 @@ int main(int argc, char** argv, char** envp) {
|
||||||
|
|
||||||
EXPECT(process.stdOut(), std::string{"Hello World!\n"});
|
EXPECT(process.stdOut(), std::string{"Hello World!\n"});
|
||||||
EXPECT(process.stdErr(), std::string{""});
|
EXPECT(process.stdErr(), std::string{""});
|
||||||
|
EXPECT(process.exitCode(), 0);
|
||||||
|
|
||||||
CProcess process2("sh", {"-c", "while true; do sleep 1; done;"});
|
CProcess process2("sh", {"-c", "while true; do sleep 1; done;"});
|
||||||
|
|
||||||
|
|
@ -26,5 +27,9 @@ int main(int argc, char** argv, char** envp) {
|
||||||
|
|
||||||
kill(process2.pid(), SIGKILL);
|
kill(process2.pid(), SIGKILL);
|
||||||
|
|
||||||
|
CProcess process3("sh", {"-c", "cat /geryueruggbuergheruger/reugiheruygyuerghuryeghyer/eruihgyuerguyerghyuerghuyergerguyer/NON_EXISTENT"});
|
||||||
|
EXPECT(process3.runSync(), true);
|
||||||
|
EXPECT(process3.exitCode(), 1);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
Loading…
Reference in New Issue