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" \
232 #define BUS_MANAGER_INTERFACE_SIGNALS \
233 " <signal name=\"UnitNew\">\n" \
234 " <arg name=\"id\" type=\"s\"/>\n" \
235 " <arg name=\"unit\" type=\"o\"/>\n" \
237 " <signal name=\"UnitRemoved\">\n" \
238 " <arg name=\"id\" type=\"s\"/>\n" \
239 " <arg name=\"unit\" type=\"o\"/>\n" \
241 " <signal name=\"JobNew\">\n" \
242 " <arg name=\"id\" type=\"u\"/>\n" \
243 " <arg name=\"job\" type=\"o\"/>\n" \
244 " <arg name=\"unit\" type=\"s\"/>\n" \
246 " <signal name=\"JobRemoved\">\n" \
247 " <arg name=\"id\" type=\"u\"/>\n" \
248 " <arg name=\"job\" type=\"o\"/>\n" \
249 " <arg name=\"unit\" type=\"s\"/>\n" \
250 " <arg name=\"result\" type=\"s\"/>\n" \
252 " <signal name=\"StartupFinished\">\n" \
253 " <arg name=\"firmware\" type=\"t\"/>\n" \
254 " <arg name=\"loader\" type=\"t\"/>\n" \
255 " <arg name=\"kernel\" type=\"t\"/>\n" \
256 " <arg name=\"initrd\" type=\"t\"/>\n" \
257 " <arg name=\"userspace\" type=\"t\"/>\n" \
258 " <arg name=\"total\" type=\"t\"/>\n" \
260 " <signal name=\"UnitFilesChanged\"/>\n"
262 #define BUS_MANAGER_INTERFACE_PROPERTIES_GENERAL \
263 " <property name=\"Version\" type=\"s\" access=\"read\"/>\n" \
264 " <property name=\"Features\" type=\"s\" access=\"read\"/>\n" \
265 " <property name=\"Tainted\" type=\"s\" access=\"read\"/>\n" \
266 " <property name=\"FirmwareTimestamp\" type=\"t\" access=\"read\"/>\n" \
267 " <property name=\"FirmwareTimestampMonotonic\" type=\"t\" access=\"read\"/>\n" \
268 " <property name=\"LoaderTimestamp\" type=\"t\" access=\"read\"/>\n" \
269 " <property name=\"LoaderTimestampMonotonic\" type=\"t\" access=\"read\"/>\n" \
270 " <property name=\"KernelTimestamp\" type=\"t\" access=\"read\"/>\n" \
271 " <property name=\"KernelTimestampMonotonic\" type=\"t\" access=\"read\"/>\n" \
272 " <property name=\"InitRDTimestamp\" type=\"t\" access=\"read\"/>\n" \
273 " <property name=\"InitRDTimestampMonotonic\" type=\"t\" access=\"read\"/>\n" \
274 " <property name=\"UserspaceTimestamp\" type=\"t\" access=\"read\"/>\n" \
275 " <property name=\"UserspaceTimestampMonotonic\" type=\"t\" access=\"read\"/>\n" \
276 " <property name=\"FinishTimestamp\" type=\"t\" access=\"read\"/>\n" \
277 " <property name=\"FinishTimestampMonotonic\" type=\"t\" access=\"read\"/>\n" \
278 " <property name=\"LogLevel\" type=\"s\" access=\"readwrite\"/>\n" \
279 " <property name=\"LogTarget\" type=\"s\" access=\"readwrite\"/>\n" \
280 " <property name=\"NNames\" type=\"u\" access=\"read\"/>\n" \
281 " <property name=\"NJobs\" type=\"u\" access=\"read\"/>\n" \
282 " <property name=\"NInstalledJobs\" type=\"u\" access=\"read\"/>\n" \
283 " <property name=\"NFailedJobs\" type=\"u\" access=\"read\"/>\n" \
284 " <property name=\"Progress\" type=\"d\" access=\"read\"/>\n" \
285 " <property name=\"Environment\" type=\"as\" access=\"read\"/>\n" \
286 " <property name=\"ConfirmSpawn\" type=\"b\" access=\"read\"/>\n" \
287 " <property name=\"ShowStatus\" type=\"b\" access=\"read\"/>\n" \
288 " <property name=\"UnitPath\" type=\"as\" access=\"read\"/>\n" \
289 " <property name=\"ControlGroupHierarchy\" type=\"s\" access=\"read\"/>\n" \
290 " <property name=\"DefaultControllers\" type=\"as\" access=\"read\"/>\n" \
291 " <property name=\"DefaultStandardOutput\" type=\"s\" access=\"read\"/>\n" \
292 " <property name=\"DefaultStandardError\" type=\"s\" access=\"read\"/>\n" \
293 " <property name=\"RuntimeWatchdogUSec\" type=\"t\" access=\"readwrite\"/>\n" \
294 " <property name=\"ShutdownWatchdogUSec\" type=\"t\" access=\"readwrite\"/>\n" \
295 " <property name=\"Virtualization\" type=\"s\" access=\"read\"/>\n"
297 #define BUS_MANAGER_INTERFACE_END \
300 #define BUS_MANAGER_INTERFACE \
301 BUS_MANAGER_INTERFACE_BEGIN \
302 BUS_MANAGER_INTERFACE_METHODS \
303 BUS_MANAGER_INTERFACE_SIGNALS \
304 BUS_MANAGER_INTERFACE_PROPERTIES_GENERAL \
305 BUS_MANAGER_INTERFACE_END
307 #define INTROSPECTION_BEGIN \
308 DBUS_INTROSPECT_1_0_XML_DOCTYPE_DECL_NODE \
310 BUS_MANAGER_INTERFACE \
311 BUS_PROPERTIES_INTERFACE \
313 BUS_INTROSPECTABLE_INTERFACE
315 #define INTROSPECTION_END \
318 #define INTERFACES_LIST \
319 BUS_GENERIC_INTERFACES_LIST \
320 "org.freedesktop.systemd1.Manager\0"
322 const char bus_manager_interface[] _introspect_("Manager") = BUS_MANAGER_INTERFACE;
324 static DEFINE_BUS_PROPERTY_APPEND_ENUM(bus_manager_append_exec_output, exec_output, ExecOutput);
326 static int bus_manager_append_tainted(DBusMessageIter *i, const char *property, void *data) {
329 char buf[LINE_MAX] = "", *e = buf, *p = NULL;
336 e = stpcpy(e, "split-usr:");
338 if (readlink_malloc("/etc/mtab", &p) < 0)
339 e = stpcpy(e, "mtab-not-symlink:");
343 if (access("/proc/cgroups", F_OK) < 0)
344 e = stpcpy(e, "cgroups-missing:");
346 if (hwclock_is_localtime() > 0)
347 e = stpcpy(e, "local-hwclock:");
349 /* remove the last ':' */
355 if (!dbus_message_iter_append_basic(i, DBUS_TYPE_STRING, &t))
361 static int bus_manager_append_log_target(DBusMessageIter *i, const char *property, void *data) {
367 t = log_target_to_string(log_get_target());
369 if (!dbus_message_iter_append_basic(i, DBUS_TYPE_STRING, &t))
375 static int bus_manager_set_log_target(DBusMessageIter *i, const char *property, void *data) {
381 dbus_message_iter_get_basic(i, &t);
383 return log_set_target_from_string(t);
386 static int bus_manager_append_log_level(DBusMessageIter *i, const char *property, void *data) {
393 r = log_level_to_string_alloc(log_get_max_level(), &t);
397 if (!dbus_message_iter_append_basic(i, DBUS_TYPE_STRING, &t))
404 static int bus_manager_set_log_level(DBusMessageIter *i, const char *property, void *data) {
410 dbus_message_iter_get_basic(i, &t);
412 return log_set_max_level_from_string(t);
415 static int bus_manager_append_n_names(DBusMessageIter *i, const char *property, void *data) {
423 u = hashmap_size(m->units);
425 if (!dbus_message_iter_append_basic(i, DBUS_TYPE_UINT32, &u))
431 static int bus_manager_append_n_jobs(DBusMessageIter *i, const char *property, void *data) {
439 u = hashmap_size(m->jobs);
441 if (!dbus_message_iter_append_basic(i, DBUS_TYPE_UINT32, &u))
447 static int bus_manager_append_progress(DBusMessageIter *i, const char *property, void *data) {
455 if (dual_timestamp_is_set(&m->finish_timestamp))
458 d = 1.0 - ((double) hashmap_size(m->jobs) / (double) m->n_installed_jobs);
460 if (!dbus_message_iter_append_basic(i, DBUS_TYPE_DOUBLE, &d))
466 static int bus_manager_append_virt(DBusMessageIter *i, const char *property, void *data) {
474 detect_virtualization(&id);
476 if (!dbus_message_iter_append_basic(i, DBUS_TYPE_STRING, &id))
482 static DBusMessage *message_from_file_changes(
484 UnitFileChange *changes,
486 int carries_install_info) {
488 DBusMessageIter iter, sub, sub2;
492 reply = dbus_message_new_method_return(m);
496 dbus_message_iter_init_append(reply, &iter);
498 if (carries_install_info >= 0) {
501 b = !!carries_install_info;
502 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &b))
506 if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "(sss)", &sub))
509 for (i = 0; i < n_changes; i++) {
510 const char *type, *path, *source;
512 type = unit_file_change_type_to_string(changes[i].type);
513 path = strempty(changes[i].path);
514 source = strempty(changes[i].source);
516 if (!dbus_message_iter_open_container(&sub, DBUS_TYPE_STRUCT, NULL, &sub2) ||
517 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &type) ||
518 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &path) ||
519 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &source) ||
520 !dbus_message_iter_close_container(&sub, &sub2))
524 if (!dbus_message_iter_close_container(&iter, &sub))
530 dbus_message_unref(reply);
534 static int bus_manager_send_unit_files_changed(Manager *m) {
538 s = dbus_message_new_signal("/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", "UnitFilesChanged");
542 r = bus_broadcast(m, s);
543 dbus_message_unref(s);
548 static int bus_manager_set_runtime_watchdog_usec(DBusMessageIter *i, const char *property, void *data) {
554 dbus_message_iter_get_basic(i, t);
556 return watchdog_set_timeout(t);
559 static const char systemd_property_string[] =
563 static const BusProperty bus_systemd_properties[] = {
564 { "Version", bus_property_append_string, "s", 0 },
565 { "Features", bus_property_append_string, "s", sizeof(PACKAGE_STRING) },
569 static const BusProperty bus_manager_properties[] = {
570 { "Tainted", bus_manager_append_tainted, "s", 0 },
571 { "FirmwareTimestamp", bus_property_append_uint64, "t", offsetof(Manager, firmware_timestamp.realtime) },
572 { "FirmwareTimestampMonotonic", bus_property_append_uint64, "t", offsetof(Manager, firmware_timestamp.monotonic) },
573 { "LoaderTimestamp", bus_property_append_uint64, "t", offsetof(Manager, loader_timestamp.realtime) },
574 { "LoaderTimestampMonotonic", bus_property_append_uint64, "t", offsetof(Manager, loader_timestamp.monotonic) },
575 { "KernelTimestamp", bus_property_append_uint64, "t", offsetof(Manager, kernel_timestamp.realtime) },
576 { "KernelTimestampMonotonic", bus_property_append_uint64, "t", offsetof(Manager, kernel_timestamp.monotonic) },
577 { "InitRDTimestamp", bus_property_append_uint64, "t", offsetof(Manager, initrd_timestamp.realtime) },
578 { "InitRDTimestampMonotonic", bus_property_append_uint64, "t", offsetof(Manager, initrd_timestamp.monotonic) },
579 { "UserspaceTimestamp", bus_property_append_uint64, "t", offsetof(Manager, userspace_timestamp.realtime) },
580 { "UserspaceTimestampMonotonic", bus_property_append_uint64, "t", offsetof(Manager, userspace_timestamp.monotonic) },
581 { "FinishTimestamp", bus_property_append_uint64, "t", offsetof(Manager, finish_timestamp.realtime) },
582 { "FinishTimestampMonotonic", bus_property_append_uint64, "t", offsetof(Manager, finish_timestamp.monotonic) },
583 { "LogLevel", bus_manager_append_log_level, "s", 0, false, bus_manager_set_log_level },
584 { "LogTarget", bus_manager_append_log_target, "s", 0, false, bus_manager_set_log_target },
585 { "NNames", bus_manager_append_n_names, "u", 0 },
586 { "NJobs", bus_manager_append_n_jobs, "u", 0 },
587 { "NInstalledJobs", bus_property_append_uint32, "u", offsetof(Manager, n_installed_jobs) },
588 { "NFailedJobs", bus_property_append_uint32, "u", offsetof(Manager, n_failed_jobs) },
589 { "Progress", bus_manager_append_progress, "d", 0 },
590 { "Environment", bus_property_append_strv, "as", offsetof(Manager, environment), true },
591 { "ConfirmSpawn", bus_property_append_bool, "b", offsetof(Manager, confirm_spawn) },
592 { "ShowStatus", bus_property_append_bool, "b", offsetof(Manager, show_status) },
593 { "UnitPath", bus_property_append_strv, "as", offsetof(Manager, lookup_paths.unit_path), true },
594 { "ControlGroupHierarchy", bus_property_append_string, "s", offsetof(Manager, cgroup_hierarchy), true },
595 { "DefaultControllers", bus_property_append_strv, "as", offsetof(Manager, default_controllers), true },
596 { "DefaultStandardOutput", bus_manager_append_exec_output, "s", offsetof(Manager, default_std_output) },
597 { "DefaultStandardError", bus_manager_append_exec_output, "s", offsetof(Manager, default_std_error) },
598 { "RuntimeWatchdogUSec", bus_property_append_usec, "t", offsetof(Manager, runtime_watchdog), false, bus_manager_set_runtime_watchdog_usec },
599 { "ShutdownWatchdogUSec", bus_property_append_usec, "t", offsetof(Manager, shutdown_watchdog), false, bus_property_set_usec },
600 { "Virtualization", bus_manager_append_virt, "s", 0, },
604 static DBusHandlerResult bus_manager_message_handler(DBusConnection *connection, DBusMessage *message, void *data) {
605 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
606 _cleanup_free_ char * path = NULL;
610 JobType job_type = _JOB_TYPE_INVALID;
611 bool reload_if_possible = false;
618 dbus_error_init(&error);
620 member = dbus_message_get_member(message);
622 if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "GetUnit")) {
626 if (!dbus_message_get_args(
629 DBUS_TYPE_STRING, &name,
631 return bus_send_error_reply(connection, message, &error, -EINVAL);
633 u = manager_get_unit(m, name);
635 dbus_set_error(&error, BUS_ERROR_NO_SUCH_UNIT, "Unit %s is not loaded.", name);
636 return bus_send_error_reply(connection, message, &error, -ENOENT);
639 SELINUX_UNIT_ACCESS_CHECK(u, connection, message, "status");
641 reply = dbus_message_new_method_return(message);
645 path = unit_dbus_path(u);
649 if (!dbus_message_append_args(
651 DBUS_TYPE_OBJECT_PATH, &path,
654 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "GetUnitByPID")) {
658 if (!dbus_message_get_args(
661 DBUS_TYPE_UINT32, &pid,
663 return bus_send_error_reply(connection, message, &error, -EINVAL);
665 u = cgroup_unit_by_pid(m, (pid_t) pid);
667 dbus_set_error(&error, BUS_ERROR_NO_SUCH_UNIT, "No unit for PID %lu is loaded.", (unsigned long) pid);
668 return bus_send_error_reply(connection, message, &error, -ENOENT);
671 SELINUX_UNIT_ACCESS_CHECK(u, connection, message, "status");
673 reply = dbus_message_new_method_return(message);
677 path = unit_dbus_path(u);
681 if (!dbus_message_append_args(
683 DBUS_TYPE_OBJECT_PATH, &path,
686 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "LoadUnit")) {
690 if (!dbus_message_get_args(
693 DBUS_TYPE_STRING, &name,
695 return bus_send_error_reply(connection, message, &error, -EINVAL);
697 r = manager_load_unit(m, name, NULL, &error, &u);
699 return bus_send_error_reply(connection, message, &error, r);
701 SELINUX_UNIT_ACCESS_CHECK(u, connection, message, "status");
703 reply = dbus_message_new_method_return(message);
707 path = unit_dbus_path(u);
711 if (!dbus_message_append_args(
713 DBUS_TYPE_OBJECT_PATH, &path,
717 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "StartUnit"))
718 job_type = JOB_START;
719 else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "StartUnitReplace"))
720 job_type = JOB_START;
721 else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "StopUnit"))
723 else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ReloadUnit"))
724 job_type = JOB_RELOAD;
725 else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "RestartUnit"))
726 job_type = JOB_RESTART;
727 else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "TryRestartUnit"))
728 job_type = JOB_TRY_RESTART;
729 else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ReloadOrRestartUnit")) {
730 reload_if_possible = true;
731 job_type = JOB_RESTART;
732 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ReloadOrTryRestartUnit")) {
733 reload_if_possible = true;
734 job_type = JOB_TRY_RESTART;
735 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "KillUnit")) {
736 const char *name, *swho;
741 if (!dbus_message_get_args(
744 DBUS_TYPE_STRING, &name,
745 DBUS_TYPE_STRING, &swho,
746 DBUS_TYPE_INT32, &signo,
748 return bus_send_error_reply(connection, message, &error, -EINVAL);
753 who = kill_who_from_string(swho);
755 return bus_send_error_reply(connection, message, &error, -EINVAL);
758 if (signo <= 0 || signo >= _NSIG)
759 return bus_send_error_reply(connection, message, &error, -EINVAL);
761 u = manager_get_unit(m, name);
763 dbus_set_error(&error, BUS_ERROR_NO_SUCH_UNIT, "Unit %s is not loaded.", name);
764 return bus_send_error_reply(connection, message, &error, -ENOENT);
767 SELINUX_UNIT_ACCESS_CHECK(u, connection, message, "stop");
769 r = unit_kill(u, who, signo, &error);
771 return bus_send_error_reply(connection, message, &error, r);
773 reply = dbus_message_new_method_return(message);
777 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "GetJob")) {
781 if (!dbus_message_get_args(
784 DBUS_TYPE_UINT32, &id,
786 return bus_send_error_reply(connection, message, &error, -EINVAL);
788 j = manager_get_job(m, id);
790 dbus_set_error(&error, BUS_ERROR_NO_SUCH_JOB, "Job %u does not exist.", (unsigned) id);
791 return bus_send_error_reply(connection, message, &error, -ENOENT);
794 SELINUX_UNIT_ACCESS_CHECK(j->unit, connection, message, "status");
796 reply = dbus_message_new_method_return(message);
800 path = job_dbus_path(j);
804 if (!dbus_message_append_args(
806 DBUS_TYPE_OBJECT_PATH, &path,
810 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "CancelJob")) {
814 if (!dbus_message_get_args(
817 DBUS_TYPE_UINT32, &id,
819 return bus_send_error_reply(connection, message, &error, -EINVAL);
821 j = manager_get_job(m, id);
823 dbus_set_error(&error, BUS_ERROR_NO_SUCH_JOB, "Job %u does not exist.", (unsigned) id);
824 return bus_send_error_reply(connection, message, &error, -ENOENT);
827 SELINUX_UNIT_ACCESS_CHECK(j->unit, connection, message, "stop");
828 job_finish_and_invalidate(j, JOB_CANCELED, true);
830 reply = dbus_message_new_method_return(message);
834 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ClearJobs")) {
836 SELINUX_ACCESS_CHECK(connection, message, "reboot");
837 manager_clear_jobs(m);
839 reply = dbus_message_new_method_return(message);
843 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ResetFailed")) {
845 SELINUX_ACCESS_CHECK(connection, message, "reload");
847 manager_reset_failed(m);
849 reply = dbus_message_new_method_return(message);
853 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ResetFailedUnit")) {
857 if (!dbus_message_get_args(
860 DBUS_TYPE_STRING, &name,
862 return bus_send_error_reply(connection, message, &error, -EINVAL);
864 u = manager_get_unit(m, name);
866 dbus_set_error(&error, BUS_ERROR_NO_SUCH_UNIT, "Unit %s is not loaded.", name);
867 return bus_send_error_reply(connection, message, &error, -ENOENT);
870 SELINUX_UNIT_ACCESS_CHECK(u, connection, message, "reload");
872 unit_reset_failed(u);
874 reply = dbus_message_new_method_return(message);
878 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "SetUnitControlGroup")) {
881 DBusMessageIter iter;
883 if (!dbus_message_iter_init(message, &iter))
886 r = bus_iter_get_basic_and_next(&iter, DBUS_TYPE_STRING, &name, true);
888 return bus_send_error_reply(connection, message, NULL, r);
890 u = manager_get_unit(m, name);
892 dbus_set_error(&error, BUS_ERROR_NO_SUCH_UNIT, "Unit %s is not loaded.", name);
893 return bus_send_error_reply(connection, message, &error, -ENOENT);
896 SELINUX_UNIT_ACCESS_CHECK(u, connection, message, "start");
898 r = bus_unit_cgroup_set(u, &iter);
900 return bus_send_error_reply(connection, message, NULL, r);
902 reply = dbus_message_new_method_return(message);
906 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "UnsetUnitControlGroup")) {
909 DBusMessageIter iter;
911 if (!dbus_message_iter_init(message, &iter))
914 r = bus_iter_get_basic_and_next(&iter, DBUS_TYPE_STRING, &name, true);
916 return bus_send_error_reply(connection, message, NULL, r);
918 u = manager_get_unit(m, name);
920 dbus_set_error(&error, BUS_ERROR_NO_SUCH_UNIT, "Unit %s is not loaded.", name);
921 return bus_send_error_reply(connection, message, &error, -ENOENT);
924 SELINUX_UNIT_ACCESS_CHECK(u, connection, message, "stop");
926 r = bus_unit_cgroup_unset(u, &iter);
928 return bus_send_error_reply(connection, message, NULL, r);
930 reply = dbus_message_new_method_return(message);
934 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "SetUnitControlGroupAttribute")) {
937 DBusMessageIter iter;
939 if (!dbus_message_iter_init(message, &iter))
942 r = bus_iter_get_basic_and_next(&iter, DBUS_TYPE_STRING, &name, true);
944 return bus_send_error_reply(connection, message, NULL, r);
946 u = manager_get_unit(m, name);
948 dbus_set_error(&error, BUS_ERROR_NO_SUCH_UNIT, "Unit %s is not loaded.", name);
949 return bus_send_error_reply(connection, message, &error, -ENOENT);
952 SELINUX_UNIT_ACCESS_CHECK(u, connection, message, "start");
954 r = bus_unit_cgroup_attribute_set(u, &iter);
956 return bus_send_error_reply(connection, message, NULL, r);
958 reply = dbus_message_new_method_return(message);
962 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "UnsetUnitControlGroupAttribute")) {
965 DBusMessageIter iter;
967 if (!dbus_message_iter_init(message, &iter))
970 r = bus_iter_get_basic_and_next(&iter, DBUS_TYPE_STRING, &name, true);
972 return bus_send_error_reply(connection, message, NULL, r);
974 u = manager_get_unit(m, name);
976 dbus_set_error(&error, BUS_ERROR_NO_SUCH_UNIT, "Unit %s is not loaded.", name);
977 return bus_send_error_reply(connection, message, &error, -ENOENT);
980 SELINUX_UNIT_ACCESS_CHECK(u, connection, message, "stop");
982 r = bus_unit_cgroup_attribute_unset(u, &iter);
984 return bus_send_error_reply(connection, message, NULL, r);
986 reply = dbus_message_new_method_return(message);
990 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "GetUnitControlGroupAttribute")) {
993 DBusMessageIter iter;
994 _cleanup_strv_free_ char **list = NULL;
996 if (!dbus_message_iter_init(message, &iter))
999 r = bus_iter_get_basic_and_next(&iter, DBUS_TYPE_STRING, &name, true);
1001 return bus_send_error_reply(connection, message, NULL, r);
1003 u = manager_get_unit(m, name);
1005 dbus_set_error(&error, BUS_ERROR_NO_SUCH_UNIT, "Unit %s is not loaded.", name);
1006 return bus_send_error_reply(connection, message, &error, -ENOENT);
1009 SELINUX_UNIT_ACCESS_CHECK(u, connection, message, "status");
1011 r = bus_unit_cgroup_attribute_get(u, &iter, &list);
1013 return bus_send_error_reply(connection, message, NULL, r);
1015 reply = dbus_message_new_method_return(message);
1019 dbus_message_iter_init_append(reply, &iter);
1020 if (bus_append_strv_iter(&iter, list) < 0)
1023 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ListUnits")) {
1024 DBusMessageIter iter, sub;
1029 SELINUX_ACCESS_CHECK(connection, message, "status");
1031 reply = dbus_message_new_method_return(message);
1035 dbus_message_iter_init_append(reply, &iter);
1037 if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "(ssssssouso)", &sub))
1040 HASHMAP_FOREACH_KEY(u, k, m->units, i) {
1041 char *u_path, *j_path;
1042 const char *description, *load_state, *active_state, *sub_state, *sjob_type, *following;
1043 DBusMessageIter sub2;
1050 if (!dbus_message_iter_open_container(&sub, DBUS_TYPE_STRUCT, NULL, &sub2))
1053 description = unit_description(u);
1054 load_state = unit_load_state_to_string(u->load_state);
1055 active_state = unit_active_state_to_string(unit_active_state(u));
1056 sub_state = unit_sub_state_to_string(u);
1058 f = unit_following(u);
1059 following = f ? f->id : "";
1061 u_path = unit_dbus_path(u);
1066 job_id = (uint32_t) u->job->id;
1068 if (!(j_path = job_dbus_path(u->job))) {
1073 sjob_type = job_type_to_string(u->job->type);
1080 if (!dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &u->id) ||
1081 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &description) ||
1082 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &load_state) ||
1083 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &active_state) ||
1084 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &sub_state) ||
1085 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &following) ||
1086 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_OBJECT_PATH, &u_path) ||
1087 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_UINT32, &job_id) ||
1088 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &sjob_type) ||
1089 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_OBJECT_PATH, &j_path)) {
1100 if (!dbus_message_iter_close_container(&sub, &sub2))
1104 if (!dbus_message_iter_close_container(&iter, &sub))
1107 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ListJobs")) {
1108 DBusMessageIter iter, sub;
1112 SELINUX_ACCESS_CHECK(connection, message, "status");
1114 reply = dbus_message_new_method_return(message);
1118 dbus_message_iter_init_append(reply, &iter);
1120 if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "(usssoo)", &sub))
1123 HASHMAP_FOREACH(j, m->jobs, i) {
1124 char *u_path, *j_path;
1125 const char *state, *type;
1127 DBusMessageIter sub2;
1129 if (!dbus_message_iter_open_container(&sub, DBUS_TYPE_STRUCT, NULL, &sub2))
1132 id = (uint32_t) j->id;
1133 state = job_state_to_string(j->state);
1134 type = job_type_to_string(j->type);
1136 j_path = job_dbus_path(j);
1140 u_path = unit_dbus_path(j->unit);
1146 if (!dbus_message_iter_append_basic(&sub2, DBUS_TYPE_UINT32, &id) ||
1147 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &j->unit->id) ||
1148 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &type) ||
1149 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &state) ||
1150 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_OBJECT_PATH, &j_path) ||
1151 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_OBJECT_PATH, &u_path)) {
1160 if (!dbus_message_iter_close_container(&sub, &sub2))
1164 if (!dbus_message_iter_close_container(&iter, &sub))
1167 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "Subscribe")) {
1171 SELINUX_ACCESS_CHECK(connection, message, "status");
1173 s = BUS_CONNECTION_SUBSCRIBED(m, connection);
1175 s = set_new(string_hash_func, string_compare_func);
1179 if (!dbus_connection_set_data(connection, m->subscribed_data_slot, s, NULL)) {
1185 client = strdup(bus_message_get_sender_with_fallback(message));
1189 r = set_consume(s, client);
1191 return bus_send_error_reply(connection, message, NULL, r);
1193 reply = dbus_message_new_method_return(message);
1197 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "Unsubscribe")) {
1200 SELINUX_ACCESS_CHECK(connection, message, "status");
1202 client = set_remove(BUS_CONNECTION_SUBSCRIBED(m, connection), (char*) bus_message_get_sender_with_fallback(message));
1204 dbus_set_error(&error, BUS_ERROR_NOT_SUBSCRIBED, "Client is not subscribed.");
1205 return bus_send_error_reply(connection, message, &error, -ENOENT);
1210 reply = dbus_message_new_method_return(message);
1214 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "Dump")) {
1219 SELINUX_ACCESS_CHECK(connection, message, "status");
1221 reply = dbus_message_new_method_return(message);
1225 f = open_memstream(&dump, &size);
1229 manager_dump_units(m, f, NULL);
1230 manager_dump_jobs(m, f, NULL);
1240 if (!dbus_message_append_args(reply, DBUS_TYPE_STRING, &dump, DBUS_TYPE_INVALID)) {
1246 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "CreateSnapshot")) {
1248 dbus_bool_t cleanup;
1251 SELINUX_ACCESS_CHECK(connection, message, "start");
1253 if (!dbus_message_get_args(
1256 DBUS_TYPE_STRING, &name,
1257 DBUS_TYPE_BOOLEAN, &cleanup,
1259 return bus_send_error_reply(connection, message, &error, -EINVAL);
1264 r = snapshot_create(m, name, cleanup, &error, &s);
1266 return bus_send_error_reply(connection, message, &error, r);
1268 reply = dbus_message_new_method_return(message);
1272 path = unit_dbus_path(UNIT(s));
1276 if (!dbus_message_append_args(
1278 DBUS_TYPE_OBJECT_PATH, &path,
1282 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "RemoveSnapshot")) {
1286 if (!dbus_message_get_args(
1289 DBUS_TYPE_STRING, &name,
1291 return bus_send_error_reply(connection, message, &error, -EINVAL);
1293 u = manager_get_unit(m, name);
1295 dbus_set_error(&error, BUS_ERROR_NO_SUCH_UNIT, "Unit %s does not exist.", name);
1296 return bus_send_error_reply(connection, message, &error, -ENOENT);
1299 if (u->type != UNIT_SNAPSHOT) {
1300 dbus_set_error(&error, BUS_ERROR_NO_SUCH_UNIT, "Unit %s is not a snapshot.", name);
1301 return bus_send_error_reply(connection, message, &error, -ENOENT);
1304 SELINUX_UNIT_ACCESS_CHECK(u, connection, message, "stop");
1305 snapshot_remove(SNAPSHOT(u));
1307 reply = dbus_message_new_method_return(message);
1311 } else if (dbus_message_is_method_call(message, "org.freedesktop.DBus.Introspectable", "Introspect")) {
1312 char *introspection = NULL;
1320 SELINUX_ACCESS_CHECK(connection, message, "status");
1322 reply = dbus_message_new_method_return(message);
1326 /* We roll our own introspection code here, instead of
1327 * relying on bus_default_message_handler() because we
1328 * need to generate our introspection string
1331 f = open_memstream(&introspection, &size);
1335 fputs(INTROSPECTION_BEGIN, f);
1337 HASHMAP_FOREACH_KEY(u, k, m->units, i) {
1343 p = bus_path_escape(k);
1346 free(introspection);
1350 fprintf(f, "<node name=\"unit/%s\"/>", p);
1354 HASHMAP_FOREACH(j, m->jobs, i)
1355 fprintf(f, "<node name=\"job/%lu\"/>", (unsigned long) j->id);
1357 fputs(INTROSPECTION_END, f);
1361 free(introspection);
1370 if (!dbus_message_append_args(reply, DBUS_TYPE_STRING, &introspection, DBUS_TYPE_INVALID)) {
1371 free(introspection);
1375 free(introspection);
1377 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "Reload")) {
1379 SELINUX_ACCESS_CHECK(connection, message, "reload");
1381 assert(!m->queued_message);
1383 /* Instead of sending the reply back right away, we
1384 * just remember that we need to and then send it
1385 * after the reload is finished. That way the caller
1386 * knows when the reload finished. */
1388 m->queued_message = dbus_message_new_method_return(message);
1389 if (!m->queued_message)
1392 m->queued_message_connection = connection;
1393 m->exit_code = MANAGER_RELOAD;
1395 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "Reexecute")) {
1397 SELINUX_ACCESS_CHECK(connection, message, "reload");
1399 /* We don't send a reply back here, the client should
1400 * just wait for us disconnecting. */
1402 m->exit_code = MANAGER_REEXECUTE;
1404 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "Exit")) {
1406 SELINUX_ACCESS_CHECK(connection, message, "halt");
1408 if (m->running_as == SYSTEMD_SYSTEM) {
1409 dbus_set_error(&error, BUS_ERROR_NOT_SUPPORTED, "Exit is only supported for user service managers.");
1410 return bus_send_error_reply(connection, message, &error, -ENOTSUP);
1413 reply = dbus_message_new_method_return(message);
1417 m->exit_code = MANAGER_EXIT;
1419 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "Reboot")) {
1421 SELINUX_ACCESS_CHECK(connection, message, "reboot");
1423 if (m->running_as != SYSTEMD_SYSTEM) {
1424 dbus_set_error(&error, BUS_ERROR_NOT_SUPPORTED, "Reboot is only supported for system managers.");
1425 return bus_send_error_reply(connection, message, &error, -ENOTSUP);
1428 reply = dbus_message_new_method_return(message);
1432 m->exit_code = MANAGER_REBOOT;
1434 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "PowerOff")) {
1436 SELINUX_ACCESS_CHECK(connection, message, "halt");
1438 if (m->running_as != SYSTEMD_SYSTEM) {
1439 dbus_set_error(&error, BUS_ERROR_NOT_SUPPORTED, "Powering off 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_POWEROFF;
1449 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "Halt")) {
1451 SELINUX_ACCESS_CHECK(connection, message, "halt");
1453 if (m->running_as != SYSTEMD_SYSTEM) {
1454 dbus_set_error(&error, BUS_ERROR_NOT_SUPPORTED, "Halting 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_HALT;
1464 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "KExec")) {
1466 SELINUX_ACCESS_CHECK(connection, message, "reboot");
1468 if (m->running_as != SYSTEMD_SYSTEM) {
1469 dbus_set_error(&error, BUS_ERROR_NOT_SUPPORTED, "kexec 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_KEXEC;
1479 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "SwitchRoot")) {
1480 const char *switch_root, *switch_root_init;
1484 SELINUX_ACCESS_CHECK(connection, message, "reboot");
1486 if (!dbus_message_get_args(
1489 DBUS_TYPE_STRING, &switch_root,
1490 DBUS_TYPE_STRING, &switch_root_init,
1492 return bus_send_error_reply(connection, message, &error, -EINVAL);
1494 if (path_equal(switch_root, "/") || !path_is_absolute(switch_root))
1495 return bus_send_error_reply(connection, message, NULL, -EINVAL);
1497 if (!isempty(switch_root_init) && !path_is_absolute(switch_root_init))
1498 return bus_send_error_reply(connection, message, NULL, -EINVAL);
1500 if (m->running_as != SYSTEMD_SYSTEM) {
1501 dbus_set_error(&error, BUS_ERROR_NOT_SUPPORTED, "Switching root is only supported for system managers.");
1502 return bus_send_error_reply(connection, message, &error, -ENOTSUP);
1506 if (isempty(switch_root_init)) {
1507 good = path_is_os_tree(switch_root);
1509 log_error("Not switching root: %s does not seem to be an OS tree. /etc/os-release is missing.", switch_root);
1512 _cleanup_free_ char *p = NULL;
1514 p = strjoin(switch_root, "/", switch_root_init, NULL);
1518 good = access(p, X_OK) >= 0;
1520 log_error("Not switching root: cannot execute new init %s", p);
1523 return bus_send_error_reply(connection, message, NULL, -EINVAL);
1525 u = strdup(switch_root);
1529 if (!isempty(switch_root_init)) {
1530 v = strdup(switch_root_init);
1538 free(m->switch_root);
1539 free(m->switch_root_init);
1541 m->switch_root_init = v;
1543 reply = dbus_message_new_method_return(message);
1547 m->exit_code = MANAGER_SWITCH_ROOT;
1549 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "SetEnvironment")) {
1550 _cleanup_strv_free_ char **l = NULL;
1553 SELINUX_ACCESS_CHECK(connection, message, "reboot");
1555 r = bus_parse_strv(message, &l);
1559 return bus_send_error_reply(connection, message, NULL, r);
1560 if (!strv_env_is_valid(l))
1561 return bus_send_error_reply(connection, message, NULL, -EINVAL);
1563 e = strv_env_merge(2, m->environment, l);
1567 reply = dbus_message_new_method_return(message);
1573 strv_free(m->environment);
1576 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "UnsetEnvironment")) {
1577 _cleanup_strv_free_ char **l = NULL;
1580 SELINUX_ACCESS_CHECK(connection, message, "reboot");
1582 r = bus_parse_strv(message, &l);
1586 return bus_send_error_reply(connection, message, NULL, r);
1587 if (!strv_env_name_or_assignment_is_valid(l))
1588 return bus_send_error_reply(connection, message, NULL, -EINVAL);
1590 e = strv_env_delete(m->environment, 1, l);
1594 reply = dbus_message_new_method_return(message);
1600 strv_free(m->environment);
1603 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "UnsetAndSetEnvironment")) {
1604 _cleanup_strv_free_ char **l_set = NULL, **l_unset = NULL, **e = NULL;
1606 DBusMessageIter iter;
1608 SELINUX_ACCESS_CHECK(connection, message, "reboot");
1610 if (!dbus_message_iter_init(message, &iter))
1613 r = bus_parse_strv_iter(&iter, &l_unset);
1617 return bus_send_error_reply(connection, message, NULL, r);
1618 if (!strv_env_name_or_assignment_is_valid(l_unset))
1619 return bus_send_error_reply(connection, message, NULL, -EINVAL);
1621 if (!dbus_message_iter_next(&iter))
1622 return bus_send_error_reply(connection, message, NULL, -EINVAL);
1624 r = bus_parse_strv_iter(&iter, &l_set);
1628 return bus_send_error_reply(connection, message, NULL, r);
1629 if (!strv_env_is_valid(l_set))
1630 return bus_send_error_reply(connection, message, NULL, -EINVAL);
1632 e = strv_env_delete(m->environment, 1, l_unset);
1636 f = strv_env_merge(2, e, l_set);
1640 reply = dbus_message_new_method_return(message);
1646 strv_free(m->environment);
1648 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ListUnitFiles")) {
1649 DBusMessageIter iter, sub, sub2;
1654 SELINUX_ACCESS_CHECK(connection, message, "status");
1656 reply = dbus_message_new_method_return(message);
1660 h = hashmap_new(string_hash_func, string_compare_func);
1664 r = unit_file_get_list(m->running_as == SYSTEMD_SYSTEM ? UNIT_FILE_SYSTEM : UNIT_FILE_USER, NULL, h);
1666 unit_file_list_free(h);
1667 return bus_send_error_reply(connection, message, NULL, r);
1670 dbus_message_iter_init_append(reply, &iter);
1672 if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "(ss)", &sub)) {
1673 unit_file_list_free(h);
1677 HASHMAP_FOREACH(item, h, i) {
1680 state = unit_file_state_to_string(item->state);
1683 if (!dbus_message_iter_open_container(&sub, DBUS_TYPE_STRUCT, NULL, &sub2) ||
1684 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &item->path) ||
1685 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &state) ||
1686 !dbus_message_iter_close_container(&sub, &sub2)) {
1687 unit_file_list_free(h);
1692 unit_file_list_free(h);
1694 if (!dbus_message_iter_close_container(&iter, &sub))
1697 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "GetUnitFileState")) {
1699 UnitFileState state;
1702 SELINUX_ACCESS_CHECK(connection, message, "status");
1704 if (!dbus_message_get_args(
1707 DBUS_TYPE_STRING, &name,
1709 return bus_send_error_reply(connection, message, &error, -EINVAL);
1711 state = unit_file_get_state(m->running_as == SYSTEMD_SYSTEM ? UNIT_FILE_SYSTEM : UNIT_FILE_USER, NULL, name);
1713 return bus_send_error_reply(connection, message, NULL, state);
1715 s = unit_file_state_to_string(state);
1718 reply = dbus_message_new_method_return(message);
1722 if (!dbus_message_append_args(
1724 DBUS_TYPE_STRING, &s,
1727 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "EnableUnitFiles") ||
1728 dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ReenableUnitFiles") ||
1729 dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "LinkUnitFiles") ||
1730 dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "PresetUnitFiles") ||
1731 dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "MaskUnitFiles")) {
1734 DBusMessageIter iter;
1735 UnitFileScope scope = m->running_as == SYSTEMD_SYSTEM ? UNIT_FILE_SYSTEM : UNIT_FILE_USER;
1736 UnitFileChange *changes = NULL;
1737 unsigned n_changes = 0;
1738 dbus_bool_t runtime, force;
1739 int carries_install_info = -1;
1741 SELINUX_ACCESS_CHECK(connection, message, streq(member, "MaskUnitFiles") ? "disable" : "enable");
1743 if (!dbus_message_iter_init(message, &iter))
1746 r = bus_parse_strv_iter(&iter, &l);
1751 return bus_send_error_reply(connection, message, NULL, r);
1754 if (!dbus_message_iter_next(&iter) ||
1755 bus_iter_get_basic_and_next(&iter, DBUS_TYPE_BOOLEAN, &runtime, true) < 0 ||
1756 bus_iter_get_basic_and_next(&iter, DBUS_TYPE_BOOLEAN, &force, false) < 0) {
1758 return bus_send_error_reply(connection, message, NULL, -EIO);
1761 if (streq(member, "EnableUnitFiles")) {
1762 r = unit_file_enable(scope, runtime, NULL, l, force, &changes, &n_changes);
1763 carries_install_info = r;
1764 } else if (streq(member, "ReenableUnitFiles")) {
1765 r = unit_file_reenable(scope, runtime, NULL, l, force, &changes, &n_changes);
1766 carries_install_info = r;
1767 } else if (streq(member, "LinkUnitFiles"))
1768 r = unit_file_link(scope, runtime, NULL, l, force, &changes, &n_changes);
1769 else if (streq(member, "PresetUnitFiles")) {
1770 r = unit_file_preset(scope, runtime, NULL, l, force, &changes, &n_changes);
1771 carries_install_info = r;
1772 } else if (streq(member, "MaskUnitFiles"))
1773 r = unit_file_mask(scope, runtime, NULL, l, force, &changes, &n_changes);
1775 assert_not_reached("Uh? Wrong method");
1778 bus_manager_send_unit_files_changed(m);
1781 unit_file_changes_free(changes, n_changes);
1782 return bus_send_error_reply(connection, message, NULL, r);
1785 reply = message_from_file_changes(message, changes, n_changes, carries_install_info);
1786 unit_file_changes_free(changes, n_changes);
1791 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "DisableUnitFiles") ||
1792 dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "UnmaskUnitFiles")) {
1795 DBusMessageIter iter;
1796 UnitFileScope scope = m->running_as == SYSTEMD_SYSTEM ? UNIT_FILE_SYSTEM : UNIT_FILE_USER;
1797 UnitFileChange *changes = NULL;
1798 unsigned n_changes = 0;
1799 dbus_bool_t runtime;
1801 SELINUX_ACCESS_CHECK(connection, message, streq(member, "UnmaskUnitFiles") ? "enable" : "disable");
1803 if (!dbus_message_iter_init(message, &iter))
1806 r = bus_parse_strv_iter(&iter, &l);
1811 return bus_send_error_reply(connection, message, NULL, r);
1814 if (!dbus_message_iter_next(&iter) ||
1815 bus_iter_get_basic_and_next(&iter, DBUS_TYPE_BOOLEAN, &runtime, false) < 0) {
1817 return bus_send_error_reply(connection, message, NULL, -EIO);
1820 if (streq(member, "DisableUnitFiles"))
1821 r = unit_file_disable(scope, runtime, NULL, l, &changes, &n_changes);
1822 else if (streq(member, "UnmaskUnitFiles"))
1823 r = unit_file_unmask(scope, runtime, NULL, l, &changes, &n_changes);
1825 assert_not_reached("Uh? Wrong method");
1828 bus_manager_send_unit_files_changed(m);
1831 unit_file_changes_free(changes, n_changes);
1832 return bus_send_error_reply(connection, message, NULL, r);
1835 reply = message_from_file_changes(message, changes, n_changes, -1);
1836 unit_file_changes_free(changes, n_changes);
1842 const BusBoundProperties bps[] = {
1843 { "org.freedesktop.systemd1.Manager", bus_systemd_properties, systemd_property_string },
1844 { "org.freedesktop.systemd1.Manager", bus_manager_properties, m },
1848 SELINUX_ACCESS_CHECK(connection, message, "status");
1850 return bus_default_message_handler(connection, message, NULL, INTERFACES_LIST, bps);
1853 if (job_type != _JOB_TYPE_INVALID) {
1854 const char *name, *smode, *old_name = NULL;
1859 if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "StartUnitReplace"))
1860 b = dbus_message_get_args(
1863 DBUS_TYPE_STRING, &old_name,
1864 DBUS_TYPE_STRING, &name,
1865 DBUS_TYPE_STRING, &smode,
1868 b = dbus_message_get_args(
1871 DBUS_TYPE_STRING, &name,
1872 DBUS_TYPE_STRING, &smode,
1875 return bus_send_error_reply(connection, message, &error, -EINVAL);
1878 u = manager_get_unit(m, old_name);
1879 if (!u || !u->job || u->job->type != JOB_START) {
1880 dbus_set_error(&error, BUS_ERROR_NO_SUCH_JOB, "No job queued for unit %s", old_name);
1881 return bus_send_error_reply(connection, message, &error, -ENOENT);
1885 mode = job_mode_from_string(smode);
1887 dbus_set_error(&error, BUS_ERROR_INVALID_JOB_MODE, "Job mode %s is invalid.", smode);
1888 return bus_send_error_reply(connection, message, &error, -EINVAL);
1891 r = manager_load_unit(m, name, NULL, &error, &u);
1893 return bus_send_error_reply(connection, message, &error, r);
1895 return bus_unit_queue_job(connection, message, u, job_type, mode, reload_if_possible);
1899 if (!bus_maybe_send_reply(connection, message, reply))
1902 return DBUS_HANDLER_RESULT_HANDLED;
1905 dbus_error_free(&error);
1907 return DBUS_HANDLER_RESULT_NEED_MEMORY;
1910 const DBusObjectPathVTable bus_manager_vtable = {
1911 .message_function = bus_manager_message_handler