1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4 This file is part of systemd.
6 Copyright 2010 Lennart Poettering
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
11 (at your option) any later version.
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
27 #include "dbus-manager.h"
29 #include "bus-errors.h"
31 #include "dbus-common.h"
33 #include "selinux-access.h"
36 #include "path-util.h"
37 #include "dbus-unit.h"
41 #define BUS_MANAGER_INTERFACE_BEGIN \
42 " <interface name=\"org.freedesktop.systemd1.Manager\">\n"
44 #define BUS_MANAGER_INTERFACE_METHODS \
45 " <method name=\"GetUnit\">\n" \
46 " <arg name=\"name\" type=\"s\" direction=\"in\"/>\n" \
47 " <arg name=\"unit\" type=\"o\" direction=\"out\"/>\n" \
49 " <method name=\"GetUnitByPID\">\n" \
50 " <arg name=\"pid\" type=\"u\" direction=\"in\"/>\n" \
51 " <arg name=\"unit\" type=\"o\" direction=\"out\"/>\n" \
53 " <method name=\"LoadUnit\">\n" \
54 " <arg name=\"name\" type=\"s\" direction=\"in\"/>\n" \
55 " <arg name=\"unit\" type=\"o\" direction=\"out\"/>\n" \
57 " <method name=\"StartUnit\">\n" \
58 " <arg name=\"name\" type=\"s\" direction=\"in\"/>\n" \
59 " <arg name=\"mode\" type=\"s\" direction=\"in\"/>\n" \
60 " <arg name=\"job\" type=\"o\" direction=\"out\"/>\n" \
62 " <method name=\"StartUnitReplace\">\n" \
63 " <arg name=\"old_unit\" type=\"s\" direction=\"in\"/>\n" \
64 " <arg name=\"new_unit\" type=\"s\" direction=\"in\"/>\n" \
65 " <arg name=\"mode\" type=\"s\" direction=\"in\"/>\n" \
66 " <arg name=\"job\" type=\"o\" direction=\"out\"/>\n" \
68 " <method name=\"StopUnit\">\n" \
69 " <arg name=\"name\" type=\"s\" direction=\"in\"/>\n" \
70 " <arg name=\"mode\" type=\"s\" direction=\"in\"/>\n" \
71 " <arg name=\"job\" type=\"o\" direction=\"out\"/>\n" \
73 " <method name=\"ReloadUnit\">\n" \
74 " <arg name=\"name\" type=\"s\" direction=\"in\"/>\n" \
75 " <arg name=\"mode\" type=\"s\" direction=\"in\"/>\n" \
76 " <arg name=\"job\" type=\"o\" direction=\"out\"/>\n" \
78 " <method name=\"RestartUnit\">\n" \
79 " <arg name=\"name\" type=\"s\" direction=\"in\"/>\n" \
80 " <arg name=\"mode\" type=\"s\" direction=\"in\"/>\n" \
81 " <arg name=\"job\" type=\"o\" direction=\"out\"/>\n" \
83 " <method name=\"TryRestartUnit\">\n" \
84 " <arg name=\"name\" type=\"s\" direction=\"in\"/>\n" \
85 " <arg name=\"mode\" type=\"s\" direction=\"in\"/>\n" \
86 " <arg name=\"job\" type=\"o\" direction=\"out\"/>\n" \
88 " <method name=\"ReloadOrRestartUnit\">\n" \
89 " <arg name=\"name\" type=\"s\" direction=\"in\"/>\n" \
90 " <arg name=\"mode\" type=\"s\" direction=\"in\"/>\n" \
91 " <arg name=\"job\" type=\"o\" direction=\"out\"/>\n" \
93 " <method name=\"ReloadOrTryRestartUnit\">\n" \
94 " <arg name=\"name\" type=\"s\" direction=\"in\"/>\n" \
95 " <arg name=\"mode\" type=\"s\" direction=\"in\"/>\n" \
96 " <arg name=\"job\" type=\"o\" direction=\"out\"/>\n" \
98 " <method name=\"KillUnit\">\n" \
99 " <arg name=\"name\" type=\"s\" direction=\"in\"/>\n" \
100 " <arg name=\"who\" type=\"s\" direction=\"in\"/>\n" \
101 " <arg name=\"signal\" type=\"i\" direction=\"in\"/>\n" \
103 " <method name=\"ResetFailedUnit\">\n" \
104 " <arg name=\"name\" type=\"s\" direction=\"in\"/>\n" \
106 " <method name=\"SetUnitControlGroup\">\n" \
107 " <arg name=\"name\" type=\"s\" direction=\"in\"/>\n" \
108 " <arg name=\"group\" type=\"s\" direction=\"in\"/>\n" \
109 " <arg name=\"mode\" type=\"s\" direction=\"in\"/>\n" \
111 " <method name=\"UnsetUnitControlGroup\">\n" \
112 " <arg name=\"name\" type=\"s\" direction=\"in\"/>\n" \
113 " <arg name=\"group\" type=\"s\" direction=\"in\"/>\n" \
114 " <arg name=\"mode\" type=\"s\" direction=\"in\"\n/>" \
116 " <method name=\"GetUnitControlGroupAttribute\">\n" \
117 " <arg name=\"name\" type=\"s\" direction=\"in\"/>\n" \
118 " <arg name=\"attribute\" type=\"s\" direction=\"in\"/>\n" \
119 " <arg name=\"values\" type=\"as\" direction=\"out\"/>\n" \
121 " <method name=\"SetUnitControlGroupAttribute\">\n" \
122 " <arg name=\"name\" type=\"s\" direction=\"in\"/>\n" \
123 " <arg name=\"attribute\" type=\"s\" direction=\"in\"/>\n" \
124 " <arg name=\"values\" type=\"as\" direction=\"in\"/>\n" \
125 " <arg name=\"mode\" type=\"s\" direction=\"in\"\n/>" \
127 " <method name=\"UnsetUnitControlGroupAttributes\">\n" \
128 " <arg name=\"name\" type=\"s\" direction=\"in\"/>\n" \
129 " <arg name=\"attribute\" type=\"s\" direction=\"in\"/>\n" \
130 " <arg name=\"mode\" type=\"s\" direction=\"in\"/>\n" \
132 " <method name=\"GetJob\">\n" \
133 " <arg name=\"id\" type=\"u\" direction=\"in\"/>\n" \
134 " <arg name=\"job\" type=\"o\" direction=\"out\"/>\n" \
136 " <method name=\"CancelJob\">\n" \
137 " <arg name=\"id\" type=\"u\" direction=\"in\"/>\n" \
139 " <method name=\"ClearJobs\"/>\n" \
140 " <method name=\"ResetFailed\"/>\n" \
141 " <method name=\"ListUnits\">\n" \
142 " <arg name=\"units\" type=\"a(ssssssouso)\" direction=\"out\"/>\n" \
144 " <method name=\"ListJobs\">\n" \
145 " <arg name=\"jobs\" type=\"a(usssoo)\" direction=\"out\"/>\n" \
147 " <method name=\"Subscribe\"/>\n" \
148 " <method name=\"Unsubscribe\"/>\n" \
149 " <method name=\"Dump\">\n" \
150 " <arg name=\"dump\" type=\"s\" direction=\"out\"/>\n" \
152 " <method name=\"CreateSnapshot\">\n" \
153 " <arg name=\"name\" type=\"s\" direction=\"in\"/>\n" \
154 " <arg name=\"cleanup\" type=\"b\" direction=\"in\"/>\n" \
155 " <arg name=\"unit\" type=\"o\" direction=\"out\"/>\n" \
157 " <method name=\"RemoveSnapshot\">\n" \
158 " <arg name=\"name\" type=\"s\" direction=\"in\"/>\n" \
160 " <method name=\"Reload\"/>\n" \
161 " <method name=\"Reexecute\"/>\n" \
162 " <method name=\"Exit\"/>\n" \
163 " <method name=\"Reboot\"/>\n" \
164 " <method name=\"PowerOff\"/>\n" \
165 " <method name=\"Halt\"/>\n" \
166 " <method name=\"KExec\"/>\n" \
167 " <method name=\"SwitchRoot\">\n" \
168 " <arg name=\"new_root\" type=\"s\" direction=\"in\"/>\n" \
169 " <arg name=\"init\" type=\"s\" direction=\"in\"/>\n" \
171 " <method name=\"SetEnvironment\">\n" \
172 " <arg name=\"names\" type=\"as\" direction=\"in\"/>\n" \
174 " <method name=\"UnsetEnvironment\">\n" \
175 " <arg name=\"names\" type=\"as\" direction=\"in\"/>\n" \
177 " <method name=\"UnsetAndSetEnvironment\">\n" \
178 " <arg name=\"unset\" type=\"as\" direction=\"in\"/>\n" \
179 " <arg name=\"set\" type=\"as\" direction=\"in\"/>\n" \
181 " <method name=\"ListUnitFiles\">\n" \
182 " <arg name=\"files\" type=\"a(ss)\" direction=\"out\"/>\n" \
184 " <method name=\"GetUnitFileState\">\n" \
185 " <arg name=\"file\" type=\"s\" direction=\"in\"/>\n" \
186 " <arg name=\"state\" type=\"s\" direction=\"out\"/>\n" \
188 " <method name=\"EnableUnitFiles\">\n" \
189 " <arg name=\"files\" type=\"as\" direction=\"in\"/>\n" \
190 " <arg name=\"runtime\" type=\"b\" direction=\"in\"/>\n" \
191 " <arg name=\"force\" type=\"b\" direction=\"in\"/>\n" \
192 " <arg name=\"carries_install_info\" type=\"b\" direction=\"out\"/>\n" \
193 " <arg name=\"changes\" type=\"a(sss)\" direction=\"out\"/>\n" \
195 " <method name=\"DisableUnitFiles\">\n" \
196 " <arg name=\"files\" type=\"as\" direction=\"in\"/>\n" \
197 " <arg name=\"runtime\" type=\"b\" direction=\"in\"/>\n" \
198 " <arg name=\"changes\" type=\"a(sss)\" direction=\"out\"/>\n" \
200 " <method name=\"ReenableUnitFiles\">\n" \
201 " <arg name=\"files\" type=\"as\" direction=\"in\"/>\n" \
202 " <arg name=\"runtime\" type=\"b\" direction=\"in\"/>\n" \
203 " <arg name=\"force\" type=\"b\" direction=\"in\"/>\n" \
204 " <arg name=\"carries_install_info\" type=\"b\" direction=\"out\"/>\n" \
205 " <arg name=\"changes\" type=\"a(sss)\" direction=\"out\"/>\n" \
207 " <method name=\"LinkUnitFiles\">\n" \
208 " <arg name=\"files\" type=\"as\" direction=\"in\"/>\n" \
209 " <arg name=\"runtime\" type=\"b\" direction=\"in\"/>\n" \
210 " <arg name=\"force\" type=\"b\" direction=\"in\"/>\n" \
211 " <arg name=\"changes\" type=\"a(sss)\" direction=\"out\"/>\n" \
213 " <method name=\"PresetUnitFiles\">\n" \
214 " <arg name=\"files\" type=\"as\" direction=\"in\"/>\n" \
215 " <arg name=\"runtime\" type=\"b\" direction=\"in\"/>\n" \
216 " <arg name=\"force\" type=\"b\" direction=\"in\"/>\n" \
217 " <arg name=\"carries_install_info\" type=\"b\" direction=\"out\"/>\n" \
218 " <arg name=\"changes\" type=\"a(sss)\" direction=\"out\"/>\n" \
220 " <method name=\"MaskUnitFiles\">\n" \
221 " <arg name=\"files\" type=\"as\" direction=\"in\"/>\n" \
222 " <arg name=\"runtime\" type=\"b\" direction=\"in\"/>\n" \
223 " <arg name=\"force\" type=\"b\" direction=\"in\"/>\n" \
224 " <arg name=\"changes\" type=\"a(sss)\" direction=\"out\"/>\n" \
226 " <method name=\"UnmaskUnitFiles\">\n" \
227 " <arg name=\"files\" type=\"as\" direction=\"in\"/>\n" \
228 " <arg name=\"runtime\" type=\"b\" direction=\"in\"/>\n" \
229 " <arg name=\"changes\" type=\"a(sss)\" direction=\"out\"/>\n" \
231 " <method name=\"SetDefaultTarget\">\n" \
232 " <arg name=\"files\" type=\"as\" direction=\"in\"/>\n" \
233 " <arg name=\"changes\" type=\"a(sss)\" direction=\"out\"/>\n" \
235 " <method name=\"GetDefaultTarget\">\n" \
236 " <arg name=\"name\" type=\"s\" direction=\"out\"/>\n" \
239 #define BUS_MANAGER_INTERFACE_SIGNALS \
240 " <signal name=\"UnitNew\">\n" \
241 " <arg name=\"id\" type=\"s\"/>\n" \
242 " <arg name=\"unit\" type=\"o\"/>\n" \
244 " <signal name=\"UnitRemoved\">\n" \
245 " <arg name=\"id\" type=\"s\"/>\n" \
246 " <arg name=\"unit\" type=\"o\"/>\n" \
248 " <signal name=\"JobNew\">\n" \
249 " <arg name=\"id\" type=\"u\"/>\n" \
250 " <arg name=\"job\" type=\"o\"/>\n" \
251 " <arg name=\"unit\" type=\"s\"/>\n" \
253 " <signal name=\"JobRemoved\">\n" \
254 " <arg name=\"id\" type=\"u\"/>\n" \
255 " <arg name=\"job\" type=\"o\"/>\n" \
256 " <arg name=\"unit\" type=\"s\"/>\n" \
257 " <arg name=\"result\" type=\"s\"/>\n" \
259 " <signal name=\"StartupFinished\">\n" \
260 " <arg name=\"firmware\" type=\"t\"/>\n" \
261 " <arg name=\"loader\" type=\"t\"/>\n" \
262 " <arg name=\"kernel\" type=\"t\"/>\n" \
263 " <arg name=\"initrd\" type=\"t\"/>\n" \
264 " <arg name=\"userspace\" type=\"t\"/>\n" \
265 " <arg name=\"total\" type=\"t\"/>\n" \
267 " <signal name=\"UnitFilesChanged\"/>\n"
269 #define BUS_MANAGER_INTERFACE_PROPERTIES_GENERAL \
270 " <property name=\"Version\" type=\"s\" access=\"read\"/>\n" \
271 " <property name=\"Features\" type=\"s\" access=\"read\"/>\n" \
272 " <property name=\"Tainted\" type=\"s\" access=\"read\"/>\n" \
273 " <property name=\"FirmwareTimestamp\" type=\"t\" access=\"read\"/>\n" \
274 " <property name=\"FirmwareTimestampMonotonic\" type=\"t\" access=\"read\"/>\n" \
275 " <property name=\"LoaderTimestamp\" type=\"t\" access=\"read\"/>\n" \
276 " <property name=\"LoaderTimestampMonotonic\" type=\"t\" access=\"read\"/>\n" \
277 " <property name=\"KernelTimestamp\" type=\"t\" access=\"read\"/>\n" \
278 " <property name=\"KernelTimestampMonotonic\" type=\"t\" access=\"read\"/>\n" \
279 " <property name=\"InitRDTimestamp\" type=\"t\" access=\"read\"/>\n" \
280 " <property name=\"InitRDTimestampMonotonic\" type=\"t\" access=\"read\"/>\n" \
281 " <property name=\"UserspaceTimestamp\" type=\"t\" access=\"read\"/>\n" \
282 " <property name=\"UserspaceTimestampMonotonic\" type=\"t\" access=\"read\"/>\n" \
283 " <property name=\"FinishTimestamp\" type=\"t\" access=\"read\"/>\n" \
284 " <property name=\"FinishTimestampMonotonic\" type=\"t\" access=\"read\"/>\n" \
285 " <property name=\"GeneratorsStartTimestamp\" type=\"t\" access=\"read\"/>\n" \
286 " <property name=\"GeneratorsStartTimestampMonotonic\" type=\"t\" access=\"read\"/>\n" \
287 " <property name=\"GeneratorsFinishTimestamp\" type=\"t\" access=\"read\"/>\n" \
288 " <property name=\"GeneratorsFinishTimestampMonotonic\" type=\"t\" access=\"read\"/>\n" \
289 " <property name=\"LogLevel\" type=\"s\" access=\"readwrite\"/>\n" \
290 " <property name=\"LogTarget\" type=\"s\" access=\"readwrite\"/>\n" \
291 " <property name=\"NNames\" type=\"u\" access=\"read\"/>\n" \
292 " <property name=\"NJobs\" type=\"u\" access=\"read\"/>\n" \
293 " <property name=\"NInstalledJobs\" type=\"u\" access=\"read\"/>\n" \
294 " <property name=\"NFailedJobs\" type=\"u\" access=\"read\"/>\n" \
295 " <property name=\"Progress\" type=\"d\" access=\"read\"/>\n" \
296 " <property name=\"Environment\" type=\"as\" access=\"read\"/>\n" \
297 " <property name=\"ConfirmSpawn\" type=\"b\" access=\"read\"/>\n" \
298 " <property name=\"ShowStatus\" type=\"b\" access=\"read\"/>\n" \
299 " <property name=\"UnitPath\" type=\"as\" access=\"read\"/>\n" \
300 " <property name=\"ControlGroupHierarchy\" type=\"s\" access=\"read\"/>\n" \
301 " <property name=\"DefaultControllers\" type=\"as\" access=\"read\"/>\n" \
302 " <property name=\"DefaultStandardOutput\" type=\"s\" access=\"read\"/>\n" \
303 " <property name=\"DefaultStandardError\" type=\"s\" access=\"read\"/>\n" \
304 " <property name=\"RuntimeWatchdogUSec\" type=\"t\" access=\"readwrite\"/>\n" \
305 " <property name=\"ShutdownWatchdogUSec\" type=\"t\" access=\"readwrite\"/>\n" \
306 " <property name=\"Virtualization\" type=\"s\" access=\"read\"/>\n"
308 #define BUS_MANAGER_INTERFACE_END \
311 #define BUS_MANAGER_INTERFACE \
312 BUS_MANAGER_INTERFACE_BEGIN \
313 BUS_MANAGER_INTERFACE_METHODS \
314 BUS_MANAGER_INTERFACE_SIGNALS \
315 BUS_MANAGER_INTERFACE_PROPERTIES_GENERAL \
316 BUS_MANAGER_INTERFACE_END
318 #define INTROSPECTION_BEGIN \
319 DBUS_INTROSPECT_1_0_XML_DOCTYPE_DECL_NODE \
321 BUS_MANAGER_INTERFACE \
322 BUS_PROPERTIES_INTERFACE \
324 BUS_INTROSPECTABLE_INTERFACE
326 #define INTROSPECTION_END \
329 #define INTERFACES_LIST \
330 BUS_GENERIC_INTERFACES_LIST \
331 "org.freedesktop.systemd1.Manager\0"
333 const char bus_manager_interface[] _introspect_("Manager") = BUS_MANAGER_INTERFACE;
335 static DEFINE_BUS_PROPERTY_APPEND_ENUM(bus_manager_append_exec_output, exec_output, ExecOutput);
337 static int bus_manager_append_tainted(DBusMessageIter *i, const char *property, void *data) {
340 char buf[LINE_MAX] = "", *e = buf, *p = NULL;
347 e = stpcpy(e, "split-usr:");
349 if (readlink_malloc("/etc/mtab", &p) < 0)
350 e = stpcpy(e, "mtab-not-symlink:");
354 if (access("/proc/cgroups", F_OK) < 0)
355 e = stpcpy(e, "cgroups-missing:");
357 if (hwclock_is_localtime() > 0)
358 e = stpcpy(e, "local-hwclock:");
360 /* remove the last ':' */
366 if (!dbus_message_iter_append_basic(i, DBUS_TYPE_STRING, &t))
372 static int bus_manager_append_log_target(DBusMessageIter *i, const char *property, void *data) {
378 t = log_target_to_string(log_get_target());
380 if (!dbus_message_iter_append_basic(i, DBUS_TYPE_STRING, &t))
386 static int bus_manager_set_log_target(DBusMessageIter *i, const char *property, void *data) {
392 dbus_message_iter_get_basic(i, &t);
394 return log_set_target_from_string(t);
397 static int bus_manager_append_log_level(DBusMessageIter *i, const char *property, void *data) {
404 r = log_level_to_string_alloc(log_get_max_level(), &t);
408 if (!dbus_message_iter_append_basic(i, DBUS_TYPE_STRING, &t))
415 static int bus_manager_set_log_level(DBusMessageIter *i, const char *property, void *data) {
421 dbus_message_iter_get_basic(i, &t);
423 return log_set_max_level_from_string(t);
426 static int bus_manager_append_n_names(DBusMessageIter *i, const char *property, void *data) {
434 u = hashmap_size(m->units);
436 if (!dbus_message_iter_append_basic(i, DBUS_TYPE_UINT32, &u))
442 static int bus_manager_append_n_jobs(DBusMessageIter *i, const char *property, void *data) {
450 u = hashmap_size(m->jobs);
452 if (!dbus_message_iter_append_basic(i, DBUS_TYPE_UINT32, &u))
458 static int bus_manager_append_progress(DBusMessageIter *i, const char *property, void *data) {
466 if (dual_timestamp_is_set(&m->finish_timestamp))
469 d = 1.0 - ((double) hashmap_size(m->jobs) / (double) m->n_installed_jobs);
471 if (!dbus_message_iter_append_basic(i, DBUS_TYPE_DOUBLE, &d))
477 static int bus_manager_append_virt(DBusMessageIter *i, const char *property, void *data) {
485 detect_virtualization(&id);
487 if (!dbus_message_iter_append_basic(i, DBUS_TYPE_STRING, &id))
493 static DBusMessage *message_from_file_changes(
495 UnitFileChange *changes,
497 int carries_install_info) {
499 DBusMessageIter iter, sub, sub2;
503 reply = dbus_message_new_method_return(m);
507 dbus_message_iter_init_append(reply, &iter);
509 if (carries_install_info >= 0) {
512 b = !!carries_install_info;
513 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &b))
517 if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "(sss)", &sub))
520 for (i = 0; i < n_changes; i++) {
521 const char *type, *path, *source;
523 type = unit_file_change_type_to_string(changes[i].type);
524 path = strempty(changes[i].path);
525 source = strempty(changes[i].source);
527 if (!dbus_message_iter_open_container(&sub, DBUS_TYPE_STRUCT, NULL, &sub2) ||
528 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &type) ||
529 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &path) ||
530 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &source) ||
531 !dbus_message_iter_close_container(&sub, &sub2))
535 if (!dbus_message_iter_close_container(&iter, &sub))
541 dbus_message_unref(reply);
545 static int bus_manager_send_unit_files_changed(Manager *m) {
549 s = dbus_message_new_signal("/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", "UnitFilesChanged");
553 r = bus_broadcast(m, s);
554 dbus_message_unref(s);
559 static int bus_manager_set_runtime_watchdog_usec(DBusMessageIter *i, const char *property, void *data) {
565 dbus_message_iter_get_basic(i, t);
567 return watchdog_set_timeout(t);
570 static const char systemd_property_string[] =
574 static const BusProperty bus_systemd_properties[] = {
575 { "Version", bus_property_append_string, "s", 0 },
576 { "Features", bus_property_append_string, "s", sizeof(PACKAGE_STRING) },
580 static const BusProperty bus_manager_properties[] = {
581 { "Tainted", bus_manager_append_tainted, "s", 0 },
582 { "FirmwareTimestamp", bus_property_append_uint64, "t", offsetof(Manager, firmware_timestamp.realtime) },
583 { "FirmwareTimestampMonotonic", bus_property_append_uint64, "t", offsetof(Manager, firmware_timestamp.monotonic) },
584 { "LoaderTimestamp", bus_property_append_uint64, "t", offsetof(Manager, loader_timestamp.realtime) },
585 { "LoaderTimestampMonotonic", bus_property_append_uint64, "t", offsetof(Manager, loader_timestamp.monotonic) },
586 { "KernelTimestamp", bus_property_append_uint64, "t", offsetof(Manager, kernel_timestamp.realtime) },
587 { "KernelTimestampMonotonic", bus_property_append_uint64, "t", offsetof(Manager, kernel_timestamp.monotonic) },
588 { "InitRDTimestamp", bus_property_append_uint64, "t", offsetof(Manager, initrd_timestamp.realtime) },
589 { "InitRDTimestampMonotonic", bus_property_append_uint64, "t", offsetof(Manager, initrd_timestamp.monotonic) },
590 { "UserspaceTimestamp", bus_property_append_uint64, "t", offsetof(Manager, userspace_timestamp.realtime) },
591 { "UserspaceTimestampMonotonic", bus_property_append_uint64, "t", offsetof(Manager, userspace_timestamp.monotonic) },
592 { "FinishTimestamp", bus_property_append_uint64, "t", offsetof(Manager, finish_timestamp.realtime) },
593 { "FinishTimestampMonotonic", bus_property_append_uint64, "t", offsetof(Manager, finish_timestamp.monotonic) },
594 { "GeneratorsStartTimestamp", bus_property_append_uint64, "t", offsetof(Manager, generators_start_timestamp.realtime) },
595 { "GeneratorsStartTimestampMonotonic", bus_property_append_uint64, "t", offsetof(Manager, generators_start_timestamp.monotonic) },
596 { "GeneratorsFinishTimestamp", bus_property_append_uint64, "t", offsetof(Manager, generators_finish_timestamp.realtime) },
597 { "GeneratorsFinishTimestampMonotonic", bus_property_append_uint64, "t", offsetof(Manager, generators_finish_timestamp.monotonic) },
598 { "LogLevel", bus_manager_append_log_level, "s", 0, false, bus_manager_set_log_level },
599 { "LogTarget", bus_manager_append_log_target, "s", 0, false, bus_manager_set_log_target },
600 { "NNames", bus_manager_append_n_names, "u", 0 },
601 { "NJobs", bus_manager_append_n_jobs, "u", 0 },
602 { "NInstalledJobs", bus_property_append_uint32, "u", offsetof(Manager, n_installed_jobs) },
603 { "NFailedJobs", bus_property_append_uint32, "u", offsetof(Manager, n_failed_jobs) },
604 { "Progress", bus_manager_append_progress, "d", 0 },
605 { "Environment", bus_property_append_strv, "as", offsetof(Manager, environment), true },
606 { "ConfirmSpawn", bus_property_append_bool, "b", offsetof(Manager, confirm_spawn) },
607 { "ShowStatus", bus_property_append_bool, "b", offsetof(Manager, show_status) },
608 { "UnitPath", bus_property_append_strv, "as", offsetof(Manager, lookup_paths.unit_path), true },
609 { "ControlGroupHierarchy", bus_property_append_string, "s", offsetof(Manager, cgroup_hierarchy), true },
610 { "DefaultControllers", bus_property_append_strv, "as", offsetof(Manager, default_controllers), true },
611 { "DefaultStandardOutput", bus_manager_append_exec_output, "s", offsetof(Manager, default_std_output) },
612 { "DefaultStandardError", bus_manager_append_exec_output, "s", offsetof(Manager, default_std_error) },
613 { "RuntimeWatchdogUSec", bus_property_append_usec, "t", offsetof(Manager, runtime_watchdog), false, bus_manager_set_runtime_watchdog_usec },
614 { "ShutdownWatchdogUSec", bus_property_append_usec, "t", offsetof(Manager, shutdown_watchdog), false, bus_property_set_usec },
615 { "Virtualization", bus_manager_append_virt, "s", 0, },
619 static DBusHandlerResult bus_manager_message_handler(DBusConnection *connection, DBusMessage *message, void *data) {
620 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
621 _cleanup_free_ char * path = NULL;
625 JobType job_type = _JOB_TYPE_INVALID;
626 bool reload_if_possible = false;
633 dbus_error_init(&error);
635 member = dbus_message_get_member(message);
637 if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "GetUnit")) {
641 if (!dbus_message_get_args(
644 DBUS_TYPE_STRING, &name,
646 return bus_send_error_reply(connection, message, &error, -EINVAL);
648 u = manager_get_unit(m, name);
650 dbus_set_error(&error, BUS_ERROR_NO_SUCH_UNIT, "Unit %s is not loaded.", name);
651 return bus_send_error_reply(connection, message, &error, -ENOENT);
654 SELINUX_UNIT_ACCESS_CHECK(u, connection, message, "status");
656 reply = dbus_message_new_method_return(message);
660 path = unit_dbus_path(u);
664 if (!dbus_message_append_args(
666 DBUS_TYPE_OBJECT_PATH, &path,
669 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "GetUnitByPID")) {
673 if (!dbus_message_get_args(
676 DBUS_TYPE_UINT32, &pid,
678 return bus_send_error_reply(connection, message, &error, -EINVAL);
680 u = cgroup_unit_by_pid(m, (pid_t) pid);
682 dbus_set_error(&error, BUS_ERROR_NO_SUCH_UNIT, "No unit for PID %lu is loaded.", (unsigned long) pid);
683 return bus_send_error_reply(connection, message, &error, -ENOENT);
686 SELINUX_UNIT_ACCESS_CHECK(u, connection, message, "status");
688 reply = dbus_message_new_method_return(message);
692 path = unit_dbus_path(u);
696 if (!dbus_message_append_args(
698 DBUS_TYPE_OBJECT_PATH, &path,
701 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "LoadUnit")) {
705 if (!dbus_message_get_args(
708 DBUS_TYPE_STRING, &name,
710 return bus_send_error_reply(connection, message, &error, -EINVAL);
712 r = manager_load_unit(m, name, NULL, &error, &u);
714 return bus_send_error_reply(connection, message, &error, r);
716 SELINUX_UNIT_ACCESS_CHECK(u, connection, message, "status");
718 reply = dbus_message_new_method_return(message);
722 path = unit_dbus_path(u);
726 if (!dbus_message_append_args(
728 DBUS_TYPE_OBJECT_PATH, &path,
732 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "StartUnit"))
733 job_type = JOB_START;
734 else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "StartUnitReplace"))
735 job_type = JOB_START;
736 else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "StopUnit"))
738 else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ReloadUnit"))
739 job_type = JOB_RELOAD;
740 else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "RestartUnit"))
741 job_type = JOB_RESTART;
742 else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "TryRestartUnit"))
743 job_type = JOB_TRY_RESTART;
744 else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ReloadOrRestartUnit")) {
745 reload_if_possible = true;
746 job_type = JOB_RESTART;
747 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ReloadOrTryRestartUnit")) {
748 reload_if_possible = true;
749 job_type = JOB_TRY_RESTART;
750 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "KillUnit")) {
751 const char *name, *swho;
756 if (!dbus_message_get_args(
759 DBUS_TYPE_STRING, &name,
760 DBUS_TYPE_STRING, &swho,
761 DBUS_TYPE_INT32, &signo,
763 return bus_send_error_reply(connection, message, &error, -EINVAL);
768 who = kill_who_from_string(swho);
770 return bus_send_error_reply(connection, message, &error, -EINVAL);
773 if (signo <= 0 || signo >= _NSIG)
774 return bus_send_error_reply(connection, message, &error, -EINVAL);
776 u = manager_get_unit(m, name);
778 dbus_set_error(&error, BUS_ERROR_NO_SUCH_UNIT, "Unit %s is not loaded.", name);
779 return bus_send_error_reply(connection, message, &error, -ENOENT);
782 SELINUX_UNIT_ACCESS_CHECK(u, connection, message, "stop");
784 r = unit_kill(u, who, signo, &error);
786 return bus_send_error_reply(connection, message, &error, r);
788 reply = dbus_message_new_method_return(message);
792 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "GetJob")) {
796 if (!dbus_message_get_args(
799 DBUS_TYPE_UINT32, &id,
801 return bus_send_error_reply(connection, message, &error, -EINVAL);
803 j = manager_get_job(m, id);
805 dbus_set_error(&error, BUS_ERROR_NO_SUCH_JOB, "Job %u does not exist.", (unsigned) id);
806 return bus_send_error_reply(connection, message, &error, -ENOENT);
809 SELINUX_UNIT_ACCESS_CHECK(j->unit, connection, message, "status");
811 reply = dbus_message_new_method_return(message);
815 path = job_dbus_path(j);
819 if (!dbus_message_append_args(
821 DBUS_TYPE_OBJECT_PATH, &path,
825 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "CancelJob")) {
829 if (!dbus_message_get_args(
832 DBUS_TYPE_UINT32, &id,
834 return bus_send_error_reply(connection, message, &error, -EINVAL);
836 j = manager_get_job(m, id);
838 dbus_set_error(&error, BUS_ERROR_NO_SUCH_JOB, "Job %u does not exist.", (unsigned) id);
839 return bus_send_error_reply(connection, message, &error, -ENOENT);
842 SELINUX_UNIT_ACCESS_CHECK(j->unit, connection, message, "stop");
843 job_finish_and_invalidate(j, JOB_CANCELED, true);
845 reply = dbus_message_new_method_return(message);
849 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ClearJobs")) {
851 SELINUX_ACCESS_CHECK(connection, message, "reboot");
852 manager_clear_jobs(m);
854 reply = dbus_message_new_method_return(message);
858 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ResetFailed")) {
860 SELINUX_ACCESS_CHECK(connection, message, "reload");
862 manager_reset_failed(m);
864 reply = dbus_message_new_method_return(message);
868 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ResetFailedUnit")) {
872 if (!dbus_message_get_args(
875 DBUS_TYPE_STRING, &name,
877 return bus_send_error_reply(connection, message, &error, -EINVAL);
879 u = manager_get_unit(m, name);
881 dbus_set_error(&error, BUS_ERROR_NO_SUCH_UNIT, "Unit %s is not loaded.", name);
882 return bus_send_error_reply(connection, message, &error, -ENOENT);
885 SELINUX_UNIT_ACCESS_CHECK(u, connection, message, "reload");
887 unit_reset_failed(u);
889 reply = dbus_message_new_method_return(message);
893 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "SetUnitControlGroup")) {
896 DBusMessageIter iter;
898 if (!dbus_message_iter_init(message, &iter))
901 r = bus_iter_get_basic_and_next(&iter, DBUS_TYPE_STRING, &name, true);
903 return bus_send_error_reply(connection, message, NULL, r);
905 u = manager_get_unit(m, name);
907 dbus_set_error(&error, BUS_ERROR_NO_SUCH_UNIT, "Unit %s is not loaded.", name);
908 return bus_send_error_reply(connection, message, &error, -ENOENT);
911 SELINUX_UNIT_ACCESS_CHECK(u, connection, message, "start");
913 r = bus_unit_cgroup_set(u, &iter);
915 return bus_send_error_reply(connection, message, NULL, r);
917 reply = dbus_message_new_method_return(message);
921 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "UnsetUnitControlGroup")) {
924 DBusMessageIter iter;
926 if (!dbus_message_iter_init(message, &iter))
929 r = bus_iter_get_basic_and_next(&iter, DBUS_TYPE_STRING, &name, true);
931 return bus_send_error_reply(connection, message, NULL, r);
933 u = manager_get_unit(m, name);
935 dbus_set_error(&error, BUS_ERROR_NO_SUCH_UNIT, "Unit %s is not loaded.", name);
936 return bus_send_error_reply(connection, message, &error, -ENOENT);
939 SELINUX_UNIT_ACCESS_CHECK(u, connection, message, "stop");
941 r = bus_unit_cgroup_unset(u, &iter);
943 return bus_send_error_reply(connection, message, NULL, r);
945 reply = dbus_message_new_method_return(message);
949 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "SetUnitControlGroupAttribute")) {
952 DBusMessageIter iter;
954 if (!dbus_message_iter_init(message, &iter))
957 r = bus_iter_get_basic_and_next(&iter, DBUS_TYPE_STRING, &name, true);
959 return bus_send_error_reply(connection, message, NULL, r);
961 u = manager_get_unit(m, name);
963 dbus_set_error(&error, BUS_ERROR_NO_SUCH_UNIT, "Unit %s is not loaded.", name);
964 return bus_send_error_reply(connection, message, &error, -ENOENT);
967 SELINUX_UNIT_ACCESS_CHECK(u, connection, message, "start");
969 r = bus_unit_cgroup_attribute_set(u, &iter);
971 return bus_send_error_reply(connection, message, NULL, r);
973 reply = dbus_message_new_method_return(message);
977 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "UnsetUnitControlGroupAttribute")) {
980 DBusMessageIter iter;
982 if (!dbus_message_iter_init(message, &iter))
985 r = bus_iter_get_basic_and_next(&iter, DBUS_TYPE_STRING, &name, true);
987 return bus_send_error_reply(connection, message, NULL, r);
989 u = manager_get_unit(m, name);
991 dbus_set_error(&error, BUS_ERROR_NO_SUCH_UNIT, "Unit %s is not loaded.", name);
992 return bus_send_error_reply(connection, message, &error, -ENOENT);
995 SELINUX_UNIT_ACCESS_CHECK(u, connection, message, "stop");
997 r = bus_unit_cgroup_attribute_unset(u, &iter);
999 return bus_send_error_reply(connection, message, NULL, r);
1001 reply = dbus_message_new_method_return(message);
1005 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "GetUnitControlGroupAttribute")) {
1008 DBusMessageIter iter;
1009 _cleanup_strv_free_ char **list = NULL;
1011 if (!dbus_message_iter_init(message, &iter))
1014 r = bus_iter_get_basic_and_next(&iter, DBUS_TYPE_STRING, &name, true);
1016 return bus_send_error_reply(connection, message, NULL, r);
1018 u = manager_get_unit(m, name);
1020 dbus_set_error(&error, BUS_ERROR_NO_SUCH_UNIT, "Unit %s is not loaded.", name);
1021 return bus_send_error_reply(connection, message, &error, -ENOENT);
1024 SELINUX_UNIT_ACCESS_CHECK(u, connection, message, "status");
1026 r = bus_unit_cgroup_attribute_get(u, &iter, &list);
1028 return bus_send_error_reply(connection, message, NULL, r);
1030 reply = dbus_message_new_method_return(message);
1034 dbus_message_iter_init_append(reply, &iter);
1035 if (bus_append_strv_iter(&iter, list) < 0)
1038 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ListUnits")) {
1039 DBusMessageIter iter, sub;
1044 SELINUX_ACCESS_CHECK(connection, message, "status");
1046 reply = dbus_message_new_method_return(message);
1050 dbus_message_iter_init_append(reply, &iter);
1052 if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "(ssssssouso)", &sub))
1055 HASHMAP_FOREACH_KEY(u, k, m->units, i) {
1056 char *u_path, *j_path;
1057 const char *description, *load_state, *active_state, *sub_state, *sjob_type, *following;
1058 DBusMessageIter sub2;
1065 if (!dbus_message_iter_open_container(&sub, DBUS_TYPE_STRUCT, NULL, &sub2))
1068 description = unit_description(u);
1069 load_state = unit_load_state_to_string(u->load_state);
1070 active_state = unit_active_state_to_string(unit_active_state(u));
1071 sub_state = unit_sub_state_to_string(u);
1073 f = unit_following(u);
1074 following = f ? f->id : "";
1076 u_path = unit_dbus_path(u);
1081 job_id = (uint32_t) u->job->id;
1083 if (!(j_path = job_dbus_path(u->job))) {
1088 sjob_type = job_type_to_string(u->job->type);
1095 if (!dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &u->id) ||
1096 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &description) ||
1097 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &load_state) ||
1098 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &active_state) ||
1099 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &sub_state) ||
1100 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &following) ||
1101 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_OBJECT_PATH, &u_path) ||
1102 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_UINT32, &job_id) ||
1103 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &sjob_type) ||
1104 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_OBJECT_PATH, &j_path)) {
1115 if (!dbus_message_iter_close_container(&sub, &sub2))
1119 if (!dbus_message_iter_close_container(&iter, &sub))
1122 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ListJobs")) {
1123 DBusMessageIter iter, sub;
1127 SELINUX_ACCESS_CHECK(connection, message, "status");
1129 reply = dbus_message_new_method_return(message);
1133 dbus_message_iter_init_append(reply, &iter);
1135 if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "(usssoo)", &sub))
1138 HASHMAP_FOREACH(j, m->jobs, i) {
1139 char *u_path, *j_path;
1140 const char *state, *type;
1142 DBusMessageIter sub2;
1144 if (!dbus_message_iter_open_container(&sub, DBUS_TYPE_STRUCT, NULL, &sub2))
1147 id = (uint32_t) j->id;
1148 state = job_state_to_string(j->state);
1149 type = job_type_to_string(j->type);
1151 j_path = job_dbus_path(j);
1155 u_path = unit_dbus_path(j->unit);
1161 if (!dbus_message_iter_append_basic(&sub2, DBUS_TYPE_UINT32, &id) ||
1162 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &j->unit->id) ||
1163 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &type) ||
1164 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &state) ||
1165 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_OBJECT_PATH, &j_path) ||
1166 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_OBJECT_PATH, &u_path)) {
1175 if (!dbus_message_iter_close_container(&sub, &sub2))
1179 if (!dbus_message_iter_close_container(&iter, &sub))
1182 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "Subscribe")) {
1186 SELINUX_ACCESS_CHECK(connection, message, "status");
1188 s = BUS_CONNECTION_SUBSCRIBED(m, connection);
1190 s = set_new(string_hash_func, string_compare_func);
1194 if (!dbus_connection_set_data(connection, m->subscribed_data_slot, s, NULL)) {
1200 client = strdup(bus_message_get_sender_with_fallback(message));
1204 r = set_consume(s, client);
1206 return bus_send_error_reply(connection, message, NULL, r);
1208 reply = dbus_message_new_method_return(message);
1212 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "Unsubscribe")) {
1215 SELINUX_ACCESS_CHECK(connection, message, "status");
1217 client = set_remove(BUS_CONNECTION_SUBSCRIBED(m, connection), (char*) bus_message_get_sender_with_fallback(message));
1219 dbus_set_error(&error, BUS_ERROR_NOT_SUBSCRIBED, "Client is not subscribed.");
1220 return bus_send_error_reply(connection, message, &error, -ENOENT);
1225 reply = dbus_message_new_method_return(message);
1229 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "Dump")) {
1234 SELINUX_ACCESS_CHECK(connection, message, "status");
1236 reply = dbus_message_new_method_return(message);
1240 f = open_memstream(&dump, &size);
1244 manager_dump_units(m, f, NULL);
1245 manager_dump_jobs(m, f, NULL);
1255 if (!dbus_message_append_args(reply, DBUS_TYPE_STRING, &dump, DBUS_TYPE_INVALID)) {
1261 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "CreateSnapshot")) {
1263 dbus_bool_t cleanup;
1266 SELINUX_ACCESS_CHECK(connection, message, "start");
1268 if (!dbus_message_get_args(
1271 DBUS_TYPE_STRING, &name,
1272 DBUS_TYPE_BOOLEAN, &cleanup,
1274 return bus_send_error_reply(connection, message, &error, -EINVAL);
1279 r = snapshot_create(m, name, cleanup, &error, &s);
1281 return bus_send_error_reply(connection, message, &error, r);
1283 reply = dbus_message_new_method_return(message);
1287 path = unit_dbus_path(UNIT(s));
1291 if (!dbus_message_append_args(
1293 DBUS_TYPE_OBJECT_PATH, &path,
1297 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "RemoveSnapshot")) {
1301 if (!dbus_message_get_args(
1304 DBUS_TYPE_STRING, &name,
1306 return bus_send_error_reply(connection, message, &error, -EINVAL);
1308 u = manager_get_unit(m, name);
1310 dbus_set_error(&error, BUS_ERROR_NO_SUCH_UNIT, "Unit %s does not exist.", name);
1311 return bus_send_error_reply(connection, message, &error, -ENOENT);
1314 if (u->type != UNIT_SNAPSHOT) {
1315 dbus_set_error(&error, BUS_ERROR_NO_SUCH_UNIT, "Unit %s is not a snapshot.", name);
1316 return bus_send_error_reply(connection, message, &error, -ENOENT);
1319 SELINUX_UNIT_ACCESS_CHECK(u, connection, message, "stop");
1320 snapshot_remove(SNAPSHOT(u));
1322 reply = dbus_message_new_method_return(message);
1326 } else if (dbus_message_is_method_call(message, "org.freedesktop.DBus.Introspectable", "Introspect")) {
1327 char *introspection = NULL;
1335 SELINUX_ACCESS_CHECK(connection, message, "status");
1337 reply = dbus_message_new_method_return(message);
1341 /* We roll our own introspection code here, instead of
1342 * relying on bus_default_message_handler() because we
1343 * need to generate our introspection string
1346 f = open_memstream(&introspection, &size);
1350 fputs(INTROSPECTION_BEGIN, f);
1352 HASHMAP_FOREACH_KEY(u, k, m->units, i) {
1358 p = bus_path_escape(k);
1361 free(introspection);
1365 fprintf(f, "<node name=\"unit/%s\"/>", p);
1369 HASHMAP_FOREACH(j, m->jobs, i)
1370 fprintf(f, "<node name=\"job/%lu\"/>", (unsigned long) j->id);
1372 fputs(INTROSPECTION_END, f);
1376 free(introspection);
1385 if (!dbus_message_append_args(reply, DBUS_TYPE_STRING, &introspection, DBUS_TYPE_INVALID)) {
1386 free(introspection);
1390 free(introspection);
1392 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "Reload")) {
1394 SELINUX_ACCESS_CHECK(connection, message, "reload");
1396 assert(!m->queued_message);
1398 /* Instead of sending the reply back right away, we
1399 * just remember that we need to and then send it
1400 * after the reload is finished. That way the caller
1401 * knows when the reload finished. */
1403 m->queued_message = dbus_message_new_method_return(message);
1404 if (!m->queued_message)
1407 m->queued_message_connection = connection;
1408 m->exit_code = MANAGER_RELOAD;
1410 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "Reexecute")) {
1412 SELINUX_ACCESS_CHECK(connection, message, "reload");
1414 /* We don't send a reply back here, the client should
1415 * just wait for us disconnecting. */
1417 m->exit_code = MANAGER_REEXECUTE;
1419 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "Exit")) {
1421 SELINUX_ACCESS_CHECK(connection, message, "halt");
1423 if (m->running_as == SYSTEMD_SYSTEM) {
1424 dbus_set_error(&error, BUS_ERROR_NOT_SUPPORTED, "Exit is only supported for user service managers.");
1425 return bus_send_error_reply(connection, message, &error, -ENOTSUP);
1428 reply = dbus_message_new_method_return(message);
1432 m->exit_code = MANAGER_EXIT;
1434 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "Reboot")) {
1436 SELINUX_ACCESS_CHECK(connection, message, "reboot");
1438 if (m->running_as != SYSTEMD_SYSTEM) {
1439 dbus_set_error(&error, BUS_ERROR_NOT_SUPPORTED, "Reboot is only supported for system managers.");
1440 return bus_send_error_reply(connection, message, &error, -ENOTSUP);
1443 reply = dbus_message_new_method_return(message);
1447 m->exit_code = MANAGER_REBOOT;
1449 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "PowerOff")) {
1451 SELINUX_ACCESS_CHECK(connection, message, "halt");
1453 if (m->running_as != SYSTEMD_SYSTEM) {
1454 dbus_set_error(&error, BUS_ERROR_NOT_SUPPORTED, "Powering off is only supported for system managers.");
1455 return bus_send_error_reply(connection, message, &error, -ENOTSUP);
1458 reply = dbus_message_new_method_return(message);
1462 m->exit_code = MANAGER_POWEROFF;
1464 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "Halt")) {
1466 SELINUX_ACCESS_CHECK(connection, message, "halt");
1468 if (m->running_as != SYSTEMD_SYSTEM) {
1469 dbus_set_error(&error, BUS_ERROR_NOT_SUPPORTED, "Halting is only supported for system managers.");
1470 return bus_send_error_reply(connection, message, &error, -ENOTSUP);
1473 reply = dbus_message_new_method_return(message);
1477 m->exit_code = MANAGER_HALT;
1479 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "KExec")) {
1481 SELINUX_ACCESS_CHECK(connection, message, "reboot");
1483 if (m->running_as != SYSTEMD_SYSTEM) {
1484 dbus_set_error(&error, BUS_ERROR_NOT_SUPPORTED, "kexec is only supported for system managers.");
1485 return bus_send_error_reply(connection, message, &error, -ENOTSUP);
1488 reply = dbus_message_new_method_return(message);
1492 m->exit_code = MANAGER_KEXEC;
1494 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "SwitchRoot")) {
1495 const char *switch_root, *switch_root_init;
1499 SELINUX_ACCESS_CHECK(connection, message, "reboot");
1501 if (!dbus_message_get_args(
1504 DBUS_TYPE_STRING, &switch_root,
1505 DBUS_TYPE_STRING, &switch_root_init,
1507 return bus_send_error_reply(connection, message, &error, -EINVAL);
1509 if (path_equal(switch_root, "/") || !path_is_absolute(switch_root))
1510 return bus_send_error_reply(connection, message, NULL, -EINVAL);
1512 if (!isempty(switch_root_init) && !path_is_absolute(switch_root_init))
1513 return bus_send_error_reply(connection, message, NULL, -EINVAL);
1515 if (m->running_as != SYSTEMD_SYSTEM) {
1516 dbus_set_error(&error, BUS_ERROR_NOT_SUPPORTED, "Switching root is only supported for system managers.");
1517 return bus_send_error_reply(connection, message, &error, -ENOTSUP);
1521 if (isempty(switch_root_init)) {
1522 good = path_is_os_tree(switch_root);
1524 log_error("Not switching root: %s does not seem to be an OS tree. /etc/os-release is missing.", switch_root);
1527 _cleanup_free_ char *p = NULL;
1529 p = strjoin(switch_root, "/", switch_root_init, NULL);
1533 good = access(p, X_OK) >= 0;
1535 log_error("Not switching root: cannot execute new init %s", p);
1538 return bus_send_error_reply(connection, message, NULL, -EINVAL);
1540 u = strdup(switch_root);
1544 if (!isempty(switch_root_init)) {
1545 v = strdup(switch_root_init);
1553 free(m->switch_root);
1554 free(m->switch_root_init);
1556 m->switch_root_init = v;
1558 reply = dbus_message_new_method_return(message);
1562 m->exit_code = MANAGER_SWITCH_ROOT;
1564 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "SetEnvironment")) {
1565 _cleanup_strv_free_ char **l = NULL;
1568 SELINUX_ACCESS_CHECK(connection, message, "reboot");
1570 r = bus_parse_strv(message, &l);
1574 return bus_send_error_reply(connection, message, NULL, r);
1575 if (!strv_env_is_valid(l))
1576 return bus_send_error_reply(connection, message, NULL, -EINVAL);
1578 e = strv_env_merge(2, m->environment, l);
1582 reply = dbus_message_new_method_return(message);
1588 strv_free(m->environment);
1591 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "UnsetEnvironment")) {
1592 _cleanup_strv_free_ char **l = NULL;
1595 SELINUX_ACCESS_CHECK(connection, message, "reboot");
1597 r = bus_parse_strv(message, &l);
1601 return bus_send_error_reply(connection, message, NULL, r);
1602 if (!strv_env_name_or_assignment_is_valid(l))
1603 return bus_send_error_reply(connection, message, NULL, -EINVAL);
1605 e = strv_env_delete(m->environment, 1, l);
1609 reply = dbus_message_new_method_return(message);
1615 strv_free(m->environment);
1618 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "UnsetAndSetEnvironment")) {
1619 _cleanup_strv_free_ char **l_set = NULL, **l_unset = NULL, **e = NULL;
1621 DBusMessageIter iter;
1623 SELINUX_ACCESS_CHECK(connection, message, "reboot");
1625 if (!dbus_message_iter_init(message, &iter))
1628 r = bus_parse_strv_iter(&iter, &l_unset);
1632 return bus_send_error_reply(connection, message, NULL, r);
1633 if (!strv_env_name_or_assignment_is_valid(l_unset))
1634 return bus_send_error_reply(connection, message, NULL, -EINVAL);
1636 if (!dbus_message_iter_next(&iter))
1637 return bus_send_error_reply(connection, message, NULL, -EINVAL);
1639 r = bus_parse_strv_iter(&iter, &l_set);
1643 return bus_send_error_reply(connection, message, NULL, r);
1644 if (!strv_env_is_valid(l_set))
1645 return bus_send_error_reply(connection, message, NULL, -EINVAL);
1647 e = strv_env_delete(m->environment, 1, l_unset);
1651 f = strv_env_merge(2, e, l_set);
1655 reply = dbus_message_new_method_return(message);
1661 strv_free(m->environment);
1663 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ListUnitFiles")) {
1664 DBusMessageIter iter, sub, sub2;
1669 SELINUX_ACCESS_CHECK(connection, message, "status");
1671 reply = dbus_message_new_method_return(message);
1675 h = hashmap_new(string_hash_func, string_compare_func);
1679 r = unit_file_get_list(m->running_as == SYSTEMD_SYSTEM ? UNIT_FILE_SYSTEM : UNIT_FILE_USER, NULL, h);
1681 unit_file_list_free(h);
1682 return bus_send_error_reply(connection, message, NULL, r);
1685 dbus_message_iter_init_append(reply, &iter);
1687 if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "(ss)", &sub)) {
1688 unit_file_list_free(h);
1692 HASHMAP_FOREACH(item, h, i) {
1695 state = unit_file_state_to_string(item->state);
1698 if (!dbus_message_iter_open_container(&sub, DBUS_TYPE_STRUCT, NULL, &sub2) ||
1699 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &item->path) ||
1700 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &state) ||
1701 !dbus_message_iter_close_container(&sub, &sub2)) {
1702 unit_file_list_free(h);
1707 unit_file_list_free(h);
1709 if (!dbus_message_iter_close_container(&iter, &sub))
1712 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "GetUnitFileState")) {
1714 UnitFileState state;
1717 SELINUX_ACCESS_CHECK(connection, message, "status");
1719 if (!dbus_message_get_args(
1722 DBUS_TYPE_STRING, &name,
1724 return bus_send_error_reply(connection, message, &error, -EINVAL);
1726 state = unit_file_get_state(m->running_as == SYSTEMD_SYSTEM ? UNIT_FILE_SYSTEM : UNIT_FILE_USER, NULL, name);
1728 return bus_send_error_reply(connection, message, NULL, state);
1730 s = unit_file_state_to_string(state);
1733 reply = dbus_message_new_method_return(message);
1737 if (!dbus_message_append_args(
1739 DBUS_TYPE_STRING, &s,
1742 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "EnableUnitFiles") ||
1743 dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ReenableUnitFiles") ||
1744 dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "LinkUnitFiles") ||
1745 dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "PresetUnitFiles") ||
1746 dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "MaskUnitFiles") ||
1747 dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "SetDefaultTarget")) {
1750 DBusMessageIter iter;
1751 UnitFileScope scope = m->running_as == SYSTEMD_SYSTEM ? UNIT_FILE_SYSTEM : UNIT_FILE_USER;
1752 UnitFileChange *changes = NULL;
1753 unsigned n_changes = 0;
1754 dbus_bool_t runtime, force;
1755 int carries_install_info = -1;
1757 SELINUX_ACCESS_CHECK(connection, message, streq(member, "MaskUnitFiles") ? "disable" : "enable");
1759 if (!dbus_message_iter_init(message, &iter))
1762 r = bus_parse_strv_iter(&iter, &l);
1767 return bus_send_error_reply(connection, message, NULL, r);
1770 if (!dbus_message_iter_next(&iter) ||
1771 bus_iter_get_basic_and_next(&iter, DBUS_TYPE_BOOLEAN, &runtime, true) < 0 ||
1772 bus_iter_get_basic_and_next(&iter, DBUS_TYPE_BOOLEAN, &force, false) < 0) {
1774 return bus_send_error_reply(connection, message, NULL, -EIO);
1777 if (streq(member, "EnableUnitFiles")) {
1778 r = unit_file_enable(scope, runtime, NULL, l, force, &changes, &n_changes);
1779 carries_install_info = r;
1780 } else if (streq(member, "ReenableUnitFiles")) {
1781 r = unit_file_reenable(scope, runtime, NULL, l, force, &changes, &n_changes);
1782 carries_install_info = r;
1783 } else if (streq(member, "LinkUnitFiles"))
1784 r = unit_file_link(scope, runtime, NULL, l, force, &changes, &n_changes);
1785 else if (streq(member, "PresetUnitFiles")) {
1786 r = unit_file_preset(scope, runtime, NULL, l, force, &changes, &n_changes);
1787 carries_install_info = r;
1788 } else if (streq(member, "MaskUnitFiles"))
1789 r = unit_file_mask(scope, runtime, NULL, l, force, &changes, &n_changes);
1790 else if (streq(member, "SetDefaultTarget"))
1791 r = unit_file_set_default(scope, NULL, l[0], &changes, &n_changes);
1793 assert_not_reached("Uh? Wrong method");
1796 bus_manager_send_unit_files_changed(m);
1799 unit_file_changes_free(changes, n_changes);
1800 return bus_send_error_reply(connection, message, NULL, r);
1803 reply = message_from_file_changes(message, changes, n_changes, carries_install_info);
1804 unit_file_changes_free(changes, n_changes);
1809 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "DisableUnitFiles") ||
1810 dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "UnmaskUnitFiles")) {
1813 DBusMessageIter iter;
1814 UnitFileScope scope = m->running_as == SYSTEMD_SYSTEM ? UNIT_FILE_SYSTEM : UNIT_FILE_USER;
1815 UnitFileChange *changes = NULL;
1816 unsigned n_changes = 0;
1817 dbus_bool_t runtime;
1819 SELINUX_ACCESS_CHECK(connection, message, streq(member, "UnmaskUnitFiles") ? "enable" : "disable");
1821 if (!dbus_message_iter_init(message, &iter))
1824 r = bus_parse_strv_iter(&iter, &l);
1829 return bus_send_error_reply(connection, message, NULL, r);
1832 if (!dbus_message_iter_next(&iter) ||
1833 bus_iter_get_basic_and_next(&iter, DBUS_TYPE_BOOLEAN, &runtime, false) < 0) {
1835 return bus_send_error_reply(connection, message, NULL, -EIO);
1838 if (streq(member, "DisableUnitFiles"))
1839 r = unit_file_disable(scope, runtime, NULL, l, &changes, &n_changes);
1840 else if (streq(member, "UnmaskUnitFiles"))
1841 r = unit_file_unmask(scope, runtime, NULL, l, &changes, &n_changes);
1843 assert_not_reached("Uh? Wrong method");
1846 bus_manager_send_unit_files_changed(m);
1849 unit_file_changes_free(changes, n_changes);
1850 return bus_send_error_reply(connection, message, NULL, r);
1853 reply = message_from_file_changes(message, changes, n_changes, -1);
1854 unit_file_changes_free(changes, n_changes);
1859 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "GetDefaultTarget")) {
1860 UnitFileScope scope = m->running_as == SYSTEMD_SYSTEM ? UNIT_FILE_SYSTEM : UNIT_FILE_USER;
1861 _cleanup_free_ char *default_target = NULL;
1863 reply = dbus_message_new_method_return(message);
1867 r = unit_file_get_default(scope, NULL, &default_target);
1870 return bus_send_error_reply(connection, message, NULL, r);
1872 if (!dbus_message_append_args(reply, DBUS_TYPE_STRING, &default_target, DBUS_TYPE_INVALID)) {
1876 const BusBoundProperties bps[] = {
1877 { "org.freedesktop.systemd1.Manager", bus_systemd_properties, systemd_property_string },
1878 { "org.freedesktop.systemd1.Manager", bus_manager_properties, m },
1882 SELINUX_ACCESS_CHECK(connection, message, "status");
1884 return bus_default_message_handler(connection, message, NULL, INTERFACES_LIST, bps);
1887 if (job_type != _JOB_TYPE_INVALID) {
1888 const char *name, *smode, *old_name = NULL;
1893 if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "StartUnitReplace"))
1894 b = dbus_message_get_args(
1897 DBUS_TYPE_STRING, &old_name,
1898 DBUS_TYPE_STRING, &name,
1899 DBUS_TYPE_STRING, &smode,
1902 b = dbus_message_get_args(
1905 DBUS_TYPE_STRING, &name,
1906 DBUS_TYPE_STRING, &smode,
1909 return bus_send_error_reply(connection, message, &error, -EINVAL);
1912 u = manager_get_unit(m, old_name);
1913 if (!u || !u->job || u->job->type != JOB_START) {
1914 dbus_set_error(&error, BUS_ERROR_NO_SUCH_JOB, "No job queued for unit %s", old_name);
1915 return bus_send_error_reply(connection, message, &error, -ENOENT);
1919 mode = job_mode_from_string(smode);
1921 dbus_set_error(&error, BUS_ERROR_INVALID_JOB_MODE, "Job mode %s is invalid.", smode);
1922 return bus_send_error_reply(connection, message, &error, -EINVAL);
1925 r = manager_load_unit(m, name, NULL, &error, &u);
1927 return bus_send_error_reply(connection, message, &error, r);
1929 return bus_unit_queue_job(connection, message, u, job_type, mode, reload_if_possible);
1933 if (!bus_maybe_send_reply(connection, message, reply))
1936 return DBUS_HANDLER_RESULT_HANDLED;
1939 dbus_error_free(&error);
1941 return DBUS_HANDLER_RESULT_NEED_MEMORY;
1944 const DBusObjectPathVTable bus_manager_vtable = {
1945 .message_function = bus_manager_message_handler