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=\"s\" access=\"readwrite\"/>\n" \
294 " <property name=\"ShutdownWatchdogUSec\" type=\"s\" 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 k = access(switch_root, F_OK);
1513 p = strjoin(switch_root, "/", switch_root_init, NULL);
1517 k = access(p, X_OK);
1521 return bus_send_error_reply(connection, message, NULL, -errno);
1523 u = strdup(switch_root);
1527 if (!isempty(switch_root_init)) {
1528 v = strdup(switch_root_init);
1536 free(m->switch_root);
1537 free(m->switch_root_init);
1539 m->switch_root_init = v;
1541 reply = dbus_message_new_method_return(message);
1545 m->exit_code = MANAGER_SWITCH_ROOT;
1547 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "SetEnvironment")) {
1548 _cleanup_strv_free_ char **l = NULL;
1551 SELINUX_ACCESS_CHECK(connection, message, "reboot");
1553 r = bus_parse_strv(message, &l);
1557 return bus_send_error_reply(connection, message, NULL, r);
1558 if (!strv_env_is_valid(l))
1559 return bus_send_error_reply(connection, message, NULL, -EINVAL);
1561 e = strv_env_merge(2, m->environment, l);
1565 reply = dbus_message_new_method_return(message);
1571 strv_free(m->environment);
1574 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "UnsetEnvironment")) {
1575 _cleanup_strv_free_ char **l = NULL;
1578 SELINUX_ACCESS_CHECK(connection, message, "reboot");
1580 r = bus_parse_strv(message, &l);
1584 return bus_send_error_reply(connection, message, NULL, r);
1585 if (!strv_env_name_or_assignment_is_valid(l))
1586 return bus_send_error_reply(connection, message, NULL, -EINVAL);
1588 e = strv_env_delete(m->environment, 1, l);
1592 reply = dbus_message_new_method_return(message);
1598 strv_free(m->environment);
1601 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "UnsetAndSetEnvironment")) {
1602 _cleanup_strv_free_ char **l_set = NULL, **l_unset = NULL, **e = NULL;
1604 DBusMessageIter iter;
1606 SELINUX_ACCESS_CHECK(connection, message, "reboot");
1608 if (!dbus_message_iter_init(message, &iter))
1611 r = bus_parse_strv_iter(&iter, &l_unset);
1615 return bus_send_error_reply(connection, message, NULL, r);
1616 if (!strv_env_name_or_assignment_is_valid(l_unset))
1617 return bus_send_error_reply(connection, message, NULL, -EINVAL);
1619 if (!dbus_message_iter_next(&iter))
1620 return bus_send_error_reply(connection, message, NULL, -EINVAL);
1622 r = bus_parse_strv_iter(&iter, &l_set);
1626 return bus_send_error_reply(connection, message, NULL, r);
1627 if (!strv_env_is_valid(l_set))
1628 return bus_send_error_reply(connection, message, NULL, -EINVAL);
1630 e = strv_env_delete(m->environment, 1, l_unset);
1634 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 (!bus_maybe_send_reply(connection, message, reply))
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