21#include <sys/socket.h>
31class ProcessImpl :
public Process
34 int spawn(
const std::string& new_exe_name,
const fs::path& argv0_path,
int& pid)
override
36 return mp::SpawnProcess(pid, [&](
int fd) {
38 path.remove_filename();
43 int waitSpawned(
int pid)
override {
return mp::WaitProcess(pid); }
44 bool checkSpawned(
int argc,
char* argv[],
int& fd)
override
49 if (argc != 3 || strcmp(argv[1],
"-ipcfd") != 0) {
59 throw std::runtime_error(
strprintf(
"Invalid -ipcfd number '%s'", argv[2]));
63 int connect(
const fs::path& data_dir,
64 const std::string& dest_exe_name,
65 std::string& address)
override;
66 int bind(
const fs::path& data_dir,
const std::string& exe_name, std::string& address)
override;
69static bool ParseAddress(std::string& address,
71 const std::string& dest_exe_name,
72 struct sockaddr_un& addr,
75 if (address ==
"unix" || address.starts_with(
"unix:")) {
77 if (address.size() <= 5) {
84 if (path_str.size() >=
sizeof(addr.sun_path)) {
88 memset(&addr, 0,
sizeof(addr));
89 addr.sun_family = AF_UNIX;
90 strncpy(addr.sun_path, path_str.c_str(),
sizeof(addr.sun_path)-1);
94 error =
strprintf(
"Unrecognized address '%s'", address);
98int ProcessImpl::connect(
const fs::path& data_dir,
99 const std::string& dest_exe_name,
100 std::string& address)
102 struct sockaddr_un addr;
104 if (!ParseAddress(address, data_dir, dest_exe_name, addr, error)) {
105 throw std::invalid_argument(error);
109 if ((fd = ::socket(addr.sun_family, SOCK_STREAM, 0)) == -1) {
110 throw std::system_error(errno, std::system_category());
112 if (::connect(fd, (
struct sockaddr*)&addr,
sizeof(addr)) == 0) {
115 int connect_error = errno;
116 if (::close(fd) != 0) {
119 throw std::system_error(connect_error, std::system_category());
122int ProcessImpl::bind(
const fs::path& data_dir,
const std::string& exe_name, std::string& address)
124 struct sockaddr_un addr;
126 if (!ParseAddress(address, data_dir, exe_name, addr, error)) {
127 throw std::invalid_argument(error);
130 if (addr.sun_family == AF_UNIX) {
133 if (fs::symlink_status(path).type() == fs::file_type::socket) {
139 if ((fd = ::socket(addr.sun_family, SOCK_STREAM, 0)) == -1) {
140 throw std::system_error(errno, std::system_category());
143 if (::bind(fd, (
struct sockaddr*)&addr,
sizeof(addr)) == 0) {
146 int bind_error = errno;
147 if (::close(fd) != 0) {
150 throw std::system_error(bind_error, std::system_category());
154std::unique_ptr<Process>
MakeProcess() {
return std::make_unique<ProcessImpl>(); }
Path class wrapper to block calls to the fs::path(std::string) implicit constructor and the fs::path:...
static bool create_directories(const std::filesystem::path &p)
Create directory (and if necessary its parents), unless the leaf directory already exists or is a sym...
static auto quoted(const std::string &s)
static std::string PathToString(const path &path)
Convert path object to a byte string.
static path PathFromString(const std::string &string)
Convert byte string to path object.
std::unique_ptr< Process > MakeProcess()
Constructor for Process interface.
std::string_view RemovePrefixView(std::string_view str, std::string_view prefix)
std::string SysErrorString(int err)
Return system error string from errno value.
bool ParseInt32(std::string_view str, int32_t *out)
Convert string to signed 32-bit integer with strict parse error feedback.