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"
40 #define BUS_MANAGER_INTERFACE_BEGIN \
41 " <interface name=\"org.freedesktop.systemd1.Manager\">\n"
43 #define BUS_MANAGER_INTERFACE_METHODS \
44 " <method name=\"GetUnit\">\n" \
45 " <arg name=\"name\" type=\"s\" direction=\"in\"/>\n" \
46 " <arg name=\"unit\" type=\"o\" direction=\"out\"/>\n" \
48 " <method name=\"GetUnitByPID\">\n" \
49 " <arg name=\"pid\" type=\"u\" direction=\"in\"/>\n" \
50 " <arg name=\"unit\" type=\"o\" direction=\"out\"/>\n" \
52 " <method name=\"LoadUnit\">\n" \
53 " <arg name=\"name\" type=\"s\" direction=\"in\"/>\n" \
54 " <arg name=\"unit\" type=\"o\" direction=\"out\"/>\n" \
56 " <method name=\"StartUnit\">\n" \
57 " <arg name=\"name\" type=\"s\" direction=\"in\"/>\n" \
58 " <arg name=\"mode\" type=\"s\" direction=\"in\"/>\n" \
59 " <arg name=\"job\" type=\"o\" direction=\"out\"/>\n" \
61 " <method name=\"StartUnitReplace\">\n" \
62 " <arg name=\"old_unit\" type=\"s\" direction=\"in\"/>\n" \
63 " <arg name=\"new_unit\" type=\"s\" direction=\"in\"/>\n" \
64 " <arg name=\"mode\" type=\"s\" direction=\"in\"/>\n" \
65 " <arg name=\"job\" type=\"o\" direction=\"out\"/>\n" \
67 " <method name=\"StopUnit\">\n" \
68 " <arg name=\"name\" type=\"s\" direction=\"in\"/>\n" \
69 " <arg name=\"mode\" type=\"s\" direction=\"in\"/>\n" \
70 " <arg name=\"job\" type=\"o\" direction=\"out\"/>\n" \
72 " <method name=\"ReloadUnit\">\n" \
73 " <arg name=\"name\" type=\"s\" direction=\"in\"/>\n" \
74 " <arg name=\"mode\" type=\"s\" direction=\"in\"/>\n" \
75 " <arg name=\"job\" type=\"o\" direction=\"out\"/>\n" \
77 " <method name=\"RestartUnit\">\n" \
78 " <arg name=\"name\" type=\"s\" direction=\"in\"/>\n" \
79 " <arg name=\"mode\" type=\"s\" direction=\"in\"/>\n" \
80 " <arg name=\"job\" type=\"o\" direction=\"out\"/>\n" \
82 " <method name=\"TryRestartUnit\">\n" \
83 " <arg name=\"name\" type=\"s\" direction=\"in\"/>\n" \
84 " <arg name=\"mode\" type=\"s\" direction=\"in\"/>\n" \
85 " <arg name=\"job\" type=\"o\" direction=\"out\"/>\n" \
87 " <method name=\"ReloadOrRestartUnit\">\n" \
88 " <arg name=\"name\" type=\"s\" direction=\"in\"/>\n" \
89 " <arg name=\"mode\" type=\"s\" direction=\"in\"/>\n" \
90 " <arg name=\"job\" type=\"o\" direction=\"out\"/>\n" \
92 " <method name=\"ReloadOrTryRestartUnit\">\n" \
93 " <arg name=\"name\" type=\"s\" direction=\"in\"/>\n" \
94 " <arg name=\"mode\" type=\"s\" direction=\"in\"/>\n" \
95 " <arg name=\"job\" type=\"o\" direction=\"out\"/>\n" \
97 " <method name=\"KillUnit\">\n" \
98 " <arg name=\"name\" type=\"s\" direction=\"in\"/>\n" \
99 " <arg name=\"who\" type=\"s\" direction=\"in\"/>\n" \
100 " <arg name=\"signal\" type=\"i\" direction=\"in\"/>\n" \
102 " <method name=\"ResetFailedUnit\">\n" \
103 " <arg name=\"name\" type=\"s\" direction=\"in\"/>\n" \
105 " <method name=\"GetJob\">\n" \
106 " <arg name=\"id\" type=\"u\" direction=\"in\"/>\n" \
107 " <arg name=\"job\" type=\"o\" direction=\"out\"/>\n" \
109 " <method name=\"CancelJob\">\n" \
110 " <arg name=\"id\" type=\"u\" direction=\"in\"/>\n" \
112 " <method name=\"ClearJobs\"/>\n" \
113 " <method name=\"ResetFailed\"/>\n" \
114 " <method name=\"ListUnits\">\n" \
115 " <arg name=\"units\" type=\"a(ssssssouso)\" direction=\"out\"/>\n" \
117 " <method name=\"ListJobs\">\n" \
118 " <arg name=\"jobs\" type=\"a(usssoo)\" direction=\"out\"/>\n" \
120 " <method name=\"Subscribe\"/>\n" \
121 " <method name=\"Unsubscribe\"/>\n" \
122 " <method name=\"Dump\">\n" \
123 " <arg name=\"dump\" type=\"s\" direction=\"out\"/>\n" \
125 " <method name=\"CreateSnapshot\">\n" \
126 " <arg name=\"name\" type=\"s\" direction=\"in\"/>\n" \
127 " <arg name=\"cleanup\" type=\"b\" direction=\"in\"/>\n" \
128 " <arg name=\"unit\" type=\"o\" direction=\"out\"/>\n" \
130 " <method name=\"RemoveSnapshot\">\n" \
131 " <arg name=\"name\" type=\"s\" direction=\"in\"/>\n" \
133 " <method name=\"Reload\"/>\n" \
134 " <method name=\"Reexecute\"/>\n" \
135 " <method name=\"Exit\"/>\n" \
136 " <method name=\"Reboot\"/>\n" \
137 " <method name=\"PowerOff\"/>\n" \
138 " <method name=\"Halt\"/>\n" \
139 " <method name=\"KExec\"/>\n" \
140 " <method name=\"SwitchRoot\">\n" \
141 " <arg name=\"new_root\" type=\"s\" direction=\"in\"/>\n" \
142 " <arg name=\"init\" type=\"s\" direction=\"in\"/>\n" \
144 " <method name=\"SetEnvironment\">\n" \
145 " <arg name=\"names\" type=\"as\" direction=\"in\"/>\n" \
147 " <method name=\"UnsetEnvironment\">\n" \
148 " <arg name=\"names\" type=\"as\" direction=\"in\"/>\n" \
150 " <method name=\"UnsetAndSetEnvironment\">\n" \
151 " <arg name=\"unset\" type=\"as\" direction=\"in\"/>\n" \
152 " <arg name=\"set\" type=\"as\" direction=\"in\"/>\n" \
154 " <method name=\"ListUnitFiles\">\n" \
155 " <arg name=\"files\" type=\"a(ss)\" direction=\"out\"/>\n" \
157 " <method name=\"GetUnitFileState\">\n" \
158 " <arg name=\"file\" type=\"s\" direction=\"in\"/>\n" \
159 " <arg name=\"state\" type=\"s\" direction=\"out\"/>\n" \
161 " <method name=\"EnableUnitFiles\">\n" \
162 " <arg name=\"files\" type=\"as\" direction=\"in\"/>\n" \
163 " <arg name=\"runtime\" type=\"b\" direction=\"in\"/>\n" \
164 " <arg name=\"force\" type=\"b\" direction=\"in\"/>\n" \
165 " <arg name=\"carries_install_info\" type=\"b\" direction=\"out\"/>\n" \
166 " <arg name=\"changes\" type=\"a(sss)\" direction=\"out\"/>\n" \
168 " <method name=\"DisableUnitFiles\">\n" \
169 " <arg name=\"files\" type=\"as\" direction=\"in\"/>\n" \
170 " <arg name=\"runtime\" type=\"b\" direction=\"in\"/>\n" \
171 " <arg name=\"changes\" type=\"a(sss)\" direction=\"out\"/>\n" \
173 " <method name=\"ReenableUnitFiles\">\n" \
174 " <arg name=\"files\" type=\"as\" direction=\"in\"/>\n" \
175 " <arg name=\"runtime\" type=\"b\" direction=\"in\"/>\n" \
176 " <arg name=\"force\" type=\"b\" direction=\"in\"/>\n" \
177 " <arg name=\"carries_install_info\" type=\"b\" direction=\"out\"/>\n" \
178 " <arg name=\"changes\" type=\"a(sss)\" direction=\"out\"/>\n" \
180 " <method name=\"LinkUnitFiles\">\n" \
181 " <arg name=\"files\" type=\"as\" direction=\"in\"/>\n" \
182 " <arg name=\"runtime\" type=\"b\" direction=\"in\"/>\n" \
183 " <arg name=\"force\" type=\"b\" direction=\"in\"/>\n" \
184 " <arg name=\"changes\" type=\"a(sss)\" direction=\"out\"/>\n" \
186 " <method name=\"PresetUnitFiles\">\n" \
187 " <arg name=\"files\" type=\"as\" direction=\"in\"/>\n" \
188 " <arg name=\"runtime\" type=\"b\" direction=\"in\"/>\n" \
189 " <arg name=\"force\" type=\"b\" direction=\"in\"/>\n" \
190 " <arg name=\"carries_install_info\" type=\"b\" direction=\"out\"/>\n" \
191 " <arg name=\"changes\" type=\"a(sss)\" direction=\"out\"/>\n" \
193 " <method name=\"MaskUnitFiles\">\n" \
194 " <arg name=\"files\" type=\"as\" direction=\"in\"/>\n" \
195 " <arg name=\"runtime\" type=\"b\" direction=\"in\"/>\n" \
196 " <arg name=\"force\" type=\"b\" direction=\"in\"/>\n" \
197 " <arg name=\"changes\" type=\"a(sss)\" direction=\"out\"/>\n" \
199 " <method name=\"UnmaskUnitFiles\">\n" \
200 " <arg name=\"files\" type=\"as\" direction=\"in\"/>\n" \
201 " <arg name=\"runtime\" type=\"b\" direction=\"in\"/>\n" \
202 " <arg name=\"changes\" type=\"a(sss)\" direction=\"out\"/>\n" \
205 #define BUS_MANAGER_INTERFACE_SIGNALS \
206 " <signal name=\"UnitNew\">\n" \
207 " <arg name=\"id\" type=\"s\"/>\n" \
208 " <arg name=\"unit\" type=\"o\"/>\n" \
210 " <signal name=\"UnitRemoved\">\n" \
211 " <arg name=\"id\" type=\"s\"/>\n" \
212 " <arg name=\"unit\" type=\"o\"/>\n" \
214 " <signal name=\"JobNew\">\n" \
215 " <arg name=\"id\" type=\"u\"/>\n" \
216 " <arg name=\"job\" type=\"o\"/>\n" \
217 " <arg name=\"unit\" type=\"s\"/>\n" \
219 " <signal name=\"JobRemoved\">\n" \
220 " <arg name=\"id\" type=\"u\"/>\n" \
221 " <arg name=\"job\" type=\"o\"/>\n" \
222 " <arg name=\"unit\" type=\"s\"/>\n" \
223 " <arg name=\"result\" type=\"s\"/>\n" \
225 " <signal name=\"StartupFinished\">\n" \
226 " <arg name=\"firmware\" type=\"t\"/>\n" \
227 " <arg name=\"loader\" type=\"t\"/>\n" \
228 " <arg name=\"kernel\" type=\"t\"/>\n" \
229 " <arg name=\"initrd\" type=\"t\"/>\n" \
230 " <arg name=\"userspace\" type=\"t\"/>\n" \
231 " <arg name=\"total\" type=\"t\"/>\n" \
233 " <signal name=\"UnitFilesChanged\"/>\n"
235 #define BUS_MANAGER_INTERFACE_PROPERTIES_GENERAL \
236 " <property name=\"Version\" type=\"s\" access=\"read\"/>\n" \
237 " <property name=\"Features\" type=\"s\" access=\"read\"/>\n" \
238 " <property name=\"Tainted\" type=\"s\" access=\"read\"/>\n" \
239 " <property name=\"FirmwareTimestamp\" type=\"t\" access=\"read\"/>\n" \
240 " <property name=\"FirmwareTimestampMonotonic\" type=\"t\" access=\"read\"/>\n" \
241 " <property name=\"LoaderTimestamp\" type=\"t\" access=\"read\"/>\n" \
242 " <property name=\"LoaderTimestampMonotonic\" type=\"t\" access=\"read\"/>\n" \
243 " <property name=\"KernelTimestamp\" type=\"t\" access=\"read\"/>\n" \
244 " <property name=\"KernelTimestampMonotonic\" type=\"t\" access=\"read\"/>\n" \
245 " <property name=\"InitRDTimestamp\" type=\"t\" access=\"read\"/>\n" \
246 " <property name=\"InitRDTimestampMonotonic\" type=\"t\" access=\"read\"/>\n" \
247 " <property name=\"UserspaceTimestamp\" type=\"t\" access=\"read\"/>\n" \
248 " <property name=\"UserspaceTimestampMonotonic\" type=\"t\" access=\"read\"/>\n" \
249 " <property name=\"FinishTimestamp\" type=\"t\" access=\"read\"/>\n" \
250 " <property name=\"FinishTimestampMonotonic\" type=\"t\" access=\"read\"/>\n" \
251 " <property name=\"LogLevel\" type=\"s\" access=\"readwrite\"/>\n" \
252 " <property name=\"LogTarget\" type=\"s\" access=\"readwrite\"/>\n" \
253 " <property name=\"NNames\" type=\"u\" access=\"read\"/>\n" \
254 " <property name=\"NJobs\" type=\"u\" access=\"read\"/>\n" \
255 " <property name=\"NInstalledJobs\" type=\"u\" access=\"read\"/>\n" \
256 " <property name=\"NFailedJobs\" type=\"u\" access=\"read\"/>\n" \
257 " <property name=\"Progress\" type=\"d\" access=\"read\"/>\n" \
258 " <property name=\"Environment\" type=\"as\" access=\"read\"/>\n" \
259 " <property name=\"ConfirmSpawn\" type=\"b\" access=\"read\"/>\n" \
260 " <property name=\"ShowStatus\" type=\"b\" access=\"read\"/>\n" \
261 " <property name=\"UnitPath\" type=\"as\" access=\"read\"/>\n" \
262 " <property name=\"ControlGroupHierarchy\" type=\"s\" access=\"read\"/>\n" \
263 " <property name=\"DefaultControllers\" type=\"as\" access=\"read\"/>\n" \
264 " <property name=\"DefaultStandardOutput\" type=\"s\" access=\"read\"/>\n" \
265 " <property name=\"DefaultStandardError\" type=\"s\" access=\"read\"/>\n" \
266 " <property name=\"RuntimeWatchdogUSec\" type=\"s\" access=\"readwrite\"/>\n" \
267 " <property name=\"ShutdownWatchdogUSec\" type=\"s\" access=\"readwrite\"/>\n" \
268 " <property name=\"Virtualization\" type=\"s\" access=\"read\"/>\n"
270 #define BUS_MANAGER_INTERFACE_END \
273 #define BUS_MANAGER_INTERFACE \
274 BUS_MANAGER_INTERFACE_BEGIN \
275 BUS_MANAGER_INTERFACE_METHODS \
276 BUS_MANAGER_INTERFACE_SIGNALS \
277 BUS_MANAGER_INTERFACE_PROPERTIES_GENERAL \
278 BUS_MANAGER_INTERFACE_END
280 #define INTROSPECTION_BEGIN \
281 DBUS_INTROSPECT_1_0_XML_DOCTYPE_DECL_NODE \
283 BUS_MANAGER_INTERFACE \
284 BUS_PROPERTIES_INTERFACE \
286 BUS_INTROSPECTABLE_INTERFACE
288 #define INTROSPECTION_END \
291 #define INTERFACES_LIST \
292 BUS_GENERIC_INTERFACES_LIST \
293 "org.freedesktop.systemd1.Manager\0"
295 const char bus_manager_interface[] _introspect_("Manager") = BUS_MANAGER_INTERFACE;
297 static DEFINE_BUS_PROPERTY_APPEND_ENUM(bus_manager_append_exec_output, exec_output, ExecOutput);
299 static int bus_manager_append_tainted(DBusMessageIter *i, const char *property, void *data) {
302 char buf[LINE_MAX] = "", *e = buf, *p = NULL;
309 e = stpcpy(e, "split-usr:");
311 if (readlink_malloc("/etc/mtab", &p) < 0)
312 e = stpcpy(e, "mtab-not-symlink:");
316 if (access("/proc/cgroups", F_OK) < 0)
317 e = stpcpy(e, "cgroups-missing:");
319 if (hwclock_is_localtime() > 0)
320 e = stpcpy(e, "local-hwclock:");
322 /* remove the last ':' */
328 if (!dbus_message_iter_append_basic(i, DBUS_TYPE_STRING, &t))
334 static int bus_manager_append_log_target(DBusMessageIter *i, const char *property, void *data) {
340 t = log_target_to_string(log_get_target());
342 if (!dbus_message_iter_append_basic(i, DBUS_TYPE_STRING, &t))
348 static int bus_manager_set_log_target(DBusMessageIter *i, const char *property, void *data) {
354 dbus_message_iter_get_basic(i, &t);
356 return log_set_target_from_string(t);
359 static int bus_manager_append_log_level(DBusMessageIter *i, const char *property, void *data) {
366 r = log_level_to_string_alloc(log_get_max_level(), &t);
370 if (!dbus_message_iter_append_basic(i, DBUS_TYPE_STRING, &t))
377 static int bus_manager_set_log_level(DBusMessageIter *i, const char *property, void *data) {
383 dbus_message_iter_get_basic(i, &t);
385 return log_set_max_level_from_string(t);
388 static int bus_manager_append_n_names(DBusMessageIter *i, const char *property, void *data) {
396 u = hashmap_size(m->units);
398 if (!dbus_message_iter_append_basic(i, DBUS_TYPE_UINT32, &u))
404 static int bus_manager_append_n_jobs(DBusMessageIter *i, const char *property, void *data) {
412 u = hashmap_size(m->jobs);
414 if (!dbus_message_iter_append_basic(i, DBUS_TYPE_UINT32, &u))
420 static int bus_manager_append_progress(DBusMessageIter *i, const char *property, void *data) {
428 if (dual_timestamp_is_set(&m->finish_timestamp))
431 d = 1.0 - ((double) hashmap_size(m->jobs) / (double) m->n_installed_jobs);
433 if (!dbus_message_iter_append_basic(i, DBUS_TYPE_DOUBLE, &d))
439 static int bus_manager_append_virt(DBusMessageIter *i, const char *property, void *data) {
447 detect_virtualization(&id);
449 if (!dbus_message_iter_append_basic(i, DBUS_TYPE_STRING, &id))
455 static DBusMessage *message_from_file_changes(
457 UnitFileChange *changes,
459 int carries_install_info) {
461 DBusMessageIter iter, sub, sub2;
465 reply = dbus_message_new_method_return(m);
469 dbus_message_iter_init_append(reply, &iter);
471 if (carries_install_info >= 0) {
474 b = !!carries_install_info;
475 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &b))
479 if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "(sss)", &sub))
482 for (i = 0; i < n_changes; i++) {
483 const char *type, *path, *source;
485 type = unit_file_change_type_to_string(changes[i].type);
486 path = strempty(changes[i].path);
487 source = strempty(changes[i].source);
489 if (!dbus_message_iter_open_container(&sub, DBUS_TYPE_STRUCT, NULL, &sub2) ||
490 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &type) ||
491 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &path) ||
492 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &source) ||
493 !dbus_message_iter_close_container(&sub, &sub2))
497 if (!dbus_message_iter_close_container(&iter, &sub))
503 dbus_message_unref(reply);
507 static int bus_manager_send_unit_files_changed(Manager *m) {
511 s = dbus_message_new_signal("/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", "UnitFilesChanged");
515 r = bus_broadcast(m, s);
516 dbus_message_unref(s);
521 static int bus_manager_set_runtime_watchdog_usec(DBusMessageIter *i, const char *property, void *data) {
527 dbus_message_iter_get_basic(i, t);
529 return watchdog_set_timeout(t);
532 static const char systemd_property_string[] =
536 static const BusProperty bus_systemd_properties[] = {
537 { "Version", bus_property_append_string, "s", 0 },
538 { "Features", bus_property_append_string, "s", sizeof(PACKAGE_STRING) },
542 static const BusProperty bus_manager_properties[] = {
543 { "Tainted", bus_manager_append_tainted, "s", 0 },
544 { "FirmwareTimestamp", bus_property_append_uint64, "t", offsetof(Manager, firmware_timestamp.realtime) },
545 { "FirmwareTimestampMonotonic", bus_property_append_uint64, "t", offsetof(Manager, firmware_timestamp.monotonic) },
546 { "LoaderTimestamp", bus_property_append_uint64, "t", offsetof(Manager, loader_timestamp.realtime) },
547 { "LoaderTimestampMonotonic", bus_property_append_uint64, "t", offsetof(Manager, loader_timestamp.monotonic) },
548 { "KernelTimestamp", bus_property_append_uint64, "t", offsetof(Manager, kernel_timestamp.realtime) },
549 { "KernelTimestampMonotonic", bus_property_append_uint64, "t", offsetof(Manager, kernel_timestamp.monotonic) },
550 { "InitRDTimestamp", bus_property_append_uint64, "t", offsetof(Manager, initrd_timestamp.realtime) },
551 { "InitRDTimestampMonotonic", bus_property_append_uint64, "t", offsetof(Manager, initrd_timestamp.monotonic) },
552 { "UserspaceTimestamp", bus_property_append_uint64, "t", offsetof(Manager, userspace_timestamp.realtime) },
553 { "UserspaceTimestampMonotonic", bus_property_append_uint64, "t", offsetof(Manager, userspace_timestamp.monotonic) },
554 { "FinishTimestamp", bus_property_append_uint64, "t", offsetof(Manager, finish_timestamp.realtime) },
555 { "FinishTimestampMonotonic", bus_property_append_uint64, "t", offsetof(Manager, finish_timestamp.monotonic) },
556 { "LogLevel", bus_manager_append_log_level, "s", 0, false, bus_manager_set_log_level },
557 { "LogTarget", bus_manager_append_log_target, "s", 0, false, bus_manager_set_log_target },
558 { "NNames", bus_manager_append_n_names, "u", 0 },
559 { "NJobs", bus_manager_append_n_jobs, "u", 0 },
560 { "NInstalledJobs", bus_property_append_uint32, "u", offsetof(Manager, n_installed_jobs) },
561 { "NFailedJobs", bus_property_append_uint32, "u", offsetof(Manager, n_failed_jobs) },
562 { "Progress", bus_manager_append_progress, "d", 0 },
563 { "Environment", bus_property_append_strv, "as", offsetof(Manager, environment), true },
564 { "ConfirmSpawn", bus_property_append_bool, "b", offsetof(Manager, confirm_spawn) },
565 { "ShowStatus", bus_property_append_bool, "b", offsetof(Manager, show_status) },
566 { "UnitPath", bus_property_append_strv, "as", offsetof(Manager, lookup_paths.unit_path), true },
567 { "ControlGroupHierarchy", bus_property_append_string, "s", offsetof(Manager, cgroup_hierarchy), true },
568 { "DefaultControllers", bus_property_append_strv, "as", offsetof(Manager, default_controllers), true },
569 { "DefaultStandardOutput", bus_manager_append_exec_output, "s", offsetof(Manager, default_std_output) },
570 { "DefaultStandardError", bus_manager_append_exec_output, "s", offsetof(Manager, default_std_error) },
571 { "RuntimeWatchdogUSec", bus_property_append_usec, "t", offsetof(Manager, runtime_watchdog), false, bus_manager_set_runtime_watchdog_usec },
572 { "ShutdownWatchdogUSec", bus_property_append_usec, "t", offsetof(Manager, shutdown_watchdog), false, bus_property_set_usec },
573 { "Virtualization", bus_manager_append_virt, "s", 0, },
577 static DBusHandlerResult bus_manager_message_handler(DBusConnection *connection, DBusMessage *message, void *data) {
578 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
579 _cleanup_free_ char * path = NULL;
583 JobType job_type = _JOB_TYPE_INVALID;
584 bool reload_if_possible = false;
591 dbus_error_init(&error);
593 member = dbus_message_get_member(message);
595 if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "GetUnit")) {
599 if (!dbus_message_get_args(
602 DBUS_TYPE_STRING, &name,
604 return bus_send_error_reply(connection, message, &error, -EINVAL);
606 u = manager_get_unit(m, name);
608 dbus_set_error(&error, BUS_ERROR_NO_SUCH_UNIT, "Unit %s is not loaded.", name);
609 return bus_send_error_reply(connection, message, &error, -ENOENT);
612 SELINUX_UNIT_ACCESS_CHECK(u, connection, message, "status");
614 reply = dbus_message_new_method_return(message);
618 path = unit_dbus_path(u);
622 if (!dbus_message_append_args(
624 DBUS_TYPE_OBJECT_PATH, &path,
627 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "GetUnitByPID")) {
631 if (!dbus_message_get_args(
634 DBUS_TYPE_UINT32, &pid,
636 return bus_send_error_reply(connection, message, &error, -EINVAL);
638 u = cgroup_unit_by_pid(m, (pid_t) pid);
640 dbus_set_error(&error, BUS_ERROR_NO_SUCH_UNIT, "No unit for PID %lu is loaded.", (unsigned long) pid);
641 return bus_send_error_reply(connection, message, &error, -ENOENT);
644 SELINUX_UNIT_ACCESS_CHECK(u, connection, message, "status");
646 reply = dbus_message_new_method_return(message);
650 path = unit_dbus_path(u);
654 if (!dbus_message_append_args(
656 DBUS_TYPE_OBJECT_PATH, &path,
659 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "LoadUnit")) {
663 if (!dbus_message_get_args(
666 DBUS_TYPE_STRING, &name,
668 return bus_send_error_reply(connection, message, &error, -EINVAL);
670 r = manager_load_unit(m, name, NULL, &error, &u);
672 return bus_send_error_reply(connection, message, &error, r);
674 SELINUX_UNIT_ACCESS_CHECK(u, connection, message, "status");
676 reply = dbus_message_new_method_return(message);
680 path = unit_dbus_path(u);
684 if (!dbus_message_append_args(
686 DBUS_TYPE_OBJECT_PATH, &path,
690 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "StartUnit"))
691 job_type = JOB_START;
692 else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "StartUnitReplace"))
693 job_type = JOB_START;
694 else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "StopUnit"))
696 else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ReloadUnit"))
697 job_type = JOB_RELOAD;
698 else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "RestartUnit"))
699 job_type = JOB_RESTART;
700 else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "TryRestartUnit"))
701 job_type = JOB_TRY_RESTART;
702 else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ReloadOrRestartUnit")) {
703 reload_if_possible = true;
704 job_type = JOB_RESTART;
705 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ReloadOrTryRestartUnit")) {
706 reload_if_possible = true;
707 job_type = JOB_TRY_RESTART;
708 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "KillUnit")) {
709 const char *name, *swho;
714 if (!dbus_message_get_args(
717 DBUS_TYPE_STRING, &name,
718 DBUS_TYPE_STRING, &swho,
719 DBUS_TYPE_INT32, &signo,
721 return bus_send_error_reply(connection, message, &error, -EINVAL);
726 who = kill_who_from_string(swho);
728 return bus_send_error_reply(connection, message, &error, -EINVAL);
731 if (signo <= 0 || signo >= _NSIG)
732 return bus_send_error_reply(connection, message, &error, -EINVAL);
734 u = manager_get_unit(m, name);
736 dbus_set_error(&error, BUS_ERROR_NO_SUCH_UNIT, "Unit %s is not loaded.", name);
737 return bus_send_error_reply(connection, message, &error, -ENOENT);
740 SELINUX_UNIT_ACCESS_CHECK(u, connection, message, "stop");
742 r = unit_kill(u, who, signo, &error);
744 return bus_send_error_reply(connection, message, &error, r);
746 reply = dbus_message_new_method_return(message);
750 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "GetJob")) {
754 if (!dbus_message_get_args(
757 DBUS_TYPE_UINT32, &id,
759 return bus_send_error_reply(connection, message, &error, -EINVAL);
761 j = manager_get_job(m, id);
763 dbus_set_error(&error, BUS_ERROR_NO_SUCH_JOB, "Job %u does not exist.", (unsigned) id);
764 return bus_send_error_reply(connection, message, &error, -ENOENT);
767 SELINUX_UNIT_ACCESS_CHECK(j->unit, connection, message, "status");
769 reply = dbus_message_new_method_return(message);
773 path = job_dbus_path(j);
777 if (!dbus_message_append_args(
779 DBUS_TYPE_OBJECT_PATH, &path,
783 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "CancelJob")) {
787 if (!dbus_message_get_args(
790 DBUS_TYPE_UINT32, &id,
792 return bus_send_error_reply(connection, message, &error, -EINVAL);
794 j = manager_get_job(m, id);
796 dbus_set_error(&error, BUS_ERROR_NO_SUCH_JOB, "Job %u does not exist.", (unsigned) id);
797 return bus_send_error_reply(connection, message, &error, -ENOENT);
800 SELINUX_UNIT_ACCESS_CHECK(j->unit, connection, message, "stop");
801 job_finish_and_invalidate(j, JOB_CANCELED, true);
803 reply = dbus_message_new_method_return(message);
807 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ClearJobs")) {
809 SELINUX_ACCESS_CHECK(connection, message, "reboot");
810 manager_clear_jobs(m);
812 reply = dbus_message_new_method_return(message);
816 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ResetFailed")) {
818 SELINUX_ACCESS_CHECK(connection, message, "reload");
820 manager_reset_failed(m);
822 reply = dbus_message_new_method_return(message);
826 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ResetFailedUnit")) {
830 if (!dbus_message_get_args(
833 DBUS_TYPE_STRING, &name,
835 return bus_send_error_reply(connection, message, &error, -EINVAL);
837 u = manager_get_unit(m, name);
839 dbus_set_error(&error, BUS_ERROR_NO_SUCH_UNIT, "Unit %s is not loaded.", name);
840 return bus_send_error_reply(connection, message, &error, -ENOENT);
843 SELINUX_UNIT_ACCESS_CHECK(u, connection, message, "reload");
845 unit_reset_failed(u);
847 reply = dbus_message_new_method_return(message);
851 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ListUnits")) {
852 DBusMessageIter iter, sub;
857 SELINUX_ACCESS_CHECK(connection, message, "status");
859 reply = dbus_message_new_method_return(message);
863 dbus_message_iter_init_append(reply, &iter);
865 if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "(ssssssouso)", &sub))
868 HASHMAP_FOREACH_KEY(u, k, m->units, i) {
869 char *u_path, *j_path;
870 const char *description, *load_state, *active_state, *sub_state, *sjob_type, *following;
871 DBusMessageIter sub2;
878 if (!dbus_message_iter_open_container(&sub, DBUS_TYPE_STRUCT, NULL, &sub2))
881 description = unit_description(u);
882 load_state = unit_load_state_to_string(u->load_state);
883 active_state = unit_active_state_to_string(unit_active_state(u));
884 sub_state = unit_sub_state_to_string(u);
886 f = unit_following(u);
887 following = f ? f->id : "";
889 u_path = unit_dbus_path(u);
894 job_id = (uint32_t) u->job->id;
896 if (!(j_path = job_dbus_path(u->job))) {
901 sjob_type = job_type_to_string(u->job->type);
908 if (!dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &u->id) ||
909 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &description) ||
910 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &load_state) ||
911 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &active_state) ||
912 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &sub_state) ||
913 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &following) ||
914 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_OBJECT_PATH, &u_path) ||
915 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_UINT32, &job_id) ||
916 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &sjob_type) ||
917 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_OBJECT_PATH, &j_path)) {
928 if (!dbus_message_iter_close_container(&sub, &sub2))
932 if (!dbus_message_iter_close_container(&iter, &sub))
935 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ListJobs")) {
936 DBusMessageIter iter, sub;
940 SELINUX_ACCESS_CHECK(connection, message, "status");
942 reply = dbus_message_new_method_return(message);
946 dbus_message_iter_init_append(reply, &iter);
948 if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "(usssoo)", &sub))
951 HASHMAP_FOREACH(j, m->jobs, i) {
952 char *u_path, *j_path;
953 const char *state, *type;
955 DBusMessageIter sub2;
957 if (!dbus_message_iter_open_container(&sub, DBUS_TYPE_STRUCT, NULL, &sub2))
960 id = (uint32_t) j->id;
961 state = job_state_to_string(j->state);
962 type = job_type_to_string(j->type);
964 j_path = job_dbus_path(j);
968 u_path = unit_dbus_path(j->unit);
974 if (!dbus_message_iter_append_basic(&sub2, DBUS_TYPE_UINT32, &id) ||
975 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &j->unit->id) ||
976 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &type) ||
977 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &state) ||
978 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_OBJECT_PATH, &j_path) ||
979 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_OBJECT_PATH, &u_path)) {
988 if (!dbus_message_iter_close_container(&sub, &sub2))
992 if (!dbus_message_iter_close_container(&iter, &sub))
995 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "Subscribe")) {
999 SELINUX_ACCESS_CHECK(connection, message, "status");
1001 s = BUS_CONNECTION_SUBSCRIBED(m, connection);
1003 s = set_new(string_hash_func, string_compare_func);
1007 if (!dbus_connection_set_data(connection, m->subscribed_data_slot, s, NULL)) {
1013 client = strdup(bus_message_get_sender_with_fallback(message));
1017 r = set_put(s, client);
1020 return bus_send_error_reply(connection, message, NULL, r);
1023 reply = dbus_message_new_method_return(message);
1027 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "Unsubscribe")) {
1030 SELINUX_ACCESS_CHECK(connection, message, "status");
1032 client = set_remove(BUS_CONNECTION_SUBSCRIBED(m, connection), (char*) bus_message_get_sender_with_fallback(message));
1034 dbus_set_error(&error, BUS_ERROR_NOT_SUBSCRIBED, "Client is not subscribed.");
1035 return bus_send_error_reply(connection, message, &error, -ENOENT);
1040 reply = dbus_message_new_method_return(message);
1044 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "Dump")) {
1049 SELINUX_ACCESS_CHECK(connection, message, "status");
1051 reply = dbus_message_new_method_return(message);
1055 f = open_memstream(&dump, &size);
1059 manager_dump_units(m, f, NULL);
1060 manager_dump_jobs(m, f, NULL);
1070 if (!dbus_message_append_args(reply, DBUS_TYPE_STRING, &dump, DBUS_TYPE_INVALID)) {
1076 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "CreateSnapshot")) {
1078 dbus_bool_t cleanup;
1081 SELINUX_ACCESS_CHECK(connection, message, "start");
1083 if (!dbus_message_get_args(
1086 DBUS_TYPE_STRING, &name,
1087 DBUS_TYPE_BOOLEAN, &cleanup,
1089 return bus_send_error_reply(connection, message, &error, -EINVAL);
1094 r = snapshot_create(m, name, cleanup, &error, &s);
1096 return bus_send_error_reply(connection, message, &error, r);
1098 reply = dbus_message_new_method_return(message);
1102 path = unit_dbus_path(UNIT(s));
1106 if (!dbus_message_append_args(
1108 DBUS_TYPE_OBJECT_PATH, &path,
1112 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "RemoveSnapshot")) {
1116 if (!dbus_message_get_args(
1119 DBUS_TYPE_STRING, &name,
1121 return bus_send_error_reply(connection, message, &error, -EINVAL);
1123 u = manager_get_unit(m, name);
1125 dbus_set_error(&error, BUS_ERROR_NO_SUCH_UNIT, "Unit %s does not exist.", name);
1126 return bus_send_error_reply(connection, message, &error, -ENOENT);
1129 if (u->type != UNIT_SNAPSHOT) {
1130 dbus_set_error(&error, BUS_ERROR_NO_SUCH_UNIT, "Unit %s is not a snapshot.", name);
1131 return bus_send_error_reply(connection, message, &error, -ENOENT);
1134 SELINUX_UNIT_ACCESS_CHECK(u, connection, message, "stop");
1135 snapshot_remove(SNAPSHOT(u));
1137 reply = dbus_message_new_method_return(message);
1141 } else if (dbus_message_is_method_call(message, "org.freedesktop.DBus.Introspectable", "Introspect")) {
1142 char *introspection = NULL;
1150 SELINUX_ACCESS_CHECK(connection, message, "status");
1152 reply = dbus_message_new_method_return(message);
1156 /* We roll our own introspection code here, instead of
1157 * relying on bus_default_message_handler() because we
1158 * need to generate our introspection string
1161 f = open_memstream(&introspection, &size);
1165 fputs(INTROSPECTION_BEGIN, f);
1167 HASHMAP_FOREACH_KEY(u, k, m->units, i) {
1173 p = bus_path_escape(k);
1176 free(introspection);
1180 fprintf(f, "<node name=\"unit/%s\"/>", p);
1184 HASHMAP_FOREACH(j, m->jobs, i)
1185 fprintf(f, "<node name=\"job/%lu\"/>", (unsigned long) j->id);
1187 fputs(INTROSPECTION_END, f);
1191 free(introspection);
1200 if (!dbus_message_append_args(reply, DBUS_TYPE_STRING, &introspection, DBUS_TYPE_INVALID)) {
1201 free(introspection);
1205 free(introspection);
1207 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "Reload")) {
1209 SELINUX_ACCESS_CHECK(connection, message, "reload");
1211 assert(!m->queued_message);
1213 /* Instead of sending the reply back right away, we
1214 * just remember that we need to and then send it
1215 * after the reload is finished. That way the caller
1216 * knows when the reload finished. */
1218 m->queued_message = dbus_message_new_method_return(message);
1219 if (!m->queued_message)
1222 m->queued_message_connection = connection;
1223 m->exit_code = MANAGER_RELOAD;
1225 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "Reexecute")) {
1227 SELINUX_ACCESS_CHECK(connection, message, "reload");
1229 /* We don't send a reply back here, the client should
1230 * just wait for us disconnecting. */
1232 m->exit_code = MANAGER_REEXECUTE;
1234 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "Exit")) {
1236 SELINUX_ACCESS_CHECK(connection, message, "halt");
1238 if (m->running_as == SYSTEMD_SYSTEM) {
1239 dbus_set_error(&error, BUS_ERROR_NOT_SUPPORTED, "Exit is only supported for user service managers.");
1240 return bus_send_error_reply(connection, message, &error, -ENOTSUP);
1243 reply = dbus_message_new_method_return(message);
1247 m->exit_code = MANAGER_EXIT;
1249 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "Reboot")) {
1251 SELINUX_ACCESS_CHECK(connection, message, "reboot");
1253 if (m->running_as != SYSTEMD_SYSTEM) {
1254 dbus_set_error(&error, BUS_ERROR_NOT_SUPPORTED, "Reboot is only supported for system managers.");
1255 return bus_send_error_reply(connection, message, &error, -ENOTSUP);
1258 reply = dbus_message_new_method_return(message);
1262 m->exit_code = MANAGER_REBOOT;
1264 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "PowerOff")) {
1266 SELINUX_ACCESS_CHECK(connection, message, "halt");
1268 if (m->running_as != SYSTEMD_SYSTEM) {
1269 dbus_set_error(&error, BUS_ERROR_NOT_SUPPORTED, "Powering off is only supported for system managers.");
1270 return bus_send_error_reply(connection, message, &error, -ENOTSUP);
1273 reply = dbus_message_new_method_return(message);
1277 m->exit_code = MANAGER_POWEROFF;
1279 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "Halt")) {
1281 SELINUX_ACCESS_CHECK(connection, message, "halt");
1283 if (m->running_as != SYSTEMD_SYSTEM) {
1284 dbus_set_error(&error, BUS_ERROR_NOT_SUPPORTED, "Halting is only supported for system managers.");
1285 return bus_send_error_reply(connection, message, &error, -ENOTSUP);
1288 reply = dbus_message_new_method_return(message);
1292 m->exit_code = MANAGER_HALT;
1294 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "KExec")) {
1296 SELINUX_ACCESS_CHECK(connection, message, "reboot");
1298 if (m->running_as != SYSTEMD_SYSTEM) {
1299 dbus_set_error(&error, BUS_ERROR_NOT_SUPPORTED, "kexec is only supported for system managers.");
1300 return bus_send_error_reply(connection, message, &error, -ENOTSUP);
1303 reply = dbus_message_new_method_return(message);
1307 m->exit_code = MANAGER_KEXEC;
1309 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "SwitchRoot")) {
1310 const char *switch_root, *switch_root_init;
1314 SELINUX_ACCESS_CHECK(connection, message, "reboot");
1316 if (!dbus_message_get_args(
1319 DBUS_TYPE_STRING, &switch_root,
1320 DBUS_TYPE_STRING, &switch_root_init,
1322 return bus_send_error_reply(connection, message, &error, -EINVAL);
1324 if (path_equal(switch_root, "/") || !path_is_absolute(switch_root))
1325 return bus_send_error_reply(connection, message, NULL, -EINVAL);
1327 if (!isempty(switch_root_init) && !path_is_absolute(switch_root_init))
1328 return bus_send_error_reply(connection, message, NULL, -EINVAL);
1330 if (m->running_as != SYSTEMD_SYSTEM) {
1331 dbus_set_error(&error, BUS_ERROR_NOT_SUPPORTED, "Switching root is only supported for system managers.");
1332 return bus_send_error_reply(connection, message, &error, -ENOTSUP);
1336 if (isempty(switch_root_init))
1337 k = access(switch_root, F_OK);
1341 p = strjoin(switch_root, "/", switch_root_init, NULL);
1345 k = access(p, X_OK);
1349 return bus_send_error_reply(connection, message, NULL, -errno);
1351 u = strdup(switch_root);
1355 if (!isempty(switch_root_init)) {
1356 v = strdup(switch_root_init);
1364 free(m->switch_root);
1365 free(m->switch_root_init);
1367 m->switch_root_init = v;
1369 reply = dbus_message_new_method_return(message);
1373 m->exit_code = MANAGER_SWITCH_ROOT;
1375 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "SetEnvironment")) {
1376 char **l = NULL, **e = NULL;
1378 SELINUX_ACCESS_CHECK(connection, message, "reboot");
1380 r = bus_parse_strv(message, &l);
1384 return bus_send_error_reply(connection, message, NULL, r);
1386 e = strv_env_merge(2, m->environment, l);
1391 reply = dbus_message_new_method_return(message);
1397 strv_free(m->environment);
1400 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "UnsetEnvironment")) {
1401 char **l = NULL, **e = NULL;
1403 SELINUX_ACCESS_CHECK(connection, message, "reboot");
1405 r = bus_parse_strv(message, &l);
1409 return bus_send_error_reply(connection, message, NULL, r);
1411 e = strv_env_delete(m->environment, 1, l);
1417 reply = dbus_message_new_method_return(message);
1423 strv_free(m->environment);
1426 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "UnsetAndSetEnvironment")) {
1427 char **l_set = NULL, **l_unset = NULL, **e = NULL, **f = NULL;
1428 DBusMessageIter iter;
1430 SELINUX_ACCESS_CHECK(connection, message, "reboot");
1432 if (!dbus_message_iter_init(message, &iter))
1435 r = bus_parse_strv_iter(&iter, &l_unset);
1439 return bus_send_error_reply(connection, message, NULL, r);
1441 if (!dbus_message_iter_next(&iter)) {
1443 return bus_send_error_reply(connection, message, NULL, -EINVAL);
1446 r = bus_parse_strv_iter(&iter, &l_set);
1452 return bus_send_error_reply(connection, message, NULL, r);
1455 e = strv_env_delete(m->environment, 1, l_unset);
1463 f = strv_env_merge(2, e, l_set);
1470 reply = dbus_message_new_method_return(message);
1476 strv_free(m->environment);
1478 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ListUnitFiles")) {
1479 DBusMessageIter iter, sub, sub2;
1484 SELINUX_ACCESS_CHECK(connection, message, "status");
1486 reply = dbus_message_new_method_return(message);
1490 h = hashmap_new(string_hash_func, string_compare_func);
1494 r = unit_file_get_list(m->running_as == SYSTEMD_SYSTEM ? UNIT_FILE_SYSTEM : UNIT_FILE_USER, NULL, h);
1496 unit_file_list_free(h);
1497 return bus_send_error_reply(connection, message, NULL, r);
1500 dbus_message_iter_init_append(reply, &iter);
1502 if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "(ss)", &sub)) {
1503 unit_file_list_free(h);
1507 HASHMAP_FOREACH(item, h, i) {
1510 state = unit_file_state_to_string(item->state);
1513 if (!dbus_message_iter_open_container(&sub, DBUS_TYPE_STRUCT, NULL, &sub2) ||
1514 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &item->path) ||
1515 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &state) ||
1516 !dbus_message_iter_close_container(&sub, &sub2)) {
1517 unit_file_list_free(h);
1522 unit_file_list_free(h);
1524 if (!dbus_message_iter_close_container(&iter, &sub))
1527 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "GetUnitFileState")) {
1529 UnitFileState state;
1532 SELINUX_ACCESS_CHECK(connection, message, "status");
1534 if (!dbus_message_get_args(
1537 DBUS_TYPE_STRING, &name,
1539 return bus_send_error_reply(connection, message, &error, -EINVAL);
1541 state = unit_file_get_state(m->running_as == SYSTEMD_SYSTEM ? UNIT_FILE_SYSTEM : UNIT_FILE_USER, NULL, name);
1543 return bus_send_error_reply(connection, message, NULL, state);
1545 s = unit_file_state_to_string(state);
1548 reply = dbus_message_new_method_return(message);
1552 if (!dbus_message_append_args(
1554 DBUS_TYPE_STRING, &s,
1557 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "EnableUnitFiles") ||
1558 dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ReenableUnitFiles") ||
1559 dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "LinkUnitFiles") ||
1560 dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "PresetUnitFiles") ||
1561 dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "MaskUnitFiles")) {
1564 DBusMessageIter iter;
1565 UnitFileScope scope = m->running_as == SYSTEMD_SYSTEM ? UNIT_FILE_SYSTEM : UNIT_FILE_USER;
1566 UnitFileChange *changes = NULL;
1567 unsigned n_changes = 0;
1568 dbus_bool_t runtime, force;
1569 int carries_install_info = -1;
1571 SELINUX_ACCESS_CHECK(connection, message, streq(member, "MaskUnitFiles") ? "disable" : "enable");
1573 if (!dbus_message_iter_init(message, &iter))
1576 r = bus_parse_strv_iter(&iter, &l);
1581 return bus_send_error_reply(connection, message, NULL, r);
1584 if (!dbus_message_iter_next(&iter) ||
1585 bus_iter_get_basic_and_next(&iter, DBUS_TYPE_BOOLEAN, &runtime, true) < 0 ||
1586 bus_iter_get_basic_and_next(&iter, DBUS_TYPE_BOOLEAN, &force, false) < 0) {
1588 return bus_send_error_reply(connection, message, NULL, -EIO);
1591 if (streq(member, "EnableUnitFiles")) {
1592 r = unit_file_enable(scope, runtime, NULL, l, force, &changes, &n_changes);
1593 carries_install_info = r;
1594 } else if (streq(member, "ReenableUnitFiles")) {
1595 r = unit_file_reenable(scope, runtime, NULL, l, force, &changes, &n_changes);
1596 carries_install_info = r;
1597 } else if (streq(member, "LinkUnitFiles"))
1598 r = unit_file_link(scope, runtime, NULL, l, force, &changes, &n_changes);
1599 else if (streq(member, "PresetUnitFiles")) {
1600 r = unit_file_preset(scope, runtime, NULL, l, force, &changes, &n_changes);
1601 carries_install_info = r;
1602 } else if (streq(member, "MaskUnitFiles"))
1603 r = unit_file_mask(scope, runtime, NULL, l, force, &changes, &n_changes);
1605 assert_not_reached("Uh? Wrong method");
1608 bus_manager_send_unit_files_changed(m);
1611 unit_file_changes_free(changes, n_changes);
1612 return bus_send_error_reply(connection, message, NULL, r);
1615 reply = message_from_file_changes(message, changes, n_changes, carries_install_info);
1616 unit_file_changes_free(changes, n_changes);
1621 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "DisableUnitFiles") ||
1622 dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "UnmaskUnitFiles")) {
1625 DBusMessageIter iter;
1626 UnitFileScope scope = m->running_as == SYSTEMD_SYSTEM ? UNIT_FILE_SYSTEM : UNIT_FILE_USER;
1627 UnitFileChange *changes = NULL;
1628 unsigned n_changes = 0;
1629 dbus_bool_t runtime;
1631 SELINUX_ACCESS_CHECK(connection, message, streq(member, "UnmaskUnitFiles") ? "enable" : "disable");
1633 if (!dbus_message_iter_init(message, &iter))
1636 r = bus_parse_strv_iter(&iter, &l);
1641 return bus_send_error_reply(connection, message, NULL, r);
1644 if (!dbus_message_iter_next(&iter) ||
1645 bus_iter_get_basic_and_next(&iter, DBUS_TYPE_BOOLEAN, &runtime, false) < 0) {
1647 return bus_send_error_reply(connection, message, NULL, -EIO);
1650 if (streq(member, "DisableUnitFiles"))
1651 r = unit_file_disable(scope, runtime, NULL, l, &changes, &n_changes);
1652 else if (streq(member, "UnmaskUnitFiles"))
1653 r = unit_file_unmask(scope, runtime, NULL, l, &changes, &n_changes);
1655 assert_not_reached("Uh? Wrong method");
1658 bus_manager_send_unit_files_changed(m);
1661 unit_file_changes_free(changes, n_changes);
1662 return bus_send_error_reply(connection, message, NULL, r);
1665 reply = message_from_file_changes(message, changes, n_changes, -1);
1666 unit_file_changes_free(changes, n_changes);
1672 const BusBoundProperties bps[] = {
1673 { "org.freedesktop.systemd1.Manager", bus_systemd_properties, systemd_property_string },
1674 { "org.freedesktop.systemd1.Manager", bus_manager_properties, m },
1678 SELINUX_ACCESS_CHECK(connection, message, "status");
1680 return bus_default_message_handler(connection, message, NULL, INTERFACES_LIST, bps);
1683 if (job_type != _JOB_TYPE_INVALID) {
1684 const char *name, *smode, *old_name = NULL;
1689 if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "StartUnitReplace"))
1690 b = dbus_message_get_args(
1693 DBUS_TYPE_STRING, &old_name,
1694 DBUS_TYPE_STRING, &name,
1695 DBUS_TYPE_STRING, &smode,
1698 b = dbus_message_get_args(
1701 DBUS_TYPE_STRING, &name,
1702 DBUS_TYPE_STRING, &smode,
1705 return bus_send_error_reply(connection, message, &error, -EINVAL);
1708 u = manager_get_unit(m, old_name);
1709 if (!u || !u->job || u->job->type != JOB_START) {
1710 dbus_set_error(&error, BUS_ERROR_NO_SUCH_JOB, "No job queued for unit %s", old_name);
1711 return bus_send_error_reply(connection, message, &error, -ENOENT);
1715 mode = job_mode_from_string(smode);
1717 dbus_set_error(&error, BUS_ERROR_INVALID_JOB_MODE, "Job mode %s is invalid.", smode);
1718 return bus_send_error_reply(connection, message, &error, -EINVAL);
1721 r = manager_load_unit(m, name, NULL, &error, &u);
1723 return bus_send_error_reply(connection, message, &error, r);
1725 return bus_unit_queue_job(connection, message, u, job_type, mode, reload_if_possible);
1729 if (!dbus_connection_send(connection, reply, NULL))
1732 return DBUS_HANDLER_RESULT_HANDLED;
1735 dbus_error_free(&error);
1737 return DBUS_HANDLER_RESULT_NEED_MEMORY;
1740 const DBusObjectPathVTable bus_manager_vtable = {
1741 .message_function = bus_manager_message_handler