1 From 1775d9857a7ac60578f3560613ead7c189d8b756 Mon Sep 17 00:00:00 2001
2 From: Julien Moutinho <julm+tmux@sourcephile.fr>
3 Date: Wed, 16 Mar 2022 02:43:18 +0100
4 Subject: [PATCH] Add support for systemd socket activation
6 See http://0pointer.de/blog/projects/socket-activation.html
7 and https://www.freedesktop.org/software/systemd/man/sd_listen_fds.html
13 compat/systemd.c | 60 ++++++++++++++++++++++++++++++++++++++++++++++++
14 configure.ac | 24 +++++++++++++++++++
15 server.c | 22 +++++++++++-------
18 7 files changed, 111 insertions(+), 8 deletions(-)
19 create mode 100644 compat/systemd.c
21 diff --git a/Makefile.am b/Makefile.am
22 index 68494932..5bdd9d5f 100644
25 @@ -204,6 +204,11 @@ if NEED_FORKPTY
26 nodist_tmux_SOURCES += compat/forkpty-@PLATFORM@.c
29 +# Add compat file for systemd.
31 +nodist_tmux_SOURCES += compat/systemd.c
34 # Add compat file for utf8proc.
36 nodist_tmux_SOURCES += compat/utf8proc.c
37 diff --git a/compat.h b/compat.h
38 index be726831..6eb97619 100644
41 @@ -421,6 +421,11 @@ void *reallocarray(void *, size_t, size_t);
42 void *recallocarray(void *, size_t, size_t, size_t);
47 +int systemd_create_socket(int, char **);
52 int utf8proc_wcwidth(wchar_t);
53 diff --git a/compat/systemd.c b/compat/systemd.c
55 index 00000000..8e34c007
57 +++ b/compat/systemd.c
62 + * Copyright (c) 2022 Nicholas Marriott <nicholas.marriott@gmail.com>
63 + * Copyright (c) 2022 Julien Moutinho <julm+tmux@sourcephile.fr>
65 + * Permission to use, copy, modify, and distribute this software for any
66 + * purpose with or without fee is hereby granted, provided that the above
67 + * copyright notice and this permission notice appear in all copies.
69 + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
70 + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
71 + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
72 + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
73 + * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
74 + * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
75 + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
78 +#include <sys/types.h>
81 +#include <systemd/sd-daemon.h>
86 +systemd_create_socket(int flags, char **cause)
90 + struct sockaddr_un sa;
91 + int addrlen = sizeof sa;
93 + fds = sd_listen_fds(0);
94 + if (fds > 1) { /* too many file descriptors */
99 + if (fds == 1) { /* socket-activated */
100 + fd = SD_LISTEN_FDS_START;
101 + if (!sd_is_socket_unix(fd, SOCK_STREAM, 1, NULL, 0)) {
102 + errno = EPFNOSUPPORT;
105 + if (getsockname(fd, (struct sockaddr *)&sa, &addrlen) == -1)
107 + socket_path = xstrdup(sa.sun_path);
108 + socket_can_be_created_again = 0;
112 + return (server_create_socket(flags, cause));
116 + xasprintf(cause, "systemd socket error (%s)", strerror(errno));
119 diff --git a/configure.ac b/configure.ac
120 index e473f141..f90d9f05 100644
123 @@ -390,6 +390,30 @@ if test "x$enable_utf8proc" = xyes; then
125 AM_CONDITIONAL(HAVE_UTF8PROC, [test "x$enable_utf8proc" = xyes])
127 +# Check for systemd support.
130 + AS_HELP_STRING(--enable-systemd, enable systemd integration)
132 +if test x"$enable_systemd" = xyes; then
137 + AM_CPPFLAGS="$SYSTEMD_CFLAGS $AM_CPPFLAGS"
138 + CPPFLAGS="$AM_CPPFLAGS $SAVED_CPPFLAGS"
139 + LIBS="$SYSTEMD_LIBS $LIBS"
140 + AC_DEFINE(HAVE_SYSTEMD)
145 + if test "x$found_systemd" = xno; then
146 + AC_MSG_ERROR("systemd not found")
149 +AM_CONDITIONAL(HAVE_SYSTEMD, [test "x$found_systemd" = xyes])
151 # Check for b64_ntop. If we have b64_ntop, we assume b64_pton as well.
152 AC_MSG_CHECKING(for b64_ntop)
153 AC_LINK_IFELSE([AC_LANG_PROGRAM(
154 diff --git a/server.c b/server.c
155 index 2db5a8d8..5acddb10 100644
158 @@ -100,7 +100,7 @@ server_check_marked(void)
161 /* Create server socket. */
164 server_create_socket(int flags, char **cause)
166 struct sockaddr_un sa;
167 @@ -214,7 +214,11 @@ server_start(struct tmuxproc *client, int flags, struct event_base *base,
169 gettimeofday(&start_time, NULL);
172 + server_fd = systemd_create_socket(flags, &cause);
174 server_fd = server_create_socket(flags, &cause);
177 server_update_socket();
178 if (~flags & CLIENT_NOFORK)
179 @@ -424,14 +428,16 @@ server_signal(int sig)
180 server_child_signal();
183 - event_del(&server_ev_accept);
184 - fd = server_create_socket(server_client_flags, NULL);
188 - server_update_socket();
189 + if (socket_can_be_created_again) {
190 + event_del(&server_ev_accept);
191 + fd = server_create_socket(server_client_flags, NULL);
195 + server_update_socket();
197 + server_add_accept(0);
199 - server_add_accept(0);
202 proc_toggle_log(server_proc);
203 diff --git a/tmux.c b/tmux.c
204 index 11c368ff..187a7429 100644
207 @@ -40,6 +40,7 @@ struct environ *global_environ;
209 struct timeval start_time;
210 const char *socket_path;
211 +int socket_can_be_created_again = 1;
213 const char *shell_command;
215 diff --git a/tmux.h b/tmux.h
216 index 370c7773..d5c63390 100644
219 @@ -2001,6 +2001,7 @@ extern struct options *global_s_options;
220 extern struct options *global_w_options;
221 extern struct environ *global_environ;
222 extern struct timeval start_time;
223 +extern int socket_can_be_created_again;
224 extern const char *socket_path;
225 extern const char *shell_command;
227 @@ -2583,6 +2584,7 @@ int server_start(struct tmuxproc *, int, struct event_base *, int, char *);
228 void server_update_socket(void);
229 void server_add_accept(int);
230 void printflike(1, 2) server_add_message(const char *, ...);
231 +int server_create_socket(int, char **);
233 /* server-client.c */
234 RB_PROTOTYPE(client_windows, client_window, entry, server_client_window_cmp);