Add systemd::notify helper (zero-dep sd_notify protocol)

Lifted from fewo-webapp (src/App.cpp). 15-line helper that speaks the
systemd notification protocol directly — no libsystemd link — for
Type=notify services.

Silent no-op when NOTIFY_SOCKET is unset so the same binary runs
unchanged under systemd or as a plain background process.

Supports Linux abstract-namespace sockets.

Unblocks fewo-webapp #451 and its twin extractions for derived projects.
This commit is contained in:
Uwe Schuster 2026-04-22 23:01:40 +02:00
parent 081e0b36dc
commit f9a244bf2b

View file

@ -0,0 +1,54 @@
#ifndef OATPP_AUTHKIT_SYSTEMD_NOTIFY_HPP
#define OATPP_AUTHKIT_SYSTEMD_NOTIFY_HPP
#include <cstdlib>
#include <cstring>
#include <sys/socket.h>
#include <sys/un.h>
#include <unistd.h>
namespace oatpp_authkit::systemd {
/**
* @brief Protocol-level sd_notify(3) implementation.
*
* Speaks the systemd notification protocol by writing a datagram to
* $NOTIFY_SOCKET no libsystemd dependency. Used to signal
* `Type=notify` services with `READY=1`, `STATUS=...`, `WATCHDOG=1`.
*
* No-op (silent return) when NOTIFY_SOCKET is unset the same binary
* can run under systemd or as a plain background process without
* conditional logic at the call site.
*
* Supports Linux abstract-namespace sockets (leading '@' in the env
* var, mapped to a leading NUL byte in the sockaddr path).
*
* Example:
* @code
* oatpp_authkit::systemd::notify("READY=1\nSTATUS=Accepting connections");
* // … later, from a watchdog thread:
* oatpp_authkit::systemd::notify("WATCHDOG=1");
* @endcode
*/
inline void notify(const char* state) {
const char* sock = std::getenv("NOTIFY_SOCKET");
if (!sock || !*sock) return;
int fd = ::socket(AF_UNIX, SOCK_DGRAM | SOCK_CLOEXEC, 0);
if (fd < 0) return;
struct sockaddr_un addr{};
addr.sun_family = AF_UNIX;
if (sock[0] == '@') {
// Linux abstract namespace: leading '@' maps to a NUL byte.
addr.sun_path[0] = '\0';
std::strncpy(addr.sun_path + 1, sock + 1, sizeof(addr.sun_path) - 2);
} else {
std::strncpy(addr.sun_path, sock, sizeof(addr.sun_path) - 1);
}
::sendto(fd, state, std::strlen(state), MSG_NOSIGNAL,
(struct sockaddr*)&addr, sizeof(addr));
::close(fd);
}
} // namespace oatpp_authkit::systemd
#endif