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 #include "path-util.h"
37 #define BUS_MANAGER_INTERFACE_BEGIN \
38 " <interface name=\"org.freedesktop.systemd1.Manager\">\n"
40 #define BUS_MANAGER_INTERFACE_METHODS \
41 " <method name=\"GetUnit\">\n" \
42 " <arg name=\"name\" type=\"s\" direction=\"in\"/>\n" \
43 " <arg name=\"unit\" type=\"o\" direction=\"out\"/>\n" \
45 " <method name=\"GetUnitByPID\">\n" \
46 " <arg name=\"pid\" type=\"u\" direction=\"in\"/>\n" \
47 " <arg name=\"unit\" type=\"o\" direction=\"out\"/>\n" \
49 " <method name=\"LoadUnit\">\n" \
50 " <arg name=\"name\" type=\"s\" direction=\"in\"/>\n" \
51 " <arg name=\"unit\" type=\"o\" direction=\"out\"/>\n" \
53 " <method name=\"StartUnit\">\n" \
54 " <arg name=\"name\" type=\"s\" direction=\"in\"/>\n" \
55 " <arg name=\"mode\" type=\"s\" direction=\"in\"/>\n" \
56 " <arg name=\"job\" type=\"o\" direction=\"out\"/>\n" \
58 " <method name=\"StartUnitReplace\">\n" \
59 " <arg name=\"old_unit\" type=\"s\" direction=\"in\"/>\n" \
60 " <arg name=\"new_unit\" type=\"s\" direction=\"in\"/>\n" \
61 " <arg name=\"mode\" type=\"s\" direction=\"in\"/>\n" \
62 " <arg name=\"job\" type=\"o\" direction=\"out\"/>\n" \
64 " <method name=\"StopUnit\">\n" \
65 " <arg name=\"name\" type=\"s\" direction=\"in\"/>\n" \
66 " <arg name=\"mode\" type=\"s\" direction=\"in\"/>\n" \
67 " <arg name=\"job\" type=\"o\" direction=\"out\"/>\n" \
69 " <method name=\"ReloadUnit\">\n" \
70 " <arg name=\"name\" type=\"s\" direction=\"in\"/>\n" \
71 " <arg name=\"mode\" type=\"s\" direction=\"in\"/>\n" \
72 " <arg name=\"job\" type=\"o\" direction=\"out\"/>\n" \
74 " <method name=\"RestartUnit\">\n" \
75 " <arg name=\"name\" type=\"s\" direction=\"in\"/>\n" \
76 " <arg name=\"mode\" type=\"s\" direction=\"in\"/>\n" \
77 " <arg name=\"job\" type=\"o\" direction=\"out\"/>\n" \
79 " <method name=\"TryRestartUnit\">\n" \
80 " <arg name=\"name\" type=\"s\" direction=\"in\"/>\n" \
81 " <arg name=\"mode\" type=\"s\" direction=\"in\"/>\n" \
82 " <arg name=\"job\" type=\"o\" direction=\"out\"/>\n" \
84 " <method name=\"ReloadOrRestartUnit\">\n" \
85 " <arg name=\"name\" type=\"s\" direction=\"in\"/>\n" \
86 " <arg name=\"mode\" type=\"s\" direction=\"in\"/>\n" \
87 " <arg name=\"job\" type=\"o\" direction=\"out\"/>\n" \
89 " <method name=\"ReloadOrTryRestartUnit\">\n" \
90 " <arg name=\"name\" type=\"s\" direction=\"in\"/>\n" \
91 " <arg name=\"mode\" type=\"s\" direction=\"in\"/>\n" \
92 " <arg name=\"job\" type=\"o\" direction=\"out\"/>\n" \
94 " <method name=\"KillUnit\">\n" \
95 " <arg name=\"name\" type=\"s\" direction=\"in\"/>\n" \
96 " <arg name=\"who\" type=\"s\" direction=\"in\"/>\n" \
97 " <arg name=\"mode\" type=\"s\" direction=\"in\"/>\n" \
98 " <arg name=\"signal\" type=\"i\" direction=\"in\"/>\n" \
100 " <method name=\"ResetFailedUnit\">\n" \
101 " <arg name=\"name\" type=\"s\" direction=\"in\"/>\n" \
103 " <method name=\"GetJob\">\n" \
104 " <arg name=\"id\" type=\"u\" direction=\"in\"/>\n" \
105 " <arg name=\"job\" type=\"o\" direction=\"out\"/>\n" \
107 " <method name=\"ClearJobs\"/>\n" \
108 " <method name=\"ResetFailed\"/>\n" \
109 " <method name=\"ListUnits\">\n" \
110 " <arg name=\"units\" type=\"a(ssssssouso)\" direction=\"out\"/>\n" \
112 " <method name=\"ListJobs\">\n" \
113 " <arg name=\"jobs\" type=\"a(usssoo)\" direction=\"out\"/>\n" \
115 " <method name=\"Subscribe\"/>\n" \
116 " <method name=\"Unsubscribe\"/>\n" \
117 " <method name=\"Dump\"/>\n" \
118 " <method name=\"CreateSnapshot\">\n" \
119 " <arg name=\"name\" type=\"s\" direction=\"in\"/>\n" \
120 " <arg name=\"cleanup\" type=\"b\" direction=\"in\"/>\n" \
121 " <arg name=\"unit\" type=\"o\" direction=\"out\"/>\n" \
123 " <method name=\"Reload\"/>\n" \
124 " <method name=\"Reexecute\"/>\n" \
125 " <method name=\"Exit\"/>\n" \
126 " <method name=\"Reboot\"/>\n" \
127 " <method name=\"PowerOff\"/>\n" \
128 " <method name=\"Halt\"/>\n" \
129 " <method name=\"KExec\"/>\n" \
130 " <method name=\"SwitchRoot\">\n" \
131 " <arg name=\"new_root\" type=\"s\" direction=\"in\"/>\n" \
132 " <arg name=\"init\" type=\"s\" direction=\"in\"/>\n" \
134 " <method name=\"SetEnvironment\">\n" \
135 " <arg name=\"names\" type=\"as\" direction=\"in\"/>\n" \
137 " <method name=\"UnsetEnvironment\">\n" \
138 " <arg name=\"names\" type=\"as\" direction=\"in\"/>\n" \
140 " <method name=\"UnsetAndSetEnvironment\">\n" \
141 " <arg name=\"unset\" type=\"as\" direction=\"in\"/>\n" \
142 " <arg name=\"set\" type=\"as\" direction=\"in\"/>\n" \
144 " <method name=\"ListUnitFiles\">\n" \
145 " <arg name=\"changes\" type=\"a(ss)\" direction=\"out\"/>\n" \
147 " <method name=\"GetUnitFileState\">\n" \
148 " <arg name=\"file\" type=\"s\" direction=\"in\"/>\n" \
149 " <arg name=\"state\" type=\"s\" direction=\"out\"/>\n" \
151 " <method name=\"EnableUnitFiles\">\n" \
152 " <arg name=\"files\" type=\"as\" direction=\"in\"/>\n" \
153 " <arg name=\"runtime\" type=\"b\" direction=\"in\"/>\n" \
154 " <arg name=\"force\" type=\"b\" direction=\"in\"/>\n" \
155 " <arg name=\"carries_install_info\" type=\"b\" direction=\"out\"/>\n" \
156 " <arg name=\"changes\" type=\"a(sss)\" direction=\"out\"/>\n" \
158 " <method name=\"DisableUnitFiles\">\n" \
159 " <arg name=\"files\" type=\"as\" direction=\"in\"/>\n" \
160 " <arg name=\"runtime\" type=\"b\" direction=\"in\"/>\n" \
161 " <arg name=\"changes\" type=\"a(sss)\" direction=\"out\"/>\n" \
163 " <method name=\"ReenableUnitFiles\">\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=\"carries_install_info\" type=\"b\" direction=\"out\"/>\n" \
168 " <arg name=\"changes\" type=\"a(sss)\" direction=\"out\"/>\n" \
170 " <method name=\"LinkUnitFiles\">\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=\"changes\" type=\"a(sss)\" direction=\"out\"/>\n" \
176 " <method name=\"PresetUnitFiles\">\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=\"carries_install_info\" type=\"b\" direction=\"out\"/>\n" \
181 " <arg name=\"changes\" type=\"a(sss)\" direction=\"out\"/>\n" \
183 " <method name=\"MaskUnitFiles\">\n" \
184 " <arg name=\"files\" type=\"as\" direction=\"in\"/>\n" \
185 " <arg name=\"runtime\" type=\"b\" direction=\"in\"/>\n" \
186 " <arg name=\"force\" type=\"b\" direction=\"in\"/>\n" \
187 " <arg name=\"changes\" type=\"a(sss)\" direction=\"out\"/>\n" \
189 " <method name=\"UnmaskUnitFiles\">\n" \
190 " <arg name=\"files\" type=\"as\" direction=\"in\"/>\n" \
191 " <arg name=\"runtime\" type=\"b\" direction=\"in\"/>\n" \
192 " <arg name=\"changes\" type=\"a(sss)\" direction=\"out\"/>\n" \
195 #define BUS_MANAGER_INTERFACE_SIGNALS \
196 " <signal name=\"UnitNew\">\n" \
197 " <arg name=\"id\" type=\"s\"/>\n" \
198 " <arg name=\"unit\" type=\"o\"/>\n" \
200 " <signal name=\"UnitRemoved\">\n" \
201 " <arg name=\"id\" type=\"s\"/>\n" \
202 " <arg name=\"unit\" type=\"o\"/>\n" \
204 " <signal name=\"JobNew\">\n" \
205 " <arg name=\"id\" type=\"u\"/>\n" \
206 " <arg name=\"job\" type=\"o\"/>\n" \
207 " <arg name=\"unit\" type=\"s\"/>\n" \
209 " <signal name=\"JobRemoved\">\n" \
210 " <arg name=\"id\" type=\"u\"/>\n" \
211 " <arg name=\"job\" type=\"o\"/>\n" \
212 " <arg name=\"unit\" type=\"s\"/>\n" \
213 " <arg name=\"result\" type=\"s\"/>\n" \
215 " <signal name=\"StartupFinished\">\n" \
216 " <arg name=\"kernel\" type=\"t\"/>\n" \
217 " <arg name=\"initrd\" type=\"t\"/>\n" \
218 " <arg name=\"userspace\" type=\"t\"/>\n" \
219 " <arg name=\"total\" type=\"t\"/>\n" \
221 " <signal name=\"UnitFilesChanged\"/>\n"
223 #define BUS_MANAGER_INTERFACE_PROPERTIES_GENERAL \
224 " <property name=\"Version\" type=\"s\" access=\"read\"/>\n" \
225 " <property name=\"Distribution\" type=\"s\" access=\"read\"/>\n" \
226 " <property name=\"Features\" type=\"s\" access=\"read\"/>\n" \
227 " <property name=\"Tainted\" type=\"s\" access=\"read\"/>\n" \
228 " <property name=\"InitRDTimestamp\" type=\"t\" access=\"read\"/>\n" \
229 " <property name=\"InitRDTimestampMonotonic\" type=\"t\" access=\"read\"/>\n" \
230 " <property name=\"StartupTimestamp\" type=\"t\" access=\"read\"/>\n" \
231 " <property name=\"StartupTimestampMonotonic\" type=\"t\" access=\"read\"/>\n" \
232 " <property name=\"FinishTimestamp\" type=\"t\" access=\"read\"/>\n" \
233 " <property name=\"FinishTimestampMonotonic\" type=\"t\" access=\"read\"/>\n" \
234 " <property name=\"LogLevel\" type=\"s\" access=\"readwrite\"/>\n" \
235 " <property name=\"LogTarget\" type=\"s\" access=\"readwrite\"/>\n" \
236 " <property name=\"NNames\" type=\"u\" access=\"read\"/>\n" \
237 " <property name=\"NJobs\" type=\"u\" access=\"read\"/>\n" \
238 " <property name=\"NInstalledJobs\" type=\"u\" access=\"read\"/>\n" \
239 " <property name=\"NFailedJobs\" type=\"u\" access=\"read\"/>\n" \
240 " <property name=\"Progress\" type=\"d\" access=\"read\"/>\n" \
241 " <property name=\"Environment\" type=\"as\" access=\"read\"/>\n" \
242 " <property name=\"ConfirmSpawn\" type=\"b\" access=\"read\"/>\n" \
243 " <property name=\"ShowStatus\" type=\"b\" access=\"read\"/>\n" \
244 " <property name=\"UnitPath\" type=\"as\" access=\"read\"/>\n" \
245 " <property name=\"ControlGroupHierarchy\" type=\"s\" access=\"read\"/>\n" \
246 " <property name=\"DefaultControllers\" type=\"as\" access=\"read\"/>\n" \
247 " <property name=\"DefaultStandardOutput\" type=\"s\" access=\"read\"/>\n" \
248 " <property name=\"DefaultStandardError\" type=\"s\" access=\"read\"/>\n" \
249 " <property name=\"RuntimeWatchdogUSec\" type=\"s\" access=\"readwrite\"/>\n" \
250 " <property name=\"ShutdownWatchdogUSec\" type=\"s\" access=\"readwrite\"/>\n" \
251 " <property name=\"HaveWatchdog\" type=\"b\" access=\"read\"/>\n"
253 #ifdef HAVE_SYSV_COMPAT
254 #define BUS_MANAGER_INTERFACE_PROPERTIES_SYSV \
255 " <property name=\"SysVConsole\" type=\"b\" access=\"read\"/>\n" \
256 " <property name=\"SysVInitPath\" type=\"as\" access=\"read\"/>\n" \
257 " <property name=\"SysVRcndPath\" type=\"as\" access=\"read\"/>\n"
259 #define BUS_MANAGER_INTERFACE_PROPERTIES_SYSV
262 #define BUS_MANAGER_INTERFACE_END \
265 #define BUS_MANAGER_INTERFACE \
266 BUS_MANAGER_INTERFACE_BEGIN \
267 BUS_MANAGER_INTERFACE_METHODS \
268 BUS_MANAGER_INTERFACE_SIGNALS \
269 BUS_MANAGER_INTERFACE_PROPERTIES_GENERAL \
270 BUS_MANAGER_INTERFACE_PROPERTIES_SYSV \
271 BUS_MANAGER_INTERFACE_END
273 #define INTROSPECTION_BEGIN \
274 DBUS_INTROSPECT_1_0_XML_DOCTYPE_DECL_NODE \
276 BUS_MANAGER_INTERFACE \
277 BUS_PROPERTIES_INTERFACE \
279 BUS_INTROSPECTABLE_INTERFACE
281 #define INTROSPECTION_END \
284 #define INTERFACES_LIST \
285 BUS_GENERIC_INTERFACES_LIST \
286 "org.freedesktop.systemd1.Manager\0"
288 const char bus_manager_interface[] _introspect_("Manager") = BUS_MANAGER_INTERFACE;
290 static DEFINE_BUS_PROPERTY_APPEND_ENUM(bus_manager_append_exec_output, exec_output, ExecOutput);
292 static int bus_manager_append_tainted(DBusMessageIter *i, const char *property, void *data) {
295 char buf[LINE_MAX] = "", *e = buf, *p = NULL;
302 e = stpcpy(e, "split-usr:");
304 if (readlink_malloc("/etc/mtab", &p) < 0)
305 e = stpcpy(e, "mtab-not-symlink:");
309 if (access("/proc/cgroups", F_OK) < 0)
310 e = stpcpy(e, "cgroups-missing:");
312 if (hwclock_is_localtime() > 0)
313 e = stpcpy(e, "local-hwclock:");
315 /* remove the last ':' */
321 if (!dbus_message_iter_append_basic(i, DBUS_TYPE_STRING, &t))
327 static int bus_manager_append_log_target(DBusMessageIter *i, const char *property, void *data) {
333 t = log_target_to_string(log_get_target());
335 if (!dbus_message_iter_append_basic(i, DBUS_TYPE_STRING, &t))
341 static int bus_manager_set_log_target(DBusMessageIter *i, const char *property, void *data) {
347 dbus_message_iter_get_basic(i, &t);
349 return log_set_target_from_string(t);
352 static int bus_manager_append_log_level(DBusMessageIter *i, const char *property, void *data) {
358 t = log_level_to_string(log_get_max_level());
360 if (!dbus_message_iter_append_basic(i, DBUS_TYPE_STRING, &t))
366 static int bus_manager_set_log_level(DBusMessageIter *i, const char *property, void *data) {
372 dbus_message_iter_get_basic(i, &t);
374 return log_set_max_level_from_string(t);
377 static int bus_manager_append_n_names(DBusMessageIter *i, const char *property, void *data) {
385 u = hashmap_size(m->units);
387 if (!dbus_message_iter_append_basic(i, DBUS_TYPE_UINT32, &u))
393 static int bus_manager_append_n_jobs(DBusMessageIter *i, const char *property, void *data) {
401 u = hashmap_size(m->jobs);
403 if (!dbus_message_iter_append_basic(i, DBUS_TYPE_UINT32, &u))
409 static int bus_manager_append_progress(DBusMessageIter *i, const char *property, void *data) {
417 if (dual_timestamp_is_set(&m->finish_timestamp))
420 d = 1.0 - ((double) hashmap_size(m->jobs) / (double) m->n_installed_jobs);
422 if (!dbus_message_iter_append_basic(i, DBUS_TYPE_DOUBLE, &d))
428 static const char *message_get_sender_with_fallback(DBusMessage *m) {
433 if ((s = dbus_message_get_sender(m)))
436 /* When the message came in from a direct connection the
437 * message will have no sender. We fix that here. */
442 static DBusMessage *message_from_file_changes(
444 UnitFileChange *changes,
446 int carries_install_info) {
448 DBusMessageIter iter, sub, sub2;
452 reply = dbus_message_new_method_return(m);
456 dbus_message_iter_init_append(reply, &iter);
458 if (carries_install_info >= 0) {
461 b = !!carries_install_info;
462 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &b))
466 if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "(sss)", &sub))
469 for (i = 0; i < n_changes; i++) {
470 const char *type, *path, *source;
472 type = unit_file_change_type_to_string(changes[i].type);
473 path = strempty(changes[i].path);
474 source = strempty(changes[i].source);
476 if (!dbus_message_iter_open_container(&sub, DBUS_TYPE_STRUCT, NULL, &sub2) ||
477 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &type) ||
478 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &path) ||
479 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &source) ||
480 !dbus_message_iter_close_container(&sub, &sub2))
484 if (!dbus_message_iter_close_container(&iter, &sub))
490 dbus_message_unref(reply);
494 static int bus_manager_send_unit_files_changed(Manager *m) {
498 s = dbus_message_new_signal("/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", "UnitFilesChanged");
502 r = bus_broadcast(m, s);
503 dbus_message_unref(s);
508 static int bus_manager_append_have_watchdog(DBusMessageIter *i, const char *property, void *data) {
514 b = access("/dev/watchdog", F_OK) >= 0;
516 if (!dbus_message_iter_append_basic(i, DBUS_TYPE_BOOLEAN, &b))
522 static int bus_manager_set_runtime_watchdog_usec(DBusMessageIter *i, const char *property, void *data) {
528 dbus_message_iter_get_basic(i, t);
530 return watchdog_set_timeout(t);
533 static const char systemd_property_string[] =
538 static const BusProperty bus_systemd_properties[] = {
539 { "Version", bus_property_append_string, "s", 0 },
540 { "Distribution", bus_property_append_string, "s", sizeof(PACKAGE_STRING) },
541 { "Features", bus_property_append_string, "s", sizeof(PACKAGE_STRING) + sizeof(DISTRIBUTION) },
545 static const BusProperty bus_manager_properties[] = {
546 { "Tainted", bus_manager_append_tainted, "s", 0 },
547 { "InitRDTimestamp", bus_property_append_uint64, "t", offsetof(Manager, initrd_timestamp.realtime) },
548 { "InitRDTimestampMonotonic", bus_property_append_uint64, "t", offsetof(Manager, initrd_timestamp.monotonic) },
549 { "StartupTimestamp", bus_property_append_uint64, "t", offsetof(Manager, startup_timestamp.realtime) },
550 { "StartupTimestampMonotonic", bus_property_append_uint64, "t", offsetof(Manager, startup_timestamp.monotonic) },
551 { "FinishTimestamp", bus_property_append_uint64, "t", offsetof(Manager, finish_timestamp.realtime) },
552 { "FinishTimestampMonotonic", bus_property_append_uint64, "t", offsetof(Manager, finish_timestamp.monotonic) },
553 { "LogLevel", bus_manager_append_log_level, "s", 0, false, bus_manager_set_log_level },
554 { "LogTarget", bus_manager_append_log_target, "s", 0, false, bus_manager_set_log_target },
555 { "NNames", bus_manager_append_n_names, "u", 0 },
556 { "NJobs", bus_manager_append_n_jobs, "u", 0 },
557 { "NInstalledJobs",bus_property_append_uint32, "u", offsetof(Manager, n_installed_jobs) },
558 { "NFailedJobs", bus_property_append_uint32, "u", offsetof(Manager, n_failed_jobs) },
559 { "Progress", bus_manager_append_progress, "d", 0 },
560 { "Environment", bus_property_append_strv, "as", offsetof(Manager, environment), true },
561 { "ConfirmSpawn", bus_property_append_bool, "b", offsetof(Manager, confirm_spawn) },
562 { "ShowStatus", bus_property_append_bool, "b", offsetof(Manager, show_status) },
563 { "UnitPath", bus_property_append_strv, "as", offsetof(Manager, lookup_paths.unit_path), true },
564 { "ControlGroupHierarchy", bus_property_append_string, "s", offsetof(Manager, cgroup_hierarchy), true },
565 { "DefaultControllers", bus_property_append_strv, "as", offsetof(Manager, default_controllers), true },
566 { "DefaultStandardOutput", bus_manager_append_exec_output, "s", offsetof(Manager, default_std_output) },
567 { "DefaultStandardError", bus_manager_append_exec_output, "s", offsetof(Manager, default_std_error) },
568 { "RuntimeWatchdogUSec", bus_property_append_usec, "t", offsetof(Manager, runtime_watchdog), false, bus_manager_set_runtime_watchdog_usec },
569 { "ShutdownWatchdogUSec", bus_property_append_usec, "t", offsetof(Manager, shutdown_watchdog), false, bus_property_set_usec },
570 { "HaveWatchdog", bus_manager_append_have_watchdog, "b", 0 },
571 #ifdef HAVE_SYSV_COMPAT
572 { "SysVConsole", bus_property_append_bool, "b", offsetof(Manager, sysv_console) },
573 { "SysVInitPath", bus_property_append_strv, "as", offsetof(Manager, lookup_paths.sysvinit_path), true },
574 { "SysVRcndPath", bus_property_append_strv, "as", offsetof(Manager, lookup_paths.sysvrcnd_path), true },
579 static DBusHandlerResult bus_manager_message_handler(DBusConnection *connection, DBusMessage *message, void *data) {
584 DBusMessage *reply = NULL;
586 JobType job_type = _JOB_TYPE_INVALID;
587 bool reload_if_possible = false;
594 dbus_error_init(&error);
596 member = dbus_message_get_member(message);
598 if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "GetUnit")) {
602 if (!dbus_message_get_args(
605 DBUS_TYPE_STRING, &name,
607 return bus_send_error_reply(connection, message, &error, -EINVAL);
609 if (!(u = manager_get_unit(m, name))) {
610 dbus_set_error(&error, BUS_ERROR_NO_SUCH_UNIT, "Unit %s is not loaded.", name);
611 return bus_send_error_reply(connection, message, &error, -ENOENT);
614 if (!(reply = dbus_message_new_method_return(message)))
617 if (!(path = unit_dbus_path(u)))
620 if (!dbus_message_append_args(
622 DBUS_TYPE_OBJECT_PATH, &path,
625 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "GetUnitByPID")) {
629 if (!dbus_message_get_args(
632 DBUS_TYPE_UINT32, &pid,
634 return bus_send_error_reply(connection, message, &error, -EINVAL);
636 if (!(u = cgroup_unit_by_pid(m, (pid_t) pid))) {
637 dbus_set_error(&error, BUS_ERROR_NO_SUCH_UNIT, "No unit for PID %lu is loaded.", (unsigned long) pid);
638 return bus_send_error_reply(connection, message, &error, -ENOENT);
641 if (!(reply = dbus_message_new_method_return(message)))
644 if (!(path = unit_dbus_path(u)))
647 if (!dbus_message_append_args(
649 DBUS_TYPE_OBJECT_PATH, &path,
652 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "LoadUnit")) {
656 if (!dbus_message_get_args(
659 DBUS_TYPE_STRING, &name,
661 return bus_send_error_reply(connection, message, &error, -EINVAL);
663 if ((r = manager_load_unit(m, name, NULL, &error, &u)) < 0)
664 return bus_send_error_reply(connection, message, &error, r);
666 if (!(reply = dbus_message_new_method_return(message)))
669 if (!(path = unit_dbus_path(u)))
672 if (!dbus_message_append_args(
674 DBUS_TYPE_OBJECT_PATH, &path,
678 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "StartUnit"))
679 job_type = JOB_START;
680 else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "StartUnitReplace"))
681 job_type = JOB_START;
682 else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "StopUnit"))
684 else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ReloadUnit"))
685 job_type = JOB_RELOAD;
686 else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "RestartUnit"))
687 job_type = JOB_RESTART;
688 else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "TryRestartUnit"))
689 job_type = JOB_TRY_RESTART;
690 else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ReloadOrRestartUnit")) {
691 reload_if_possible = true;
692 job_type = JOB_RESTART;
693 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ReloadOrTryRestartUnit")) {
694 reload_if_possible = true;
695 job_type = JOB_TRY_RESTART;
696 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "KillUnit")) {
697 const char *name, *swho, *smode;
703 if (!dbus_message_get_args(
706 DBUS_TYPE_STRING, &name,
707 DBUS_TYPE_STRING, &swho,
708 DBUS_TYPE_STRING, &smode,
709 DBUS_TYPE_INT32, &signo,
711 return bus_send_error_reply(connection, message, &error, -EINVAL);
716 who = kill_who_from_string(swho);
718 return bus_send_error_reply(connection, message, &error, -EINVAL);
722 mode = KILL_CONTROL_GROUP;
724 mode = kill_mode_from_string(smode);
726 return bus_send_error_reply(connection, message, &error, -EINVAL);
729 if (signo <= 0 || signo >= _NSIG)
730 return bus_send_error_reply(connection, message, &error, -EINVAL);
732 if (!(u = manager_get_unit(m, name))) {
733 dbus_set_error(&error, BUS_ERROR_NO_SUCH_UNIT, "Unit %s is not loaded.", name);
734 return bus_send_error_reply(connection, message, &error, -ENOENT);
737 if ((r = unit_kill(u, who, mode, signo, &error)) < 0)
738 return bus_send_error_reply(connection, message, &error, r);
740 if (!(reply = dbus_message_new_method_return(message)))
743 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "GetJob")) {
747 if (!dbus_message_get_args(
750 DBUS_TYPE_UINT32, &id,
752 return bus_send_error_reply(connection, message, &error, -EINVAL);
754 if (!(j = manager_get_job(m, id))) {
755 dbus_set_error(&error, BUS_ERROR_NO_SUCH_JOB, "Job %u does not exist.", (unsigned) id);
756 return bus_send_error_reply(connection, message, &error, -ENOENT);
759 if (!(reply = dbus_message_new_method_return(message)))
762 if (!(path = job_dbus_path(j)))
765 if (!dbus_message_append_args(
767 DBUS_TYPE_OBJECT_PATH, &path,
771 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ClearJobs")) {
773 manager_clear_jobs(m);
775 if (!(reply = dbus_message_new_method_return(message)))
778 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ResetFailed")) {
780 manager_reset_failed(m);
782 if (!(reply = dbus_message_new_method_return(message)))
785 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ResetFailedUnit")) {
789 if (!dbus_message_get_args(
792 DBUS_TYPE_STRING, &name,
794 return bus_send_error_reply(connection, message, &error, -EINVAL);
796 if (!(u = manager_get_unit(m, name))) {
797 dbus_set_error(&error, BUS_ERROR_NO_SUCH_UNIT, "Unit %s is not loaded.", name);
798 return bus_send_error_reply(connection, message, &error, -ENOENT);
801 unit_reset_failed(u);
803 if (!(reply = dbus_message_new_method_return(message)))
806 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ListUnits")) {
807 DBusMessageIter iter, sub;
812 if (!(reply = dbus_message_new_method_return(message)))
815 dbus_message_iter_init_append(reply, &iter);
817 if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "(ssssssouso)", &sub))
820 HASHMAP_FOREACH_KEY(u, k, m->units, i) {
821 char *u_path, *j_path;
822 const char *description, *load_state, *active_state, *sub_state, *sjob_type, *following;
823 DBusMessageIter sub2;
830 if (!dbus_message_iter_open_container(&sub, DBUS_TYPE_STRUCT, NULL, &sub2))
833 description = unit_description(u);
834 load_state = unit_load_state_to_string(u->load_state);
835 active_state = unit_active_state_to_string(unit_active_state(u));
836 sub_state = unit_sub_state_to_string(u);
838 f = unit_following(u);
839 following = f ? f->id : "";
841 if (!(u_path = unit_dbus_path(u)))
845 job_id = (uint32_t) u->job->id;
847 if (!(j_path = job_dbus_path(u->job))) {
852 sjob_type = job_type_to_string(u->job->type);
859 if (!dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &u->id) ||
860 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &description) ||
861 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &load_state) ||
862 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &active_state) ||
863 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &sub_state) ||
864 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &following) ||
865 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_OBJECT_PATH, &u_path) ||
866 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_UINT32, &job_id) ||
867 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &sjob_type) ||
868 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_OBJECT_PATH, &j_path)) {
879 if (!dbus_message_iter_close_container(&sub, &sub2))
883 if (!dbus_message_iter_close_container(&iter, &sub))
886 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ListJobs")) {
887 DBusMessageIter iter, sub;
891 if (!(reply = dbus_message_new_method_return(message)))
894 dbus_message_iter_init_append(reply, &iter);
896 if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "(usssoo)", &sub))
899 HASHMAP_FOREACH(j, m->jobs, i) {
900 char *u_path, *j_path;
901 const char *state, *type;
903 DBusMessageIter sub2;
905 if (!dbus_message_iter_open_container(&sub, DBUS_TYPE_STRUCT, NULL, &sub2))
908 id = (uint32_t) j->id;
909 state = job_state_to_string(j->state);
910 type = job_type_to_string(j->type);
912 if (!(j_path = job_dbus_path(j)))
915 if (!(u_path = unit_dbus_path(j->unit))) {
920 if (!dbus_message_iter_append_basic(&sub2, DBUS_TYPE_UINT32, &id) ||
921 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &j->unit->id) ||
922 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &type) ||
923 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &state) ||
924 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_OBJECT_PATH, &j_path) ||
925 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_OBJECT_PATH, &u_path)) {
934 if (!dbus_message_iter_close_container(&sub, &sub2))
938 if (!dbus_message_iter_close_container(&iter, &sub))
941 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "Subscribe")) {
945 if (!(s = BUS_CONNECTION_SUBSCRIBED(m, connection))) {
946 if (!(s = set_new(string_hash_func, string_compare_func)))
949 if (!(dbus_connection_set_data(connection, m->subscribed_data_slot, s, NULL))) {
955 if (!(client = strdup(message_get_sender_with_fallback(message))))
958 if ((r = set_put(s, client)) < 0) {
960 return bus_send_error_reply(connection, message, NULL, r);
963 if (!(reply = dbus_message_new_method_return(message)))
966 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "Unsubscribe")) {
969 if (!(client = set_remove(BUS_CONNECTION_SUBSCRIBED(m, connection), (char*) message_get_sender_with_fallback(message)))) {
970 dbus_set_error(&error, BUS_ERROR_NOT_SUBSCRIBED, "Client is not subscribed.");
971 return bus_send_error_reply(connection, message, &error, -ENOENT);
976 if (!(reply = dbus_message_new_method_return(message)))
979 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "Dump")) {
984 if (!(reply = dbus_message_new_method_return(message)))
987 if (!(f = open_memstream(&dump, &size)))
990 manager_dump_units(m, f, NULL);
991 manager_dump_jobs(m, f, NULL);
1001 if (!dbus_message_append_args(reply, DBUS_TYPE_STRING, &dump, DBUS_TYPE_INVALID)) {
1007 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "CreateSnapshot")) {
1009 dbus_bool_t cleanup;
1012 if (!dbus_message_get_args(
1015 DBUS_TYPE_STRING, &name,
1016 DBUS_TYPE_BOOLEAN, &cleanup,
1018 return bus_send_error_reply(connection, message, &error, -EINVAL);
1020 if (name && name[0] == 0)
1023 if ((r = snapshot_create(m, name, cleanup, &error, &s)) < 0)
1024 return bus_send_error_reply(connection, message, &error, r);
1026 if (!(reply = dbus_message_new_method_return(message)))
1029 if (!(path = unit_dbus_path(UNIT(s))))
1032 if (!dbus_message_append_args(
1034 DBUS_TYPE_OBJECT_PATH, &path,
1038 } else if (dbus_message_is_method_call(message, "org.freedesktop.DBus.Introspectable", "Introspect")) {
1039 char *introspection = NULL;
1047 if (!(reply = dbus_message_new_method_return(message)))
1050 /* We roll our own introspection code here, instead of
1051 * relying on bus_default_message_handler() because we
1052 * need to generate our introspection string
1055 if (!(f = open_memstream(&introspection, &size)))
1058 fputs(INTROSPECTION_BEGIN, f);
1060 HASHMAP_FOREACH_KEY(u, k, m->units, i) {
1066 if (!(p = bus_path_escape(k))) {
1068 free(introspection);
1072 fprintf(f, "<node name=\"unit/%s\"/>", p);
1076 HASHMAP_FOREACH(j, m->jobs, i)
1077 fprintf(f, "<node name=\"job/%lu\"/>", (unsigned long) j->id);
1079 fputs(INTROSPECTION_END, f);
1083 free(introspection);
1092 if (!dbus_message_append_args(reply, DBUS_TYPE_STRING, &introspection, DBUS_TYPE_INVALID)) {
1093 free(introspection);
1097 free(introspection);
1099 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "Reload")) {
1101 assert(!m->queued_message);
1103 /* Instead of sending the reply back right away, we
1104 * just remember that we need to and then send it
1105 * after the reload is finished. That way the caller
1106 * knows when the reload finished. */
1108 if (!(m->queued_message = dbus_message_new_method_return(message)))
1111 m->queued_message_connection = connection;
1112 m->exit_code = MANAGER_RELOAD;
1114 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "Reexecute")) {
1116 /* We don't send a reply back here, the client should
1117 * just wait for us disconnecting. */
1119 m->exit_code = MANAGER_REEXECUTE;
1121 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "Exit")) {
1123 if (m->running_as == MANAGER_SYSTEM) {
1124 dbus_set_error(&error, BUS_ERROR_NOT_SUPPORTED, "Exit is only supported for user service managers.");
1125 return bus_send_error_reply(connection, message, &error, -ENOTSUP);
1128 if (!(reply = dbus_message_new_method_return(message)))
1131 m->exit_code = MANAGER_EXIT;
1133 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "Reboot")) {
1135 if (m->running_as != MANAGER_SYSTEM) {
1136 dbus_set_error(&error, BUS_ERROR_NOT_SUPPORTED, "Reboot is only supported for system managers.");
1137 return bus_send_error_reply(connection, message, &error, -ENOTSUP);
1140 if (!(reply = dbus_message_new_method_return(message)))
1143 m->exit_code = MANAGER_REBOOT;
1145 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "PowerOff")) {
1147 if (m->running_as != MANAGER_SYSTEM) {
1148 dbus_set_error(&error, BUS_ERROR_NOT_SUPPORTED, "Powering off is only supported for system managers.");
1149 return bus_send_error_reply(connection, message, &error, -ENOTSUP);
1152 if (!(reply = dbus_message_new_method_return(message)))
1155 m->exit_code = MANAGER_POWEROFF;
1157 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "Halt")) {
1159 if (m->running_as != MANAGER_SYSTEM) {
1160 dbus_set_error(&error, BUS_ERROR_NOT_SUPPORTED, "Halting is only supported for system managers.");
1161 return bus_send_error_reply(connection, message, &error, -ENOTSUP);
1164 if (!(reply = dbus_message_new_method_return(message)))
1167 m->exit_code = MANAGER_HALT;
1169 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "KExec")) {
1171 if (m->running_as != MANAGER_SYSTEM) {
1172 dbus_set_error(&error, BUS_ERROR_NOT_SUPPORTED, "kexec is only supported for system managers.");
1173 return bus_send_error_reply(connection, message, &error, -ENOTSUP);
1176 if (!(reply = dbus_message_new_method_return(message)))
1179 m->exit_code = MANAGER_KEXEC;
1181 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "SwitchRoot")) {
1182 const char *switch_root, *switch_root_init;
1186 if (!dbus_message_get_args(
1189 DBUS_TYPE_STRING, &switch_root,
1190 DBUS_TYPE_STRING, &switch_root_init,
1192 return bus_send_error_reply(connection, message, &error, -EINVAL);
1194 if (path_equal(switch_root, "/") || !path_is_absolute(switch_root))
1195 return bus_send_error_reply(connection, message, NULL, -EINVAL);
1197 if (!isempty(switch_root_init) && !path_is_absolute(switch_root_init))
1198 return bus_send_error_reply(connection, message, NULL, -EINVAL);
1200 if (m->running_as != MANAGER_SYSTEM) {
1201 dbus_set_error(&error, BUS_ERROR_NOT_SUPPORTED, "Switching root is only supported for system managers.");
1202 return bus_send_error_reply(connection, message, &error, -ENOTSUP);
1206 if (isempty(switch_root_init))
1207 k = access(switch_root, F_OK);
1211 p = join(switch_root, "/", switch_root_init, NULL);
1215 k = access(p, X_OK);
1219 return bus_send_error_reply(connection, message, NULL, -errno);
1221 u = strdup(switch_root);
1225 if (!isempty(switch_root_init)) {
1226 v = strdup(switch_root_init);
1234 free(m->switch_root);
1235 free(m->switch_root_init);
1237 m->switch_root_init = v;
1239 reply = dbus_message_new_method_return(message);
1243 m->exit_code = MANAGER_SWITCH_ROOT;
1245 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "SetEnvironment")) {
1246 char **l = NULL, **e = NULL;
1248 if ((r = bus_parse_strv(message, &l)) < 0) {
1252 return bus_send_error_reply(connection, message, NULL, r);
1255 e = strv_env_merge(2, m->environment, l);
1261 if (!(reply = dbus_message_new_method_return(message))) {
1266 strv_free(m->environment);
1269 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "UnsetEnvironment")) {
1270 char **l = NULL, **e = NULL;
1272 if ((r = bus_parse_strv(message, &l)) < 0) {
1276 return bus_send_error_reply(connection, message, NULL, r);
1279 e = strv_env_delete(m->environment, 1, l);
1285 if (!(reply = dbus_message_new_method_return(message))) {
1290 strv_free(m->environment);
1293 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "UnsetAndSetEnvironment")) {
1294 char **l_set = NULL, **l_unset = NULL, **e = NULL, **f = NULL;
1295 DBusMessageIter iter;
1297 if (!dbus_message_iter_init(message, &iter))
1300 r = bus_parse_strv_iter(&iter, &l_unset);
1305 return bus_send_error_reply(connection, message, NULL, r);
1308 if (!dbus_message_iter_next(&iter)) {
1310 return bus_send_error_reply(connection, message, NULL, -EINVAL);
1313 r = bus_parse_strv_iter(&iter, &l_set);
1319 return bus_send_error_reply(connection, message, NULL, r);
1322 e = strv_env_delete(m->environment, 1, l_unset);
1330 f = strv_env_merge(2, e, l_set);
1337 if (!(reply = dbus_message_new_method_return(message))) {
1342 strv_free(m->environment);
1344 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ListUnitFiles")) {
1345 DBusMessageIter iter, sub, sub2;
1350 reply = dbus_message_new_method_return(message);
1354 h = hashmap_new(string_hash_func, string_compare_func);
1358 r = unit_file_get_list(m->running_as == MANAGER_SYSTEM ? UNIT_FILE_SYSTEM : UNIT_FILE_USER, NULL, h);
1360 unit_file_list_free(h);
1361 dbus_message_unref(reply);
1362 return bus_send_error_reply(connection, message, NULL, r);
1365 dbus_message_iter_init_append(reply, &iter);
1367 if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "(ss)", &sub)) {
1368 unit_file_list_free(h);
1372 HASHMAP_FOREACH(item, h, i) {
1375 state = unit_file_state_to_string(item->state);
1378 if (!dbus_message_iter_open_container(&sub, DBUS_TYPE_STRUCT, NULL, &sub2) ||
1379 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &item->path) ||
1380 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &state) ||
1381 !dbus_message_iter_close_container(&sub, &sub2)) {
1382 unit_file_list_free(h);
1387 unit_file_list_free(h);
1389 if (!dbus_message_iter_close_container(&iter, &sub))
1392 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "GetUnitFileState")) {
1394 UnitFileState state;
1397 if (!dbus_message_get_args(
1400 DBUS_TYPE_STRING, &name,
1402 return bus_send_error_reply(connection, message, &error, -EINVAL);
1404 state = unit_file_get_state(m->running_as == MANAGER_SYSTEM ? UNIT_FILE_SYSTEM : UNIT_FILE_USER, NULL, name);
1406 return bus_send_error_reply(connection, message, NULL, state);
1408 s = unit_file_state_to_string(state);
1411 reply = dbus_message_new_method_return(message);
1415 if (!dbus_message_append_args(
1417 DBUS_TYPE_STRING, &s,
1420 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "EnableUnitFiles") ||
1421 dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ReenableUnitFiles") ||
1422 dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "LinkUnitFiles") ||
1423 dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "PresetUnitFiles") ||
1424 dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "MaskUnitFiles")) {
1427 DBusMessageIter iter;
1428 UnitFileScope scope = m->running_as == MANAGER_SYSTEM ? UNIT_FILE_SYSTEM : UNIT_FILE_USER;
1429 UnitFileChange *changes = NULL;
1430 unsigned n_changes = 0;
1431 dbus_bool_t runtime, force;
1432 int carries_install_info = -1;
1434 if (!dbus_message_iter_init(message, &iter))
1437 r = bus_parse_strv_iter(&iter, &l);
1442 return bus_send_error_reply(connection, message, NULL, r);
1445 if (!dbus_message_iter_next(&iter) ||
1446 bus_iter_get_basic_and_next(&iter, DBUS_TYPE_BOOLEAN, &runtime, true) < 0 ||
1447 bus_iter_get_basic_and_next(&iter, DBUS_TYPE_BOOLEAN, &force, false) < 0) {
1449 return bus_send_error_reply(connection, message, NULL, -EIO);
1452 if (streq(member, "EnableUnitFiles")) {
1453 r = unit_file_enable(scope, runtime, NULL, l, force, &changes, &n_changes);
1454 carries_install_info = r;
1455 } else if (streq(member, "ReenableUnitFiles")) {
1456 r = unit_file_reenable(scope, runtime, NULL, l, force, &changes, &n_changes);
1457 carries_install_info = r;
1458 } else if (streq(member, "LinkUnitFiles"))
1459 r = unit_file_link(scope, runtime, NULL, l, force, &changes, &n_changes);
1460 else if (streq(member, "PresetUnitFiles")) {
1461 r = unit_file_preset(scope, runtime, NULL, l, force, &changes, &n_changes);
1462 carries_install_info = r;
1463 } else if (streq(member, "MaskUnitFiles"))
1464 r = unit_file_mask(scope, runtime, NULL, l, force, &changes, &n_changes);
1466 assert_not_reached("Uh? Wrong method");
1469 bus_manager_send_unit_files_changed(m);
1472 unit_file_changes_free(changes, n_changes);
1473 return bus_send_error_reply(connection, message, NULL, r);
1476 reply = message_from_file_changes(message, changes, n_changes, carries_install_info);
1477 unit_file_changes_free(changes, n_changes);
1482 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "DisableUnitFiles") ||
1483 dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "UnmaskUnitFiles")) {
1486 DBusMessageIter iter;
1487 UnitFileScope scope = m->running_as == MANAGER_SYSTEM ? UNIT_FILE_SYSTEM : UNIT_FILE_USER;
1488 UnitFileChange *changes = NULL;
1489 unsigned n_changes = 0;
1490 dbus_bool_t runtime;
1492 if (!dbus_message_iter_init(message, &iter))
1495 r = bus_parse_strv_iter(&iter, &l);
1500 return bus_send_error_reply(connection, message, NULL, r);
1503 if (!dbus_message_iter_next(&iter) ||
1504 bus_iter_get_basic_and_next(&iter, DBUS_TYPE_BOOLEAN, &runtime, false) < 0) {
1506 return bus_send_error_reply(connection, message, NULL, -EIO);
1509 if (streq(member, "DisableUnitFiles"))
1510 r = unit_file_disable(scope, runtime, NULL, l, &changes, &n_changes);
1511 else if (streq(member, "UnmaskUnitFiles"))
1512 r = unit_file_unmask(scope, runtime, NULL, l, &changes, &n_changes);
1514 assert_not_reached("Uh? Wrong method");
1517 bus_manager_send_unit_files_changed(m);
1520 unit_file_changes_free(changes, n_changes);
1521 return bus_send_error_reply(connection, message, NULL, r);
1524 reply = message_from_file_changes(message, changes, n_changes, -1);
1525 unit_file_changes_free(changes, n_changes);
1531 const BusBoundProperties bps[] = {
1532 { "org.freedesktop.systemd1.Manager", bus_systemd_properties, systemd_property_string },
1533 { "org.freedesktop.systemd1.Manager", bus_manager_properties, m },
1536 return bus_default_message_handler(connection, message, NULL, INTERFACES_LIST, bps);
1539 if (job_type != _JOB_TYPE_INVALID) {
1540 const char *name, *smode, *old_name = NULL;
1547 if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "StartUnitReplace"))
1548 b = dbus_message_get_args(
1551 DBUS_TYPE_STRING, &old_name,
1552 DBUS_TYPE_STRING, &name,
1553 DBUS_TYPE_STRING, &smode,
1556 b = dbus_message_get_args(
1559 DBUS_TYPE_STRING, &name,
1560 DBUS_TYPE_STRING, &smode,
1564 return bus_send_error_reply(connection, message, &error, -EINVAL);
1567 if (!(u = manager_get_unit(m, old_name)) ||
1569 u->job->type != JOB_START) {
1570 dbus_set_error(&error, BUS_ERROR_NO_SUCH_JOB, "No job queued for unit %s", old_name);
1571 return bus_send_error_reply(connection, message, &error, -ENOENT);
1575 if ((mode = job_mode_from_string(smode)) == _JOB_MODE_INVALID) {
1576 dbus_set_error(&error, BUS_ERROR_INVALID_JOB_MODE, "Job mode %s is invalid.", smode);
1577 return bus_send_error_reply(connection, message, &error, -EINVAL);
1580 if ((r = manager_load_unit(m, name, NULL, &error, &u)) < 0)
1581 return bus_send_error_reply(connection, message, &error, r);
1583 if (reload_if_possible && unit_can_reload(u)) {
1584 if (job_type == JOB_RESTART)
1585 job_type = JOB_RELOAD_OR_START;
1586 else if (job_type == JOB_TRY_RESTART)
1587 job_type = JOB_RELOAD;
1590 if ((job_type == JOB_START && u->refuse_manual_start) ||
1591 (job_type == JOB_STOP && u->refuse_manual_stop) ||
1592 ((job_type == JOB_RESTART || job_type == JOB_TRY_RESTART) &&
1593 (u->refuse_manual_start || u->refuse_manual_stop))) {
1594 dbus_set_error(&error, BUS_ERROR_ONLY_BY_DEPENDENCY, "Operation refused, may be requested by dependency only.");
1595 return bus_send_error_reply(connection, message, &error, -EPERM);
1598 if ((r = manager_add_job(m, job_type, u, mode, true, &error, &j)) < 0)
1599 return bus_send_error_reply(connection, message, &error, r);
1601 cl = job_bus_client_new(connection, message_get_sender_with_fallback(message));
1605 LIST_PREPEND(JobBusClient, client, j->bus_client_list, cl);
1607 if (!(reply = dbus_message_new_method_return(message)))
1610 if (!(path = job_dbus_path(j)))
1613 if (!dbus_message_append_args(
1615 DBUS_TYPE_OBJECT_PATH, &path,
1621 if (!dbus_connection_send(connection, reply, NULL))
1624 dbus_message_unref(reply);
1629 return DBUS_HANDLER_RESULT_HANDLED;
1635 dbus_message_unref(reply);
1637 dbus_error_free(&error);
1639 return DBUS_HANDLER_RESULT_NEED_MEMORY;
1642 const DBusObjectPathVTable bus_manager_vtable = {
1643 .message_function = bus_manager_message_handler