2020-12-26 14:12:05 -08:00
|
|
|
// Copyright (c) FIRST and other WPILib contributors.
|
|
|
|
|
// Open Source Software; you can modify and/or share it under the terms of
|
|
|
|
|
// the WPILib BSD license file in the root directory of this project.
|
2018-07-17 01:06:24 -07:00
|
|
|
|
|
|
|
|
#include "wpi/uv/Process.h"
|
|
|
|
|
|
|
|
|
|
#include "wpi/SmallString.h"
|
|
|
|
|
#include "wpi/uv/Loop.h"
|
|
|
|
|
#include "wpi/uv/Pipe.h"
|
|
|
|
|
|
2020-12-28 01:19:59 -08:00
|
|
|
namespace wpi::uv {
|
2018-07-17 01:06:24 -07:00
|
|
|
|
2021-06-06 16:13:58 -07:00
|
|
|
std::shared_ptr<Process> Process::SpawnArray(Loop& loop, std::string_view file,
|
2018-11-19 19:54:54 -08:00
|
|
|
ArrayRef<Option> options) {
|
|
|
|
|
// convert Option array to libuv structure
|
2018-07-17 01:06:24 -07:00
|
|
|
uv_process_options_t coptions;
|
2018-11-19 19:54:54 -08:00
|
|
|
|
2018-07-17 01:06:24 -07:00
|
|
|
coptions.exit_cb = [](uv_process_t* handle, int64_t status, int signal) {
|
|
|
|
|
auto& h = *static_cast<Process*>(handle->data);
|
|
|
|
|
h.exited(status, signal);
|
|
|
|
|
};
|
2018-11-19 19:54:54 -08:00
|
|
|
|
2021-06-06 16:13:58 -07:00
|
|
|
SmallString<128> fileBuf{file};
|
|
|
|
|
coptions.file = fileBuf.c_str();
|
2018-11-19 19:54:54 -08:00
|
|
|
coptions.cwd = nullptr;
|
|
|
|
|
coptions.flags = 0;
|
|
|
|
|
coptions.uid = 0;
|
|
|
|
|
coptions.gid = 0;
|
|
|
|
|
|
|
|
|
|
SmallVector<char*, 4> argsBuf;
|
|
|
|
|
SmallVector<char*, 4> envBuf;
|
|
|
|
|
struct StdioContainer : public uv_stdio_container_t {
|
|
|
|
|
StdioContainer() {
|
|
|
|
|
flags = UV_IGNORE;
|
|
|
|
|
data.fd = 0;
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
SmallVector<StdioContainer, 4> stdioBuf;
|
|
|
|
|
|
|
|
|
|
for (auto&& o : options) {
|
|
|
|
|
switch (o.m_type) {
|
|
|
|
|
case Option::kArg:
|
|
|
|
|
argsBuf.push_back(const_cast<char*>(o.m_data.str));
|
|
|
|
|
break;
|
|
|
|
|
case Option::kEnv:
|
|
|
|
|
envBuf.push_back(const_cast<char*>(o.m_data.str));
|
|
|
|
|
break;
|
|
|
|
|
case Option::kCwd:
|
|
|
|
|
coptions.cwd = o.m_data.str[0] == '\0' ? nullptr : o.m_data.str;
|
|
|
|
|
break;
|
|
|
|
|
case Option::kUid:
|
|
|
|
|
coptions.uid = o.m_data.uid;
|
|
|
|
|
coptions.flags |= UV_PROCESS_SETUID;
|
|
|
|
|
break;
|
|
|
|
|
case Option::kGid:
|
|
|
|
|
coptions.gid = o.m_data.gid;
|
|
|
|
|
coptions.flags |= UV_PROCESS_SETGID;
|
|
|
|
|
break;
|
|
|
|
|
case Option::kSetFlags:
|
|
|
|
|
coptions.flags |= o.m_data.flags;
|
|
|
|
|
break;
|
|
|
|
|
case Option::kClearFlags:
|
|
|
|
|
coptions.flags &= ~o.m_data.flags;
|
|
|
|
|
break;
|
|
|
|
|
case Option::kStdioIgnore: {
|
|
|
|
|
size_t index = o.m_data.stdio.index;
|
2020-12-28 12:58:06 -08:00
|
|
|
if (index >= stdioBuf.size()) {
|
|
|
|
|
stdioBuf.resize(index + 1);
|
|
|
|
|
}
|
2018-11-19 19:54:54 -08:00
|
|
|
stdioBuf[index].flags = UV_IGNORE;
|
|
|
|
|
stdioBuf[index].data.fd = 0;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case Option::kStdioInheritFd: {
|
|
|
|
|
size_t index = o.m_data.stdio.index;
|
2020-12-28 12:58:06 -08:00
|
|
|
if (index >= stdioBuf.size()) {
|
|
|
|
|
stdioBuf.resize(index + 1);
|
|
|
|
|
}
|
2018-11-19 19:54:54 -08:00
|
|
|
stdioBuf[index].flags = UV_INHERIT_FD;
|
|
|
|
|
stdioBuf[index].data.fd = o.m_data.stdio.fd;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case Option::kStdioInheritPipe: {
|
|
|
|
|
size_t index = o.m_data.stdio.index;
|
2020-12-28 12:58:06 -08:00
|
|
|
if (index >= stdioBuf.size()) {
|
|
|
|
|
stdioBuf.resize(index + 1);
|
|
|
|
|
}
|
2018-11-19 19:54:54 -08:00
|
|
|
stdioBuf[index].flags = UV_INHERIT_STREAM;
|
|
|
|
|
stdioBuf[index].data.stream = o.m_data.stdio.pipe->GetRawStream();
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case Option::kStdioCreatePipe: {
|
|
|
|
|
size_t index = o.m_data.stdio.index;
|
2020-12-28 12:58:06 -08:00
|
|
|
if (index >= stdioBuf.size()) {
|
|
|
|
|
stdioBuf.resize(index + 1);
|
|
|
|
|
}
|
2018-11-19 19:54:54 -08:00
|
|
|
stdioBuf[index].flags =
|
|
|
|
|
static_cast<uv_stdio_flags>(UV_CREATE_PIPE | o.m_data.stdio.flags);
|
|
|
|
|
stdioBuf[index].data.stream = o.m_data.stdio.pipe->GetRawStream();
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
default:
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-12-28 12:58:06 -08:00
|
|
|
if (argsBuf.empty()) {
|
|
|
|
|
argsBuf.push_back(const_cast<char*>(coptions.file));
|
|
|
|
|
}
|
2018-11-19 19:54:54 -08:00
|
|
|
argsBuf.push_back(nullptr);
|
|
|
|
|
coptions.args = argsBuf.data();
|
|
|
|
|
|
|
|
|
|
if (envBuf.empty()) {
|
|
|
|
|
coptions.env = nullptr;
|
|
|
|
|
} else {
|
|
|
|
|
envBuf.push_back(nullptr);
|
|
|
|
|
coptions.env = envBuf.data();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
coptions.stdio_count = stdioBuf.size();
|
|
|
|
|
coptions.stdio = static_cast<uv_stdio_container_t*>(stdioBuf.data());
|
2018-07-17 01:06:24 -07:00
|
|
|
|
|
|
|
|
auto h = std::make_shared<Process>(private_init{});
|
|
|
|
|
int err = uv_spawn(loop.GetRaw(), h->GetRaw(), &coptions);
|
|
|
|
|
if (err < 0) {
|
|
|
|
|
loop.ReportError(err);
|
|
|
|
|
return nullptr;
|
|
|
|
|
}
|
|
|
|
|
h->Keep();
|
|
|
|
|
return h;
|
|
|
|
|
}
|
|
|
|
|
|
2020-12-28 01:19:59 -08:00
|
|
|
} // namespace wpi::uv
|