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, "usr-separate-fs ");
299 if (readlink_malloc("/etc/mtab", &p) < 0)
300 e = stpcpy(e, "etc-mtab-not-symlink ");
304 if (access("/proc/cgroups", F_OK) < 0)
305 stpcpy(e, "cgroups-missing ");
309 if (!dbus_message_iter_append_basic(i, DBUS_TYPE_STRING, &t))
315 static int bus_manager_append_log_target(DBusMessageIter *i, const char *property, void *data) {
321 t = log_target_to_string(log_get_target());
323 if (!dbus_message_iter_append_basic(i, DBUS_TYPE_STRING, &t))
329 static int bus_manager_set_log_target(DBusMessageIter *i, const char *property, void *data) {
335 dbus_message_iter_get_basic(i, &t);
337 return log_set_target_from_string(t);
340 static int bus_manager_append_log_level(DBusMessageIter *i, const char *property, void *data) {
346 t = log_level_to_string(log_get_max_level());
348 if (!dbus_message_iter_append_basic(i, DBUS_TYPE_STRING, &t))
354 static int bus_manager_set_log_level(DBusMessageIter *i, const char *property, void *data) {
360 dbus_message_iter_get_basic(i, &t);
362 return log_set_max_level_from_string(t);
365 static int bus_manager_append_n_names(DBusMessageIter *i, const char *property, void *data) {
373 u = hashmap_size(m->units);
375 if (!dbus_message_iter_append_basic(i, DBUS_TYPE_UINT32, &u))
381 static int bus_manager_append_n_jobs(DBusMessageIter *i, const char *property, void *data) {
389 u = hashmap_size(m->jobs);
391 if (!dbus_message_iter_append_basic(i, DBUS_TYPE_UINT32, &u))
397 static int bus_manager_append_progress(DBusMessageIter *i, const char *property, void *data) {
405 if (dual_timestamp_is_set(&m->finish_timestamp))
408 d = 1.0 - ((double) hashmap_size(m->jobs) / (double) m->n_installed_jobs);
410 if (!dbus_message_iter_append_basic(i, DBUS_TYPE_DOUBLE, &d))
416 static const char *message_get_sender_with_fallback(DBusMessage *m) {
421 if ((s = dbus_message_get_sender(m)))
424 /* When the message came in from a direct connection the
425 * message will have no sender. We fix that here. */
430 static DBusMessage *message_from_file_changes(
432 UnitFileChange *changes,
434 int carries_install_info) {
436 DBusMessageIter iter, sub, sub2;
440 reply = dbus_message_new_method_return(m);
444 dbus_message_iter_init_append(reply, &iter);
446 if (carries_install_info >= 0) {
449 b = !!carries_install_info;
450 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &b))
454 if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "(sss)", &sub))
457 for (i = 0; i < n_changes; i++) {
458 const char *type, *path, *source;
460 type = unit_file_change_type_to_string(changes[i].type);
461 path = strempty(changes[i].path);
462 source = strempty(changes[i].source);
464 if (!dbus_message_iter_open_container(&sub, DBUS_TYPE_STRUCT, NULL, &sub2) ||
465 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &type) ||
466 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &path) ||
467 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &source) ||
468 !dbus_message_iter_close_container(&sub, &sub2))
472 if (!dbus_message_iter_close_container(&iter, &sub))
478 dbus_message_unref(reply);
482 static int bus_manager_send_unit_files_changed(Manager *m) {
486 s = dbus_message_new_signal("/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", "UnitFilesChanged");
490 r = bus_broadcast(m, s);
491 dbus_message_unref(s);
496 static int bus_manager_append_have_watchdog(DBusMessageIter *i, const char *property, void *data) {
502 b = access("/dev/watchdog", F_OK) >= 0;
504 if (!dbus_message_iter_append_basic(i, DBUS_TYPE_BOOLEAN, &b))
510 static int bus_manager_set_runtime_watchdog_usec(DBusMessageIter *i, const char *property, void *data) {
516 dbus_message_iter_get_basic(i, t);
518 return watchdog_set_timeout(t);
521 static const char systemd_property_string[] =
526 static const BusProperty bus_systemd_properties[] = {
527 { "Version", bus_property_append_string, "s", 0 },
528 { "Distribution", bus_property_append_string, "s", sizeof(PACKAGE_STRING) },
529 { "Features", bus_property_append_string, "s", sizeof(PACKAGE_STRING) + sizeof(DISTRIBUTION) },
533 static const BusProperty bus_manager_properties[] = {
534 { "RunningAs", bus_manager_append_running_as, "s", offsetof(Manager, running_as) },
535 { "Tainted", bus_manager_append_tainted, "s", 0 },
536 { "InitRDTimestamp", bus_property_append_uint64, "t", offsetof(Manager, initrd_timestamp.realtime) },
537 { "InitRDTimestampMonotonic", bus_property_append_uint64, "t", offsetof(Manager, initrd_timestamp.monotonic) },
538 { "StartupTimestamp", bus_property_append_uint64, "t", offsetof(Manager, startup_timestamp.realtime) },
539 { "StartupTimestampMonotonic", bus_property_append_uint64, "t", offsetof(Manager, startup_timestamp.monotonic) },
540 { "FinishTimestamp", bus_property_append_uint64, "t", offsetof(Manager, finish_timestamp.realtime) },
541 { "FinishTimestampMonotonic", bus_property_append_uint64, "t", offsetof(Manager, finish_timestamp.monotonic) },
542 { "LogLevel", bus_manager_append_log_level, "s", 0, false, bus_manager_set_log_level },
543 { "LogTarget", bus_manager_append_log_target, "s", 0, false, bus_manager_set_log_target },
544 { "NNames", bus_manager_append_n_names, "u", 0 },
545 { "NJobs", bus_manager_append_n_jobs, "u", 0 },
546 { "NInstalledJobs",bus_property_append_uint32, "u", offsetof(Manager, n_installed_jobs) },
547 { "NFailedJobs", bus_property_append_uint32, "u", offsetof(Manager, n_failed_jobs) },
548 { "Progress", bus_manager_append_progress, "d", 0 },
549 { "Environment", bus_property_append_strv, "as", offsetof(Manager, environment), true },
550 { "ConfirmSpawn", bus_property_append_bool, "b", offsetof(Manager, confirm_spawn) },
551 { "ShowStatus", bus_property_append_bool, "b", offsetof(Manager, show_status) },
552 { "UnitPath", bus_property_append_strv, "as", offsetof(Manager, lookup_paths.unit_path), true },
553 { "NotifySocket", bus_property_append_string, "s", offsetof(Manager, notify_socket), true },
554 { "ControlGroupHierarchy", bus_property_append_string, "s", offsetof(Manager, cgroup_hierarchy), true },
555 { "DefaultControllers", bus_property_append_strv, "as", offsetof(Manager, default_controllers), true },
556 { "DefaultStandardOutput", bus_manager_append_exec_output, "s", offsetof(Manager, default_std_output) },
557 { "DefaultStandardError", bus_manager_append_exec_output, "s", offsetof(Manager, default_std_error) },
558 { "RuntimeWatchdogUSec", bus_property_append_usec, "t", offsetof(Manager, runtime_watchdog), false, bus_manager_set_runtime_watchdog_usec },
559 { "ShutdownWatchdogUSec", bus_property_append_usec, "t", offsetof(Manager, shutdown_watchdog), false, bus_property_set_usec },
560 { "HaveWatchdog", bus_manager_append_have_watchdog, "b", 0 },
561 #ifdef HAVE_SYSV_COMPAT
562 { "SysVConsole", bus_property_append_bool, "b", offsetof(Manager, sysv_console) },
563 { "SysVInitPath", bus_property_append_strv, "as", offsetof(Manager, lookup_paths.sysvinit_path), true },
564 { "SysVRcndPath", bus_property_append_strv, "as", offsetof(Manager, lookup_paths.sysvrcnd_path), true },
569 static DBusHandlerResult bus_manager_message_handler(DBusConnection *connection, DBusMessage *message, void *data) {
574 DBusMessage *reply = NULL;
576 JobType job_type = _JOB_TYPE_INVALID;
577 bool reload_if_possible = false;
584 dbus_error_init(&error);
586 member = dbus_message_get_member(message);
588 if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "GetUnit")) {
592 if (!dbus_message_get_args(
595 DBUS_TYPE_STRING, &name,
597 return bus_send_error_reply(connection, message, &error, -EINVAL);
599 if (!(u = manager_get_unit(m, name))) {
600 dbus_set_error(&error, BUS_ERROR_NO_SUCH_UNIT, "Unit %s is not loaded.", name);
601 return bus_send_error_reply(connection, message, &error, -ENOENT);
604 if (!(reply = dbus_message_new_method_return(message)))
607 if (!(path = unit_dbus_path(u)))
610 if (!dbus_message_append_args(
612 DBUS_TYPE_OBJECT_PATH, &path,
615 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "GetUnitByPID")) {
619 if (!dbus_message_get_args(
622 DBUS_TYPE_UINT32, &pid,
624 return bus_send_error_reply(connection, message, &error, -EINVAL);
626 if (!(u = cgroup_unit_by_pid(m, (pid_t) pid))) {
627 dbus_set_error(&error, BUS_ERROR_NO_SUCH_UNIT, "No unit for PID %lu is loaded.", (unsigned long) pid);
628 return bus_send_error_reply(connection, message, &error, -ENOENT);
631 if (!(reply = dbus_message_new_method_return(message)))
634 if (!(path = unit_dbus_path(u)))
637 if (!dbus_message_append_args(
639 DBUS_TYPE_OBJECT_PATH, &path,
642 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "LoadUnit")) {
646 if (!dbus_message_get_args(
649 DBUS_TYPE_STRING, &name,
651 return bus_send_error_reply(connection, message, &error, -EINVAL);
653 if ((r = manager_load_unit(m, name, NULL, &error, &u)) < 0)
654 return bus_send_error_reply(connection, message, &error, r);
656 if (!(reply = dbus_message_new_method_return(message)))
659 if (!(path = unit_dbus_path(u)))
662 if (!dbus_message_append_args(
664 DBUS_TYPE_OBJECT_PATH, &path,
668 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "StartUnit"))
669 job_type = JOB_START;
670 else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "StartUnitReplace"))
671 job_type = JOB_START;
672 else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "StopUnit"))
674 else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ReloadUnit"))
675 job_type = JOB_RELOAD;
676 else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "RestartUnit"))
677 job_type = JOB_RESTART;
678 else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "TryRestartUnit"))
679 job_type = JOB_TRY_RESTART;
680 else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ReloadOrRestartUnit")) {
681 reload_if_possible = true;
682 job_type = JOB_RESTART;
683 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ReloadOrTryRestartUnit")) {
684 reload_if_possible = true;
685 job_type = JOB_TRY_RESTART;
686 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "KillUnit")) {
687 const char *name, *swho, *smode;
693 if (!dbus_message_get_args(
696 DBUS_TYPE_STRING, &name,
697 DBUS_TYPE_STRING, &swho,
698 DBUS_TYPE_STRING, &smode,
699 DBUS_TYPE_INT32, &signo,
701 return bus_send_error_reply(connection, message, &error, -EINVAL);
706 who = kill_who_from_string(swho);
708 return bus_send_error_reply(connection, message, &error, -EINVAL);
712 mode = KILL_CONTROL_GROUP;
714 mode = kill_mode_from_string(smode);
716 return bus_send_error_reply(connection, message, &error, -EINVAL);
719 if (signo <= 0 || signo >= _NSIG)
720 return bus_send_error_reply(connection, message, &error, -EINVAL);
722 if (!(u = manager_get_unit(m, name))) {
723 dbus_set_error(&error, BUS_ERROR_NO_SUCH_UNIT, "Unit %s is not loaded.", name);
724 return bus_send_error_reply(connection, message, &error, -ENOENT);
727 if ((r = unit_kill(u, who, mode, signo, &error)) < 0)
728 return bus_send_error_reply(connection, message, &error, r);
730 if (!(reply = dbus_message_new_method_return(message)))
733 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "GetJob")) {
737 if (!dbus_message_get_args(
740 DBUS_TYPE_UINT32, &id,
742 return bus_send_error_reply(connection, message, &error, -EINVAL);
744 if (!(j = manager_get_job(m, id))) {
745 dbus_set_error(&error, BUS_ERROR_NO_SUCH_JOB, "Job %u does not exist.", (unsigned) id);
746 return bus_send_error_reply(connection, message, &error, -ENOENT);
749 if (!(reply = dbus_message_new_method_return(message)))
752 if (!(path = job_dbus_path(j)))
755 if (!dbus_message_append_args(
757 DBUS_TYPE_OBJECT_PATH, &path,
761 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ClearJobs")) {
763 manager_clear_jobs(m);
765 if (!(reply = dbus_message_new_method_return(message)))
768 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ResetFailed")) {
770 manager_reset_failed(m);
772 if (!(reply = dbus_message_new_method_return(message)))
775 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ResetFailedUnit")) {
779 if (!dbus_message_get_args(
782 DBUS_TYPE_STRING, &name,
784 return bus_send_error_reply(connection, message, &error, -EINVAL);
786 if (!(u = manager_get_unit(m, name))) {
787 dbus_set_error(&error, BUS_ERROR_NO_SUCH_UNIT, "Unit %s is not loaded.", name);
788 return bus_send_error_reply(connection, message, &error, -ENOENT);
791 unit_reset_failed(u);
793 if (!(reply = dbus_message_new_method_return(message)))
796 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ListUnits")) {
797 DBusMessageIter iter, sub;
802 if (!(reply = dbus_message_new_method_return(message)))
805 dbus_message_iter_init_append(reply, &iter);
807 if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "(ssssssouso)", &sub))
810 HASHMAP_FOREACH_KEY(u, k, m->units, i) {
811 char *u_path, *j_path;
812 const char *description, *load_state, *active_state, *sub_state, *sjob_type, *following;
813 DBusMessageIter sub2;
820 if (!dbus_message_iter_open_container(&sub, DBUS_TYPE_STRUCT, NULL, &sub2))
823 description = unit_description(u);
824 load_state = unit_load_state_to_string(u->load_state);
825 active_state = unit_active_state_to_string(unit_active_state(u));
826 sub_state = unit_sub_state_to_string(u);
828 f = unit_following(u);
829 following = f ? f->id : "";
831 if (!(u_path = unit_dbus_path(u)))
835 job_id = (uint32_t) u->job->id;
837 if (!(j_path = job_dbus_path(u->job))) {
842 sjob_type = job_type_to_string(u->job->type);
849 if (!dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &u->id) ||
850 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &description) ||
851 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &load_state) ||
852 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &active_state) ||
853 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &sub_state) ||
854 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &following) ||
855 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_OBJECT_PATH, &u_path) ||
856 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_UINT32, &job_id) ||
857 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &sjob_type) ||
858 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_OBJECT_PATH, &j_path)) {
869 if (!dbus_message_iter_close_container(&sub, &sub2))
873 if (!dbus_message_iter_close_container(&iter, &sub))
876 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ListJobs")) {
877 DBusMessageIter iter, sub;
881 if (!(reply = dbus_message_new_method_return(message)))
884 dbus_message_iter_init_append(reply, &iter);
886 if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "(usssoo)", &sub))
889 HASHMAP_FOREACH(j, m->jobs, i) {
890 char *u_path, *j_path;
891 const char *state, *type;
893 DBusMessageIter sub2;
895 if (!dbus_message_iter_open_container(&sub, DBUS_TYPE_STRUCT, NULL, &sub2))
898 id = (uint32_t) j->id;
899 state = job_state_to_string(j->state);
900 type = job_type_to_string(j->type);
902 if (!(j_path = job_dbus_path(j)))
905 if (!(u_path = unit_dbus_path(j->unit))) {
910 if (!dbus_message_iter_append_basic(&sub2, DBUS_TYPE_UINT32, &id) ||
911 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &j->unit->id) ||
912 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &type) ||
913 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &state) ||
914 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_OBJECT_PATH, &j_path) ||
915 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_OBJECT_PATH, &u_path)) {
924 if (!dbus_message_iter_close_container(&sub, &sub2))
928 if (!dbus_message_iter_close_container(&iter, &sub))
931 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "Subscribe")) {
935 if (!(s = BUS_CONNECTION_SUBSCRIBED(m, connection))) {
936 if (!(s = set_new(string_hash_func, string_compare_func)))
939 if (!(dbus_connection_set_data(connection, m->subscribed_data_slot, s, NULL))) {
945 if (!(client = strdup(message_get_sender_with_fallback(message))))
948 if ((r = set_put(s, client)) < 0) {
950 return bus_send_error_reply(connection, message, NULL, r);
953 if (!(reply = dbus_message_new_method_return(message)))
956 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "Unsubscribe")) {
959 if (!(client = set_remove(BUS_CONNECTION_SUBSCRIBED(m, connection), (char*) message_get_sender_with_fallback(message)))) {
960 dbus_set_error(&error, BUS_ERROR_NOT_SUBSCRIBED, "Client is not subscribed.");
961 return bus_send_error_reply(connection, message, &error, -ENOENT);
966 if (!(reply = dbus_message_new_method_return(message)))
969 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "Dump")) {
974 if (!(reply = dbus_message_new_method_return(message)))
977 if (!(f = open_memstream(&dump, &size)))
980 manager_dump_units(m, f, NULL);
981 manager_dump_jobs(m, f, NULL);
991 if (!dbus_message_append_args(reply, DBUS_TYPE_STRING, &dump, DBUS_TYPE_INVALID)) {
997 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "CreateSnapshot")) {
1002 if (!dbus_message_get_args(
1005 DBUS_TYPE_STRING, &name,
1006 DBUS_TYPE_BOOLEAN, &cleanup,
1008 return bus_send_error_reply(connection, message, &error, -EINVAL);
1010 if (name && name[0] == 0)
1013 if ((r = snapshot_create(m, name, cleanup, &error, &s)) < 0)
1014 return bus_send_error_reply(connection, message, &error, r);
1016 if (!(reply = dbus_message_new_method_return(message)))
1019 if (!(path = unit_dbus_path(UNIT(s))))
1022 if (!dbus_message_append_args(
1024 DBUS_TYPE_OBJECT_PATH, &path,
1028 } else if (dbus_message_is_method_call(message, "org.freedesktop.DBus.Introspectable", "Introspect")) {
1029 char *introspection = NULL;
1037 if (!(reply = dbus_message_new_method_return(message)))
1040 /* We roll our own introspection code here, instead of
1041 * relying on bus_default_message_handler() because we
1042 * need to generate our introspection string
1045 if (!(f = open_memstream(&introspection, &size)))
1048 fputs(INTROSPECTION_BEGIN, f);
1050 HASHMAP_FOREACH_KEY(u, k, m->units, i) {
1056 if (!(p = bus_path_escape(k))) {
1058 free(introspection);
1062 fprintf(f, "<node name=\"unit/%s\"/>", p);
1066 HASHMAP_FOREACH(j, m->jobs, i)
1067 fprintf(f, "<node name=\"job/%lu\"/>", (unsigned long) j->id);
1069 fputs(INTROSPECTION_END, f);
1073 free(introspection);
1082 if (!dbus_message_append_args(reply, DBUS_TYPE_STRING, &introspection, DBUS_TYPE_INVALID)) {
1083 free(introspection);
1087 free(introspection);
1089 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "Reload")) {
1091 assert(!m->queued_message);
1093 /* Instead of sending the reply back right away, we
1094 * just remember that we need to and then send it
1095 * after the reload is finished. That way the caller
1096 * knows when the reload finished. */
1098 if (!(m->queued_message = dbus_message_new_method_return(message)))
1101 m->queued_message_connection = connection;
1102 m->exit_code = MANAGER_RELOAD;
1104 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "Reexecute")) {
1106 /* We don't send a reply back here, the client should
1107 * just wait for us disconnecting. */
1109 m->exit_code = MANAGER_REEXECUTE;
1111 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "Exit")) {
1113 if (m->running_as == MANAGER_SYSTEM) {
1114 dbus_set_error(&error, BUS_ERROR_NOT_SUPPORTED, "Exit is only supported for user service managers.");
1115 return bus_send_error_reply(connection, message, &error, -ENOTSUP);
1118 if (!(reply = dbus_message_new_method_return(message)))
1121 m->exit_code = MANAGER_EXIT;
1123 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "Reboot")) {
1125 if (m->running_as != MANAGER_SYSTEM) {
1126 dbus_set_error(&error, BUS_ERROR_NOT_SUPPORTED, "Reboot is only supported for system managers.");
1127 return bus_send_error_reply(connection, message, &error, -ENOTSUP);
1130 if (!(reply = dbus_message_new_method_return(message)))
1133 m->exit_code = MANAGER_REBOOT;
1135 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "PowerOff")) {
1137 if (m->running_as != MANAGER_SYSTEM) {
1138 dbus_set_error(&error, BUS_ERROR_NOT_SUPPORTED, "Powering off is only supported for system managers.");
1139 return bus_send_error_reply(connection, message, &error, -ENOTSUP);
1142 if (!(reply = dbus_message_new_method_return(message)))
1145 m->exit_code = MANAGER_POWEROFF;
1147 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "Halt")) {
1149 if (m->running_as != MANAGER_SYSTEM) {
1150 dbus_set_error(&error, BUS_ERROR_NOT_SUPPORTED, "Halting is only supported for system managers.");
1151 return bus_send_error_reply(connection, message, &error, -ENOTSUP);
1154 if (!(reply = dbus_message_new_method_return(message)))
1157 m->exit_code = MANAGER_HALT;
1159 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "KExec")) {
1161 if (m->running_as != MANAGER_SYSTEM) {
1162 dbus_set_error(&error, BUS_ERROR_NOT_SUPPORTED, "kexec is only supported for system managers.");
1163 return bus_send_error_reply(connection, message, &error, -ENOTSUP);
1166 if (!(reply = dbus_message_new_method_return(message)))
1169 m->exit_code = MANAGER_KEXEC;
1171 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "SetEnvironment")) {
1172 char **l = NULL, **e = NULL;
1174 if ((r = bus_parse_strv(message, &l)) < 0) {
1178 return bus_send_error_reply(connection, message, NULL, r);
1181 e = strv_env_merge(2, m->environment, l);
1187 if (!(reply = dbus_message_new_method_return(message))) {
1192 strv_free(m->environment);
1195 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "UnsetEnvironment")) {
1196 char **l = NULL, **e = NULL;
1198 if ((r = bus_parse_strv(message, &l)) < 0) {
1202 return bus_send_error_reply(connection, message, NULL, r);
1205 e = strv_env_delete(m->environment, 1, l);
1211 if (!(reply = dbus_message_new_method_return(message))) {
1216 strv_free(m->environment);
1219 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "UnsetAndSetEnvironment")) {
1220 char **l_set = NULL, **l_unset = NULL, **e = NULL, **f = NULL;
1221 DBusMessageIter iter;
1223 if (!dbus_message_iter_init(message, &iter))
1226 r = bus_parse_strv_iter(&iter, &l_unset);
1231 return bus_send_error_reply(connection, message, NULL, r);
1234 if (!dbus_message_iter_next(&iter)) {
1236 return bus_send_error_reply(connection, message, NULL, -EINVAL);
1239 r = bus_parse_strv_iter(&iter, &l_set);
1245 return bus_send_error_reply(connection, message, NULL, r);
1248 e = strv_env_delete(m->environment, 1, l_unset);
1256 f = strv_env_merge(2, e, l_set);
1263 if (!(reply = dbus_message_new_method_return(message))) {
1268 strv_free(m->environment);
1270 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ListUnitFiles")) {
1271 DBusMessageIter iter, sub, sub2;
1276 reply = dbus_message_new_method_return(message);
1280 h = hashmap_new(string_hash_func, string_compare_func);
1284 r = unit_file_get_list(m->running_as == MANAGER_SYSTEM ? UNIT_FILE_SYSTEM : UNIT_FILE_USER, NULL, h);
1286 unit_file_list_free(h);
1287 dbus_message_unref(reply);
1288 return bus_send_error_reply(connection, message, NULL, r);
1291 dbus_message_iter_init_append(reply, &iter);
1293 if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "(ss)", &sub)) {
1294 unit_file_list_free(h);
1298 HASHMAP_FOREACH(item, h, i) {
1301 state = unit_file_state_to_string(item->state);
1304 if (!dbus_message_iter_open_container(&sub, DBUS_TYPE_STRUCT, NULL, &sub2) ||
1305 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &item->path) ||
1306 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &state) ||
1307 !dbus_message_iter_close_container(&sub, &sub2)) {
1308 unit_file_list_free(h);
1313 unit_file_list_free(h);
1315 if (!dbus_message_iter_close_container(&iter, &sub))
1318 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "GetUnitFileState")) {
1320 UnitFileState state;
1323 if (!dbus_message_get_args(
1326 DBUS_TYPE_STRING, &name,
1328 return bus_send_error_reply(connection, message, &error, -EINVAL);
1330 state = unit_file_get_state(m->running_as == MANAGER_SYSTEM ? UNIT_FILE_SYSTEM : UNIT_FILE_USER, NULL, name);
1332 return bus_send_error_reply(connection, message, NULL, state);
1334 s = unit_file_state_to_string(state);
1337 reply = dbus_message_new_method_return(message);
1341 if (!dbus_message_append_args(
1343 DBUS_TYPE_STRING, &s,
1346 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "EnableUnitFiles") ||
1347 dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ReenableUnitFiles") ||
1348 dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "LinkUnitFiles") ||
1349 dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "PresetUnitFiles") ||
1350 dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "MaskUnitFiles")) {
1353 DBusMessageIter iter;
1354 UnitFileScope scope = m->running_as == MANAGER_SYSTEM ? UNIT_FILE_SYSTEM : UNIT_FILE_USER;
1355 UnitFileChange *changes = NULL;
1356 unsigned n_changes = 0;
1357 dbus_bool_t runtime, force;
1358 int carries_install_info = -1;
1360 if (!dbus_message_iter_init(message, &iter))
1363 r = bus_parse_strv_iter(&iter, &l);
1368 return bus_send_error_reply(connection, message, NULL, r);
1371 if (!dbus_message_iter_next(&iter) ||
1372 bus_iter_get_basic_and_next(&iter, DBUS_TYPE_BOOLEAN, &runtime, true) < 0 ||
1373 bus_iter_get_basic_and_next(&iter, DBUS_TYPE_BOOLEAN, &force, false) < 0) {
1375 return bus_send_error_reply(connection, message, NULL, -EIO);
1378 if (streq(member, "EnableUnitFiles")) {
1379 r = unit_file_enable(scope, runtime, NULL, l, force, &changes, &n_changes);
1380 carries_install_info = r;
1381 } else if (streq(member, "ReenableUnitFiles")) {
1382 r = unit_file_reenable(scope, runtime, NULL, l, force, &changes, &n_changes);
1383 carries_install_info = r;
1384 } else if (streq(member, "LinkUnitFiles"))
1385 r = unit_file_link(scope, runtime, NULL, l, force, &changes, &n_changes);
1386 else if (streq(member, "PresetUnitFiles")) {
1387 r = unit_file_preset(scope, runtime, NULL, l, force, &changes, &n_changes);
1388 carries_install_info = r;
1389 } else if (streq(member, "MaskUnitFiles"))
1390 r = unit_file_mask(scope, runtime, NULL, l, force, &changes, &n_changes);
1392 assert_not_reached("Uh? Wrong method");
1395 bus_manager_send_unit_files_changed(m);
1398 unit_file_changes_free(changes, n_changes);
1399 return bus_send_error_reply(connection, message, NULL, r);
1402 reply = message_from_file_changes(message, changes, n_changes, carries_install_info);
1403 unit_file_changes_free(changes, n_changes);
1408 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "DisableUnitFiles") ||
1409 dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "UnmaskUnitFiles")) {
1412 DBusMessageIter iter;
1413 UnitFileScope scope = m->running_as == MANAGER_SYSTEM ? UNIT_FILE_SYSTEM : UNIT_FILE_USER;
1414 UnitFileChange *changes = NULL;
1415 unsigned n_changes = 0;
1416 dbus_bool_t runtime;
1418 if (!dbus_message_iter_init(message, &iter))
1421 r = bus_parse_strv_iter(&iter, &l);
1426 return bus_send_error_reply(connection, message, NULL, r);
1429 if (!dbus_message_iter_next(&iter) ||
1430 bus_iter_get_basic_and_next(&iter, DBUS_TYPE_BOOLEAN, &runtime, false) < 0) {
1432 return bus_send_error_reply(connection, message, NULL, -EIO);
1435 if (streq(member, "DisableUnitFiles"))
1436 r = unit_file_disable(scope, runtime, NULL, l, &changes, &n_changes);
1437 else if (streq(member, "UnmaskUnitFiles"))
1438 r = unit_file_unmask(scope, runtime, NULL, l, &changes, &n_changes);
1440 assert_not_reached("Uh? Wrong method");
1443 bus_manager_send_unit_files_changed(m);
1446 unit_file_changes_free(changes, n_changes);
1447 return bus_send_error_reply(connection, message, NULL, r);
1450 reply = message_from_file_changes(message, changes, n_changes, -1);
1451 unit_file_changes_free(changes, n_changes);
1457 const BusBoundProperties bps[] = {
1458 { "org.freedesktop.systemd1.Manager", bus_systemd_properties, systemd_property_string },
1459 { "org.freedesktop.systemd1.Manager", bus_manager_properties, m },
1462 return bus_default_message_handler(connection, message, NULL, INTERFACES_LIST, bps);
1465 if (job_type != _JOB_TYPE_INVALID) {
1466 const char *name, *smode, *old_name = NULL;
1473 if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "StartUnitReplace"))
1474 b = dbus_message_get_args(
1477 DBUS_TYPE_STRING, &old_name,
1478 DBUS_TYPE_STRING, &name,
1479 DBUS_TYPE_STRING, &smode,
1482 b = dbus_message_get_args(
1485 DBUS_TYPE_STRING, &name,
1486 DBUS_TYPE_STRING, &smode,
1490 return bus_send_error_reply(connection, message, &error, -EINVAL);
1493 if (!(u = manager_get_unit(m, old_name)) ||
1495 u->job->type != JOB_START) {
1496 dbus_set_error(&error, BUS_ERROR_NO_SUCH_JOB, "No job queued for unit %s", old_name);
1497 return bus_send_error_reply(connection, message, &error, -ENOENT);
1501 if ((mode = job_mode_from_string(smode)) == _JOB_MODE_INVALID) {
1502 dbus_set_error(&error, BUS_ERROR_INVALID_JOB_MODE, "Job mode %s is invalid.", smode);
1503 return bus_send_error_reply(connection, message, &error, -EINVAL);
1506 if ((r = manager_load_unit(m, name, NULL, &error, &u)) < 0)
1507 return bus_send_error_reply(connection, message, &error, r);
1509 if (reload_if_possible && unit_can_reload(u)) {
1510 if (job_type == JOB_RESTART)
1511 job_type = JOB_RELOAD_OR_START;
1512 else if (job_type == JOB_TRY_RESTART)
1513 job_type = JOB_RELOAD;
1516 if ((job_type == JOB_START && u->refuse_manual_start) ||
1517 (job_type == JOB_STOP && u->refuse_manual_stop) ||
1518 ((job_type == JOB_RESTART || job_type == JOB_TRY_RESTART) &&
1519 (u->refuse_manual_start || u->refuse_manual_stop))) {
1520 dbus_set_error(&error, BUS_ERROR_ONLY_BY_DEPENDENCY, "Operation refused, may be requested by dependency only.");
1521 return bus_send_error_reply(connection, message, &error, -EPERM);
1524 if ((r = manager_add_job(m, job_type, u, mode, true, &error, &j)) < 0)
1525 return bus_send_error_reply(connection, message, &error, r);
1527 cl = job_bus_client_new(connection, message_get_sender_with_fallback(message));
1531 LIST_PREPEND(JobBusClient, client, j->bus_client_list, cl);
1533 if (!(reply = dbus_message_new_method_return(message)))
1536 if (!(path = job_dbus_path(j)))
1539 if (!dbus_message_append_args(
1541 DBUS_TYPE_OBJECT_PATH, &path,
1547 if (!dbus_connection_send(connection, reply, NULL))
1550 dbus_message_unref(reply);
1555 return DBUS_HANDLER_RESULT_HANDLED;
1561 dbus_message_unref(reply);
1563 dbus_error_free(&error);
1565 return DBUS_HANDLER_RESULT_NEED_MEMORY;
1568 const DBusObjectPathVTable bus_manager_vtable = {
1569 .message_function = bus_manager_message_handler