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=\"MountAuto\" type=\"b\" access=\"read\"/>\n" \
241 " <property name=\"SwapAuto\" type=\"b\" access=\"read\"/>\n" \
242 " <property name=\"DefaultControllers\" type=\"as\" access=\"read\"/>\n" \
243 " <property name=\"DefaultStandardOutput\" type=\"s\" access=\"read\"/>\n" \
244 " <property name=\"DefaultStandardError\" type=\"s\" access=\"read\"/>\n" \
245 " <property name=\"RuntimeWatchdogUSec\" type=\"s\" access=\"readwrite\"/>\n" \
246 " <property name=\"ShutdownWatchdogUSec\" type=\"s\" access=\"readwrite\"/>\n" \
247 " <property name=\"HaveWatchdog\" type=\"b\" access=\"read\"/>\n"
249 #ifdef HAVE_SYSV_COMPAT
250 #define BUS_MANAGER_INTERFACE_PROPERTIES_SYSV \
251 " <property name=\"SysVConsole\" type=\"b\" access=\"read\"/>\n" \
252 " <property name=\"SysVInitPath\" type=\"as\" access=\"read\"/>\n" \
253 " <property name=\"SysVRcndPath\" type=\"as\" access=\"read\"/>\n"
255 #define BUS_MANAGER_INTERFACE_PROPERTIES_SYSV
258 #define BUS_MANAGER_INTERFACE_END \
261 #define BUS_MANAGER_INTERFACE \
262 BUS_MANAGER_INTERFACE_BEGIN \
263 BUS_MANAGER_INTERFACE_METHODS \
264 BUS_MANAGER_INTERFACE_SIGNALS \
265 BUS_MANAGER_INTERFACE_PROPERTIES_GENERAL \
266 BUS_MANAGER_INTERFACE_PROPERTIES_SYSV \
267 BUS_MANAGER_INTERFACE_END
269 #define INTROSPECTION_BEGIN \
270 DBUS_INTROSPECT_1_0_XML_DOCTYPE_DECL_NODE \
272 BUS_MANAGER_INTERFACE \
273 BUS_PROPERTIES_INTERFACE \
275 BUS_INTROSPECTABLE_INTERFACE
277 #define INTROSPECTION_END \
280 #define INTERFACES_LIST \
281 BUS_GENERIC_INTERFACES_LIST \
282 "org.freedesktop.systemd1.Manager\0"
284 const char bus_manager_interface[] _introspect_("Manager") = BUS_MANAGER_INTERFACE;
286 static DEFINE_BUS_PROPERTY_APPEND_ENUM(bus_manager_append_running_as, manager_running_as, ManagerRunningAs);
287 static DEFINE_BUS_PROPERTY_APPEND_ENUM(bus_manager_append_exec_output, exec_output, ExecOutput);
289 static int bus_manager_append_tainted(DBusMessageIter *i, const char *property, void *data) {
292 char buf[LINE_MAX] = "", *e = buf, *p = NULL;
299 e = stpcpy(e, "usr-separate-fs ");
301 if (readlink_malloc("/etc/mtab", &p) < 0)
302 e = stpcpy(e, "etc-mtab-not-symlink ");
306 if (access("/proc/cgroups", F_OK) < 0)
307 stpcpy(e, "cgroups-missing ");
311 if (!dbus_message_iter_append_basic(i, DBUS_TYPE_STRING, &t))
317 static int bus_manager_append_log_target(DBusMessageIter *i, const char *property, void *data) {
323 t = log_target_to_string(log_get_target());
325 if (!dbus_message_iter_append_basic(i, DBUS_TYPE_STRING, &t))
331 static int bus_manager_set_log_target(DBusMessageIter *i, const char *property, void *data) {
337 dbus_message_iter_get_basic(i, &t);
339 return log_set_target_from_string(t);
342 static int bus_manager_append_log_level(DBusMessageIter *i, const char *property, void *data) {
348 t = log_level_to_string(log_get_max_level());
350 if (!dbus_message_iter_append_basic(i, DBUS_TYPE_STRING, &t))
356 static int bus_manager_set_log_level(DBusMessageIter *i, const char *property, void *data) {
362 dbus_message_iter_get_basic(i, &t);
364 return log_set_max_level_from_string(t);
367 static int bus_manager_append_n_names(DBusMessageIter *i, const char *property, void *data) {
375 u = hashmap_size(m->units);
377 if (!dbus_message_iter_append_basic(i, DBUS_TYPE_UINT32, &u))
383 static int bus_manager_append_n_jobs(DBusMessageIter *i, const char *property, void *data) {
391 u = hashmap_size(m->jobs);
393 if (!dbus_message_iter_append_basic(i, DBUS_TYPE_UINT32, &u))
399 static int bus_manager_append_progress(DBusMessageIter *i, const char *property, void *data) {
407 if (dual_timestamp_is_set(&m->finish_timestamp))
410 d = 1.0 - ((double) hashmap_size(m->jobs) / (double) m->n_installed_jobs);
412 if (!dbus_message_iter_append_basic(i, DBUS_TYPE_DOUBLE, &d))
418 static const char *message_get_sender_with_fallback(DBusMessage *m) {
423 if ((s = dbus_message_get_sender(m)))
426 /* When the message came in from a direct connection the
427 * message will have no sender. We fix that here. */
432 static DBusMessage *message_from_file_changes(
434 UnitFileChange *changes,
436 int carries_install_info) {
438 DBusMessageIter iter, sub, sub2;
442 reply = dbus_message_new_method_return(m);
446 dbus_message_iter_init_append(reply, &iter);
448 if (carries_install_info >= 0) {
451 b = !!carries_install_info;
452 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &b))
456 if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "(sss)", &sub))
459 for (i = 0; i < n_changes; i++) {
460 const char *type, *path, *source;
462 type = unit_file_change_type_to_string(changes[i].type);
463 path = strempty(changes[i].path);
464 source = strempty(changes[i].source);
466 if (!dbus_message_iter_open_container(&sub, DBUS_TYPE_STRUCT, NULL, &sub2) ||
467 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &type) ||
468 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &path) ||
469 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &source) ||
470 !dbus_message_iter_close_container(&sub, &sub2))
474 if (!dbus_message_iter_close_container(&iter, &sub))
480 dbus_message_unref(reply);
484 static int bus_manager_send_unit_files_changed(Manager *m) {
488 s = dbus_message_new_signal("/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", "UnitFilesChanged");
492 r = bus_broadcast(m, s);
493 dbus_message_unref(s);
498 static int bus_manager_append_have_watchdog(DBusMessageIter *i, const char *property, void *data) {
504 b = access("/dev/watchdog", F_OK) >= 0;
506 if (!dbus_message_iter_append_basic(i, DBUS_TYPE_BOOLEAN, &b))
512 static int bus_manager_set_runtime_watchdog_usec(DBusMessageIter *i, const char *property, void *data) {
518 dbus_message_iter_get_basic(i, t);
520 return watchdog_set_timeout(t);
523 static const char systemd_property_string[] =
528 static const BusProperty bus_systemd_properties[] = {
529 { "Version", bus_property_append_string, "s", 0 },
530 { "Distribution", bus_property_append_string, "s", sizeof(PACKAGE_STRING) },
531 { "Features", bus_property_append_string, "s", sizeof(PACKAGE_STRING) + sizeof(DISTRIBUTION) },
535 static const BusProperty bus_manager_properties[] = {
536 { "RunningAs", bus_manager_append_running_as, "s", offsetof(Manager, running_as) },
537 { "Tainted", bus_manager_append_tainted, "s", 0 },
538 { "InitRDTimestamp", bus_property_append_uint64, "t", offsetof(Manager, initrd_timestamp.realtime) },
539 { "InitRDTimestampMonotonic", bus_property_append_uint64, "t", offsetof(Manager, initrd_timestamp.monotonic) },
540 { "StartupTimestamp", bus_property_append_uint64, "t", offsetof(Manager, startup_timestamp.realtime) },
541 { "StartupTimestampMonotonic", bus_property_append_uint64, "t", offsetof(Manager, startup_timestamp.monotonic) },
542 { "FinishTimestamp", bus_property_append_uint64, "t", offsetof(Manager, finish_timestamp.realtime) },
543 { "FinishTimestampMonotonic", bus_property_append_uint64, "t", offsetof(Manager, finish_timestamp.monotonic) },
544 { "LogLevel", bus_manager_append_log_level, "s", 0, false, bus_manager_set_log_level },
545 { "LogTarget", bus_manager_append_log_target, "s", 0, false, bus_manager_set_log_target },
546 { "NNames", bus_manager_append_n_names, "u", 0 },
547 { "NJobs", bus_manager_append_n_jobs, "u", 0 },
548 { "NInstalledJobs",bus_property_append_uint32, "u", offsetof(Manager, n_installed_jobs) },
549 { "NFailedJobs", bus_property_append_uint32, "u", offsetof(Manager, n_failed_jobs) },
550 { "Progress", bus_manager_append_progress, "d", 0 },
551 { "Environment", bus_property_append_strv, "as", offsetof(Manager, environment), true },
552 { "ConfirmSpawn", bus_property_append_bool, "b", offsetof(Manager, confirm_spawn) },
553 { "ShowStatus", bus_property_append_bool, "b", offsetof(Manager, show_status) },
554 { "UnitPath", bus_property_append_strv, "as", offsetof(Manager, lookup_paths.unit_path), true },
555 { "NotifySocket", bus_property_append_string, "s", offsetof(Manager, notify_socket), true },
556 { "ControlGroupHierarchy", bus_property_append_string, "s", offsetof(Manager, cgroup_hierarchy), true },
557 { "MountAuto", bus_property_append_bool, "b", offsetof(Manager, mount_auto) },
558 { "SwapAuto", bus_property_append_bool, "b", offsetof(Manager, swap_auto) },
559 { "DefaultControllers", bus_property_append_strv, "as", offsetof(Manager, default_controllers), true },
560 { "DefaultStandardOutput", bus_manager_append_exec_output, "s", offsetof(Manager, default_std_output) },
561 { "DefaultStandardError", bus_manager_append_exec_output, "s", offsetof(Manager, default_std_error) },
562 { "RuntimeWatchdogUSec", bus_property_append_usec, "t", offsetof(Manager, runtime_watchdog), false, bus_manager_set_runtime_watchdog_usec },
563 { "ShutdownWatchdogUSec", bus_property_append_usec, "t", offsetof(Manager, shutdown_watchdog), false, bus_property_set_usec },
564 { "HaveWatchdog", bus_manager_append_have_watchdog, "b", 0 },
565 #ifdef HAVE_SYSV_COMPAT
566 { "SysVConsole", bus_property_append_bool, "b", offsetof(Manager, sysv_console) },
567 { "SysVInitPath", bus_property_append_strv, "as", offsetof(Manager, lookup_paths.sysvinit_path), true },
568 { "SysVRcndPath", bus_property_append_strv, "as", offsetof(Manager, lookup_paths.sysvrcnd_path), true },
573 static DBusHandlerResult bus_manager_message_handler(DBusConnection *connection, DBusMessage *message, void *data) {
578 DBusMessage *reply = NULL;
580 JobType job_type = _JOB_TYPE_INVALID;
581 bool reload_if_possible = false;
588 dbus_error_init(&error);
590 member = dbus_message_get_member(message);
592 if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "GetUnit")) {
596 if (!dbus_message_get_args(
599 DBUS_TYPE_STRING, &name,
601 return bus_send_error_reply(connection, message, &error, -EINVAL);
603 if (!(u = manager_get_unit(m, name))) {
604 dbus_set_error(&error, BUS_ERROR_NO_SUCH_UNIT, "Unit %s is not loaded.", name);
605 return bus_send_error_reply(connection, message, &error, -ENOENT);
608 if (!(reply = dbus_message_new_method_return(message)))
611 if (!(path = unit_dbus_path(u)))
614 if (!dbus_message_append_args(
616 DBUS_TYPE_OBJECT_PATH, &path,
619 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "GetUnitByPID")) {
623 if (!dbus_message_get_args(
626 DBUS_TYPE_UINT32, &pid,
628 return bus_send_error_reply(connection, message, &error, -EINVAL);
630 if (!(u = cgroup_unit_by_pid(m, (pid_t) pid))) {
631 dbus_set_error(&error, BUS_ERROR_NO_SUCH_UNIT, "No unit for PID %lu is loaded.", (unsigned long) pid);
632 return bus_send_error_reply(connection, message, &error, -ENOENT);
635 if (!(reply = dbus_message_new_method_return(message)))
638 if (!(path = unit_dbus_path(u)))
641 if (!dbus_message_append_args(
643 DBUS_TYPE_OBJECT_PATH, &path,
646 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "LoadUnit")) {
650 if (!dbus_message_get_args(
653 DBUS_TYPE_STRING, &name,
655 return bus_send_error_reply(connection, message, &error, -EINVAL);
657 if ((r = manager_load_unit(m, name, NULL, &error, &u)) < 0)
658 return bus_send_error_reply(connection, message, &error, r);
660 if (!(reply = dbus_message_new_method_return(message)))
663 if (!(path = unit_dbus_path(u)))
666 if (!dbus_message_append_args(
668 DBUS_TYPE_OBJECT_PATH, &path,
672 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "StartUnit"))
673 job_type = JOB_START;
674 else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "StartUnitReplace"))
675 job_type = JOB_START;
676 else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "StopUnit"))
678 else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ReloadUnit"))
679 job_type = JOB_RELOAD;
680 else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "RestartUnit"))
681 job_type = JOB_RESTART;
682 else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "TryRestartUnit"))
683 job_type = JOB_TRY_RESTART;
684 else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ReloadOrRestartUnit")) {
685 reload_if_possible = true;
686 job_type = JOB_RESTART;
687 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ReloadOrTryRestartUnit")) {
688 reload_if_possible = true;
689 job_type = JOB_TRY_RESTART;
690 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "KillUnit")) {
691 const char *name, *swho, *smode;
697 if (!dbus_message_get_args(
700 DBUS_TYPE_STRING, &name,
701 DBUS_TYPE_STRING, &swho,
702 DBUS_TYPE_STRING, &smode,
703 DBUS_TYPE_INT32, &signo,
705 return bus_send_error_reply(connection, message, &error, -EINVAL);
710 who = kill_who_from_string(swho);
712 return bus_send_error_reply(connection, message, &error, -EINVAL);
716 mode = KILL_CONTROL_GROUP;
718 mode = kill_mode_from_string(smode);
720 return bus_send_error_reply(connection, message, &error, -EINVAL);
723 if (signo <= 0 || signo >= _NSIG)
724 return bus_send_error_reply(connection, message, &error, -EINVAL);
726 if (!(u = manager_get_unit(m, name))) {
727 dbus_set_error(&error, BUS_ERROR_NO_SUCH_UNIT, "Unit %s is not loaded.", name);
728 return bus_send_error_reply(connection, message, &error, -ENOENT);
731 if ((r = unit_kill(u, who, mode, signo, &error)) < 0)
732 return bus_send_error_reply(connection, message, &error, r);
734 if (!(reply = dbus_message_new_method_return(message)))
737 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "GetJob")) {
741 if (!dbus_message_get_args(
744 DBUS_TYPE_UINT32, &id,
746 return bus_send_error_reply(connection, message, &error, -EINVAL);
748 if (!(j = manager_get_job(m, id))) {
749 dbus_set_error(&error, BUS_ERROR_NO_SUCH_JOB, "Job %u does not exist.", (unsigned) id);
750 return bus_send_error_reply(connection, message, &error, -ENOENT);
753 if (!(reply = dbus_message_new_method_return(message)))
756 if (!(path = job_dbus_path(j)))
759 if (!dbus_message_append_args(
761 DBUS_TYPE_OBJECT_PATH, &path,
765 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ClearJobs")) {
767 manager_clear_jobs(m);
769 if (!(reply = dbus_message_new_method_return(message)))
772 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ResetFailed")) {
774 manager_reset_failed(m);
776 if (!(reply = dbus_message_new_method_return(message)))
779 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ResetFailedUnit")) {
783 if (!dbus_message_get_args(
786 DBUS_TYPE_STRING, &name,
788 return bus_send_error_reply(connection, message, &error, -EINVAL);
790 if (!(u = manager_get_unit(m, name))) {
791 dbus_set_error(&error, BUS_ERROR_NO_SUCH_UNIT, "Unit %s is not loaded.", name);
792 return bus_send_error_reply(connection, message, &error, -ENOENT);
795 unit_reset_failed(u);
797 if (!(reply = dbus_message_new_method_return(message)))
800 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ListUnits")) {
801 DBusMessageIter iter, sub;
806 if (!(reply = dbus_message_new_method_return(message)))
809 dbus_message_iter_init_append(reply, &iter);
811 if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "(ssssssouso)", &sub))
814 HASHMAP_FOREACH_KEY(u, k, m->units, i) {
815 char *u_path, *j_path;
816 const char *description, *load_state, *active_state, *sub_state, *sjob_type, *following;
817 DBusMessageIter sub2;
824 if (!dbus_message_iter_open_container(&sub, DBUS_TYPE_STRUCT, NULL, &sub2))
827 description = unit_description(u);
828 load_state = unit_load_state_to_string(u->load_state);
829 active_state = unit_active_state_to_string(unit_active_state(u));
830 sub_state = unit_sub_state_to_string(u);
832 f = unit_following(u);
833 following = f ? f->id : "";
835 if (!(u_path = unit_dbus_path(u)))
839 job_id = (uint32_t) u->job->id;
841 if (!(j_path = job_dbus_path(u->job))) {
846 sjob_type = job_type_to_string(u->job->type);
853 if (!dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &u->id) ||
854 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &description) ||
855 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &load_state) ||
856 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &active_state) ||
857 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &sub_state) ||
858 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &following) ||
859 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_OBJECT_PATH, &u_path) ||
860 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_UINT32, &job_id) ||
861 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &sjob_type) ||
862 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_OBJECT_PATH, &j_path)) {
873 if (!dbus_message_iter_close_container(&sub, &sub2))
877 if (!dbus_message_iter_close_container(&iter, &sub))
880 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ListJobs")) {
881 DBusMessageIter iter, sub;
885 if (!(reply = dbus_message_new_method_return(message)))
888 dbus_message_iter_init_append(reply, &iter);
890 if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "(usssoo)", &sub))
893 HASHMAP_FOREACH(j, m->jobs, i) {
894 char *u_path, *j_path;
895 const char *state, *type;
897 DBusMessageIter sub2;
899 if (!dbus_message_iter_open_container(&sub, DBUS_TYPE_STRUCT, NULL, &sub2))
902 id = (uint32_t) j->id;
903 state = job_state_to_string(j->state);
904 type = job_type_to_string(j->type);
906 if (!(j_path = job_dbus_path(j)))
909 if (!(u_path = unit_dbus_path(j->unit))) {
914 if (!dbus_message_iter_append_basic(&sub2, DBUS_TYPE_UINT32, &id) ||
915 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &j->unit->id) ||
916 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &type) ||
917 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &state) ||
918 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_OBJECT_PATH, &j_path) ||
919 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_OBJECT_PATH, &u_path)) {
928 if (!dbus_message_iter_close_container(&sub, &sub2))
932 if (!dbus_message_iter_close_container(&iter, &sub))
935 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "Subscribe")) {
939 if (!(s = BUS_CONNECTION_SUBSCRIBED(m, connection))) {
940 if (!(s = set_new(string_hash_func, string_compare_func)))
943 if (!(dbus_connection_set_data(connection, m->subscribed_data_slot, s, NULL))) {
949 if (!(client = strdup(message_get_sender_with_fallback(message))))
952 if ((r = set_put(s, client)) < 0) {
954 return bus_send_error_reply(connection, message, NULL, r);
957 if (!(reply = dbus_message_new_method_return(message)))
960 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "Unsubscribe")) {
963 if (!(client = set_remove(BUS_CONNECTION_SUBSCRIBED(m, connection), (char*) message_get_sender_with_fallback(message)))) {
964 dbus_set_error(&error, BUS_ERROR_NOT_SUBSCRIBED, "Client is not subscribed.");
965 return bus_send_error_reply(connection, message, &error, -ENOENT);
970 if (!(reply = dbus_message_new_method_return(message)))
973 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "Dump")) {
978 if (!(reply = dbus_message_new_method_return(message)))
981 if (!(f = open_memstream(&dump, &size)))
984 manager_dump_units(m, f, NULL);
985 manager_dump_jobs(m, f, NULL);
995 if (!dbus_message_append_args(reply, DBUS_TYPE_STRING, &dump, DBUS_TYPE_INVALID)) {
1001 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "CreateSnapshot")) {
1003 dbus_bool_t cleanup;
1006 if (!dbus_message_get_args(
1009 DBUS_TYPE_STRING, &name,
1010 DBUS_TYPE_BOOLEAN, &cleanup,
1012 return bus_send_error_reply(connection, message, &error, -EINVAL);
1014 if (name && name[0] == 0)
1017 if ((r = snapshot_create(m, name, cleanup, &error, &s)) < 0)
1018 return bus_send_error_reply(connection, message, &error, r);
1020 if (!(reply = dbus_message_new_method_return(message)))
1023 if (!(path = unit_dbus_path(UNIT(s))))
1026 if (!dbus_message_append_args(
1028 DBUS_TYPE_OBJECT_PATH, &path,
1032 } else if (dbus_message_is_method_call(message, "org.freedesktop.DBus.Introspectable", "Introspect")) {
1033 char *introspection = NULL;
1041 if (!(reply = dbus_message_new_method_return(message)))
1044 /* We roll our own introspection code here, instead of
1045 * relying on bus_default_message_handler() because we
1046 * need to generate our introspection string
1049 if (!(f = open_memstream(&introspection, &size)))
1052 fputs(INTROSPECTION_BEGIN, f);
1054 HASHMAP_FOREACH_KEY(u, k, m->units, i) {
1060 if (!(p = bus_path_escape(k))) {
1062 free(introspection);
1066 fprintf(f, "<node name=\"unit/%s\"/>", p);
1070 HASHMAP_FOREACH(j, m->jobs, i)
1071 fprintf(f, "<node name=\"job/%lu\"/>", (unsigned long) j->id);
1073 fputs(INTROSPECTION_END, f);
1077 free(introspection);
1086 if (!dbus_message_append_args(reply, DBUS_TYPE_STRING, &introspection, DBUS_TYPE_INVALID)) {
1087 free(introspection);
1091 free(introspection);
1093 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "Reload")) {
1095 assert(!m->queued_message);
1097 /* Instead of sending the reply back right away, we
1098 * just remember that we need to and then send it
1099 * after the reload is finished. That way the caller
1100 * knows when the reload finished. */
1102 if (!(m->queued_message = dbus_message_new_method_return(message)))
1105 m->queued_message_connection = connection;
1106 m->exit_code = MANAGER_RELOAD;
1108 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "Reexecute")) {
1110 /* We don't send a reply back here, the client should
1111 * just wait for us disconnecting. */
1113 m->exit_code = MANAGER_REEXECUTE;
1115 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "Exit")) {
1117 if (m->running_as == MANAGER_SYSTEM) {
1118 dbus_set_error(&error, BUS_ERROR_NOT_SUPPORTED, "Exit is only supported for user service managers.");
1119 return bus_send_error_reply(connection, message, &error, -ENOTSUP);
1122 if (!(reply = dbus_message_new_method_return(message)))
1125 m->exit_code = MANAGER_EXIT;
1127 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "Reboot")) {
1129 if (m->running_as != MANAGER_SYSTEM) {
1130 dbus_set_error(&error, BUS_ERROR_NOT_SUPPORTED, "Reboot is only supported for system managers.");
1131 return bus_send_error_reply(connection, message, &error, -ENOTSUP);
1134 if (!(reply = dbus_message_new_method_return(message)))
1137 m->exit_code = MANAGER_REBOOT;
1139 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "PowerOff")) {
1141 if (m->running_as != MANAGER_SYSTEM) {
1142 dbus_set_error(&error, BUS_ERROR_NOT_SUPPORTED, "Powering off is only supported for system managers.");
1143 return bus_send_error_reply(connection, message, &error, -ENOTSUP);
1146 if (!(reply = dbus_message_new_method_return(message)))
1149 m->exit_code = MANAGER_POWEROFF;
1151 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "Halt")) {
1153 if (m->running_as != MANAGER_SYSTEM) {
1154 dbus_set_error(&error, BUS_ERROR_NOT_SUPPORTED, "Halting is only supported for system managers.");
1155 return bus_send_error_reply(connection, message, &error, -ENOTSUP);
1158 if (!(reply = dbus_message_new_method_return(message)))
1161 m->exit_code = MANAGER_HALT;
1163 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "KExec")) {
1165 if (m->running_as != MANAGER_SYSTEM) {
1166 dbus_set_error(&error, BUS_ERROR_NOT_SUPPORTED, "kexec is only supported for system managers.");
1167 return bus_send_error_reply(connection, message, &error, -ENOTSUP);
1170 if (!(reply = dbus_message_new_method_return(message)))
1173 m->exit_code = MANAGER_KEXEC;
1175 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "SetEnvironment")) {
1176 char **l = NULL, **e = NULL;
1178 if ((r = bus_parse_strv(message, &l)) < 0) {
1182 return bus_send_error_reply(connection, message, NULL, r);
1185 e = strv_env_merge(2, m->environment, l);
1191 if (!(reply = dbus_message_new_method_return(message))) {
1196 strv_free(m->environment);
1199 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "UnsetEnvironment")) {
1200 char **l = NULL, **e = NULL;
1202 if ((r = bus_parse_strv(message, &l)) < 0) {
1206 return bus_send_error_reply(connection, message, NULL, r);
1209 e = strv_env_delete(m->environment, 1, l);
1215 if (!(reply = dbus_message_new_method_return(message))) {
1220 strv_free(m->environment);
1223 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "UnsetAndSetEnvironment")) {
1224 char **l_set = NULL, **l_unset = NULL, **e = NULL, **f = NULL;
1225 DBusMessageIter iter;
1227 if (!dbus_message_iter_init(message, &iter))
1230 r = bus_parse_strv_iter(&iter, &l_unset);
1235 return bus_send_error_reply(connection, message, NULL, r);
1238 if (!dbus_message_iter_next(&iter)) {
1240 return bus_send_error_reply(connection, message, NULL, -EINVAL);
1243 r = bus_parse_strv_iter(&iter, &l_set);
1249 return bus_send_error_reply(connection, message, NULL, r);
1252 e = strv_env_delete(m->environment, 1, l_unset);
1260 f = strv_env_merge(2, e, l_set);
1267 if (!(reply = dbus_message_new_method_return(message))) {
1272 strv_free(m->environment);
1274 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ListUnitFiles")) {
1275 DBusMessageIter iter, sub, sub2;
1280 reply = dbus_message_new_method_return(message);
1284 h = hashmap_new(string_hash_func, string_compare_func);
1288 r = unit_file_get_list(m->running_as == MANAGER_SYSTEM ? UNIT_FILE_SYSTEM : UNIT_FILE_USER, NULL, h);
1290 unit_file_list_free(h);
1291 dbus_message_unref(reply);
1292 return bus_send_error_reply(connection, message, NULL, r);
1295 dbus_message_iter_init_append(reply, &iter);
1297 if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "(ss)", &sub)) {
1298 unit_file_list_free(h);
1302 HASHMAP_FOREACH(item, h, i) {
1305 state = unit_file_state_to_string(item->state);
1308 if (!dbus_message_iter_open_container(&sub, DBUS_TYPE_STRUCT, NULL, &sub2) ||
1309 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &item->path) ||
1310 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &state) ||
1311 !dbus_message_iter_close_container(&sub, &sub2)) {
1312 unit_file_list_free(h);
1317 unit_file_list_free(h);
1319 if (!dbus_message_iter_close_container(&iter, &sub))
1322 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "GetUnitFileState")) {
1324 UnitFileState state;
1327 if (!dbus_message_get_args(
1330 DBUS_TYPE_STRING, &name,
1332 return bus_send_error_reply(connection, message, &error, -EINVAL);
1334 state = unit_file_get_state(m->running_as == MANAGER_SYSTEM ? UNIT_FILE_SYSTEM : UNIT_FILE_USER, NULL, name);
1336 return bus_send_error_reply(connection, message, NULL, state);
1338 s = unit_file_state_to_string(state);
1341 reply = dbus_message_new_method_return(message);
1345 if (!dbus_message_append_args(
1347 DBUS_TYPE_STRING, &s,
1350 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "EnableUnitFiles") ||
1351 dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ReenableUnitFiles") ||
1352 dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "LinkUnitFiles") ||
1353 dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "PresetUnitFiles") ||
1354 dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "MaskUnitFiles")) {
1357 DBusMessageIter iter;
1358 UnitFileScope scope = m->running_as == MANAGER_SYSTEM ? UNIT_FILE_SYSTEM : UNIT_FILE_USER;
1359 UnitFileChange *changes = NULL;
1360 unsigned n_changes = 0;
1361 dbus_bool_t runtime, force;
1362 int carries_install_info = -1;
1364 if (!dbus_message_iter_init(message, &iter))
1367 r = bus_parse_strv_iter(&iter, &l);
1372 return bus_send_error_reply(connection, message, NULL, r);
1375 if (!dbus_message_iter_next(&iter) ||
1376 bus_iter_get_basic_and_next(&iter, DBUS_TYPE_BOOLEAN, &runtime, true) < 0 ||
1377 bus_iter_get_basic_and_next(&iter, DBUS_TYPE_BOOLEAN, &force, false) < 0) {
1379 return bus_send_error_reply(connection, message, NULL, -EIO);
1382 if (streq(member, "EnableUnitFiles")) {
1383 r = unit_file_enable(scope, runtime, NULL, l, force, &changes, &n_changes);
1384 carries_install_info = r;
1385 } else if (streq(member, "ReenableUnitFiles")) {
1386 r = unit_file_reenable(scope, runtime, NULL, l, force, &changes, &n_changes);
1387 carries_install_info = r;
1388 } else if (streq(member, "LinkUnitFiles"))
1389 r = unit_file_link(scope, runtime, NULL, l, force, &changes, &n_changes);
1390 else if (streq(member, "PresetUnitFiles")) {
1391 r = unit_file_preset(scope, runtime, NULL, l, force, &changes, &n_changes);
1392 carries_install_info = r;
1393 } else if (streq(member, "MaskUnitFiles"))
1394 r = unit_file_mask(scope, runtime, NULL, l, force, &changes, &n_changes);
1396 assert_not_reached("Uh? Wrong method");
1399 bus_manager_send_unit_files_changed(m);
1402 unit_file_changes_free(changes, n_changes);
1403 return bus_send_error_reply(connection, message, NULL, r);
1406 reply = message_from_file_changes(message, changes, n_changes, carries_install_info);
1407 unit_file_changes_free(changes, n_changes);
1412 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "DisableUnitFiles") ||
1413 dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "UnmaskUnitFiles")) {
1416 DBusMessageIter iter;
1417 UnitFileScope scope = m->running_as == MANAGER_SYSTEM ? UNIT_FILE_SYSTEM : UNIT_FILE_USER;
1418 UnitFileChange *changes = NULL;
1419 unsigned n_changes = 0;
1420 dbus_bool_t runtime;
1422 if (!dbus_message_iter_init(message, &iter))
1425 r = bus_parse_strv_iter(&iter, &l);
1430 return bus_send_error_reply(connection, message, NULL, r);
1433 if (!dbus_message_iter_next(&iter) ||
1434 bus_iter_get_basic_and_next(&iter, DBUS_TYPE_BOOLEAN, &runtime, false) < 0) {
1436 return bus_send_error_reply(connection, message, NULL, -EIO);
1439 if (streq(member, "DisableUnitFiles"))
1440 r = unit_file_disable(scope, runtime, NULL, l, &changes, &n_changes);
1441 else if (streq(member, "UnmaskUnitFiles"))
1442 r = unit_file_unmask(scope, runtime, NULL, l, &changes, &n_changes);
1444 assert_not_reached("Uh? Wrong method");
1447 bus_manager_send_unit_files_changed(m);
1450 unit_file_changes_free(changes, n_changes);
1451 return bus_send_error_reply(connection, message, NULL, r);
1454 reply = message_from_file_changes(message, changes, n_changes, -1);
1455 unit_file_changes_free(changes, n_changes);
1461 const BusBoundProperties bps[] = {
1462 { "org.freedesktop.systemd1.Manager", bus_systemd_properties, systemd_property_string },
1463 { "org.freedesktop.systemd1.Manager", bus_manager_properties, m },
1466 return bus_default_message_handler(connection, message, NULL, INTERFACES_LIST, bps);
1469 if (job_type != _JOB_TYPE_INVALID) {
1470 const char *name, *smode, *old_name = NULL;
1476 if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "StartUnitReplace"))
1477 b = dbus_message_get_args(
1480 DBUS_TYPE_STRING, &old_name,
1481 DBUS_TYPE_STRING, &name,
1482 DBUS_TYPE_STRING, &smode,
1485 b = dbus_message_get_args(
1488 DBUS_TYPE_STRING, &name,
1489 DBUS_TYPE_STRING, &smode,
1493 return bus_send_error_reply(connection, message, &error, -EINVAL);
1496 if (!(u = manager_get_unit(m, old_name)) ||
1498 u->job->type != JOB_START) {
1499 dbus_set_error(&error, BUS_ERROR_NO_SUCH_JOB, "No job queued for unit %s", old_name);
1500 return bus_send_error_reply(connection, message, &error, -ENOENT);
1504 if ((mode = job_mode_from_string(smode)) == _JOB_MODE_INVALID) {
1505 dbus_set_error(&error, BUS_ERROR_INVALID_JOB_MODE, "Job mode %s is invalid.", smode);
1506 return bus_send_error_reply(connection, message, &error, -EINVAL);
1509 if ((r = manager_load_unit(m, name, NULL, &error, &u)) < 0)
1510 return bus_send_error_reply(connection, message, &error, r);
1512 if (reload_if_possible && unit_can_reload(u)) {
1513 if (job_type == JOB_RESTART)
1514 job_type = JOB_RELOAD_OR_START;
1515 else if (job_type == JOB_TRY_RESTART)
1516 job_type = JOB_RELOAD;
1519 if ((job_type == JOB_START && u->refuse_manual_start) ||
1520 (job_type == JOB_STOP && u->refuse_manual_stop) ||
1521 ((job_type == JOB_RESTART || job_type == JOB_TRY_RESTART) &&
1522 (u->refuse_manual_start || u->refuse_manual_stop))) {
1523 dbus_set_error(&error, BUS_ERROR_ONLY_BY_DEPENDENCY, "Operation refused, may be requested by dependency only.");
1524 return bus_send_error_reply(connection, message, &error, -EPERM);
1527 if ((r = manager_add_job(m, job_type, u, mode, true, &error, &j)) < 0)
1528 return bus_send_error_reply(connection, message, &error, r);
1530 if (!(j->bus_client = strdup(message_get_sender_with_fallback(message))))
1533 j->bus = connection;
1535 if (!(reply = dbus_message_new_method_return(message)))
1538 if (!(path = job_dbus_path(j)))
1541 if (!dbus_message_append_args(
1543 DBUS_TYPE_OBJECT_PATH, &path,
1549 if (!dbus_connection_send(connection, reply, NULL))
1552 dbus_message_unref(reply);
1557 return DBUS_HANDLER_RESULT_HANDLED;
1563 dbus_message_unref(reply);
1565 dbus_error_free(&error);
1567 return DBUS_HANDLER_RESULT_NEED_MEMORY;
1570 const DBusObjectPathVTable bus_manager_vtable = {
1571 .message_function = bus_manager_message_handler