/* * Copyright © 2020 Christian Persch * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 3 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "config.h" #include "systemd.hh" #include #include #include "glib-glue.hh" #include "refptr.hh" namespace vte::systemd { bool create_scope_for_pid_sync(pid_t pid, int timeout, GCancellable* cancellable, GError** error) { auto const parent_pid = getpid(); { char* unit = nullptr; if (auto r = sd_pid_get_user_unit(parent_pid, &unit) < 0) { g_set_error(error, G_IO_ERROR, g_io_error_from_errno(-r), "Failed sd_pid_get_user_unit(%d): %s", pid, g_strerror(-r)); return false; } free(unit); } auto bus = vte::glib::take_ref(g_bus_get_sync(G_BUS_TYPE_SESSION, cancellable, error)); if (!bus) return false; auto uuid = vte::glib::take_string(g_uuid_string_random()); auto scope = vte::glib::take_string(g_strdup_printf("vte-spawn-%s.scope", uuid.get())); auto prgname = vte::glib::take_string(g_utf8_make_valid(g_get_prgname(), -1)); auto description = vte::glib::take_string(g_strdup_printf("VTE child process %d launched by %s process %d", pid, prgname.get(), getpid())); auto builder_stack = GVariantBuilder{}; auto builder = &builder_stack; g_variant_builder_init(builder, G_VARIANT_TYPE("(ssa(sv)a(sa(sv)))")); g_variant_builder_add(builder, "s", scope.get()); // unit name g_variant_builder_add(builder, "s", "fail"); // failure mode // Unit properties g_variant_builder_open(builder, G_VARIANT_TYPE("a(sv)")); g_variant_builder_add(builder, "(sv)", "Description", g_variant_new_string(description.get())); g_variant_builder_open(builder, G_VARIANT_TYPE("(sv)")); g_variant_builder_add(builder, "s", "PIDs"); g_variant_builder_open(builder, G_VARIANT_TYPE("v")); g_variant_builder_open(builder, G_VARIANT_TYPE("au")); g_variant_builder_add(builder, "u", unsigned(pid)); g_variant_builder_close(builder); // au g_variant_builder_close(builder); // v g_variant_builder_close(builder); // (sv) char* slice = nullptr; if (sd_pid_get_user_slice(parent_pid, &slice) >= 0) { g_variant_builder_add(builder, "(sv)", "Slice", g_variant_new_string(slice)); free(slice); } else { // Fallback g_variant_builder_add(builder, "(sv)", "Slice", g_variant_new_string("app-org.gnome.vte.slice")); } g_variant_builder_close(builder); // a(sv) // No auxiliary units g_variant_builder_open(builder, G_VARIANT_TYPE("a(sa(sv))")); g_variant_builder_close(builder); // Create transient scope auto reply = std::unique_ptr {g_dbus_connection_call_sync(bus.get(), "org.freedesktop.systemd1", "/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", "StartTransientUnit", g_variant_builder_end(builder), // parameters G_VARIANT_TYPE("(o)"), // reply type, GDBusCallFlags{G_DBUS_CALL_FLAGS_NO_AUTO_START}, timeout, // in ms cancellable, error), &g_variant_unref}; return bool(reply); } } // namespace vte::systemd