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 if (!(reply = dbus_message_new_method_return(message)))
746 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "GetJob")) {
750 if (!dbus_message_get_args(
753 DBUS_TYPE_UINT32, &id,
755 return bus_send_error_reply(connection, message, &error, -EINVAL);
757 j = manager_get_job(m, id);
759 dbus_set_error(&error, BUS_ERROR_NO_SUCH_JOB, "Job %u does not exist.", (unsigned) id);
760 return bus_send_error_reply(connection, message, &error, -ENOENT);
763 SELINUX_UNIT_ACCESS_CHECK(j->unit, connection, message, "status");
765 reply = dbus_message_new_method_return(message);
769 path = job_dbus_path(j);
773 if (!dbus_message_append_args(
775 DBUS_TYPE_OBJECT_PATH, &path,
779 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ClearJobs")) {
781 SELINUX_ACCESS_CHECK(connection, message, "reboot");
783 manager_clear_jobs(m);
785 reply = dbus_message_new_method_return(message);
789 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ResetFailed")) {
791 SELINUX_ACCESS_CHECK(connection, message, "reload");
793 manager_reset_failed(m);
795 reply = dbus_message_new_method_return(message);
799 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ResetFailedUnit")) {
803 if (!dbus_message_get_args(
806 DBUS_TYPE_STRING, &name,
808 return bus_send_error_reply(connection, message, &error, -EINVAL);
810 u = manager_get_unit(m, name);
812 dbus_set_error(&error, BUS_ERROR_NO_SUCH_UNIT, "Unit %s is not loaded.", name);
813 return bus_send_error_reply(connection, message, &error, -ENOENT);
816 SELINUX_UNIT_ACCESS_CHECK(u, connection, message, "reload");
818 unit_reset_failed(u);
820 reply = dbus_message_new_method_return(message);
824 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ListUnits")) {
825 DBusMessageIter iter, sub;
830 SELINUX_ACCESS_CHECK(connection, message, "status");
832 reply = dbus_message_new_method_return(message);
836 dbus_message_iter_init_append(reply, &iter);
838 if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "(ssssssouso)", &sub))
841 HASHMAP_FOREACH_KEY(u, k, m->units, i) {
842 char *u_path, *j_path;
843 const char *description, *load_state, *active_state, *sub_state, *sjob_type, *following;
844 DBusMessageIter sub2;
851 if (!dbus_message_iter_open_container(&sub, DBUS_TYPE_STRUCT, NULL, &sub2))
854 description = unit_description(u);
855 load_state = unit_load_state_to_string(u->load_state);
856 active_state = unit_active_state_to_string(unit_active_state(u));
857 sub_state = unit_sub_state_to_string(u);
859 f = unit_following(u);
860 following = f ? f->id : "";
862 u_path = unit_dbus_path(u);
867 job_id = (uint32_t) u->job->id;
869 if (!(j_path = job_dbus_path(u->job))) {
874 sjob_type = job_type_to_string(u->job->type);
881 if (!dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &u->id) ||
882 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &description) ||
883 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &load_state) ||
884 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &active_state) ||
885 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &sub_state) ||
886 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &following) ||
887 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_OBJECT_PATH, &u_path) ||
888 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_UINT32, &job_id) ||
889 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &sjob_type) ||
890 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_OBJECT_PATH, &j_path)) {
901 if (!dbus_message_iter_close_container(&sub, &sub2))
905 if (!dbus_message_iter_close_container(&iter, &sub))
908 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ListJobs")) {
909 DBusMessageIter iter, sub;
913 SELINUX_ACCESS_CHECK(connection, message, "status");
915 reply = dbus_message_new_method_return(message);
919 dbus_message_iter_init_append(reply, &iter);
921 if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "(usssoo)", &sub))
924 HASHMAP_FOREACH(j, m->jobs, i) {
925 char *u_path, *j_path;
926 const char *state, *type;
928 DBusMessageIter sub2;
930 if (!dbus_message_iter_open_container(&sub, DBUS_TYPE_STRUCT, NULL, &sub2))
933 id = (uint32_t) j->id;
934 state = job_state_to_string(j->state);
935 type = job_type_to_string(j->type);
937 j_path = job_dbus_path(j);
941 u_path = unit_dbus_path(j->unit);
947 if (!dbus_message_iter_append_basic(&sub2, DBUS_TYPE_UINT32, &id) ||
948 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &j->unit->id) ||
949 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &type) ||
950 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &state) ||
951 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_OBJECT_PATH, &j_path) ||
952 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_OBJECT_PATH, &u_path)) {
961 if (!dbus_message_iter_close_container(&sub, &sub2))
965 if (!dbus_message_iter_close_container(&iter, &sub))
968 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "Subscribe")) {
972 SELINUX_ACCESS_CHECK(connection, message, "status");
974 s = BUS_CONNECTION_SUBSCRIBED(m, connection);
976 s = set_new(string_hash_func, string_compare_func);
980 if (!dbus_connection_set_data(connection, m->subscribed_data_slot, s, NULL)) {
986 client = strdup(bus_message_get_sender_with_fallback(message));
990 r = set_put(s, client);
993 return bus_send_error_reply(connection, message, NULL, r);
996 reply = dbus_message_new_method_return(message);
1000 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "Unsubscribe")) {
1003 SELINUX_ACCESS_CHECK(connection, message, "status");
1005 client = set_remove(BUS_CONNECTION_SUBSCRIBED(m, connection), (char*) bus_message_get_sender_with_fallback(message));
1007 dbus_set_error(&error, BUS_ERROR_NOT_SUBSCRIBED, "Client is not subscribed.");
1008 return bus_send_error_reply(connection, message, &error, -ENOENT);
1013 reply = dbus_message_new_method_return(message);
1017 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "Dump")) {
1022 SELINUX_ACCESS_CHECK(connection, message, "status");
1024 reply = dbus_message_new_method_return(message);
1028 f = open_memstream(&dump, &size);
1032 manager_dump_units(m, f, NULL);
1033 manager_dump_jobs(m, f, NULL);
1043 if (!dbus_message_append_args(reply, DBUS_TYPE_STRING, &dump, DBUS_TYPE_INVALID)) {
1049 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "CreateSnapshot")) {
1051 dbus_bool_t cleanup;
1054 SELINUX_ACCESS_CHECK(connection, message, "start");
1056 if (!dbus_message_get_args(
1059 DBUS_TYPE_STRING, &name,
1060 DBUS_TYPE_BOOLEAN, &cleanup,
1062 return bus_send_error_reply(connection, message, &error, -EINVAL);
1067 r = snapshot_create(m, name, cleanup, &error, &s);
1069 return bus_send_error_reply(connection, message, &error, r);
1071 reply = dbus_message_new_method_return(message);
1075 path = unit_dbus_path(UNIT(s));
1079 if (!dbus_message_append_args(
1081 DBUS_TYPE_OBJECT_PATH, &path,
1085 } else if (dbus_message_is_method_call(message, "org.freedesktop.DBus.Introspectable", "Introspect")) {
1086 char *introspection = NULL;
1094 SELINUX_ACCESS_CHECK(connection, message, "status");
1096 reply = dbus_message_new_method_return(message);
1100 /* We roll our own introspection code here, instead of
1101 * relying on bus_default_message_handler() because we
1102 * need to generate our introspection string
1105 f = open_memstream(&introspection, &size);
1109 fputs(INTROSPECTION_BEGIN, f);
1111 HASHMAP_FOREACH_KEY(u, k, m->units, i) {
1117 p = bus_path_escape(k);
1120 free(introspection);
1124 fprintf(f, "<node name=\"unit/%s\"/>", p);
1128 HASHMAP_FOREACH(j, m->jobs, i)
1129 fprintf(f, "<node name=\"job/%lu\"/>", (unsigned long) j->id);
1131 fputs(INTROSPECTION_END, f);
1135 free(introspection);
1144 if (!dbus_message_append_args(reply, DBUS_TYPE_STRING, &introspection, DBUS_TYPE_INVALID)) {
1145 free(introspection);
1149 free(introspection);
1151 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "Reload")) {
1153 SELINUX_ACCESS_CHECK(connection, message, "reload");
1155 assert(!m->queued_message);
1157 /* Instead of sending the reply back right away, we
1158 * just remember that we need to and then send it
1159 * after the reload is finished. That way the caller
1160 * knows when the reload finished. */
1162 m->queued_message = dbus_message_new_method_return(message);
1163 if (!m->queued_message)
1166 m->queued_message_connection = connection;
1167 m->exit_code = MANAGER_RELOAD;
1169 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "Reexecute")) {
1171 SELINUX_ACCESS_CHECK(connection, message, "reload");
1173 /* We don't send a reply back here, the client should
1174 * just wait for us disconnecting. */
1176 m->exit_code = MANAGER_REEXECUTE;
1178 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "Exit")) {
1180 SELINUX_ACCESS_CHECK(connection, message, "halt");
1182 if (m->running_as == SYSTEMD_SYSTEM) {
1183 dbus_set_error(&error, BUS_ERROR_NOT_SUPPORTED, "Exit is only supported for user service managers.");
1184 return bus_send_error_reply(connection, message, &error, -ENOTSUP);
1187 reply = dbus_message_new_method_return(message);
1191 m->exit_code = MANAGER_EXIT;
1193 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "Reboot")) {
1195 SELINUX_ACCESS_CHECK(connection, message, "reboot");
1197 if (m->running_as != SYSTEMD_SYSTEM) {
1198 dbus_set_error(&error, BUS_ERROR_NOT_SUPPORTED, "Reboot is only supported for system managers.");
1199 return bus_send_error_reply(connection, message, &error, -ENOTSUP);
1202 reply = dbus_message_new_method_return(message);
1206 m->exit_code = MANAGER_REBOOT;
1208 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "PowerOff")) {
1210 SELINUX_ACCESS_CHECK(connection, message, "halt");
1212 if (m->running_as != SYSTEMD_SYSTEM) {
1213 dbus_set_error(&error, BUS_ERROR_NOT_SUPPORTED, "Powering off is only supported for system managers.");
1214 return bus_send_error_reply(connection, message, &error, -ENOTSUP);
1217 reply = dbus_message_new_method_return(message);
1221 m->exit_code = MANAGER_POWEROFF;
1223 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "Halt")) {
1225 SELINUX_ACCESS_CHECK(connection, message, "halt");
1227 if (m->running_as != SYSTEMD_SYSTEM) {
1228 dbus_set_error(&error, BUS_ERROR_NOT_SUPPORTED, "Halting is only supported for system managers.");
1229 return bus_send_error_reply(connection, message, &error, -ENOTSUP);
1232 reply = dbus_message_new_method_return(message);
1236 m->exit_code = MANAGER_HALT;
1238 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "KExec")) {
1240 SELINUX_ACCESS_CHECK(connection, message, "reboot");
1242 if (m->running_as != SYSTEMD_SYSTEM) {
1243 dbus_set_error(&error, BUS_ERROR_NOT_SUPPORTED, "kexec is only supported for system managers.");
1244 return bus_send_error_reply(connection, message, &error, -ENOTSUP);
1247 reply = dbus_message_new_method_return(message);
1251 m->exit_code = MANAGER_KEXEC;
1253 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "SwitchRoot")) {
1254 const char *switch_root, *switch_root_init;
1258 SELINUX_ACCESS_CHECK(connection, message, "reboot");
1260 if (!dbus_message_get_args(
1263 DBUS_TYPE_STRING, &switch_root,
1264 DBUS_TYPE_STRING, &switch_root_init,
1266 return bus_send_error_reply(connection, message, &error, -EINVAL);
1268 if (path_equal(switch_root, "/") || !path_is_absolute(switch_root))
1269 return bus_send_error_reply(connection, message, NULL, -EINVAL);
1271 if (!isempty(switch_root_init) && !path_is_absolute(switch_root_init))
1272 return bus_send_error_reply(connection, message, NULL, -EINVAL);
1274 if (m->running_as != SYSTEMD_SYSTEM) {
1275 dbus_set_error(&error, BUS_ERROR_NOT_SUPPORTED, "Switching root is only supported for system managers.");
1276 return bus_send_error_reply(connection, message, &error, -ENOTSUP);
1280 if (isempty(switch_root_init))
1281 k = access(switch_root, F_OK);
1285 p = strjoin(switch_root, "/", switch_root_init, NULL);
1289 k = access(p, X_OK);
1293 return bus_send_error_reply(connection, message, NULL, -errno);
1295 u = strdup(switch_root);
1299 if (!isempty(switch_root_init)) {
1300 v = strdup(switch_root_init);
1308 free(m->switch_root);
1309 free(m->switch_root_init);
1311 m->switch_root_init = v;
1313 reply = dbus_message_new_method_return(message);
1317 m->exit_code = MANAGER_SWITCH_ROOT;
1319 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "SetEnvironment")) {
1320 char **l = NULL, **e = NULL;
1322 SELINUX_ACCESS_CHECK(connection, message, "reboot");
1324 r = bus_parse_strv(message, &l);
1328 return bus_send_error_reply(connection, message, NULL, r);
1330 e = strv_env_merge(2, m->environment, l);
1335 reply = dbus_message_new_method_return(message);
1341 strv_free(m->environment);
1344 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "UnsetEnvironment")) {
1345 char **l = NULL, **e = NULL;
1347 SELINUX_ACCESS_CHECK(connection, message, "reboot");
1349 r = bus_parse_strv(message, &l);
1353 return bus_send_error_reply(connection, message, NULL, r);
1355 e = strv_env_delete(m->environment, 1, l);
1361 if (!(reply = dbus_message_new_method_return(message))) {
1366 strv_free(m->environment);
1369 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "UnsetAndSetEnvironment")) {
1370 char **l_set = NULL, **l_unset = NULL, **e = NULL, **f = NULL;
1371 DBusMessageIter iter;
1373 SELINUX_ACCESS_CHECK(connection, message, "reboot");
1375 if (!dbus_message_iter_init(message, &iter))
1378 r = bus_parse_strv_iter(&iter, &l_unset);
1382 return bus_send_error_reply(connection, message, NULL, r);
1384 if (!dbus_message_iter_next(&iter)) {
1386 return bus_send_error_reply(connection, message, NULL, -EINVAL);
1389 r = bus_parse_strv_iter(&iter, &l_set);
1395 return bus_send_error_reply(connection, message, NULL, r);
1398 e = strv_env_delete(m->environment, 1, l_unset);
1406 f = strv_env_merge(2, e, l_set);
1413 if (!(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 dbus_message_unref(reply);
1440 return bus_send_error_reply(connection, message, NULL, r);
1443 dbus_message_iter_init_append(reply, &iter);
1445 if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "(ss)", &sub)) {
1446 unit_file_list_free(h);
1450 HASHMAP_FOREACH(item, h, i) {
1453 state = unit_file_state_to_string(item->state);
1456 if (!dbus_message_iter_open_container(&sub, DBUS_TYPE_STRUCT, NULL, &sub2) ||
1457 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &item->path) ||
1458 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &state) ||
1459 !dbus_message_iter_close_container(&sub, &sub2)) {
1460 unit_file_list_free(h);
1465 unit_file_list_free(h);
1467 if (!dbus_message_iter_close_container(&iter, &sub))
1470 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "GetUnitFileState")) {
1472 UnitFileState state;
1475 SELINUX_ACCESS_CHECK(connection, message, "status");
1477 if (!dbus_message_get_args(
1480 DBUS_TYPE_STRING, &name,
1482 return bus_send_error_reply(connection, message, &error, -EINVAL);
1484 state = unit_file_get_state(m->running_as == SYSTEMD_SYSTEM ? UNIT_FILE_SYSTEM : UNIT_FILE_USER, NULL, name);
1486 return bus_send_error_reply(connection, message, NULL, state);
1488 s = unit_file_state_to_string(state);
1491 reply = dbus_message_new_method_return(message);
1495 if (!dbus_message_append_args(
1497 DBUS_TYPE_STRING, &s,
1500 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "EnableUnitFiles") ||
1501 dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ReenableUnitFiles") ||
1502 dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "LinkUnitFiles") ||
1503 dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "PresetUnitFiles") ||
1504 dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "MaskUnitFiles")) {
1507 DBusMessageIter iter;
1508 UnitFileScope scope = m->running_as == SYSTEMD_SYSTEM ? UNIT_FILE_SYSTEM : UNIT_FILE_USER;
1509 UnitFileChange *changes = NULL;
1510 unsigned n_changes = 0;
1511 dbus_bool_t runtime, force;
1512 int carries_install_info = -1;
1514 SELINUX_ACCESS_CHECK(connection, message, streq(member, "MaskUnitFiles") ? "disable" : "enable");
1516 if (!dbus_message_iter_init(message, &iter))
1519 r = bus_parse_strv_iter(&iter, &l);
1524 return bus_send_error_reply(connection, message, NULL, r);
1527 if (!dbus_message_iter_next(&iter) ||
1528 bus_iter_get_basic_and_next(&iter, DBUS_TYPE_BOOLEAN, &runtime, true) < 0 ||
1529 bus_iter_get_basic_and_next(&iter, DBUS_TYPE_BOOLEAN, &force, false) < 0) {
1531 return bus_send_error_reply(connection, message, NULL, -EIO);
1534 if (streq(member, "EnableUnitFiles")) {
1535 r = unit_file_enable(scope, runtime, NULL, l, force, &changes, &n_changes);
1536 carries_install_info = r;
1537 } else if (streq(member, "ReenableUnitFiles")) {
1538 r = unit_file_reenable(scope, runtime, NULL, l, force, &changes, &n_changes);
1539 carries_install_info = r;
1540 } else if (streq(member, "LinkUnitFiles"))
1541 r = unit_file_link(scope, runtime, NULL, l, force, &changes, &n_changes);
1542 else if (streq(member, "PresetUnitFiles")) {
1543 r = unit_file_preset(scope, runtime, NULL, l, force, &changes, &n_changes);
1544 carries_install_info = r;
1545 } else if (streq(member, "MaskUnitFiles"))
1546 r = unit_file_mask(scope, runtime, NULL, l, force, &changes, &n_changes);
1548 assert_not_reached("Uh? Wrong method");
1551 bus_manager_send_unit_files_changed(m);
1554 unit_file_changes_free(changes, n_changes);
1555 return bus_send_error_reply(connection, message, NULL, r);
1558 reply = message_from_file_changes(message, changes, n_changes, carries_install_info);
1559 unit_file_changes_free(changes, n_changes);
1564 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "DisableUnitFiles") ||
1565 dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "UnmaskUnitFiles")) {
1568 DBusMessageIter iter;
1569 UnitFileScope scope = m->running_as == SYSTEMD_SYSTEM ? UNIT_FILE_SYSTEM : UNIT_FILE_USER;
1570 UnitFileChange *changes = NULL;
1571 unsigned n_changes = 0;
1572 dbus_bool_t runtime;
1574 SELINUX_ACCESS_CHECK(connection, message, streq(member, "UnmaskUnitFiles") ? "enable" : "disable");
1576 if (!dbus_message_iter_init(message, &iter))
1579 r = bus_parse_strv_iter(&iter, &l);
1584 return bus_send_error_reply(connection, message, NULL, r);
1587 if (!dbus_message_iter_next(&iter) ||
1588 bus_iter_get_basic_and_next(&iter, DBUS_TYPE_BOOLEAN, &runtime, false) < 0) {
1590 return bus_send_error_reply(connection, message, NULL, -EIO);
1593 if (streq(member, "DisableUnitFiles"))
1594 r = unit_file_disable(scope, runtime, NULL, l, &changes, &n_changes);
1595 else if (streq(member, "UnmaskUnitFiles"))
1596 r = unit_file_unmask(scope, runtime, NULL, l, &changes, &n_changes);
1598 assert_not_reached("Uh? Wrong method");
1601 bus_manager_send_unit_files_changed(m);
1604 unit_file_changes_free(changes, n_changes);
1605 return bus_send_error_reply(connection, message, NULL, r);
1608 reply = message_from_file_changes(message, changes, n_changes, -1);
1609 unit_file_changes_free(changes, n_changes);
1615 const BusBoundProperties bps[] = {
1616 { "org.freedesktop.systemd1.Manager", bus_systemd_properties, systemd_property_string },
1617 { "org.freedesktop.systemd1.Manager", bus_manager_properties, m },
1621 SELINUX_ACCESS_CHECK(connection, message, "status");
1623 return bus_default_message_handler(connection, message, NULL, INTERFACES_LIST, bps);
1626 if (job_type != _JOB_TYPE_INVALID) {
1627 const char *name, *smode, *old_name = NULL;
1632 if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "StartUnitReplace"))
1633 b = dbus_message_get_args(
1636 DBUS_TYPE_STRING, &old_name,
1637 DBUS_TYPE_STRING, &name,
1638 DBUS_TYPE_STRING, &smode,
1641 b = dbus_message_get_args(
1644 DBUS_TYPE_STRING, &name,
1645 DBUS_TYPE_STRING, &smode,
1648 return bus_send_error_reply(connection, message, &error, -EINVAL);
1651 u = manager_get_unit(m, old_name);
1652 if (!u || !u->job || u->job->type != JOB_START) {
1653 dbus_set_error(&error, BUS_ERROR_NO_SUCH_JOB, "No job queued for unit %s", old_name);
1654 return bus_send_error_reply(connection, message, &error, -ENOENT);
1658 mode = job_mode_from_string(smode);
1660 dbus_set_error(&error, BUS_ERROR_INVALID_JOB_MODE, "Job mode %s is invalid.", smode);
1661 return bus_send_error_reply(connection, message, &error, -EINVAL);
1664 r = manager_load_unit(m, name, NULL, &error, &u);
1666 return bus_send_error_reply(connection, message, &error, r);
1668 return bus_unit_queue_job(connection, message, u, job_type, mode, reload_if_possible);
1672 if (!dbus_connection_send(connection, reply, NULL))
1675 return DBUS_HANDLER_RESULT_HANDLED;
1678 dbus_error_free(&error);
1680 return DBUS_HANDLER_RESULT_NEED_MEMORY;
1683 const DBusObjectPathVTable bus_manager_vtable = {
1684 .message_function = bus_manager_message_handler