1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
|
/*
* 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 <https://www.gnu.org/licenses/>.
*/
#include "config.h"
#include "systemd.hh"
#include <memory>
#include <systemd/sd-login.h>
#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)
{
{
char* unit = nullptr;
if (auto r = sd_pid_get_user_unit(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)", "CollectMode", g_variant_new_string("inactive-or-failed"));
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)
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<GVariant, decltype(&g_variant_unref)>
{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
|