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"
41 #define BUS_MANAGER_INTERFACE_BEGIN \
42 " <interface name=\"org.freedesktop.systemd1.Manager\">\n"
44 #define BUS_MANAGER_INTERFACE_METHODS \
45 " <method name=\"GetUnit\">\n" \
46 " <arg name=\"name\" type=\"s\" direction=\"in\"/>\n" \
47 " <arg name=\"unit\" type=\"o\" direction=\"out\"/>\n" \
49 " <method name=\"GetUnitByPID\">\n" \
50 " <arg name=\"pid\" type=\"u\" direction=\"in\"/>\n" \
51 " <arg name=\"unit\" type=\"o\" direction=\"out\"/>\n" \
53 " <method name=\"LoadUnit\">\n" \
54 " <arg name=\"name\" type=\"s\" direction=\"in\"/>\n" \
55 " <arg name=\"unit\" type=\"o\" direction=\"out\"/>\n" \
57 " <method name=\"StartUnit\">\n" \
58 " <arg name=\"name\" type=\"s\" direction=\"in\"/>\n" \
59 " <arg name=\"mode\" type=\"s\" direction=\"in\"/>\n" \
60 " <arg name=\"job\" type=\"o\" direction=\"out\"/>\n" \
62 " <method name=\"StartUnitReplace\">\n" \
63 " <arg name=\"old_unit\" type=\"s\" direction=\"in\"/>\n" \
64 " <arg name=\"new_unit\" type=\"s\" direction=\"in\"/>\n" \
65 " <arg name=\"mode\" type=\"s\" direction=\"in\"/>\n" \
66 " <arg name=\"job\" type=\"o\" direction=\"out\"/>\n" \
68 " <method name=\"StopUnit\">\n" \
69 " <arg name=\"name\" type=\"s\" direction=\"in\"/>\n" \
70 " <arg name=\"mode\" type=\"s\" direction=\"in\"/>\n" \
71 " <arg name=\"job\" type=\"o\" direction=\"out\"/>\n" \
73 " <method name=\"ReloadUnit\">\n" \
74 " <arg name=\"name\" type=\"s\" direction=\"in\"/>\n" \
75 " <arg name=\"mode\" type=\"s\" direction=\"in\"/>\n" \
76 " <arg name=\"job\" type=\"o\" direction=\"out\"/>\n" \
78 " <method name=\"RestartUnit\">\n" \
79 " <arg name=\"name\" type=\"s\" direction=\"in\"/>\n" \
80 " <arg name=\"mode\" type=\"s\" direction=\"in\"/>\n" \
81 " <arg name=\"job\" type=\"o\" direction=\"out\"/>\n" \
83 " <method name=\"TryRestartUnit\">\n" \
84 " <arg name=\"name\" type=\"s\" direction=\"in\"/>\n" \
85 " <arg name=\"mode\" type=\"s\" direction=\"in\"/>\n" \
86 " <arg name=\"job\" type=\"o\" direction=\"out\"/>\n" \
88 " <method name=\"ReloadOrRestartUnit\">\n" \
89 " <arg name=\"name\" type=\"s\" direction=\"in\"/>\n" \
90 " <arg name=\"mode\" type=\"s\" direction=\"in\"/>\n" \
91 " <arg name=\"job\" type=\"o\" direction=\"out\"/>\n" \
93 " <method name=\"ReloadOrTryRestartUnit\">\n" \
94 " <arg name=\"name\" type=\"s\" direction=\"in\"/>\n" \
95 " <arg name=\"mode\" type=\"s\" direction=\"in\"/>\n" \
96 " <arg name=\"job\" type=\"o\" direction=\"out\"/>\n" \
98 " <method name=\"KillUnit\">\n" \
99 " <arg name=\"name\" type=\"s\" direction=\"in\"/>\n" \
100 " <arg name=\"who\" type=\"s\" direction=\"in\"/>\n" \
101 " <arg name=\"signal\" type=\"i\" direction=\"in\"/>\n" \
103 " <method name=\"ResetFailedUnit\">\n" \
104 " <arg name=\"name\" type=\"s\" direction=\"in\"/>\n" \
106 " <method name=\"SetUnitControlGroup\">\n" \
107 " <arg name=\"name\" type=\"s\" direction=\"in\"/>\n" \
108 " <arg name=\"group\" type=\"s\" direction=\"in\"/>\n" \
109 " <arg name=\"mode\" type=\"s\" direction=\"in\"/>\n" \
111 " <method name=\"UnsetUnitControlGroup\">\n" \
112 " <arg name=\"name\" type=\"s\" direction=\"in\"/>\n" \
113 " <arg name=\"group\" type=\"s\" direction=\"in\"/>\n" \
114 " <arg name=\"mode\" type=\"s\" direction=\"in\"\n/>" \
116 " <method name=\"GetUnitControlGroupAttribute\">\n" \
117 " <arg name=\"name\" type=\"s\" direction=\"in\"/>\n" \
118 " <arg name=\"attribute\" type=\"s\" direction=\"in\"/>\n" \
119 " <arg name=\"values\" type=\"as\" direction=\"out\"/>\n" \
121 " <method name=\"SetUnitControlGroupAttribute\">\n" \
122 " <arg name=\"name\" type=\"s\" direction=\"in\"/>\n" \
123 " <arg name=\"attribute\" type=\"s\" direction=\"in\"/>\n" \
124 " <arg name=\"values\" type=\"as\" direction=\"in\"/>\n" \
125 " <arg name=\"mode\" type=\"s\" direction=\"in\"\n/>" \
127 " <method name=\"UnsetUnitControlGroupAttributes\">\n" \
128 " <arg name=\"name\" type=\"s\" direction=\"in\"/>\n" \
129 " <arg name=\"attribute\" type=\"s\" direction=\"in\"/>\n" \
130 " <arg name=\"mode\" type=\"s\" direction=\"in\"/>\n" \
132 " <method name=\"GetJob\">\n" \
133 " <arg name=\"id\" type=\"u\" direction=\"in\"/>\n" \
134 " <arg name=\"job\" type=\"o\" direction=\"out\"/>\n" \
136 " <method name=\"CancelJob\">\n" \
137 " <arg name=\"id\" type=\"u\" direction=\"in\"/>\n" \
139 " <method name=\"ClearJobs\"/>\n" \
140 " <method name=\"ResetFailed\"/>\n" \
141 " <method name=\"ListUnits\">\n" \
142 " <arg name=\"units\" type=\"a(ssssssouso)\" direction=\"out\"/>\n" \
144 " <method name=\"ListJobs\">\n" \
145 " <arg name=\"jobs\" type=\"a(usssoo)\" direction=\"out\"/>\n" \
147 " <method name=\"Subscribe\"/>\n" \
148 " <method name=\"Unsubscribe\"/>\n" \
149 " <method name=\"Dump\">\n" \
150 " <arg name=\"dump\" type=\"s\" direction=\"out\"/>\n" \
152 " <method name=\"CreateSnapshot\">\n" \
153 " <arg name=\"name\" type=\"s\" direction=\"in\"/>\n" \
154 " <arg name=\"cleanup\" type=\"b\" direction=\"in\"/>\n" \
155 " <arg name=\"unit\" type=\"o\" direction=\"out\"/>\n" \
157 " <method name=\"RemoveSnapshot\">\n" \
158 " <arg name=\"name\" type=\"s\" direction=\"in\"/>\n" \
160 " <method name=\"Reload\"/>\n" \
161 " <method name=\"Reexecute\"/>\n" \
162 " <method name=\"Exit\"/>\n" \
163 " <method name=\"Reboot\"/>\n" \
164 " <method name=\"PowerOff\"/>\n" \
165 " <method name=\"Halt\"/>\n" \
166 " <method name=\"KExec\"/>\n" \
167 " <method name=\"SwitchRoot\">\n" \
168 " <arg name=\"new_root\" type=\"s\" direction=\"in\"/>\n" \
169 " <arg name=\"init\" type=\"s\" direction=\"in\"/>\n" \
171 " <method name=\"SetEnvironment\">\n" \
172 " <arg name=\"names\" type=\"as\" direction=\"in\"/>\n" \
174 " <method name=\"UnsetEnvironment\">\n" \
175 " <arg name=\"names\" type=\"as\" direction=\"in\"/>\n" \
177 " <method name=\"UnsetAndSetEnvironment\">\n" \
178 " <arg name=\"unset\" type=\"as\" direction=\"in\"/>\n" \
179 " <arg name=\"set\" type=\"as\" direction=\"in\"/>\n" \
181 " <method name=\"ListUnitFiles\">\n" \
182 " <arg name=\"files\" type=\"a(ss)\" direction=\"out\"/>\n" \
184 " <method name=\"GetUnitFileState\">\n" \
185 " <arg name=\"file\" type=\"s\" direction=\"in\"/>\n" \
186 " <arg name=\"state\" type=\"s\" direction=\"out\"/>\n" \
188 " <method name=\"EnableUnitFiles\">\n" \
189 " <arg name=\"files\" type=\"as\" direction=\"in\"/>\n" \
190 " <arg name=\"runtime\" type=\"b\" direction=\"in\"/>\n" \
191 " <arg name=\"force\" type=\"b\" direction=\"in\"/>\n" \
192 " <arg name=\"carries_install_info\" type=\"b\" direction=\"out\"/>\n" \
193 " <arg name=\"changes\" type=\"a(sss)\" direction=\"out\"/>\n" \
195 " <method name=\"DisableUnitFiles\">\n" \
196 " <arg name=\"files\" type=\"as\" direction=\"in\"/>\n" \
197 " <arg name=\"runtime\" type=\"b\" direction=\"in\"/>\n" \
198 " <arg name=\"changes\" type=\"a(sss)\" direction=\"out\"/>\n" \
200 " <method name=\"ReenableUnitFiles\">\n" \
201 " <arg name=\"files\" type=\"as\" direction=\"in\"/>\n" \
202 " <arg name=\"runtime\" type=\"b\" direction=\"in\"/>\n" \
203 " <arg name=\"force\" type=\"b\" direction=\"in\"/>\n" \
204 " <arg name=\"carries_install_info\" type=\"b\" direction=\"out\"/>\n" \
205 " <arg name=\"changes\" type=\"a(sss)\" direction=\"out\"/>\n" \
207 " <method name=\"LinkUnitFiles\">\n" \
208 " <arg name=\"files\" type=\"as\" direction=\"in\"/>\n" \
209 " <arg name=\"runtime\" type=\"b\" direction=\"in\"/>\n" \
210 " <arg name=\"force\" type=\"b\" direction=\"in\"/>\n" \
211 " <arg name=\"changes\" type=\"a(sss)\" direction=\"out\"/>\n" \
213 " <method name=\"PresetUnitFiles\">\n" \
214 " <arg name=\"files\" type=\"as\" direction=\"in\"/>\n" \
215 " <arg name=\"runtime\" type=\"b\" direction=\"in\"/>\n" \
216 " <arg name=\"force\" type=\"b\" direction=\"in\"/>\n" \
217 " <arg name=\"carries_install_info\" type=\"b\" direction=\"out\"/>\n" \
218 " <arg name=\"changes\" type=\"a(sss)\" direction=\"out\"/>\n" \
220 " <method name=\"MaskUnitFiles\">\n" \
221 " <arg name=\"files\" type=\"as\" direction=\"in\"/>\n" \
222 " <arg name=\"runtime\" type=\"b\" direction=\"in\"/>\n" \
223 " <arg name=\"force\" type=\"b\" direction=\"in\"/>\n" \
224 " <arg name=\"changes\" type=\"a(sss)\" direction=\"out\"/>\n" \
226 " <method name=\"UnmaskUnitFiles\">\n" \
227 " <arg name=\"files\" type=\"as\" direction=\"in\"/>\n" \
228 " <arg name=\"runtime\" type=\"b\" direction=\"in\"/>\n" \
229 " <arg name=\"changes\" type=\"a(sss)\" direction=\"out\"/>\n" \
232 #define BUS_MANAGER_INTERFACE_SIGNALS \
233 " <signal name=\"UnitNew\">\n" \
234 " <arg name=\"id\" type=\"s\"/>\n" \
235 " <arg name=\"unit\" type=\"o\"/>\n" \
237 " <signal name=\"UnitRemoved\">\n" \
238 " <arg name=\"id\" type=\"s\"/>\n" \
239 " <arg name=\"unit\" type=\"o\"/>\n" \
241 " <signal name=\"JobNew\">\n" \
242 " <arg name=\"id\" type=\"u\"/>\n" \
243 " <arg name=\"job\" type=\"o\"/>\n" \
244 " <arg name=\"unit\" type=\"s\"/>\n" \
246 " <signal name=\"JobRemoved\">\n" \
247 " <arg name=\"id\" type=\"u\"/>\n" \
248 " <arg name=\"job\" type=\"o\"/>\n" \
249 " <arg name=\"unit\" type=\"s\"/>\n" \
250 " <arg name=\"result\" type=\"s\"/>\n" \
252 " <signal name=\"StartupFinished\">\n" \
253 " <arg name=\"firmware\" type=\"t\"/>\n" \
254 " <arg name=\"loader\" type=\"t\"/>\n" \
255 " <arg name=\"kernel\" type=\"t\"/>\n" \
256 " <arg name=\"initrd\" type=\"t\"/>\n" \
257 " <arg name=\"userspace\" type=\"t\"/>\n" \
258 " <arg name=\"total\" type=\"t\"/>\n" \
260 " <signal name=\"UnitFilesChanged\"/>\n"
262 #define BUS_MANAGER_INTERFACE_PROPERTIES_GENERAL \
263 " <property name=\"Version\" type=\"s\" access=\"read\"/>\n" \
264 " <property name=\"Features\" type=\"s\" access=\"read\"/>\n" \
265 " <property name=\"Tainted\" type=\"s\" access=\"read\"/>\n" \
266 " <property name=\"FirmwareTimestamp\" type=\"t\" access=\"read\"/>\n" \
267 " <property name=\"FirmwareTimestampMonotonic\" type=\"t\" access=\"read\"/>\n" \
268 " <property name=\"LoaderTimestamp\" type=\"t\" access=\"read\"/>\n" \
269 " <property name=\"LoaderTimestampMonotonic\" type=\"t\" access=\"read\"/>\n" \
270 " <property name=\"KernelTimestamp\" type=\"t\" access=\"read\"/>\n" \
271 " <property name=\"KernelTimestampMonotonic\" type=\"t\" access=\"read\"/>\n" \
272 " <property name=\"InitRDTimestamp\" type=\"t\" access=\"read\"/>\n" \
273 " <property name=\"InitRDTimestampMonotonic\" type=\"t\" access=\"read\"/>\n" \
274 " <property name=\"UserspaceTimestamp\" type=\"t\" access=\"read\"/>\n" \
275 " <property name=\"UserspaceTimestampMonotonic\" type=\"t\" access=\"read\"/>\n" \
276 " <property name=\"FinishTimestamp\" type=\"t\" access=\"read\"/>\n" \
277 " <property name=\"FinishTimestampMonotonic\" type=\"t\" access=\"read\"/>\n" \
278 " <property name=\"LogLevel\" type=\"s\" access=\"readwrite\"/>\n" \
279 " <property name=\"LogTarget\" type=\"s\" access=\"readwrite\"/>\n" \
280 " <property name=\"NNames\" type=\"u\" access=\"read\"/>\n" \
281 " <property name=\"NJobs\" type=\"u\" access=\"read\"/>\n" \
282 " <property name=\"NInstalledJobs\" type=\"u\" access=\"read\"/>\n" \
283 " <property name=\"NFailedJobs\" type=\"u\" access=\"read\"/>\n" \
284 " <property name=\"Progress\" type=\"d\" access=\"read\"/>\n" \
285 " <property name=\"Environment\" type=\"as\" access=\"read\"/>\n" \
286 " <property name=\"ConfirmSpawn\" type=\"b\" access=\"read\"/>\n" \
287 " <property name=\"ShowStatus\" type=\"b\" access=\"read\"/>\n" \
288 " <property name=\"UnitPath\" type=\"as\" access=\"read\"/>\n" \
289 " <property name=\"ControlGroupHierarchy\" type=\"s\" access=\"read\"/>\n" \
290 " <property name=\"DefaultControllers\" type=\"as\" access=\"read\"/>\n" \
291 " <property name=\"DefaultStandardOutput\" type=\"s\" access=\"read\"/>\n" \
292 " <property name=\"DefaultStandardError\" type=\"s\" access=\"read\"/>\n" \
293 " <property name=\"RuntimeWatchdogUSec\" type=\"t\" access=\"readwrite\"/>\n" \
294 " <property name=\"ShutdownWatchdogUSec\" type=\"t\" access=\"readwrite\"/>\n" \
295 " <property name=\"Virtualization\" type=\"s\" access=\"read\"/>\n"
297 #define BUS_MANAGER_INTERFACE_END \
300 #define BUS_MANAGER_INTERFACE \
301 BUS_MANAGER_INTERFACE_BEGIN \
302 BUS_MANAGER_INTERFACE_METHODS \
303 BUS_MANAGER_INTERFACE_SIGNALS \
304 BUS_MANAGER_INTERFACE_PROPERTIES_GENERAL \
305 BUS_MANAGER_INTERFACE_END
307 #define INTROSPECTION_BEGIN \
308 DBUS_INTROSPECT_1_0_XML_DOCTYPE_DECL_NODE \
310 BUS_MANAGER_INTERFACE \
311 BUS_PROPERTIES_INTERFACE \
313 BUS_INTROSPECTABLE_INTERFACE
315 #define INTROSPECTION_END \
318 #define INTERFACES_LIST \
319 BUS_GENERIC_INTERFACES_LIST \
320 "org.freedesktop.systemd1.Manager\0"
322 const char bus_manager_interface[] _introspect_("Manager") = BUS_MANAGER_INTERFACE;
324 static DEFINE_BUS_PROPERTY_APPEND_ENUM(bus_manager_append_exec_output, exec_output, ExecOutput);
326 static int bus_manager_append_tainted(DBusMessageIter *i, const char *property, void *data) {
329 char buf[LINE_MAX] = "", *e = buf, *p = NULL;
336 e = stpcpy(e, "split-usr:");
338 if (readlink_malloc("/etc/mtab", &p) < 0)
339 e = stpcpy(e, "mtab-not-symlink:");
343 if (access("/proc/cgroups", F_OK) < 0)
344 e = stpcpy(e, "cgroups-missing:");
346 if (hwclock_is_localtime() > 0)
347 e = stpcpy(e, "local-hwclock:");
349 /* remove the last ':' */
355 if (!dbus_message_iter_append_basic(i, DBUS_TYPE_STRING, &t))
361 static int bus_manager_append_log_target(DBusMessageIter *i, const char *property, void *data) {
367 t = log_target_to_string(log_get_target());
369 if (!dbus_message_iter_append_basic(i, DBUS_TYPE_STRING, &t))
375 static int bus_manager_set_log_target(DBusMessageIter *i, const char *property, void *data) {
381 dbus_message_iter_get_basic(i, &t);
383 return log_set_target_from_string(t);
386 static int bus_manager_append_log_level(DBusMessageIter *i, const char *property, void *data) {
393 r = log_level_to_string_alloc(log_get_max_level(), &t);
397 if (!dbus_message_iter_append_basic(i, DBUS_TYPE_STRING, &t))
404 static int bus_manager_set_log_level(DBusMessageIter *i, const char *property, void *data) {
410 dbus_message_iter_get_basic(i, &t);
412 return log_set_max_level_from_string(t);
415 static int bus_manager_append_n_names(DBusMessageIter *i, const char *property, void *data) {
423 u = hashmap_size(m->units);
425 if (!dbus_message_iter_append_basic(i, DBUS_TYPE_UINT32, &u))
431 static int bus_manager_append_n_jobs(DBusMessageIter *i, const char *property, void *data) {
439 u = hashmap_size(m->jobs);
441 if (!dbus_message_iter_append_basic(i, DBUS_TYPE_UINT32, &u))
447 static int bus_manager_append_progress(DBusMessageIter *i, const char *property, void *data) {
455 if (dual_timestamp_is_set(&m->finish_timestamp))
458 d = 1.0 - ((double) hashmap_size(m->jobs) / (double) m->n_installed_jobs);
460 if (!dbus_message_iter_append_basic(i, DBUS_TYPE_DOUBLE, &d))
466 static int bus_manager_append_virt(DBusMessageIter *i, const char *property, void *data) {
474 detect_virtualization(&id);
476 if (!dbus_message_iter_append_basic(i, DBUS_TYPE_STRING, &id))
482 static DBusMessage *message_from_file_changes(
484 UnitFileChange *changes,
486 int carries_install_info) {
488 DBusMessageIter iter, sub, sub2;
492 reply = dbus_message_new_method_return(m);
496 dbus_message_iter_init_append(reply, &iter);
498 if (carries_install_info >= 0) {
501 b = !!carries_install_info;
502 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &b))
506 if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "(sss)", &sub))
509 for (i = 0; i < n_changes; i++) {
510 const char *type, *path, *source;
512 type = unit_file_change_type_to_string(changes[i].type);
513 path = strempty(changes[i].path);
514 source = strempty(changes[i].source);
516 if (!dbus_message_iter_open_container(&sub, DBUS_TYPE_STRUCT, NULL, &sub2) ||
517 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &type) ||
518 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &path) ||
519 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &source) ||
520 !dbus_message_iter_close_container(&sub, &sub2))
524 if (!dbus_message_iter_close_container(&iter, &sub))
530 dbus_message_unref(reply);
534 static int bus_manager_send_unit_files_changed(Manager *m) {
538 s = dbus_message_new_signal("/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", "UnitFilesChanged");
542 r = bus_broadcast(m, s);
543 dbus_message_unref(s);
548 static int bus_manager_set_runtime_watchdog_usec(DBusMessageIter *i, const char *property, void *data) {
554 dbus_message_iter_get_basic(i, t);
556 return watchdog_set_timeout(t);
559 static const char systemd_property_string[] =
563 static const BusProperty bus_systemd_properties[] = {
564 { "Version", bus_property_append_string, "s", 0 },
565 { "Features", bus_property_append_string, "s", sizeof(PACKAGE_STRING) },
569 static const BusProperty bus_manager_properties[] = {
570 { "Tainted", bus_manager_append_tainted, "s", 0 },
571 { "FirmwareTimestamp", bus_property_append_uint64, "t", offsetof(Manager, firmware_timestamp.realtime) },
572 { "FirmwareTimestampMonotonic", bus_property_append_uint64, "t", offsetof(Manager, firmware_timestamp.monotonic) },
573 { "LoaderTimestamp", bus_property_append_uint64, "t", offsetof(Manager, loader_timestamp.realtime) },
574 { "LoaderTimestampMonotonic", bus_property_append_uint64, "t", offsetof(Manager, loader_timestamp.monotonic) },
575 { "KernelTimestamp", bus_property_append_uint64, "t", offsetof(Manager, kernel_timestamp.realtime) },
576 { "KernelTimestampMonotonic", bus_property_append_uint64, "t", offsetof(Manager, kernel_timestamp.monotonic) },
577 { "InitRDTimestamp", bus_property_append_uint64, "t", offsetof(Manager, initrd_timestamp.realtime) },
578 { "InitRDTimestampMonotonic", bus_property_append_uint64, "t", offsetof(Manager, initrd_timestamp.monotonic) },
579 { "UserspaceTimestamp", bus_property_append_uint64, "t", offsetof(Manager, userspace_timestamp.realtime) },
580 { "UserspaceTimestampMonotonic", bus_property_append_uint64, "t", offsetof(Manager, userspace_timestamp.monotonic) },
581 { "FinishTimestamp", bus_property_append_uint64, "t", offsetof(Manager, finish_timestamp.realtime) },
582 { "FinishTimestampMonotonic", bus_property_append_uint64, "t", offsetof(Manager, finish_timestamp.monotonic) },
583 { "LogLevel", bus_manager_append_log_level, "s", 0, false, bus_manager_set_log_level },
584 { "LogTarget", bus_manager_append_log_target, "s", 0, false, bus_manager_set_log_target },
585 { "NNames", bus_manager_append_n_names, "u", 0 },
586 { "NJobs", bus_manager_append_n_jobs, "u", 0 },
587 { "NInstalledJobs", bus_property_append_uint32, "u", offsetof(Manager, n_installed_jobs) },
588 { "NFailedJobs", bus_property_append_uint32, "u", offsetof(Manager, n_failed_jobs) },
589 { "Progress", bus_manager_append_progress, "d", 0 },
590 { "Environment", bus_property_append_strv, "as", offsetof(Manager, environment), true },
591 { "ConfirmSpawn", bus_property_append_bool, "b", offsetof(Manager, confirm_spawn) },
592 { "ShowStatus", bus_property_append_bool, "b", offsetof(Manager, show_status) },
593 { "UnitPath", bus_property_append_strv, "as", offsetof(Manager, lookup_paths.unit_path), true },
594 { "ControlGroupHierarchy", bus_property_append_string, "s", offsetof(Manager, cgroup_hierarchy), true },
595 { "DefaultControllers", bus_property_append_strv, "as", offsetof(Manager, default_controllers), true },
596 { "DefaultStandardOutput", bus_manager_append_exec_output, "s", offsetof(Manager, default_std_output) },
597 { "DefaultStandardError", bus_manager_append_exec_output, "s", offsetof(Manager, default_std_error) },
598 { "RuntimeWatchdogUSec", bus_property_append_usec, "t", offsetof(Manager, runtime_watchdog), false, bus_manager_set_runtime_watchdog_usec },
599 { "ShutdownWatchdogUSec", bus_property_append_usec, "t", offsetof(Manager, shutdown_watchdog), false, bus_property_set_usec },
600 { "Virtualization", bus_manager_append_virt, "s", 0, },
604 static DBusHandlerResult bus_manager_message_handler(DBusConnection *connection, DBusMessage *message, void *data) {
605 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
606 _cleanup_free_ char * path = NULL;
610 JobType job_type = _JOB_TYPE_INVALID;
611 bool reload_if_possible = false;
618 dbus_error_init(&error);
620 member = dbus_message_get_member(message);
622 if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "GetUnit")) {
626 if (!dbus_message_get_args(
629 DBUS_TYPE_STRING, &name,
631 return bus_send_error_reply(connection, message, &error, -EINVAL);
633 u = manager_get_unit(m, name);
635 dbus_set_error(&error, BUS_ERROR_NO_SUCH_UNIT, "Unit %s is not loaded.", name);
636 return bus_send_error_reply(connection, message, &error, -ENOENT);
639 SELINUX_UNIT_ACCESS_CHECK(u, connection, message, "status");
641 reply = dbus_message_new_method_return(message);
645 path = unit_dbus_path(u);
649 if (!dbus_message_append_args(
651 DBUS_TYPE_OBJECT_PATH, &path,
654 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "GetUnitByPID")) {
658 if (!dbus_message_get_args(
661 DBUS_TYPE_UINT32, &pid,
663 return bus_send_error_reply(connection, message, &error, -EINVAL);
665 u = cgroup_unit_by_pid(m, (pid_t) pid);
667 dbus_set_error(&error, BUS_ERROR_NO_SUCH_UNIT, "No unit for PID %lu is loaded.", (unsigned long) pid);
668 return bus_send_error_reply(connection, message, &error, -ENOENT);
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,
686 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "LoadUnit")) {
690 if (!dbus_message_get_args(
693 DBUS_TYPE_STRING, &name,
695 return bus_send_error_reply(connection, message, &error, -EINVAL);
697 r = manager_load_unit(m, name, NULL, &error, &u);
699 return bus_send_error_reply(connection, message, &error, r);
701 SELINUX_UNIT_ACCESS_CHECK(u, connection, message, "status");
703 reply = dbus_message_new_method_return(message);
707 path = unit_dbus_path(u);
711 if (!dbus_message_append_args(
713 DBUS_TYPE_OBJECT_PATH, &path,
717 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "StartUnit"))
718 job_type = JOB_START;
719 else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "StartUnitReplace"))
720 job_type = JOB_START;
721 else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "StopUnit"))
723 else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ReloadUnit"))
724 job_type = JOB_RELOAD;
725 else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "RestartUnit"))
726 job_type = JOB_RESTART;
727 else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "TryRestartUnit"))
728 job_type = JOB_TRY_RESTART;
729 else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ReloadOrRestartUnit")) {
730 reload_if_possible = true;
731 job_type = JOB_RESTART;
732 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ReloadOrTryRestartUnit")) {
733 reload_if_possible = true;
734 job_type = JOB_TRY_RESTART;
735 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "KillUnit")) {
736 const char *name, *swho;
741 if (!dbus_message_get_args(
744 DBUS_TYPE_STRING, &name,
745 DBUS_TYPE_STRING, &swho,
746 DBUS_TYPE_INT32, &signo,
748 return bus_send_error_reply(connection, message, &error, -EINVAL);
753 who = kill_who_from_string(swho);
755 return bus_send_error_reply(connection, message, &error, -EINVAL);
758 if (signo <= 0 || signo >= _NSIG)
759 return bus_send_error_reply(connection, message, &error, -EINVAL);
761 u = manager_get_unit(m, name);
763 dbus_set_error(&error, BUS_ERROR_NO_SUCH_UNIT, "Unit %s is not loaded.", name);
764 return bus_send_error_reply(connection, message, &error, -ENOENT);
767 SELINUX_UNIT_ACCESS_CHECK(u, connection, message, "stop");
769 r = unit_kill(u, who, signo, &error);
771 return bus_send_error_reply(connection, message, &error, r);
773 reply = dbus_message_new_method_return(message);
777 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "GetJob")) {
781 if (!dbus_message_get_args(
784 DBUS_TYPE_UINT32, &id,
786 return bus_send_error_reply(connection, message, &error, -EINVAL);
788 j = manager_get_job(m, id);
790 dbus_set_error(&error, BUS_ERROR_NO_SUCH_JOB, "Job %u does not exist.", (unsigned) id);
791 return bus_send_error_reply(connection, message, &error, -ENOENT);
794 SELINUX_UNIT_ACCESS_CHECK(j->unit, connection, message, "status");
796 reply = dbus_message_new_method_return(message);
800 path = job_dbus_path(j);
804 if (!dbus_message_append_args(
806 DBUS_TYPE_OBJECT_PATH, &path,
810 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "CancelJob")) {
814 if (!dbus_message_get_args(
817 DBUS_TYPE_UINT32, &id,
819 return bus_send_error_reply(connection, message, &error, -EINVAL);
821 j = manager_get_job(m, id);
823 dbus_set_error(&error, BUS_ERROR_NO_SUCH_JOB, "Job %u does not exist.", (unsigned) id);
824 return bus_send_error_reply(connection, message, &error, -ENOENT);
827 SELINUX_UNIT_ACCESS_CHECK(j->unit, connection, message, "stop");
828 job_finish_and_invalidate(j, JOB_CANCELED, true);
830 reply = dbus_message_new_method_return(message);
834 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ClearJobs")) {
836 SELINUX_ACCESS_CHECK(connection, message, "reboot");
837 manager_clear_jobs(m);
839 reply = dbus_message_new_method_return(message);
843 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ResetFailed")) {
845 SELINUX_ACCESS_CHECK(connection, message, "reload");
847 manager_reset_failed(m);
849 reply = dbus_message_new_method_return(message);
853 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ResetFailedUnit")) {
857 if (!dbus_message_get_args(
860 DBUS_TYPE_STRING, &name,
862 return bus_send_error_reply(connection, message, &error, -EINVAL);
864 u = manager_get_unit(m, name);
866 dbus_set_error(&error, BUS_ERROR_NO_SUCH_UNIT, "Unit %s is not loaded.", name);
867 return bus_send_error_reply(connection, message, &error, -ENOENT);
870 SELINUX_UNIT_ACCESS_CHECK(u, connection, message, "reload");
872 unit_reset_failed(u);
874 reply = dbus_message_new_method_return(message);
878 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "SetUnitControlGroup")) {
881 DBusMessageIter iter;
883 if (!dbus_message_iter_init(message, &iter))
886 r = bus_iter_get_basic_and_next(&iter, DBUS_TYPE_STRING, &name, true);
888 return bus_send_error_reply(connection, message, NULL, r);
890 u = manager_get_unit(m, name);
892 dbus_set_error(&error, BUS_ERROR_NO_SUCH_UNIT, "Unit %s is not loaded.", name);
893 return bus_send_error_reply(connection, message, &error, -ENOENT);
896 SELINUX_UNIT_ACCESS_CHECK(u, connection, message, "start");
898 r = bus_unit_cgroup_set(u, &iter);
900 return bus_send_error_reply(connection, message, NULL, r);
902 reply = dbus_message_new_method_return(message);
906 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "UnsetUnitControlGroup")) {
909 DBusMessageIter iter;
911 if (!dbus_message_iter_init(message, &iter))
914 r = bus_iter_get_basic_and_next(&iter, DBUS_TYPE_STRING, &name, true);
916 return bus_send_error_reply(connection, message, NULL, r);
918 u = manager_get_unit(m, name);
920 dbus_set_error(&error, BUS_ERROR_NO_SUCH_UNIT, "Unit %s is not loaded.", name);
921 return bus_send_error_reply(connection, message, &error, -ENOENT);
924 SELINUX_UNIT_ACCESS_CHECK(u, connection, message, "stop");
926 r = bus_unit_cgroup_unset(u, &iter);
928 return bus_send_error_reply(connection, message, NULL, r);
930 reply = dbus_message_new_method_return(message);
934 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "SetUnitControlGroupAttribute")) {
937 DBusMessageIter iter;
939 if (!dbus_message_iter_init(message, &iter))
942 r = bus_iter_get_basic_and_next(&iter, DBUS_TYPE_STRING, &name, true);
944 return bus_send_error_reply(connection, message, NULL, r);
946 u = manager_get_unit(m, name);
948 dbus_set_error(&error, BUS_ERROR_NO_SUCH_UNIT, "Unit %s is not loaded.", name);
949 return bus_send_error_reply(connection, message, &error, -ENOENT);
952 SELINUX_UNIT_ACCESS_CHECK(u, connection, message, "start");
954 r = bus_unit_cgroup_attribute_set(u, &iter);
956 return bus_send_error_reply(connection, message, NULL, r);
958 reply = dbus_message_new_method_return(message);
962 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "UnsetUnitControlGroupAttribute")) {
965 DBusMessageIter iter;
967 if (!dbus_message_iter_init(message, &iter))
970 r = bus_iter_get_basic_and_next(&iter, DBUS_TYPE_STRING, &name, true);
972 return bus_send_error_reply(connection, message, NULL, r);
974 u = manager_get_unit(m, name);
976 dbus_set_error(&error, BUS_ERROR_NO_SUCH_UNIT, "Unit %s is not loaded.", name);
977 return bus_send_error_reply(connection, message, &error, -ENOENT);
980 SELINUX_UNIT_ACCESS_CHECK(u, connection, message, "stop");
982 r = bus_unit_cgroup_attribute_unset(u, &iter);
984 return bus_send_error_reply(connection, message, NULL, r);
986 reply = dbus_message_new_method_return(message);
990 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "GetUnitControlGroupAttribute")) {
993 DBusMessageIter iter;
994 _cleanup_strv_free_ char **list = NULL;
996 if (!dbus_message_iter_init(message, &iter))
999 r = bus_iter_get_basic_and_next(&iter, DBUS_TYPE_STRING, &name, true);
1001 return bus_send_error_reply(connection, message, NULL, r);
1003 u = manager_get_unit(m, name);
1005 dbus_set_error(&error, BUS_ERROR_NO_SUCH_UNIT, "Unit %s is not loaded.", name);
1006 return bus_send_error_reply(connection, message, &error, -ENOENT);
1009 SELINUX_UNIT_ACCESS_CHECK(u, connection, message, "status");
1011 r = bus_unit_cgroup_attribute_get(u, &iter, &list);
1013 return bus_send_error_reply(connection, message, NULL, r);
1015 reply = dbus_message_new_method_return(message);
1019 dbus_message_iter_init_append(reply, &iter);
1020 if (bus_append_strv_iter(&iter, list) < 0)
1023 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ListUnits")) {
1024 DBusMessageIter iter, sub;
1029 SELINUX_ACCESS_CHECK(connection, message, "status");
1031 reply = dbus_message_new_method_return(message);
1035 dbus_message_iter_init_append(reply, &iter);
1037 if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "(ssssssouso)", &sub))
1040 HASHMAP_FOREACH_KEY(u, k, m->units, i) {
1041 char *u_path, *j_path;
1042 const char *description, *load_state, *active_state, *sub_state, *sjob_type, *following;
1043 DBusMessageIter sub2;
1050 if (!dbus_message_iter_open_container(&sub, DBUS_TYPE_STRUCT, NULL, &sub2))
1053 description = unit_description(u);
1054 load_state = unit_load_state_to_string(u->load_state);
1055 active_state = unit_active_state_to_string(unit_active_state(u));
1056 sub_state = unit_sub_state_to_string(u);
1058 f = unit_following(u);
1059 following = f ? f->id : "";
1061 u_path = unit_dbus_path(u);
1066 job_id = (uint32_t) u->job->id;
1068 if (!(j_path = job_dbus_path(u->job))) {
1073 sjob_type = job_type_to_string(u->job->type);
1080 if (!dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &u->id) ||
1081 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &description) ||
1082 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &load_state) ||
1083 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &active_state) ||
1084 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &sub_state) ||
1085 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &following) ||
1086 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_OBJECT_PATH, &u_path) ||
1087 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_UINT32, &job_id) ||
1088 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &sjob_type) ||
1089 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_OBJECT_PATH, &j_path)) {
1100 if (!dbus_message_iter_close_container(&sub, &sub2))
1104 if (!dbus_message_iter_close_container(&iter, &sub))
1107 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ListJobs")) {
1108 DBusMessageIter iter, sub;
1112 SELINUX_ACCESS_CHECK(connection, message, "status");
1114 reply = dbus_message_new_method_return(message);
1118 dbus_message_iter_init_append(reply, &iter);
1120 if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "(usssoo)", &sub))
1123 HASHMAP_FOREACH(j, m->jobs, i) {
1124 char *u_path, *j_path;
1125 const char *state, *type;
1127 DBusMessageIter sub2;
1129 if (!dbus_message_iter_open_container(&sub, DBUS_TYPE_STRUCT, NULL, &sub2))
1132 id = (uint32_t) j->id;
1133 state = job_state_to_string(j->state);
1134 type = job_type_to_string(j->type);
1136 j_path = job_dbus_path(j);
1140 u_path = unit_dbus_path(j->unit);
1146 if (!dbus_message_iter_append_basic(&sub2, DBUS_TYPE_UINT32, &id) ||
1147 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &j->unit->id) ||
1148 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &type) ||
1149 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &state) ||
1150 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_OBJECT_PATH, &j_path) ||
1151 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_OBJECT_PATH, &u_path)) {
1160 if (!dbus_message_iter_close_container(&sub, &sub2))
1164 if (!dbus_message_iter_close_container(&iter, &sub))
1167 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "Subscribe")) {
1171 SELINUX_ACCESS_CHECK(connection, message, "status");
1173 s = BUS_CONNECTION_SUBSCRIBED(m, connection);
1175 s = set_new(string_hash_func, string_compare_func);
1179 if (!dbus_connection_set_data(connection, m->subscribed_data_slot, s, NULL)) {
1185 client = strdup(bus_message_get_sender_with_fallback(message));
1189 r = set_put(s, client);
1192 return bus_send_error_reply(connection, message, NULL, r);
1195 reply = dbus_message_new_method_return(message);
1199 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "Unsubscribe")) {
1202 SELINUX_ACCESS_CHECK(connection, message, "status");
1204 client = set_remove(BUS_CONNECTION_SUBSCRIBED(m, connection), (char*) bus_message_get_sender_with_fallback(message));
1206 dbus_set_error(&error, BUS_ERROR_NOT_SUBSCRIBED, "Client is not subscribed.");
1207 return bus_send_error_reply(connection, message, &error, -ENOENT);
1212 reply = dbus_message_new_method_return(message);
1216 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "Dump")) {
1221 SELINUX_ACCESS_CHECK(connection, message, "status");
1223 reply = dbus_message_new_method_return(message);
1227 f = open_memstream(&dump, &size);
1231 manager_dump_units(m, f, NULL);
1232 manager_dump_jobs(m, f, NULL);
1242 if (!dbus_message_append_args(reply, DBUS_TYPE_STRING, &dump, DBUS_TYPE_INVALID)) {
1248 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "CreateSnapshot")) {
1250 dbus_bool_t cleanup;
1253 SELINUX_ACCESS_CHECK(connection, message, "start");
1255 if (!dbus_message_get_args(
1258 DBUS_TYPE_STRING, &name,
1259 DBUS_TYPE_BOOLEAN, &cleanup,
1261 return bus_send_error_reply(connection, message, &error, -EINVAL);
1266 r = snapshot_create(m, name, cleanup, &error, &s);
1268 return bus_send_error_reply(connection, message, &error, r);
1270 reply = dbus_message_new_method_return(message);
1274 path = unit_dbus_path(UNIT(s));
1278 if (!dbus_message_append_args(
1280 DBUS_TYPE_OBJECT_PATH, &path,
1284 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "RemoveSnapshot")) {
1288 if (!dbus_message_get_args(
1291 DBUS_TYPE_STRING, &name,
1293 return bus_send_error_reply(connection, message, &error, -EINVAL);
1295 u = manager_get_unit(m, name);
1297 dbus_set_error(&error, BUS_ERROR_NO_SUCH_UNIT, "Unit %s does not exist.", name);
1298 return bus_send_error_reply(connection, message, &error, -ENOENT);
1301 if (u->type != UNIT_SNAPSHOT) {
1302 dbus_set_error(&error, BUS_ERROR_NO_SUCH_UNIT, "Unit %s is not a snapshot.", name);
1303 return bus_send_error_reply(connection, message, &error, -ENOENT);
1306 SELINUX_UNIT_ACCESS_CHECK(u, connection, message, "stop");
1307 snapshot_remove(SNAPSHOT(u));
1309 reply = dbus_message_new_method_return(message);
1313 } else if (dbus_message_is_method_call(message, "org.freedesktop.DBus.Introspectable", "Introspect")) {
1314 char *introspection = NULL;
1322 SELINUX_ACCESS_CHECK(connection, message, "status");
1324 reply = dbus_message_new_method_return(message);
1328 /* We roll our own introspection code here, instead of
1329 * relying on bus_default_message_handler() because we
1330 * need to generate our introspection string
1333 f = open_memstream(&introspection, &size);
1337 fputs(INTROSPECTION_BEGIN, f);
1339 HASHMAP_FOREACH_KEY(u, k, m->units, i) {
1345 p = bus_path_escape(k);
1348 free(introspection);
1352 fprintf(f, "<node name=\"unit/%s\"/>", p);
1356 HASHMAP_FOREACH(j, m->jobs, i)
1357 fprintf(f, "<node name=\"job/%lu\"/>", (unsigned long) j->id);
1359 fputs(INTROSPECTION_END, f);
1363 free(introspection);
1372 if (!dbus_message_append_args(reply, DBUS_TYPE_STRING, &introspection, DBUS_TYPE_INVALID)) {
1373 free(introspection);
1377 free(introspection);
1379 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "Reload")) {
1381 SELINUX_ACCESS_CHECK(connection, message, "reload");
1383 assert(!m->queued_message);
1385 /* Instead of sending the reply back right away, we
1386 * just remember that we need to and then send it
1387 * after the reload is finished. That way the caller
1388 * knows when the reload finished. */
1390 m->queued_message = dbus_message_new_method_return(message);
1391 if (!m->queued_message)
1394 m->queued_message_connection = connection;
1395 m->exit_code = MANAGER_RELOAD;
1397 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "Reexecute")) {
1399 SELINUX_ACCESS_CHECK(connection, message, "reload");
1401 /* We don't send a reply back here, the client should
1402 * just wait for us disconnecting. */
1404 m->exit_code = MANAGER_REEXECUTE;
1406 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "Exit")) {
1408 SELINUX_ACCESS_CHECK(connection, message, "halt");
1410 if (m->running_as == SYSTEMD_SYSTEM) {
1411 dbus_set_error(&error, BUS_ERROR_NOT_SUPPORTED, "Exit is only supported for user service managers.");
1412 return bus_send_error_reply(connection, message, &error, -ENOTSUP);
1415 reply = dbus_message_new_method_return(message);
1419 m->exit_code = MANAGER_EXIT;
1421 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "Reboot")) {
1423 SELINUX_ACCESS_CHECK(connection, message, "reboot");
1425 if (m->running_as != SYSTEMD_SYSTEM) {
1426 dbus_set_error(&error, BUS_ERROR_NOT_SUPPORTED, "Reboot is only supported for system managers.");
1427 return bus_send_error_reply(connection, message, &error, -ENOTSUP);
1430 reply = dbus_message_new_method_return(message);
1434 m->exit_code = MANAGER_REBOOT;
1436 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "PowerOff")) {
1438 SELINUX_ACCESS_CHECK(connection, message, "halt");
1440 if (m->running_as != SYSTEMD_SYSTEM) {
1441 dbus_set_error(&error, BUS_ERROR_NOT_SUPPORTED, "Powering off is only supported for system managers.");
1442 return bus_send_error_reply(connection, message, &error, -ENOTSUP);
1445 reply = dbus_message_new_method_return(message);
1449 m->exit_code = MANAGER_POWEROFF;
1451 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "Halt")) {
1453 SELINUX_ACCESS_CHECK(connection, message, "halt");
1455 if (m->running_as != SYSTEMD_SYSTEM) {
1456 dbus_set_error(&error, BUS_ERROR_NOT_SUPPORTED, "Halting is only supported for system managers.");
1457 return bus_send_error_reply(connection, message, &error, -ENOTSUP);
1460 reply = dbus_message_new_method_return(message);
1464 m->exit_code = MANAGER_HALT;
1466 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "KExec")) {
1468 SELINUX_ACCESS_CHECK(connection, message, "reboot");
1470 if (m->running_as != SYSTEMD_SYSTEM) {
1471 dbus_set_error(&error, BUS_ERROR_NOT_SUPPORTED, "kexec is only supported for system managers.");
1472 return bus_send_error_reply(connection, message, &error, -ENOTSUP);
1475 reply = dbus_message_new_method_return(message);
1479 m->exit_code = MANAGER_KEXEC;
1481 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "SwitchRoot")) {
1482 const char *switch_root, *switch_root_init;
1486 SELINUX_ACCESS_CHECK(connection, message, "reboot");
1488 if (!dbus_message_get_args(
1491 DBUS_TYPE_STRING, &switch_root,
1492 DBUS_TYPE_STRING, &switch_root_init,
1494 return bus_send_error_reply(connection, message, &error, -EINVAL);
1496 if (path_equal(switch_root, "/") || !path_is_absolute(switch_root))
1497 return bus_send_error_reply(connection, message, NULL, -EINVAL);
1499 if (!isempty(switch_root_init) && !path_is_absolute(switch_root_init))
1500 return bus_send_error_reply(connection, message, NULL, -EINVAL);
1502 if (m->running_as != SYSTEMD_SYSTEM) {
1503 dbus_set_error(&error, BUS_ERROR_NOT_SUPPORTED, "Switching root is only supported for system managers.");
1504 return bus_send_error_reply(connection, message, &error, -ENOTSUP);
1508 if (isempty(switch_root_init))
1509 good = path_is_os_tree(switch_root);
1511 _cleanup_free_ char *p = NULL;
1513 p = strjoin(switch_root, "/", switch_root_init, NULL);
1517 good = access(p, X_OK) >= 0;
1520 return bus_send_error_reply(connection, message, NULL, -EINVAL);
1522 u = strdup(switch_root);
1526 if (!isempty(switch_root_init)) {
1527 v = strdup(switch_root_init);
1535 free(m->switch_root);
1536 free(m->switch_root_init);
1538 m->switch_root_init = v;
1540 reply = dbus_message_new_method_return(message);
1544 m->exit_code = MANAGER_SWITCH_ROOT;
1546 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "SetEnvironment")) {
1547 _cleanup_strv_free_ char **l = NULL;
1550 SELINUX_ACCESS_CHECK(connection, message, "reboot");
1552 r = bus_parse_strv(message, &l);
1556 return bus_send_error_reply(connection, message, NULL, r);
1557 if (!strv_env_is_valid(l))
1558 return bus_send_error_reply(connection, message, NULL, -EINVAL);
1560 e = strv_env_merge(2, m->environment, l);
1564 reply = dbus_message_new_method_return(message);
1570 strv_free(m->environment);
1573 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "UnsetEnvironment")) {
1574 _cleanup_strv_free_ char **l = NULL;
1577 SELINUX_ACCESS_CHECK(connection, message, "reboot");
1579 r = bus_parse_strv(message, &l);
1583 return bus_send_error_reply(connection, message, NULL, r);
1584 if (!strv_env_name_or_assignment_is_valid(l))
1585 return bus_send_error_reply(connection, message, NULL, -EINVAL);
1587 e = strv_env_delete(m->environment, 1, l);
1591 reply = dbus_message_new_method_return(message);
1597 strv_free(m->environment);
1600 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "UnsetAndSetEnvironment")) {
1601 _cleanup_strv_free_ char **l_set = NULL, **l_unset = NULL, **e = NULL;
1603 DBusMessageIter iter;
1605 SELINUX_ACCESS_CHECK(connection, message, "reboot");
1607 if (!dbus_message_iter_init(message, &iter))
1610 r = bus_parse_strv_iter(&iter, &l_unset);
1614 return bus_send_error_reply(connection, message, NULL, r);
1615 if (!strv_env_name_or_assignment_is_valid(l_unset))
1616 return bus_send_error_reply(connection, message, NULL, -EINVAL);
1618 if (!dbus_message_iter_next(&iter))
1619 return bus_send_error_reply(connection, message, NULL, -EINVAL);
1621 r = bus_parse_strv_iter(&iter, &l_set);
1625 return bus_send_error_reply(connection, message, NULL, r);
1626 if (!strv_env_is_valid(l_set))
1627 return bus_send_error_reply(connection, message, NULL, -EINVAL);
1629 e = strv_env_delete(m->environment, 1, l_unset);
1633 f = strv_env_merge(2, e, l_set);
1637 reply = dbus_message_new_method_return(message);
1643 strv_free(m->environment);
1645 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ListUnitFiles")) {
1646 DBusMessageIter iter, sub, sub2;
1651 SELINUX_ACCESS_CHECK(connection, message, "status");
1653 reply = dbus_message_new_method_return(message);
1657 h = hashmap_new(string_hash_func, string_compare_func);
1661 r = unit_file_get_list(m->running_as == SYSTEMD_SYSTEM ? UNIT_FILE_SYSTEM : UNIT_FILE_USER, NULL, h);
1663 unit_file_list_free(h);
1664 return bus_send_error_reply(connection, message, NULL, r);
1667 dbus_message_iter_init_append(reply, &iter);
1669 if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "(ss)", &sub)) {
1670 unit_file_list_free(h);
1674 HASHMAP_FOREACH(item, h, i) {
1677 state = unit_file_state_to_string(item->state);
1680 if (!dbus_message_iter_open_container(&sub, DBUS_TYPE_STRUCT, NULL, &sub2) ||
1681 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &item->path) ||
1682 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &state) ||
1683 !dbus_message_iter_close_container(&sub, &sub2)) {
1684 unit_file_list_free(h);
1689 unit_file_list_free(h);
1691 if (!dbus_message_iter_close_container(&iter, &sub))
1694 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "GetUnitFileState")) {
1696 UnitFileState state;
1699 SELINUX_ACCESS_CHECK(connection, message, "status");
1701 if (!dbus_message_get_args(
1704 DBUS_TYPE_STRING, &name,
1706 return bus_send_error_reply(connection, message, &error, -EINVAL);
1708 state = unit_file_get_state(m->running_as == SYSTEMD_SYSTEM ? UNIT_FILE_SYSTEM : UNIT_FILE_USER, NULL, name);
1710 return bus_send_error_reply(connection, message, NULL, state);
1712 s = unit_file_state_to_string(state);
1715 reply = dbus_message_new_method_return(message);
1719 if (!dbus_message_append_args(
1721 DBUS_TYPE_STRING, &s,
1724 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "EnableUnitFiles") ||
1725 dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ReenableUnitFiles") ||
1726 dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "LinkUnitFiles") ||
1727 dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "PresetUnitFiles") ||
1728 dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "MaskUnitFiles")) {
1731 DBusMessageIter iter;
1732 UnitFileScope scope = m->running_as == SYSTEMD_SYSTEM ? UNIT_FILE_SYSTEM : UNIT_FILE_USER;
1733 UnitFileChange *changes = NULL;
1734 unsigned n_changes = 0;
1735 dbus_bool_t runtime, force;
1736 int carries_install_info = -1;
1738 SELINUX_ACCESS_CHECK(connection, message, streq(member, "MaskUnitFiles") ? "disable" : "enable");
1740 if (!dbus_message_iter_init(message, &iter))
1743 r = bus_parse_strv_iter(&iter, &l);
1748 return bus_send_error_reply(connection, message, NULL, r);
1751 if (!dbus_message_iter_next(&iter) ||
1752 bus_iter_get_basic_and_next(&iter, DBUS_TYPE_BOOLEAN, &runtime, true) < 0 ||
1753 bus_iter_get_basic_and_next(&iter, DBUS_TYPE_BOOLEAN, &force, false) < 0) {
1755 return bus_send_error_reply(connection, message, NULL, -EIO);
1758 if (streq(member, "EnableUnitFiles")) {
1759 r = unit_file_enable(scope, runtime, NULL, l, force, &changes, &n_changes);
1760 carries_install_info = r;
1761 } else if (streq(member, "ReenableUnitFiles")) {
1762 r = unit_file_reenable(scope, runtime, NULL, l, force, &changes, &n_changes);
1763 carries_install_info = r;
1764 } else if (streq(member, "LinkUnitFiles"))
1765 r = unit_file_link(scope, runtime, NULL, l, force, &changes, &n_changes);
1766 else if (streq(member, "PresetUnitFiles")) {
1767 r = unit_file_preset(scope, runtime, NULL, l, force, &changes, &n_changes);
1768 carries_install_info = r;
1769 } else if (streq(member, "MaskUnitFiles"))
1770 r = unit_file_mask(scope, runtime, NULL, l, force, &changes, &n_changes);
1772 assert_not_reached("Uh? Wrong method");
1775 bus_manager_send_unit_files_changed(m);
1778 unit_file_changes_free(changes, n_changes);
1779 return bus_send_error_reply(connection, message, NULL, r);
1782 reply = message_from_file_changes(message, changes, n_changes, carries_install_info);
1783 unit_file_changes_free(changes, n_changes);
1788 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "DisableUnitFiles") ||
1789 dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "UnmaskUnitFiles")) {
1792 DBusMessageIter iter;
1793 UnitFileScope scope = m->running_as == SYSTEMD_SYSTEM ? UNIT_FILE_SYSTEM : UNIT_FILE_USER;
1794 UnitFileChange *changes = NULL;
1795 unsigned n_changes = 0;
1796 dbus_bool_t runtime;
1798 SELINUX_ACCESS_CHECK(connection, message, streq(member, "UnmaskUnitFiles") ? "enable" : "disable");
1800 if (!dbus_message_iter_init(message, &iter))
1803 r = bus_parse_strv_iter(&iter, &l);
1808 return bus_send_error_reply(connection, message, NULL, r);
1811 if (!dbus_message_iter_next(&iter) ||
1812 bus_iter_get_basic_and_next(&iter, DBUS_TYPE_BOOLEAN, &runtime, false) < 0) {
1814 return bus_send_error_reply(connection, message, NULL, -EIO);
1817 if (streq(member, "DisableUnitFiles"))
1818 r = unit_file_disable(scope, runtime, NULL, l, &changes, &n_changes);
1819 else if (streq(member, "UnmaskUnitFiles"))
1820 r = unit_file_unmask(scope, runtime, NULL, l, &changes, &n_changes);
1822 assert_not_reached("Uh? Wrong method");
1825 bus_manager_send_unit_files_changed(m);
1828 unit_file_changes_free(changes, n_changes);
1829 return bus_send_error_reply(connection, message, NULL, r);
1832 reply = message_from_file_changes(message, changes, n_changes, -1);
1833 unit_file_changes_free(changes, n_changes);
1839 const BusBoundProperties bps[] = {
1840 { "org.freedesktop.systemd1.Manager", bus_systemd_properties, systemd_property_string },
1841 { "org.freedesktop.systemd1.Manager", bus_manager_properties, m },
1845 SELINUX_ACCESS_CHECK(connection, message, "status");
1847 return bus_default_message_handler(connection, message, NULL, INTERFACES_LIST, bps);
1850 if (job_type != _JOB_TYPE_INVALID) {
1851 const char *name, *smode, *old_name = NULL;
1856 if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "StartUnitReplace"))
1857 b = dbus_message_get_args(
1860 DBUS_TYPE_STRING, &old_name,
1861 DBUS_TYPE_STRING, &name,
1862 DBUS_TYPE_STRING, &smode,
1865 b = dbus_message_get_args(
1868 DBUS_TYPE_STRING, &name,
1869 DBUS_TYPE_STRING, &smode,
1872 return bus_send_error_reply(connection, message, &error, -EINVAL);
1875 u = manager_get_unit(m, old_name);
1876 if (!u || !u->job || u->job->type != JOB_START) {
1877 dbus_set_error(&error, BUS_ERROR_NO_SUCH_JOB, "No job queued for unit %s", old_name);
1878 return bus_send_error_reply(connection, message, &error, -ENOENT);
1882 mode = job_mode_from_string(smode);
1884 dbus_set_error(&error, BUS_ERROR_INVALID_JOB_MODE, "Job mode %s is invalid.", smode);
1885 return bus_send_error_reply(connection, message, &error, -EINVAL);
1888 r = manager_load_unit(m, name, NULL, &error, &u);
1890 return bus_send_error_reply(connection, message, &error, r);
1892 return bus_unit_queue_job(connection, message, u, job_type, mode, reload_if_possible);
1896 if (!bus_maybe_send_reply(connection, message, reply))
1899 return DBUS_HANDLER_RESULT_HANDLED;
1902 dbus_error_free(&error);
1904 return DBUS_HANDLER_RESULT_NEED_MEMORY;
1907 const DBusObjectPathVTable bus_manager_vtable = {
1908 .message_function = bus_manager_message_handler