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
|
#include "SdDaemon.hpp"
#include <memory>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <string.h>
#include <stdlib.h>
#include <cstring>
namespace Systemd {
int SdBooted(void) {
if (!faccessat(AT_FDCWD, "/run/systemd/system/", F_OK, AT_SYMLINK_NOFOLLOW))
return true;
if (errno == ENOENT)
return false;
return -errno;
}
int SdNotify(int unsetEnvironment, const char* state) {
int fd = socket(AF_UNIX, SOCK_DGRAM | SOCK_CLOEXEC, 0);
if (fd < 0)
return -errno;
constexpr char envVar[] = "NOTIFY_SOCKET";
auto cleanup = [unsetEnvironment, envVar](int* fd) {
if (unsetEnvironment)
unsetenv(envVar);
close(*fd);
};
std::unique_ptr<int, decltype(cleanup)> fdCleaup(&fd, cleanup);
const char* addr = getenv(envVar);
if (!addr)
return 0;
// address length must be at most this; see man 7 unix
size_t addrLen = strnlen(addr, 107);
struct sockaddr_un unixAddr;
unixAddr.sun_family = AF_UNIX;
strncpy(unixAddr.sun_path, addr, addrLen);
if (unixAddr.sun_path[0] == '@')
unixAddr.sun_path[0] = '\0';
if (connect(fd, (const sockaddr*)&unixAddr, sizeof(struct sockaddr_un)) < 0)
return -errno;
// arbitrary value which seems to be enough for s-d messages
ssize_t stateLen = strnlen(state, 128);
if (write(fd, state, stateLen) == stateLen)
return 1;
return -errno;
}
}
|