Hi, here's a couple of patches to improve busybox compatibility with systemd: - 0001 adds a minimal sd-daemon implementation to libbb - 0002 implements socket activation for syslogd - 0003 implements hwclock --systz - 0004 adds example systemd units for a number of busybox applets
The sd-daemon stuff is a stripped-down version of the reference implementation shipped with systemd, with only the bare minimum required to make syslogd work (i.e. AF_UNIX socket activation). hwclock --systz is based on the util-linux-ng implementation. make bloatcheck for syslogd: function old new delta sd_listen_fds - 287 +287 .rodata 145677 145844 +167 xsystemd_unix_socket - 88 +88 create_socket 154 175 +21 ------------------------------------------------------------------------------ (add/remove: 3/0 grow/shrink: 2/0 up/down: 563/0) Total: 563 bytes text data bss dec hex filename 921266 4114 9536 934916 e4404 busybox_old 922241 4114 9536 935891 e47d3 busybox_unstripped and for hwclock: function old new delta hwclock_main 345 461 +116 .rodata 145902 145945 +43 packed_usage 27401 27424 +23 static.hwclock_longopts 53 61 +8 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 4/0 up/down: 190/0) Total: 190 bytes text data bss dec hex filename 922188 4114 9568 935870 e47be busybox_old 922347 4114 9568 936029 e485d busybox_unstripped Please review - this is my first contribution to busybox, so let me know if I've done something stupid :) Regards, Davide
>From 04a91949e46db799e67ec775d8349414abde1a34 Mon Sep 17 00:00:00 2001 From: Davide Cavalca <[email protected]> Date: Sun, 16 Jan 2011 10:39:08 +0100 Subject: [PATCH 1/4] libbb: add minimal sd-daemon implementation Signed-off-by: Davide Cavalca <[email protected]> --- include/sd-daemon.h | 36 +++++++++++ libbb/sd-daemon.c | 164 +++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 200 insertions(+), 0 deletions(-) create mode 100644 include/sd-daemon.h create mode 100644 libbb/sd-daemon.c diff --git a/include/sd-daemon.h b/include/sd-daemon.h new file mode 100644 index 0000000..f605c52 --- /dev/null +++ b/include/sd-daemon.h @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2011 Davide Cavalca <[email protected]> + * + * Based on http://cgit.freedesktop.org/systemd/tree/src/sd-daemon.h + * Copyright 2010 Lennart Poettering + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation files + * (the "Software"), to deal in the Software without restriction, + * including without limitation the rights to use, copy, modify, merge, + * publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef BB_SD_DAEMON_H +#define BB_SD_DAEMON_H + +#define SD_LISTEN_FDS_START 3 + +int sd_listen_fds(void); +int xsystemd_unix_socket(const char *path); + +#endif diff --git a/libbb/sd-daemon.c b/libbb/sd-daemon.c new file mode 100644 index 0000000..2237e19 --- /dev/null +++ b/libbb/sd-daemon.c @@ -0,0 +1,164 @@ +/* + * Copyright (C) 2011 Davide Cavalca <[email protected]> + * + * Based on http://cgit.freedesktop.org/systemd/tree/src/sd-daemon.c + * Copyright 2010 Lennart Poettering + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation files + * (the "Software"), to deal in the Software without restriction, + * including without limitation the rights to use, copy, modify, merge, + * publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include <sys/un.h> + +#include "libbb.h" +#include "sd-daemon.h" + +int sd_listen_fds(void) { + int fd; + const char *e; + char *p = NULL; + unsigned long l; + + if (!(e = getenv("LISTEN_PID"))) + return 0; + + errno = 0; + l = strtoul(e, &p, 10); + + if (errno != 0) + return -errno; + + if (!p || *p || l <= 0) + return -EINVAL; + + /* Is this for us? */ + if (getpid() != (pid_t) l) + return 0; + + if (!(e = getenv("LISTEN_FDS"))) + return 0; + + errno = 0; + l = strtoul(e, &p, 10); + + if (errno != 0) + return -errno; + + if (!p || *p) + return -EINVAL; + + for (fd = SD_LISTEN_FDS_START; fd < SD_LISTEN_FDS_START + (int) l; fd ++) { + int flags; + + if ((flags = fcntl(fd, F_GETFD)) < 0) + return -errno; + + if (flags & FD_CLOEXEC) + continue; + + if (fcntl(fd, F_SETFD, flags | FD_CLOEXEC) < 0) + return -errno; + } + + return (int) l; +} + +static int sd_is_socket_internal(int fd, int type) { + struct stat st_fd; + + if (fd < 0 || type < 0) + return -EINVAL; + + if (fstat(fd, &st_fd) < 0) + return -errno; + + if (!S_ISSOCK(st_fd.st_mode)) + return 0; + + if (type != 0) { + int other_type = 0; + socklen_t l = sizeof(other_type); + + if (getsockopt(fd, SOL_SOCKET, SO_TYPE, &other_type, &l) < 0) + return -errno; + + if (l != sizeof(other_type)) + return -EINVAL; + + if (other_type != type) + return 0; + } + + return 1; +} + +union sockaddr_union { + struct sockaddr sa; + struct sockaddr_in in4; + struct sockaddr_in6 in6; + struct sockaddr_un un; + struct sockaddr_storage storage; +}; + +static int sd_is_socket_unix(int fd, int type, const char *path) { + union sockaddr_union sockaddr; + socklen_t l; + int r; + + if ((r = sd_is_socket_internal(fd, type)) <= 0) + return r; + + memset(&sockaddr, 0, sizeof(sockaddr)); + l = sizeof(sockaddr); + + if (getsockname(fd, &sockaddr.sa, &l) < 0) + return -errno; + + if (l < sizeof(sa_family_t)) + return -EINVAL; + + if (sockaddr.sa.sa_family != AF_UNIX) + return 0; + + return (l >= offsetof(struct sockaddr_un, sun_path) + 1) && + memcmp(path, sockaddr.un.sun_path, 1) == 0; +} + +int xsystemd_unix_socket(const char *path) { + int r = sd_listen_fds(); + + if (r < 0) + bb_error_msg_and_die ("Failed to acquire systemd socket"); + if (r > 1) + bb_error_msg_and_die ("Wrong number of systemd sockets passed"); + if (r == 1) { + int fd = SD_LISTEN_FDS_START; + + r = sd_is_socket_unix(fd, SOCK_DGRAM, path); + if (r < 0) + bb_error_msg_and_die ("Failed to verify systemd socket type"); + if (!r) + bb_error_msg_and_die ("Passed systemd socket of wrong type"); + + return fd; + } + + return -1; +} -- 1.7.2.3
>From dabbfb2070c1223b8b439334eea4613d6328219b Mon Sep 17 00:00:00 2001 From: Davide Cavalca <[email protected]> Date: Sun, 16 Jan 2011 10:40:58 +0100 Subject: [PATCH 2/4] syslogd: conditional systemd support Signed-off-by: Davide Cavalca <[email protected]> --- libbb/Kbuild.src | 2 ++ sysklogd/Config.src | 8 ++++++++ sysklogd/syslogd.c | 8 ++++++++ 3 files changed, 18 insertions(+), 0 deletions(-) diff --git a/libbb/Kbuild.src b/libbb/Kbuild.src index 0fa1451..119e0ad 100644 --- a/libbb/Kbuild.src +++ b/libbb/Kbuild.src @@ -160,6 +160,8 @@ lib-$(CONFIG_IOSTAT) += get_cpu_count.o lib-$(CONFIG_MPSTAT) += get_cpu_count.o lib-$(CONFIG_POWERTOP) += get_cpu_count.o +lib-$(CONFIG_FEATURE_SYSLOGD_SYSTEMD) += sd-daemon.o + # We shouldn't build xregcomp.c if we don't need it - this ensures we don't # require regex.h to be in the include dir even if we don't need it thereby # allowing us to build busybox even if uclibc regex support is disabled. diff --git a/sysklogd/Config.src b/sysklogd/Config.src index 1e59872..a9af225 100644 --- a/sysklogd/Config.src +++ b/sysklogd/Config.src @@ -22,6 +22,14 @@ config SYSLOGD wrong. And something almost always will go wrong if you wait long enough.... +config FEATURE_SYSLOGD_SYSTEMD + bool "Enable systemd socket activation support" + default n + depends on SYSLOGD && PLATFORM_LINUX + help + This makes syslogd compliant to the systemd's New-Style Daemons + guidelines and implements socket-based activation. + config FEATURE_ROTATE_LOGFILE bool "Rotate message files" default y diff --git a/sysklogd/syslogd.c b/sysklogd/syslogd.c index fb73095..1837413 100644 --- a/sysklogd/syslogd.c +++ b/sysklogd/syslogd.c @@ -34,6 +34,9 @@ #include <sys/shm.h> #endif +#if ENABLE_FEATURE_SYSLOGD_SYSTEMD +#include "sd-daemon.h" +#endif #define DEBUG 0 @@ -512,6 +515,11 @@ static NOINLINE int create_socket(void) int sock_fd; char *dev_log_name; +#if ENABLE_FEATURE_SYSLOGD_SYSTEMD + if ((sock_fd = xsystemd_unix_socket("/dev/log")) != -1) + return sock_fd; +#endif + memset(&sunx, 0, sizeof(sunx)); sunx.sun_family = AF_UNIX; -- 1.7.2.3
>From fbb5187b2823fba696fb1dae73c03280d97b3ee1 Mon Sep 17 00:00:00 2001 From: Davide Cavalca <[email protected]> Date: Sun, 16 Jan 2011 15:48:15 +0100 Subject: [PATCH 3/4] hwclock: implement --systz Signed-off-by: Davide Cavalca <[email protected]> --- include/usage.src.h | 5 +++-- util-linux/hwclock.c | 29 ++++++++++++++++++++++++++--- 2 files changed, 29 insertions(+), 5 deletions(-) diff --git a/include/usage.src.h b/include/usage.src.h index a4776a2..ca47137 100644 --- a/include/usage.src.h +++ b/include/usage.src.h @@ -1597,12 +1597,12 @@ INSERT #define hwclock_trivial_usage \ IF_FEATURE_HWCLOCK_LONG_OPTIONS( \ - "[-r|--show] [-s|--hctosys] [-w|--systohc]" \ + "[-r|--show] [-s|--hctosys] [-w|--systohc] [-t|--systz]" \ " [-l|--localtime] [-u|--utc]" \ " [-f FILE]" \ ) \ IF_NOT_FEATURE_HWCLOCK_LONG_OPTIONS( \ - "[-r] [-s] [-w] [-l] [-u] [-f FILE]" \ + "[-r] [-s] [-w] [-t] [-l] [-u] [-f FILE]" \ ) #define hwclock_full_usage "\n\n" \ "Query and set hardware clock (RTC)\n" \ @@ -1610,6 +1610,7 @@ INSERT "\n -r Show hardware clock time" \ "\n -s Set system time from hardware clock" \ "\n -w Set hardware clock to system time" \ + "\n -t Set the system time based on the current timezone" \ "\n -u Hardware clock is in UTC" \ "\n -l Hardware clock is in local time" \ "\n -f FILE Use specified device (e.g. /dev/rtc2)" \ diff --git a/util-linux/hwclock.c b/util-linux/hwclock.c index 922dd05..ad022c5 100644 --- a/util-linux/hwclock.c +++ b/util-linux/hwclock.c @@ -223,12 +223,32 @@ static void from_sys_clock(const char **pp_rtcname, int utc) close(rtc); } +static void set_system_clock_timezone(int utc) +{ + struct timeval tv; + struct tm *broken; + struct timezone tz; + + gettimeofday(&tv, NULL); + broken = localtime(&tv.tv_sec); + tz.tz_minuteswest = timezone/60; + if (broken->tm_isdst) + tz.tz_minuteswest -= 60; + tz.tz_dsttime = 0; + gettimeofday(&tv, NULL); + if (!utc) + tv.tv_sec += tz.tz_minuteswest * 60; + if (settimeofday(&tv, &tz)) + bb_perror_msg_and_die("settimeofday"); +} + #define HWCLOCK_OPT_LOCALTIME 0x01 #define HWCLOCK_OPT_UTC 0x02 #define HWCLOCK_OPT_SHOW 0x04 #define HWCLOCK_OPT_HCTOSYS 0x08 #define HWCLOCK_OPT_SYSTOHC 0x10 -#define HWCLOCK_OPT_RTCFILE 0x20 +#define HWCLOCK_OPT_SYSTZ 0x20 +#define HWCLOCK_OPT_RTCFILE 0x40 int hwclock_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; int hwclock_main(int argc UNUSED_PARAM, char **argv) @@ -244,12 +264,13 @@ int hwclock_main(int argc UNUSED_PARAM, char **argv) "show\0" No_argument "r" "hctosys\0" No_argument "s" "systohc\0" No_argument "w" + "systz\0" No_argument "t" "file\0" Required_argument "f" ; applet_long_options = hwclock_longopts; #endif - opt_complementary = "r--ws:w--rs:s--wr:l--u:u--l"; - opt = getopt32(argv, "lurswf:", &rtcname); + opt_complementary = "r--wst:w--rst:s--wrt:t--rswt:l--u:u--l"; + opt = getopt32(argv, "lurswtf:", &rtcname); /* If -u or -l wasn't given check if we are using utc */ if (opt & (HWCLOCK_OPT_UTC | HWCLOCK_OPT_LOCALTIME)) @@ -261,6 +282,8 @@ int hwclock_main(int argc UNUSED_PARAM, char **argv) to_sys_clock(&rtcname, utc); else if (opt & HWCLOCK_OPT_SYSTOHC) from_sys_clock(&rtcname, utc); + else if (opt & HWCLOCK_OPT_SYSTZ) + set_system_clock_timezone(utc); else /* default HWCLOCK_OPT_SHOW */ show_clock(&rtcname, utc); -- 1.7.2.3
>From d1c569411bf0a64cad366d336d65400fa2384d13 Mon Sep 17 00:00:00 2001 From: Davide Cavalca <[email protected]> Date: Sun, 16 Jan 2011 17:05:43 +0100 Subject: [PATCH 4/4] examples: add systemd units for some applets Signed-off-by: Davide Cavalca <[email protected]> --- examples/systemd/acpid.service | 9 +++++++++ examples/systemd/crond.service | 9 +++++++++ examples/systemd/klogd.service | 9 +++++++++ examples/systemd/syslogd.service | 10 ++++++++++ examples/systemd/[email protected] | 7 +++++++ 5 files changed, 44 insertions(+), 0 deletions(-) create mode 100644 examples/systemd/acpid.service create mode 100644 examples/systemd/crond.service create mode 100644 examples/systemd/klogd.service create mode 100644 examples/systemd/syslogd.service create mode 100644 examples/systemd/[email protected] diff --git a/examples/systemd/acpid.service b/examples/systemd/acpid.service new file mode 100644 index 0000000..5397420 --- /dev/null +++ b/examples/systemd/acpid.service @@ -0,0 +1,9 @@ +[Unit] +Description=ACPI Event Daemon +After=syslog.target + +[Service] +ExecStart=/sbin/acpid -d + +[Install] +WantedBy=multi-user.target diff --git a/examples/systemd/crond.service b/examples/systemd/crond.service new file mode 100644 index 0000000..9eba329 --- /dev/null +++ b/examples/systemd/crond.service @@ -0,0 +1,9 @@ +[Unit] +Description=Command Scheduler +After=syslog.target + +[Service] +ExecStart=/usr/sbin/crond -fS + +[Install] +WantedBy=multi-user.target diff --git a/examples/systemd/klogd.service b/examples/systemd/klogd.service new file mode 100644 index 0000000..0208a0f --- /dev/null +++ b/examples/systemd/klogd.service @@ -0,0 +1,9 @@ +[Unit] +Description=Kernel Logger Daemon +After=syslog.target + +[Service] +ExecStart=/sbin/klogd -n + +[Install] +WantedBy=multi-user.target diff --git a/examples/systemd/syslogd.service b/examples/systemd/syslogd.service new file mode 100644 index 0000000..9ff7174 --- /dev/null +++ b/examples/systemd/syslogd.service @@ -0,0 +1,10 @@ +[Unit] +Description=System Logger Daemon + +[Service] +ExecStartPre=/bin/systemctl stop systemd-syslog-kmsg.service +ExecStart=/sbin/syslogd -n -C10240 +Sockets=syslog.socket + +[Install] +WantedBy=multi-user.target diff --git a/examples/systemd/[email protected] b/examples/systemd/[email protected] new file mode 100644 index 0000000..e0897eb --- /dev/null +++ b/examples/systemd/[email protected] @@ -0,0 +1,7 @@ +[Unit] +Description=Telnet Per-Connection Server +After=syslog.target + +[Service] +ExecStart=/usr/sbin/telnetd -i +StandardInput=socket -- 1.7.2.3
_______________________________________________ busybox mailing list [email protected] http://lists.busybox.net/mailman/listinfo/busybox
