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"
34 #define BUS_MANAGER_INTERFACE_BEGIN \
35 " <interface name=\"org.freedesktop.systemd1.Manager\">\n"
37 #define BUS_MANAGER_INTERFACE_METHODS \
38 " <method name=\"GetUnit\">\n" \
39 " <arg name=\"name\" type=\"s\" direction=\"in\"/>\n" \
40 " <arg name=\"unit\" type=\"o\" direction=\"out\"/>\n" \
42 " <method name=\"GetUnitByPID\">\n" \
43 " <arg name=\"pid\" type=\"u\" direction=\"in\"/>\n" \
44 " <arg name=\"unit\" type=\"o\" direction=\"out\"/>\n" \
46 " <method name=\"LoadUnit\">\n" \
47 " <arg name=\"name\" type=\"s\" direction=\"in\"/>\n" \
48 " <arg name=\"unit\" type=\"o\" direction=\"out\"/>\n" \
50 " <method name=\"StartUnit\">\n" \
51 " <arg name=\"name\" type=\"s\" direction=\"in\"/>\n" \
52 " <arg name=\"mode\" type=\"s\" direction=\"in\"/>\n" \
53 " <arg name=\"job\" type=\"o\" direction=\"out\"/>\n" \
55 " <method name=\"StartUnitReplace\">\n" \
56 " <arg name=\"old_unit\" type=\"s\" direction=\"in\"/>\n" \
57 " <arg name=\"new_unit\" type=\"s\" direction=\"in\"/>\n" \
58 " <arg name=\"mode\" type=\"s\" direction=\"in\"/>\n" \
59 " <arg name=\"job\" type=\"o\" direction=\"out\"/>\n" \
61 " <method name=\"StopUnit\">\n" \
62 " <arg name=\"name\" type=\"s\" direction=\"in\"/>\n" \
63 " <arg name=\"mode\" type=\"s\" direction=\"in\"/>\n" \
64 " <arg name=\"job\" type=\"o\" direction=\"out\"/>\n" \
66 " <method name=\"ReloadUnit\">\n" \
67 " <arg name=\"name\" type=\"s\" direction=\"in\"/>\n" \
68 " <arg name=\"mode\" type=\"s\" direction=\"in\"/>\n" \
69 " <arg name=\"job\" type=\"o\" direction=\"out\"/>\n" \
71 " <method name=\"RestartUnit\">\n" \
72 " <arg name=\"name\" type=\"s\" direction=\"in\"/>\n" \
73 " <arg name=\"mode\" type=\"s\" direction=\"in\"/>\n" \
74 " <arg name=\"job\" type=\"o\" direction=\"out\"/>\n" \
76 " <method name=\"TryRestartUnit\">\n" \
77 " <arg name=\"name\" type=\"s\" direction=\"in\"/>\n" \
78 " <arg name=\"mode\" type=\"s\" direction=\"in\"/>\n" \
79 " <arg name=\"job\" type=\"o\" direction=\"out\"/>\n" \
81 " <method name=\"ReloadOrRestartUnit\">\n" \
82 " <arg name=\"name\" type=\"s\" direction=\"in\"/>\n" \
83 " <arg name=\"mode\" type=\"s\" direction=\"in\"/>\n" \
84 " <arg name=\"job\" type=\"o\" direction=\"out\"/>\n" \
86 " <method name=\"ReloadOrTryRestartUnit\">\n" \
87 " <arg name=\"name\" type=\"s\" direction=\"in\"/>\n" \
88 " <arg name=\"mode\" type=\"s\" direction=\"in\"/>\n" \
89 " <arg name=\"job\" type=\"o\" direction=\"out\"/>\n" \
91 " <method name=\"KillUnit\">\n" \
92 " <arg name=\"name\" type=\"s\" direction=\"in\"/>\n" \
93 " <arg name=\"who\" type=\"s\" direction=\"in\"/>\n" \
94 " <arg name=\"mode\" type=\"s\" direction=\"in\"/>\n" \
95 " <arg name=\"signal\" type=\"i\" direction=\"in\"/>\n" \
97 " <method name=\"ResetFailedUnit\">\n" \
98 " <arg name=\"name\" type=\"s\" direction=\"in\"/>\n" \
100 " <method name=\"GetJob\">\n" \
101 " <arg name=\"id\" type=\"u\" direction=\"in\"/>\n" \
102 " <arg name=\"job\" type=\"o\" direction=\"out\"/>\n" \
104 " <method name=\"ClearJobs\"/>\n" \
105 " <method name=\"ResetFailed\"/>\n" \
106 " <method name=\"ListUnits\">\n" \
107 " <arg name=\"units\" type=\"a(ssssssouso)\" direction=\"out\"/>\n" \
109 " <method name=\"ListJobs\">\n" \
110 " <arg name=\"jobs\" type=\"a(usssoo)\" direction=\"out\"/>\n" \
112 " <method name=\"Subscribe\"/>\n" \
113 " <method name=\"Unsubscribe\"/>\n" \
114 " <method name=\"Dump\"/>\n" \
115 " <method name=\"CreateSnapshot\">\n" \
116 " <arg name=\"name\" type=\"s\" direction=\"in\"/>\n" \
117 " <arg name=\"cleanup\" type=\"b\" direction=\"in\"/>\n" \
118 " <arg name=\"unit\" type=\"o\" direction=\"out\"/>\n" \
120 " <method name=\"Reload\"/>\n" \
121 " <method name=\"Reexecute\"/>\n" \
122 " <method name=\"Exit\"/>\n" \
123 " <method name=\"Reboot\"/>\n" \
124 " <method name=\"PowerOff\"/>\n" \
125 " <method name=\"Halt\"/>\n" \
126 " <method name=\"KExec\"/>\n" \
127 " <method name=\"SetEnvironment\">\n" \
128 " <arg name=\"names\" type=\"as\" direction=\"in\"/>\n" \
130 " <method name=\"UnsetEnvironment\">\n" \
131 " <arg name=\"names\" type=\"as\" direction=\"in\"/>\n" \
133 " <method name=\"UnsetAndSetEnvironment\">\n" \
134 " <arg name=\"unset\" type=\"as\" direction=\"in\"/>\n" \
135 " <arg name=\"set\" type=\"as\" direction=\"in\"/>\n" \
137 " <method name=\"ListUnitFiles\">\n" \
138 " <arg name=\"changes\" type=\"a(ss)\" direction=\"out\"/>\n" \
140 " <method name=\"GetUnitFileState\">\n" \
141 " <arg name=\"file\" type=\"s\" direction=\"in\"/>\n" \
142 " <arg name=\"state\" type=\"s\" direction=\"out\"/>\n" \
144 " <method name=\"EnableUnitFiles\">\n" \
145 " <arg name=\"files\" type=\"as\" direction=\"in\"/>\n" \
146 " <arg name=\"runtime\" type=\"b\" direction=\"in\"/>\n" \
147 " <arg name=\"force\" type=\"b\" direction=\"in\"/>\n" \
148 " <arg name=\"carries_install_info\" type=\"b\" direction=\"out\"/>\n" \
149 " <arg name=\"changes\" type=\"a(sss)\" direction=\"out\"/>\n" \
151 " <method name=\"DisableUnitFiles\">\n" \
152 " <arg name=\"files\" type=\"as\" direction=\"in\"/>\n" \
153 " <arg name=\"runtime\" type=\"b\" direction=\"in\"/>\n" \
154 " <arg name=\"changes\" type=\"a(sss)\" direction=\"out\"/>\n" \
156 " <method name=\"ReenableUnitFiles\">\n" \
157 " <arg name=\"files\" type=\"as\" direction=\"in\"/>\n" \
158 " <arg name=\"runtime\" type=\"b\" direction=\"in\"/>\n" \
159 " <arg name=\"force\" type=\"b\" direction=\"in\"/>\n" \
160 " <arg name=\"carries_install_info\" type=\"b\" direction=\"out\"/>\n" \
161 " <arg name=\"changes\" type=\"a(sss)\" direction=\"out\"/>\n" \
163 " <method name=\"LinkUnitFiles\">\n" \
164 " <arg name=\"files\" type=\"as\" direction=\"in\"/>\n" \
165 " <arg name=\"runtime\" type=\"b\" direction=\"in\"/>\n" \
166 " <arg name=\"force\" type=\"b\" direction=\"in\"/>\n" \
167 " <arg name=\"changes\" type=\"a(sss)\" direction=\"out\"/>\n" \
169 " <method name=\"PresetUnitFiles\">\n" \
170 " <arg name=\"files\" type=\"as\" direction=\"in\"/>\n" \
171 " <arg name=\"runtime\" type=\"b\" direction=\"in\"/>\n" \
172 " <arg name=\"force\" type=\"b\" direction=\"in\"/>\n" \
173 " <arg name=\"carries_install_info\" type=\"b\" direction=\"out\"/>\n" \
174 " <arg name=\"changes\" type=\"a(sss)\" direction=\"out\"/>\n" \
176 " <method name=\"MaskUnitFiles\">\n" \
177 " <arg name=\"files\" type=\"as\" direction=\"in\"/>\n" \
178 " <arg name=\"runtime\" type=\"b\" direction=\"in\"/>\n" \
179 " <arg name=\"force\" type=\"b\" direction=\"in\"/>\n" \
180 " <arg name=\"changes\" type=\"a(sss)\" direction=\"out\"/>\n" \
182 " <method name=\"UnmaskUnitFiles\">\n" \
183 " <arg name=\"files\" type=\"as\" direction=\"in\"/>\n" \
184 " <arg name=\"runtime\" type=\"b\" direction=\"in\"/>\n" \
185 " <arg name=\"changes\" type=\"a(sss)\" direction=\"out\"/>\n" \
188 #define BUS_MANAGER_INTERFACE_SIGNALS \
189 " <signal name=\"UnitNew\">\n" \
190 " <arg name=\"id\" type=\"s\"/>\n" \
191 " <arg name=\"unit\" type=\"o\"/>\n" \
193 " <signal name=\"UnitRemoved\">\n" \
194 " <arg name=\"id\" type=\"s\"/>\n" \
195 " <arg name=\"unit\" type=\"o\"/>\n" \
197 " <signal name=\"JobNew\">\n" \
198 " <arg name=\"id\" type=\"u\"/>\n" \
199 " <arg name=\"job\" type=\"o\"/>\n" \
201 " <signal name=\"JobRemoved\">\n" \
202 " <arg name=\"id\" type=\"u\"/>\n" \
203 " <arg name=\"job\" type=\"o\"/>\n" \
204 " <arg name=\"result\" type=\"s\"/>\n" \
206 " <signal name=\"StartupFinished\">\n" \
207 " <arg name=\"kernel\" type=\"t\"/>\n" \
208 " <arg name=\"initrd\" type=\"t\"/>\n" \
209 " <arg name=\"userspace\" type=\"t\"/>\n" \
210 " <arg name=\"total\" type=\"t\"/>\n" \
212 " <signal name=\"UnitFilesChanged\"/>\n"
214 #define BUS_MANAGER_INTERFACE_PROPERTIES_GENERAL \
215 " <property name=\"Version\" type=\"s\" access=\"read\"/>\n" \
216 " <property name=\"Distribution\" type=\"s\" access=\"read\"/>\n" \
217 " <property name=\"Features\" type=\"s\" access=\"read\"/>\n" \
218 " <property name=\"Tainted\" type=\"s\" access=\"read\"/>\n" \
219 " <property name=\"RunningAs\" type=\"s\" access=\"read\"/>\n" \
220 " <property name=\"InitRDTimestamp\" type=\"t\" access=\"read\"/>\n" \
221 " <property name=\"InitRDTimestampMonotonic\" type=\"t\" access=\"read\"/>\n" \
222 " <property name=\"StartupTimestamp\" type=\"t\" access=\"read\"/>\n" \
223 " <property name=\"StartupTimestampMonotonic\" type=\"t\" access=\"read\"/>\n" \
224 " <property name=\"FinishTimestamp\" type=\"t\" access=\"read\"/>\n" \
225 " <property name=\"FinishTimestampMonotonic\" type=\"t\" access=\"read\"/>\n" \
226 " <property name=\"LogLevel\" type=\"s\" access=\"readwrite\"/>\n" \
227 " <property name=\"LogTarget\" type=\"s\" access=\"readwrite\"/>\n" \
228 " <property name=\"NNames\" type=\"u\" access=\"read\"/>\n" \
229 " <property name=\"NJobs\" type=\"u\" access=\"read\"/>\n" \
230 " <property name=\"NInstalledJobs\" type=\"u\" access=\"read\"/>\n" \
231 " <property name=\"NFailedJobs\" type=\"u\" access=\"read\"/>\n" \
232 " <property name=\"Progress\" type=\"d\" access=\"read\"/>\n" \
233 " <property name=\"Environment\" type=\"as\" access=\"read\"/>\n" \
234 " <property name=\"ConfirmSpawn\" type=\"b\" access=\"read\"/>\n" \
235 " <property name=\"ShowStatus\" type=\"b\" access=\"read\"/>\n" \
236 " <property name=\"UnitPath\" type=\"as\" access=\"read\"/>\n" \
237 " <property name=\"NotifySocket\" type=\"s\" access=\"read\"/>\n" \
238 " <property name=\"ControlGroupHierarchy\" type=\"s\" access=\"read\"/>\n" \
239 " <property name=\"MountAuto\" type=\"b\" access=\"read\"/>\n" \
240 " <property name=\"SwapAuto\" type=\"b\" access=\"read\"/>\n" \
241 " <property name=\"DefaultControllers\" type=\"as\" access=\"read\"/>\n" \
242 " <property name=\"DefaultStandardOutput\" type=\"s\" access=\"read\"/>\n" \
243 " <property name=\"DefaultStandardError\" type=\"s\" access=\"read\"/>\n" \
244 " <property name=\"RuntimeWatchdogUSec\" type=\"s\" access=\"read\"/>\n" \
245 " <property name=\"ShutdownWatchdogUSec\" type=\"s\" access=\"read\"/>\n" \
246 " <property name=\"HaveWatchdog\" type=\"b\" access=\"read\"/>\n"
248 #ifdef HAVE_SYSV_COMPAT
249 #define BUS_MANAGER_INTERFACE_PROPERTIES_SYSV \
250 " <property name=\"SysVConsole\" type=\"b\" access=\"read\"/>\n" \
251 " <property name=\"SysVInitPath\" type=\"as\" access=\"read\"/>\n" \
252 " <property name=\"SysVRcndPath\" type=\"as\" access=\"read\"/>\n"
254 #define BUS_MANAGER_INTERFACE_PROPERTIES_SYSV
257 #define BUS_MANAGER_INTERFACE_END \
260 #define BUS_MANAGER_INTERFACE \
261 BUS_MANAGER_INTERFACE_BEGIN \
262 BUS_MANAGER_INTERFACE_METHODS \
263 BUS_MANAGER_INTERFACE_SIGNALS \
264 BUS_MANAGER_INTERFACE_PROPERTIES_GENERAL \
265 BUS_MANAGER_INTERFACE_PROPERTIES_SYSV \
266 BUS_MANAGER_INTERFACE_END
268 #define INTROSPECTION_BEGIN \
269 DBUS_INTROSPECT_1_0_XML_DOCTYPE_DECL_NODE \
271 BUS_MANAGER_INTERFACE \
272 BUS_PROPERTIES_INTERFACE \
274 BUS_INTROSPECTABLE_INTERFACE
276 #define INTROSPECTION_END \
279 #define INTERFACES_LIST \
280 BUS_GENERIC_INTERFACES_LIST \
281 "org.freedesktop.systemd1.Manager\0"
283 const char bus_manager_interface[] _introspect_("Manager") = BUS_MANAGER_INTERFACE;
285 static DEFINE_BUS_PROPERTY_APPEND_ENUM(bus_manager_append_running_as, manager_running_as, ManagerRunningAs);
286 static DEFINE_BUS_PROPERTY_APPEND_ENUM(bus_manager_append_exec_output, exec_output, ExecOutput);
288 static int bus_manager_append_tainted(DBusMessageIter *i, const char *property, void *data) {
291 char buf[LINE_MAX] = "", *e = buf, *p = NULL;
298 e = stpcpy(e, "usr-separate-fs ");
300 if (readlink_malloc("/etc/mtab", &p) < 0)
301 e = stpcpy(e, "etc-mtab-not-symlink ");
305 if (access("/proc/cgroups", F_OK) < 0)
306 stpcpy(e, "cgroups-missing ");
310 if (!dbus_message_iter_append_basic(i, DBUS_TYPE_STRING, &t))
316 static int bus_manager_append_log_target(DBusMessageIter *i, const char *property, void *data) {
322 t = log_target_to_string(log_get_target());
324 if (!dbus_message_iter_append_basic(i, DBUS_TYPE_STRING, &t))
330 static int bus_manager_set_log_target(DBusMessageIter *i, const char *property, void *data) {
336 dbus_message_iter_get_basic(i, &t);
338 return log_set_target_from_string(t);
341 static int bus_manager_append_log_level(DBusMessageIter *i, const char *property, void *data) {
347 t = log_level_to_string(log_get_max_level());
349 if (!dbus_message_iter_append_basic(i, DBUS_TYPE_STRING, &t))
355 static int bus_manager_set_log_level(DBusMessageIter *i, const char *property, void *data) {
361 dbus_message_iter_get_basic(i, &t);
363 return log_set_max_level_from_string(t);
366 static int bus_manager_append_n_names(DBusMessageIter *i, const char *property, void *data) {
374 u = hashmap_size(m->units);
376 if (!dbus_message_iter_append_basic(i, DBUS_TYPE_UINT32, &u))
382 static int bus_manager_append_n_jobs(DBusMessageIter *i, const char *property, void *data) {
390 u = hashmap_size(m->jobs);
392 if (!dbus_message_iter_append_basic(i, DBUS_TYPE_UINT32, &u))
398 static int bus_manager_append_progress(DBusMessageIter *i, const char *property, void *data) {
406 if (dual_timestamp_is_set(&m->finish_timestamp))
409 d = 1.0 - ((double) hashmap_size(m->jobs) / (double) m->n_installed_jobs);
411 if (!dbus_message_iter_append_basic(i, DBUS_TYPE_DOUBLE, &d))
417 static const char *message_get_sender_with_fallback(DBusMessage *m) {
422 if ((s = dbus_message_get_sender(m)))
425 /* When the message came in from a direct connection the
426 * message will have no sender. We fix that here. */
431 static DBusMessage *message_from_file_changes(
433 UnitFileChange *changes,
435 int carries_install_info) {
437 DBusMessageIter iter, sub, sub2;
441 reply = dbus_message_new_method_return(m);
445 dbus_message_iter_init_append(reply, &iter);
447 if (carries_install_info >= 0) {
450 b = !!carries_install_info;
451 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &b))
455 if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "(sss)", &sub))
458 for (i = 0; i < n_changes; i++) {
459 const char *type, *path, *source;
461 type = unit_file_change_type_to_string(changes[i].type);
462 path = strempty(changes[i].path);
463 source = strempty(changes[i].source);
465 if (!dbus_message_iter_open_container(&sub, DBUS_TYPE_STRUCT, NULL, &sub2) ||
466 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &type) ||
467 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &path) ||
468 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &source) ||
469 !dbus_message_iter_close_container(&sub, &sub2))
473 if (!dbus_message_iter_close_container(&iter, &sub))
479 dbus_message_unref(reply);
483 static int bus_manager_send_unit_files_changed(Manager *m) {
487 s = dbus_message_new_signal("/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", "UnitFilesChanged");
491 r = bus_broadcast(m, s);
492 dbus_message_unref(s);
497 static int bus_manager_append_have_watchdog(DBusMessageIter *i, const char *property, void *data) {
503 b = access("/dev/watchdog", F_OK) >= 0;
505 if (!dbus_message_iter_append_basic(i, DBUS_TYPE_BOOLEAN, &b))
511 static const char systemd_property_string[] =
516 static const BusProperty bus_systemd_properties[] = {
517 { "Version", bus_property_append_string, "s", 0 },
518 { "Distribution", bus_property_append_string, "s", sizeof(PACKAGE_STRING) },
519 { "Features", bus_property_append_string, "s", sizeof(PACKAGE_STRING) + sizeof(DISTRIBUTION) },
523 static const BusProperty bus_manager_properties[] = {
524 { "RunningAs", bus_manager_append_running_as, "s", offsetof(Manager, running_as) },
525 { "Tainted", bus_manager_append_tainted, "s", 0 },
526 { "InitRDTimestamp", bus_property_append_uint64, "t", offsetof(Manager, initrd_timestamp.realtime) },
527 { "InitRDTimestampMonotonic", bus_property_append_uint64, "t", offsetof(Manager, initrd_timestamp.monotonic) },
528 { "StartupTimestamp", bus_property_append_uint64, "t", offsetof(Manager, startup_timestamp.realtime) },
529 { "StartupTimestampMonotonic", bus_property_append_uint64, "t", offsetof(Manager, startup_timestamp.monotonic) },
530 { "FinishTimestamp", bus_property_append_uint64, "t", offsetof(Manager, finish_timestamp.realtime) },
531 { "FinishTimestampMonotonic", bus_property_append_uint64, "t", offsetof(Manager, finish_timestamp.monotonic) },
532 { "LogLevel", bus_manager_append_log_level, "s", 0, 0, bus_manager_set_log_level },
533 { "LogTarget", bus_manager_append_log_target, "s", 0, 0, bus_manager_set_log_target },
534 { "NNames", bus_manager_append_n_names, "u", 0 },
535 { "NJobs", bus_manager_append_n_jobs, "u", 0 },
536 { "NInstalledJobs",bus_property_append_uint32, "u", offsetof(Manager, n_installed_jobs) },
537 { "NFailedJobs", bus_property_append_uint32, "u", offsetof(Manager, n_failed_jobs) },
538 { "Progress", bus_manager_append_progress, "d", 0 },
539 { "Environment", bus_property_append_strv, "as", offsetof(Manager, environment), true },
540 { "ConfirmSpawn", bus_property_append_bool, "b", offsetof(Manager, confirm_spawn) },
541 { "ShowStatus", bus_property_append_bool, "b", offsetof(Manager, show_status) },
542 { "UnitPath", bus_property_append_strv, "as", offsetof(Manager, lookup_paths.unit_path), true },
543 { "NotifySocket", bus_property_append_string, "s", offsetof(Manager, notify_socket), true },
544 { "ControlGroupHierarchy", bus_property_append_string, "s", offsetof(Manager, cgroup_hierarchy), true },
545 { "MountAuto", bus_property_append_bool, "b", offsetof(Manager, mount_auto) },
546 { "SwapAuto", bus_property_append_bool, "b", offsetof(Manager, swap_auto) },
547 { "DefaultControllers", bus_property_append_strv, "as", offsetof(Manager, default_controllers), true },
548 { "DefaultStandardOutput", bus_manager_append_exec_output, "s", offsetof(Manager, default_std_output) },
549 { "DefaultStandardError", bus_manager_append_exec_output, "s", offsetof(Manager, default_std_error) },
550 { "RuntimeWatchdogUSec", bus_property_append_usec, "t", offsetof(Manager, runtime_watchdog), },
551 { "ShutdownWatchdogUSec", bus_property_append_usec, "t", offsetof(Manager, shutdown_watchdog), },
552 { "HaveWatchdog", bus_manager_append_have_watchdog, "b", 0 },
553 #ifdef HAVE_SYSV_COMPAT
554 { "SysVConsole", bus_property_append_bool, "b", offsetof(Manager, sysv_console) },
555 { "SysVInitPath", bus_property_append_strv, "as", offsetof(Manager, lookup_paths.sysvinit_path), true },
556 { "SysVRcndPath", bus_property_append_strv, "as", offsetof(Manager, lookup_paths.sysvrcnd_path), true },
561 static DBusHandlerResult bus_manager_message_handler(DBusConnection *connection, DBusMessage *message, void *data) {
566 DBusMessage *reply = NULL;
568 JobType job_type = _JOB_TYPE_INVALID;
569 bool reload_if_possible = false;
576 dbus_error_init(&error);
578 member = dbus_message_get_member(message);
580 if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "GetUnit")) {
584 if (!dbus_message_get_args(
587 DBUS_TYPE_STRING, &name,
589 return bus_send_error_reply(connection, message, &error, -EINVAL);
591 if (!(u = manager_get_unit(m, name))) {
592 dbus_set_error(&error, BUS_ERROR_NO_SUCH_UNIT, "Unit %s is not loaded.", name);
593 return bus_send_error_reply(connection, message, &error, -ENOENT);
596 if (!(reply = dbus_message_new_method_return(message)))
599 if (!(path = unit_dbus_path(u)))
602 if (!dbus_message_append_args(
604 DBUS_TYPE_OBJECT_PATH, &path,
607 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "GetUnitByPID")) {
611 if (!dbus_message_get_args(
614 DBUS_TYPE_UINT32, &pid,
616 return bus_send_error_reply(connection, message, &error, -EINVAL);
618 if (!(u = cgroup_unit_by_pid(m, (pid_t) pid))) {
619 dbus_set_error(&error, BUS_ERROR_NO_SUCH_UNIT, "No unit for PID %lu is loaded.", (unsigned long) pid);
620 return bus_send_error_reply(connection, message, &error, -ENOENT);
623 if (!(reply = dbus_message_new_method_return(message)))
626 if (!(path = unit_dbus_path(u)))
629 if (!dbus_message_append_args(
631 DBUS_TYPE_OBJECT_PATH, &path,
634 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "LoadUnit")) {
638 if (!dbus_message_get_args(
641 DBUS_TYPE_STRING, &name,
643 return bus_send_error_reply(connection, message, &error, -EINVAL);
645 if ((r = manager_load_unit(m, name, NULL, &error, &u)) < 0)
646 return bus_send_error_reply(connection, message, &error, r);
648 if (!(reply = dbus_message_new_method_return(message)))
651 if (!(path = unit_dbus_path(u)))
654 if (!dbus_message_append_args(
656 DBUS_TYPE_OBJECT_PATH, &path,
660 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "StartUnit"))
661 job_type = JOB_START;
662 else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "StartUnitReplace"))
663 job_type = JOB_START;
664 else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "StopUnit"))
666 else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ReloadUnit"))
667 job_type = JOB_RELOAD;
668 else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "RestartUnit"))
669 job_type = JOB_RESTART;
670 else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "TryRestartUnit"))
671 job_type = JOB_TRY_RESTART;
672 else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ReloadOrRestartUnit")) {
673 reload_if_possible = true;
674 job_type = JOB_RESTART;
675 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ReloadOrTryRestartUnit")) {
676 reload_if_possible = true;
677 job_type = JOB_TRY_RESTART;
678 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "KillUnit")) {
679 const char *name, *swho, *smode;
685 if (!dbus_message_get_args(
688 DBUS_TYPE_STRING, &name,
689 DBUS_TYPE_STRING, &swho,
690 DBUS_TYPE_STRING, &smode,
691 DBUS_TYPE_INT32, &signo,
693 return bus_send_error_reply(connection, message, &error, -EINVAL);
698 who = kill_who_from_string(swho);
700 return bus_send_error_reply(connection, message, &error, -EINVAL);
704 mode = KILL_CONTROL_GROUP;
706 mode = kill_mode_from_string(smode);
708 return bus_send_error_reply(connection, message, &error, -EINVAL);
711 if (signo <= 0 || signo >= _NSIG)
712 return bus_send_error_reply(connection, message, &error, -EINVAL);
714 if (!(u = manager_get_unit(m, name))) {
715 dbus_set_error(&error, BUS_ERROR_NO_SUCH_UNIT, "Unit %s is not loaded.", name);
716 return bus_send_error_reply(connection, message, &error, -ENOENT);
719 if ((r = unit_kill(u, who, mode, signo, &error)) < 0)
720 return bus_send_error_reply(connection, message, &error, r);
722 if (!(reply = dbus_message_new_method_return(message)))
725 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "GetJob")) {
729 if (!dbus_message_get_args(
732 DBUS_TYPE_UINT32, &id,
734 return bus_send_error_reply(connection, message, &error, -EINVAL);
736 if (!(j = manager_get_job(m, id))) {
737 dbus_set_error(&error, BUS_ERROR_NO_SUCH_JOB, "Job %u does not exist.", (unsigned) id);
738 return bus_send_error_reply(connection, message, &error, -ENOENT);
741 if (!(reply = dbus_message_new_method_return(message)))
744 if (!(path = job_dbus_path(j)))
747 if (!dbus_message_append_args(
749 DBUS_TYPE_OBJECT_PATH, &path,
753 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ClearJobs")) {
755 manager_clear_jobs(m);
757 if (!(reply = dbus_message_new_method_return(message)))
760 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ResetFailed")) {
762 manager_reset_failed(m);
764 if (!(reply = dbus_message_new_method_return(message)))
767 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ResetFailedUnit")) {
771 if (!dbus_message_get_args(
774 DBUS_TYPE_STRING, &name,
776 return bus_send_error_reply(connection, message, &error, -EINVAL);
778 if (!(u = manager_get_unit(m, name))) {
779 dbus_set_error(&error, BUS_ERROR_NO_SUCH_UNIT, "Unit %s is not loaded.", name);
780 return bus_send_error_reply(connection, message, &error, -ENOENT);
783 unit_reset_failed(u);
785 if (!(reply = dbus_message_new_method_return(message)))
788 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ListUnits")) {
789 DBusMessageIter iter, sub;
794 if (!(reply = dbus_message_new_method_return(message)))
797 dbus_message_iter_init_append(reply, &iter);
799 if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "(ssssssouso)", &sub))
802 HASHMAP_FOREACH_KEY(u, k, m->units, i) {
803 char *u_path, *j_path;
804 const char *description, *load_state, *active_state, *sub_state, *sjob_type, *following;
805 DBusMessageIter sub2;
812 if (!dbus_message_iter_open_container(&sub, DBUS_TYPE_STRUCT, NULL, &sub2))
815 description = unit_description(u);
816 load_state = unit_load_state_to_string(u->load_state);
817 active_state = unit_active_state_to_string(unit_active_state(u));
818 sub_state = unit_sub_state_to_string(u);
820 f = unit_following(u);
821 following = f ? f->id : "";
823 if (!(u_path = unit_dbus_path(u)))
827 job_id = (uint32_t) u->job->id;
829 if (!(j_path = job_dbus_path(u->job))) {
834 sjob_type = job_type_to_string(u->job->type);
841 if (!dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &u->id) ||
842 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &description) ||
843 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &load_state) ||
844 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &active_state) ||
845 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &sub_state) ||
846 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &following) ||
847 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_OBJECT_PATH, &u_path) ||
848 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_UINT32, &job_id) ||
849 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &sjob_type) ||
850 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_OBJECT_PATH, &j_path)) {
861 if (!dbus_message_iter_close_container(&sub, &sub2))
865 if (!dbus_message_iter_close_container(&iter, &sub))
868 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ListJobs")) {
869 DBusMessageIter iter, sub;
873 if (!(reply = dbus_message_new_method_return(message)))
876 dbus_message_iter_init_append(reply, &iter);
878 if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "(usssoo)", &sub))
881 HASHMAP_FOREACH(j, m->jobs, i) {
882 char *u_path, *j_path;
883 const char *state, *type;
885 DBusMessageIter sub2;
887 if (!dbus_message_iter_open_container(&sub, DBUS_TYPE_STRUCT, NULL, &sub2))
890 id = (uint32_t) j->id;
891 state = job_state_to_string(j->state);
892 type = job_type_to_string(j->type);
894 if (!(j_path = job_dbus_path(j)))
897 if (!(u_path = unit_dbus_path(j->unit))) {
902 if (!dbus_message_iter_append_basic(&sub2, DBUS_TYPE_UINT32, &id) ||
903 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &j->unit->id) ||
904 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &type) ||
905 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &state) ||
906 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_OBJECT_PATH, &j_path) ||
907 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_OBJECT_PATH, &u_path)) {
916 if (!dbus_message_iter_close_container(&sub, &sub2))
920 if (!dbus_message_iter_close_container(&iter, &sub))
923 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "Subscribe")) {
927 if (!(s = BUS_CONNECTION_SUBSCRIBED(m, connection))) {
928 if (!(s = set_new(string_hash_func, string_compare_func)))
931 if (!(dbus_connection_set_data(connection, m->subscribed_data_slot, s, NULL))) {
937 if (!(client = strdup(message_get_sender_with_fallback(message))))
940 if ((r = set_put(s, client)) < 0) {
942 return bus_send_error_reply(connection, message, NULL, r);
945 if (!(reply = dbus_message_new_method_return(message)))
948 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "Unsubscribe")) {
951 if (!(client = set_remove(BUS_CONNECTION_SUBSCRIBED(m, connection), (char*) message_get_sender_with_fallback(message)))) {
952 dbus_set_error(&error, BUS_ERROR_NOT_SUBSCRIBED, "Client is not subscribed.");
953 return bus_send_error_reply(connection, message, &error, -ENOENT);
958 if (!(reply = dbus_message_new_method_return(message)))
961 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "Dump")) {
966 if (!(reply = dbus_message_new_method_return(message)))
969 if (!(f = open_memstream(&dump, &size)))
972 manager_dump_units(m, f, NULL);
973 manager_dump_jobs(m, f, NULL);
983 if (!dbus_message_append_args(reply, DBUS_TYPE_STRING, &dump, DBUS_TYPE_INVALID)) {
989 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "CreateSnapshot")) {
994 if (!dbus_message_get_args(
997 DBUS_TYPE_STRING, &name,
998 DBUS_TYPE_BOOLEAN, &cleanup,
1000 return bus_send_error_reply(connection, message, &error, -EINVAL);
1002 if (name && name[0] == 0)
1005 if ((r = snapshot_create(m, name, cleanup, &error, &s)) < 0)
1006 return bus_send_error_reply(connection, message, &error, r);
1008 if (!(reply = dbus_message_new_method_return(message)))
1011 if (!(path = unit_dbus_path(UNIT(s))))
1014 if (!dbus_message_append_args(
1016 DBUS_TYPE_OBJECT_PATH, &path,
1020 } else if (dbus_message_is_method_call(message, "org.freedesktop.DBus.Introspectable", "Introspect")) {
1021 char *introspection = NULL;
1029 if (!(reply = dbus_message_new_method_return(message)))
1032 /* We roll our own introspection code here, instead of
1033 * relying on bus_default_message_handler() because we
1034 * need to generate our introspection string
1037 if (!(f = open_memstream(&introspection, &size)))
1040 fputs(INTROSPECTION_BEGIN, f);
1042 HASHMAP_FOREACH_KEY(u, k, m->units, i) {
1048 if (!(p = bus_path_escape(k))) {
1050 free(introspection);
1054 fprintf(f, "<node name=\"unit/%s\"/>", p);
1058 HASHMAP_FOREACH(j, m->jobs, i)
1059 fprintf(f, "<node name=\"job/%lu\"/>", (unsigned long) j->id);
1061 fputs(INTROSPECTION_END, f);
1065 free(introspection);
1074 if (!dbus_message_append_args(reply, DBUS_TYPE_STRING, &introspection, DBUS_TYPE_INVALID)) {
1075 free(introspection);
1079 free(introspection);
1081 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "Reload")) {
1083 assert(!m->queued_message);
1085 /* Instead of sending the reply back right away, we
1086 * just remember that we need to and then send it
1087 * after the reload is finished. That way the caller
1088 * knows when the reload finished. */
1090 if (!(m->queued_message = dbus_message_new_method_return(message)))
1093 m->queued_message_connection = connection;
1094 m->exit_code = MANAGER_RELOAD;
1096 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "Reexecute")) {
1098 /* We don't send a reply back here, the client should
1099 * just wait for us disconnecting. */
1101 m->exit_code = MANAGER_REEXECUTE;
1103 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "Exit")) {
1105 if (m->running_as == MANAGER_SYSTEM) {
1106 dbus_set_error(&error, BUS_ERROR_NOT_SUPPORTED, "Exit is only supported for user service managers.");
1107 return bus_send_error_reply(connection, message, &error, -ENOTSUP);
1110 if (!(reply = dbus_message_new_method_return(message)))
1113 m->exit_code = MANAGER_EXIT;
1115 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "Reboot")) {
1117 if (m->running_as != MANAGER_SYSTEM) {
1118 dbus_set_error(&error, BUS_ERROR_NOT_SUPPORTED, "Reboot is only supported for system 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_REBOOT;
1127 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "PowerOff")) {
1129 if (m->running_as != MANAGER_SYSTEM) {
1130 dbus_set_error(&error, BUS_ERROR_NOT_SUPPORTED, "Powering off 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_POWEROFF;
1139 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "Halt")) {
1141 if (m->running_as != MANAGER_SYSTEM) {
1142 dbus_set_error(&error, BUS_ERROR_NOT_SUPPORTED, "Halting 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_HALT;
1151 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "KExec")) {
1153 if (m->running_as != MANAGER_SYSTEM) {
1154 dbus_set_error(&error, BUS_ERROR_NOT_SUPPORTED, "kexec 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_KEXEC;
1163 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "SetEnvironment")) {
1164 char **l = NULL, **e = NULL;
1166 if ((r = bus_parse_strv(message, &l)) < 0) {
1170 return bus_send_error_reply(connection, message, NULL, r);
1173 e = strv_env_merge(2, m->environment, l);
1179 if (!(reply = dbus_message_new_method_return(message))) {
1184 strv_free(m->environment);
1187 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "UnsetEnvironment")) {
1188 char **l = NULL, **e = NULL;
1190 if ((r = bus_parse_strv(message, &l)) < 0) {
1194 return bus_send_error_reply(connection, message, NULL, r);
1197 e = strv_env_delete(m->environment, 1, l);
1203 if (!(reply = dbus_message_new_method_return(message))) {
1208 strv_free(m->environment);
1211 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "UnsetAndSetEnvironment")) {
1212 char **l_set = NULL, **l_unset = NULL, **e = NULL, **f = NULL;
1213 DBusMessageIter iter;
1215 if (!dbus_message_iter_init(message, &iter))
1218 r = bus_parse_strv_iter(&iter, &l_unset);
1223 return bus_send_error_reply(connection, message, NULL, r);
1226 if (!dbus_message_iter_next(&iter)) {
1228 return bus_send_error_reply(connection, message, NULL, -EINVAL);
1231 r = bus_parse_strv_iter(&iter, &l_set);
1237 return bus_send_error_reply(connection, message, NULL, r);
1240 e = strv_env_delete(m->environment, 1, l_unset);
1248 f = strv_env_merge(2, e, l_set);
1255 if (!(reply = dbus_message_new_method_return(message))) {
1260 strv_free(m->environment);
1262 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ListUnitFiles")) {
1263 DBusMessageIter iter, sub, sub2;
1268 reply = dbus_message_new_method_return(message);
1272 h = hashmap_new(string_hash_func, string_compare_func);
1276 r = unit_file_get_list(m->running_as == MANAGER_SYSTEM ? UNIT_FILE_SYSTEM : UNIT_FILE_USER, NULL, h);
1278 unit_file_list_free(h);
1279 dbus_message_unref(reply);
1280 return bus_send_error_reply(connection, message, NULL, r);
1283 dbus_message_iter_init_append(reply, &iter);
1285 if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "(ss)", &sub)) {
1286 unit_file_list_free(h);
1290 HASHMAP_FOREACH(item, h, i) {
1293 state = unit_file_state_to_string(item->state);
1296 if (!dbus_message_iter_open_container(&sub, DBUS_TYPE_STRUCT, NULL, &sub2) ||
1297 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &item->path) ||
1298 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &state) ||
1299 !dbus_message_iter_close_container(&sub, &sub2)) {
1300 unit_file_list_free(h);
1305 unit_file_list_free(h);
1307 if (!dbus_message_iter_close_container(&iter, &sub))
1310 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "GetUnitFileState")) {
1312 UnitFileState state;
1315 if (!dbus_message_get_args(
1318 DBUS_TYPE_STRING, &name,
1320 return bus_send_error_reply(connection, message, &error, -EINVAL);
1322 state = unit_file_get_state(m->running_as == MANAGER_SYSTEM ? UNIT_FILE_SYSTEM : UNIT_FILE_USER, NULL, name);
1324 return bus_send_error_reply(connection, message, NULL, state);
1326 s = unit_file_state_to_string(state);
1329 reply = dbus_message_new_method_return(message);
1333 if (!dbus_message_append_args(
1335 DBUS_TYPE_STRING, &s,
1338 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "EnableUnitFiles") ||
1339 dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ReenableUnitFiles") ||
1340 dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "LinkUnitFiles") ||
1341 dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "PresetUnitFiles") ||
1342 dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "MaskUnitFiles")) {
1345 DBusMessageIter iter;
1346 UnitFileScope scope = m->running_as == MANAGER_SYSTEM ? UNIT_FILE_SYSTEM : UNIT_FILE_USER;
1347 UnitFileChange *changes = NULL;
1348 unsigned n_changes = 0;
1349 dbus_bool_t runtime, force;
1350 int carries_install_info = -1;
1352 if (!dbus_message_iter_init(message, &iter))
1355 r = bus_parse_strv_iter(&iter, &l);
1360 return bus_send_error_reply(connection, message, NULL, r);
1363 if (!dbus_message_iter_next(&iter) ||
1364 bus_iter_get_basic_and_next(&iter, DBUS_TYPE_BOOLEAN, &runtime, true) < 0 ||
1365 bus_iter_get_basic_and_next(&iter, DBUS_TYPE_BOOLEAN, &force, false) < 0) {
1367 return bus_send_error_reply(connection, message, NULL, -EIO);
1370 if (streq(member, "EnableUnitFiles")) {
1371 r = unit_file_enable(scope, runtime, NULL, l, force, &changes, &n_changes);
1372 carries_install_info = r;
1373 } else if (streq(member, "ReenableUnitFiles")) {
1374 r = unit_file_reenable(scope, runtime, NULL, l, force, &changes, &n_changes);
1375 carries_install_info = r;
1376 } else if (streq(member, "LinkUnitFiles"))
1377 r = unit_file_link(scope, runtime, NULL, l, force, &changes, &n_changes);
1378 else if (streq(member, "PresetUnitFiles")) {
1379 r = unit_file_preset(scope, runtime, NULL, l, force, &changes, &n_changes);
1380 carries_install_info = r;
1381 } else if (streq(member, "MaskUnitFiles"))
1382 r = unit_file_mask(scope, runtime, NULL, l, force, &changes, &n_changes);
1384 assert_not_reached("Uh? Wrong method");
1387 bus_manager_send_unit_files_changed(m);
1390 unit_file_changes_free(changes, n_changes);
1391 return bus_send_error_reply(connection, message, NULL, r);
1394 reply = message_from_file_changes(message, changes, n_changes, carries_install_info);
1395 unit_file_changes_free(changes, n_changes);
1400 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "DisableUnitFiles") ||
1401 dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "UnmaskUnitFiles")) {
1404 DBusMessageIter iter;
1405 UnitFileScope scope = m->running_as == MANAGER_SYSTEM ? UNIT_FILE_SYSTEM : UNIT_FILE_USER;
1406 UnitFileChange *changes = NULL;
1407 unsigned n_changes = 0;
1408 dbus_bool_t runtime;
1410 if (!dbus_message_iter_init(message, &iter))
1413 r = bus_parse_strv_iter(&iter, &l);
1418 return bus_send_error_reply(connection, message, NULL, r);
1421 if (!dbus_message_iter_next(&iter) ||
1422 bus_iter_get_basic_and_next(&iter, DBUS_TYPE_BOOLEAN, &runtime, false) < 0) {
1424 return bus_send_error_reply(connection, message, NULL, -EIO);
1427 if (streq(member, "DisableUnitFiles"))
1428 r = unit_file_disable(scope, runtime, NULL, l, &changes, &n_changes);
1429 else if (streq(member, "UnmaskUnitFiles"))
1430 r = unit_file_unmask(scope, runtime, NULL, l, &changes, &n_changes);
1432 assert_not_reached("Uh? Wrong method");
1435 bus_manager_send_unit_files_changed(m);
1438 unit_file_changes_free(changes, n_changes);
1439 return bus_send_error_reply(connection, message, NULL, r);
1442 reply = message_from_file_changes(message, changes, n_changes, -1);
1443 unit_file_changes_free(changes, n_changes);
1449 const BusBoundProperties bps[] = {
1450 { "org.freedesktop.systemd1.Manager", bus_systemd_properties, systemd_property_string },
1451 { "org.freedesktop.systemd1.Manager", bus_manager_properties, m },
1454 return bus_default_message_handler(connection, message, NULL, INTERFACES_LIST, bps);
1457 if (job_type != _JOB_TYPE_INVALID) {
1458 const char *name, *smode, *old_name = NULL;
1464 if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "StartUnitReplace"))
1465 b = dbus_message_get_args(
1468 DBUS_TYPE_STRING, &old_name,
1469 DBUS_TYPE_STRING, &name,
1470 DBUS_TYPE_STRING, &smode,
1473 b = dbus_message_get_args(
1476 DBUS_TYPE_STRING, &name,
1477 DBUS_TYPE_STRING, &smode,
1481 return bus_send_error_reply(connection, message, &error, -EINVAL);
1484 if (!(u = manager_get_unit(m, old_name)) ||
1486 u->job->type != JOB_START) {
1487 dbus_set_error(&error, BUS_ERROR_NO_SUCH_JOB, "No job queued for unit %s", old_name);
1488 return bus_send_error_reply(connection, message, &error, -ENOENT);
1492 if ((mode = job_mode_from_string(smode)) == _JOB_MODE_INVALID) {
1493 dbus_set_error(&error, BUS_ERROR_INVALID_JOB_MODE, "Job mode %s is invalid.", smode);
1494 return bus_send_error_reply(connection, message, &error, -EINVAL);
1497 if ((r = manager_load_unit(m, name, NULL, &error, &u)) < 0)
1498 return bus_send_error_reply(connection, message, &error, r);
1500 if (reload_if_possible && unit_can_reload(u)) {
1501 if (job_type == JOB_RESTART)
1502 job_type = JOB_RELOAD_OR_START;
1503 else if (job_type == JOB_TRY_RESTART)
1504 job_type = JOB_RELOAD;
1507 if ((job_type == JOB_START && u->refuse_manual_start) ||
1508 (job_type == JOB_STOP && u->refuse_manual_stop) ||
1509 ((job_type == JOB_RESTART || job_type == JOB_TRY_RESTART) &&
1510 (u->refuse_manual_start || u->refuse_manual_stop))) {
1511 dbus_set_error(&error, BUS_ERROR_ONLY_BY_DEPENDENCY, "Operation refused, may be requested by dependency only.");
1512 return bus_send_error_reply(connection, message, &error, -EPERM);
1515 if ((r = manager_add_job(m, job_type, u, mode, true, &error, &j)) < 0)
1516 return bus_send_error_reply(connection, message, &error, r);
1518 if (!(j->bus_client = strdup(message_get_sender_with_fallback(message))))
1521 j->bus = connection;
1523 if (!(reply = dbus_message_new_method_return(message)))
1526 if (!(path = job_dbus_path(j)))
1529 if (!dbus_message_append_args(
1531 DBUS_TYPE_OBJECT_PATH, &path,
1537 if (!dbus_connection_send(connection, reply, NULL))
1540 dbus_message_unref(reply);
1545 return DBUS_HANDLER_RESULT_HANDLED;
1551 dbus_message_unref(reply);
1553 dbus_error_free(&error);
1555 return DBUS_HANDLER_RESULT_NEED_MEMORY;
1558 const DBusObjectPathVTable bus_manager_vtable = {
1559 .message_function = bus_manager_message_handler