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=\"UnitsLoadStartTimestamp\" type=\"t\" access=\"read\"/>\n" \
290 " <property name=\"UnitsLoadStartTimestampMonotonic\" type=\"t\" access=\"read\"/>\n" \
291 " <property name=\"UnitsLoadFinishTimestamp\" type=\"t\" access=\"read\"/>\n" \
292 " <property name=\"UnitsLoadFinishTimestampMonotonic\" type=\"t\" access=\"read\"/>\n" \
293 " <property name=\"LogLevel\" type=\"s\" access=\"readwrite\"/>\n" \
294 " <property name=\"LogTarget\" type=\"s\" access=\"readwrite\"/>\n" \
295 " <property name=\"NNames\" type=\"u\" access=\"read\"/>\n" \
296 " <property name=\"NJobs\" type=\"u\" access=\"read\"/>\n" \
297 " <property name=\"NInstalledJobs\" type=\"u\" access=\"read\"/>\n" \
298 " <property name=\"NFailedJobs\" type=\"u\" access=\"read\"/>\n" \
299 " <property name=\"Progress\" type=\"d\" access=\"read\"/>\n" \
300 " <property name=\"Environment\" type=\"as\" access=\"read\"/>\n" \
301 " <property name=\"ConfirmSpawn\" type=\"b\" access=\"read\"/>\n" \
302 " <property name=\"ShowStatus\" type=\"b\" access=\"read\"/>\n" \
303 " <property name=\"UnitPath\" type=\"as\" access=\"read\"/>\n" \
304 " <property name=\"DefaultControllers\" type=\"as\" access=\"read\"/>\n" \
305 " <property name=\"DefaultStandardOutput\" type=\"s\" access=\"read\"/>\n" \
306 " <property name=\"DefaultStandardError\" type=\"s\" access=\"read\"/>\n" \
307 " <property name=\"RuntimeWatchdogUSec\" type=\"t\" access=\"readwrite\"/>\n" \
308 " <property name=\"ShutdownWatchdogUSec\" type=\"t\" access=\"readwrite\"/>\n" \
309 " <property name=\"Virtualization\" type=\"s\" access=\"read\"/>\n"
311 #define BUS_MANAGER_INTERFACE_END \
314 #define BUS_MANAGER_INTERFACE \
315 BUS_MANAGER_INTERFACE_BEGIN \
316 BUS_MANAGER_INTERFACE_METHODS \
317 BUS_MANAGER_INTERFACE_SIGNALS \
318 BUS_MANAGER_INTERFACE_PROPERTIES_GENERAL \
319 BUS_MANAGER_INTERFACE_END
321 #define INTROSPECTION_BEGIN \
322 DBUS_INTROSPECT_1_0_XML_DOCTYPE_DECL_NODE \
324 BUS_MANAGER_INTERFACE \
325 BUS_PROPERTIES_INTERFACE \
327 BUS_INTROSPECTABLE_INTERFACE
329 #define INTROSPECTION_END \
332 #define INTERFACES_LIST \
333 BUS_GENERIC_INTERFACES_LIST \
334 "org.freedesktop.systemd1.Manager\0"
336 const char bus_manager_interface[] _introspect_("Manager") = BUS_MANAGER_INTERFACE;
338 static DEFINE_BUS_PROPERTY_APPEND_ENUM(bus_manager_append_exec_output, exec_output, ExecOutput);
340 static int bus_manager_append_tainted(DBusMessageIter *i, const char *property, void *data) {
343 char buf[LINE_MAX] = "", *e = buf, *p = NULL;
350 e = stpcpy(e, "split-usr:");
352 if (readlink_malloc("/etc/mtab", &p) < 0)
353 e = stpcpy(e, "mtab-not-symlink:");
357 if (access("/proc/cgroups", F_OK) < 0)
358 e = stpcpy(e, "cgroups-missing:");
360 if (hwclock_is_localtime() > 0)
361 e = stpcpy(e, "local-hwclock:");
363 /* remove the last ':' */
369 if (!dbus_message_iter_append_basic(i, DBUS_TYPE_STRING, &t))
375 static int bus_manager_append_log_target(DBusMessageIter *i, const char *property, void *data) {
381 t = log_target_to_string(log_get_target());
383 if (!dbus_message_iter_append_basic(i, DBUS_TYPE_STRING, &t))
389 static int bus_manager_set_log_target(DBusMessageIter *i, const char *property, void *data) {
395 dbus_message_iter_get_basic(i, &t);
397 return log_set_target_from_string(t);
400 static int bus_manager_append_log_level(DBusMessageIter *i, const char *property, void *data) {
407 r = log_level_to_string_alloc(log_get_max_level(), &t);
411 if (!dbus_message_iter_append_basic(i, DBUS_TYPE_STRING, &t))
418 static int bus_manager_set_log_level(DBusMessageIter *i, const char *property, void *data) {
424 dbus_message_iter_get_basic(i, &t);
426 return log_set_max_level_from_string(t);
429 static int bus_manager_append_n_names(DBusMessageIter *i, const char *property, void *data) {
437 u = hashmap_size(m->units);
439 if (!dbus_message_iter_append_basic(i, DBUS_TYPE_UINT32, &u))
445 static int bus_manager_append_n_jobs(DBusMessageIter *i, const char *property, void *data) {
453 u = hashmap_size(m->jobs);
455 if (!dbus_message_iter_append_basic(i, DBUS_TYPE_UINT32, &u))
461 static int bus_manager_append_progress(DBusMessageIter *i, const char *property, void *data) {
469 if (dual_timestamp_is_set(&m->finish_timestamp))
472 d = 1.0 - ((double) hashmap_size(m->jobs) / (double) m->n_installed_jobs);
474 if (!dbus_message_iter_append_basic(i, DBUS_TYPE_DOUBLE, &d))
480 static int bus_manager_append_virt(DBusMessageIter *i, const char *property, void *data) {
488 detect_virtualization(&id);
490 if (!dbus_message_iter_append_basic(i, DBUS_TYPE_STRING, &id))
496 static DBusMessage *message_from_file_changes(
498 UnitFileChange *changes,
500 int carries_install_info) {
502 DBusMessageIter iter, sub, sub2;
506 reply = dbus_message_new_method_return(m);
510 dbus_message_iter_init_append(reply, &iter);
512 if (carries_install_info >= 0) {
515 b = !!carries_install_info;
516 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &b))
520 if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "(sss)", &sub))
523 for (i = 0; i < n_changes; i++) {
524 const char *type, *path, *source;
526 type = unit_file_change_type_to_string(changes[i].type);
527 path = strempty(changes[i].path);
528 source = strempty(changes[i].source);
530 if (!dbus_message_iter_open_container(&sub, DBUS_TYPE_STRUCT, NULL, &sub2) ||
531 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &type) ||
532 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &path) ||
533 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &source) ||
534 !dbus_message_iter_close_container(&sub, &sub2))
538 if (!dbus_message_iter_close_container(&iter, &sub))
544 dbus_message_unref(reply);
548 static int bus_manager_send_unit_files_changed(Manager *m) {
552 s = dbus_message_new_signal("/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", "UnitFilesChanged");
556 r = bus_broadcast(m, s);
557 dbus_message_unref(s);
562 static int bus_manager_set_runtime_watchdog_usec(DBusMessageIter *i, const char *property, void *data) {
568 dbus_message_iter_get_basic(i, t);
570 return watchdog_set_timeout(t);
573 static const char systemd_property_string[] =
577 static const BusProperty bus_systemd_properties[] = {
578 { "Version", bus_property_append_string, "s", 0 },
579 { "Features", bus_property_append_string, "s", sizeof(PACKAGE_STRING) },
583 static const BusProperty bus_manager_properties[] = {
584 { "Tainted", bus_manager_append_tainted, "s", 0 },
585 { "FirmwareTimestamp", bus_property_append_uint64, "t", offsetof(Manager, firmware_timestamp.realtime) },
586 { "FirmwareTimestampMonotonic", bus_property_append_uint64, "t", offsetof(Manager, firmware_timestamp.monotonic) },
587 { "LoaderTimestamp", bus_property_append_uint64, "t", offsetof(Manager, loader_timestamp.realtime) },
588 { "LoaderTimestampMonotonic", bus_property_append_uint64, "t", offsetof(Manager, loader_timestamp.monotonic) },
589 { "KernelTimestamp", bus_property_append_uint64, "t", offsetof(Manager, kernel_timestamp.realtime) },
590 { "KernelTimestampMonotonic", bus_property_append_uint64, "t", offsetof(Manager, kernel_timestamp.monotonic) },
591 { "InitRDTimestamp", bus_property_append_uint64, "t", offsetof(Manager, initrd_timestamp.realtime) },
592 { "InitRDTimestampMonotonic", bus_property_append_uint64, "t", offsetof(Manager, initrd_timestamp.monotonic) },
593 { "UserspaceTimestamp", bus_property_append_uint64, "t", offsetof(Manager, userspace_timestamp.realtime) },
594 { "UserspaceTimestampMonotonic", bus_property_append_uint64, "t", offsetof(Manager, userspace_timestamp.monotonic) },
595 { "FinishTimestamp", bus_property_append_uint64, "t", offsetof(Manager, finish_timestamp.realtime) },
596 { "FinishTimestampMonotonic", bus_property_append_uint64, "t", offsetof(Manager, finish_timestamp.monotonic) },
597 { "GeneratorsStartTimestamp", bus_property_append_uint64, "t", offsetof(Manager, generators_start_timestamp.realtime) },
598 { "GeneratorsStartTimestampMonotonic", bus_property_append_uint64, "t", offsetof(Manager, generators_start_timestamp.monotonic) },
599 { "GeneratorsFinishTimestamp", bus_property_append_uint64, "t", offsetof(Manager, generators_finish_timestamp.realtime) },
600 { "GeneratorsFinishTimestampMonotonic", bus_property_append_uint64, "t", offsetof(Manager, generators_finish_timestamp.monotonic) },
601 { "UnitsLoadStartTimestamp", bus_property_append_uint64, "t", offsetof(Manager, unitsload_start_timestamp.realtime) },
602 { "UnitsLoadStartTimestampMonotonic", bus_property_append_uint64, "t", offsetof(Manager, unitsload_start_timestamp.monotonic) },
603 { "UnitsLoadFinishTimestamp", bus_property_append_uint64, "t", offsetof(Manager, unitsload_finish_timestamp.realtime) },
604 { "UnitsLoadFinishTimestampMonotonic", bus_property_append_uint64, "t", offsetof(Manager, unitsload_finish_timestamp.monotonic) },
605 { "LogLevel", bus_manager_append_log_level, "s", 0, false, bus_manager_set_log_level },
606 { "LogTarget", bus_manager_append_log_target, "s", 0, false, bus_manager_set_log_target },
607 { "NNames", bus_manager_append_n_names, "u", 0 },
608 { "NJobs", bus_manager_append_n_jobs, "u", 0 },
609 { "NInstalledJobs", bus_property_append_uint32, "u", offsetof(Manager, n_installed_jobs) },
610 { "NFailedJobs", bus_property_append_uint32, "u", offsetof(Manager, n_failed_jobs) },
611 { "Progress", bus_manager_append_progress, "d", 0 },
612 { "Environment", bus_property_append_strv, "as", offsetof(Manager, environment), true },
613 { "ConfirmSpawn", bus_property_append_bool, "b", offsetof(Manager, confirm_spawn) },
614 { "ShowStatus", bus_property_append_bool, "b", offsetof(Manager, show_status) },
615 { "UnitPath", bus_property_append_strv, "as", offsetof(Manager, lookup_paths.unit_path), true },
616 { "DefaultControllers", bus_property_append_strv, "as", offsetof(Manager, default_controllers), true },
617 { "DefaultStandardOutput", bus_manager_append_exec_output, "s", offsetof(Manager, default_std_output) },
618 { "DefaultStandardError", bus_manager_append_exec_output, "s", offsetof(Manager, default_std_error) },
619 { "RuntimeWatchdogUSec", bus_property_append_usec, "t", offsetof(Manager, runtime_watchdog), false, bus_manager_set_runtime_watchdog_usec },
620 { "ShutdownWatchdogUSec", bus_property_append_usec, "t", offsetof(Manager, shutdown_watchdog), false, bus_property_set_usec },
621 { "Virtualization", bus_manager_append_virt, "s", 0, },
625 static DBusHandlerResult bus_manager_message_handler(DBusConnection *connection, DBusMessage *message, void *data) {
626 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
627 _cleanup_free_ char * path = NULL;
631 JobType job_type = _JOB_TYPE_INVALID;
632 bool reload_if_possible = false;
639 dbus_error_init(&error);
641 member = dbus_message_get_member(message);
643 if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "GetUnit")) {
647 if (!dbus_message_get_args(
650 DBUS_TYPE_STRING, &name,
652 return bus_send_error_reply(connection, message, &error, -EINVAL);
654 u = manager_get_unit(m, name);
656 dbus_set_error(&error, BUS_ERROR_NO_SUCH_UNIT, "Unit %s is not loaded.", name);
657 return bus_send_error_reply(connection, message, &error, -ENOENT);
660 SELINUX_UNIT_ACCESS_CHECK(u, connection, message, "status");
662 reply = dbus_message_new_method_return(message);
666 path = unit_dbus_path(u);
670 if (!dbus_message_append_args(
672 DBUS_TYPE_OBJECT_PATH, &path,
675 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "GetUnitByPID")) {
679 if (!dbus_message_get_args(
682 DBUS_TYPE_UINT32, &pid,
684 return bus_send_error_reply(connection, message, &error, -EINVAL);
686 u = cgroup_unit_by_pid(m, (pid_t) pid);
688 dbus_set_error(&error, BUS_ERROR_NO_SUCH_UNIT, "No unit for PID %lu is loaded.", (unsigned long) pid);
689 return bus_send_error_reply(connection, message, &error, -ENOENT);
692 SELINUX_UNIT_ACCESS_CHECK(u, connection, message, "status");
694 reply = dbus_message_new_method_return(message);
698 path = unit_dbus_path(u);
702 if (!dbus_message_append_args(
704 DBUS_TYPE_OBJECT_PATH, &path,
707 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "LoadUnit")) {
711 if (!dbus_message_get_args(
714 DBUS_TYPE_STRING, &name,
716 return bus_send_error_reply(connection, message, &error, -EINVAL);
718 r = manager_load_unit(m, name, NULL, &error, &u);
720 return bus_send_error_reply(connection, message, &error, r);
722 SELINUX_UNIT_ACCESS_CHECK(u, connection, message, "status");
724 reply = dbus_message_new_method_return(message);
728 path = unit_dbus_path(u);
732 if (!dbus_message_append_args(
734 DBUS_TYPE_OBJECT_PATH, &path,
738 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "StartUnit"))
739 job_type = JOB_START;
740 else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "StartUnitReplace"))
741 job_type = JOB_START;
742 else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "StopUnit"))
744 else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ReloadUnit"))
745 job_type = JOB_RELOAD;
746 else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "RestartUnit"))
747 job_type = JOB_RESTART;
748 else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "TryRestartUnit"))
749 job_type = JOB_TRY_RESTART;
750 else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ReloadOrRestartUnit")) {
751 reload_if_possible = true;
752 job_type = JOB_RESTART;
753 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ReloadOrTryRestartUnit")) {
754 reload_if_possible = true;
755 job_type = JOB_TRY_RESTART;
756 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "KillUnit")) {
757 const char *name, *swho;
762 if (!dbus_message_get_args(
765 DBUS_TYPE_STRING, &name,
766 DBUS_TYPE_STRING, &swho,
767 DBUS_TYPE_INT32, &signo,
769 return bus_send_error_reply(connection, message, &error, -EINVAL);
774 who = kill_who_from_string(swho);
776 return bus_send_error_reply(connection, message, &error, -EINVAL);
779 if (signo <= 0 || signo >= _NSIG)
780 return bus_send_error_reply(connection, message, &error, -EINVAL);
782 u = manager_get_unit(m, name);
784 dbus_set_error(&error, BUS_ERROR_NO_SUCH_UNIT, "Unit %s is not loaded.", name);
785 return bus_send_error_reply(connection, message, &error, -ENOENT);
788 SELINUX_UNIT_ACCESS_CHECK(u, connection, message, "stop");
790 r = unit_kill(u, who, signo, &error);
792 return bus_send_error_reply(connection, message, &error, r);
794 reply = dbus_message_new_method_return(message);
798 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "GetJob")) {
802 if (!dbus_message_get_args(
805 DBUS_TYPE_UINT32, &id,
807 return bus_send_error_reply(connection, message, &error, -EINVAL);
809 j = manager_get_job(m, id);
811 dbus_set_error(&error, BUS_ERROR_NO_SUCH_JOB, "Job %u does not exist.", (unsigned) id);
812 return bus_send_error_reply(connection, message, &error, -ENOENT);
815 SELINUX_UNIT_ACCESS_CHECK(j->unit, connection, message, "status");
817 reply = dbus_message_new_method_return(message);
821 path = job_dbus_path(j);
825 if (!dbus_message_append_args(
827 DBUS_TYPE_OBJECT_PATH, &path,
831 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "CancelJob")) {
835 if (!dbus_message_get_args(
838 DBUS_TYPE_UINT32, &id,
840 return bus_send_error_reply(connection, message, &error, -EINVAL);
842 j = manager_get_job(m, id);
844 dbus_set_error(&error, BUS_ERROR_NO_SUCH_JOB, "Job %u does not exist.", (unsigned) id);
845 return bus_send_error_reply(connection, message, &error, -ENOENT);
848 SELINUX_UNIT_ACCESS_CHECK(j->unit, connection, message, "stop");
849 job_finish_and_invalidate(j, JOB_CANCELED, true);
851 reply = dbus_message_new_method_return(message);
855 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ClearJobs")) {
857 SELINUX_ACCESS_CHECK(connection, message, "reboot");
858 manager_clear_jobs(m);
860 reply = dbus_message_new_method_return(message);
864 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ResetFailed")) {
866 SELINUX_ACCESS_CHECK(connection, message, "reload");
868 manager_reset_failed(m);
870 reply = dbus_message_new_method_return(message);
874 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ResetFailedUnit")) {
878 if (!dbus_message_get_args(
881 DBUS_TYPE_STRING, &name,
883 return bus_send_error_reply(connection, message, &error, -EINVAL);
885 u = manager_get_unit(m, name);
887 dbus_set_error(&error, BUS_ERROR_NO_SUCH_UNIT, "Unit %s is not loaded.", name);
888 return bus_send_error_reply(connection, message, &error, -ENOENT);
891 SELINUX_UNIT_ACCESS_CHECK(u, connection, message, "reload");
893 unit_reset_failed(u);
895 reply = dbus_message_new_method_return(message);
899 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "SetUnitControlGroup")) {
902 DBusMessageIter iter;
904 if (!dbus_message_iter_init(message, &iter))
907 r = bus_iter_get_basic_and_next(&iter, DBUS_TYPE_STRING, &name, true);
909 return bus_send_error_reply(connection, message, NULL, r);
911 u = manager_get_unit(m, name);
913 dbus_set_error(&error, BUS_ERROR_NO_SUCH_UNIT, "Unit %s is not loaded.", name);
914 return bus_send_error_reply(connection, message, &error, -ENOENT);
917 SELINUX_UNIT_ACCESS_CHECK(u, connection, message, "start");
919 r = bus_unit_cgroup_set(u, &iter);
921 return bus_send_error_reply(connection, message, NULL, r);
923 reply = dbus_message_new_method_return(message);
927 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "UnsetUnitControlGroup")) {
930 DBusMessageIter iter;
932 if (!dbus_message_iter_init(message, &iter))
935 r = bus_iter_get_basic_and_next(&iter, DBUS_TYPE_STRING, &name, true);
937 return bus_send_error_reply(connection, message, NULL, r);
939 u = manager_get_unit(m, name);
941 dbus_set_error(&error, BUS_ERROR_NO_SUCH_UNIT, "Unit %s is not loaded.", name);
942 return bus_send_error_reply(connection, message, &error, -ENOENT);
945 SELINUX_UNIT_ACCESS_CHECK(u, connection, message, "stop");
947 r = bus_unit_cgroup_unset(u, &iter);
949 return bus_send_error_reply(connection, message, NULL, r);
951 reply = dbus_message_new_method_return(message);
955 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "SetUnitControlGroupAttribute")) {
958 DBusMessageIter iter;
960 if (!dbus_message_iter_init(message, &iter))
963 r = bus_iter_get_basic_and_next(&iter, DBUS_TYPE_STRING, &name, true);
965 return bus_send_error_reply(connection, message, NULL, r);
967 u = manager_get_unit(m, name);
969 dbus_set_error(&error, BUS_ERROR_NO_SUCH_UNIT, "Unit %s is not loaded.", name);
970 return bus_send_error_reply(connection, message, &error, -ENOENT);
973 SELINUX_UNIT_ACCESS_CHECK(u, connection, message, "start");
975 r = bus_unit_cgroup_attribute_set(u, &iter);
977 return bus_send_error_reply(connection, message, NULL, r);
979 reply = dbus_message_new_method_return(message);
983 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "UnsetUnitControlGroupAttribute")) {
986 DBusMessageIter iter;
988 if (!dbus_message_iter_init(message, &iter))
991 r = bus_iter_get_basic_and_next(&iter, DBUS_TYPE_STRING, &name, true);
993 return bus_send_error_reply(connection, message, NULL, r);
995 u = manager_get_unit(m, name);
997 dbus_set_error(&error, BUS_ERROR_NO_SUCH_UNIT, "Unit %s is not loaded.", name);
998 return bus_send_error_reply(connection, message, &error, -ENOENT);
1001 SELINUX_UNIT_ACCESS_CHECK(u, connection, message, "stop");
1003 r = bus_unit_cgroup_attribute_unset(u, &iter);
1005 return bus_send_error_reply(connection, message, NULL, r);
1007 reply = dbus_message_new_method_return(message);
1011 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "GetUnitControlGroupAttribute")) {
1014 DBusMessageIter iter;
1015 _cleanup_strv_free_ char **list = NULL;
1017 if (!dbus_message_iter_init(message, &iter))
1020 r = bus_iter_get_basic_and_next(&iter, DBUS_TYPE_STRING, &name, true);
1022 return bus_send_error_reply(connection, message, NULL, r);
1024 u = manager_get_unit(m, name);
1026 dbus_set_error(&error, BUS_ERROR_NO_SUCH_UNIT, "Unit %s is not loaded.", name);
1027 return bus_send_error_reply(connection, message, &error, -ENOENT);
1030 SELINUX_UNIT_ACCESS_CHECK(u, connection, message, "status");
1032 r = bus_unit_cgroup_attribute_get(u, &iter, &list);
1034 return bus_send_error_reply(connection, message, NULL, r);
1036 reply = dbus_message_new_method_return(message);
1040 dbus_message_iter_init_append(reply, &iter);
1041 if (bus_append_strv_iter(&iter, list) < 0)
1044 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ListUnits")) {
1045 DBusMessageIter iter, sub;
1050 SELINUX_ACCESS_CHECK(connection, message, "status");
1052 reply = dbus_message_new_method_return(message);
1056 dbus_message_iter_init_append(reply, &iter);
1058 if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "(ssssssouso)", &sub))
1061 HASHMAP_FOREACH_KEY(u, k, m->units, i) {
1062 char *u_path, *j_path;
1063 const char *description, *load_state, *active_state, *sub_state, *sjob_type, *following;
1064 DBusMessageIter sub2;
1071 if (!dbus_message_iter_open_container(&sub, DBUS_TYPE_STRUCT, NULL, &sub2))
1074 description = unit_description(u);
1075 load_state = unit_load_state_to_string(u->load_state);
1076 active_state = unit_active_state_to_string(unit_active_state(u));
1077 sub_state = unit_sub_state_to_string(u);
1079 f = unit_following(u);
1080 following = f ? f->id : "";
1082 u_path = unit_dbus_path(u);
1087 job_id = (uint32_t) u->job->id;
1089 if (!(j_path = job_dbus_path(u->job))) {
1094 sjob_type = job_type_to_string(u->job->type);
1101 if (!dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &u->id) ||
1102 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &description) ||
1103 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &load_state) ||
1104 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &active_state) ||
1105 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &sub_state) ||
1106 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &following) ||
1107 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_OBJECT_PATH, &u_path) ||
1108 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_UINT32, &job_id) ||
1109 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &sjob_type) ||
1110 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_OBJECT_PATH, &j_path)) {
1121 if (!dbus_message_iter_close_container(&sub, &sub2))
1125 if (!dbus_message_iter_close_container(&iter, &sub))
1128 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ListJobs")) {
1129 DBusMessageIter iter, sub;
1133 SELINUX_ACCESS_CHECK(connection, message, "status");
1135 reply = dbus_message_new_method_return(message);
1139 dbus_message_iter_init_append(reply, &iter);
1141 if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "(usssoo)", &sub))
1144 HASHMAP_FOREACH(j, m->jobs, i) {
1145 char *u_path, *j_path;
1146 const char *state, *type;
1148 DBusMessageIter sub2;
1150 if (!dbus_message_iter_open_container(&sub, DBUS_TYPE_STRUCT, NULL, &sub2))
1153 id = (uint32_t) j->id;
1154 state = job_state_to_string(j->state);
1155 type = job_type_to_string(j->type);
1157 j_path = job_dbus_path(j);
1161 u_path = unit_dbus_path(j->unit);
1167 if (!dbus_message_iter_append_basic(&sub2, DBUS_TYPE_UINT32, &id) ||
1168 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &j->unit->id) ||
1169 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &type) ||
1170 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &state) ||
1171 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_OBJECT_PATH, &j_path) ||
1172 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_OBJECT_PATH, &u_path)) {
1181 if (!dbus_message_iter_close_container(&sub, &sub2))
1185 if (!dbus_message_iter_close_container(&iter, &sub))
1188 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "Subscribe")) {
1192 SELINUX_ACCESS_CHECK(connection, message, "status");
1194 s = BUS_CONNECTION_SUBSCRIBED(m, connection);
1196 s = set_new(string_hash_func, string_compare_func);
1200 if (!dbus_connection_set_data(connection, m->subscribed_data_slot, s, NULL)) {
1206 client = strdup(bus_message_get_sender_with_fallback(message));
1210 r = set_consume(s, client);
1212 return bus_send_error_reply(connection, message, NULL, r);
1214 reply = dbus_message_new_method_return(message);
1218 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "Unsubscribe")) {
1221 SELINUX_ACCESS_CHECK(connection, message, "status");
1223 client = set_remove(BUS_CONNECTION_SUBSCRIBED(m, connection), (char*) bus_message_get_sender_with_fallback(message));
1225 dbus_set_error(&error, BUS_ERROR_NOT_SUBSCRIBED, "Client is not subscribed.");
1226 return bus_send_error_reply(connection, message, &error, -ENOENT);
1231 reply = dbus_message_new_method_return(message);
1235 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "Dump")) {
1240 SELINUX_ACCESS_CHECK(connection, message, "status");
1242 reply = dbus_message_new_method_return(message);
1246 f = open_memstream(&dump, &size);
1250 manager_dump_units(m, f, NULL);
1251 manager_dump_jobs(m, f, NULL);
1261 if (!dbus_message_append_args(reply, DBUS_TYPE_STRING, &dump, DBUS_TYPE_INVALID)) {
1267 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "CreateSnapshot")) {
1269 dbus_bool_t cleanup;
1272 SELINUX_ACCESS_CHECK(connection, message, "start");
1274 if (!dbus_message_get_args(
1277 DBUS_TYPE_STRING, &name,
1278 DBUS_TYPE_BOOLEAN, &cleanup,
1280 return bus_send_error_reply(connection, message, &error, -EINVAL);
1285 r = snapshot_create(m, name, cleanup, &error, &s);
1287 return bus_send_error_reply(connection, message, &error, r);
1289 reply = dbus_message_new_method_return(message);
1293 path = unit_dbus_path(UNIT(s));
1297 if (!dbus_message_append_args(
1299 DBUS_TYPE_OBJECT_PATH, &path,
1303 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "RemoveSnapshot")) {
1307 if (!dbus_message_get_args(
1310 DBUS_TYPE_STRING, &name,
1312 return bus_send_error_reply(connection, message, &error, -EINVAL);
1314 u = manager_get_unit(m, name);
1316 dbus_set_error(&error, BUS_ERROR_NO_SUCH_UNIT, "Unit %s does not exist.", name);
1317 return bus_send_error_reply(connection, message, &error, -ENOENT);
1320 if (u->type != UNIT_SNAPSHOT) {
1321 dbus_set_error(&error, BUS_ERROR_NO_SUCH_UNIT, "Unit %s is not a snapshot.", name);
1322 return bus_send_error_reply(connection, message, &error, -ENOENT);
1325 SELINUX_UNIT_ACCESS_CHECK(u, connection, message, "stop");
1326 snapshot_remove(SNAPSHOT(u));
1328 reply = dbus_message_new_method_return(message);
1332 } else if (dbus_message_is_method_call(message, "org.freedesktop.DBus.Introspectable", "Introspect")) {
1333 char *introspection = NULL;
1341 SELINUX_ACCESS_CHECK(connection, message, "status");
1343 reply = dbus_message_new_method_return(message);
1347 /* We roll our own introspection code here, instead of
1348 * relying on bus_default_message_handler() because we
1349 * need to generate our introspection string
1352 f = open_memstream(&introspection, &size);
1356 fputs(INTROSPECTION_BEGIN, f);
1358 HASHMAP_FOREACH_KEY(u, k, m->units, i) {
1364 p = bus_path_escape(k);
1367 free(introspection);
1371 fprintf(f, "<node name=\"unit/%s\"/>", p);
1375 HASHMAP_FOREACH(j, m->jobs, i)
1376 fprintf(f, "<node name=\"job/%lu\"/>", (unsigned long) j->id);
1378 fputs(INTROSPECTION_END, f);
1382 free(introspection);
1391 if (!dbus_message_append_args(reply, DBUS_TYPE_STRING, &introspection, DBUS_TYPE_INVALID)) {
1392 free(introspection);
1396 free(introspection);
1398 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "Reload")) {
1400 SELINUX_ACCESS_CHECK(connection, message, "reload");
1402 assert(!m->queued_message);
1404 /* Instead of sending the reply back right away, we
1405 * just remember that we need to and then send it
1406 * after the reload is finished. That way the caller
1407 * knows when the reload finished. */
1409 m->queued_message = dbus_message_new_method_return(message);
1410 if (!m->queued_message)
1413 m->queued_message_connection = connection;
1414 m->exit_code = MANAGER_RELOAD;
1416 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "Reexecute")) {
1418 SELINUX_ACCESS_CHECK(connection, message, "reload");
1420 /* We don't send a reply back here, the client should
1421 * just wait for us disconnecting. */
1423 m->exit_code = MANAGER_REEXECUTE;
1425 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "Exit")) {
1427 SELINUX_ACCESS_CHECK(connection, message, "halt");
1429 if (m->running_as == SYSTEMD_SYSTEM) {
1430 dbus_set_error(&error, BUS_ERROR_NOT_SUPPORTED, "Exit is only supported for user service managers.");
1431 return bus_send_error_reply(connection, message, &error, -ENOTSUP);
1434 reply = dbus_message_new_method_return(message);
1438 m->exit_code = MANAGER_EXIT;
1440 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "Reboot")) {
1442 SELINUX_ACCESS_CHECK(connection, message, "reboot");
1444 if (m->running_as != SYSTEMD_SYSTEM) {
1445 dbus_set_error(&error, BUS_ERROR_NOT_SUPPORTED, "Reboot is only supported for system managers.");
1446 return bus_send_error_reply(connection, message, &error, -ENOTSUP);
1449 reply = dbus_message_new_method_return(message);
1453 m->exit_code = MANAGER_REBOOT;
1455 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "PowerOff")) {
1457 SELINUX_ACCESS_CHECK(connection, message, "halt");
1459 if (m->running_as != SYSTEMD_SYSTEM) {
1460 dbus_set_error(&error, BUS_ERROR_NOT_SUPPORTED, "Powering off is only supported for system managers.");
1461 return bus_send_error_reply(connection, message, &error, -ENOTSUP);
1464 reply = dbus_message_new_method_return(message);
1468 m->exit_code = MANAGER_POWEROFF;
1470 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "Halt")) {
1472 SELINUX_ACCESS_CHECK(connection, message, "halt");
1474 if (m->running_as != SYSTEMD_SYSTEM) {
1475 dbus_set_error(&error, BUS_ERROR_NOT_SUPPORTED, "Halting is only supported for system managers.");
1476 return bus_send_error_reply(connection, message, &error, -ENOTSUP);
1479 reply = dbus_message_new_method_return(message);
1483 m->exit_code = MANAGER_HALT;
1485 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "KExec")) {
1487 SELINUX_ACCESS_CHECK(connection, message, "reboot");
1489 if (m->running_as != SYSTEMD_SYSTEM) {
1490 dbus_set_error(&error, BUS_ERROR_NOT_SUPPORTED, "kexec is only supported for system managers.");
1491 return bus_send_error_reply(connection, message, &error, -ENOTSUP);
1494 reply = dbus_message_new_method_return(message);
1498 m->exit_code = MANAGER_KEXEC;
1500 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "SwitchRoot")) {
1501 const char *switch_root, *switch_root_init;
1505 SELINUX_ACCESS_CHECK(connection, message, "reboot");
1507 if (!dbus_message_get_args(
1510 DBUS_TYPE_STRING, &switch_root,
1511 DBUS_TYPE_STRING, &switch_root_init,
1513 return bus_send_error_reply(connection, message, &error, -EINVAL);
1515 if (path_equal(switch_root, "/") || !path_is_absolute(switch_root))
1516 return bus_send_error_reply(connection, message, NULL, -EINVAL);
1518 if (!isempty(switch_root_init) && !path_is_absolute(switch_root_init))
1519 return bus_send_error_reply(connection, message, NULL, -EINVAL);
1521 if (m->running_as != SYSTEMD_SYSTEM) {
1522 dbus_set_error(&error, BUS_ERROR_NOT_SUPPORTED, "Switching root is only supported for system managers.");
1523 return bus_send_error_reply(connection, message, &error, -ENOTSUP);
1527 if (isempty(switch_root_init)) {
1528 good = path_is_os_tree(switch_root);
1530 log_error("Not switching root: %s does not seem to be an OS tree. /etc/os-release is missing.", switch_root);
1533 _cleanup_free_ char *p = NULL;
1535 p = strjoin(switch_root, "/", switch_root_init, NULL);
1539 good = access(p, X_OK) >= 0;
1541 log_error("Not switching root: cannot execute new init %s", p);
1544 return bus_send_error_reply(connection, message, NULL, -EINVAL);
1546 u = strdup(switch_root);
1550 if (!isempty(switch_root_init)) {
1551 v = strdup(switch_root_init);
1559 free(m->switch_root);
1560 free(m->switch_root_init);
1562 m->switch_root_init = v;
1564 reply = dbus_message_new_method_return(message);
1568 m->exit_code = MANAGER_SWITCH_ROOT;
1570 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "SetEnvironment")) {
1571 _cleanup_strv_free_ char **l = NULL;
1574 SELINUX_ACCESS_CHECK(connection, message, "reboot");
1576 r = bus_parse_strv(message, &l);
1580 return bus_send_error_reply(connection, message, NULL, r);
1581 if (!strv_env_is_valid(l))
1582 return bus_send_error_reply(connection, message, NULL, -EINVAL);
1584 e = strv_env_merge(2, m->environment, l);
1588 reply = dbus_message_new_method_return(message);
1594 strv_free(m->environment);
1597 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "UnsetEnvironment")) {
1598 _cleanup_strv_free_ char **l = NULL;
1601 SELINUX_ACCESS_CHECK(connection, message, "reboot");
1603 r = bus_parse_strv(message, &l);
1607 return bus_send_error_reply(connection, message, NULL, r);
1608 if (!strv_env_name_or_assignment_is_valid(l))
1609 return bus_send_error_reply(connection, message, NULL, -EINVAL);
1611 e = strv_env_delete(m->environment, 1, l);
1615 reply = dbus_message_new_method_return(message);
1621 strv_free(m->environment);
1624 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "UnsetAndSetEnvironment")) {
1625 _cleanup_strv_free_ char **l_set = NULL, **l_unset = NULL, **e = NULL;
1627 DBusMessageIter iter;
1629 SELINUX_ACCESS_CHECK(connection, message, "reboot");
1631 if (!dbus_message_iter_init(message, &iter))
1634 r = bus_parse_strv_iter(&iter, &l_unset);
1638 return bus_send_error_reply(connection, message, NULL, r);
1639 if (!strv_env_name_or_assignment_is_valid(l_unset))
1640 return bus_send_error_reply(connection, message, NULL, -EINVAL);
1642 if (!dbus_message_iter_next(&iter))
1643 return bus_send_error_reply(connection, message, NULL, -EINVAL);
1645 r = bus_parse_strv_iter(&iter, &l_set);
1649 return bus_send_error_reply(connection, message, NULL, r);
1650 if (!strv_env_is_valid(l_set))
1651 return bus_send_error_reply(connection, message, NULL, -EINVAL);
1653 e = strv_env_delete(m->environment, 1, l_unset);
1657 f = strv_env_merge(2, e, l_set);
1661 reply = dbus_message_new_method_return(message);
1667 strv_free(m->environment);
1669 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ListUnitFiles")) {
1670 DBusMessageIter iter, sub, sub2;
1675 SELINUX_ACCESS_CHECK(connection, message, "status");
1677 reply = dbus_message_new_method_return(message);
1681 h = hashmap_new(string_hash_func, string_compare_func);
1685 r = unit_file_get_list(m->running_as == SYSTEMD_SYSTEM ? UNIT_FILE_SYSTEM : UNIT_FILE_USER, NULL, h);
1687 unit_file_list_free(h);
1688 return bus_send_error_reply(connection, message, NULL, r);
1691 dbus_message_iter_init_append(reply, &iter);
1693 if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "(ss)", &sub)) {
1694 unit_file_list_free(h);
1698 HASHMAP_FOREACH(item, h, i) {
1701 state = unit_file_state_to_string(item->state);
1704 if (!dbus_message_iter_open_container(&sub, DBUS_TYPE_STRUCT, NULL, &sub2) ||
1705 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &item->path) ||
1706 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &state) ||
1707 !dbus_message_iter_close_container(&sub, &sub2)) {
1708 unit_file_list_free(h);
1713 unit_file_list_free(h);
1715 if (!dbus_message_iter_close_container(&iter, &sub))
1718 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "GetUnitFileState")) {
1720 UnitFileState state;
1723 SELINUX_ACCESS_CHECK(connection, message, "status");
1725 if (!dbus_message_get_args(
1728 DBUS_TYPE_STRING, &name,
1730 return bus_send_error_reply(connection, message, &error, -EINVAL);
1732 state = unit_file_get_state(m->running_as == SYSTEMD_SYSTEM ? UNIT_FILE_SYSTEM : UNIT_FILE_USER, NULL, name);
1734 return bus_send_error_reply(connection, message, NULL, state);
1736 s = unit_file_state_to_string(state);
1739 reply = dbus_message_new_method_return(message);
1743 if (!dbus_message_append_args(
1745 DBUS_TYPE_STRING, &s,
1748 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "EnableUnitFiles") ||
1749 dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ReenableUnitFiles") ||
1750 dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "LinkUnitFiles") ||
1751 dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "PresetUnitFiles") ||
1752 dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "MaskUnitFiles") ||
1753 dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "SetDefaultTarget")) {
1756 DBusMessageIter iter;
1757 UnitFileScope scope = m->running_as == SYSTEMD_SYSTEM ? UNIT_FILE_SYSTEM : UNIT_FILE_USER;
1758 UnitFileChange *changes = NULL;
1759 unsigned n_changes = 0;
1760 dbus_bool_t runtime, force;
1761 int carries_install_info = -1;
1763 SELINUX_ACCESS_CHECK(connection, message, streq(member, "MaskUnitFiles") ? "disable" : "enable");
1765 if (!dbus_message_iter_init(message, &iter))
1768 r = bus_parse_strv_iter(&iter, &l);
1773 return bus_send_error_reply(connection, message, NULL, r);
1776 if (!dbus_message_iter_next(&iter) ||
1777 bus_iter_get_basic_and_next(&iter, DBUS_TYPE_BOOLEAN, &runtime, true) < 0 ||
1778 bus_iter_get_basic_and_next(&iter, DBUS_TYPE_BOOLEAN, &force, false) < 0) {
1780 return bus_send_error_reply(connection, message, NULL, -EIO);
1783 if (streq(member, "EnableUnitFiles")) {
1784 r = unit_file_enable(scope, runtime, NULL, l, force, &changes, &n_changes);
1785 carries_install_info = r;
1786 } else if (streq(member, "ReenableUnitFiles")) {
1787 r = unit_file_reenable(scope, runtime, NULL, l, force, &changes, &n_changes);
1788 carries_install_info = r;
1789 } else if (streq(member, "LinkUnitFiles"))
1790 r = unit_file_link(scope, runtime, NULL, l, force, &changes, &n_changes);
1791 else if (streq(member, "PresetUnitFiles")) {
1792 r = unit_file_preset(scope, runtime, NULL, l, force, &changes, &n_changes);
1793 carries_install_info = r;
1794 } else if (streq(member, "MaskUnitFiles"))
1795 r = unit_file_mask(scope, runtime, NULL, l, force, &changes, &n_changes);
1796 else if (streq(member, "SetDefaultTarget"))
1797 r = unit_file_set_default(scope, NULL, l[0], &changes, &n_changes);
1799 assert_not_reached("Uh? Wrong method");
1802 bus_manager_send_unit_files_changed(m);
1805 unit_file_changes_free(changes, n_changes);
1806 return bus_send_error_reply(connection, message, NULL, r);
1809 reply = message_from_file_changes(message, changes, n_changes, carries_install_info);
1810 unit_file_changes_free(changes, n_changes);
1815 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "DisableUnitFiles") ||
1816 dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "UnmaskUnitFiles")) {
1819 DBusMessageIter iter;
1820 UnitFileScope scope = m->running_as == SYSTEMD_SYSTEM ? UNIT_FILE_SYSTEM : UNIT_FILE_USER;
1821 UnitFileChange *changes = NULL;
1822 unsigned n_changes = 0;
1823 dbus_bool_t runtime;
1825 SELINUX_ACCESS_CHECK(connection, message, streq(member, "UnmaskUnitFiles") ? "enable" : "disable");
1827 if (!dbus_message_iter_init(message, &iter))
1830 r = bus_parse_strv_iter(&iter, &l);
1835 return bus_send_error_reply(connection, message, NULL, r);
1838 if (!dbus_message_iter_next(&iter) ||
1839 bus_iter_get_basic_and_next(&iter, DBUS_TYPE_BOOLEAN, &runtime, false) < 0) {
1841 return bus_send_error_reply(connection, message, NULL, -EIO);
1844 if (streq(member, "DisableUnitFiles"))
1845 r = unit_file_disable(scope, runtime, NULL, l, &changes, &n_changes);
1846 else if (streq(member, "UnmaskUnitFiles"))
1847 r = unit_file_unmask(scope, runtime, NULL, l, &changes, &n_changes);
1849 assert_not_reached("Uh? Wrong method");
1852 bus_manager_send_unit_files_changed(m);
1855 unit_file_changes_free(changes, n_changes);
1856 return bus_send_error_reply(connection, message, NULL, r);
1859 reply = message_from_file_changes(message, changes, n_changes, -1);
1860 unit_file_changes_free(changes, n_changes);
1865 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "GetDefaultTarget")) {
1866 UnitFileScope scope = m->running_as == SYSTEMD_SYSTEM ? UNIT_FILE_SYSTEM : UNIT_FILE_USER;
1867 _cleanup_free_ char *default_target = NULL;
1869 reply = dbus_message_new_method_return(message);
1873 r = unit_file_get_default(scope, NULL, &default_target);
1876 return bus_send_error_reply(connection, message, NULL, r);
1878 if (!dbus_message_append_args(reply, DBUS_TYPE_STRING, &default_target, DBUS_TYPE_INVALID)) {
1882 const BusBoundProperties bps[] = {
1883 { "org.freedesktop.systemd1.Manager", bus_systemd_properties, systemd_property_string },
1884 { "org.freedesktop.systemd1.Manager", bus_manager_properties, m },
1888 SELINUX_ACCESS_CHECK(connection, message, "status");
1890 return bus_default_message_handler(connection, message, NULL, INTERFACES_LIST, bps);
1893 if (job_type != _JOB_TYPE_INVALID) {
1894 const char *name, *smode, *old_name = NULL;
1899 if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "StartUnitReplace"))
1900 b = dbus_message_get_args(
1903 DBUS_TYPE_STRING, &old_name,
1904 DBUS_TYPE_STRING, &name,
1905 DBUS_TYPE_STRING, &smode,
1908 b = dbus_message_get_args(
1911 DBUS_TYPE_STRING, &name,
1912 DBUS_TYPE_STRING, &smode,
1915 return bus_send_error_reply(connection, message, &error, -EINVAL);
1918 u = manager_get_unit(m, old_name);
1919 if (!u || !u->job || u->job->type != JOB_START) {
1920 dbus_set_error(&error, BUS_ERROR_NO_SUCH_JOB, "No job queued for unit %s", old_name);
1921 return bus_send_error_reply(connection, message, &error, -ENOENT);
1925 mode = job_mode_from_string(smode);
1927 dbus_set_error(&error, BUS_ERROR_INVALID_JOB_MODE, "Job mode %s is invalid.", smode);
1928 return bus_send_error_reply(connection, message, &error, -EINVAL);
1931 r = manager_load_unit(m, name, NULL, &error, &u);
1933 return bus_send_error_reply(connection, message, &error, r);
1935 return bus_unit_queue_job(connection, message, u, job_type, mode, reload_if_possible);
1939 if (!bus_maybe_send_reply(connection, message, reply))
1942 return DBUS_HANDLER_RESULT_HANDLED;
1945 dbus_error_free(&error);
1947 return DBUS_HANDLER_RESULT_NEED_MEMORY;
1950 const DBusObjectPathVTable bus_manager_vtable = {
1951 .message_function = bus_manager_message_handler