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) {
361 r = log_level_to_string_alloc(log_get_max_level(), &t);
365 if (!dbus_message_iter_append_basic(i, DBUS_TYPE_STRING, &t))
372 static int bus_manager_set_log_level(DBusMessageIter *i, const char *property, void *data) {
378 dbus_message_iter_get_basic(i, &t);
380 return log_set_max_level_from_string(t);
383 static int bus_manager_append_n_names(DBusMessageIter *i, const char *property, void *data) {
391 u = hashmap_size(m->units);
393 if (!dbus_message_iter_append_basic(i, DBUS_TYPE_UINT32, &u))
399 static int bus_manager_append_n_jobs(DBusMessageIter *i, const char *property, void *data) {
407 u = hashmap_size(m->jobs);
409 if (!dbus_message_iter_append_basic(i, DBUS_TYPE_UINT32, &u))
415 static int bus_manager_append_progress(DBusMessageIter *i, const char *property, void *data) {
423 if (dual_timestamp_is_set(&m->finish_timestamp))
426 d = 1.0 - ((double) hashmap_size(m->jobs) / (double) m->n_installed_jobs);
428 if (!dbus_message_iter_append_basic(i, DBUS_TYPE_DOUBLE, &d))
434 static int bus_manager_append_virt(DBusMessageIter *i, const char *property, void *data) {
442 detect_virtualization(&id);
444 if (!dbus_message_iter_append_basic(i, DBUS_TYPE_STRING, &id))
450 static DBusMessage *message_from_file_changes(
452 UnitFileChange *changes,
454 int carries_install_info) {
456 DBusMessageIter iter, sub, sub2;
460 reply = dbus_message_new_method_return(m);
464 dbus_message_iter_init_append(reply, &iter);
466 if (carries_install_info >= 0) {
469 b = !!carries_install_info;
470 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &b))
474 if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "(sss)", &sub))
477 for (i = 0; i < n_changes; i++) {
478 const char *type, *path, *source;
480 type = unit_file_change_type_to_string(changes[i].type);
481 path = strempty(changes[i].path);
482 source = strempty(changes[i].source);
484 if (!dbus_message_iter_open_container(&sub, DBUS_TYPE_STRUCT, NULL, &sub2) ||
485 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &type) ||
486 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &path) ||
487 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &source) ||
488 !dbus_message_iter_close_container(&sub, &sub2))
492 if (!dbus_message_iter_close_container(&iter, &sub))
498 dbus_message_unref(reply);
502 static int bus_manager_send_unit_files_changed(Manager *m) {
506 s = dbus_message_new_signal("/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", "UnitFilesChanged");
510 r = bus_broadcast(m, s);
511 dbus_message_unref(s);
516 static int bus_manager_set_runtime_watchdog_usec(DBusMessageIter *i, const char *property, void *data) {
522 dbus_message_iter_get_basic(i, t);
524 return watchdog_set_timeout(t);
527 static const char systemd_property_string[] =
532 static const BusProperty bus_systemd_properties[] = {
533 { "Version", bus_property_append_string, "s", 0 },
534 { "Distribution", bus_property_append_string, "s", sizeof(PACKAGE_STRING) },
535 { "Features", bus_property_append_string, "s", sizeof(PACKAGE_STRING) + sizeof(DISTRIBUTION) },
539 static const BusProperty bus_manager_properties[] = {
540 { "Tainted", bus_manager_append_tainted, "s", 0 },
541 { "FirmwareTimestamp", bus_property_append_uint64, "t", offsetof(Manager, firmware_timestamp.realtime) },
542 { "FirmwareTimestampMonotonic", bus_property_append_uint64, "t", offsetof(Manager, firmware_timestamp.monotonic) },
543 { "LoaderTimestamp", bus_property_append_uint64, "t", offsetof(Manager, loader_timestamp.realtime) },
544 { "LoaderTimestampMonotonic", bus_property_append_uint64, "t", offsetof(Manager, loader_timestamp.monotonic) },
545 { "KernelTimestamp", bus_property_append_uint64, "t", offsetof(Manager, kernel_timestamp.realtime) },
546 { "KernelTimestampMonotonic", bus_property_append_uint64, "t", offsetof(Manager, kernel_timestamp.monotonic) },
547 { "InitRDTimestamp", bus_property_append_uint64, "t", offsetof(Manager, initrd_timestamp.realtime) },
548 { "InitRDTimestampMonotonic", bus_property_append_uint64, "t", offsetof(Manager, initrd_timestamp.monotonic) },
549 { "UserspaceTimestamp", bus_property_append_uint64, "t", offsetof(Manager, userspace_timestamp.realtime) },
550 { "UserspaceTimestampMonotonic", bus_property_append_uint64, "t", offsetof(Manager, userspace_timestamp.monotonic) },
551 { "FinishTimestamp", bus_property_append_uint64, "t", offsetof(Manager, finish_timestamp.realtime) },
552 { "FinishTimestampMonotonic", bus_property_append_uint64, "t", offsetof(Manager, finish_timestamp.monotonic) },
553 { "LogLevel", bus_manager_append_log_level, "s", 0, false, bus_manager_set_log_level },
554 { "LogTarget", bus_manager_append_log_target, "s", 0, false, bus_manager_set_log_target },
555 { "NNames", bus_manager_append_n_names, "u", 0 },
556 { "NJobs", bus_manager_append_n_jobs, "u", 0 },
557 { "NInstalledJobs", bus_property_append_uint32, "u", offsetof(Manager, n_installed_jobs) },
558 { "NFailedJobs", bus_property_append_uint32, "u", offsetof(Manager, n_failed_jobs) },
559 { "Progress", bus_manager_append_progress, "d", 0 },
560 { "Environment", bus_property_append_strv, "as", offsetof(Manager, environment), true },
561 { "ConfirmSpawn", bus_property_append_bool, "b", offsetof(Manager, confirm_spawn) },
562 { "ShowStatus", bus_property_append_bool, "b", offsetof(Manager, show_status) },
563 { "UnitPath", bus_property_append_strv, "as", offsetof(Manager, lookup_paths.unit_path), true },
564 { "ControlGroupHierarchy", bus_property_append_string, "s", offsetof(Manager, cgroup_hierarchy), true },
565 { "DefaultControllers", bus_property_append_strv, "as", offsetof(Manager, default_controllers), true },
566 { "DefaultStandardOutput", bus_manager_append_exec_output, "s", offsetof(Manager, default_std_output) },
567 { "DefaultStandardError", bus_manager_append_exec_output, "s", offsetof(Manager, default_std_error) },
568 { "RuntimeWatchdogUSec", bus_property_append_usec, "t", offsetof(Manager, runtime_watchdog), false, bus_manager_set_runtime_watchdog_usec },
569 { "ShutdownWatchdogUSec", bus_property_append_usec, "t", offsetof(Manager, shutdown_watchdog), false, bus_property_set_usec },
570 { "Virtualization", bus_manager_append_virt, "s", 0, },
574 static DBusHandlerResult bus_manager_message_handler(DBusConnection *connection, DBusMessage *message, void *data) {
575 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
576 _cleanup_free_ char * path = NULL;
580 JobType job_type = _JOB_TYPE_INVALID;
581 bool reload_if_possible = false;
588 dbus_error_init(&error);
590 member = dbus_message_get_member(message);
592 if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "GetUnit")) {
596 if (!dbus_message_get_args(
599 DBUS_TYPE_STRING, &name,
601 return bus_send_error_reply(connection, message, &error, -EINVAL);
603 u = manager_get_unit(m, name);
605 dbus_set_error(&error, BUS_ERROR_NO_SUCH_UNIT, "Unit %s is not loaded.", name);
606 return bus_send_error_reply(connection, message, &error, -ENOENT);
609 SELINUX_UNIT_ACCESS_CHECK(u, connection, message, "status");
611 reply = dbus_message_new_method_return(message);
615 path = unit_dbus_path(u);
619 if (!dbus_message_append_args(
621 DBUS_TYPE_OBJECT_PATH, &path,
624 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "GetUnitByPID")) {
628 if (!dbus_message_get_args(
631 DBUS_TYPE_UINT32, &pid,
633 return bus_send_error_reply(connection, message, &error, -EINVAL);
635 u = cgroup_unit_by_pid(m, (pid_t) pid);
637 dbus_set_error(&error, BUS_ERROR_NO_SUCH_UNIT, "No unit for PID %lu is loaded.", (unsigned long) pid);
638 return bus_send_error_reply(connection, message, &error, -ENOENT);
641 SELINUX_UNIT_ACCESS_CHECK(u, connection, message, "status");
643 reply = dbus_message_new_method_return(message);
647 path = unit_dbus_path(u);
651 if (!dbus_message_append_args(
653 DBUS_TYPE_OBJECT_PATH, &path,
656 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "LoadUnit")) {
660 if (!dbus_message_get_args(
663 DBUS_TYPE_STRING, &name,
665 return bus_send_error_reply(connection, message, &error, -EINVAL);
667 r = manager_load_unit(m, name, NULL, &error, &u);
669 return bus_send_error_reply(connection, message, &error, r);
671 SELINUX_UNIT_ACCESS_CHECK(u, connection, message, "status");
673 reply = dbus_message_new_method_return(message);
677 path = unit_dbus_path(u);
681 if (!dbus_message_append_args(
683 DBUS_TYPE_OBJECT_PATH, &path,
687 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "StartUnit"))
688 job_type = JOB_START;
689 else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "StartUnitReplace"))
690 job_type = JOB_START;
691 else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "StopUnit"))
693 else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ReloadUnit"))
694 job_type = JOB_RELOAD;
695 else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "RestartUnit"))
696 job_type = JOB_RESTART;
697 else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "TryRestartUnit"))
698 job_type = JOB_TRY_RESTART;
699 else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ReloadOrRestartUnit")) {
700 reload_if_possible = true;
701 job_type = JOB_RESTART;
702 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ReloadOrTryRestartUnit")) {
703 reload_if_possible = true;
704 job_type = JOB_TRY_RESTART;
705 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "KillUnit")) {
706 const char *name, *swho;
711 if (!dbus_message_get_args(
714 DBUS_TYPE_STRING, &name,
715 DBUS_TYPE_STRING, &swho,
716 DBUS_TYPE_INT32, &signo,
718 return bus_send_error_reply(connection, message, &error, -EINVAL);
723 who = kill_who_from_string(swho);
725 return bus_send_error_reply(connection, message, &error, -EINVAL);
728 if (signo <= 0 || signo >= _NSIG)
729 return bus_send_error_reply(connection, message, &error, -EINVAL);
731 u = manager_get_unit(m, name);
733 dbus_set_error(&error, BUS_ERROR_NO_SUCH_UNIT, "Unit %s is not loaded.", name);
734 return bus_send_error_reply(connection, message, &error, -ENOENT);
737 SELINUX_UNIT_ACCESS_CHECK(u, connection, message, "stop");
739 r = unit_kill(u, who, signo, &error);
741 return bus_send_error_reply(connection, message, &error, r);
743 reply = dbus_message_new_method_return(message);
747 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "GetJob")) {
751 if (!dbus_message_get_args(
754 DBUS_TYPE_UINT32, &id,
756 return bus_send_error_reply(connection, message, &error, -EINVAL);
758 j = manager_get_job(m, id);
760 dbus_set_error(&error, BUS_ERROR_NO_SUCH_JOB, "Job %u does not exist.", (unsigned) id);
761 return bus_send_error_reply(connection, message, &error, -ENOENT);
764 SELINUX_UNIT_ACCESS_CHECK(j->unit, connection, message, "status");
766 reply = dbus_message_new_method_return(message);
770 path = job_dbus_path(j);
774 if (!dbus_message_append_args(
776 DBUS_TYPE_OBJECT_PATH, &path,
780 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ClearJobs")) {
782 SELINUX_ACCESS_CHECK(connection, message, "reboot");
784 manager_clear_jobs(m);
786 reply = dbus_message_new_method_return(message);
790 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ResetFailed")) {
792 SELINUX_ACCESS_CHECK(connection, message, "reload");
794 manager_reset_failed(m);
796 reply = dbus_message_new_method_return(message);
800 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ResetFailedUnit")) {
804 if (!dbus_message_get_args(
807 DBUS_TYPE_STRING, &name,
809 return bus_send_error_reply(connection, message, &error, -EINVAL);
811 u = manager_get_unit(m, name);
813 dbus_set_error(&error, BUS_ERROR_NO_SUCH_UNIT, "Unit %s is not loaded.", name);
814 return bus_send_error_reply(connection, message, &error, -ENOENT);
817 SELINUX_UNIT_ACCESS_CHECK(u, connection, message, "reload");
819 unit_reset_failed(u);
821 reply = dbus_message_new_method_return(message);
825 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ListUnits")) {
826 DBusMessageIter iter, sub;
831 SELINUX_ACCESS_CHECK(connection, message, "status");
833 reply = dbus_message_new_method_return(message);
837 dbus_message_iter_init_append(reply, &iter);
839 if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "(ssssssouso)", &sub))
842 HASHMAP_FOREACH_KEY(u, k, m->units, i) {
843 char *u_path, *j_path;
844 const char *description, *load_state, *active_state, *sub_state, *sjob_type, *following;
845 DBusMessageIter sub2;
852 if (!dbus_message_iter_open_container(&sub, DBUS_TYPE_STRUCT, NULL, &sub2))
855 description = unit_description(u);
856 load_state = unit_load_state_to_string(u->load_state);
857 active_state = unit_active_state_to_string(unit_active_state(u));
858 sub_state = unit_sub_state_to_string(u);
860 f = unit_following(u);
861 following = f ? f->id : "";
863 u_path = unit_dbus_path(u);
868 job_id = (uint32_t) u->job->id;
870 if (!(j_path = job_dbus_path(u->job))) {
875 sjob_type = job_type_to_string(u->job->type);
882 if (!dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &u->id) ||
883 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &description) ||
884 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &load_state) ||
885 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &active_state) ||
886 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &sub_state) ||
887 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &following) ||
888 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_OBJECT_PATH, &u_path) ||
889 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_UINT32, &job_id) ||
890 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &sjob_type) ||
891 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_OBJECT_PATH, &j_path)) {
902 if (!dbus_message_iter_close_container(&sub, &sub2))
906 if (!dbus_message_iter_close_container(&iter, &sub))
909 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ListJobs")) {
910 DBusMessageIter iter, sub;
914 SELINUX_ACCESS_CHECK(connection, message, "status");
916 reply = dbus_message_new_method_return(message);
920 dbus_message_iter_init_append(reply, &iter);
922 if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "(usssoo)", &sub))
925 HASHMAP_FOREACH(j, m->jobs, i) {
926 char *u_path, *j_path;
927 const char *state, *type;
929 DBusMessageIter sub2;
931 if (!dbus_message_iter_open_container(&sub, DBUS_TYPE_STRUCT, NULL, &sub2))
934 id = (uint32_t) j->id;
935 state = job_state_to_string(j->state);
936 type = job_type_to_string(j->type);
938 j_path = job_dbus_path(j);
942 u_path = unit_dbus_path(j->unit);
948 if (!dbus_message_iter_append_basic(&sub2, DBUS_TYPE_UINT32, &id) ||
949 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &j->unit->id) ||
950 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &type) ||
951 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &state) ||
952 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_OBJECT_PATH, &j_path) ||
953 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_OBJECT_PATH, &u_path)) {
962 if (!dbus_message_iter_close_container(&sub, &sub2))
966 if (!dbus_message_iter_close_container(&iter, &sub))
969 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "Subscribe")) {
973 SELINUX_ACCESS_CHECK(connection, message, "status");
975 s = BUS_CONNECTION_SUBSCRIBED(m, connection);
977 s = set_new(string_hash_func, string_compare_func);
981 if (!dbus_connection_set_data(connection, m->subscribed_data_slot, s, NULL)) {
987 client = strdup(bus_message_get_sender_with_fallback(message));
991 r = set_put(s, client);
994 return bus_send_error_reply(connection, message, NULL, r);
997 reply = dbus_message_new_method_return(message);
1001 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "Unsubscribe")) {
1004 SELINUX_ACCESS_CHECK(connection, message, "status");
1006 client = set_remove(BUS_CONNECTION_SUBSCRIBED(m, connection), (char*) bus_message_get_sender_with_fallback(message));
1008 dbus_set_error(&error, BUS_ERROR_NOT_SUBSCRIBED, "Client is not subscribed.");
1009 return bus_send_error_reply(connection, message, &error, -ENOENT);
1014 reply = dbus_message_new_method_return(message);
1018 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "Dump")) {
1023 SELINUX_ACCESS_CHECK(connection, message, "status");
1025 reply = dbus_message_new_method_return(message);
1029 f = open_memstream(&dump, &size);
1033 manager_dump_units(m, f, NULL);
1034 manager_dump_jobs(m, f, NULL);
1044 if (!dbus_message_append_args(reply, DBUS_TYPE_STRING, &dump, DBUS_TYPE_INVALID)) {
1050 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "CreateSnapshot")) {
1052 dbus_bool_t cleanup;
1055 SELINUX_ACCESS_CHECK(connection, message, "start");
1057 if (!dbus_message_get_args(
1060 DBUS_TYPE_STRING, &name,
1061 DBUS_TYPE_BOOLEAN, &cleanup,
1063 return bus_send_error_reply(connection, message, &error, -EINVAL);
1068 r = snapshot_create(m, name, cleanup, &error, &s);
1070 return bus_send_error_reply(connection, message, &error, r);
1072 reply = dbus_message_new_method_return(message);
1076 path = unit_dbus_path(UNIT(s));
1080 if (!dbus_message_append_args(
1082 DBUS_TYPE_OBJECT_PATH, &path,
1086 } else if (dbus_message_is_method_call(message, "org.freedesktop.DBus.Introspectable", "Introspect")) {
1087 char *introspection = NULL;
1095 SELINUX_ACCESS_CHECK(connection, message, "status");
1097 reply = dbus_message_new_method_return(message);
1101 /* We roll our own introspection code here, instead of
1102 * relying on bus_default_message_handler() because we
1103 * need to generate our introspection string
1106 f = open_memstream(&introspection, &size);
1110 fputs(INTROSPECTION_BEGIN, f);
1112 HASHMAP_FOREACH_KEY(u, k, m->units, i) {
1118 p = bus_path_escape(k);
1121 free(introspection);
1125 fprintf(f, "<node name=\"unit/%s\"/>", p);
1129 HASHMAP_FOREACH(j, m->jobs, i)
1130 fprintf(f, "<node name=\"job/%lu\"/>", (unsigned long) j->id);
1132 fputs(INTROSPECTION_END, f);
1136 free(introspection);
1145 if (!dbus_message_append_args(reply, DBUS_TYPE_STRING, &introspection, DBUS_TYPE_INVALID)) {
1146 free(introspection);
1150 free(introspection);
1152 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "Reload")) {
1154 SELINUX_ACCESS_CHECK(connection, message, "reload");
1156 assert(!m->queued_message);
1158 /* Instead of sending the reply back right away, we
1159 * just remember that we need to and then send it
1160 * after the reload is finished. That way the caller
1161 * knows when the reload finished. */
1163 m->queued_message = dbus_message_new_method_return(message);
1164 if (!m->queued_message)
1167 m->queued_message_connection = connection;
1168 m->exit_code = MANAGER_RELOAD;
1170 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "Reexecute")) {
1172 SELINUX_ACCESS_CHECK(connection, message, "reload");
1174 /* We don't send a reply back here, the client should
1175 * just wait for us disconnecting. */
1177 m->exit_code = MANAGER_REEXECUTE;
1179 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "Exit")) {
1181 SELINUX_ACCESS_CHECK(connection, message, "halt");
1183 if (m->running_as == SYSTEMD_SYSTEM) {
1184 dbus_set_error(&error, BUS_ERROR_NOT_SUPPORTED, "Exit is only supported for user service managers.");
1185 return bus_send_error_reply(connection, message, &error, -ENOTSUP);
1188 reply = dbus_message_new_method_return(message);
1192 m->exit_code = MANAGER_EXIT;
1194 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "Reboot")) {
1196 SELINUX_ACCESS_CHECK(connection, message, "reboot");
1198 if (m->running_as != SYSTEMD_SYSTEM) {
1199 dbus_set_error(&error, BUS_ERROR_NOT_SUPPORTED, "Reboot is only supported for system managers.");
1200 return bus_send_error_reply(connection, message, &error, -ENOTSUP);
1203 reply = dbus_message_new_method_return(message);
1207 m->exit_code = MANAGER_REBOOT;
1209 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "PowerOff")) {
1211 SELINUX_ACCESS_CHECK(connection, message, "halt");
1213 if (m->running_as != SYSTEMD_SYSTEM) {
1214 dbus_set_error(&error, BUS_ERROR_NOT_SUPPORTED, "Powering off is only supported for system managers.");
1215 return bus_send_error_reply(connection, message, &error, -ENOTSUP);
1218 reply = dbus_message_new_method_return(message);
1222 m->exit_code = MANAGER_POWEROFF;
1224 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "Halt")) {
1226 SELINUX_ACCESS_CHECK(connection, message, "halt");
1228 if (m->running_as != SYSTEMD_SYSTEM) {
1229 dbus_set_error(&error, BUS_ERROR_NOT_SUPPORTED, "Halting is only supported for system managers.");
1230 return bus_send_error_reply(connection, message, &error, -ENOTSUP);
1233 reply = dbus_message_new_method_return(message);
1237 m->exit_code = MANAGER_HALT;
1239 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "KExec")) {
1241 SELINUX_ACCESS_CHECK(connection, message, "reboot");
1243 if (m->running_as != SYSTEMD_SYSTEM) {
1244 dbus_set_error(&error, BUS_ERROR_NOT_SUPPORTED, "kexec is only supported for system managers.");
1245 return bus_send_error_reply(connection, message, &error, -ENOTSUP);
1248 reply = dbus_message_new_method_return(message);
1252 m->exit_code = MANAGER_KEXEC;
1254 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "SwitchRoot")) {
1255 const char *switch_root, *switch_root_init;
1259 SELINUX_ACCESS_CHECK(connection, message, "reboot");
1261 if (!dbus_message_get_args(
1264 DBUS_TYPE_STRING, &switch_root,
1265 DBUS_TYPE_STRING, &switch_root_init,
1267 return bus_send_error_reply(connection, message, &error, -EINVAL);
1269 if (path_equal(switch_root, "/") || !path_is_absolute(switch_root))
1270 return bus_send_error_reply(connection, message, NULL, -EINVAL);
1272 if (!isempty(switch_root_init) && !path_is_absolute(switch_root_init))
1273 return bus_send_error_reply(connection, message, NULL, -EINVAL);
1275 if (m->running_as != SYSTEMD_SYSTEM) {
1276 dbus_set_error(&error, BUS_ERROR_NOT_SUPPORTED, "Switching root is only supported for system managers.");
1277 return bus_send_error_reply(connection, message, &error, -ENOTSUP);
1281 if (isempty(switch_root_init))
1282 k = access(switch_root, F_OK);
1286 p = strjoin(switch_root, "/", switch_root_init, NULL);
1290 k = access(p, X_OK);
1294 return bus_send_error_reply(connection, message, NULL, -errno);
1296 u = strdup(switch_root);
1300 if (!isempty(switch_root_init)) {
1301 v = strdup(switch_root_init);
1309 free(m->switch_root);
1310 free(m->switch_root_init);
1312 m->switch_root_init = v;
1314 reply = dbus_message_new_method_return(message);
1318 m->exit_code = MANAGER_SWITCH_ROOT;
1320 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "SetEnvironment")) {
1321 char **l = NULL, **e = NULL;
1323 SELINUX_ACCESS_CHECK(connection, message, "reboot");
1325 r = bus_parse_strv(message, &l);
1329 return bus_send_error_reply(connection, message, NULL, r);
1331 e = strv_env_merge(2, m->environment, l);
1336 reply = dbus_message_new_method_return(message);
1342 strv_free(m->environment);
1345 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "UnsetEnvironment")) {
1346 char **l = NULL, **e = NULL;
1348 SELINUX_ACCESS_CHECK(connection, message, "reboot");
1350 r = bus_parse_strv(message, &l);
1354 return bus_send_error_reply(connection, message, NULL, r);
1356 e = strv_env_delete(m->environment, 1, l);
1362 reply = dbus_message_new_method_return(message);
1368 strv_free(m->environment);
1371 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "UnsetAndSetEnvironment")) {
1372 char **l_set = NULL, **l_unset = NULL, **e = NULL, **f = NULL;
1373 DBusMessageIter iter;
1375 SELINUX_ACCESS_CHECK(connection, message, "reboot");
1377 if (!dbus_message_iter_init(message, &iter))
1380 r = bus_parse_strv_iter(&iter, &l_unset);
1384 return bus_send_error_reply(connection, message, NULL, r);
1386 if (!dbus_message_iter_next(&iter)) {
1388 return bus_send_error_reply(connection, message, NULL, -EINVAL);
1391 r = bus_parse_strv_iter(&iter, &l_set);
1397 return bus_send_error_reply(connection, message, NULL, r);
1400 e = strv_env_delete(m->environment, 1, l_unset);
1408 f = strv_env_merge(2, e, l_set);
1415 reply = dbus_message_new_method_return(message);
1421 strv_free(m->environment);
1423 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ListUnitFiles")) {
1424 DBusMessageIter iter, sub, sub2;
1429 SELINUX_ACCESS_CHECK(connection, message, "status");
1431 reply = dbus_message_new_method_return(message);
1435 h = hashmap_new(string_hash_func, string_compare_func);
1439 r = unit_file_get_list(m->running_as == SYSTEMD_SYSTEM ? UNIT_FILE_SYSTEM : UNIT_FILE_USER, NULL, h);
1441 unit_file_list_free(h);
1442 return bus_send_error_reply(connection, message, NULL, r);
1445 dbus_message_iter_init_append(reply, &iter);
1447 if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "(ss)", &sub)) {
1448 unit_file_list_free(h);
1452 HASHMAP_FOREACH(item, h, i) {
1455 state = unit_file_state_to_string(item->state);
1458 if (!dbus_message_iter_open_container(&sub, DBUS_TYPE_STRUCT, NULL, &sub2) ||
1459 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &item->path) ||
1460 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &state) ||
1461 !dbus_message_iter_close_container(&sub, &sub2)) {
1462 unit_file_list_free(h);
1467 unit_file_list_free(h);
1469 if (!dbus_message_iter_close_container(&iter, &sub))
1472 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "GetUnitFileState")) {
1474 UnitFileState state;
1477 SELINUX_ACCESS_CHECK(connection, message, "status");
1479 if (!dbus_message_get_args(
1482 DBUS_TYPE_STRING, &name,
1484 return bus_send_error_reply(connection, message, &error, -EINVAL);
1486 state = unit_file_get_state(m->running_as == SYSTEMD_SYSTEM ? UNIT_FILE_SYSTEM : UNIT_FILE_USER, NULL, name);
1488 return bus_send_error_reply(connection, message, NULL, state);
1490 s = unit_file_state_to_string(state);
1493 reply = dbus_message_new_method_return(message);
1497 if (!dbus_message_append_args(
1499 DBUS_TYPE_STRING, &s,
1502 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "EnableUnitFiles") ||
1503 dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ReenableUnitFiles") ||
1504 dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "LinkUnitFiles") ||
1505 dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "PresetUnitFiles") ||
1506 dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "MaskUnitFiles")) {
1509 DBusMessageIter iter;
1510 UnitFileScope scope = m->running_as == SYSTEMD_SYSTEM ? UNIT_FILE_SYSTEM : UNIT_FILE_USER;
1511 UnitFileChange *changes = NULL;
1512 unsigned n_changes = 0;
1513 dbus_bool_t runtime, force;
1514 int carries_install_info = -1;
1516 SELINUX_ACCESS_CHECK(connection, message, streq(member, "MaskUnitFiles") ? "disable" : "enable");
1518 if (!dbus_message_iter_init(message, &iter))
1521 r = bus_parse_strv_iter(&iter, &l);
1526 return bus_send_error_reply(connection, message, NULL, r);
1529 if (!dbus_message_iter_next(&iter) ||
1530 bus_iter_get_basic_and_next(&iter, DBUS_TYPE_BOOLEAN, &runtime, true) < 0 ||
1531 bus_iter_get_basic_and_next(&iter, DBUS_TYPE_BOOLEAN, &force, false) < 0) {
1533 return bus_send_error_reply(connection, message, NULL, -EIO);
1536 if (streq(member, "EnableUnitFiles")) {
1537 r = unit_file_enable(scope, runtime, NULL, l, force, &changes, &n_changes);
1538 carries_install_info = r;
1539 } else if (streq(member, "ReenableUnitFiles")) {
1540 r = unit_file_reenable(scope, runtime, NULL, l, force, &changes, &n_changes);
1541 carries_install_info = r;
1542 } else if (streq(member, "LinkUnitFiles"))
1543 r = unit_file_link(scope, runtime, NULL, l, force, &changes, &n_changes);
1544 else if (streq(member, "PresetUnitFiles")) {
1545 r = unit_file_preset(scope, runtime, NULL, l, force, &changes, &n_changes);
1546 carries_install_info = r;
1547 } else if (streq(member, "MaskUnitFiles"))
1548 r = unit_file_mask(scope, runtime, NULL, l, force, &changes, &n_changes);
1550 assert_not_reached("Uh? Wrong method");
1553 bus_manager_send_unit_files_changed(m);
1556 unit_file_changes_free(changes, n_changes);
1557 return bus_send_error_reply(connection, message, NULL, r);
1560 reply = message_from_file_changes(message, changes, n_changes, carries_install_info);
1561 unit_file_changes_free(changes, n_changes);
1566 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "DisableUnitFiles") ||
1567 dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "UnmaskUnitFiles")) {
1570 DBusMessageIter iter;
1571 UnitFileScope scope = m->running_as == SYSTEMD_SYSTEM ? UNIT_FILE_SYSTEM : UNIT_FILE_USER;
1572 UnitFileChange *changes = NULL;
1573 unsigned n_changes = 0;
1574 dbus_bool_t runtime;
1576 SELINUX_ACCESS_CHECK(connection, message, streq(member, "UnmaskUnitFiles") ? "enable" : "disable");
1578 if (!dbus_message_iter_init(message, &iter))
1581 r = bus_parse_strv_iter(&iter, &l);
1586 return bus_send_error_reply(connection, message, NULL, r);
1589 if (!dbus_message_iter_next(&iter) ||
1590 bus_iter_get_basic_and_next(&iter, DBUS_TYPE_BOOLEAN, &runtime, false) < 0) {
1592 return bus_send_error_reply(connection, message, NULL, -EIO);
1595 if (streq(member, "DisableUnitFiles"))
1596 r = unit_file_disable(scope, runtime, NULL, l, &changes, &n_changes);
1597 else if (streq(member, "UnmaskUnitFiles"))
1598 r = unit_file_unmask(scope, runtime, NULL, l, &changes, &n_changes);
1600 assert_not_reached("Uh? Wrong method");
1603 bus_manager_send_unit_files_changed(m);
1606 unit_file_changes_free(changes, n_changes);
1607 return bus_send_error_reply(connection, message, NULL, r);
1610 reply = message_from_file_changes(message, changes, n_changes, -1);
1611 unit_file_changes_free(changes, n_changes);
1617 const BusBoundProperties bps[] = {
1618 { "org.freedesktop.systemd1.Manager", bus_systemd_properties, systemd_property_string },
1619 { "org.freedesktop.systemd1.Manager", bus_manager_properties, m },
1623 SELINUX_ACCESS_CHECK(connection, message, "status");
1625 return bus_default_message_handler(connection, message, NULL, INTERFACES_LIST, bps);
1628 if (job_type != _JOB_TYPE_INVALID) {
1629 const char *name, *smode, *old_name = NULL;
1634 if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "StartUnitReplace"))
1635 b = dbus_message_get_args(
1638 DBUS_TYPE_STRING, &old_name,
1639 DBUS_TYPE_STRING, &name,
1640 DBUS_TYPE_STRING, &smode,
1643 b = dbus_message_get_args(
1646 DBUS_TYPE_STRING, &name,
1647 DBUS_TYPE_STRING, &smode,
1650 return bus_send_error_reply(connection, message, &error, -EINVAL);
1653 u = manager_get_unit(m, old_name);
1654 if (!u || !u->job || u->job->type != JOB_START) {
1655 dbus_set_error(&error, BUS_ERROR_NO_SUCH_JOB, "No job queued for unit %s", old_name);
1656 return bus_send_error_reply(connection, message, &error, -ENOENT);
1660 mode = job_mode_from_string(smode);
1662 dbus_set_error(&error, BUS_ERROR_INVALID_JOB_MODE, "Job mode %s is invalid.", smode);
1663 return bus_send_error_reply(connection, message, &error, -EINVAL);
1666 r = manager_load_unit(m, name, NULL, &error, &u);
1668 return bus_send_error_reply(connection, message, &error, r);
1670 return bus_unit_queue_job(connection, message, u, job_type, mode, reload_if_possible);
1674 if (!dbus_connection_send(connection, reply, NULL))
1677 return DBUS_HANDLER_RESULT_HANDLED;
1680 dbus_error_free(&error);
1682 return DBUS_HANDLER_RESULT_NEED_MEMORY;
1685 const DBusObjectPathVTable bus_manager_vtable = {
1686 .message_function = bus_manager_message_handler