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"
35 #define BUS_MANAGER_INTERFACE_BEGIN \
36 " <interface name=\"org.freedesktop.systemd1.Manager\">\n"
38 #define BUS_MANAGER_INTERFACE_METHODS \
39 " <method name=\"GetUnit\">\n" \
40 " <arg name=\"name\" type=\"s\" direction=\"in\"/>\n" \
41 " <arg name=\"unit\" type=\"o\" direction=\"out\"/>\n" \
43 " <method name=\"GetUnitByPID\">\n" \
44 " <arg name=\"pid\" type=\"u\" direction=\"in\"/>\n" \
45 " <arg name=\"unit\" type=\"o\" direction=\"out\"/>\n" \
47 " <method name=\"LoadUnit\">\n" \
48 " <arg name=\"name\" type=\"s\" direction=\"in\"/>\n" \
49 " <arg name=\"unit\" type=\"o\" direction=\"out\"/>\n" \
51 " <method name=\"StartUnit\">\n" \
52 " <arg name=\"name\" type=\"s\" direction=\"in\"/>\n" \
53 " <arg name=\"mode\" type=\"s\" direction=\"in\"/>\n" \
54 " <arg name=\"job\" type=\"o\" direction=\"out\"/>\n" \
56 " <method name=\"StartUnitReplace\">\n" \
57 " <arg name=\"old_unit\" type=\"s\" direction=\"in\"/>\n" \
58 " <arg name=\"new_unit\" 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=\"StopUnit\">\n" \
63 " <arg name=\"name\" type=\"s\" direction=\"in\"/>\n" \
64 " <arg name=\"mode\" type=\"s\" direction=\"in\"/>\n" \
65 " <arg name=\"job\" type=\"o\" direction=\"out\"/>\n" \
67 " <method name=\"ReloadUnit\">\n" \
68 " <arg name=\"name\" type=\"s\" direction=\"in\"/>\n" \
69 " <arg name=\"mode\" type=\"s\" direction=\"in\"/>\n" \
70 " <arg name=\"job\" type=\"o\" direction=\"out\"/>\n" \
72 " <method name=\"RestartUnit\">\n" \
73 " <arg name=\"name\" type=\"s\" direction=\"in\"/>\n" \
74 " <arg name=\"mode\" type=\"s\" direction=\"in\"/>\n" \
75 " <arg name=\"job\" type=\"o\" direction=\"out\"/>\n" \
77 " <method name=\"TryRestartUnit\">\n" \
78 " <arg name=\"name\" type=\"s\" direction=\"in\"/>\n" \
79 " <arg name=\"mode\" type=\"s\" direction=\"in\"/>\n" \
80 " <arg name=\"job\" type=\"o\" direction=\"out\"/>\n" \
82 " <method name=\"ReloadOrRestartUnit\">\n" \
83 " <arg name=\"name\" type=\"s\" direction=\"in\"/>\n" \
84 " <arg name=\"mode\" type=\"s\" direction=\"in\"/>\n" \
85 " <arg name=\"job\" type=\"o\" direction=\"out\"/>\n" \
87 " <method name=\"ReloadOrTryRestartUnit\">\n" \
88 " <arg name=\"name\" type=\"s\" direction=\"in\"/>\n" \
89 " <arg name=\"mode\" type=\"s\" direction=\"in\"/>\n" \
90 " <arg name=\"job\" type=\"o\" direction=\"out\"/>\n" \
92 " <method name=\"KillUnit\">\n" \
93 " <arg name=\"name\" type=\"s\" direction=\"in\"/>\n" \
94 " <arg name=\"who\" type=\"s\" direction=\"in\"/>\n" \
95 " <arg name=\"mode\" type=\"s\" direction=\"in\"/>\n" \
96 " <arg name=\"signal\" type=\"i\" direction=\"in\"/>\n" \
98 " <method name=\"ResetFailedUnit\">\n" \
99 " <arg name=\"name\" type=\"s\" direction=\"in\"/>\n" \
101 " <method name=\"GetJob\">\n" \
102 " <arg name=\"id\" type=\"u\" direction=\"in\"/>\n" \
103 " <arg name=\"job\" type=\"o\" direction=\"out\"/>\n" \
105 " <method name=\"ClearJobs\"/>\n" \
106 " <method name=\"ResetFailed\"/>\n" \
107 " <method name=\"ListUnits\">\n" \
108 " <arg name=\"units\" type=\"a(ssssssouso)\" direction=\"out\"/>\n" \
110 " <method name=\"ListJobs\">\n" \
111 " <arg name=\"jobs\" type=\"a(usssoo)\" direction=\"out\"/>\n" \
113 " <method name=\"Subscribe\"/>\n" \
114 " <method name=\"Unsubscribe\"/>\n" \
115 " <method name=\"Dump\"/>\n" \
116 " <method name=\"CreateSnapshot\">\n" \
117 " <arg name=\"name\" type=\"s\" direction=\"in\"/>\n" \
118 " <arg name=\"cleanup\" type=\"b\" direction=\"in\"/>\n" \
119 " <arg name=\"unit\" type=\"o\" direction=\"out\"/>\n" \
121 " <method name=\"Reload\"/>\n" \
122 " <method name=\"Reexecute\"/>\n" \
123 " <method name=\"Exit\"/>\n" \
124 " <method name=\"Reboot\"/>\n" \
125 " <method name=\"PowerOff\"/>\n" \
126 " <method name=\"Halt\"/>\n" \
127 " <method name=\"KExec\"/>\n" \
128 " <method name=\"SetEnvironment\">\n" \
129 " <arg name=\"names\" type=\"as\" direction=\"in\"/>\n" \
131 " <method name=\"UnsetEnvironment\">\n" \
132 " <arg name=\"names\" type=\"as\" direction=\"in\"/>\n" \
134 " <method name=\"UnsetAndSetEnvironment\">\n" \
135 " <arg name=\"unset\" type=\"as\" direction=\"in\"/>\n" \
136 " <arg name=\"set\" type=\"as\" direction=\"in\"/>\n" \
138 " <method name=\"ListUnitFiles\">\n" \
139 " <arg name=\"changes\" type=\"a(ss)\" direction=\"out\"/>\n" \
141 " <method name=\"GetUnitFileState\">\n" \
142 " <arg name=\"file\" type=\"s\" direction=\"in\"/>\n" \
143 " <arg name=\"state\" type=\"s\" direction=\"out\"/>\n" \
145 " <method name=\"EnableUnitFiles\">\n" \
146 " <arg name=\"files\" type=\"as\" direction=\"in\"/>\n" \
147 " <arg name=\"runtime\" type=\"b\" direction=\"in\"/>\n" \
148 " <arg name=\"force\" type=\"b\" direction=\"in\"/>\n" \
149 " <arg name=\"carries_install_info\" type=\"b\" direction=\"out\"/>\n" \
150 " <arg name=\"changes\" type=\"a(sss)\" direction=\"out\"/>\n" \
152 " <method name=\"DisableUnitFiles\">\n" \
153 " <arg name=\"files\" type=\"as\" direction=\"in\"/>\n" \
154 " <arg name=\"runtime\" type=\"b\" direction=\"in\"/>\n" \
155 " <arg name=\"changes\" type=\"a(sss)\" direction=\"out\"/>\n" \
157 " <method name=\"ReenableUnitFiles\">\n" \
158 " <arg name=\"files\" type=\"as\" direction=\"in\"/>\n" \
159 " <arg name=\"runtime\" type=\"b\" direction=\"in\"/>\n" \
160 " <arg name=\"force\" type=\"b\" direction=\"in\"/>\n" \
161 " <arg name=\"carries_install_info\" type=\"b\" direction=\"out\"/>\n" \
162 " <arg name=\"changes\" type=\"a(sss)\" direction=\"out\"/>\n" \
164 " <method name=\"LinkUnitFiles\">\n" \
165 " <arg name=\"files\" type=\"as\" direction=\"in\"/>\n" \
166 " <arg name=\"runtime\" type=\"b\" direction=\"in\"/>\n" \
167 " <arg name=\"force\" type=\"b\" direction=\"in\"/>\n" \
168 " <arg name=\"changes\" type=\"a(sss)\" direction=\"out\"/>\n" \
170 " <method name=\"PresetUnitFiles\">\n" \
171 " <arg name=\"files\" type=\"as\" direction=\"in\"/>\n" \
172 " <arg name=\"runtime\" type=\"b\" direction=\"in\"/>\n" \
173 " <arg name=\"force\" type=\"b\" direction=\"in\"/>\n" \
174 " <arg name=\"carries_install_info\" type=\"b\" direction=\"out\"/>\n" \
175 " <arg name=\"changes\" type=\"a(sss)\" direction=\"out\"/>\n" \
177 " <method name=\"MaskUnitFiles\">\n" \
178 " <arg name=\"files\" type=\"as\" direction=\"in\"/>\n" \
179 " <arg name=\"runtime\" type=\"b\" direction=\"in\"/>\n" \
180 " <arg name=\"force\" type=\"b\" direction=\"in\"/>\n" \
181 " <arg name=\"changes\" type=\"a(sss)\" direction=\"out\"/>\n" \
183 " <method name=\"UnmaskUnitFiles\">\n" \
184 " <arg name=\"files\" type=\"as\" direction=\"in\"/>\n" \
185 " <arg name=\"runtime\" type=\"b\" direction=\"in\"/>\n" \
186 " <arg name=\"changes\" type=\"a(sss)\" direction=\"out\"/>\n" \
189 #define BUS_MANAGER_INTERFACE_SIGNALS \
190 " <signal name=\"UnitNew\">\n" \
191 " <arg name=\"id\" type=\"s\"/>\n" \
192 " <arg name=\"unit\" type=\"o\"/>\n" \
194 " <signal name=\"UnitRemoved\">\n" \
195 " <arg name=\"id\" type=\"s\"/>\n" \
196 " <arg name=\"unit\" type=\"o\"/>\n" \
198 " <signal name=\"JobNew\">\n" \
199 " <arg name=\"id\" type=\"u\"/>\n" \
200 " <arg name=\"job\" type=\"o\"/>\n" \
202 " <signal name=\"JobRemoved\">\n" \
203 " <arg name=\"id\" type=\"u\"/>\n" \
204 " <arg name=\"job\" type=\"o\"/>\n" \
205 " <arg name=\"result\" type=\"s\"/>\n" \
207 " <signal name=\"StartupFinished\">\n" \
208 " <arg name=\"kernel\" type=\"t\"/>\n" \
209 " <arg name=\"initrd\" type=\"t\"/>\n" \
210 " <arg name=\"userspace\" type=\"t\"/>\n" \
211 " <arg name=\"total\" type=\"t\"/>\n" \
213 " <signal name=\"UnitFilesChanged\"/>\n"
215 #define BUS_MANAGER_INTERFACE_PROPERTIES_GENERAL \
216 " <property name=\"Version\" type=\"s\" access=\"read\"/>\n" \
217 " <property name=\"Distribution\" type=\"s\" access=\"read\"/>\n" \
218 " <property name=\"Features\" type=\"s\" access=\"read\"/>\n" \
219 " <property name=\"Tainted\" type=\"s\" access=\"read\"/>\n" \
220 " <property name=\"RunningAs\" type=\"s\" access=\"read\"/>\n" \
221 " <property name=\"InitRDTimestamp\" type=\"t\" access=\"read\"/>\n" \
222 " <property name=\"InitRDTimestampMonotonic\" type=\"t\" access=\"read\"/>\n" \
223 " <property name=\"StartupTimestamp\" type=\"t\" access=\"read\"/>\n" \
224 " <property name=\"StartupTimestampMonotonic\" type=\"t\" access=\"read\"/>\n" \
225 " <property name=\"FinishTimestamp\" type=\"t\" access=\"read\"/>\n" \
226 " <property name=\"FinishTimestampMonotonic\" type=\"t\" access=\"read\"/>\n" \
227 " <property name=\"LogLevel\" type=\"s\" access=\"readwrite\"/>\n" \
228 " <property name=\"LogTarget\" type=\"s\" access=\"readwrite\"/>\n" \
229 " <property name=\"NNames\" type=\"u\" access=\"read\"/>\n" \
230 " <property name=\"NJobs\" type=\"u\" access=\"read\"/>\n" \
231 " <property name=\"NInstalledJobs\" type=\"u\" access=\"read\"/>\n" \
232 " <property name=\"NFailedJobs\" type=\"u\" access=\"read\"/>\n" \
233 " <property name=\"Progress\" type=\"d\" access=\"read\"/>\n" \
234 " <property name=\"Environment\" type=\"as\" access=\"read\"/>\n" \
235 " <property name=\"ConfirmSpawn\" type=\"b\" access=\"read\"/>\n" \
236 " <property name=\"ShowStatus\" type=\"b\" access=\"read\"/>\n" \
237 " <property name=\"UnitPath\" type=\"as\" access=\"read\"/>\n" \
238 " <property name=\"NotifySocket\" type=\"s\" access=\"read\"/>\n" \
239 " <property name=\"ControlGroupHierarchy\" type=\"s\" access=\"read\"/>\n" \
240 " <property name=\"DefaultControllers\" type=\"as\" access=\"read\"/>\n" \
241 " <property name=\"DefaultStandardOutput\" type=\"s\" access=\"read\"/>\n" \
242 " <property name=\"DefaultStandardError\" type=\"s\" access=\"read\"/>\n" \
243 " <property name=\"RuntimeWatchdogUSec\" type=\"s\" access=\"readwrite\"/>\n" \
244 " <property name=\"ShutdownWatchdogUSec\" type=\"s\" access=\"readwrite\"/>\n" \
245 " <property name=\"HaveWatchdog\" type=\"b\" access=\"read\"/>\n"
247 #ifdef HAVE_SYSV_COMPAT
248 #define BUS_MANAGER_INTERFACE_PROPERTIES_SYSV \
249 " <property name=\"SysVConsole\" type=\"b\" access=\"read\"/>\n" \
250 " <property name=\"SysVInitPath\" type=\"as\" access=\"read\"/>\n" \
251 " <property name=\"SysVRcndPath\" type=\"as\" access=\"read\"/>\n"
253 #define BUS_MANAGER_INTERFACE_PROPERTIES_SYSV
256 #define BUS_MANAGER_INTERFACE_END \
259 #define BUS_MANAGER_INTERFACE \
260 BUS_MANAGER_INTERFACE_BEGIN \
261 BUS_MANAGER_INTERFACE_METHODS \
262 BUS_MANAGER_INTERFACE_SIGNALS \
263 BUS_MANAGER_INTERFACE_PROPERTIES_GENERAL \
264 BUS_MANAGER_INTERFACE_PROPERTIES_SYSV \
265 BUS_MANAGER_INTERFACE_END
267 #define INTROSPECTION_BEGIN \
268 DBUS_INTROSPECT_1_0_XML_DOCTYPE_DECL_NODE \
270 BUS_MANAGER_INTERFACE \
271 BUS_PROPERTIES_INTERFACE \
273 BUS_INTROSPECTABLE_INTERFACE
275 #define INTROSPECTION_END \
278 #define INTERFACES_LIST \
279 BUS_GENERIC_INTERFACES_LIST \
280 "org.freedesktop.systemd1.Manager\0"
282 const char bus_manager_interface[] _introspect_("Manager") = BUS_MANAGER_INTERFACE;
284 static DEFINE_BUS_PROPERTY_APPEND_ENUM(bus_manager_append_running_as, manager_running_as, ManagerRunningAs);
285 static DEFINE_BUS_PROPERTY_APPEND_ENUM(bus_manager_append_exec_output, exec_output, ExecOutput);
287 static int bus_manager_append_tainted(DBusMessageIter *i, const char *property, void *data) {
290 char buf[LINE_MAX] = "", *e = buf, *p = NULL;
297 e = stpcpy(e, "split-usr:");
299 if (readlink_malloc("/etc/mtab", &p) < 0)
300 e = stpcpy(e, "mtab-not-symlink:");
304 if (access("/proc/cgroups", F_OK) < 0)
305 stpcpy(e, "cgroups-missing:");
307 if (hwclock_is_localtime() > 0)
308 stpcpy(e, "local-hwclock:");
310 if (endswith(buf, ":"))
311 buf[strlen(buf)-1] = 0;
315 if (!dbus_message_iter_append_basic(i, DBUS_TYPE_STRING, &t))
321 static int bus_manager_append_log_target(DBusMessageIter *i, const char *property, void *data) {
327 t = log_target_to_string(log_get_target());
329 if (!dbus_message_iter_append_basic(i, DBUS_TYPE_STRING, &t))
335 static int bus_manager_set_log_target(DBusMessageIter *i, const char *property, void *data) {
341 dbus_message_iter_get_basic(i, &t);
343 return log_set_target_from_string(t);
346 static int bus_manager_append_log_level(DBusMessageIter *i, const char *property, void *data) {
352 t = log_level_to_string(log_get_max_level());
354 if (!dbus_message_iter_append_basic(i, DBUS_TYPE_STRING, &t))
360 static int bus_manager_set_log_level(DBusMessageIter *i, const char *property, void *data) {
366 dbus_message_iter_get_basic(i, &t);
368 return log_set_max_level_from_string(t);
371 static int bus_manager_append_n_names(DBusMessageIter *i, const char *property, void *data) {
379 u = hashmap_size(m->units);
381 if (!dbus_message_iter_append_basic(i, DBUS_TYPE_UINT32, &u))
387 static int bus_manager_append_n_jobs(DBusMessageIter *i, const char *property, void *data) {
395 u = hashmap_size(m->jobs);
397 if (!dbus_message_iter_append_basic(i, DBUS_TYPE_UINT32, &u))
403 static int bus_manager_append_progress(DBusMessageIter *i, const char *property, void *data) {
411 if (dual_timestamp_is_set(&m->finish_timestamp))
414 d = 1.0 - ((double) hashmap_size(m->jobs) / (double) m->n_installed_jobs);
416 if (!dbus_message_iter_append_basic(i, DBUS_TYPE_DOUBLE, &d))
422 static const char *message_get_sender_with_fallback(DBusMessage *m) {
427 if ((s = dbus_message_get_sender(m)))
430 /* When the message came in from a direct connection the
431 * message will have no sender. We fix that here. */
436 static DBusMessage *message_from_file_changes(
438 UnitFileChange *changes,
440 int carries_install_info) {
442 DBusMessageIter iter, sub, sub2;
446 reply = dbus_message_new_method_return(m);
450 dbus_message_iter_init_append(reply, &iter);
452 if (carries_install_info >= 0) {
455 b = !!carries_install_info;
456 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &b))
460 if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "(sss)", &sub))
463 for (i = 0; i < n_changes; i++) {
464 const char *type, *path, *source;
466 type = unit_file_change_type_to_string(changes[i].type);
467 path = strempty(changes[i].path);
468 source = strempty(changes[i].source);
470 if (!dbus_message_iter_open_container(&sub, DBUS_TYPE_STRUCT, NULL, &sub2) ||
471 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &type) ||
472 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &path) ||
473 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &source) ||
474 !dbus_message_iter_close_container(&sub, &sub2))
478 if (!dbus_message_iter_close_container(&iter, &sub))
484 dbus_message_unref(reply);
488 static int bus_manager_send_unit_files_changed(Manager *m) {
492 s = dbus_message_new_signal("/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", "UnitFilesChanged");
496 r = bus_broadcast(m, s);
497 dbus_message_unref(s);
502 static int bus_manager_append_have_watchdog(DBusMessageIter *i, const char *property, void *data) {
508 b = access("/dev/watchdog", F_OK) >= 0;
510 if (!dbus_message_iter_append_basic(i, DBUS_TYPE_BOOLEAN, &b))
516 static int bus_manager_set_runtime_watchdog_usec(DBusMessageIter *i, const char *property, void *data) {
522 dbus_message_iter_get_basic(i, t);
524 return watchdog_set_timeout(t);
527 static const char systemd_property_string[] =
532 static const BusProperty bus_systemd_properties[] = {
533 { "Version", bus_property_append_string, "s", 0 },
534 { "Distribution", bus_property_append_string, "s", sizeof(PACKAGE_STRING) },
535 { "Features", bus_property_append_string, "s", sizeof(PACKAGE_STRING) + sizeof(DISTRIBUTION) },
539 static const BusProperty bus_manager_properties[] = {
540 { "RunningAs", bus_manager_append_running_as, "s", offsetof(Manager, running_as) },
541 { "Tainted", bus_manager_append_tainted, "s", 0 },
542 { "InitRDTimestamp", bus_property_append_uint64, "t", offsetof(Manager, initrd_timestamp.realtime) },
543 { "InitRDTimestampMonotonic", bus_property_append_uint64, "t", offsetof(Manager, initrd_timestamp.monotonic) },
544 { "StartupTimestamp", bus_property_append_uint64, "t", offsetof(Manager, startup_timestamp.realtime) },
545 { "StartupTimestampMonotonic", bus_property_append_uint64, "t", offsetof(Manager, startup_timestamp.monotonic) },
546 { "FinishTimestamp", bus_property_append_uint64, "t", offsetof(Manager, finish_timestamp.realtime) },
547 { "FinishTimestampMonotonic", bus_property_append_uint64, "t", offsetof(Manager, finish_timestamp.monotonic) },
548 { "LogLevel", bus_manager_append_log_level, "s", 0, false, bus_manager_set_log_level },
549 { "LogTarget", bus_manager_append_log_target, "s", 0, false, bus_manager_set_log_target },
550 { "NNames", bus_manager_append_n_names, "u", 0 },
551 { "NJobs", bus_manager_append_n_jobs, "u", 0 },
552 { "NInstalledJobs",bus_property_append_uint32, "u", offsetof(Manager, n_installed_jobs) },
553 { "NFailedJobs", bus_property_append_uint32, "u", offsetof(Manager, n_failed_jobs) },
554 { "Progress", bus_manager_append_progress, "d", 0 },
555 { "Environment", bus_property_append_strv, "as", offsetof(Manager, environment), true },
556 { "ConfirmSpawn", bus_property_append_bool, "b", offsetof(Manager, confirm_spawn) },
557 { "ShowStatus", bus_property_append_bool, "b", offsetof(Manager, show_status) },
558 { "UnitPath", bus_property_append_strv, "as", offsetof(Manager, lookup_paths.unit_path), true },
559 { "NotifySocket", bus_property_append_string, "s", offsetof(Manager, notify_socket), true },
560 { "ControlGroupHierarchy", bus_property_append_string, "s", offsetof(Manager, cgroup_hierarchy), true },
561 { "DefaultControllers", bus_property_append_strv, "as", offsetof(Manager, default_controllers), true },
562 { "DefaultStandardOutput", bus_manager_append_exec_output, "s", offsetof(Manager, default_std_output) },
563 { "DefaultStandardError", bus_manager_append_exec_output, "s", offsetof(Manager, default_std_error) },
564 { "RuntimeWatchdogUSec", bus_property_append_usec, "t", offsetof(Manager, runtime_watchdog), false, bus_manager_set_runtime_watchdog_usec },
565 { "ShutdownWatchdogUSec", bus_property_append_usec, "t", offsetof(Manager, shutdown_watchdog), false, bus_property_set_usec },
566 { "HaveWatchdog", bus_manager_append_have_watchdog, "b", 0 },
567 #ifdef HAVE_SYSV_COMPAT
568 { "SysVConsole", bus_property_append_bool, "b", offsetof(Manager, sysv_console) },
569 { "SysVInitPath", bus_property_append_strv, "as", offsetof(Manager, lookup_paths.sysvinit_path), true },
570 { "SysVRcndPath", bus_property_append_strv, "as", offsetof(Manager, lookup_paths.sysvrcnd_path), true },
575 static DBusHandlerResult bus_manager_message_handler(DBusConnection *connection, DBusMessage *message, void *data) {
580 DBusMessage *reply = NULL;
582 JobType job_type = _JOB_TYPE_INVALID;
583 bool reload_if_possible = false;
590 dbus_error_init(&error);
592 member = dbus_message_get_member(message);
594 if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "GetUnit")) {
598 if (!dbus_message_get_args(
601 DBUS_TYPE_STRING, &name,
603 return bus_send_error_reply(connection, message, &error, -EINVAL);
605 if (!(u = manager_get_unit(m, name))) {
606 dbus_set_error(&error, BUS_ERROR_NO_SUCH_UNIT, "Unit %s is not loaded.", name);
607 return bus_send_error_reply(connection, message, &error, -ENOENT);
610 if (!(reply = dbus_message_new_method_return(message)))
613 if (!(path = unit_dbus_path(u)))
616 if (!dbus_message_append_args(
618 DBUS_TYPE_OBJECT_PATH, &path,
621 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "GetUnitByPID")) {
625 if (!dbus_message_get_args(
628 DBUS_TYPE_UINT32, &pid,
630 return bus_send_error_reply(connection, message, &error, -EINVAL);
632 if (!(u = cgroup_unit_by_pid(m, (pid_t) pid))) {
633 dbus_set_error(&error, BUS_ERROR_NO_SUCH_UNIT, "No unit for PID %lu is loaded.", (unsigned long) pid);
634 return bus_send_error_reply(connection, message, &error, -ENOENT);
637 if (!(reply = dbus_message_new_method_return(message)))
640 if (!(path = unit_dbus_path(u)))
643 if (!dbus_message_append_args(
645 DBUS_TYPE_OBJECT_PATH, &path,
648 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "LoadUnit")) {
652 if (!dbus_message_get_args(
655 DBUS_TYPE_STRING, &name,
657 return bus_send_error_reply(connection, message, &error, -EINVAL);
659 if ((r = manager_load_unit(m, name, NULL, &error, &u)) < 0)
660 return bus_send_error_reply(connection, message, &error, r);
662 if (!(reply = dbus_message_new_method_return(message)))
665 if (!(path = unit_dbus_path(u)))
668 if (!dbus_message_append_args(
670 DBUS_TYPE_OBJECT_PATH, &path,
674 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "StartUnit"))
675 job_type = JOB_START;
676 else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "StartUnitReplace"))
677 job_type = JOB_START;
678 else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "StopUnit"))
680 else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ReloadUnit"))
681 job_type = JOB_RELOAD;
682 else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "RestartUnit"))
683 job_type = JOB_RESTART;
684 else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "TryRestartUnit"))
685 job_type = JOB_TRY_RESTART;
686 else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ReloadOrRestartUnit")) {
687 reload_if_possible = true;
688 job_type = JOB_RESTART;
689 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ReloadOrTryRestartUnit")) {
690 reload_if_possible = true;
691 job_type = JOB_TRY_RESTART;
692 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "KillUnit")) {
693 const char *name, *swho, *smode;
699 if (!dbus_message_get_args(
702 DBUS_TYPE_STRING, &name,
703 DBUS_TYPE_STRING, &swho,
704 DBUS_TYPE_STRING, &smode,
705 DBUS_TYPE_INT32, &signo,
707 return bus_send_error_reply(connection, message, &error, -EINVAL);
712 who = kill_who_from_string(swho);
714 return bus_send_error_reply(connection, message, &error, -EINVAL);
718 mode = KILL_CONTROL_GROUP;
720 mode = kill_mode_from_string(smode);
722 return bus_send_error_reply(connection, message, &error, -EINVAL);
725 if (signo <= 0 || signo >= _NSIG)
726 return bus_send_error_reply(connection, message, &error, -EINVAL);
728 if (!(u = manager_get_unit(m, name))) {
729 dbus_set_error(&error, BUS_ERROR_NO_SUCH_UNIT, "Unit %s is not loaded.", name);
730 return bus_send_error_reply(connection, message, &error, -ENOENT);
733 if ((r = unit_kill(u, who, mode, signo, &error)) < 0)
734 return bus_send_error_reply(connection, message, &error, r);
736 if (!(reply = dbus_message_new_method_return(message)))
739 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "GetJob")) {
743 if (!dbus_message_get_args(
746 DBUS_TYPE_UINT32, &id,
748 return bus_send_error_reply(connection, message, &error, -EINVAL);
750 if (!(j = manager_get_job(m, id))) {
751 dbus_set_error(&error, BUS_ERROR_NO_SUCH_JOB, "Job %u does not exist.", (unsigned) id);
752 return bus_send_error_reply(connection, message, &error, -ENOENT);
755 if (!(reply = dbus_message_new_method_return(message)))
758 if (!(path = job_dbus_path(j)))
761 if (!dbus_message_append_args(
763 DBUS_TYPE_OBJECT_PATH, &path,
767 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ClearJobs")) {
769 manager_clear_jobs(m);
771 if (!(reply = dbus_message_new_method_return(message)))
774 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ResetFailed")) {
776 manager_reset_failed(m);
778 if (!(reply = dbus_message_new_method_return(message)))
781 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ResetFailedUnit")) {
785 if (!dbus_message_get_args(
788 DBUS_TYPE_STRING, &name,
790 return bus_send_error_reply(connection, message, &error, -EINVAL);
792 if (!(u = manager_get_unit(m, name))) {
793 dbus_set_error(&error, BUS_ERROR_NO_SUCH_UNIT, "Unit %s is not loaded.", name);
794 return bus_send_error_reply(connection, message, &error, -ENOENT);
797 unit_reset_failed(u);
799 if (!(reply = dbus_message_new_method_return(message)))
802 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ListUnits")) {
803 DBusMessageIter iter, sub;
808 if (!(reply = dbus_message_new_method_return(message)))
811 dbus_message_iter_init_append(reply, &iter);
813 if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "(ssssssouso)", &sub))
816 HASHMAP_FOREACH_KEY(u, k, m->units, i) {
817 char *u_path, *j_path;
818 const char *description, *load_state, *active_state, *sub_state, *sjob_type, *following;
819 DBusMessageIter sub2;
826 if (!dbus_message_iter_open_container(&sub, DBUS_TYPE_STRUCT, NULL, &sub2))
829 description = unit_description(u);
830 load_state = unit_load_state_to_string(u->load_state);
831 active_state = unit_active_state_to_string(unit_active_state(u));
832 sub_state = unit_sub_state_to_string(u);
834 f = unit_following(u);
835 following = f ? f->id : "";
837 if (!(u_path = unit_dbus_path(u)))
841 job_id = (uint32_t) u->job->id;
843 if (!(j_path = job_dbus_path(u->job))) {
848 sjob_type = job_type_to_string(u->job->type);
855 if (!dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &u->id) ||
856 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &description) ||
857 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &load_state) ||
858 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &active_state) ||
859 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &sub_state) ||
860 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &following) ||
861 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_OBJECT_PATH, &u_path) ||
862 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_UINT32, &job_id) ||
863 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &sjob_type) ||
864 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_OBJECT_PATH, &j_path)) {
875 if (!dbus_message_iter_close_container(&sub, &sub2))
879 if (!dbus_message_iter_close_container(&iter, &sub))
882 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ListJobs")) {
883 DBusMessageIter iter, sub;
887 if (!(reply = dbus_message_new_method_return(message)))
890 dbus_message_iter_init_append(reply, &iter);
892 if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "(usssoo)", &sub))
895 HASHMAP_FOREACH(j, m->jobs, i) {
896 char *u_path, *j_path;
897 const char *state, *type;
899 DBusMessageIter sub2;
901 if (!dbus_message_iter_open_container(&sub, DBUS_TYPE_STRUCT, NULL, &sub2))
904 id = (uint32_t) j->id;
905 state = job_state_to_string(j->state);
906 type = job_type_to_string(j->type);
908 if (!(j_path = job_dbus_path(j)))
911 if (!(u_path = unit_dbus_path(j->unit))) {
916 if (!dbus_message_iter_append_basic(&sub2, DBUS_TYPE_UINT32, &id) ||
917 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &j->unit->id) ||
918 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &type) ||
919 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &state) ||
920 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_OBJECT_PATH, &j_path) ||
921 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_OBJECT_PATH, &u_path)) {
930 if (!dbus_message_iter_close_container(&sub, &sub2))
934 if (!dbus_message_iter_close_container(&iter, &sub))
937 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "Subscribe")) {
941 if (!(s = BUS_CONNECTION_SUBSCRIBED(m, connection))) {
942 if (!(s = set_new(string_hash_func, string_compare_func)))
945 if (!(dbus_connection_set_data(connection, m->subscribed_data_slot, s, NULL))) {
951 if (!(client = strdup(message_get_sender_with_fallback(message))))
954 if ((r = set_put(s, client)) < 0) {
956 return bus_send_error_reply(connection, message, NULL, r);
959 if (!(reply = dbus_message_new_method_return(message)))
962 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "Unsubscribe")) {
965 if (!(client = set_remove(BUS_CONNECTION_SUBSCRIBED(m, connection), (char*) message_get_sender_with_fallback(message)))) {
966 dbus_set_error(&error, BUS_ERROR_NOT_SUBSCRIBED, "Client is not subscribed.");
967 return bus_send_error_reply(connection, message, &error, -ENOENT);
972 if (!(reply = dbus_message_new_method_return(message)))
975 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "Dump")) {
980 if (!(reply = dbus_message_new_method_return(message)))
983 if (!(f = open_memstream(&dump, &size)))
986 manager_dump_units(m, f, NULL);
987 manager_dump_jobs(m, f, NULL);
997 if (!dbus_message_append_args(reply, DBUS_TYPE_STRING, &dump, DBUS_TYPE_INVALID)) {
1003 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "CreateSnapshot")) {
1005 dbus_bool_t cleanup;
1008 if (!dbus_message_get_args(
1011 DBUS_TYPE_STRING, &name,
1012 DBUS_TYPE_BOOLEAN, &cleanup,
1014 return bus_send_error_reply(connection, message, &error, -EINVAL);
1016 if (name && name[0] == 0)
1019 if ((r = snapshot_create(m, name, cleanup, &error, &s)) < 0)
1020 return bus_send_error_reply(connection, message, &error, r);
1022 if (!(reply = dbus_message_new_method_return(message)))
1025 if (!(path = unit_dbus_path(UNIT(s))))
1028 if (!dbus_message_append_args(
1030 DBUS_TYPE_OBJECT_PATH, &path,
1034 } else if (dbus_message_is_method_call(message, "org.freedesktop.DBus.Introspectable", "Introspect")) {
1035 char *introspection = NULL;
1043 if (!(reply = dbus_message_new_method_return(message)))
1046 /* We roll our own introspection code here, instead of
1047 * relying on bus_default_message_handler() because we
1048 * need to generate our introspection string
1051 if (!(f = open_memstream(&introspection, &size)))
1054 fputs(INTROSPECTION_BEGIN, f);
1056 HASHMAP_FOREACH_KEY(u, k, m->units, i) {
1062 if (!(p = bus_path_escape(k))) {
1064 free(introspection);
1068 fprintf(f, "<node name=\"unit/%s\"/>", p);
1072 HASHMAP_FOREACH(j, m->jobs, i)
1073 fprintf(f, "<node name=\"job/%lu\"/>", (unsigned long) j->id);
1075 fputs(INTROSPECTION_END, f);
1079 free(introspection);
1088 if (!dbus_message_append_args(reply, DBUS_TYPE_STRING, &introspection, DBUS_TYPE_INVALID)) {
1089 free(introspection);
1093 free(introspection);
1095 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "Reload")) {
1097 assert(!m->queued_message);
1099 /* Instead of sending the reply back right away, we
1100 * just remember that we need to and then send it
1101 * after the reload is finished. That way the caller
1102 * knows when the reload finished. */
1104 if (!(m->queued_message = dbus_message_new_method_return(message)))
1107 m->queued_message_connection = connection;
1108 m->exit_code = MANAGER_RELOAD;
1110 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "Reexecute")) {
1112 /* We don't send a reply back here, the client should
1113 * just wait for us disconnecting. */
1115 m->exit_code = MANAGER_REEXECUTE;
1117 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "Exit")) {
1119 if (m->running_as == MANAGER_SYSTEM) {
1120 dbus_set_error(&error, BUS_ERROR_NOT_SUPPORTED, "Exit is only supported for user service managers.");
1121 return bus_send_error_reply(connection, message, &error, -ENOTSUP);
1124 if (!(reply = dbus_message_new_method_return(message)))
1127 m->exit_code = MANAGER_EXIT;
1129 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "Reboot")) {
1131 if (m->running_as != MANAGER_SYSTEM) {
1132 dbus_set_error(&error, BUS_ERROR_NOT_SUPPORTED, "Reboot is only supported for system managers.");
1133 return bus_send_error_reply(connection, message, &error, -ENOTSUP);
1136 if (!(reply = dbus_message_new_method_return(message)))
1139 m->exit_code = MANAGER_REBOOT;
1141 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "PowerOff")) {
1143 if (m->running_as != MANAGER_SYSTEM) {
1144 dbus_set_error(&error, BUS_ERROR_NOT_SUPPORTED, "Powering off is only supported for system managers.");
1145 return bus_send_error_reply(connection, message, &error, -ENOTSUP);
1148 if (!(reply = dbus_message_new_method_return(message)))
1151 m->exit_code = MANAGER_POWEROFF;
1153 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "Halt")) {
1155 if (m->running_as != MANAGER_SYSTEM) {
1156 dbus_set_error(&error, BUS_ERROR_NOT_SUPPORTED, "Halting is only supported for system managers.");
1157 return bus_send_error_reply(connection, message, &error, -ENOTSUP);
1160 if (!(reply = dbus_message_new_method_return(message)))
1163 m->exit_code = MANAGER_HALT;
1165 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "KExec")) {
1167 if (m->running_as != MANAGER_SYSTEM) {
1168 dbus_set_error(&error, BUS_ERROR_NOT_SUPPORTED, "kexec is only supported for system managers.");
1169 return bus_send_error_reply(connection, message, &error, -ENOTSUP);
1172 if (!(reply = dbus_message_new_method_return(message)))
1175 m->exit_code = MANAGER_KEXEC;
1177 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "SetEnvironment")) {
1178 char **l = NULL, **e = NULL;
1180 if ((r = bus_parse_strv(message, &l)) < 0) {
1184 return bus_send_error_reply(connection, message, NULL, r);
1187 e = strv_env_merge(2, m->environment, l);
1193 if (!(reply = dbus_message_new_method_return(message))) {
1198 strv_free(m->environment);
1201 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "UnsetEnvironment")) {
1202 char **l = NULL, **e = NULL;
1204 if ((r = bus_parse_strv(message, &l)) < 0) {
1208 return bus_send_error_reply(connection, message, NULL, r);
1211 e = strv_env_delete(m->environment, 1, l);
1217 if (!(reply = dbus_message_new_method_return(message))) {
1222 strv_free(m->environment);
1225 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "UnsetAndSetEnvironment")) {
1226 char **l_set = NULL, **l_unset = NULL, **e = NULL, **f = NULL;
1227 DBusMessageIter iter;
1229 if (!dbus_message_iter_init(message, &iter))
1232 r = bus_parse_strv_iter(&iter, &l_unset);
1237 return bus_send_error_reply(connection, message, NULL, r);
1240 if (!dbus_message_iter_next(&iter)) {
1242 return bus_send_error_reply(connection, message, NULL, -EINVAL);
1245 r = bus_parse_strv_iter(&iter, &l_set);
1251 return bus_send_error_reply(connection, message, NULL, r);
1254 e = strv_env_delete(m->environment, 1, l_unset);
1262 f = strv_env_merge(2, e, l_set);
1269 if (!(reply = dbus_message_new_method_return(message))) {
1274 strv_free(m->environment);
1276 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ListUnitFiles")) {
1277 DBusMessageIter iter, sub, sub2;
1282 reply = dbus_message_new_method_return(message);
1286 h = hashmap_new(string_hash_func, string_compare_func);
1290 r = unit_file_get_list(m->running_as == MANAGER_SYSTEM ? UNIT_FILE_SYSTEM : UNIT_FILE_USER, NULL, h);
1292 unit_file_list_free(h);
1293 dbus_message_unref(reply);
1294 return bus_send_error_reply(connection, message, NULL, r);
1297 dbus_message_iter_init_append(reply, &iter);
1299 if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "(ss)", &sub)) {
1300 unit_file_list_free(h);
1304 HASHMAP_FOREACH(item, h, i) {
1307 state = unit_file_state_to_string(item->state);
1310 if (!dbus_message_iter_open_container(&sub, DBUS_TYPE_STRUCT, NULL, &sub2) ||
1311 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &item->path) ||
1312 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &state) ||
1313 !dbus_message_iter_close_container(&sub, &sub2)) {
1314 unit_file_list_free(h);
1319 unit_file_list_free(h);
1321 if (!dbus_message_iter_close_container(&iter, &sub))
1324 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "GetUnitFileState")) {
1326 UnitFileState state;
1329 if (!dbus_message_get_args(
1332 DBUS_TYPE_STRING, &name,
1334 return bus_send_error_reply(connection, message, &error, -EINVAL);
1336 state = unit_file_get_state(m->running_as == MANAGER_SYSTEM ? UNIT_FILE_SYSTEM : UNIT_FILE_USER, NULL, name);
1338 return bus_send_error_reply(connection, message, NULL, state);
1340 s = unit_file_state_to_string(state);
1343 reply = dbus_message_new_method_return(message);
1347 if (!dbus_message_append_args(
1349 DBUS_TYPE_STRING, &s,
1352 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "EnableUnitFiles") ||
1353 dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ReenableUnitFiles") ||
1354 dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "LinkUnitFiles") ||
1355 dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "PresetUnitFiles") ||
1356 dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "MaskUnitFiles")) {
1359 DBusMessageIter iter;
1360 UnitFileScope scope = m->running_as == MANAGER_SYSTEM ? UNIT_FILE_SYSTEM : UNIT_FILE_USER;
1361 UnitFileChange *changes = NULL;
1362 unsigned n_changes = 0;
1363 dbus_bool_t runtime, force;
1364 int carries_install_info = -1;
1366 if (!dbus_message_iter_init(message, &iter))
1369 r = bus_parse_strv_iter(&iter, &l);
1374 return bus_send_error_reply(connection, message, NULL, r);
1377 if (!dbus_message_iter_next(&iter) ||
1378 bus_iter_get_basic_and_next(&iter, DBUS_TYPE_BOOLEAN, &runtime, true) < 0 ||
1379 bus_iter_get_basic_and_next(&iter, DBUS_TYPE_BOOLEAN, &force, false) < 0) {
1381 return bus_send_error_reply(connection, message, NULL, -EIO);
1384 if (streq(member, "EnableUnitFiles")) {
1385 r = unit_file_enable(scope, runtime, NULL, l, force, &changes, &n_changes);
1386 carries_install_info = r;
1387 } else if (streq(member, "ReenableUnitFiles")) {
1388 r = unit_file_reenable(scope, runtime, NULL, l, force, &changes, &n_changes);
1389 carries_install_info = r;
1390 } else if (streq(member, "LinkUnitFiles"))
1391 r = unit_file_link(scope, runtime, NULL, l, force, &changes, &n_changes);
1392 else if (streq(member, "PresetUnitFiles")) {
1393 r = unit_file_preset(scope, runtime, NULL, l, force, &changes, &n_changes);
1394 carries_install_info = r;
1395 } else if (streq(member, "MaskUnitFiles"))
1396 r = unit_file_mask(scope, runtime, NULL, l, force, &changes, &n_changes);
1398 assert_not_reached("Uh? Wrong method");
1401 bus_manager_send_unit_files_changed(m);
1404 unit_file_changes_free(changes, n_changes);
1405 return bus_send_error_reply(connection, message, NULL, r);
1408 reply = message_from_file_changes(message, changes, n_changes, carries_install_info);
1409 unit_file_changes_free(changes, n_changes);
1414 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "DisableUnitFiles") ||
1415 dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "UnmaskUnitFiles")) {
1418 DBusMessageIter iter;
1419 UnitFileScope scope = m->running_as == MANAGER_SYSTEM ? UNIT_FILE_SYSTEM : UNIT_FILE_USER;
1420 UnitFileChange *changes = NULL;
1421 unsigned n_changes = 0;
1422 dbus_bool_t runtime;
1424 if (!dbus_message_iter_init(message, &iter))
1427 r = bus_parse_strv_iter(&iter, &l);
1432 return bus_send_error_reply(connection, message, NULL, r);
1435 if (!dbus_message_iter_next(&iter) ||
1436 bus_iter_get_basic_and_next(&iter, DBUS_TYPE_BOOLEAN, &runtime, false) < 0) {
1438 return bus_send_error_reply(connection, message, NULL, -EIO);
1441 if (streq(member, "DisableUnitFiles"))
1442 r = unit_file_disable(scope, runtime, NULL, l, &changes, &n_changes);
1443 else if (streq(member, "UnmaskUnitFiles"))
1444 r = unit_file_unmask(scope, runtime, NULL, l, &changes, &n_changes);
1446 assert_not_reached("Uh? Wrong method");
1449 bus_manager_send_unit_files_changed(m);
1452 unit_file_changes_free(changes, n_changes);
1453 return bus_send_error_reply(connection, message, NULL, r);
1456 reply = message_from_file_changes(message, changes, n_changes, -1);
1457 unit_file_changes_free(changes, n_changes);
1463 const BusBoundProperties bps[] = {
1464 { "org.freedesktop.systemd1.Manager", bus_systemd_properties, systemd_property_string },
1465 { "org.freedesktop.systemd1.Manager", bus_manager_properties, m },
1468 return bus_default_message_handler(connection, message, NULL, INTERFACES_LIST, bps);
1471 if (job_type != _JOB_TYPE_INVALID) {
1472 const char *name, *smode, *old_name = NULL;
1479 if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "StartUnitReplace"))
1480 b = dbus_message_get_args(
1483 DBUS_TYPE_STRING, &old_name,
1484 DBUS_TYPE_STRING, &name,
1485 DBUS_TYPE_STRING, &smode,
1488 b = dbus_message_get_args(
1491 DBUS_TYPE_STRING, &name,
1492 DBUS_TYPE_STRING, &smode,
1496 return bus_send_error_reply(connection, message, &error, -EINVAL);
1499 if (!(u = manager_get_unit(m, old_name)) ||
1501 u->job->type != JOB_START) {
1502 dbus_set_error(&error, BUS_ERROR_NO_SUCH_JOB, "No job queued for unit %s", old_name);
1503 return bus_send_error_reply(connection, message, &error, -ENOENT);
1507 if ((mode = job_mode_from_string(smode)) == _JOB_MODE_INVALID) {
1508 dbus_set_error(&error, BUS_ERROR_INVALID_JOB_MODE, "Job mode %s is invalid.", smode);
1509 return bus_send_error_reply(connection, message, &error, -EINVAL);
1512 if ((r = manager_load_unit(m, name, NULL, &error, &u)) < 0)
1513 return bus_send_error_reply(connection, message, &error, r);
1515 if (reload_if_possible && unit_can_reload(u)) {
1516 if (job_type == JOB_RESTART)
1517 job_type = JOB_RELOAD_OR_START;
1518 else if (job_type == JOB_TRY_RESTART)
1519 job_type = JOB_RELOAD;
1522 if ((job_type == JOB_START && u->refuse_manual_start) ||
1523 (job_type == JOB_STOP && u->refuse_manual_stop) ||
1524 ((job_type == JOB_RESTART || job_type == JOB_TRY_RESTART) &&
1525 (u->refuse_manual_start || u->refuse_manual_stop))) {
1526 dbus_set_error(&error, BUS_ERROR_ONLY_BY_DEPENDENCY, "Operation refused, may be requested by dependency only.");
1527 return bus_send_error_reply(connection, message, &error, -EPERM);
1530 if ((r = manager_add_job(m, job_type, u, mode, true, &error, &j)) < 0)
1531 return bus_send_error_reply(connection, message, &error, r);
1533 cl = job_bus_client_new(connection, message_get_sender_with_fallback(message));
1537 LIST_PREPEND(JobBusClient, client, j->bus_client_list, cl);
1539 if (!(reply = dbus_message_new_method_return(message)))
1542 if (!(path = job_dbus_path(j)))
1545 if (!dbus_message_append_args(
1547 DBUS_TYPE_OBJECT_PATH, &path,
1553 if (!dbus_connection_send(connection, reply, NULL))
1556 dbus_message_unref(reply);
1561 return DBUS_HANDLER_RESULT_HANDLED;
1567 dbus_message_unref(reply);
1569 dbus_error_free(&error);
1571 return DBUS_HANDLER_RESULT_NEED_MEMORY;
1574 const DBusObjectPathVTable bus_manager_vtable = {
1575 .message_function = bus_manager_message_handler