From 1c69a91c25654339a0e670ed5a1495d52b37eb8e Mon Sep 17 00:00:00 2001 From: Nicholas Marriott Date: Mon, 28 Mar 2022 08:42:13 +0100 Subject: [PATCH] Add support for systemd socket activation (where systemd creates the Unix domain socket for tmux rather than tmux creating it). Build with --enable-systemd. From Julien Moutinho in GitHub issue 3119. --- Makefile.am | 5 +++++ compat.h | 5 +++++ compat/systemd.c | 58 ++++++++++++++++++++++++++++++++++++++++++++++++ configure.ac | 25 +++++++++++++++++++++ server.c | 6 ++++- tmux.h | 1 + 6 files changed, 99 insertions(+), 1 deletion(-) create mode 100644 compat/systemd.c diff --git a/Makefile.am b/Makefile.am index 68494932..5bdd9d5f 100644 --- a/Makefile.am +++ b/Makefile.am @@ -204,6 +204,11 @@ if NEED_FORKPTY nodist_tmux_SOURCES += compat/forkpty-@PLATFORM@.c endif +# Add compat file for systemd. +if HAVE_SYSTEMD +nodist_tmux_SOURCES += compat/systemd.c +endif + # Add compat file for utf8proc. if HAVE_UTF8PROC nodist_tmux_SOURCES += compat/utf8proc.c diff --git a/compat.h b/compat.h index be726831..6eb97619 100644 --- a/compat.h +++ b/compat.h @@ -421,6 +421,11 @@ void *reallocarray(void *, size_t, size_t); void *recallocarray(void *, size_t, size_t, size_t); #endif +#ifdef HAVE_SYSTEMD +/* systemd.c */ +int systemd_create_socket(int, char **); +#endif + #ifdef HAVE_UTF8PROC /* utf8proc.c */ int utf8proc_wcwidth(wchar_t); diff --git a/compat/systemd.c b/compat/systemd.c new file mode 100644 index 00000000..7317e43a --- /dev/null +++ b/compat/systemd.c @@ -0,0 +1,58 @@ +/* $OpenBSD$ */ + +/* + * Copyright (c) 2022 Nicholas Marriott + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER + * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include + +#include + +#include "tmux.h" + +int +systemd_create_socket(int flags, char **cause) +{ + int fds; + int fd; + struct sockaddr_un sa; + int addrlen = sizeof sa; + + fds = sd_listen_fds(0); + if (fds > 1) { /* too many file descriptors */ + errno = E2BIG; + goto fail; + } + + if (fds == 1) { /* socket-activated */ + fd = SD_LISTEN_FDS_START; + if (!sd_is_socket_unix(fd, SOCK_STREAM, 1, NULL, 0)) { + errno = EPFNOSUPPORT; + goto fail; + } + if (getsockname(fd, (struct sockaddr *)&sa, &addrlen) == -1) + goto fail; + socket_path = xstrdup(sa.sun_path); + return (fd); + } + + return (server_create_socket(flags, cause)); + +fail: + if (cause != NULL) + xasprintf(cause, "systemd socket error (%s)", strerror(errno)); + return (-1); +} diff --git a/configure.ac b/configure.ac index a9c035d7..20199515 100644 --- a/configure.ac +++ b/configure.ac @@ -390,6 +390,31 @@ if test "x$enable_utf8proc" = xyes; then fi AM_CONDITIONAL(HAVE_UTF8PROC, [test "x$enable_utf8proc" = xyes]) +# Check for systemd support. +AC_ARG_ENABLE( + systemd, + AS_HELP_STRING(--enable-systemd, enable systemd integration) +) +if test x"$enable_systemd" = xyes; then + PKG_CHECK_MODULES( + SYSTEMD, + libsystemd, + [ + AM_CPPFLAGS="$SYSTEMD_CFLAGS $AM_CPPFLAGS" + CPPFLAGS="$AM_CPPFLAGS $SAVED_CPPFLAGS" + LIBS="$SYSTEMD_LIBS $LIBS" + found_systemd=yes + ], + found_systemd=no + ) + if test "x$found_systemd" = xyes; then + AC_DEFINE(HAVE_SYSTEMD) + else + AC_MSG_ERROR("systemd not found") + fi +fi +AM_CONDITIONAL(HAVE_SYSTEMD, [test "x$found_systemd" = xyes]) + # Check for b64_ntop. If we have b64_ntop, we assume b64_pton as well. AC_MSG_CHECKING(for b64_ntop) AC_LINK_IFELSE([AC_LANG_PROGRAM( diff --git a/server.c b/server.c index 2db5a8d8..bf3a8361 100644 --- a/server.c +++ b/server.c @@ -100,7 +100,7 @@ server_check_marked(void) } /* Create server socket. */ -static int +int server_create_socket(int flags, char **cause) { struct sockaddr_un sa; @@ -214,7 +214,11 @@ server_start(struct tmuxproc *client, int flags, struct event_base *base, gettimeofday(&start_time, NULL); +#ifdef HAVE_SYSTEMD + server_fd = systemd_create_socket(flags, &cause); +#else server_fd = server_create_socket(flags, &cause); +#endif if (server_fd != -1) server_update_socket(); if (~flags & CLIENT_NOFORK) diff --git a/tmux.h b/tmux.h index 370c7773..f16b5250 100644 --- a/tmux.h +++ b/tmux.h @@ -2583,6 +2583,7 @@ int server_start(struct tmuxproc *, int, struct event_base *, int, char *); void server_update_socket(void); void server_add_accept(int); void printflike(1, 2) server_add_message(const char *, ...); +int server_create_socket(int, char **); /* server-client.c */ RB_PROTOTYPE(client_windows, client_window, entry, server_client_window_cmp);