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=\"GetUnitControlGroupAttributes\">\n" \
106 " <arg name=\"name\" type=\"s\" direction=\"in\"/>\n" \
107 " <arg name=\"attributes\" type=\"as\" direction=\"in\"/>\n" \
108 " <arg name=\"values\" type=\"as\" direction=\"out\"/>\n" \
110 " <method name=\"SetUnitControlGroupAttributes\">\n" \
111 " <arg name=\"name\" type=\"s\" direction=\"in\"/>\n" \
112 " <arg name=\"attributes\" type=\"a(sss)\" direction=\"in\"/>\n" \
113 " <arg name=\"mode\" type=\"s\" direction=\"in\"\n/>" \
115 " <method name=\"UnsetUnitControlGroupAttributes\">\n" \
116 " <arg name=\"name\" type=\"s\" direction=\"in\"/>\n" \
117 " <arg name=\"attributes\" type=\"a(ss)\" direction=\"in\"/>\n" \
118 " <arg name=\"mode\" type=\"s\" direction=\"in\"/>\n" \
120 " <method name=\"SetUnitControlGroups\">\n" \
121 " <arg name=\"name\" type=\"s\" direction=\"in\"/>\n" \
122 " <arg name=\"groups\" type=\"as\" direction=\"in\"/>\n" \
123 " <arg name=\"mode\" type=\"s\" direction=\"in\"/>\n" \
125 " <method name=\"UnsetUnitControlGroups\">\n" \
126 " <arg name=\"name\" type=\"s\" direction=\"in\"/>\n" \
127 " <arg name=\"groups\" type=\"as\" direction=\"in\"/>\n" \
128 " <arg name=\"mode\" type=\"s\" direction=\"in\"\n/>" \
130 " <method name=\"GetJob\">\n" \
131 " <arg name=\"id\" type=\"u\" direction=\"in\"/>\n" \
132 " <arg name=\"job\" type=\"o\" direction=\"out\"/>\n" \
134 " <method name=\"CancelJob\">\n" \
135 " <arg name=\"id\" type=\"u\" direction=\"in\"/>\n" \
137 " <method name=\"ClearJobs\"/>\n" \
138 " <method name=\"ResetFailed\"/>\n" \
139 " <method name=\"ListUnits\">\n" \
140 " <arg name=\"units\" type=\"a(ssssssouso)\" direction=\"out\"/>\n" \
142 " <method name=\"ListJobs\">\n" \
143 " <arg name=\"jobs\" type=\"a(usssoo)\" direction=\"out\"/>\n" \
145 " <method name=\"Subscribe\"/>\n" \
146 " <method name=\"Unsubscribe\"/>\n" \
147 " <method name=\"Dump\">\n" \
148 " <arg name=\"dump\" type=\"s\" direction=\"out\"/>\n" \
150 " <method name=\"CreateSnapshot\">\n" \
151 " <arg name=\"name\" type=\"s\" direction=\"in\"/>\n" \
152 " <arg name=\"cleanup\" type=\"b\" direction=\"in\"/>\n" \
153 " <arg name=\"unit\" type=\"o\" direction=\"out\"/>\n" \
155 " <method name=\"RemoveSnapshot\">\n" \
156 " <arg name=\"name\" type=\"s\" direction=\"in\"/>\n" \
158 " <method name=\"Reload\"/>\n" \
159 " <method name=\"Reexecute\"/>\n" \
160 " <method name=\"Exit\"/>\n" \
161 " <method name=\"Reboot\"/>\n" \
162 " <method name=\"PowerOff\"/>\n" \
163 " <method name=\"Halt\"/>\n" \
164 " <method name=\"KExec\"/>\n" \
165 " <method name=\"SwitchRoot\">\n" \
166 " <arg name=\"new_root\" type=\"s\" direction=\"in\"/>\n" \
167 " <arg name=\"init\" type=\"s\" direction=\"in\"/>\n" \
169 " <method name=\"SetEnvironment\">\n" \
170 " <arg name=\"names\" type=\"as\" direction=\"in\"/>\n" \
172 " <method name=\"UnsetEnvironment\">\n" \
173 " <arg name=\"names\" type=\"as\" direction=\"in\"/>\n" \
175 " <method name=\"UnsetAndSetEnvironment\">\n" \
176 " <arg name=\"unset\" type=\"as\" direction=\"in\"/>\n" \
177 " <arg name=\"set\" type=\"as\" direction=\"in\"/>\n" \
179 " <method name=\"ListUnitFiles\">\n" \
180 " <arg name=\"files\" type=\"a(ss)\" direction=\"out\"/>\n" \
182 " <method name=\"GetUnitFileState\">\n" \
183 " <arg name=\"file\" type=\"s\" direction=\"in\"/>\n" \
184 " <arg name=\"state\" type=\"s\" direction=\"out\"/>\n" \
186 " <method name=\"EnableUnitFiles\">\n" \
187 " <arg name=\"files\" type=\"as\" direction=\"in\"/>\n" \
188 " <arg name=\"runtime\" type=\"b\" direction=\"in\"/>\n" \
189 " <arg name=\"force\" type=\"b\" direction=\"in\"/>\n" \
190 " <arg name=\"carries_install_info\" type=\"b\" direction=\"out\"/>\n" \
191 " <arg name=\"changes\" type=\"a(sss)\" direction=\"out\"/>\n" \
193 " <method name=\"DisableUnitFiles\">\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" \
198 " <method name=\"ReenableUnitFiles\">\n" \
199 " <arg name=\"files\" type=\"as\" direction=\"in\"/>\n" \
200 " <arg name=\"runtime\" type=\"b\" direction=\"in\"/>\n" \
201 " <arg name=\"force\" type=\"b\" direction=\"in\"/>\n" \
202 " <arg name=\"carries_install_info\" type=\"b\" direction=\"out\"/>\n" \
203 " <arg name=\"changes\" type=\"a(sss)\" direction=\"out\"/>\n" \
205 " <method name=\"LinkUnitFiles\">\n" \
206 " <arg name=\"files\" type=\"as\" direction=\"in\"/>\n" \
207 " <arg name=\"runtime\" type=\"b\" direction=\"in\"/>\n" \
208 " <arg name=\"force\" type=\"b\" direction=\"in\"/>\n" \
209 " <arg name=\"changes\" type=\"a(sss)\" direction=\"out\"/>\n" \
211 " <method name=\"PresetUnitFiles\">\n" \
212 " <arg name=\"files\" type=\"as\" direction=\"in\"/>\n" \
213 " <arg name=\"runtime\" type=\"b\" direction=\"in\"/>\n" \
214 " <arg name=\"force\" type=\"b\" direction=\"in\"/>\n" \
215 " <arg name=\"carries_install_info\" type=\"b\" direction=\"out\"/>\n" \
216 " <arg name=\"changes\" type=\"a(sss)\" direction=\"out\"/>\n" \
218 " <method name=\"MaskUnitFiles\">\n" \
219 " <arg name=\"files\" type=\"as\" direction=\"in\"/>\n" \
220 " <arg name=\"runtime\" type=\"b\" direction=\"in\"/>\n" \
221 " <arg name=\"force\" type=\"b\" direction=\"in\"/>\n" \
222 " <arg name=\"changes\" type=\"a(sss)\" direction=\"out\"/>\n" \
224 " <method name=\"UnmaskUnitFiles\">\n" \
225 " <arg name=\"files\" type=\"as\" direction=\"in\"/>\n" \
226 " <arg name=\"runtime\" type=\"b\" direction=\"in\"/>\n" \
227 " <arg name=\"changes\" type=\"a(sss)\" direction=\"out\"/>\n" \
230 #define BUS_MANAGER_INTERFACE_SIGNALS \
231 " <signal name=\"UnitNew\">\n" \
232 " <arg name=\"id\" type=\"s\"/>\n" \
233 " <arg name=\"unit\" type=\"o\"/>\n" \
235 " <signal name=\"UnitRemoved\">\n" \
236 " <arg name=\"id\" type=\"s\"/>\n" \
237 " <arg name=\"unit\" type=\"o\"/>\n" \
239 " <signal name=\"JobNew\">\n" \
240 " <arg name=\"id\" type=\"u\"/>\n" \
241 " <arg name=\"job\" type=\"o\"/>\n" \
242 " <arg name=\"unit\" type=\"s\"/>\n" \
244 " <signal name=\"JobRemoved\">\n" \
245 " <arg name=\"id\" type=\"u\"/>\n" \
246 " <arg name=\"job\" type=\"o\"/>\n" \
247 " <arg name=\"unit\" type=\"s\"/>\n" \
248 " <arg name=\"result\" type=\"s\"/>\n" \
250 " <signal name=\"StartupFinished\">\n" \
251 " <arg name=\"firmware\" type=\"t\"/>\n" \
252 " <arg name=\"loader\" type=\"t\"/>\n" \
253 " <arg name=\"kernel\" type=\"t\"/>\n" \
254 " <arg name=\"initrd\" type=\"t\"/>\n" \
255 " <arg name=\"userspace\" type=\"t\"/>\n" \
256 " <arg name=\"total\" type=\"t\"/>\n" \
258 " <signal name=\"UnitFilesChanged\"/>\n"
260 #define BUS_MANAGER_INTERFACE_PROPERTIES_GENERAL \
261 " <property name=\"Version\" type=\"s\" access=\"read\"/>\n" \
262 " <property name=\"Features\" type=\"s\" access=\"read\"/>\n" \
263 " <property name=\"Tainted\" type=\"s\" access=\"read\"/>\n" \
264 " <property name=\"FirmwareTimestamp\" type=\"t\" access=\"read\"/>\n" \
265 " <property name=\"FirmwareTimestampMonotonic\" type=\"t\" access=\"read\"/>\n" \
266 " <property name=\"LoaderTimestamp\" type=\"t\" access=\"read\"/>\n" \
267 " <property name=\"LoaderTimestampMonotonic\" type=\"t\" access=\"read\"/>\n" \
268 " <property name=\"KernelTimestamp\" type=\"t\" access=\"read\"/>\n" \
269 " <property name=\"KernelTimestampMonotonic\" type=\"t\" access=\"read\"/>\n" \
270 " <property name=\"InitRDTimestamp\" type=\"t\" access=\"read\"/>\n" \
271 " <property name=\"InitRDTimestampMonotonic\" type=\"t\" access=\"read\"/>\n" \
272 " <property name=\"UserspaceTimestamp\" type=\"t\" access=\"read\"/>\n" \
273 " <property name=\"UserspaceTimestampMonotonic\" type=\"t\" access=\"read\"/>\n" \
274 " <property name=\"FinishTimestamp\" type=\"t\" access=\"read\"/>\n" \
275 " <property name=\"FinishTimestampMonotonic\" type=\"t\" access=\"read\"/>\n" \
276 " <property name=\"LogLevel\" type=\"s\" access=\"readwrite\"/>\n" \
277 " <property name=\"LogTarget\" type=\"s\" access=\"readwrite\"/>\n" \
278 " <property name=\"NNames\" type=\"u\" access=\"read\"/>\n" \
279 " <property name=\"NJobs\" type=\"u\" access=\"read\"/>\n" \
280 " <property name=\"NInstalledJobs\" type=\"u\" access=\"read\"/>\n" \
281 " <property name=\"NFailedJobs\" type=\"u\" access=\"read\"/>\n" \
282 " <property name=\"Progress\" type=\"d\" access=\"read\"/>\n" \
283 " <property name=\"Environment\" type=\"as\" access=\"read\"/>\n" \
284 " <property name=\"ConfirmSpawn\" type=\"b\" access=\"read\"/>\n" \
285 " <property name=\"ShowStatus\" type=\"b\" access=\"read\"/>\n" \
286 " <property name=\"UnitPath\" type=\"as\" access=\"read\"/>\n" \
287 " <property name=\"ControlGroupHierarchy\" type=\"s\" access=\"read\"/>\n" \
288 " <property name=\"DefaultControllers\" type=\"as\" access=\"read\"/>\n" \
289 " <property name=\"DefaultStandardOutput\" type=\"s\" access=\"read\"/>\n" \
290 " <property name=\"DefaultStandardError\" type=\"s\" access=\"read\"/>\n" \
291 " <property name=\"RuntimeWatchdogUSec\" type=\"s\" access=\"readwrite\"/>\n" \
292 " <property name=\"ShutdownWatchdogUSec\" type=\"s\" access=\"readwrite\"/>\n" \
293 " <property name=\"Virtualization\" type=\"s\" access=\"read\"/>\n"
295 #define BUS_MANAGER_INTERFACE_END \
298 #define BUS_MANAGER_INTERFACE \
299 BUS_MANAGER_INTERFACE_BEGIN \
300 BUS_MANAGER_INTERFACE_METHODS \
301 BUS_MANAGER_INTERFACE_SIGNALS \
302 BUS_MANAGER_INTERFACE_PROPERTIES_GENERAL \
303 BUS_MANAGER_INTERFACE_END
305 #define INTROSPECTION_BEGIN \
306 DBUS_INTROSPECT_1_0_XML_DOCTYPE_DECL_NODE \
308 BUS_MANAGER_INTERFACE \
309 BUS_PROPERTIES_INTERFACE \
311 BUS_INTROSPECTABLE_INTERFACE
313 #define INTROSPECTION_END \
316 #define INTERFACES_LIST \
317 BUS_GENERIC_INTERFACES_LIST \
318 "org.freedesktop.systemd1.Manager\0"
320 const char bus_manager_interface[] _introspect_("Manager") = BUS_MANAGER_INTERFACE;
322 static DEFINE_BUS_PROPERTY_APPEND_ENUM(bus_manager_append_exec_output, exec_output, ExecOutput);
324 static int bus_manager_append_tainted(DBusMessageIter *i, const char *property, void *data) {
327 char buf[LINE_MAX] = "", *e = buf, *p = NULL;
334 e = stpcpy(e, "split-usr:");
336 if (readlink_malloc("/etc/mtab", &p) < 0)
337 e = stpcpy(e, "mtab-not-symlink:");
341 if (access("/proc/cgroups", F_OK) < 0)
342 e = stpcpy(e, "cgroups-missing:");
344 if (hwclock_is_localtime() > 0)
345 e = stpcpy(e, "local-hwclock:");
347 /* remove the last ':' */
353 if (!dbus_message_iter_append_basic(i, DBUS_TYPE_STRING, &t))
359 static int bus_manager_append_log_target(DBusMessageIter *i, const char *property, void *data) {
365 t = log_target_to_string(log_get_target());
367 if (!dbus_message_iter_append_basic(i, DBUS_TYPE_STRING, &t))
373 static int bus_manager_set_log_target(DBusMessageIter *i, const char *property, void *data) {
379 dbus_message_iter_get_basic(i, &t);
381 return log_set_target_from_string(t);
384 static int bus_manager_append_log_level(DBusMessageIter *i, const char *property, void *data) {
391 r = log_level_to_string_alloc(log_get_max_level(), &t);
395 if (!dbus_message_iter_append_basic(i, DBUS_TYPE_STRING, &t))
402 static int bus_manager_set_log_level(DBusMessageIter *i, const char *property, void *data) {
408 dbus_message_iter_get_basic(i, &t);
410 return log_set_max_level_from_string(t);
413 static int bus_manager_append_n_names(DBusMessageIter *i, const char *property, void *data) {
421 u = hashmap_size(m->units);
423 if (!dbus_message_iter_append_basic(i, DBUS_TYPE_UINT32, &u))
429 static int bus_manager_append_n_jobs(DBusMessageIter *i, const char *property, void *data) {
437 u = hashmap_size(m->jobs);
439 if (!dbus_message_iter_append_basic(i, DBUS_TYPE_UINT32, &u))
445 static int bus_manager_append_progress(DBusMessageIter *i, const char *property, void *data) {
453 if (dual_timestamp_is_set(&m->finish_timestamp))
456 d = 1.0 - ((double) hashmap_size(m->jobs) / (double) m->n_installed_jobs);
458 if (!dbus_message_iter_append_basic(i, DBUS_TYPE_DOUBLE, &d))
464 static int bus_manager_append_virt(DBusMessageIter *i, const char *property, void *data) {
472 detect_virtualization(&id);
474 if (!dbus_message_iter_append_basic(i, DBUS_TYPE_STRING, &id))
480 static DBusMessage *message_from_file_changes(
482 UnitFileChange *changes,
484 int carries_install_info) {
486 DBusMessageIter iter, sub, sub2;
490 reply = dbus_message_new_method_return(m);
494 dbus_message_iter_init_append(reply, &iter);
496 if (carries_install_info >= 0) {
499 b = !!carries_install_info;
500 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &b))
504 if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "(sss)", &sub))
507 for (i = 0; i < n_changes; i++) {
508 const char *type, *path, *source;
510 type = unit_file_change_type_to_string(changes[i].type);
511 path = strempty(changes[i].path);
512 source = strempty(changes[i].source);
514 if (!dbus_message_iter_open_container(&sub, DBUS_TYPE_STRUCT, NULL, &sub2) ||
515 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &type) ||
516 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &path) ||
517 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &source) ||
518 !dbus_message_iter_close_container(&sub, &sub2))
522 if (!dbus_message_iter_close_container(&iter, &sub))
528 dbus_message_unref(reply);
532 static int bus_manager_send_unit_files_changed(Manager *m) {
536 s = dbus_message_new_signal("/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", "UnitFilesChanged");
540 r = bus_broadcast(m, s);
541 dbus_message_unref(s);
546 static int bus_manager_set_runtime_watchdog_usec(DBusMessageIter *i, const char *property, void *data) {
552 dbus_message_iter_get_basic(i, t);
554 return watchdog_set_timeout(t);
557 static const char systemd_property_string[] =
561 static const BusProperty bus_systemd_properties[] = {
562 { "Version", bus_property_append_string, "s", 0 },
563 { "Features", bus_property_append_string, "s", sizeof(PACKAGE_STRING) },
567 static const BusProperty bus_manager_properties[] = {
568 { "Tainted", bus_manager_append_tainted, "s", 0 },
569 { "FirmwareTimestamp", bus_property_append_uint64, "t", offsetof(Manager, firmware_timestamp.realtime) },
570 { "FirmwareTimestampMonotonic", bus_property_append_uint64, "t", offsetof(Manager, firmware_timestamp.monotonic) },
571 { "LoaderTimestamp", bus_property_append_uint64, "t", offsetof(Manager, loader_timestamp.realtime) },
572 { "LoaderTimestampMonotonic", bus_property_append_uint64, "t", offsetof(Manager, loader_timestamp.monotonic) },
573 { "KernelTimestamp", bus_property_append_uint64, "t", offsetof(Manager, kernel_timestamp.realtime) },
574 { "KernelTimestampMonotonic", bus_property_append_uint64, "t", offsetof(Manager, kernel_timestamp.monotonic) },
575 { "InitRDTimestamp", bus_property_append_uint64, "t", offsetof(Manager, initrd_timestamp.realtime) },
576 { "InitRDTimestampMonotonic", bus_property_append_uint64, "t", offsetof(Manager, initrd_timestamp.monotonic) },
577 { "UserspaceTimestamp", bus_property_append_uint64, "t", offsetof(Manager, userspace_timestamp.realtime) },
578 { "UserspaceTimestampMonotonic", bus_property_append_uint64, "t", offsetof(Manager, userspace_timestamp.monotonic) },
579 { "FinishTimestamp", bus_property_append_uint64, "t", offsetof(Manager, finish_timestamp.realtime) },
580 { "FinishTimestampMonotonic", bus_property_append_uint64, "t", offsetof(Manager, finish_timestamp.monotonic) },
581 { "LogLevel", bus_manager_append_log_level, "s", 0, false, bus_manager_set_log_level },
582 { "LogTarget", bus_manager_append_log_target, "s", 0, false, bus_manager_set_log_target },
583 { "NNames", bus_manager_append_n_names, "u", 0 },
584 { "NJobs", bus_manager_append_n_jobs, "u", 0 },
585 { "NInstalledJobs", bus_property_append_uint32, "u", offsetof(Manager, n_installed_jobs) },
586 { "NFailedJobs", bus_property_append_uint32, "u", offsetof(Manager, n_failed_jobs) },
587 { "Progress", bus_manager_append_progress, "d", 0 },
588 { "Environment", bus_property_append_strv, "as", offsetof(Manager, environment), true },
589 { "ConfirmSpawn", bus_property_append_bool, "b", offsetof(Manager, confirm_spawn) },
590 { "ShowStatus", bus_property_append_bool, "b", offsetof(Manager, show_status) },
591 { "UnitPath", bus_property_append_strv, "as", offsetof(Manager, lookup_paths.unit_path), true },
592 { "ControlGroupHierarchy", bus_property_append_string, "s", offsetof(Manager, cgroup_hierarchy), true },
593 { "DefaultControllers", bus_property_append_strv, "as", offsetof(Manager, default_controllers), true },
594 { "DefaultStandardOutput", bus_manager_append_exec_output, "s", offsetof(Manager, default_std_output) },
595 { "DefaultStandardError", bus_manager_append_exec_output, "s", offsetof(Manager, default_std_error) },
596 { "RuntimeWatchdogUSec", bus_property_append_usec, "t", offsetof(Manager, runtime_watchdog), false, bus_manager_set_runtime_watchdog_usec },
597 { "ShutdownWatchdogUSec", bus_property_append_usec, "t", offsetof(Manager, shutdown_watchdog), false, bus_property_set_usec },
598 { "Virtualization", bus_manager_append_virt, "s", 0, },
602 static DBusHandlerResult bus_manager_message_handler(DBusConnection *connection, DBusMessage *message, void *data) {
603 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
604 _cleanup_free_ char * path = NULL;
608 JobType job_type = _JOB_TYPE_INVALID;
609 bool reload_if_possible = false;
616 dbus_error_init(&error);
618 member = dbus_message_get_member(message);
620 if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "GetUnit")) {
624 if (!dbus_message_get_args(
627 DBUS_TYPE_STRING, &name,
629 return bus_send_error_reply(connection, message, &error, -EINVAL);
631 u = manager_get_unit(m, name);
633 dbus_set_error(&error, BUS_ERROR_NO_SUCH_UNIT, "Unit %s is not loaded.", name);
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", "GetUnitByPID")) {
656 if (!dbus_message_get_args(
659 DBUS_TYPE_UINT32, &pid,
661 return bus_send_error_reply(connection, message, &error, -EINVAL);
663 u = cgroup_unit_by_pid(m, (pid_t) pid);
665 dbus_set_error(&error, BUS_ERROR_NO_SUCH_UNIT, "No unit for PID %lu is loaded.", (unsigned long) pid);
666 return bus_send_error_reply(connection, message, &error, -ENOENT);
669 SELINUX_UNIT_ACCESS_CHECK(u, connection, message, "status");
671 reply = dbus_message_new_method_return(message);
675 path = unit_dbus_path(u);
679 if (!dbus_message_append_args(
681 DBUS_TYPE_OBJECT_PATH, &path,
684 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "LoadUnit")) {
688 if (!dbus_message_get_args(
691 DBUS_TYPE_STRING, &name,
693 return bus_send_error_reply(connection, message, &error, -EINVAL);
695 r = manager_load_unit(m, name, NULL, &error, &u);
697 return bus_send_error_reply(connection, message, &error, r);
699 SELINUX_UNIT_ACCESS_CHECK(u, connection, message, "status");
701 reply = dbus_message_new_method_return(message);
705 path = unit_dbus_path(u);
709 if (!dbus_message_append_args(
711 DBUS_TYPE_OBJECT_PATH, &path,
715 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "StartUnit"))
716 job_type = JOB_START;
717 else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "StartUnitReplace"))
718 job_type = JOB_START;
719 else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "StopUnit"))
721 else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ReloadUnit"))
722 job_type = JOB_RELOAD;
723 else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "RestartUnit"))
724 job_type = JOB_RESTART;
725 else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "TryRestartUnit"))
726 job_type = JOB_TRY_RESTART;
727 else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ReloadOrRestartUnit")) {
728 reload_if_possible = true;
729 job_type = JOB_RESTART;
730 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ReloadOrTryRestartUnit")) {
731 reload_if_possible = true;
732 job_type = JOB_TRY_RESTART;
733 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "KillUnit")) {
734 const char *name, *swho;
739 if (!dbus_message_get_args(
742 DBUS_TYPE_STRING, &name,
743 DBUS_TYPE_STRING, &swho,
744 DBUS_TYPE_INT32, &signo,
746 return bus_send_error_reply(connection, message, &error, -EINVAL);
751 who = kill_who_from_string(swho);
753 return bus_send_error_reply(connection, message, &error, -EINVAL);
756 if (signo <= 0 || signo >= _NSIG)
757 return bus_send_error_reply(connection, message, &error, -EINVAL);
759 u = manager_get_unit(m, name);
761 dbus_set_error(&error, BUS_ERROR_NO_SUCH_UNIT, "Unit %s is not loaded.", name);
762 return bus_send_error_reply(connection, message, &error, -ENOENT);
765 SELINUX_UNIT_ACCESS_CHECK(u, connection, message, "stop");
767 r = unit_kill(u, who, signo, &error);
769 return bus_send_error_reply(connection, message, &error, r);
771 reply = dbus_message_new_method_return(message);
775 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "GetJob")) {
779 if (!dbus_message_get_args(
782 DBUS_TYPE_UINT32, &id,
784 return bus_send_error_reply(connection, message, &error, -EINVAL);
786 j = manager_get_job(m, id);
788 dbus_set_error(&error, BUS_ERROR_NO_SUCH_JOB, "Job %u does not exist.", (unsigned) id);
789 return bus_send_error_reply(connection, message, &error, -ENOENT);
792 SELINUX_UNIT_ACCESS_CHECK(j->unit, connection, message, "status");
794 reply = dbus_message_new_method_return(message);
798 path = job_dbus_path(j);
802 if (!dbus_message_append_args(
804 DBUS_TYPE_OBJECT_PATH, &path,
808 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "CancelJob")) {
812 if (!dbus_message_get_args(
815 DBUS_TYPE_UINT32, &id,
817 return bus_send_error_reply(connection, message, &error, -EINVAL);
819 j = manager_get_job(m, id);
821 dbus_set_error(&error, BUS_ERROR_NO_SUCH_JOB, "Job %u does not exist.", (unsigned) id);
822 return bus_send_error_reply(connection, message, &error, -ENOENT);
825 SELINUX_UNIT_ACCESS_CHECK(j->unit, connection, message, "stop");
826 job_finish_and_invalidate(j, JOB_CANCELED, true);
828 reply = dbus_message_new_method_return(message);
832 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ClearJobs")) {
834 SELINUX_ACCESS_CHECK(connection, message, "reboot");
835 manager_clear_jobs(m);
837 reply = dbus_message_new_method_return(message);
841 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ResetFailed")) {
843 SELINUX_ACCESS_CHECK(connection, message, "reload");
845 manager_reset_failed(m);
847 reply = dbus_message_new_method_return(message);
851 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ResetFailedUnit")) {
855 if (!dbus_message_get_args(
858 DBUS_TYPE_STRING, &name,
860 return bus_send_error_reply(connection, message, &error, -EINVAL);
862 u = manager_get_unit(m, name);
864 dbus_set_error(&error, BUS_ERROR_NO_SUCH_UNIT, "Unit %s is not loaded.", name);
865 return bus_send_error_reply(connection, message, &error, -ENOENT);
868 SELINUX_UNIT_ACCESS_CHECK(u, connection, message, "reload");
870 unit_reset_failed(u);
872 reply = dbus_message_new_method_return(message);
876 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "SetUnitControlGroups")) {
879 DBusMessageIter iter;
881 if (!dbus_message_iter_init(message, &iter))
884 r = bus_iter_get_basic_and_next(&iter, DBUS_TYPE_STRING, &name, true);
886 return bus_send_error_reply(connection, message, NULL, r);
888 u = manager_get_unit(m, name);
890 dbus_set_error(&error, BUS_ERROR_NO_SUCH_UNIT, "Unit %s is not loaded.", name);
891 return bus_send_error_reply(connection, message, &error, -ENOENT);
894 SELINUX_UNIT_ACCESS_CHECK(u, connection, message, "start");
896 r = bus_unit_cgroup_set(u, &iter);
898 return bus_send_error_reply(connection, message, NULL, r);
900 reply = dbus_message_new_method_return(message);
904 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "UnsetUnitControlGroups")) {
907 DBusMessageIter iter;
909 if (!dbus_message_iter_init(message, &iter))
912 r = bus_iter_get_basic_and_next(&iter, DBUS_TYPE_STRING, &name, true);
914 return bus_send_error_reply(connection, message, NULL, r);
916 u = manager_get_unit(m, name);
918 dbus_set_error(&error, BUS_ERROR_NO_SUCH_UNIT, "Unit %s is not loaded.", name);
919 return bus_send_error_reply(connection, message, &error, -ENOENT);
922 SELINUX_UNIT_ACCESS_CHECK(u, connection, message, "stop");
924 r = bus_unit_cgroup_unset(u, &iter);
926 return bus_send_error_reply(connection, message, NULL, r);
928 reply = dbus_message_new_method_return(message);
932 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "SetUnitControlGroupAttributes")) {
935 DBusMessageIter iter;
937 if (!dbus_message_iter_init(message, &iter))
940 r = bus_iter_get_basic_and_next(&iter, DBUS_TYPE_STRING, &name, true);
942 return bus_send_error_reply(connection, message, NULL, r);
944 u = manager_get_unit(m, name);
946 dbus_set_error(&error, BUS_ERROR_NO_SUCH_UNIT, "Unit %s is not loaded.", name);
947 return bus_send_error_reply(connection, message, &error, -ENOENT);
950 SELINUX_UNIT_ACCESS_CHECK(u, connection, message, "start");
951 r = bus_unit_cgroup_attribute_set(u, &iter);
953 return bus_send_error_reply(connection, message, NULL, r);
955 reply = dbus_message_new_method_return(message);
959 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "UnsetUnitControlGroupAttributes")) {
962 DBusMessageIter iter;
964 if (!dbus_message_iter_init(message, &iter))
967 r = bus_iter_get_basic_and_next(&iter, DBUS_TYPE_STRING, &name, true);
969 return bus_send_error_reply(connection, message, NULL, r);
971 u = manager_get_unit(m, name);
973 dbus_set_error(&error, BUS_ERROR_NO_SUCH_UNIT, "Unit %s is not loaded.", name);
974 return bus_send_error_reply(connection, message, &error, -ENOENT);
977 SELINUX_UNIT_ACCESS_CHECK(u, connection, message, "stop");
979 r = bus_unit_cgroup_attribute_unset(u, &iter);
981 return bus_send_error_reply(connection, message, NULL, r);
983 reply = dbus_message_new_method_return(message);
987 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "GetUnitControlGroupAttributes")) {
990 DBusMessageIter iter;
991 _cleanup_strv_free_ char **list = NULL;
993 if (!dbus_message_iter_init(message, &iter))
996 r = bus_iter_get_basic_and_next(&iter, DBUS_TYPE_STRING, &name, true);
998 return bus_send_error_reply(connection, message, NULL, r);
1000 u = manager_get_unit(m, name);
1002 dbus_set_error(&error, BUS_ERROR_NO_SUCH_UNIT, "Unit %s is not loaded.", name);
1003 return bus_send_error_reply(connection, message, &error, -ENOENT);
1006 SELINUX_UNIT_ACCESS_CHECK(u, connection, message, "status");
1007 r = bus_unit_cgroup_attribute_get(u, &iter, &list);
1009 return bus_send_error_reply(connection, message, NULL, r);
1011 reply = dbus_message_new_method_return(message);
1015 dbus_message_iter_init_append(reply, &iter);
1016 if (bus_append_strv_iter(&iter, list) < 0)
1019 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ListUnits")) {
1020 DBusMessageIter iter, sub;
1025 SELINUX_ACCESS_CHECK(connection, message, "status");
1027 reply = dbus_message_new_method_return(message);
1031 dbus_message_iter_init_append(reply, &iter);
1033 if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "(ssssssouso)", &sub))
1036 HASHMAP_FOREACH_KEY(u, k, m->units, i) {
1037 char *u_path, *j_path;
1038 const char *description, *load_state, *active_state, *sub_state, *sjob_type, *following;
1039 DBusMessageIter sub2;
1046 if (!dbus_message_iter_open_container(&sub, DBUS_TYPE_STRUCT, NULL, &sub2))
1049 description = unit_description(u);
1050 load_state = unit_load_state_to_string(u->load_state);
1051 active_state = unit_active_state_to_string(unit_active_state(u));
1052 sub_state = unit_sub_state_to_string(u);
1054 f = unit_following(u);
1055 following = f ? f->id : "";
1057 u_path = unit_dbus_path(u);
1062 job_id = (uint32_t) u->job->id;
1064 if (!(j_path = job_dbus_path(u->job))) {
1069 sjob_type = job_type_to_string(u->job->type);
1076 if (!dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &u->id) ||
1077 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &description) ||
1078 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &load_state) ||
1079 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &active_state) ||
1080 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &sub_state) ||
1081 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &following) ||
1082 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_OBJECT_PATH, &u_path) ||
1083 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_UINT32, &job_id) ||
1084 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &sjob_type) ||
1085 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_OBJECT_PATH, &j_path)) {
1096 if (!dbus_message_iter_close_container(&sub, &sub2))
1100 if (!dbus_message_iter_close_container(&iter, &sub))
1103 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ListJobs")) {
1104 DBusMessageIter iter, sub;
1108 SELINUX_ACCESS_CHECK(connection, message, "status");
1110 reply = dbus_message_new_method_return(message);
1114 dbus_message_iter_init_append(reply, &iter);
1116 if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "(usssoo)", &sub))
1119 HASHMAP_FOREACH(j, m->jobs, i) {
1120 char *u_path, *j_path;
1121 const char *state, *type;
1123 DBusMessageIter sub2;
1125 if (!dbus_message_iter_open_container(&sub, DBUS_TYPE_STRUCT, NULL, &sub2))
1128 id = (uint32_t) j->id;
1129 state = job_state_to_string(j->state);
1130 type = job_type_to_string(j->type);
1132 j_path = job_dbus_path(j);
1136 u_path = unit_dbus_path(j->unit);
1142 if (!dbus_message_iter_append_basic(&sub2, DBUS_TYPE_UINT32, &id) ||
1143 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &j->unit->id) ||
1144 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &type) ||
1145 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &state) ||
1146 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_OBJECT_PATH, &j_path) ||
1147 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_OBJECT_PATH, &u_path)) {
1156 if (!dbus_message_iter_close_container(&sub, &sub2))
1160 if (!dbus_message_iter_close_container(&iter, &sub))
1163 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "Subscribe")) {
1167 SELINUX_ACCESS_CHECK(connection, message, "status");
1169 s = BUS_CONNECTION_SUBSCRIBED(m, connection);
1171 s = set_new(string_hash_func, string_compare_func);
1175 if (!dbus_connection_set_data(connection, m->subscribed_data_slot, s, NULL)) {
1181 client = strdup(bus_message_get_sender_with_fallback(message));
1185 r = set_put(s, client);
1188 return bus_send_error_reply(connection, message, NULL, r);
1191 reply = dbus_message_new_method_return(message);
1195 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "Unsubscribe")) {
1198 SELINUX_ACCESS_CHECK(connection, message, "status");
1200 client = set_remove(BUS_CONNECTION_SUBSCRIBED(m, connection), (char*) bus_message_get_sender_with_fallback(message));
1202 dbus_set_error(&error, BUS_ERROR_NOT_SUBSCRIBED, "Client is not subscribed.");
1203 return bus_send_error_reply(connection, message, &error, -ENOENT);
1208 reply = dbus_message_new_method_return(message);
1212 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "Dump")) {
1217 SELINUX_ACCESS_CHECK(connection, message, "status");
1219 reply = dbus_message_new_method_return(message);
1223 f = open_memstream(&dump, &size);
1227 manager_dump_units(m, f, NULL);
1228 manager_dump_jobs(m, f, NULL);
1238 if (!dbus_message_append_args(reply, DBUS_TYPE_STRING, &dump, DBUS_TYPE_INVALID)) {
1244 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "CreateSnapshot")) {
1246 dbus_bool_t cleanup;
1249 SELINUX_ACCESS_CHECK(connection, message, "start");
1251 if (!dbus_message_get_args(
1254 DBUS_TYPE_STRING, &name,
1255 DBUS_TYPE_BOOLEAN, &cleanup,
1257 return bus_send_error_reply(connection, message, &error, -EINVAL);
1262 r = snapshot_create(m, name, cleanup, &error, &s);
1264 return bus_send_error_reply(connection, message, &error, r);
1266 reply = dbus_message_new_method_return(message);
1270 path = unit_dbus_path(UNIT(s));
1274 if (!dbus_message_append_args(
1276 DBUS_TYPE_OBJECT_PATH, &path,
1280 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "RemoveSnapshot")) {
1284 if (!dbus_message_get_args(
1287 DBUS_TYPE_STRING, &name,
1289 return bus_send_error_reply(connection, message, &error, -EINVAL);
1291 u = manager_get_unit(m, name);
1293 dbus_set_error(&error, BUS_ERROR_NO_SUCH_UNIT, "Unit %s does not exist.", name);
1294 return bus_send_error_reply(connection, message, &error, -ENOENT);
1297 if (u->type != UNIT_SNAPSHOT) {
1298 dbus_set_error(&error, BUS_ERROR_NO_SUCH_UNIT, "Unit %s is not a snapshot.", name);
1299 return bus_send_error_reply(connection, message, &error, -ENOENT);
1302 SELINUX_UNIT_ACCESS_CHECK(u, connection, message, "stop");
1303 snapshot_remove(SNAPSHOT(u));
1305 reply = dbus_message_new_method_return(message);
1309 } else if (dbus_message_is_method_call(message, "org.freedesktop.DBus.Introspectable", "Introspect")) {
1310 char *introspection = NULL;
1318 SELINUX_ACCESS_CHECK(connection, message, "status");
1320 reply = dbus_message_new_method_return(message);
1324 /* We roll our own introspection code here, instead of
1325 * relying on bus_default_message_handler() because we
1326 * need to generate our introspection string
1329 f = open_memstream(&introspection, &size);
1333 fputs(INTROSPECTION_BEGIN, f);
1335 HASHMAP_FOREACH_KEY(u, k, m->units, i) {
1341 p = bus_path_escape(k);
1344 free(introspection);
1348 fprintf(f, "<node name=\"unit/%s\"/>", p);
1352 HASHMAP_FOREACH(j, m->jobs, i)
1353 fprintf(f, "<node name=\"job/%lu\"/>", (unsigned long) j->id);
1355 fputs(INTROSPECTION_END, f);
1359 free(introspection);
1368 if (!dbus_message_append_args(reply, DBUS_TYPE_STRING, &introspection, DBUS_TYPE_INVALID)) {
1369 free(introspection);
1373 free(introspection);
1375 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "Reload")) {
1377 SELINUX_ACCESS_CHECK(connection, message, "reload");
1379 assert(!m->queued_message);
1381 /* Instead of sending the reply back right away, we
1382 * just remember that we need to and then send it
1383 * after the reload is finished. That way the caller
1384 * knows when the reload finished. */
1386 m->queued_message = dbus_message_new_method_return(message);
1387 if (!m->queued_message)
1390 m->queued_message_connection = connection;
1391 m->exit_code = MANAGER_RELOAD;
1393 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "Reexecute")) {
1395 SELINUX_ACCESS_CHECK(connection, message, "reload");
1397 /* We don't send a reply back here, the client should
1398 * just wait for us disconnecting. */
1400 m->exit_code = MANAGER_REEXECUTE;
1402 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "Exit")) {
1404 SELINUX_ACCESS_CHECK(connection, message, "halt");
1406 if (m->running_as == SYSTEMD_SYSTEM) {
1407 dbus_set_error(&error, BUS_ERROR_NOT_SUPPORTED, "Exit is only supported for user service managers.");
1408 return bus_send_error_reply(connection, message, &error, -ENOTSUP);
1411 reply = dbus_message_new_method_return(message);
1415 m->exit_code = MANAGER_EXIT;
1417 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "Reboot")) {
1419 SELINUX_ACCESS_CHECK(connection, message, "reboot");
1421 if (m->running_as != SYSTEMD_SYSTEM) {
1422 dbus_set_error(&error, BUS_ERROR_NOT_SUPPORTED, "Reboot is only supported for system managers.");
1423 return bus_send_error_reply(connection, message, &error, -ENOTSUP);
1426 reply = dbus_message_new_method_return(message);
1430 m->exit_code = MANAGER_REBOOT;
1432 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "PowerOff")) {
1434 SELINUX_ACCESS_CHECK(connection, message, "halt");
1436 if (m->running_as != SYSTEMD_SYSTEM) {
1437 dbus_set_error(&error, BUS_ERROR_NOT_SUPPORTED, "Powering off is only supported for system managers.");
1438 return bus_send_error_reply(connection, message, &error, -ENOTSUP);
1441 reply = dbus_message_new_method_return(message);
1445 m->exit_code = MANAGER_POWEROFF;
1447 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "Halt")) {
1449 SELINUX_ACCESS_CHECK(connection, message, "halt");
1451 if (m->running_as != SYSTEMD_SYSTEM) {
1452 dbus_set_error(&error, BUS_ERROR_NOT_SUPPORTED, "Halting is only supported for system managers.");
1453 return bus_send_error_reply(connection, message, &error, -ENOTSUP);
1456 reply = dbus_message_new_method_return(message);
1460 m->exit_code = MANAGER_HALT;
1462 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "KExec")) {
1464 SELINUX_ACCESS_CHECK(connection, message, "reboot");
1466 if (m->running_as != SYSTEMD_SYSTEM) {
1467 dbus_set_error(&error, BUS_ERROR_NOT_SUPPORTED, "kexec is only supported for system managers.");
1468 return bus_send_error_reply(connection, message, &error, -ENOTSUP);
1471 reply = dbus_message_new_method_return(message);
1475 m->exit_code = MANAGER_KEXEC;
1477 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "SwitchRoot")) {
1478 const char *switch_root, *switch_root_init;
1482 SELINUX_ACCESS_CHECK(connection, message, "reboot");
1484 if (!dbus_message_get_args(
1487 DBUS_TYPE_STRING, &switch_root,
1488 DBUS_TYPE_STRING, &switch_root_init,
1490 return bus_send_error_reply(connection, message, &error, -EINVAL);
1492 if (path_equal(switch_root, "/") || !path_is_absolute(switch_root))
1493 return bus_send_error_reply(connection, message, NULL, -EINVAL);
1495 if (!isempty(switch_root_init) && !path_is_absolute(switch_root_init))
1496 return bus_send_error_reply(connection, message, NULL, -EINVAL);
1498 if (m->running_as != SYSTEMD_SYSTEM) {
1499 dbus_set_error(&error, BUS_ERROR_NOT_SUPPORTED, "Switching root is only supported for system managers.");
1500 return bus_send_error_reply(connection, message, &error, -ENOTSUP);
1504 if (isempty(switch_root_init))
1505 k = access(switch_root, F_OK);
1509 p = strjoin(switch_root, "/", switch_root_init, NULL);
1513 k = access(p, X_OK);
1517 return bus_send_error_reply(connection, message, NULL, -errno);
1519 u = strdup(switch_root);
1523 if (!isempty(switch_root_init)) {
1524 v = strdup(switch_root_init);
1532 free(m->switch_root);
1533 free(m->switch_root_init);
1535 m->switch_root_init = v;
1537 reply = dbus_message_new_method_return(message);
1541 m->exit_code = MANAGER_SWITCH_ROOT;
1543 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "SetEnvironment")) {
1544 char **l = NULL, **e = NULL;
1546 SELINUX_ACCESS_CHECK(connection, message, "reboot");
1548 r = bus_parse_strv(message, &l);
1552 return bus_send_error_reply(connection, message, NULL, r);
1554 e = strv_env_merge(2, m->environment, l);
1559 reply = dbus_message_new_method_return(message);
1565 strv_free(m->environment);
1568 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "UnsetEnvironment")) {
1569 char **l = NULL, **e = NULL;
1571 SELINUX_ACCESS_CHECK(connection, message, "reboot");
1573 r = bus_parse_strv(message, &l);
1577 return bus_send_error_reply(connection, message, NULL, r);
1579 e = strv_env_delete(m->environment, 1, l);
1585 reply = dbus_message_new_method_return(message);
1591 strv_free(m->environment);
1594 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "UnsetAndSetEnvironment")) {
1595 char **l_set = NULL, **l_unset = NULL, **e = NULL, **f = NULL;
1596 DBusMessageIter iter;
1598 SELINUX_ACCESS_CHECK(connection, message, "reboot");
1600 if (!dbus_message_iter_init(message, &iter))
1603 r = bus_parse_strv_iter(&iter, &l_unset);
1607 return bus_send_error_reply(connection, message, NULL, r);
1609 if (!dbus_message_iter_next(&iter)) {
1611 return bus_send_error_reply(connection, message, NULL, -EINVAL);
1614 r = bus_parse_strv_iter(&iter, &l_set);
1620 return bus_send_error_reply(connection, message, NULL, r);
1623 e = strv_env_delete(m->environment, 1, l_unset);
1631 f = strv_env_merge(2, e, l_set);
1638 reply = dbus_message_new_method_return(message);
1644 strv_free(m->environment);
1646 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ListUnitFiles")) {
1647 DBusMessageIter iter, sub, sub2;
1652 SELINUX_ACCESS_CHECK(connection, message, "status");
1654 reply = dbus_message_new_method_return(message);
1658 h = hashmap_new(string_hash_func, string_compare_func);
1662 r = unit_file_get_list(m->running_as == SYSTEMD_SYSTEM ? UNIT_FILE_SYSTEM : UNIT_FILE_USER, NULL, h);
1664 unit_file_list_free(h);
1665 return bus_send_error_reply(connection, message, NULL, r);
1668 dbus_message_iter_init_append(reply, &iter);
1670 if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "(ss)", &sub)) {
1671 unit_file_list_free(h);
1675 HASHMAP_FOREACH(item, h, i) {
1678 state = unit_file_state_to_string(item->state);
1681 if (!dbus_message_iter_open_container(&sub, DBUS_TYPE_STRUCT, NULL, &sub2) ||
1682 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &item->path) ||
1683 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &state) ||
1684 !dbus_message_iter_close_container(&sub, &sub2)) {
1685 unit_file_list_free(h);
1690 unit_file_list_free(h);
1692 if (!dbus_message_iter_close_container(&iter, &sub))
1695 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "GetUnitFileState")) {
1697 UnitFileState state;
1700 SELINUX_ACCESS_CHECK(connection, message, "status");
1702 if (!dbus_message_get_args(
1705 DBUS_TYPE_STRING, &name,
1707 return bus_send_error_reply(connection, message, &error, -EINVAL);
1709 state = unit_file_get_state(m->running_as == SYSTEMD_SYSTEM ? UNIT_FILE_SYSTEM : UNIT_FILE_USER, NULL, name);
1711 return bus_send_error_reply(connection, message, NULL, state);
1713 s = unit_file_state_to_string(state);
1716 reply = dbus_message_new_method_return(message);
1720 if (!dbus_message_append_args(
1722 DBUS_TYPE_STRING, &s,
1725 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "EnableUnitFiles") ||
1726 dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ReenableUnitFiles") ||
1727 dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "LinkUnitFiles") ||
1728 dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "PresetUnitFiles") ||
1729 dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "MaskUnitFiles")) {
1732 DBusMessageIter iter;
1733 UnitFileScope scope = m->running_as == SYSTEMD_SYSTEM ? UNIT_FILE_SYSTEM : UNIT_FILE_USER;
1734 UnitFileChange *changes = NULL;
1735 unsigned n_changes = 0;
1736 dbus_bool_t runtime, force;
1737 int carries_install_info = -1;
1739 SELINUX_ACCESS_CHECK(connection, message, streq(member, "MaskUnitFiles") ? "disable" : "enable");
1741 if (!dbus_message_iter_init(message, &iter))
1744 r = bus_parse_strv_iter(&iter, &l);
1749 return bus_send_error_reply(connection, message, NULL, r);
1752 if (!dbus_message_iter_next(&iter) ||
1753 bus_iter_get_basic_and_next(&iter, DBUS_TYPE_BOOLEAN, &runtime, true) < 0 ||
1754 bus_iter_get_basic_and_next(&iter, DBUS_TYPE_BOOLEAN, &force, false) < 0) {
1756 return bus_send_error_reply(connection, message, NULL, -EIO);
1759 if (streq(member, "EnableUnitFiles")) {
1760 r = unit_file_enable(scope, runtime, NULL, l, force, &changes, &n_changes);
1761 carries_install_info = r;
1762 } else if (streq(member, "ReenableUnitFiles")) {
1763 r = unit_file_reenable(scope, runtime, NULL, l, force, &changes, &n_changes);
1764 carries_install_info = r;
1765 } else if (streq(member, "LinkUnitFiles"))
1766 r = unit_file_link(scope, runtime, NULL, l, force, &changes, &n_changes);
1767 else if (streq(member, "PresetUnitFiles")) {
1768 r = unit_file_preset(scope, runtime, NULL, l, force, &changes, &n_changes);
1769 carries_install_info = r;
1770 } else if (streq(member, "MaskUnitFiles"))
1771 r = unit_file_mask(scope, runtime, NULL, l, force, &changes, &n_changes);
1773 assert_not_reached("Uh? Wrong method");
1776 bus_manager_send_unit_files_changed(m);
1779 unit_file_changes_free(changes, n_changes);
1780 return bus_send_error_reply(connection, message, NULL, r);
1783 reply = message_from_file_changes(message, changes, n_changes, carries_install_info);
1784 unit_file_changes_free(changes, n_changes);
1789 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "DisableUnitFiles") ||
1790 dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "UnmaskUnitFiles")) {
1793 DBusMessageIter iter;
1794 UnitFileScope scope = m->running_as == SYSTEMD_SYSTEM ? UNIT_FILE_SYSTEM : UNIT_FILE_USER;
1795 UnitFileChange *changes = NULL;
1796 unsigned n_changes = 0;
1797 dbus_bool_t runtime;
1799 SELINUX_ACCESS_CHECK(connection, message, streq(member, "UnmaskUnitFiles") ? "enable" : "disable");
1801 if (!dbus_message_iter_init(message, &iter))
1804 r = bus_parse_strv_iter(&iter, &l);
1809 return bus_send_error_reply(connection, message, NULL, r);
1812 if (!dbus_message_iter_next(&iter) ||
1813 bus_iter_get_basic_and_next(&iter, DBUS_TYPE_BOOLEAN, &runtime, false) < 0) {
1815 return bus_send_error_reply(connection, message, NULL, -EIO);
1818 if (streq(member, "DisableUnitFiles"))
1819 r = unit_file_disable(scope, runtime, NULL, l, &changes, &n_changes);
1820 else if (streq(member, "UnmaskUnitFiles"))
1821 r = unit_file_unmask(scope, runtime, NULL, l, &changes, &n_changes);
1823 assert_not_reached("Uh? Wrong method");
1826 bus_manager_send_unit_files_changed(m);
1829 unit_file_changes_free(changes, n_changes);
1830 return bus_send_error_reply(connection, message, NULL, r);
1833 reply = message_from_file_changes(message, changes, n_changes, -1);
1834 unit_file_changes_free(changes, n_changes);
1840 const BusBoundProperties bps[] = {
1841 { "org.freedesktop.systemd1.Manager", bus_systemd_properties, systemd_property_string },
1842 { "org.freedesktop.systemd1.Manager", bus_manager_properties, m },
1846 SELINUX_ACCESS_CHECK(connection, message, "status");
1848 return bus_default_message_handler(connection, message, NULL, INTERFACES_LIST, bps);
1851 if (job_type != _JOB_TYPE_INVALID) {
1852 const char *name, *smode, *old_name = NULL;
1857 if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "StartUnitReplace"))
1858 b = dbus_message_get_args(
1861 DBUS_TYPE_STRING, &old_name,
1862 DBUS_TYPE_STRING, &name,
1863 DBUS_TYPE_STRING, &smode,
1866 b = dbus_message_get_args(
1869 DBUS_TYPE_STRING, &name,
1870 DBUS_TYPE_STRING, &smode,
1873 return bus_send_error_reply(connection, message, &error, -EINVAL);
1876 u = manager_get_unit(m, old_name);
1877 if (!u || !u->job || u->job->type != JOB_START) {
1878 dbus_set_error(&error, BUS_ERROR_NO_SUCH_JOB, "No job queued for unit %s", old_name);
1879 return bus_send_error_reply(connection, message, &error, -ENOENT);
1883 mode = job_mode_from_string(smode);
1885 dbus_set_error(&error, BUS_ERROR_INVALID_JOB_MODE, "Job mode %s is invalid.", smode);
1886 return bus_send_error_reply(connection, message, &error, -EINVAL);
1889 r = manager_load_unit(m, name, NULL, &error, &u);
1891 return bus_send_error_reply(connection, message, &error, r);
1893 return bus_unit_queue_job(connection, message, u, job_type, mode, reload_if_possible);
1897 if (!dbus_connection_send(connection, reply, NULL))
1900 return DBUS_HANDLER_RESULT_HANDLED;
1903 dbus_error_free(&error);
1905 return DBUS_HANDLER_RESULT_NEED_MEMORY;
1908 const DBusObjectPathVTable bus_manager_vtable = {
1909 .message_function = bus_manager_message_handler