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=\"ClearJobs\"/>\n" \
110 " <method name=\"ResetFailed\"/>\n" \
111 " <method name=\"ListUnits\">\n" \
112 " <arg name=\"units\" type=\"a(ssssssouso)\" direction=\"out\"/>\n" \
114 " <method name=\"ListJobs\">\n" \
115 " <arg name=\"jobs\" type=\"a(usssoo)\" direction=\"out\"/>\n" \
117 " <method name=\"Subscribe\"/>\n" \
118 " <method name=\"Unsubscribe\"/>\n" \
119 " <method name=\"Dump\">\n" \
120 " <arg name=\"dump\" type=\"s\" direction=\"out\"/>\n" \
122 " <method name=\"CreateSnapshot\">\n" \
123 " <arg name=\"name\" type=\"s\" direction=\"in\"/>\n" \
124 " <arg name=\"cleanup\" type=\"b\" direction=\"in\"/>\n" \
125 " <arg name=\"unit\" type=\"o\" direction=\"out\"/>\n" \
127 " <method name=\"Reload\"/>\n" \
128 " <method name=\"Reexecute\"/>\n" \
129 " <method name=\"Exit\"/>\n" \
130 " <method name=\"Reboot\"/>\n" \
131 " <method name=\"PowerOff\"/>\n" \
132 " <method name=\"Halt\"/>\n" \
133 " <method name=\"KExec\"/>\n" \
134 " <method name=\"SwitchRoot\">\n" \
135 " <arg name=\"new_root\" type=\"s\" direction=\"in\"/>\n" \
136 " <arg name=\"init\" type=\"s\" direction=\"in\"/>\n" \
138 " <method name=\"SetEnvironment\">\n" \
139 " <arg name=\"names\" type=\"as\" direction=\"in\"/>\n" \
141 " <method name=\"UnsetEnvironment\">\n" \
142 " <arg name=\"names\" type=\"as\" direction=\"in\"/>\n" \
144 " <method name=\"UnsetAndSetEnvironment\">\n" \
145 " <arg name=\"unset\" type=\"as\" direction=\"in\"/>\n" \
146 " <arg name=\"set\" type=\"as\" direction=\"in\"/>\n" \
148 " <method name=\"ListUnitFiles\">\n" \
149 " <arg name=\"files\" type=\"a(ss)\" direction=\"out\"/>\n" \
151 " <method name=\"GetUnitFileState\">\n" \
152 " <arg name=\"file\" type=\"s\" direction=\"in\"/>\n" \
153 " <arg name=\"state\" type=\"s\" direction=\"out\"/>\n" \
155 " <method name=\"EnableUnitFiles\">\n" \
156 " <arg name=\"files\" type=\"as\" direction=\"in\"/>\n" \
157 " <arg name=\"runtime\" type=\"b\" direction=\"in\"/>\n" \
158 " <arg name=\"force\" type=\"b\" direction=\"in\"/>\n" \
159 " <arg name=\"carries_install_info\" type=\"b\" direction=\"out\"/>\n" \
160 " <arg name=\"changes\" type=\"a(sss)\" direction=\"out\"/>\n" \
162 " <method name=\"DisableUnitFiles\">\n" \
163 " <arg name=\"files\" type=\"as\" direction=\"in\"/>\n" \
164 " <arg name=\"runtime\" type=\"b\" direction=\"in\"/>\n" \
165 " <arg name=\"changes\" type=\"a(sss)\" direction=\"out\"/>\n" \
167 " <method name=\"ReenableUnitFiles\">\n" \
168 " <arg name=\"files\" type=\"as\" direction=\"in\"/>\n" \
169 " <arg name=\"runtime\" type=\"b\" direction=\"in\"/>\n" \
170 " <arg name=\"force\" type=\"b\" direction=\"in\"/>\n" \
171 " <arg name=\"carries_install_info\" type=\"b\" direction=\"out\"/>\n" \
172 " <arg name=\"changes\" type=\"a(sss)\" direction=\"out\"/>\n" \
174 " <method name=\"LinkUnitFiles\">\n" \
175 " <arg name=\"files\" type=\"as\" direction=\"in\"/>\n" \
176 " <arg name=\"runtime\" type=\"b\" direction=\"in\"/>\n" \
177 " <arg name=\"force\" type=\"b\" direction=\"in\"/>\n" \
178 " <arg name=\"changes\" type=\"a(sss)\" direction=\"out\"/>\n" \
180 " <method name=\"PresetUnitFiles\">\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=\"carries_install_info\" type=\"b\" direction=\"out\"/>\n" \
185 " <arg name=\"changes\" type=\"a(sss)\" direction=\"out\"/>\n" \
187 " <method name=\"MaskUnitFiles\">\n" \
188 " <arg name=\"files\" type=\"as\" direction=\"in\"/>\n" \
189 " <arg name=\"runtime\" type=\"b\" direction=\"in\"/>\n" \
190 " <arg name=\"force\" type=\"b\" direction=\"in\"/>\n" \
191 " <arg name=\"changes\" type=\"a(sss)\" direction=\"out\"/>\n" \
193 " <method name=\"UnmaskUnitFiles\">\n" \
194 " <arg name=\"files\" type=\"as\" direction=\"in\"/>\n" \
195 " <arg name=\"runtime\" type=\"b\" direction=\"in\"/>\n" \
196 " <arg name=\"changes\" type=\"a(sss)\" direction=\"out\"/>\n" \
199 #define BUS_MANAGER_INTERFACE_SIGNALS \
200 " <signal name=\"UnitNew\">\n" \
201 " <arg name=\"id\" type=\"s\"/>\n" \
202 " <arg name=\"unit\" type=\"o\"/>\n" \
204 " <signal name=\"UnitRemoved\">\n" \
205 " <arg name=\"id\" type=\"s\"/>\n" \
206 " <arg name=\"unit\" type=\"o\"/>\n" \
208 " <signal name=\"JobNew\">\n" \
209 " <arg name=\"id\" type=\"u\"/>\n" \
210 " <arg name=\"job\" type=\"o\"/>\n" \
211 " <arg name=\"unit\" type=\"s\"/>\n" \
213 " <signal name=\"JobRemoved\">\n" \
214 " <arg name=\"id\" type=\"u\"/>\n" \
215 " <arg name=\"job\" type=\"o\"/>\n" \
216 " <arg name=\"unit\" type=\"s\"/>\n" \
217 " <arg name=\"result\" type=\"s\"/>\n" \
219 " <signal name=\"StartupFinished\">\n" \
220 " <arg name=\"firmware\" type=\"t\"/>\n" \
221 " <arg name=\"loader\" type=\"t\"/>\n" \
222 " <arg name=\"kernel\" type=\"t\"/>\n" \
223 " <arg name=\"initrd\" type=\"t\"/>\n" \
224 " <arg name=\"userspace\" type=\"t\"/>\n" \
225 " <arg name=\"total\" type=\"t\"/>\n" \
227 " <signal name=\"UnitFilesChanged\"/>\n"
229 #define BUS_MANAGER_INTERFACE_PROPERTIES_GENERAL \
230 " <property name=\"Version\" 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" \
262 " <property name=\"Virtualization\" type=\"s\" access=\"read\"/>\n"
264 #define BUS_MANAGER_INTERFACE_END \
267 #define BUS_MANAGER_INTERFACE \
268 BUS_MANAGER_INTERFACE_BEGIN \
269 BUS_MANAGER_INTERFACE_METHODS \
270 BUS_MANAGER_INTERFACE_SIGNALS \
271 BUS_MANAGER_INTERFACE_PROPERTIES_GENERAL \
272 BUS_MANAGER_INTERFACE_END
274 #define INTROSPECTION_BEGIN \
275 DBUS_INTROSPECT_1_0_XML_DOCTYPE_DECL_NODE \
277 BUS_MANAGER_INTERFACE \
278 BUS_PROPERTIES_INTERFACE \
280 BUS_INTROSPECTABLE_INTERFACE
282 #define INTROSPECTION_END \
285 #define INTERFACES_LIST \
286 BUS_GENERIC_INTERFACES_LIST \
287 "org.freedesktop.systemd1.Manager\0"
289 const char bus_manager_interface[] _introspect_("Manager") = BUS_MANAGER_INTERFACE;
291 static DEFINE_BUS_PROPERTY_APPEND_ENUM(bus_manager_append_exec_output, exec_output, ExecOutput);
293 static int bus_manager_append_tainted(DBusMessageIter *i, const char *property, void *data) {
296 char buf[LINE_MAX] = "", *e = buf, *p = NULL;
303 e = stpcpy(e, "split-usr:");
305 if (readlink_malloc("/etc/mtab", &p) < 0)
306 e = stpcpy(e, "mtab-not-symlink:");
310 if (access("/proc/cgroups", F_OK) < 0)
311 e = stpcpy(e, "cgroups-missing:");
313 if (hwclock_is_localtime() > 0)
314 e = stpcpy(e, "local-hwclock:");
316 /* remove the last ':' */
322 if (!dbus_message_iter_append_basic(i, DBUS_TYPE_STRING, &t))
328 static int bus_manager_append_log_target(DBusMessageIter *i, const char *property, void *data) {
334 t = log_target_to_string(log_get_target());
336 if (!dbus_message_iter_append_basic(i, DBUS_TYPE_STRING, &t))
342 static int bus_manager_set_log_target(DBusMessageIter *i, const char *property, void *data) {
348 dbus_message_iter_get_basic(i, &t);
350 return log_set_target_from_string(t);
353 static int bus_manager_append_log_level(DBusMessageIter *i, const char *property, void *data) {
360 r = log_level_to_string_alloc(log_get_max_level(), &t);
364 if (!dbus_message_iter_append_basic(i, DBUS_TYPE_STRING, &t))
371 static int bus_manager_set_log_level(DBusMessageIter *i, const char *property, void *data) {
377 dbus_message_iter_get_basic(i, &t);
379 return log_set_max_level_from_string(t);
382 static int bus_manager_append_n_names(DBusMessageIter *i, const char *property, void *data) {
390 u = hashmap_size(m->units);
392 if (!dbus_message_iter_append_basic(i, DBUS_TYPE_UINT32, &u))
398 static int bus_manager_append_n_jobs(DBusMessageIter *i, const char *property, void *data) {
406 u = hashmap_size(m->jobs);
408 if (!dbus_message_iter_append_basic(i, DBUS_TYPE_UINT32, &u))
414 static int bus_manager_append_progress(DBusMessageIter *i, const char *property, void *data) {
422 if (dual_timestamp_is_set(&m->finish_timestamp))
425 d = 1.0 - ((double) hashmap_size(m->jobs) / (double) m->n_installed_jobs);
427 if (!dbus_message_iter_append_basic(i, DBUS_TYPE_DOUBLE, &d))
433 static int bus_manager_append_virt(DBusMessageIter *i, const char *property, void *data) {
441 detect_virtualization(&id);
443 if (!dbus_message_iter_append_basic(i, DBUS_TYPE_STRING, &id))
449 static DBusMessage *message_from_file_changes(
451 UnitFileChange *changes,
453 int carries_install_info) {
455 DBusMessageIter iter, sub, sub2;
459 reply = dbus_message_new_method_return(m);
463 dbus_message_iter_init_append(reply, &iter);
465 if (carries_install_info >= 0) {
468 b = !!carries_install_info;
469 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &b))
473 if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "(sss)", &sub))
476 for (i = 0; i < n_changes; i++) {
477 const char *type, *path, *source;
479 type = unit_file_change_type_to_string(changes[i].type);
480 path = strempty(changes[i].path);
481 source = strempty(changes[i].source);
483 if (!dbus_message_iter_open_container(&sub, DBUS_TYPE_STRUCT, NULL, &sub2) ||
484 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &type) ||
485 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &path) ||
486 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &source) ||
487 !dbus_message_iter_close_container(&sub, &sub2))
491 if (!dbus_message_iter_close_container(&iter, &sub))
497 dbus_message_unref(reply);
501 static int bus_manager_send_unit_files_changed(Manager *m) {
505 s = dbus_message_new_signal("/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", "UnitFilesChanged");
509 r = bus_broadcast(m, s);
510 dbus_message_unref(s);
515 static int bus_manager_set_runtime_watchdog_usec(DBusMessageIter *i, const char *property, void *data) {
521 dbus_message_iter_get_basic(i, t);
523 return watchdog_set_timeout(t);
526 static const char systemd_property_string[] =
530 static const BusProperty bus_systemd_properties[] = {
531 { "Version", bus_property_append_string, "s", 0 },
532 { "Features", bus_property_append_string, "s", sizeof(PACKAGE_STRING) },
536 static const BusProperty bus_manager_properties[] = {
537 { "Tainted", bus_manager_append_tainted, "s", 0 },
538 { "FirmwareTimestamp", bus_property_append_uint64, "t", offsetof(Manager, firmware_timestamp.realtime) },
539 { "FirmwareTimestampMonotonic", bus_property_append_uint64, "t", offsetof(Manager, firmware_timestamp.monotonic) },
540 { "LoaderTimestamp", bus_property_append_uint64, "t", offsetof(Manager, loader_timestamp.realtime) },
541 { "LoaderTimestampMonotonic", bus_property_append_uint64, "t", offsetof(Manager, loader_timestamp.monotonic) },
542 { "KernelTimestamp", bus_property_append_uint64, "t", offsetof(Manager, kernel_timestamp.realtime) },
543 { "KernelTimestampMonotonic", bus_property_append_uint64, "t", offsetof(Manager, kernel_timestamp.monotonic) },
544 { "InitRDTimestamp", bus_property_append_uint64, "t", offsetof(Manager, initrd_timestamp.realtime) },
545 { "InitRDTimestampMonotonic", bus_property_append_uint64, "t", offsetof(Manager, initrd_timestamp.monotonic) },
546 { "UserspaceTimestamp", bus_property_append_uint64, "t", offsetof(Manager, userspace_timestamp.realtime) },
547 { "UserspaceTimestampMonotonic", bus_property_append_uint64, "t", offsetof(Manager, userspace_timestamp.monotonic) },
548 { "FinishTimestamp", bus_property_append_uint64, "t", offsetof(Manager, finish_timestamp.realtime) },
549 { "FinishTimestampMonotonic", bus_property_append_uint64, "t", offsetof(Manager, finish_timestamp.monotonic) },
550 { "LogLevel", bus_manager_append_log_level, "s", 0, false, bus_manager_set_log_level },
551 { "LogTarget", bus_manager_append_log_target, "s", 0, false, bus_manager_set_log_target },
552 { "NNames", bus_manager_append_n_names, "u", 0 },
553 { "NJobs", bus_manager_append_n_jobs, "u", 0 },
554 { "NInstalledJobs", bus_property_append_uint32, "u", offsetof(Manager, n_installed_jobs) },
555 { "NFailedJobs", bus_property_append_uint32, "u", offsetof(Manager, n_failed_jobs) },
556 { "Progress", bus_manager_append_progress, "d", 0 },
557 { "Environment", bus_property_append_strv, "as", offsetof(Manager, environment), true },
558 { "ConfirmSpawn", bus_property_append_bool, "b", offsetof(Manager, confirm_spawn) },
559 { "ShowStatus", bus_property_append_bool, "b", offsetof(Manager, show_status) },
560 { "UnitPath", bus_property_append_strv, "as", offsetof(Manager, lookup_paths.unit_path), true },
561 { "ControlGroupHierarchy", bus_property_append_string, "s", offsetof(Manager, cgroup_hierarchy), true },
562 { "DefaultControllers", bus_property_append_strv, "as", offsetof(Manager, default_controllers), true },
563 { "DefaultStandardOutput", bus_manager_append_exec_output, "s", offsetof(Manager, default_std_output) },
564 { "DefaultStandardError", bus_manager_append_exec_output, "s", offsetof(Manager, default_std_error) },
565 { "RuntimeWatchdogUSec", bus_property_append_usec, "t", offsetof(Manager, runtime_watchdog), false, bus_manager_set_runtime_watchdog_usec },
566 { "ShutdownWatchdogUSec", bus_property_append_usec, "t", offsetof(Manager, shutdown_watchdog), false, bus_property_set_usec },
567 { "Virtualization", bus_manager_append_virt, "s", 0, },
571 static DBusHandlerResult bus_manager_message_handler(DBusConnection *connection, DBusMessage *message, void *data) {
572 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
573 _cleanup_free_ char * path = NULL;
577 JobType job_type = _JOB_TYPE_INVALID;
578 bool reload_if_possible = false;
585 dbus_error_init(&error);
587 member = dbus_message_get_member(message);
589 if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "GetUnit")) {
593 if (!dbus_message_get_args(
596 DBUS_TYPE_STRING, &name,
598 return bus_send_error_reply(connection, message, &error, -EINVAL);
600 u = manager_get_unit(m, name);
602 dbus_set_error(&error, BUS_ERROR_NO_SUCH_UNIT, "Unit %s is not loaded.", name);
603 return bus_send_error_reply(connection, message, &error, -ENOENT);
606 SELINUX_UNIT_ACCESS_CHECK(u, connection, message, "status");
608 reply = dbus_message_new_method_return(message);
612 path = unit_dbus_path(u);
616 if (!dbus_message_append_args(
618 DBUS_TYPE_OBJECT_PATH, &path,
621 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "GetUnitByPID")) {
625 if (!dbus_message_get_args(
628 DBUS_TYPE_UINT32, &pid,
630 return bus_send_error_reply(connection, message, &error, -EINVAL);
632 u = cgroup_unit_by_pid(m, (pid_t) pid);
634 dbus_set_error(&error, BUS_ERROR_NO_SUCH_UNIT, "No unit for PID %lu is loaded.", (unsigned long) pid);
635 return bus_send_error_reply(connection, message, &error, -ENOENT);
638 SELINUX_UNIT_ACCESS_CHECK(u, connection, message, "status");
640 reply = dbus_message_new_method_return(message);
644 path = unit_dbus_path(u);
648 if (!dbus_message_append_args(
650 DBUS_TYPE_OBJECT_PATH, &path,
653 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "LoadUnit")) {
657 if (!dbus_message_get_args(
660 DBUS_TYPE_STRING, &name,
662 return bus_send_error_reply(connection, message, &error, -EINVAL);
664 r = manager_load_unit(m, name, NULL, &error, &u);
666 return bus_send_error_reply(connection, message, &error, r);
668 SELINUX_UNIT_ACCESS_CHECK(u, connection, message, "status");
670 reply = dbus_message_new_method_return(message);
674 path = unit_dbus_path(u);
678 if (!dbus_message_append_args(
680 DBUS_TYPE_OBJECT_PATH, &path,
684 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "StartUnit"))
685 job_type = JOB_START;
686 else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "StartUnitReplace"))
687 job_type = JOB_START;
688 else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "StopUnit"))
690 else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ReloadUnit"))
691 job_type = JOB_RELOAD;
692 else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "RestartUnit"))
693 job_type = JOB_RESTART;
694 else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "TryRestartUnit"))
695 job_type = JOB_TRY_RESTART;
696 else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ReloadOrRestartUnit")) {
697 reload_if_possible = true;
698 job_type = JOB_RESTART;
699 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ReloadOrTryRestartUnit")) {
700 reload_if_possible = true;
701 job_type = JOB_TRY_RESTART;
702 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "KillUnit")) {
703 const char *name, *swho;
708 if (!dbus_message_get_args(
711 DBUS_TYPE_STRING, &name,
712 DBUS_TYPE_STRING, &swho,
713 DBUS_TYPE_INT32, &signo,
715 return bus_send_error_reply(connection, message, &error, -EINVAL);
720 who = kill_who_from_string(swho);
722 return bus_send_error_reply(connection, message, &error, -EINVAL);
725 if (signo <= 0 || signo >= _NSIG)
726 return bus_send_error_reply(connection, message, &error, -EINVAL);
728 u = manager_get_unit(m, name);
730 dbus_set_error(&error, BUS_ERROR_NO_SUCH_UNIT, "Unit %s is not loaded.", name);
731 return bus_send_error_reply(connection, message, &error, -ENOENT);
734 SELINUX_UNIT_ACCESS_CHECK(u, connection, message, "stop");
736 r = unit_kill(u, who, signo, &error);
738 return bus_send_error_reply(connection, message, &error, r);
740 reply = dbus_message_new_method_return(message);
744 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "GetJob")) {
748 if (!dbus_message_get_args(
751 DBUS_TYPE_UINT32, &id,
753 return bus_send_error_reply(connection, message, &error, -EINVAL);
755 j = manager_get_job(m, id);
757 dbus_set_error(&error, BUS_ERROR_NO_SUCH_JOB, "Job %u does not exist.", (unsigned) id);
758 return bus_send_error_reply(connection, message, &error, -ENOENT);
761 SELINUX_UNIT_ACCESS_CHECK(j->unit, connection, message, "status");
763 reply = dbus_message_new_method_return(message);
767 path = job_dbus_path(j);
771 if (!dbus_message_append_args(
773 DBUS_TYPE_OBJECT_PATH, &path,
777 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ClearJobs")) {
779 SELINUX_ACCESS_CHECK(connection, message, "reboot");
781 manager_clear_jobs(m);
783 reply = dbus_message_new_method_return(message);
787 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ResetFailed")) {
789 SELINUX_ACCESS_CHECK(connection, message, "reload");
791 manager_reset_failed(m);
793 reply = dbus_message_new_method_return(message);
797 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ResetFailedUnit")) {
801 if (!dbus_message_get_args(
804 DBUS_TYPE_STRING, &name,
806 return bus_send_error_reply(connection, message, &error, -EINVAL);
808 u = manager_get_unit(m, name);
810 dbus_set_error(&error, BUS_ERROR_NO_SUCH_UNIT, "Unit %s is not loaded.", name);
811 return bus_send_error_reply(connection, message, &error, -ENOENT);
814 SELINUX_UNIT_ACCESS_CHECK(u, connection, message, "reload");
816 unit_reset_failed(u);
818 reply = dbus_message_new_method_return(message);
822 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ListUnits")) {
823 DBusMessageIter iter, sub;
828 SELINUX_ACCESS_CHECK(connection, message, "status");
830 reply = dbus_message_new_method_return(message);
834 dbus_message_iter_init_append(reply, &iter);
836 if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "(ssssssouso)", &sub))
839 HASHMAP_FOREACH_KEY(u, k, m->units, i) {
840 char *u_path, *j_path;
841 const char *description, *load_state, *active_state, *sub_state, *sjob_type, *following;
842 DBusMessageIter sub2;
849 if (!dbus_message_iter_open_container(&sub, DBUS_TYPE_STRUCT, NULL, &sub2))
852 description = unit_description(u);
853 load_state = unit_load_state_to_string(u->load_state);
854 active_state = unit_active_state_to_string(unit_active_state(u));
855 sub_state = unit_sub_state_to_string(u);
857 f = unit_following(u);
858 following = f ? f->id : "";
860 u_path = unit_dbus_path(u);
865 job_id = (uint32_t) u->job->id;
867 if (!(j_path = job_dbus_path(u->job))) {
872 sjob_type = job_type_to_string(u->job->type);
879 if (!dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &u->id) ||
880 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &description) ||
881 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &load_state) ||
882 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &active_state) ||
883 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &sub_state) ||
884 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &following) ||
885 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_OBJECT_PATH, &u_path) ||
886 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_UINT32, &job_id) ||
887 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &sjob_type) ||
888 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_OBJECT_PATH, &j_path)) {
899 if (!dbus_message_iter_close_container(&sub, &sub2))
903 if (!dbus_message_iter_close_container(&iter, &sub))
906 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ListJobs")) {
907 DBusMessageIter iter, sub;
911 SELINUX_ACCESS_CHECK(connection, message, "status");
913 reply = dbus_message_new_method_return(message);
917 dbus_message_iter_init_append(reply, &iter);
919 if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "(usssoo)", &sub))
922 HASHMAP_FOREACH(j, m->jobs, i) {
923 char *u_path, *j_path;
924 const char *state, *type;
926 DBusMessageIter sub2;
928 if (!dbus_message_iter_open_container(&sub, DBUS_TYPE_STRUCT, NULL, &sub2))
931 id = (uint32_t) j->id;
932 state = job_state_to_string(j->state);
933 type = job_type_to_string(j->type);
935 j_path = job_dbus_path(j);
939 u_path = unit_dbus_path(j->unit);
945 if (!dbus_message_iter_append_basic(&sub2, DBUS_TYPE_UINT32, &id) ||
946 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &j->unit->id) ||
947 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &type) ||
948 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &state) ||
949 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_OBJECT_PATH, &j_path) ||
950 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_OBJECT_PATH, &u_path)) {
959 if (!dbus_message_iter_close_container(&sub, &sub2))
963 if (!dbus_message_iter_close_container(&iter, &sub))
966 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "Subscribe")) {
970 SELINUX_ACCESS_CHECK(connection, message, "status");
972 s = BUS_CONNECTION_SUBSCRIBED(m, connection);
974 s = set_new(string_hash_func, string_compare_func);
978 if (!dbus_connection_set_data(connection, m->subscribed_data_slot, s, NULL)) {
984 client = strdup(bus_message_get_sender_with_fallback(message));
988 r = set_put(s, client);
991 return bus_send_error_reply(connection, message, NULL, r);
994 reply = dbus_message_new_method_return(message);
998 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "Unsubscribe")) {
1001 SELINUX_ACCESS_CHECK(connection, message, "status");
1003 client = set_remove(BUS_CONNECTION_SUBSCRIBED(m, connection), (char*) bus_message_get_sender_with_fallback(message));
1005 dbus_set_error(&error, BUS_ERROR_NOT_SUBSCRIBED, "Client is not subscribed.");
1006 return bus_send_error_reply(connection, message, &error, -ENOENT);
1011 reply = dbus_message_new_method_return(message);
1015 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "Dump")) {
1020 SELINUX_ACCESS_CHECK(connection, message, "status");
1022 reply = dbus_message_new_method_return(message);
1026 f = open_memstream(&dump, &size);
1030 manager_dump_units(m, f, NULL);
1031 manager_dump_jobs(m, f, NULL);
1041 if (!dbus_message_append_args(reply, DBUS_TYPE_STRING, &dump, DBUS_TYPE_INVALID)) {
1047 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "CreateSnapshot")) {
1049 dbus_bool_t cleanup;
1052 SELINUX_ACCESS_CHECK(connection, message, "start");
1054 if (!dbus_message_get_args(
1057 DBUS_TYPE_STRING, &name,
1058 DBUS_TYPE_BOOLEAN, &cleanup,
1060 return bus_send_error_reply(connection, message, &error, -EINVAL);
1065 r = snapshot_create(m, name, cleanup, &error, &s);
1067 return bus_send_error_reply(connection, message, &error, r);
1069 reply = dbus_message_new_method_return(message);
1073 path = unit_dbus_path(UNIT(s));
1077 if (!dbus_message_append_args(
1079 DBUS_TYPE_OBJECT_PATH, &path,
1083 } else if (dbus_message_is_method_call(message, "org.freedesktop.DBus.Introspectable", "Introspect")) {
1084 char *introspection = NULL;
1092 SELINUX_ACCESS_CHECK(connection, message, "status");
1094 reply = dbus_message_new_method_return(message);
1098 /* We roll our own introspection code here, instead of
1099 * relying on bus_default_message_handler() because we
1100 * need to generate our introspection string
1103 f = open_memstream(&introspection, &size);
1107 fputs(INTROSPECTION_BEGIN, f);
1109 HASHMAP_FOREACH_KEY(u, k, m->units, i) {
1115 p = bus_path_escape(k);
1118 free(introspection);
1122 fprintf(f, "<node name=\"unit/%s\"/>", p);
1126 HASHMAP_FOREACH(j, m->jobs, i)
1127 fprintf(f, "<node name=\"job/%lu\"/>", (unsigned long) j->id);
1129 fputs(INTROSPECTION_END, f);
1133 free(introspection);
1142 if (!dbus_message_append_args(reply, DBUS_TYPE_STRING, &introspection, DBUS_TYPE_INVALID)) {
1143 free(introspection);
1147 free(introspection);
1149 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "Reload")) {
1151 SELINUX_ACCESS_CHECK(connection, message, "reload");
1153 assert(!m->queued_message);
1155 /* Instead of sending the reply back right away, we
1156 * just remember that we need to and then send it
1157 * after the reload is finished. That way the caller
1158 * knows when the reload finished. */
1160 m->queued_message = dbus_message_new_method_return(message);
1161 if (!m->queued_message)
1164 m->queued_message_connection = connection;
1165 m->exit_code = MANAGER_RELOAD;
1167 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "Reexecute")) {
1169 SELINUX_ACCESS_CHECK(connection, message, "reload");
1171 /* We don't send a reply back here, the client should
1172 * just wait for us disconnecting. */
1174 m->exit_code = MANAGER_REEXECUTE;
1176 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "Exit")) {
1178 SELINUX_ACCESS_CHECK(connection, message, "halt");
1180 if (m->running_as == SYSTEMD_SYSTEM) {
1181 dbus_set_error(&error, BUS_ERROR_NOT_SUPPORTED, "Exit is only supported for user service managers.");
1182 return bus_send_error_reply(connection, message, &error, -ENOTSUP);
1185 reply = dbus_message_new_method_return(message);
1189 m->exit_code = MANAGER_EXIT;
1191 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "Reboot")) {
1193 SELINUX_ACCESS_CHECK(connection, message, "reboot");
1195 if (m->running_as != SYSTEMD_SYSTEM) {
1196 dbus_set_error(&error, BUS_ERROR_NOT_SUPPORTED, "Reboot is only supported for system managers.");
1197 return bus_send_error_reply(connection, message, &error, -ENOTSUP);
1200 reply = dbus_message_new_method_return(message);
1204 m->exit_code = MANAGER_REBOOT;
1206 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "PowerOff")) {
1208 SELINUX_ACCESS_CHECK(connection, message, "halt");
1210 if (m->running_as != SYSTEMD_SYSTEM) {
1211 dbus_set_error(&error, BUS_ERROR_NOT_SUPPORTED, "Powering off is only supported for system managers.");
1212 return bus_send_error_reply(connection, message, &error, -ENOTSUP);
1215 reply = dbus_message_new_method_return(message);
1219 m->exit_code = MANAGER_POWEROFF;
1221 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "Halt")) {
1223 SELINUX_ACCESS_CHECK(connection, message, "halt");
1225 if (m->running_as != SYSTEMD_SYSTEM) {
1226 dbus_set_error(&error, BUS_ERROR_NOT_SUPPORTED, "Halting is only supported for system managers.");
1227 return bus_send_error_reply(connection, message, &error, -ENOTSUP);
1230 reply = dbus_message_new_method_return(message);
1234 m->exit_code = MANAGER_HALT;
1236 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "KExec")) {
1238 SELINUX_ACCESS_CHECK(connection, message, "reboot");
1240 if (m->running_as != SYSTEMD_SYSTEM) {
1241 dbus_set_error(&error, BUS_ERROR_NOT_SUPPORTED, "kexec is only supported for system managers.");
1242 return bus_send_error_reply(connection, message, &error, -ENOTSUP);
1245 reply = dbus_message_new_method_return(message);
1249 m->exit_code = MANAGER_KEXEC;
1251 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "SwitchRoot")) {
1252 const char *switch_root, *switch_root_init;
1256 SELINUX_ACCESS_CHECK(connection, message, "reboot");
1258 if (!dbus_message_get_args(
1261 DBUS_TYPE_STRING, &switch_root,
1262 DBUS_TYPE_STRING, &switch_root_init,
1264 return bus_send_error_reply(connection, message, &error, -EINVAL);
1266 if (path_equal(switch_root, "/") || !path_is_absolute(switch_root))
1267 return bus_send_error_reply(connection, message, NULL, -EINVAL);
1269 if (!isempty(switch_root_init) && !path_is_absolute(switch_root_init))
1270 return bus_send_error_reply(connection, message, NULL, -EINVAL);
1272 if (m->running_as != SYSTEMD_SYSTEM) {
1273 dbus_set_error(&error, BUS_ERROR_NOT_SUPPORTED, "Switching root is only supported for system managers.");
1274 return bus_send_error_reply(connection, message, &error, -ENOTSUP);
1278 if (isempty(switch_root_init))
1279 k = access(switch_root, F_OK);
1283 p = strjoin(switch_root, "/", switch_root_init, NULL);
1287 k = access(p, X_OK);
1291 return bus_send_error_reply(connection, message, NULL, -errno);
1293 u = strdup(switch_root);
1297 if (!isempty(switch_root_init)) {
1298 v = strdup(switch_root_init);
1306 free(m->switch_root);
1307 free(m->switch_root_init);
1309 m->switch_root_init = v;
1311 reply = dbus_message_new_method_return(message);
1315 m->exit_code = MANAGER_SWITCH_ROOT;
1317 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "SetEnvironment")) {
1318 char **l = NULL, **e = NULL;
1320 SELINUX_ACCESS_CHECK(connection, message, "reboot");
1322 r = bus_parse_strv(message, &l);
1326 return bus_send_error_reply(connection, message, NULL, r);
1328 e = strv_env_merge(2, m->environment, l);
1333 reply = dbus_message_new_method_return(message);
1339 strv_free(m->environment);
1342 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "UnsetEnvironment")) {
1343 char **l = NULL, **e = NULL;
1345 SELINUX_ACCESS_CHECK(connection, message, "reboot");
1347 r = bus_parse_strv(message, &l);
1351 return bus_send_error_reply(connection, message, NULL, r);
1353 e = strv_env_delete(m->environment, 1, l);
1359 reply = dbus_message_new_method_return(message);
1365 strv_free(m->environment);
1368 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "UnsetAndSetEnvironment")) {
1369 char **l_set = NULL, **l_unset = NULL, **e = NULL, **f = NULL;
1370 DBusMessageIter iter;
1372 SELINUX_ACCESS_CHECK(connection, message, "reboot");
1374 if (!dbus_message_iter_init(message, &iter))
1377 r = bus_parse_strv_iter(&iter, &l_unset);
1381 return bus_send_error_reply(connection, message, NULL, r);
1383 if (!dbus_message_iter_next(&iter)) {
1385 return bus_send_error_reply(connection, message, NULL, -EINVAL);
1388 r = bus_parse_strv_iter(&iter, &l_set);
1394 return bus_send_error_reply(connection, message, NULL, r);
1397 e = strv_env_delete(m->environment, 1, l_unset);
1405 f = strv_env_merge(2, e, l_set);
1412 reply = dbus_message_new_method_return(message);
1418 strv_free(m->environment);
1420 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ListUnitFiles")) {
1421 DBusMessageIter iter, sub, sub2;
1426 SELINUX_ACCESS_CHECK(connection, message, "status");
1428 reply = dbus_message_new_method_return(message);
1432 h = hashmap_new(string_hash_func, string_compare_func);
1436 r = unit_file_get_list(m->running_as == SYSTEMD_SYSTEM ? UNIT_FILE_SYSTEM : UNIT_FILE_USER, NULL, h);
1438 unit_file_list_free(h);
1439 return bus_send_error_reply(connection, message, NULL, r);
1442 dbus_message_iter_init_append(reply, &iter);
1444 if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "(ss)", &sub)) {
1445 unit_file_list_free(h);
1449 HASHMAP_FOREACH(item, h, i) {
1452 state = unit_file_state_to_string(item->state);
1455 if (!dbus_message_iter_open_container(&sub, DBUS_TYPE_STRUCT, NULL, &sub2) ||
1456 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &item->path) ||
1457 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &state) ||
1458 !dbus_message_iter_close_container(&sub, &sub2)) {
1459 unit_file_list_free(h);
1464 unit_file_list_free(h);
1466 if (!dbus_message_iter_close_container(&iter, &sub))
1469 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "GetUnitFileState")) {
1471 UnitFileState state;
1474 SELINUX_ACCESS_CHECK(connection, message, "status");
1476 if (!dbus_message_get_args(
1479 DBUS_TYPE_STRING, &name,
1481 return bus_send_error_reply(connection, message, &error, -EINVAL);
1483 state = unit_file_get_state(m->running_as == SYSTEMD_SYSTEM ? UNIT_FILE_SYSTEM : UNIT_FILE_USER, NULL, name);
1485 return bus_send_error_reply(connection, message, NULL, state);
1487 s = unit_file_state_to_string(state);
1490 reply = dbus_message_new_method_return(message);
1494 if (!dbus_message_append_args(
1496 DBUS_TYPE_STRING, &s,
1499 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "EnableUnitFiles") ||
1500 dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ReenableUnitFiles") ||
1501 dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "LinkUnitFiles") ||
1502 dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "PresetUnitFiles") ||
1503 dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "MaskUnitFiles")) {
1506 DBusMessageIter iter;
1507 UnitFileScope scope = m->running_as == SYSTEMD_SYSTEM ? UNIT_FILE_SYSTEM : UNIT_FILE_USER;
1508 UnitFileChange *changes = NULL;
1509 unsigned n_changes = 0;
1510 dbus_bool_t runtime, force;
1511 int carries_install_info = -1;
1513 SELINUX_ACCESS_CHECK(connection, message, streq(member, "MaskUnitFiles") ? "disable" : "enable");
1515 if (!dbus_message_iter_init(message, &iter))
1518 r = bus_parse_strv_iter(&iter, &l);
1523 return bus_send_error_reply(connection, message, NULL, r);
1526 if (!dbus_message_iter_next(&iter) ||
1527 bus_iter_get_basic_and_next(&iter, DBUS_TYPE_BOOLEAN, &runtime, true) < 0 ||
1528 bus_iter_get_basic_and_next(&iter, DBUS_TYPE_BOOLEAN, &force, false) < 0) {
1530 return bus_send_error_reply(connection, message, NULL, -EIO);
1533 if (streq(member, "EnableUnitFiles")) {
1534 r = unit_file_enable(scope, runtime, NULL, l, force, &changes, &n_changes);
1535 carries_install_info = r;
1536 } else if (streq(member, "ReenableUnitFiles")) {
1537 r = unit_file_reenable(scope, runtime, NULL, l, force, &changes, &n_changes);
1538 carries_install_info = r;
1539 } else if (streq(member, "LinkUnitFiles"))
1540 r = unit_file_link(scope, runtime, NULL, l, force, &changes, &n_changes);
1541 else if (streq(member, "PresetUnitFiles")) {
1542 r = unit_file_preset(scope, runtime, NULL, l, force, &changes, &n_changes);
1543 carries_install_info = r;
1544 } else if (streq(member, "MaskUnitFiles"))
1545 r = unit_file_mask(scope, runtime, NULL, l, force, &changes, &n_changes);
1547 assert_not_reached("Uh? Wrong method");
1550 bus_manager_send_unit_files_changed(m);
1553 unit_file_changes_free(changes, n_changes);
1554 return bus_send_error_reply(connection, message, NULL, r);
1557 reply = message_from_file_changes(message, changes, n_changes, carries_install_info);
1558 unit_file_changes_free(changes, n_changes);
1563 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "DisableUnitFiles") ||
1564 dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "UnmaskUnitFiles")) {
1567 DBusMessageIter iter;
1568 UnitFileScope scope = m->running_as == SYSTEMD_SYSTEM ? UNIT_FILE_SYSTEM : UNIT_FILE_USER;
1569 UnitFileChange *changes = NULL;
1570 unsigned n_changes = 0;
1571 dbus_bool_t runtime;
1573 SELINUX_ACCESS_CHECK(connection, message, streq(member, "UnmaskUnitFiles") ? "enable" : "disable");
1575 if (!dbus_message_iter_init(message, &iter))
1578 r = bus_parse_strv_iter(&iter, &l);
1583 return bus_send_error_reply(connection, message, NULL, r);
1586 if (!dbus_message_iter_next(&iter) ||
1587 bus_iter_get_basic_and_next(&iter, DBUS_TYPE_BOOLEAN, &runtime, false) < 0) {
1589 return bus_send_error_reply(connection, message, NULL, -EIO);
1592 if (streq(member, "DisableUnitFiles"))
1593 r = unit_file_disable(scope, runtime, NULL, l, &changes, &n_changes);
1594 else if (streq(member, "UnmaskUnitFiles"))
1595 r = unit_file_unmask(scope, runtime, NULL, l, &changes, &n_changes);
1597 assert_not_reached("Uh? Wrong method");
1600 bus_manager_send_unit_files_changed(m);
1603 unit_file_changes_free(changes, n_changes);
1604 return bus_send_error_reply(connection, message, NULL, r);
1607 reply = message_from_file_changes(message, changes, n_changes, -1);
1608 unit_file_changes_free(changes, n_changes);
1614 const BusBoundProperties bps[] = {
1615 { "org.freedesktop.systemd1.Manager", bus_systemd_properties, systemd_property_string },
1616 { "org.freedesktop.systemd1.Manager", bus_manager_properties, m },
1620 SELINUX_ACCESS_CHECK(connection, message, "status");
1622 return bus_default_message_handler(connection, message, NULL, INTERFACES_LIST, bps);
1625 if (job_type != _JOB_TYPE_INVALID) {
1626 const char *name, *smode, *old_name = NULL;
1631 if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "StartUnitReplace"))
1632 b = dbus_message_get_args(
1635 DBUS_TYPE_STRING, &old_name,
1636 DBUS_TYPE_STRING, &name,
1637 DBUS_TYPE_STRING, &smode,
1640 b = dbus_message_get_args(
1643 DBUS_TYPE_STRING, &name,
1644 DBUS_TYPE_STRING, &smode,
1647 return bus_send_error_reply(connection, message, &error, -EINVAL);
1650 u = manager_get_unit(m, old_name);
1651 if (!u || !u->job || u->job->type != JOB_START) {
1652 dbus_set_error(&error, BUS_ERROR_NO_SUCH_JOB, "No job queued for unit %s", old_name);
1653 return bus_send_error_reply(connection, message, &error, -ENOENT);
1657 mode = job_mode_from_string(smode);
1659 dbus_set_error(&error, BUS_ERROR_INVALID_JOB_MODE, "Job mode %s is invalid.", smode);
1660 return bus_send_error_reply(connection, message, &error, -EINVAL);
1663 r = manager_load_unit(m, name, NULL, &error, &u);
1665 return bus_send_error_reply(connection, message, &error, r);
1667 return bus_unit_queue_job(connection, message, u, job_type, mode, reload_if_possible);
1671 if (!dbus_connection_send(connection, reply, NULL))
1674 return DBUS_HANDLER_RESULT_HANDLED;
1677 dbus_error_free(&error);
1679 return DBUS_HANDLER_RESULT_NEED_MEMORY;
1682 const DBusObjectPathVTable bus_manager_vtable = {
1683 .message_function = bus_manager_message_handler