1 /* $NetBSD: sd-notify.h,v 1.2 2025/09/05 21:16:19 christos Exp $ */ 2 3 /* SPDX-License-Identifier: MIT-0 */ 4 /* Implement the systemd notify protocol without external dependencies. 5 * Supports both readiness notification on startup and on reloading, 6 * according to the protocol defined at: 7 * https://www.freedesktop.org/software/systemd/man/latest/sd_notify.html 8 * This protocol is guaranteed to be stable as per: 9 * https://systemd.io/PORTABILITY_AND_STABILITY/ */ 10 #include <errno.h> 11 #include <stdlib.h> 12 #include <stdio.h> 13 #include <sys/socket.h> 14 #include <sys/un.h> 15 #include <unistd.h> 16 17 static int sd_notify(int ignore, const char *message) { 18 union sockaddr_union { 19 struct sockaddr sa; 20 struct sockaddr_un sun; 21 } socket_addr = { 22 .sun.sun_family = AF_UNIX, 23 }; 24 size_t path_length, message_length; 25 const char *socket_path; 26 int fd = -1; 27 int rc = 1; 28 29 socket_path = getenv("NOTIFY_SOCKET"); 30 if (!socket_path) 31 return 0; /* Not running under systemd? Nothing to do */ 32 33 if (!message) 34 return -EINVAL; 35 36 message_length = strlen(message); 37 if (message_length == 0) 38 return -EINVAL; 39 40 /* Only AF_UNIX is supported, with path or abstract sockets */ 41 if (socket_path[0] != '/' && socket_path[0] != '@') 42 return -EAFNOSUPPORT; 43 44 path_length = strlen(socket_path); 45 /* Ensure there is room for NUL byte */ 46 if (path_length >= sizeof(socket_addr.sun.sun_path)) 47 return -E2BIG; 48 49 memcpy(socket_addr.sun.sun_path, socket_path, path_length); 50 51 /* Support for abstract socket */ 52 if (socket_addr.sun.sun_path[0] == '@') 53 socket_addr.sun.sun_path[0] = 0; 54 55 fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0); 56 if (fd < 0) 57 return -errno; 58 59 ssize_t written = sendto(fd, message, message_length, 0, 60 &socket_addr.sa, offsetof(struct sockaddr_un, sun_path) + path_length); 61 if (written != (ssize_t) message_length) 62 rc = written < 0 ? -errno : -EPROTO; 63 64 close(fd); 65 return rc; 66 } 67