diff options
Diffstat (limited to 'include/sd-notify.h')
-rw-r--r-- | include/sd-notify.h | 64 |
1 files changed, 64 insertions, 0 deletions
diff --git a/include/sd-notify.h b/include/sd-notify.h new file mode 100644 index 0000000..be284f6 --- /dev/null +++ b/include/sd-notify.h @@ -0,0 +1,64 @@ +/* SPDX-License-Identifier: MIT-0 */ +/* Implement the systemd notify protocol without external dependencies. + * Supports both readiness notification on startup and on reloading, + * according to the protocol defined at: + * https://www.freedesktop.org/software/systemd/man/latest/sd_notify.html + * This protocol is guaranteed to be stable as per: + * https://systemd.io/PORTABILITY_AND_STABILITY/ */ +#include <errno.h> +#include <stdlib.h> +#include <stdio.h> +#include <sys/socket.h> +#include <sys/un.h> +#include <unistd.h> + +static int sd_notify(int ignore, const char *message) { + union sockaddr_union { + struct sockaddr sa; + struct sockaddr_un sun; + } socket_addr = { + .sun.sun_family = AF_UNIX, + }; + size_t path_length, message_length; + const char *socket_path; + int fd = -1; + int rc = 1; + + socket_path = getenv("NOTIFY_SOCKET"); + if (!socket_path) + return 0; /* Not running under systemd? Nothing to do */ + + if (!message) + return -EINVAL; + + message_length = strlen(message); + if (message_length == 0) + return -EINVAL; + + /* Only AF_UNIX is supported, with path or abstract sockets */ + if (socket_path[0] != '/' && socket_path[0] != '@') + return -EAFNOSUPPORT; + + path_length = strlen(socket_path); + /* Ensure there is room for NUL byte */ + if (path_length >= sizeof(socket_addr.sun.sun_path)) + return -E2BIG; + + memcpy(socket_addr.sun.sun_path, socket_path, path_length); + + /* Support for abstract socket */ + if (socket_addr.sun.sun_path[0] == '@') + socket_addr.sun.sun_path[0] = 0; + + fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0); + if (fd < 0) + return -errno; + + ssize_t written = sendto(fd, message, message_length, 0, + &socket_addr.sa, offsetof(struct sockaddr_un, sun_path) + path_length); + if (written != (ssize_t) message_length) + rc = written < 0 ? -errno : -EPROTO; + + close(fd); + return rc; +} |