Files
finit/libsystemd/sd-daemon.c
T
Ming Liu de4be1557b sd-daemon.c: fix a compilation error
A following compilation error was observed:
| libsystemd/sd-daemon.c:64: undefined reference to `strlcpy'

fix it by include the required libite dependency.

Signed-off-by: Ming Liu <liu.ming50@gmail.com>
2025-07-08 11:19:38 +02:00

222 lines
4.0 KiB
C

/* SPDX-License-Identifier: MIT-0 */
/*
* systemd notify protocol, supporting readiness notification on startup
* and 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/
*/
#define _GNU_SOURCE 1
#include <errno.h>
#include <inttypes.h>
#include <signal.h>
#include <stdbool.h>
#include <stdarg.h>
#include <stddef.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <time.h>
#include <unistd.h>
#ifdef _LIBITE_LITE
# include <libite/lite.h>
#else
# include <lite/lite.h>
#endif
#include "sd-daemon.h"
/*
* NOTE: As per spec., this function does not return POSIX OK(0) but
* rather "a positive value", i.e., 1.
*/
int sd_notify(int unset_environment, const char *state)
{
struct sockaddr_un sun = {
.sun_family = AF_UNIX,
};
size_t len, sun_len;
const char *path;
ssize_t written;
int sd;
if (!state)
return -EINVAL;
len = strlen(state);
if (len == 0)
return -EINVAL;
/* If the variable is not set, the protocol is a noop */
path = getenv("NOTIFY_SOCKET");
if (!path)
return 0; /* Not set? Nothing to do */
/* Only AF_UNIX is supported, with path or abstract sockets */
if (path[0] != '/' && path[0] != '@')
return -EAFNOSUPPORT;
/* Ensure there is room for NUL byte */
sun_len = strlen(path);
if (sun_len >= sizeof(sun.sun_path))
return -E2BIG;
strlcpy(sun.sun_path, path, sizeof(sun.sun_path));
if (sun.sun_path[0] == '@')
sun.sun_path[0] = 0;
sd = socket(AF_UNIX, SOCK_DGRAM | SOCK_CLOEXEC, 0);
if (sd == -1)
return -errno;
if (connect(sd, (struct sockaddr *)&sun, offsetof(struct sockaddr_un, sun_path) + sun_len) == -1) {
close(sd);
return -errno;
}
if (unset_environment)
unsetenv("NOTIFY_SOCKET");
written = write(sd, state, len);
close(sd);
if (written != (ssize_t) len)
return written < 0 ? -errno : -EPROTO;
return 1;
}
/*
* Printf-style notification function
*/
int sd_notifyf(int unset_environment, const char *format, ...)
{
va_list ap;
char *state;
int ret;
if (!format)
return -EINVAL;
va_start(ap, format);
ret = vasprintf(&state, format, ap);
va_end(ap);
if (ret < 0)
return -ENOMEM;
ret = sd_notify(unset_environment, state);
free(state);
return ret;
}
/*
* PID-specific notification function
*/
int sd_pid_notify(pid_t pid, int unset_environment, const char *state)
{
char path[256], *env;
size_t len;
int ret;
if (!state)
return -EINVAL;
len = strlen(state);
if (len == 0)
return -EINVAL;
if (pid == 0)
pid = getpid();
env = getenv("NOTIFY_SOCKET");
if (env) {
env = strdup(env);
if (!env)
return -errno;
}
snprintf(path, sizeof(path), "@run/finit/notify/%d", pid);
setenv("NOTIFY_SOCKET", path, 1);
ret = sd_notify(unset_environment, state);
if (env) {
setenv("NOTIFY_SOCKET", env, 1);
free(env);
}
return ret;
}
/*
* PID-specific printf-style notification function
*/
int sd_pid_notifyf(pid_t pid, int unset_environment, const char *format, ...)
{
va_list ap;
char *state;
int ret;
if (!format)
return -EINVAL;
va_start(ap, format);
ret = vasprintf(&state, format, ap);
va_end(ap);
if (ret < 0)
return -ENOMEM;
ret = sd_pid_notify(pid, unset_environment, state);
free(state);
return ret;
}
/*
* Socket activation stub - Finit doesn't support socket activation yet
* Returns 0 (no file descriptors passed)
*/
int sd_listen_fds(int unset_environment)
{
if (unset_environment) {
unsetenv("LISTEN_PID");
unsetenv("LISTEN_FDS");
unsetenv("LISTEN_FDNAMES");
}
return 0;
}
/*
* Watchdog stub - Finit doesn't support watchdog yet
* Returns 0 (no watchdog enabled)
*/
int sd_watchdog_enabled(int unset_environment, uint64_t *usec)
{
if (unset_environment) {
unsetenv("WATCHDOG_PID");
unsetenv("WATCHDOG_USEC");
}
if (usec)
*usec = 0;
return 0;
}
/*
* System detection function
* Returns 1 to indicate systemd compatibility (trick applications)
*/
int sd_booted(void)
{
return 1;
}