summaryrefslogtreecommitdiffstats
path: root/compat/systemd.c
diff options
context:
space:
mode:
Diffstat (limited to 'compat/systemd.c')
-rw-r--r--compat/systemd.c159
1 files changed, 158 insertions, 1 deletions
diff --git a/compat/systemd.c b/compat/systemd.c
index 7317e43..6f790a3 100644
--- a/compat/systemd.c
+++ b/compat/systemd.c
@@ -19,17 +19,28 @@
#include <sys/types.h>
#include <sys/un.h>
+#include <systemd/sd-bus.h>
#include <systemd/sd-daemon.h>
+#include <systemd/sd-login.h>
+#include <systemd/sd-id128.h>
+
+#include <string.h>
#include "tmux.h"
int
+systemd_activated(void)
+{
+ return (sd_listen_fds(0) >= 1);
+}
+
+int
systemd_create_socket(int flags, char **cause)
{
int fds;
int fd;
struct sockaddr_un sa;
- int addrlen = sizeof sa;
+ socklen_t addrlen = sizeof sa;
fds = sd_listen_fds(0);
if (fds > 1) { /* too many file descriptors */
@@ -56,3 +67,149 @@ fail:
xasprintf(cause, "systemd socket error (%s)", strerror(errno));
return (-1);
}
+
+int
+systemd_move_pid_to_new_cgroup(pid_t pid, char **cause)
+{
+ sd_bus_error error = SD_BUS_ERROR_NULL;
+ sd_bus_message *m = NULL, *reply = NULL;
+ sd_bus *bus = NULL;
+ char *name, *desc, *slice;
+ sd_id128_t uuid;
+ int r;
+ pid_t parent_pid;
+
+ /* Connect to the session bus. */
+ r = sd_bus_default_user(&bus);
+ if (r < 0) {
+ xasprintf(cause, "failed to connect to session bus: %s",
+ strerror(-r));
+ goto finish;
+ }
+
+ /* Start building the method call. */
+ r = sd_bus_message_new_method_call(bus, &m,
+ "org.freedesktop.systemd1",
+ "/org/freedesktop/systemd1",
+ "org.freedesktop.systemd1.Manager",
+ "StartTransientUnit");
+ if (r < 0) {
+ xasprintf(cause, "failed to create bus message: %s",
+ strerror(-r));
+ goto finish;
+ }
+
+ /* Generate a unique name for the new scope, to avoid collisions. */
+ r = sd_id128_randomize(&uuid);
+ if (r < 0) {
+ xasprintf(cause, "failed to generate uuid: %s", strerror(-r));
+ goto finish;
+ }
+ xasprintf(&name, "tmux-spawn-" SD_ID128_UUID_FORMAT_STR ".scope",
+ SD_ID128_FORMAT_VAL(uuid));
+ r = sd_bus_message_append(m, "s", name);
+ free(name);
+ if (r < 0) {
+ xasprintf(cause, "failed to append to bus message: %s",
+ strerror(-r));
+ goto finish;
+ }
+
+ /* Mode: fail if there's a queued unit with the same name. */
+ r = sd_bus_message_append(m, "s", "fail");
+ if (r < 0) {
+ xasprintf(cause, "failed to append to bus message: %s",
+ strerror(-r));
+ goto finish;
+ }
+
+ /* Start properties array. */
+ r = sd_bus_message_open_container(m, 'a', "(sv)");
+ if (r < 0) {
+ xasprintf(cause, "failed to start properties array: %s",
+ strerror(-r));
+ goto finish;
+ }
+
+ parent_pid = getpid();
+ xasprintf(&desc, "tmux child pane %ld launched by process %ld",
+ (long)pid, (long)parent_pid);
+ r = sd_bus_message_append(m, "(sv)", "Description", "s", desc);
+ free(desc);
+ if (r < 0) {
+ xasprintf(cause, "failed to append to properties: %s",
+ strerror(-r));
+ goto finish;
+ }
+
+ /*
+ * Inherit the slice from the parent process, or default to
+ * "app-tmux.slice" if that fails.
+ */
+ r = sd_pid_get_user_slice(parent_pid, &slice);
+ if (r < 0) {
+ slice = xstrdup("app-tmux.slice");
+ }
+ r = sd_bus_message_append(m, "(sv)", "Slice", "s", slice);
+ free(slice);
+ if (r < 0) {
+ xasprintf(cause, "failed to append to properties: %s",
+ strerror(-r));
+ goto finish;
+ }
+
+ /* PIDs to add to the scope: length - 1 array of uint32_t. */
+ r = sd_bus_message_append(m, "(sv)", "PIDs", "au", 1, pid);
+ if (r < 0) {
+ xasprintf(cause, "failed to append to properties: %s",
+ strerror(-r));
+ goto finish;
+ }
+
+ /* Clean up the scope even if it fails. */
+ r = sd_bus_message_append(m, "(sv)", "CollectMode", "s",
+ "inactive-or-failed");
+ if (r < 0) {
+ xasprintf(cause, "failed to append to properties: %s",
+ strerror(-r));
+ goto finish;
+ }
+
+ /* End properties array. */
+ r = sd_bus_message_close_container(m);
+ if (r < 0) {
+ xasprintf(cause, "failed to end properties array: %s",
+ strerror(-r));
+ goto finish;
+ }
+
+ /* aux is currently unused and should be passed an empty array. */
+ r = sd_bus_message_append(m, "a(sa(sv))", 0);
+ if (r < 0) {
+ xasprintf(cause, "failed to append to bus message: %s",
+ strerror(-r));
+ goto finish;
+ }
+
+ /* Call the method with a timeout of 1 second = 1e6 us. */
+ r = sd_bus_call(bus, m, 1000000, &error, &reply);
+ if (r < 0) {
+ if (error.message != NULL) {
+ /* We have a specific error message from sd-bus. */
+ xasprintf(cause, "StartTransientUnit call failed: %s",
+ error.message);
+ } else {
+ xasprintf(cause, "StartTransientUnit call failed: %s",
+ strerror(-r));
+ }
+ goto finish;
+ }
+
+finish:
+ sd_bus_error_free(&error);
+ sd_bus_message_unref(m);
+ sd_bus_message_unref(reply);
+ sd_bus_unref(bus);
+
+ return (r);
+}