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"
39 #define BUS_MANAGER_INTERFACE_BEGIN \
40 " <interface name=\"org.freedesktop.systemd1.Manager\">\n"
42 #define BUS_MANAGER_INTERFACE_METHODS \
43 " <method name=\"GetUnit\">\n" \
44 " <arg name=\"name\" type=\"s\" direction=\"in\"/>\n" \
45 " <arg name=\"unit\" type=\"o\" direction=\"out\"/>\n" \
47 " <method name=\"GetUnitByPID\">\n" \
48 " <arg name=\"pid\" type=\"u\" direction=\"in\"/>\n" \
49 " <arg name=\"unit\" type=\"o\" direction=\"out\"/>\n" \
51 " <method name=\"LoadUnit\">\n" \
52 " <arg name=\"name\" type=\"s\" direction=\"in\"/>\n" \
53 " <arg name=\"unit\" type=\"o\" direction=\"out\"/>\n" \
55 " <method name=\"StartUnit\">\n" \
56 " <arg name=\"name\" type=\"s\" direction=\"in\"/>\n" \
57 " <arg name=\"mode\" type=\"s\" direction=\"in\"/>\n" \
58 " <arg name=\"job\" type=\"o\" direction=\"out\"/>\n" \
60 " <method name=\"StartUnitReplace\">\n" \
61 " <arg name=\"old_unit\" type=\"s\" direction=\"in\"/>\n" \
62 " <arg name=\"new_unit\" type=\"s\" direction=\"in\"/>\n" \
63 " <arg name=\"mode\" type=\"s\" direction=\"in\"/>\n" \
64 " <arg name=\"job\" type=\"o\" direction=\"out\"/>\n" \
66 " <method name=\"StopUnit\">\n" \
67 " <arg name=\"name\" type=\"s\" direction=\"in\"/>\n" \
68 " <arg name=\"mode\" type=\"s\" direction=\"in\"/>\n" \
69 " <arg name=\"job\" type=\"o\" direction=\"out\"/>\n" \
71 " <method name=\"ReloadUnit\">\n" \
72 " <arg name=\"name\" type=\"s\" direction=\"in\"/>\n" \
73 " <arg name=\"mode\" type=\"s\" direction=\"in\"/>\n" \
74 " <arg name=\"job\" type=\"o\" direction=\"out\"/>\n" \
76 " <method name=\"RestartUnit\">\n" \
77 " <arg name=\"name\" type=\"s\" direction=\"in\"/>\n" \
78 " <arg name=\"mode\" type=\"s\" direction=\"in\"/>\n" \
79 " <arg name=\"job\" type=\"o\" direction=\"out\"/>\n" \
81 " <method name=\"TryRestartUnit\">\n" \
82 " <arg name=\"name\" type=\"s\" direction=\"in\"/>\n" \
83 " <arg name=\"mode\" type=\"s\" direction=\"in\"/>\n" \
84 " <arg name=\"job\" type=\"o\" direction=\"out\"/>\n" \
86 " <method name=\"ReloadOrRestartUnit\">\n" \
87 " <arg name=\"name\" type=\"s\" direction=\"in\"/>\n" \
88 " <arg name=\"mode\" type=\"s\" direction=\"in\"/>\n" \
89 " <arg name=\"job\" type=\"o\" direction=\"out\"/>\n" \
91 " <method name=\"ReloadOrTryRestartUnit\">\n" \
92 " <arg name=\"name\" type=\"s\" direction=\"in\"/>\n" \
93 " <arg name=\"mode\" type=\"s\" direction=\"in\"/>\n" \
94 " <arg name=\"job\" type=\"o\" direction=\"out\"/>\n" \
96 " <method name=\"KillUnit\">\n" \
97 " <arg name=\"name\" type=\"s\" direction=\"in\"/>\n" \
98 " <arg name=\"who\" type=\"s\" direction=\"in\"/>\n" \
99 " <arg name=\"signal\" type=\"i\" direction=\"in\"/>\n" \
101 " <method name=\"ResetFailedUnit\">\n" \
102 " <arg name=\"name\" type=\"s\" direction=\"in\"/>\n" \
104 " <method name=\"GetJob\">\n" \
105 " <arg name=\"id\" type=\"u\" direction=\"in\"/>\n" \
106 " <arg name=\"job\" type=\"o\" direction=\"out\"/>\n" \
108 " <method name=\"ClearJobs\"/>\n" \
109 " <method name=\"ResetFailed\"/>\n" \
110 " <method name=\"ListUnits\">\n" \
111 " <arg name=\"units\" type=\"a(ssssssouso)\" direction=\"out\"/>\n" \
113 " <method name=\"ListJobs\">\n" \
114 " <arg name=\"jobs\" type=\"a(usssoo)\" direction=\"out\"/>\n" \
116 " <method name=\"Subscribe\"/>\n" \
117 " <method name=\"Unsubscribe\"/>\n" \
118 " <method name=\"Dump\">\n" \
119 " <arg name=\"dump\" type=\"s\" direction=\"out\"/>\n" \
121 " <method name=\"CreateSnapshot\">\n" \
122 " <arg name=\"name\" type=\"s\" direction=\"in\"/>\n" \
123 " <arg name=\"cleanup\" type=\"b\" direction=\"in\"/>\n" \
124 " <arg name=\"unit\" type=\"o\" direction=\"out\"/>\n" \
126 " <method name=\"Reload\"/>\n" \
127 " <method name=\"Reexecute\"/>\n" \
128 " <method name=\"Exit\"/>\n" \
129 " <method name=\"Reboot\"/>\n" \
130 " <method name=\"PowerOff\"/>\n" \
131 " <method name=\"Halt\"/>\n" \
132 " <method name=\"KExec\"/>\n" \
133 " <method name=\"SwitchRoot\">\n" \
134 " <arg name=\"new_root\" type=\"s\" direction=\"in\"/>\n" \
135 " <arg name=\"init\" type=\"s\" direction=\"in\"/>\n" \
137 " <method name=\"SetEnvironment\">\n" \
138 " <arg name=\"names\" type=\"as\" direction=\"in\"/>\n" \
140 " <method name=\"UnsetEnvironment\">\n" \
141 " <arg name=\"names\" type=\"as\" direction=\"in\"/>\n" \
143 " <method name=\"UnsetAndSetEnvironment\">\n" \
144 " <arg name=\"unset\" type=\"as\" direction=\"in\"/>\n" \
145 " <arg name=\"set\" type=\"as\" direction=\"in\"/>\n" \
147 " <method name=\"ListUnitFiles\">\n" \
148 " <arg name=\"files\" type=\"a(ss)\" direction=\"out\"/>\n" \
150 " <method name=\"GetUnitFileState\">\n" \
151 " <arg name=\"file\" type=\"s\" direction=\"in\"/>\n" \
152 " <arg name=\"state\" type=\"s\" direction=\"out\"/>\n" \
154 " <method name=\"EnableUnitFiles\">\n" \
155 " <arg name=\"files\" type=\"as\" direction=\"in\"/>\n" \
156 " <arg name=\"runtime\" type=\"b\" direction=\"in\"/>\n" \
157 " <arg name=\"force\" type=\"b\" direction=\"in\"/>\n" \
158 " <arg name=\"carries_install_info\" type=\"b\" direction=\"out\"/>\n" \
159 " <arg name=\"changes\" type=\"a(sss)\" direction=\"out\"/>\n" \
161 " <method name=\"DisableUnitFiles\">\n" \
162 " <arg name=\"files\" type=\"as\" direction=\"in\"/>\n" \
163 " <arg name=\"runtime\" type=\"b\" direction=\"in\"/>\n" \
164 " <arg name=\"changes\" type=\"a(sss)\" direction=\"out\"/>\n" \
166 " <method name=\"ReenableUnitFiles\">\n" \
167 " <arg name=\"files\" type=\"as\" direction=\"in\"/>\n" \
168 " <arg name=\"runtime\" type=\"b\" direction=\"in\"/>\n" \
169 " <arg name=\"force\" type=\"b\" direction=\"in\"/>\n" \
170 " <arg name=\"carries_install_info\" type=\"b\" direction=\"out\"/>\n" \
171 " <arg name=\"changes\" type=\"a(sss)\" direction=\"out\"/>\n" \
173 " <method name=\"LinkUnitFiles\">\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=\"changes\" type=\"a(sss)\" direction=\"out\"/>\n" \
179 " <method name=\"PresetUnitFiles\">\n" \
180 " <arg name=\"files\" type=\"as\" direction=\"in\"/>\n" \
181 " <arg name=\"runtime\" type=\"b\" direction=\"in\"/>\n" \
182 " <arg name=\"force\" type=\"b\" direction=\"in\"/>\n" \
183 " <arg name=\"carries_install_info\" type=\"b\" direction=\"out\"/>\n" \
184 " <arg name=\"changes\" type=\"a(sss)\" direction=\"out\"/>\n" \
186 " <method name=\"MaskUnitFiles\">\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=\"changes\" type=\"a(sss)\" direction=\"out\"/>\n" \
192 " <method name=\"UnmaskUnitFiles\">\n" \
193 " <arg name=\"files\" type=\"as\" direction=\"in\"/>\n" \
194 " <arg name=\"runtime\" type=\"b\" direction=\"in\"/>\n" \
195 " <arg name=\"changes\" type=\"a(sss)\" direction=\"out\"/>\n" \
198 #define BUS_MANAGER_INTERFACE_SIGNALS \
199 " <signal name=\"UnitNew\">\n" \
200 " <arg name=\"id\" type=\"s\"/>\n" \
201 " <arg name=\"unit\" type=\"o\"/>\n" \
203 " <signal name=\"UnitRemoved\">\n" \
204 " <arg name=\"id\" type=\"s\"/>\n" \
205 " <arg name=\"unit\" type=\"o\"/>\n" \
207 " <signal name=\"JobNew\">\n" \
208 " <arg name=\"id\" type=\"u\"/>\n" \
209 " <arg name=\"job\" type=\"o\"/>\n" \
210 " <arg name=\"unit\" type=\"s\"/>\n" \
212 " <signal name=\"JobRemoved\">\n" \
213 " <arg name=\"id\" type=\"u\"/>\n" \
214 " <arg name=\"job\" type=\"o\"/>\n" \
215 " <arg name=\"unit\" type=\"s\"/>\n" \
216 " <arg name=\"result\" type=\"s\"/>\n" \
218 " <signal name=\"StartupFinished\">\n" \
219 " <arg name=\"firmware\" type=\"t\"/>\n" \
220 " <arg name=\"loader\" type=\"t\"/>\n" \
221 " <arg name=\"kernel\" type=\"t\"/>\n" \
222 " <arg name=\"initrd\" type=\"t\"/>\n" \
223 " <arg name=\"userspace\" type=\"t\"/>\n" \
224 " <arg name=\"total\" type=\"t\"/>\n" \
226 " <signal name=\"UnitFilesChanged\"/>\n"
228 #define BUS_MANAGER_INTERFACE_PROPERTIES_GENERAL \
229 " <property name=\"Version\" type=\"s\" access=\"read\"/>\n" \
230 " <property name=\"Distribution\" type=\"s\" access=\"read\"/>\n" \
231 " <property name=\"Features\" type=\"s\" access=\"read\"/>\n" \
232 " <property name=\"Tainted\" type=\"s\" access=\"read\"/>\n" \
233 " <property name=\"FirmwareTimestamp\" type=\"t\" access=\"read\"/>\n" \
234 " <property name=\"FirmwareTimestampMonotonic\" type=\"t\" access=\"read\"/>\n" \
235 " <property name=\"LoaderTimestamp\" type=\"t\" access=\"read\"/>\n" \
236 " <property name=\"LoaderTimestampMonotonic\" type=\"t\" access=\"read\"/>\n" \
237 " <property name=\"KernelTimestamp\" type=\"t\" access=\"read\"/>\n" \
238 " <property name=\"KernelTimestampMonotonic\" type=\"t\" access=\"read\"/>\n" \
239 " <property name=\"InitRDTimestamp\" type=\"t\" access=\"read\"/>\n" \
240 " <property name=\"InitRDTimestampMonotonic\" type=\"t\" access=\"read\"/>\n" \
241 " <property name=\"UserspaceTimestamp\" type=\"t\" access=\"read\"/>\n" \
242 " <property name=\"UserspaceTimestampMonotonic\" type=\"t\" access=\"read\"/>\n" \
243 " <property name=\"FinishTimestamp\" type=\"t\" access=\"read\"/>\n" \
244 " <property name=\"FinishTimestampMonotonic\" type=\"t\" access=\"read\"/>\n" \
245 " <property name=\"LogLevel\" type=\"s\" access=\"readwrite\"/>\n" \
246 " <property name=\"LogTarget\" type=\"s\" access=\"readwrite\"/>\n" \
247 " <property name=\"NNames\" type=\"u\" access=\"read\"/>\n" \
248 " <property name=\"NJobs\" type=\"u\" access=\"read\"/>\n" \
249 " <property name=\"NInstalledJobs\" type=\"u\" access=\"read\"/>\n" \
250 " <property name=\"NFailedJobs\" type=\"u\" access=\"read\"/>\n" \
251 " <property name=\"Progress\" type=\"d\" access=\"read\"/>\n" \
252 " <property name=\"Environment\" type=\"as\" access=\"read\"/>\n" \
253 " <property name=\"ConfirmSpawn\" type=\"b\" access=\"read\"/>\n" \
254 " <property name=\"ShowStatus\" type=\"b\" access=\"read\"/>\n" \
255 " <property name=\"UnitPath\" type=\"as\" access=\"read\"/>\n" \
256 " <property name=\"ControlGroupHierarchy\" type=\"s\" access=\"read\"/>\n" \
257 " <property name=\"DefaultControllers\" type=\"as\" access=\"read\"/>\n" \
258 " <property name=\"DefaultStandardOutput\" type=\"s\" access=\"read\"/>\n" \
259 " <property name=\"DefaultStandardError\" type=\"s\" access=\"read\"/>\n" \
260 " <property name=\"RuntimeWatchdogUSec\" type=\"s\" access=\"readwrite\"/>\n" \
261 " <property name=\"ShutdownWatchdogUSec\" type=\"s\" access=\"readwrite\"/>\n"
263 #define BUS_MANAGER_INTERFACE_END \
266 #define BUS_MANAGER_INTERFACE \
267 BUS_MANAGER_INTERFACE_BEGIN \
268 BUS_MANAGER_INTERFACE_METHODS \
269 BUS_MANAGER_INTERFACE_SIGNALS \
270 BUS_MANAGER_INTERFACE_PROPERTIES_GENERAL \
271 BUS_MANAGER_INTERFACE_END
273 #define INTROSPECTION_BEGIN \
274 DBUS_INTROSPECT_1_0_XML_DOCTYPE_DECL_NODE \
276 BUS_MANAGER_INTERFACE \
277 BUS_PROPERTIES_INTERFACE \
279 BUS_INTROSPECTABLE_INTERFACE
281 #define INTROSPECTION_END \
284 #define INTERFACES_LIST \
285 BUS_GENERIC_INTERFACES_LIST \
286 "org.freedesktop.systemd1.Manager\0"
288 const char bus_manager_interface[] _introspect_("Manager") = BUS_MANAGER_INTERFACE;
290 static DEFINE_BUS_PROPERTY_APPEND_ENUM(bus_manager_append_exec_output, exec_output, ExecOutput);
292 static int bus_manager_append_tainted(DBusMessageIter *i, const char *property, void *data) {
295 char buf[LINE_MAX] = "", *e = buf, *p = NULL;
302 e = stpcpy(e, "split-usr:");
304 if (readlink_malloc("/etc/mtab", &p) < 0)
305 e = stpcpy(e, "mtab-not-symlink:");
309 if (access("/proc/cgroups", F_OK) < 0)
310 e = stpcpy(e, "cgroups-missing:");
312 if (hwclock_is_localtime() > 0)
313 e = stpcpy(e, "local-hwclock:");
315 /* remove the last ':' */
321 if (!dbus_message_iter_append_basic(i, DBUS_TYPE_STRING, &t))
327 static int bus_manager_append_log_target(DBusMessageIter *i, const char *property, void *data) {
333 t = log_target_to_string(log_get_target());
335 if (!dbus_message_iter_append_basic(i, DBUS_TYPE_STRING, &t))
341 static int bus_manager_set_log_target(DBusMessageIter *i, const char *property, void *data) {
347 dbus_message_iter_get_basic(i, &t);
349 return log_set_target_from_string(t);
352 static int bus_manager_append_log_level(DBusMessageIter *i, const char *property, void *data) {
358 t = log_level_to_string(log_get_max_level());
360 if (!dbus_message_iter_append_basic(i, DBUS_TYPE_STRING, &t))
366 static int bus_manager_set_log_level(DBusMessageIter *i, const char *property, void *data) {
372 dbus_message_iter_get_basic(i, &t);
374 return log_set_max_level_from_string(t);
377 static int bus_manager_append_n_names(DBusMessageIter *i, const char *property, void *data) {
385 u = hashmap_size(m->units);
387 if (!dbus_message_iter_append_basic(i, DBUS_TYPE_UINT32, &u))
393 static int bus_manager_append_n_jobs(DBusMessageIter *i, const char *property, void *data) {
401 u = hashmap_size(m->jobs);
403 if (!dbus_message_iter_append_basic(i, DBUS_TYPE_UINT32, &u))
409 static int bus_manager_append_progress(DBusMessageIter *i, const char *property, void *data) {
417 if (dual_timestamp_is_set(&m->finish_timestamp))
420 d = 1.0 - ((double) hashmap_size(m->jobs) / (double) m->n_installed_jobs);
422 if (!dbus_message_iter_append_basic(i, DBUS_TYPE_DOUBLE, &d))
428 static DBusMessage *message_from_file_changes(
430 UnitFileChange *changes,
432 int carries_install_info) {
434 DBusMessageIter iter, sub, sub2;
438 reply = dbus_message_new_method_return(m);
442 dbus_message_iter_init_append(reply, &iter);
444 if (carries_install_info >= 0) {
447 b = !!carries_install_info;
448 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &b))
452 if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "(sss)", &sub))
455 for (i = 0; i < n_changes; i++) {
456 const char *type, *path, *source;
458 type = unit_file_change_type_to_string(changes[i].type);
459 path = strempty(changes[i].path);
460 source = strempty(changes[i].source);
462 if (!dbus_message_iter_open_container(&sub, DBUS_TYPE_STRUCT, NULL, &sub2) ||
463 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &type) ||
464 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &path) ||
465 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &source) ||
466 !dbus_message_iter_close_container(&sub, &sub2))
470 if (!dbus_message_iter_close_container(&iter, &sub))
476 dbus_message_unref(reply);
480 static int bus_manager_send_unit_files_changed(Manager *m) {
484 s = dbus_message_new_signal("/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", "UnitFilesChanged");
488 r = bus_broadcast(m, s);
489 dbus_message_unref(s);
494 static int bus_manager_set_runtime_watchdog_usec(DBusMessageIter *i, const char *property, void *data) {
500 dbus_message_iter_get_basic(i, t);
502 return watchdog_set_timeout(t);
505 static const char systemd_property_string[] =
510 static const BusProperty bus_systemd_properties[] = {
511 { "Version", bus_property_append_string, "s", 0 },
512 { "Distribution", bus_property_append_string, "s", sizeof(PACKAGE_STRING) },
513 { "Features", bus_property_append_string, "s", sizeof(PACKAGE_STRING) + sizeof(DISTRIBUTION) },
517 static const BusProperty bus_manager_properties[] = {
518 { "Tainted", bus_manager_append_tainted, "s", 0 },
519 { "FirmwareTimestamp", bus_property_append_uint64, "t", offsetof(Manager, firmware_timestamp.realtime) },
520 { "FirmwareTimestampMonotonic", bus_property_append_uint64,"t", offsetof(Manager, firmware_timestamp.monotonic)},
521 { "LoaderTimestamp", bus_property_append_uint64, "t", offsetof(Manager, loader_timestamp.realtime) },
522 { "LoaderTimestampMonotonic", bus_property_append_uint64, "t", offsetof(Manager, loader_timestamp.monotonic) },
523 { "KernelTimestamp", bus_property_append_uint64, "t", offsetof(Manager, kernel_timestamp.realtime) },
524 { "KernelTimestampMonotonic", bus_property_append_uint64, "t", offsetof(Manager, kernel_timestamp.monotonic) },
525 { "InitRDTimestamp", bus_property_append_uint64, "t", offsetof(Manager, initrd_timestamp.realtime) },
526 { "InitRDTimestampMonotonic", bus_property_append_uint64, "t", offsetof(Manager, initrd_timestamp.monotonic) },
527 { "UserspaceTimestamp", bus_property_append_uint64, "t", offsetof(Manager, userspace_timestamp.realtime)},
528 { "UserspaceTimestampMonotonic", bus_property_append_uint64,"t",offsetof(Manager, userspace_timestamp.monotonic)},
529 { "FinishTimestamp", bus_property_append_uint64, "t", offsetof(Manager, finish_timestamp.realtime) },
530 { "FinishTimestampMonotonic", bus_property_append_uint64, "t", offsetof(Manager, finish_timestamp.monotonic) },
531 { "LogLevel", bus_manager_append_log_level, "s", 0, false, bus_manager_set_log_level },
532 { "LogTarget", bus_manager_append_log_target, "s", 0, false, bus_manager_set_log_target },
533 { "NNames", bus_manager_append_n_names, "u", 0 },
534 { "NJobs", bus_manager_append_n_jobs, "u", 0 },
535 { "NInstalledJobs",bus_property_append_uint32, "u", offsetof(Manager, n_installed_jobs) },
536 { "NFailedJobs", bus_property_append_uint32, "u", offsetof(Manager, n_failed_jobs) },
537 { "Progress", bus_manager_append_progress, "d", 0 },
538 { "Environment", bus_property_append_strv, "as", offsetof(Manager, environment), true },
539 { "ConfirmSpawn", bus_property_append_bool, "b", offsetof(Manager, confirm_spawn) },
540 { "ShowStatus", bus_property_append_bool, "b", offsetof(Manager, show_status) },
541 { "UnitPath", bus_property_append_strv, "as", offsetof(Manager, lookup_paths.unit_path), true },
542 { "ControlGroupHierarchy", bus_property_append_string, "s", offsetof(Manager, cgroup_hierarchy), true },
543 { "DefaultControllers", bus_property_append_strv, "as", offsetof(Manager, default_controllers), true },
544 { "DefaultStandardOutput", bus_manager_append_exec_output, "s", offsetof(Manager, default_std_output) },
545 { "DefaultStandardError", bus_manager_append_exec_output, "s", offsetof(Manager, default_std_error) },
546 { "RuntimeWatchdogUSec", bus_property_append_usec, "t", offsetof(Manager, runtime_watchdog), false, bus_manager_set_runtime_watchdog_usec },
547 { "ShutdownWatchdogUSec", bus_property_append_usec, "t", offsetof(Manager, shutdown_watchdog), false, bus_property_set_usec },
551 static DBusHandlerResult bus_manager_message_handler(DBusConnection *connection, DBusMessage *message, void *data) {
552 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
553 _cleanup_free_ char * path = NULL;
557 JobType job_type = _JOB_TYPE_INVALID;
558 bool reload_if_possible = false;
565 dbus_error_init(&error);
567 member = dbus_message_get_member(message);
569 if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "GetUnit")) {
573 if (!dbus_message_get_args(
576 DBUS_TYPE_STRING, &name,
578 return bus_send_error_reply(connection, message, &error, -EINVAL);
580 u = manager_get_unit(m, name);
582 dbus_set_error(&error, BUS_ERROR_NO_SUCH_UNIT, "Unit %s is not loaded.", name);
583 return bus_send_error_reply(connection, message, &error, -ENOENT);
586 SELINUX_UNIT_ACCESS_CHECK(u, connection, message, "status");
588 reply = dbus_message_new_method_return(message);
592 path = unit_dbus_path(u);
596 if (!dbus_message_append_args(
598 DBUS_TYPE_OBJECT_PATH, &path,
601 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "GetUnitByPID")) {
605 if (!dbus_message_get_args(
608 DBUS_TYPE_UINT32, &pid,
610 return bus_send_error_reply(connection, message, &error, -EINVAL);
612 u = cgroup_unit_by_pid(m, (pid_t) pid);
614 dbus_set_error(&error, BUS_ERROR_NO_SUCH_UNIT, "No unit for PID %lu is loaded.", (unsigned long) pid);
615 return bus_send_error_reply(connection, message, &error, -ENOENT);
618 SELINUX_UNIT_ACCESS_CHECK(u, connection, message, "status");
620 reply = dbus_message_new_method_return(message);
624 path = unit_dbus_path(u);
628 if (!dbus_message_append_args(
630 DBUS_TYPE_OBJECT_PATH, &path,
633 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "LoadUnit")) {
637 if (!dbus_message_get_args(
640 DBUS_TYPE_STRING, &name,
642 return bus_send_error_reply(connection, message, &error, -EINVAL);
644 r = manager_load_unit(m, name, NULL, &error, &u);
646 return bus_send_error_reply(connection, message, &error, r);
648 SELINUX_UNIT_ACCESS_CHECK(u, connection, message, "status");
650 reply = dbus_message_new_method_return(message);
654 path = unit_dbus_path(u);
658 if (!dbus_message_append_args(
660 DBUS_TYPE_OBJECT_PATH, &path,
664 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "StartUnit"))
665 job_type = JOB_START;
666 else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "StartUnitReplace"))
667 job_type = JOB_START;
668 else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "StopUnit"))
670 else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ReloadUnit"))
671 job_type = JOB_RELOAD;
672 else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "RestartUnit"))
673 job_type = JOB_RESTART;
674 else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "TryRestartUnit"))
675 job_type = JOB_TRY_RESTART;
676 else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ReloadOrRestartUnit")) {
677 reload_if_possible = true;
678 job_type = JOB_RESTART;
679 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ReloadOrTryRestartUnit")) {
680 reload_if_possible = true;
681 job_type = JOB_TRY_RESTART;
682 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "KillUnit")) {
683 const char *name, *swho;
688 if (!dbus_message_get_args(
691 DBUS_TYPE_STRING, &name,
692 DBUS_TYPE_STRING, &swho,
693 DBUS_TYPE_INT32, &signo,
695 return bus_send_error_reply(connection, message, &error, -EINVAL);
700 who = kill_who_from_string(swho);
702 return bus_send_error_reply(connection, message, &error, -EINVAL);
705 if (signo <= 0 || signo >= _NSIG)
706 return bus_send_error_reply(connection, message, &error, -EINVAL);
708 u = manager_get_unit(m, name);
710 dbus_set_error(&error, BUS_ERROR_NO_SUCH_UNIT, "Unit %s is not loaded.", name);
711 return bus_send_error_reply(connection, message, &error, -ENOENT);
714 SELINUX_UNIT_ACCESS_CHECK(u, connection, message, "stop");
716 r = unit_kill(u, who, signo, &error);
718 return bus_send_error_reply(connection, message, &error, r);
720 if (!(reply = dbus_message_new_method_return(message)))
723 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "GetJob")) {
727 if (!dbus_message_get_args(
730 DBUS_TYPE_UINT32, &id,
732 return bus_send_error_reply(connection, message, &error, -EINVAL);
734 j = manager_get_job(m, id);
736 dbus_set_error(&error, BUS_ERROR_NO_SUCH_JOB, "Job %u does not exist.", (unsigned) id);
737 return bus_send_error_reply(connection, message, &error, -ENOENT);
740 SELINUX_UNIT_ACCESS_CHECK(j->unit, connection, message, "status");
742 reply = dbus_message_new_method_return(message);
746 path = job_dbus_path(j);
750 if (!dbus_message_append_args(
752 DBUS_TYPE_OBJECT_PATH, &path,
756 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ClearJobs")) {
758 SELINUX_ACCESS_CHECK(connection, message, "reboot");
760 manager_clear_jobs(m);
762 reply = dbus_message_new_method_return(message);
766 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ResetFailed")) {
768 SELINUX_ACCESS_CHECK(connection, message, "reload");
770 manager_reset_failed(m);
772 reply = dbus_message_new_method_return(message);
776 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ResetFailedUnit")) {
780 if (!dbus_message_get_args(
783 DBUS_TYPE_STRING, &name,
785 return bus_send_error_reply(connection, message, &error, -EINVAL);
787 u = manager_get_unit(m, name);
789 dbus_set_error(&error, BUS_ERROR_NO_SUCH_UNIT, "Unit %s is not loaded.", name);
790 return bus_send_error_reply(connection, message, &error, -ENOENT);
793 SELINUX_UNIT_ACCESS_CHECK(u, connection, message, "reload");
795 unit_reset_failed(u);
797 reply = dbus_message_new_method_return(message);
801 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ListUnits")) {
802 DBusMessageIter iter, sub;
807 SELINUX_ACCESS_CHECK(connection, message, "status");
809 reply = dbus_message_new_method_return(message);
813 dbus_message_iter_init_append(reply, &iter);
815 if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "(ssssssouso)", &sub))
818 HASHMAP_FOREACH_KEY(u, k, m->units, i) {
819 char *u_path, *j_path;
820 const char *description, *load_state, *active_state, *sub_state, *sjob_type, *following;
821 DBusMessageIter sub2;
828 if (!dbus_message_iter_open_container(&sub, DBUS_TYPE_STRUCT, NULL, &sub2))
831 description = unit_description(u);
832 load_state = unit_load_state_to_string(u->load_state);
833 active_state = unit_active_state_to_string(unit_active_state(u));
834 sub_state = unit_sub_state_to_string(u);
836 f = unit_following(u);
837 following = f ? f->id : "";
839 u_path = unit_dbus_path(u);
844 job_id = (uint32_t) u->job->id;
846 if (!(j_path = job_dbus_path(u->job))) {
851 sjob_type = job_type_to_string(u->job->type);
858 if (!dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &u->id) ||
859 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &description) ||
860 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &load_state) ||
861 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &active_state) ||
862 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &sub_state) ||
863 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &following) ||
864 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_OBJECT_PATH, &u_path) ||
865 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_UINT32, &job_id) ||
866 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &sjob_type) ||
867 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_OBJECT_PATH, &j_path)) {
878 if (!dbus_message_iter_close_container(&sub, &sub2))
882 if (!dbus_message_iter_close_container(&iter, &sub))
885 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ListJobs")) {
886 DBusMessageIter iter, sub;
890 SELINUX_ACCESS_CHECK(connection, message, "status");
892 reply = dbus_message_new_method_return(message);
896 dbus_message_iter_init_append(reply, &iter);
898 if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "(usssoo)", &sub))
901 HASHMAP_FOREACH(j, m->jobs, i) {
902 char *u_path, *j_path;
903 const char *state, *type;
905 DBusMessageIter sub2;
907 if (!dbus_message_iter_open_container(&sub, DBUS_TYPE_STRUCT, NULL, &sub2))
910 id = (uint32_t) j->id;
911 state = job_state_to_string(j->state);
912 type = job_type_to_string(j->type);
914 j_path = job_dbus_path(j);
918 u_path = unit_dbus_path(j->unit);
924 if (!dbus_message_iter_append_basic(&sub2, DBUS_TYPE_UINT32, &id) ||
925 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &j->unit->id) ||
926 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &type) ||
927 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &state) ||
928 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_OBJECT_PATH, &j_path) ||
929 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_OBJECT_PATH, &u_path)) {
938 if (!dbus_message_iter_close_container(&sub, &sub2))
942 if (!dbus_message_iter_close_container(&iter, &sub))
945 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "Subscribe")) {
949 SELINUX_ACCESS_CHECK(connection, message, "status");
951 s = BUS_CONNECTION_SUBSCRIBED(m, connection);
953 s = set_new(string_hash_func, string_compare_func);
957 if (!dbus_connection_set_data(connection, m->subscribed_data_slot, s, NULL)) {
963 client = strdup(bus_message_get_sender_with_fallback(message));
967 r = set_put(s, client);
970 return bus_send_error_reply(connection, message, NULL, r);
973 reply = dbus_message_new_method_return(message);
977 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "Unsubscribe")) {
980 SELINUX_ACCESS_CHECK(connection, message, "status");
982 client = set_remove(BUS_CONNECTION_SUBSCRIBED(m, connection), (char*) bus_message_get_sender_with_fallback(message));
984 dbus_set_error(&error, BUS_ERROR_NOT_SUBSCRIBED, "Client is not subscribed.");
985 return bus_send_error_reply(connection, message, &error, -ENOENT);
990 reply = dbus_message_new_method_return(message);
994 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "Dump")) {
999 SELINUX_ACCESS_CHECK(connection, message, "status");
1001 reply = dbus_message_new_method_return(message);
1005 f = open_memstream(&dump, &size);
1009 manager_dump_units(m, f, NULL);
1010 manager_dump_jobs(m, f, NULL);
1020 if (!dbus_message_append_args(reply, DBUS_TYPE_STRING, &dump, DBUS_TYPE_INVALID)) {
1026 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "CreateSnapshot")) {
1028 dbus_bool_t cleanup;
1031 SELINUX_ACCESS_CHECK(connection, message, "start");
1033 if (!dbus_message_get_args(
1036 DBUS_TYPE_STRING, &name,
1037 DBUS_TYPE_BOOLEAN, &cleanup,
1039 return bus_send_error_reply(connection, message, &error, -EINVAL);
1044 r = snapshot_create(m, name, cleanup, &error, &s);
1046 return bus_send_error_reply(connection, message, &error, r);
1048 reply = dbus_message_new_method_return(message);
1052 path = unit_dbus_path(UNIT(s));
1056 if (!dbus_message_append_args(
1058 DBUS_TYPE_OBJECT_PATH, &path,
1062 } else if (dbus_message_is_method_call(message, "org.freedesktop.DBus.Introspectable", "Introspect")) {
1063 char *introspection = NULL;
1071 SELINUX_ACCESS_CHECK(connection, message, "status");
1073 reply = dbus_message_new_method_return(message);
1077 /* We roll our own introspection code here, instead of
1078 * relying on bus_default_message_handler() because we
1079 * need to generate our introspection string
1082 f = open_memstream(&introspection, &size);
1086 fputs(INTROSPECTION_BEGIN, f);
1088 HASHMAP_FOREACH_KEY(u, k, m->units, i) {
1094 p = bus_path_escape(k);
1097 free(introspection);
1101 fprintf(f, "<node name=\"unit/%s\"/>", p);
1105 HASHMAP_FOREACH(j, m->jobs, i)
1106 fprintf(f, "<node name=\"job/%lu\"/>", (unsigned long) j->id);
1108 fputs(INTROSPECTION_END, f);
1112 free(introspection);
1121 if (!dbus_message_append_args(reply, DBUS_TYPE_STRING, &introspection, DBUS_TYPE_INVALID)) {
1122 free(introspection);
1126 free(introspection);
1128 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "Reload")) {
1130 SELINUX_ACCESS_CHECK(connection, message, "reload");
1132 assert(!m->queued_message);
1134 /* Instead of sending the reply back right away, we
1135 * just remember that we need to and then send it
1136 * after the reload is finished. That way the caller
1137 * knows when the reload finished. */
1139 m->queued_message = dbus_message_new_method_return(message);
1140 if (!m->queued_message)
1143 m->queued_message_connection = connection;
1144 m->exit_code = MANAGER_RELOAD;
1146 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "Reexecute")) {
1148 SELINUX_ACCESS_CHECK(connection, message, "reload");
1150 /* We don't send a reply back here, the client should
1151 * just wait for us disconnecting. */
1153 m->exit_code = MANAGER_REEXECUTE;
1155 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "Exit")) {
1157 SELINUX_ACCESS_CHECK(connection, message, "halt");
1159 if (m->running_as == SYSTEMD_SYSTEM) {
1160 dbus_set_error(&error, BUS_ERROR_NOT_SUPPORTED, "Exit is only supported for user service managers.");
1161 return bus_send_error_reply(connection, message, &error, -ENOTSUP);
1164 reply = dbus_message_new_method_return(message);
1168 m->exit_code = MANAGER_EXIT;
1170 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "Reboot")) {
1172 SELINUX_ACCESS_CHECK(connection, message, "reboot");
1174 if (m->running_as != SYSTEMD_SYSTEM) {
1175 dbus_set_error(&error, BUS_ERROR_NOT_SUPPORTED, "Reboot is only supported for system managers.");
1176 return bus_send_error_reply(connection, message, &error, -ENOTSUP);
1179 reply = dbus_message_new_method_return(message);
1183 m->exit_code = MANAGER_REBOOT;
1185 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "PowerOff")) {
1187 SELINUX_ACCESS_CHECK(connection, message, "halt");
1189 if (m->running_as != SYSTEMD_SYSTEM) {
1190 dbus_set_error(&error, BUS_ERROR_NOT_SUPPORTED, "Powering off is only supported for system managers.");
1191 return bus_send_error_reply(connection, message, &error, -ENOTSUP);
1194 reply = dbus_message_new_method_return(message);
1198 m->exit_code = MANAGER_POWEROFF;
1200 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "Halt")) {
1202 SELINUX_ACCESS_CHECK(connection, message, "halt");
1204 if (m->running_as != SYSTEMD_SYSTEM) {
1205 dbus_set_error(&error, BUS_ERROR_NOT_SUPPORTED, "Halting is only supported for system managers.");
1206 return bus_send_error_reply(connection, message, &error, -ENOTSUP);
1209 reply = dbus_message_new_method_return(message);
1213 m->exit_code = MANAGER_HALT;
1215 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "KExec")) {
1217 SELINUX_ACCESS_CHECK(connection, message, "reboot");
1219 if (m->running_as != SYSTEMD_SYSTEM) {
1220 dbus_set_error(&error, BUS_ERROR_NOT_SUPPORTED, "kexec is only supported for system managers.");
1221 return bus_send_error_reply(connection, message, &error, -ENOTSUP);
1224 reply = dbus_message_new_method_return(message);
1228 m->exit_code = MANAGER_KEXEC;
1230 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "SwitchRoot")) {
1231 const char *switch_root, *switch_root_init;
1235 SELINUX_ACCESS_CHECK(connection, message, "reboot");
1237 if (!dbus_message_get_args(
1240 DBUS_TYPE_STRING, &switch_root,
1241 DBUS_TYPE_STRING, &switch_root_init,
1243 return bus_send_error_reply(connection, message, &error, -EINVAL);
1245 if (path_equal(switch_root, "/") || !path_is_absolute(switch_root))
1246 return bus_send_error_reply(connection, message, NULL, -EINVAL);
1248 if (!isempty(switch_root_init) && !path_is_absolute(switch_root_init))
1249 return bus_send_error_reply(connection, message, NULL, -EINVAL);
1251 if (m->running_as != SYSTEMD_SYSTEM) {
1252 dbus_set_error(&error, BUS_ERROR_NOT_SUPPORTED, "Switching root is only supported for system managers.");
1253 return bus_send_error_reply(connection, message, &error, -ENOTSUP);
1257 if (isempty(switch_root_init))
1258 k = access(switch_root, F_OK);
1262 p = strjoin(switch_root, "/", switch_root_init, NULL);
1266 k = access(p, X_OK);
1270 return bus_send_error_reply(connection, message, NULL, -errno);
1272 u = strdup(switch_root);
1276 if (!isempty(switch_root_init)) {
1277 v = strdup(switch_root_init);
1285 free(m->switch_root);
1286 free(m->switch_root_init);
1288 m->switch_root_init = v;
1290 reply = dbus_message_new_method_return(message);
1294 m->exit_code = MANAGER_SWITCH_ROOT;
1296 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "SetEnvironment")) {
1297 char **l = NULL, **e = NULL;
1299 SELINUX_ACCESS_CHECK(connection, message, "reboot");
1301 r = bus_parse_strv(message, &l);
1305 return bus_send_error_reply(connection, message, NULL, r);
1307 e = strv_env_merge(2, m->environment, l);
1312 reply = dbus_message_new_method_return(message);
1318 strv_free(m->environment);
1321 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "UnsetEnvironment")) {
1322 char **l = NULL, **e = NULL;
1324 SELINUX_ACCESS_CHECK(connection, message, "reboot");
1326 r = bus_parse_strv(message, &l);
1330 return bus_send_error_reply(connection, message, NULL, r);
1332 e = strv_env_delete(m->environment, 1, l);
1338 if (!(reply = dbus_message_new_method_return(message))) {
1343 strv_free(m->environment);
1346 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "UnsetAndSetEnvironment")) {
1347 char **l_set = NULL, **l_unset = NULL, **e = NULL, **f = NULL;
1348 DBusMessageIter iter;
1350 SELINUX_ACCESS_CHECK(connection, message, "reboot");
1352 if (!dbus_message_iter_init(message, &iter))
1355 r = bus_parse_strv_iter(&iter, &l_unset);
1359 return bus_send_error_reply(connection, message, NULL, r);
1361 if (!dbus_message_iter_next(&iter)) {
1363 return bus_send_error_reply(connection, message, NULL, -EINVAL);
1366 r = bus_parse_strv_iter(&iter, &l_set);
1372 return bus_send_error_reply(connection, message, NULL, r);
1375 e = strv_env_delete(m->environment, 1, l_unset);
1383 f = strv_env_merge(2, e, l_set);
1390 if (!(reply = dbus_message_new_method_return(message))) {
1395 strv_free(m->environment);
1397 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ListUnitFiles")) {
1398 DBusMessageIter iter, sub, sub2;
1403 SELINUX_ACCESS_CHECK(connection, message, "status");
1405 reply = dbus_message_new_method_return(message);
1409 h = hashmap_new(string_hash_func, string_compare_func);
1413 r = unit_file_get_list(m->running_as == SYSTEMD_SYSTEM ? UNIT_FILE_SYSTEM : UNIT_FILE_USER, NULL, h);
1415 unit_file_list_free(h);
1416 dbus_message_unref(reply);
1417 return bus_send_error_reply(connection, message, NULL, r);
1420 dbus_message_iter_init_append(reply, &iter);
1422 if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "(ss)", &sub)) {
1423 unit_file_list_free(h);
1427 HASHMAP_FOREACH(item, h, i) {
1430 state = unit_file_state_to_string(item->state);
1433 if (!dbus_message_iter_open_container(&sub, DBUS_TYPE_STRUCT, NULL, &sub2) ||
1434 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &item->path) ||
1435 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &state) ||
1436 !dbus_message_iter_close_container(&sub, &sub2)) {
1437 unit_file_list_free(h);
1442 unit_file_list_free(h);
1444 if (!dbus_message_iter_close_container(&iter, &sub))
1447 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "GetUnitFileState")) {
1449 UnitFileState state;
1452 SELINUX_ACCESS_CHECK(connection, message, "status");
1454 if (!dbus_message_get_args(
1457 DBUS_TYPE_STRING, &name,
1459 return bus_send_error_reply(connection, message, &error, -EINVAL);
1461 state = unit_file_get_state(m->running_as == SYSTEMD_SYSTEM ? UNIT_FILE_SYSTEM : UNIT_FILE_USER, NULL, name);
1463 return bus_send_error_reply(connection, message, NULL, state);
1465 s = unit_file_state_to_string(state);
1468 reply = dbus_message_new_method_return(message);
1472 if (!dbus_message_append_args(
1474 DBUS_TYPE_STRING, &s,
1477 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "EnableUnitFiles") ||
1478 dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ReenableUnitFiles") ||
1479 dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "LinkUnitFiles") ||
1480 dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "PresetUnitFiles") ||
1481 dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "MaskUnitFiles")) {
1484 DBusMessageIter iter;
1485 UnitFileScope scope = m->running_as == SYSTEMD_SYSTEM ? UNIT_FILE_SYSTEM : UNIT_FILE_USER;
1486 UnitFileChange *changes = NULL;
1487 unsigned n_changes = 0;
1488 dbus_bool_t runtime, force;
1489 int carries_install_info = -1;
1491 SELINUX_ACCESS_CHECK(connection, message, streq(member, "MaskUnitFiles") ? "disable" : "enable");
1493 if (!dbus_message_iter_init(message, &iter))
1496 r = bus_parse_strv_iter(&iter, &l);
1501 return bus_send_error_reply(connection, message, NULL, r);
1504 if (!dbus_message_iter_next(&iter) ||
1505 bus_iter_get_basic_and_next(&iter, DBUS_TYPE_BOOLEAN, &runtime, true) < 0 ||
1506 bus_iter_get_basic_and_next(&iter, DBUS_TYPE_BOOLEAN, &force, false) < 0) {
1508 return bus_send_error_reply(connection, message, NULL, -EIO);
1511 if (streq(member, "EnableUnitFiles")) {
1512 r = unit_file_enable(scope, runtime, NULL, l, force, &changes, &n_changes);
1513 carries_install_info = r;
1514 } else if (streq(member, "ReenableUnitFiles")) {
1515 r = unit_file_reenable(scope, runtime, NULL, l, force, &changes, &n_changes);
1516 carries_install_info = r;
1517 } else if (streq(member, "LinkUnitFiles"))
1518 r = unit_file_link(scope, runtime, NULL, l, force, &changes, &n_changes);
1519 else if (streq(member, "PresetUnitFiles")) {
1520 r = unit_file_preset(scope, runtime, NULL, l, force, &changes, &n_changes);
1521 carries_install_info = r;
1522 } else if (streq(member, "MaskUnitFiles"))
1523 r = unit_file_mask(scope, runtime, NULL, l, force, &changes, &n_changes);
1525 assert_not_reached("Uh? Wrong method");
1528 bus_manager_send_unit_files_changed(m);
1531 unit_file_changes_free(changes, n_changes);
1532 return bus_send_error_reply(connection, message, NULL, r);
1535 reply = message_from_file_changes(message, changes, n_changes, carries_install_info);
1536 unit_file_changes_free(changes, n_changes);
1541 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "DisableUnitFiles") ||
1542 dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "UnmaskUnitFiles")) {
1545 DBusMessageIter iter;
1546 UnitFileScope scope = m->running_as == SYSTEMD_SYSTEM ? UNIT_FILE_SYSTEM : UNIT_FILE_USER;
1547 UnitFileChange *changes = NULL;
1548 unsigned n_changes = 0;
1549 dbus_bool_t runtime;
1551 SELINUX_ACCESS_CHECK(connection, message, streq(member, "UnmaskUnitFiles") ? "enable" : "disable");
1553 if (!dbus_message_iter_init(message, &iter))
1556 r = bus_parse_strv_iter(&iter, &l);
1561 return bus_send_error_reply(connection, message, NULL, r);
1564 if (!dbus_message_iter_next(&iter) ||
1565 bus_iter_get_basic_and_next(&iter, DBUS_TYPE_BOOLEAN, &runtime, false) < 0) {
1567 return bus_send_error_reply(connection, message, NULL, -EIO);
1570 if (streq(member, "DisableUnitFiles"))
1571 r = unit_file_disable(scope, runtime, NULL, l, &changes, &n_changes);
1572 else if (streq(member, "UnmaskUnitFiles"))
1573 r = unit_file_unmask(scope, runtime, NULL, l, &changes, &n_changes);
1575 assert_not_reached("Uh? Wrong method");
1578 bus_manager_send_unit_files_changed(m);
1581 unit_file_changes_free(changes, n_changes);
1582 return bus_send_error_reply(connection, message, NULL, r);
1585 reply = message_from_file_changes(message, changes, n_changes, -1);
1586 unit_file_changes_free(changes, n_changes);
1592 const BusBoundProperties bps[] = {
1593 { "org.freedesktop.systemd1.Manager", bus_systemd_properties, systemd_property_string },
1594 { "org.freedesktop.systemd1.Manager", bus_manager_properties, m },
1598 SELINUX_ACCESS_CHECK(connection, message, "status");
1600 return bus_default_message_handler(connection, message, NULL, INTERFACES_LIST, bps);
1603 if (job_type != _JOB_TYPE_INVALID) {
1604 const char *name, *smode, *old_name = NULL;
1609 if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "StartUnitReplace"))
1610 b = dbus_message_get_args(
1613 DBUS_TYPE_STRING, &old_name,
1614 DBUS_TYPE_STRING, &name,
1615 DBUS_TYPE_STRING, &smode,
1618 b = dbus_message_get_args(
1621 DBUS_TYPE_STRING, &name,
1622 DBUS_TYPE_STRING, &smode,
1625 return bus_send_error_reply(connection, message, &error, -EINVAL);
1628 u = manager_get_unit(m, old_name);
1629 if (!u || !u->job || u->job->type != JOB_START) {
1630 dbus_set_error(&error, BUS_ERROR_NO_SUCH_JOB, "No job queued for unit %s", old_name);
1631 return bus_send_error_reply(connection, message, &error, -ENOENT);
1635 mode = job_mode_from_string(smode);
1637 dbus_set_error(&error, BUS_ERROR_INVALID_JOB_MODE, "Job mode %s is invalid.", smode);
1638 return bus_send_error_reply(connection, message, &error, -EINVAL);
1641 r = manager_load_unit(m, name, NULL, &error, &u);
1643 return bus_send_error_reply(connection, message, &error, r);
1645 return bus_unit_queue_job(connection, message, u, job_type, mode, reload_if_possible);
1649 if (!dbus_connection_send(connection, reply, NULL))
1652 return DBUS_HANDLER_RESULT_HANDLED;
1655 dbus_error_free(&error);
1657 return DBUS_HANDLER_RESULT_NEED_MEMORY;
1660 const DBusObjectPathVTable bus_manager_vtable = {
1661 .message_function = bus_manager_message_handler