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=\"Distribution\" type=\"s\" access=\"read\"/>\n" \
232 " <property name=\"Features\" type=\"s\" access=\"read\"/>\n" \
233 " <property name=\"Tainted\" type=\"s\" access=\"read\"/>\n" \
234 " <property name=\"FirmwareTimestamp\" type=\"t\" access=\"read\"/>\n" \
235 " <property name=\"FirmwareTimestampMonotonic\" type=\"t\" access=\"read\"/>\n" \
236 " <property name=\"LoaderTimestamp\" type=\"t\" access=\"read\"/>\n" \
237 " <property name=\"LoaderTimestampMonotonic\" type=\"t\" access=\"read\"/>\n" \
238 " <property name=\"KernelTimestamp\" type=\"t\" access=\"read\"/>\n" \
239 " <property name=\"KernelTimestampMonotonic\" type=\"t\" access=\"read\"/>\n" \
240 " <property name=\"InitRDTimestamp\" type=\"t\" access=\"read\"/>\n" \
241 " <property name=\"InitRDTimestampMonotonic\" type=\"t\" access=\"read\"/>\n" \
242 " <property name=\"UserspaceTimestamp\" type=\"t\" access=\"read\"/>\n" \
243 " <property name=\"UserspaceTimestampMonotonic\" type=\"t\" access=\"read\"/>\n" \
244 " <property name=\"FinishTimestamp\" type=\"t\" access=\"read\"/>\n" \
245 " <property name=\"FinishTimestampMonotonic\" type=\"t\" access=\"read\"/>\n" \
246 " <property name=\"LogLevel\" type=\"s\" access=\"readwrite\"/>\n" \
247 " <property name=\"LogTarget\" type=\"s\" access=\"readwrite\"/>\n" \
248 " <property name=\"NNames\" type=\"u\" access=\"read\"/>\n" \
249 " <property name=\"NJobs\" type=\"u\" access=\"read\"/>\n" \
250 " <property name=\"NInstalledJobs\" type=\"u\" access=\"read\"/>\n" \
251 " <property name=\"NFailedJobs\" type=\"u\" access=\"read\"/>\n" \
252 " <property name=\"Progress\" type=\"d\" access=\"read\"/>\n" \
253 " <property name=\"Environment\" type=\"as\" access=\"read\"/>\n" \
254 " <property name=\"ConfirmSpawn\" type=\"b\" access=\"read\"/>\n" \
255 " <property name=\"ShowStatus\" type=\"b\" access=\"read\"/>\n" \
256 " <property name=\"UnitPath\" type=\"as\" access=\"read\"/>\n" \
257 " <property name=\"ControlGroupHierarchy\" type=\"s\" access=\"read\"/>\n" \
258 " <property name=\"DefaultControllers\" type=\"as\" access=\"read\"/>\n" \
259 " <property name=\"DefaultStandardOutput\" type=\"s\" access=\"read\"/>\n" \
260 " <property name=\"DefaultStandardError\" type=\"s\" access=\"read\"/>\n" \
261 " <property name=\"RuntimeWatchdogUSec\" type=\"s\" access=\"readwrite\"/>\n" \
262 " <property name=\"ShutdownWatchdogUSec\" type=\"s\" access=\"readwrite\"/>\n" \
263 " <property name=\"Virtualization\" type=\"s\" access=\"read\"/>\n"
265 #define BUS_MANAGER_INTERFACE_END \
268 #define BUS_MANAGER_INTERFACE \
269 BUS_MANAGER_INTERFACE_BEGIN \
270 BUS_MANAGER_INTERFACE_METHODS \
271 BUS_MANAGER_INTERFACE_SIGNALS \
272 BUS_MANAGER_INTERFACE_PROPERTIES_GENERAL \
273 BUS_MANAGER_INTERFACE_END
275 #define INTROSPECTION_BEGIN \
276 DBUS_INTROSPECT_1_0_XML_DOCTYPE_DECL_NODE \
278 BUS_MANAGER_INTERFACE \
279 BUS_PROPERTIES_INTERFACE \
281 BUS_INTROSPECTABLE_INTERFACE
283 #define INTROSPECTION_END \
286 #define INTERFACES_LIST \
287 BUS_GENERIC_INTERFACES_LIST \
288 "org.freedesktop.systemd1.Manager\0"
290 const char bus_manager_interface[] _introspect_("Manager") = BUS_MANAGER_INTERFACE;
292 static DEFINE_BUS_PROPERTY_APPEND_ENUM(bus_manager_append_exec_output, exec_output, ExecOutput);
294 static int bus_manager_append_tainted(DBusMessageIter *i, const char *property, void *data) {
297 char buf[LINE_MAX] = "", *e = buf, *p = NULL;
304 e = stpcpy(e, "split-usr:");
306 if (readlink_malloc("/etc/mtab", &p) < 0)
307 e = stpcpy(e, "mtab-not-symlink:");
311 if (access("/proc/cgroups", F_OK) < 0)
312 e = stpcpy(e, "cgroups-missing:");
314 if (hwclock_is_localtime() > 0)
315 e = stpcpy(e, "local-hwclock:");
317 /* remove the last ':' */
323 if (!dbus_message_iter_append_basic(i, DBUS_TYPE_STRING, &t))
329 static int bus_manager_append_log_target(DBusMessageIter *i, const char *property, void *data) {
335 t = log_target_to_string(log_get_target());
337 if (!dbus_message_iter_append_basic(i, DBUS_TYPE_STRING, &t))
343 static int bus_manager_set_log_target(DBusMessageIter *i, const char *property, void *data) {
349 dbus_message_iter_get_basic(i, &t);
351 return log_set_target_from_string(t);
354 static int bus_manager_append_log_level(DBusMessageIter *i, const char *property, void *data) {
360 t = log_level_to_string(log_get_max_level());
362 if (!dbus_message_iter_append_basic(i, DBUS_TYPE_STRING, &t))
368 static int bus_manager_set_log_level(DBusMessageIter *i, const char *property, void *data) {
374 dbus_message_iter_get_basic(i, &t);
376 return log_set_max_level_from_string(t);
379 static int bus_manager_append_n_names(DBusMessageIter *i, const char *property, void *data) {
387 u = hashmap_size(m->units);
389 if (!dbus_message_iter_append_basic(i, DBUS_TYPE_UINT32, &u))
395 static int bus_manager_append_n_jobs(DBusMessageIter *i, const char *property, void *data) {
403 u = hashmap_size(m->jobs);
405 if (!dbus_message_iter_append_basic(i, DBUS_TYPE_UINT32, &u))
411 static int bus_manager_append_progress(DBusMessageIter *i, const char *property, void *data) {
419 if (dual_timestamp_is_set(&m->finish_timestamp))
422 d = 1.0 - ((double) hashmap_size(m->jobs) / (double) m->n_installed_jobs);
424 if (!dbus_message_iter_append_basic(i, DBUS_TYPE_DOUBLE, &d))
430 static int bus_manager_append_virt(DBusMessageIter *i, const char *property, void *data) {
438 detect_virtualization(&id);
440 if (!dbus_message_iter_append_basic(i, DBUS_TYPE_STRING, &id))
446 static DBusMessage *message_from_file_changes(
448 UnitFileChange *changes,
450 int carries_install_info) {
452 DBusMessageIter iter, sub, sub2;
456 reply = dbus_message_new_method_return(m);
460 dbus_message_iter_init_append(reply, &iter);
462 if (carries_install_info >= 0) {
465 b = !!carries_install_info;
466 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &b))
470 if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "(sss)", &sub))
473 for (i = 0; i < n_changes; i++) {
474 const char *type, *path, *source;
476 type = unit_file_change_type_to_string(changes[i].type);
477 path = strempty(changes[i].path);
478 source = strempty(changes[i].source);
480 if (!dbus_message_iter_open_container(&sub, DBUS_TYPE_STRUCT, NULL, &sub2) ||
481 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &type) ||
482 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &path) ||
483 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &source) ||
484 !dbus_message_iter_close_container(&sub, &sub2))
488 if (!dbus_message_iter_close_container(&iter, &sub))
494 dbus_message_unref(reply);
498 static int bus_manager_send_unit_files_changed(Manager *m) {
502 s = dbus_message_new_signal("/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", "UnitFilesChanged");
506 r = bus_broadcast(m, s);
507 dbus_message_unref(s);
512 static int bus_manager_set_runtime_watchdog_usec(DBusMessageIter *i, const char *property, void *data) {
518 dbus_message_iter_get_basic(i, t);
520 return watchdog_set_timeout(t);
523 static const char systemd_property_string[] =
528 static const BusProperty bus_systemd_properties[] = {
529 { "Version", bus_property_append_string, "s", 0 },
530 { "Distribution", bus_property_append_string, "s", sizeof(PACKAGE_STRING) },
531 { "Features", bus_property_append_string, "s", sizeof(PACKAGE_STRING) + sizeof(DISTRIBUTION) },
535 static const BusProperty bus_manager_properties[] = {
536 { "Tainted", bus_manager_append_tainted, "s", 0 },
537 { "FirmwareTimestamp", bus_property_append_uint64, "t", offsetof(Manager, firmware_timestamp.realtime) },
538 { "FirmwareTimestampMonotonic", bus_property_append_uint64, "t", offsetof(Manager, firmware_timestamp.monotonic) },
539 { "LoaderTimestamp", bus_property_append_uint64, "t", offsetof(Manager, loader_timestamp.realtime) },
540 { "LoaderTimestampMonotonic", bus_property_append_uint64, "t", offsetof(Manager, loader_timestamp.monotonic) },
541 { "KernelTimestamp", bus_property_append_uint64, "t", offsetof(Manager, kernel_timestamp.realtime) },
542 { "KernelTimestampMonotonic", bus_property_append_uint64, "t", offsetof(Manager, kernel_timestamp.monotonic) },
543 { "InitRDTimestamp", bus_property_append_uint64, "t", offsetof(Manager, initrd_timestamp.realtime) },
544 { "InitRDTimestampMonotonic", bus_property_append_uint64, "t", offsetof(Manager, initrd_timestamp.monotonic) },
545 { "UserspaceTimestamp", bus_property_append_uint64, "t", offsetof(Manager, userspace_timestamp.realtime) },
546 { "UserspaceTimestampMonotonic", bus_property_append_uint64, "t", offsetof(Manager, userspace_timestamp.monotonic) },
547 { "FinishTimestamp", bus_property_append_uint64, "t", offsetof(Manager, finish_timestamp.realtime) },
548 { "FinishTimestampMonotonic", bus_property_append_uint64, "t", offsetof(Manager, finish_timestamp.monotonic) },
549 { "LogLevel", bus_manager_append_log_level, "s", 0, false, bus_manager_set_log_level },
550 { "LogTarget", bus_manager_append_log_target, "s", 0, false, bus_manager_set_log_target },
551 { "NNames", bus_manager_append_n_names, "u", 0 },
552 { "NJobs", bus_manager_append_n_jobs, "u", 0 },
553 { "NInstalledJobs", bus_property_append_uint32, "u", offsetof(Manager, n_installed_jobs) },
554 { "NFailedJobs", bus_property_append_uint32, "u", offsetof(Manager, n_failed_jobs) },
555 { "Progress", bus_manager_append_progress, "d", 0 },
556 { "Environment", bus_property_append_strv, "as", offsetof(Manager, environment), true },
557 { "ConfirmSpawn", bus_property_append_bool, "b", offsetof(Manager, confirm_spawn) },
558 { "ShowStatus", bus_property_append_bool, "b", offsetof(Manager, show_status) },
559 { "UnitPath", bus_property_append_strv, "as", offsetof(Manager, lookup_paths.unit_path), true },
560 { "ControlGroupHierarchy", bus_property_append_string, "s", offsetof(Manager, cgroup_hierarchy), true },
561 { "DefaultControllers", bus_property_append_strv, "as", offsetof(Manager, default_controllers), true },
562 { "DefaultStandardOutput", bus_manager_append_exec_output, "s", offsetof(Manager, default_std_output) },
563 { "DefaultStandardError", bus_manager_append_exec_output, "s", offsetof(Manager, default_std_error) },
564 { "RuntimeWatchdogUSec", bus_property_append_usec, "t", offsetof(Manager, runtime_watchdog), false, bus_manager_set_runtime_watchdog_usec },
565 { "ShutdownWatchdogUSec", bus_property_append_usec, "t", offsetof(Manager, shutdown_watchdog), false, bus_property_set_usec },
566 { "Virtualization", bus_manager_append_virt, "s", 0, },
570 static DBusHandlerResult bus_manager_message_handler(DBusConnection *connection, DBusMessage *message, void *data) {
571 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
572 _cleanup_free_ char * path = NULL;
576 JobType job_type = _JOB_TYPE_INVALID;
577 bool reload_if_possible = false;
584 dbus_error_init(&error);
586 member = dbus_message_get_member(message);
588 if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "GetUnit")) {
592 if (!dbus_message_get_args(
595 DBUS_TYPE_STRING, &name,
597 return bus_send_error_reply(connection, message, &error, -EINVAL);
599 u = manager_get_unit(m, name);
601 dbus_set_error(&error, BUS_ERROR_NO_SUCH_UNIT, "Unit %s is not loaded.", name);
602 return bus_send_error_reply(connection, message, &error, -ENOENT);
605 SELINUX_UNIT_ACCESS_CHECK(u, connection, message, "status");
607 reply = dbus_message_new_method_return(message);
611 path = unit_dbus_path(u);
615 if (!dbus_message_append_args(
617 DBUS_TYPE_OBJECT_PATH, &path,
620 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "GetUnitByPID")) {
624 if (!dbus_message_get_args(
627 DBUS_TYPE_UINT32, &pid,
629 return bus_send_error_reply(connection, message, &error, -EINVAL);
631 u = cgroup_unit_by_pid(m, (pid_t) pid);
633 dbus_set_error(&error, BUS_ERROR_NO_SUCH_UNIT, "No unit for PID %lu is loaded.", (unsigned long) pid);
634 return bus_send_error_reply(connection, message, &error, -ENOENT);
637 SELINUX_UNIT_ACCESS_CHECK(u, connection, message, "status");
639 reply = dbus_message_new_method_return(message);
643 path = unit_dbus_path(u);
647 if (!dbus_message_append_args(
649 DBUS_TYPE_OBJECT_PATH, &path,
652 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "LoadUnit")) {
656 if (!dbus_message_get_args(
659 DBUS_TYPE_STRING, &name,
661 return bus_send_error_reply(connection, message, &error, -EINVAL);
663 r = manager_load_unit(m, name, NULL, &error, &u);
665 return bus_send_error_reply(connection, message, &error, r);
667 SELINUX_UNIT_ACCESS_CHECK(u, connection, message, "status");
669 reply = dbus_message_new_method_return(message);
673 path = unit_dbus_path(u);
677 if (!dbus_message_append_args(
679 DBUS_TYPE_OBJECT_PATH, &path,
683 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "StartUnit"))
684 job_type = JOB_START;
685 else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "StartUnitReplace"))
686 job_type = JOB_START;
687 else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "StopUnit"))
689 else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ReloadUnit"))
690 job_type = JOB_RELOAD;
691 else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "RestartUnit"))
692 job_type = JOB_RESTART;
693 else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "TryRestartUnit"))
694 job_type = JOB_TRY_RESTART;
695 else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ReloadOrRestartUnit")) {
696 reload_if_possible = true;
697 job_type = JOB_RESTART;
698 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ReloadOrTryRestartUnit")) {
699 reload_if_possible = true;
700 job_type = JOB_TRY_RESTART;
701 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "KillUnit")) {
702 const char *name, *swho;
707 if (!dbus_message_get_args(
710 DBUS_TYPE_STRING, &name,
711 DBUS_TYPE_STRING, &swho,
712 DBUS_TYPE_INT32, &signo,
714 return bus_send_error_reply(connection, message, &error, -EINVAL);
719 who = kill_who_from_string(swho);
721 return bus_send_error_reply(connection, message, &error, -EINVAL);
724 if (signo <= 0 || signo >= _NSIG)
725 return bus_send_error_reply(connection, message, &error, -EINVAL);
727 u = manager_get_unit(m, name);
729 dbus_set_error(&error, BUS_ERROR_NO_SUCH_UNIT, "Unit %s is not loaded.", name);
730 return bus_send_error_reply(connection, message, &error, -ENOENT);
733 SELINUX_UNIT_ACCESS_CHECK(u, connection, message, "stop");
735 r = unit_kill(u, who, signo, &error);
737 return bus_send_error_reply(connection, message, &error, r);
739 if (!(reply = dbus_message_new_method_return(message)))
742 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "GetJob")) {
746 if (!dbus_message_get_args(
749 DBUS_TYPE_UINT32, &id,
751 return bus_send_error_reply(connection, message, &error, -EINVAL);
753 j = manager_get_job(m, id);
755 dbus_set_error(&error, BUS_ERROR_NO_SUCH_JOB, "Job %u does not exist.", (unsigned) id);
756 return bus_send_error_reply(connection, message, &error, -ENOENT);
759 SELINUX_UNIT_ACCESS_CHECK(j->unit, connection, message, "status");
761 reply = dbus_message_new_method_return(message);
765 path = job_dbus_path(j);
769 if (!dbus_message_append_args(
771 DBUS_TYPE_OBJECT_PATH, &path,
775 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ClearJobs")) {
777 SELINUX_ACCESS_CHECK(connection, message, "reboot");
779 manager_clear_jobs(m);
781 reply = dbus_message_new_method_return(message);
785 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ResetFailed")) {
787 SELINUX_ACCESS_CHECK(connection, message, "reload");
789 manager_reset_failed(m);
791 reply = dbus_message_new_method_return(message);
795 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ResetFailedUnit")) {
799 if (!dbus_message_get_args(
802 DBUS_TYPE_STRING, &name,
804 return bus_send_error_reply(connection, message, &error, -EINVAL);
806 u = manager_get_unit(m, name);
808 dbus_set_error(&error, BUS_ERROR_NO_SUCH_UNIT, "Unit %s is not loaded.", name);
809 return bus_send_error_reply(connection, message, &error, -ENOENT);
812 SELINUX_UNIT_ACCESS_CHECK(u, connection, message, "reload");
814 unit_reset_failed(u);
816 reply = dbus_message_new_method_return(message);
820 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ListUnits")) {
821 DBusMessageIter iter, sub;
826 SELINUX_ACCESS_CHECK(connection, message, "status");
828 reply = dbus_message_new_method_return(message);
832 dbus_message_iter_init_append(reply, &iter);
834 if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "(ssssssouso)", &sub))
837 HASHMAP_FOREACH_KEY(u, k, m->units, i) {
838 char *u_path, *j_path;
839 const char *description, *load_state, *active_state, *sub_state, *sjob_type, *following;
840 DBusMessageIter sub2;
847 if (!dbus_message_iter_open_container(&sub, DBUS_TYPE_STRUCT, NULL, &sub2))
850 description = unit_description(u);
851 load_state = unit_load_state_to_string(u->load_state);
852 active_state = unit_active_state_to_string(unit_active_state(u));
853 sub_state = unit_sub_state_to_string(u);
855 f = unit_following(u);
856 following = f ? f->id : "";
858 u_path = unit_dbus_path(u);
863 job_id = (uint32_t) u->job->id;
865 if (!(j_path = job_dbus_path(u->job))) {
870 sjob_type = job_type_to_string(u->job->type);
877 if (!dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &u->id) ||
878 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &description) ||
879 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &load_state) ||
880 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &active_state) ||
881 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &sub_state) ||
882 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &following) ||
883 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_OBJECT_PATH, &u_path) ||
884 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_UINT32, &job_id) ||
885 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &sjob_type) ||
886 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_OBJECT_PATH, &j_path)) {
897 if (!dbus_message_iter_close_container(&sub, &sub2))
901 if (!dbus_message_iter_close_container(&iter, &sub))
904 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ListJobs")) {
905 DBusMessageIter iter, sub;
909 SELINUX_ACCESS_CHECK(connection, message, "status");
911 reply = dbus_message_new_method_return(message);
915 dbus_message_iter_init_append(reply, &iter);
917 if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "(usssoo)", &sub))
920 HASHMAP_FOREACH(j, m->jobs, i) {
921 char *u_path, *j_path;
922 const char *state, *type;
924 DBusMessageIter sub2;
926 if (!dbus_message_iter_open_container(&sub, DBUS_TYPE_STRUCT, NULL, &sub2))
929 id = (uint32_t) j->id;
930 state = job_state_to_string(j->state);
931 type = job_type_to_string(j->type);
933 j_path = job_dbus_path(j);
937 u_path = unit_dbus_path(j->unit);
943 if (!dbus_message_iter_append_basic(&sub2, DBUS_TYPE_UINT32, &id) ||
944 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &j->unit->id) ||
945 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &type) ||
946 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &state) ||
947 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_OBJECT_PATH, &j_path) ||
948 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_OBJECT_PATH, &u_path)) {
957 if (!dbus_message_iter_close_container(&sub, &sub2))
961 if (!dbus_message_iter_close_container(&iter, &sub))
964 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "Subscribe")) {
968 SELINUX_ACCESS_CHECK(connection, message, "status");
970 s = BUS_CONNECTION_SUBSCRIBED(m, connection);
972 s = set_new(string_hash_func, string_compare_func);
976 if (!dbus_connection_set_data(connection, m->subscribed_data_slot, s, NULL)) {
982 client = strdup(bus_message_get_sender_with_fallback(message));
986 r = set_put(s, client);
989 return bus_send_error_reply(connection, message, NULL, r);
992 reply = dbus_message_new_method_return(message);
996 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "Unsubscribe")) {
999 SELINUX_ACCESS_CHECK(connection, message, "status");
1001 client = set_remove(BUS_CONNECTION_SUBSCRIBED(m, connection), (char*) bus_message_get_sender_with_fallback(message));
1003 dbus_set_error(&error, BUS_ERROR_NOT_SUBSCRIBED, "Client is not subscribed.");
1004 return bus_send_error_reply(connection, message, &error, -ENOENT);
1009 reply = dbus_message_new_method_return(message);
1013 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "Dump")) {
1018 SELINUX_ACCESS_CHECK(connection, message, "status");
1020 reply = dbus_message_new_method_return(message);
1024 f = open_memstream(&dump, &size);
1028 manager_dump_units(m, f, NULL);
1029 manager_dump_jobs(m, f, NULL);
1039 if (!dbus_message_append_args(reply, DBUS_TYPE_STRING, &dump, DBUS_TYPE_INVALID)) {
1045 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "CreateSnapshot")) {
1047 dbus_bool_t cleanup;
1050 SELINUX_ACCESS_CHECK(connection, message, "start");
1052 if (!dbus_message_get_args(
1055 DBUS_TYPE_STRING, &name,
1056 DBUS_TYPE_BOOLEAN, &cleanup,
1058 return bus_send_error_reply(connection, message, &error, -EINVAL);
1063 r = snapshot_create(m, name, cleanup, &error, &s);
1065 return bus_send_error_reply(connection, message, &error, r);
1067 reply = dbus_message_new_method_return(message);
1071 path = unit_dbus_path(UNIT(s));
1075 if (!dbus_message_append_args(
1077 DBUS_TYPE_OBJECT_PATH, &path,
1081 } else if (dbus_message_is_method_call(message, "org.freedesktop.DBus.Introspectable", "Introspect")) {
1082 char *introspection = NULL;
1090 SELINUX_ACCESS_CHECK(connection, message, "status");
1092 reply = dbus_message_new_method_return(message);
1096 /* We roll our own introspection code here, instead of
1097 * relying on bus_default_message_handler() because we
1098 * need to generate our introspection string
1101 f = open_memstream(&introspection, &size);
1105 fputs(INTROSPECTION_BEGIN, f);
1107 HASHMAP_FOREACH_KEY(u, k, m->units, i) {
1113 p = bus_path_escape(k);
1116 free(introspection);
1120 fprintf(f, "<node name=\"unit/%s\"/>", p);
1124 HASHMAP_FOREACH(j, m->jobs, i)
1125 fprintf(f, "<node name=\"job/%lu\"/>", (unsigned long) j->id);
1127 fputs(INTROSPECTION_END, f);
1131 free(introspection);
1140 if (!dbus_message_append_args(reply, DBUS_TYPE_STRING, &introspection, DBUS_TYPE_INVALID)) {
1141 free(introspection);
1145 free(introspection);
1147 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "Reload")) {
1149 SELINUX_ACCESS_CHECK(connection, message, "reload");
1151 assert(!m->queued_message);
1153 /* Instead of sending the reply back right away, we
1154 * just remember that we need to and then send it
1155 * after the reload is finished. That way the caller
1156 * knows when the reload finished. */
1158 m->queued_message = dbus_message_new_method_return(message);
1159 if (!m->queued_message)
1162 m->queued_message_connection = connection;
1163 m->exit_code = MANAGER_RELOAD;
1165 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "Reexecute")) {
1167 SELINUX_ACCESS_CHECK(connection, message, "reload");
1169 /* We don't send a reply back here, the client should
1170 * just wait for us disconnecting. */
1172 m->exit_code = MANAGER_REEXECUTE;
1174 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "Exit")) {
1176 SELINUX_ACCESS_CHECK(connection, message, "halt");
1178 if (m->running_as == SYSTEMD_SYSTEM) {
1179 dbus_set_error(&error, BUS_ERROR_NOT_SUPPORTED, "Exit is only supported for user service managers.");
1180 return bus_send_error_reply(connection, message, &error, -ENOTSUP);
1183 reply = dbus_message_new_method_return(message);
1187 m->exit_code = MANAGER_EXIT;
1189 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "Reboot")) {
1191 SELINUX_ACCESS_CHECK(connection, message, "reboot");
1193 if (m->running_as != SYSTEMD_SYSTEM) {
1194 dbus_set_error(&error, BUS_ERROR_NOT_SUPPORTED, "Reboot is only supported for system managers.");
1195 return bus_send_error_reply(connection, message, &error, -ENOTSUP);
1198 reply = dbus_message_new_method_return(message);
1202 m->exit_code = MANAGER_REBOOT;
1204 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "PowerOff")) {
1206 SELINUX_ACCESS_CHECK(connection, message, "halt");
1208 if (m->running_as != SYSTEMD_SYSTEM) {
1209 dbus_set_error(&error, BUS_ERROR_NOT_SUPPORTED, "Powering off is only supported for system managers.");
1210 return bus_send_error_reply(connection, message, &error, -ENOTSUP);
1213 reply = dbus_message_new_method_return(message);
1217 m->exit_code = MANAGER_POWEROFF;
1219 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "Halt")) {
1221 SELINUX_ACCESS_CHECK(connection, message, "halt");
1223 if (m->running_as != SYSTEMD_SYSTEM) {
1224 dbus_set_error(&error, BUS_ERROR_NOT_SUPPORTED, "Halting is only supported for system managers.");
1225 return bus_send_error_reply(connection, message, &error, -ENOTSUP);
1228 reply = dbus_message_new_method_return(message);
1232 m->exit_code = MANAGER_HALT;
1234 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "KExec")) {
1236 SELINUX_ACCESS_CHECK(connection, message, "reboot");
1238 if (m->running_as != SYSTEMD_SYSTEM) {
1239 dbus_set_error(&error, BUS_ERROR_NOT_SUPPORTED, "kexec is only supported for system managers.");
1240 return bus_send_error_reply(connection, message, &error, -ENOTSUP);
1243 reply = dbus_message_new_method_return(message);
1247 m->exit_code = MANAGER_KEXEC;
1249 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "SwitchRoot")) {
1250 const char *switch_root, *switch_root_init;
1254 SELINUX_ACCESS_CHECK(connection, message, "reboot");
1256 if (!dbus_message_get_args(
1259 DBUS_TYPE_STRING, &switch_root,
1260 DBUS_TYPE_STRING, &switch_root_init,
1262 return bus_send_error_reply(connection, message, &error, -EINVAL);
1264 if (path_equal(switch_root, "/") || !path_is_absolute(switch_root))
1265 return bus_send_error_reply(connection, message, NULL, -EINVAL);
1267 if (!isempty(switch_root_init) && !path_is_absolute(switch_root_init))
1268 return bus_send_error_reply(connection, message, NULL, -EINVAL);
1270 if (m->running_as != SYSTEMD_SYSTEM) {
1271 dbus_set_error(&error, BUS_ERROR_NOT_SUPPORTED, "Switching root is only supported for system managers.");
1272 return bus_send_error_reply(connection, message, &error, -ENOTSUP);
1276 if (isempty(switch_root_init))
1277 k = access(switch_root, F_OK);
1281 p = strjoin(switch_root, "/", switch_root_init, NULL);
1285 k = access(p, X_OK);
1289 return bus_send_error_reply(connection, message, NULL, -errno);
1291 u = strdup(switch_root);
1295 if (!isempty(switch_root_init)) {
1296 v = strdup(switch_root_init);
1304 free(m->switch_root);
1305 free(m->switch_root_init);
1307 m->switch_root_init = v;
1309 reply = dbus_message_new_method_return(message);
1313 m->exit_code = MANAGER_SWITCH_ROOT;
1315 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "SetEnvironment")) {
1316 char **l = NULL, **e = NULL;
1318 SELINUX_ACCESS_CHECK(connection, message, "reboot");
1320 r = bus_parse_strv(message, &l);
1324 return bus_send_error_reply(connection, message, NULL, r);
1326 e = strv_env_merge(2, m->environment, l);
1331 reply = dbus_message_new_method_return(message);
1337 strv_free(m->environment);
1340 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "UnsetEnvironment")) {
1341 char **l = NULL, **e = NULL;
1343 SELINUX_ACCESS_CHECK(connection, message, "reboot");
1345 r = bus_parse_strv(message, &l);
1349 return bus_send_error_reply(connection, message, NULL, r);
1351 e = strv_env_delete(m->environment, 1, l);
1357 if (!(reply = dbus_message_new_method_return(message))) {
1362 strv_free(m->environment);
1365 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "UnsetAndSetEnvironment")) {
1366 char **l_set = NULL, **l_unset = NULL, **e = NULL, **f = NULL;
1367 DBusMessageIter iter;
1369 SELINUX_ACCESS_CHECK(connection, message, "reboot");
1371 if (!dbus_message_iter_init(message, &iter))
1374 r = bus_parse_strv_iter(&iter, &l_unset);
1378 return bus_send_error_reply(connection, message, NULL, r);
1380 if (!dbus_message_iter_next(&iter)) {
1382 return bus_send_error_reply(connection, message, NULL, -EINVAL);
1385 r = bus_parse_strv_iter(&iter, &l_set);
1391 return bus_send_error_reply(connection, message, NULL, r);
1394 e = strv_env_delete(m->environment, 1, l_unset);
1402 f = strv_env_merge(2, e, l_set);
1409 if (!(reply = dbus_message_new_method_return(message))) {
1414 strv_free(m->environment);
1416 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ListUnitFiles")) {
1417 DBusMessageIter iter, sub, sub2;
1422 SELINUX_ACCESS_CHECK(connection, message, "status");
1424 reply = dbus_message_new_method_return(message);
1428 h = hashmap_new(string_hash_func, string_compare_func);
1432 r = unit_file_get_list(m->running_as == SYSTEMD_SYSTEM ? UNIT_FILE_SYSTEM : UNIT_FILE_USER, NULL, h);
1434 unit_file_list_free(h);
1435 dbus_message_unref(reply);
1436 return bus_send_error_reply(connection, message, NULL, r);
1439 dbus_message_iter_init_append(reply, &iter);
1441 if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "(ss)", &sub)) {
1442 unit_file_list_free(h);
1446 HASHMAP_FOREACH(item, h, i) {
1449 state = unit_file_state_to_string(item->state);
1452 if (!dbus_message_iter_open_container(&sub, DBUS_TYPE_STRUCT, NULL, &sub2) ||
1453 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &item->path) ||
1454 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &state) ||
1455 !dbus_message_iter_close_container(&sub, &sub2)) {
1456 unit_file_list_free(h);
1461 unit_file_list_free(h);
1463 if (!dbus_message_iter_close_container(&iter, &sub))
1466 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "GetUnitFileState")) {
1468 UnitFileState state;
1471 SELINUX_ACCESS_CHECK(connection, message, "status");
1473 if (!dbus_message_get_args(
1476 DBUS_TYPE_STRING, &name,
1478 return bus_send_error_reply(connection, message, &error, -EINVAL);
1480 state = unit_file_get_state(m->running_as == SYSTEMD_SYSTEM ? UNIT_FILE_SYSTEM : UNIT_FILE_USER, NULL, name);
1482 return bus_send_error_reply(connection, message, NULL, state);
1484 s = unit_file_state_to_string(state);
1487 reply = dbus_message_new_method_return(message);
1491 if (!dbus_message_append_args(
1493 DBUS_TYPE_STRING, &s,
1496 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "EnableUnitFiles") ||
1497 dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ReenableUnitFiles") ||
1498 dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "LinkUnitFiles") ||
1499 dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "PresetUnitFiles") ||
1500 dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "MaskUnitFiles")) {
1503 DBusMessageIter iter;
1504 UnitFileScope scope = m->running_as == SYSTEMD_SYSTEM ? UNIT_FILE_SYSTEM : UNIT_FILE_USER;
1505 UnitFileChange *changes = NULL;
1506 unsigned n_changes = 0;
1507 dbus_bool_t runtime, force;
1508 int carries_install_info = -1;
1510 SELINUX_ACCESS_CHECK(connection, message, streq(member, "MaskUnitFiles") ? "disable" : "enable");
1512 if (!dbus_message_iter_init(message, &iter))
1515 r = bus_parse_strv_iter(&iter, &l);
1520 return bus_send_error_reply(connection, message, NULL, r);
1523 if (!dbus_message_iter_next(&iter) ||
1524 bus_iter_get_basic_and_next(&iter, DBUS_TYPE_BOOLEAN, &runtime, true) < 0 ||
1525 bus_iter_get_basic_and_next(&iter, DBUS_TYPE_BOOLEAN, &force, false) < 0) {
1527 return bus_send_error_reply(connection, message, NULL, -EIO);
1530 if (streq(member, "EnableUnitFiles")) {
1531 r = unit_file_enable(scope, runtime, NULL, l, force, &changes, &n_changes);
1532 carries_install_info = r;
1533 } else if (streq(member, "ReenableUnitFiles")) {
1534 r = unit_file_reenable(scope, runtime, NULL, l, force, &changes, &n_changes);
1535 carries_install_info = r;
1536 } else if (streq(member, "LinkUnitFiles"))
1537 r = unit_file_link(scope, runtime, NULL, l, force, &changes, &n_changes);
1538 else if (streq(member, "PresetUnitFiles")) {
1539 r = unit_file_preset(scope, runtime, NULL, l, force, &changes, &n_changes);
1540 carries_install_info = r;
1541 } else if (streq(member, "MaskUnitFiles"))
1542 r = unit_file_mask(scope, runtime, NULL, l, force, &changes, &n_changes);
1544 assert_not_reached("Uh? Wrong method");
1547 bus_manager_send_unit_files_changed(m);
1550 unit_file_changes_free(changes, n_changes);
1551 return bus_send_error_reply(connection, message, NULL, r);
1554 reply = message_from_file_changes(message, changes, n_changes, carries_install_info);
1555 unit_file_changes_free(changes, n_changes);
1560 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "DisableUnitFiles") ||
1561 dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "UnmaskUnitFiles")) {
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;
1570 SELINUX_ACCESS_CHECK(connection, message, streq(member, "UnmaskUnitFiles") ? "enable" : "disable");
1572 if (!dbus_message_iter_init(message, &iter))
1575 r = bus_parse_strv_iter(&iter, &l);
1580 return bus_send_error_reply(connection, message, NULL, r);
1583 if (!dbus_message_iter_next(&iter) ||
1584 bus_iter_get_basic_and_next(&iter, DBUS_TYPE_BOOLEAN, &runtime, false) < 0) {
1586 return bus_send_error_reply(connection, message, NULL, -EIO);
1589 if (streq(member, "DisableUnitFiles"))
1590 r = unit_file_disable(scope, runtime, NULL, l, &changes, &n_changes);
1591 else if (streq(member, "UnmaskUnitFiles"))
1592 r = unit_file_unmask(scope, runtime, NULL, l, &changes, &n_changes);
1594 assert_not_reached("Uh? Wrong method");
1597 bus_manager_send_unit_files_changed(m);
1600 unit_file_changes_free(changes, n_changes);
1601 return bus_send_error_reply(connection, message, NULL, r);
1604 reply = message_from_file_changes(message, changes, n_changes, -1);
1605 unit_file_changes_free(changes, n_changes);
1611 const BusBoundProperties bps[] = {
1612 { "org.freedesktop.systemd1.Manager", bus_systemd_properties, systemd_property_string },
1613 { "org.freedesktop.systemd1.Manager", bus_manager_properties, m },
1617 SELINUX_ACCESS_CHECK(connection, message, "status");
1619 return bus_default_message_handler(connection, message, NULL, INTERFACES_LIST, bps);
1622 if (job_type != _JOB_TYPE_INVALID) {
1623 const char *name, *smode, *old_name = NULL;
1628 if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "StartUnitReplace"))
1629 b = dbus_message_get_args(
1632 DBUS_TYPE_STRING, &old_name,
1633 DBUS_TYPE_STRING, &name,
1634 DBUS_TYPE_STRING, &smode,
1637 b = dbus_message_get_args(
1640 DBUS_TYPE_STRING, &name,
1641 DBUS_TYPE_STRING, &smode,
1644 return bus_send_error_reply(connection, message, &error, -EINVAL);
1647 u = manager_get_unit(m, old_name);
1648 if (!u || !u->job || u->job->type != JOB_START) {
1649 dbus_set_error(&error, BUS_ERROR_NO_SUCH_JOB, "No job queued for unit %s", old_name);
1650 return bus_send_error_reply(connection, message, &error, -ENOENT);
1654 mode = job_mode_from_string(smode);
1656 dbus_set_error(&error, BUS_ERROR_INVALID_JOB_MODE, "Job mode %s is invalid.", smode);
1657 return bus_send_error_reply(connection, message, &error, -EINVAL);
1660 r = manager_load_unit(m, name, NULL, &error, &u);
1662 return bus_send_error_reply(connection, message, &error, r);
1664 return bus_unit_queue_job(connection, message, u, job_type, mode, reload_if_possible);
1668 if (!dbus_connection_send(connection, reply, NULL))
1671 return DBUS_HANDLER_RESULT_HANDLED;
1674 dbus_error_free(&error);
1676 return DBUS_HANDLER_RESULT_NEED_MEMORY;
1679 const DBusObjectPathVTable bus_manager_vtable = {
1680 .message_function = bus_manager_message_handler