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
|
#include "common.hh"
#include <sys/socket.h>
#include <sys/un.h>
LIBEXEC_HELPER(5)
static int resultFd = -1;
static void sendResult(int result)
{
// NOTE posix says pipe writes smaller than PIPE_BUF must be atomic, so this either
// succeeds or fails (pipe bufs of four bytes make no sense at all for our systems)
int error = result;
DIE_UNLESS_SYS("writing result", ::write(resultFd, &error, sizeof(error)));
}
int helperMain(const char *, std::span<char *> args) noexcept
{
int socket = argToInt<int>("socket", args[0]);
std::string_view method = args[1];
const auto dir = args[2];
const auto name = args[3];
resultFd = argToInt<int>("result-fd", args[4]);
if (chdir(dir)) {
sendResult(errno);
return 0;
}
struct sockaddr_un addr;
addr.sun_family = AF_UNIX;
if (auto nameLen = strlen(name); nameLen + 1 >= sizeof(addr.sun_path)) {
die(std::format("socket path {}/{} is too long", dir, name));
} else {
memcpy(addr.sun_path, name, nameLen + 1);
}
if (method == "bind") {
auto result = bind(socket, reinterpret_cast<struct sockaddr *>(&addr), sizeof(addr)) ? errno : 0;
sendResult(result);
} else if (method == "connect") {
auto result = connect(socket, reinterpret_cast<struct sockaddr *>(&addr), sizeof(addr)) ? errno : 0;
sendResult(result);
} else {
die(std::format("invalid method %s", method));
}
return 0;
}
|