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"
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 const char systemd_property_string[] =
501 static const BusProperty bus_systemd_properties[] = {
502 { "Version", bus_property_append_string, "s", 0 },
503 { "Distribution", bus_property_append_string, "s", sizeof(PACKAGE_STRING) },
504 { "Features", bus_property_append_string, "s", sizeof(PACKAGE_STRING) + sizeof(DISTRIBUTION) },
508 static const BusProperty bus_manager_properties[] = {
509 { "RunningAs", bus_manager_append_running_as, "s", offsetof(Manager, running_as) },
510 { "Tainted", bus_manager_append_tainted, "s", 0 },
511 { "InitRDTimestamp", bus_property_append_uint64, "t", offsetof(Manager, initrd_timestamp.realtime) },
512 { "InitRDTimestampMonotonic", bus_property_append_uint64, "t", offsetof(Manager, initrd_timestamp.monotonic) },
513 { "StartupTimestamp", bus_property_append_uint64, "t", offsetof(Manager, startup_timestamp.realtime) },
514 { "StartupTimestampMonotonic", bus_property_append_uint64, "t", offsetof(Manager, startup_timestamp.monotonic) },
515 { "FinishTimestamp", bus_property_append_uint64, "t", offsetof(Manager, finish_timestamp.realtime) },
516 { "FinishTimestampMonotonic", bus_property_append_uint64, "t", offsetof(Manager, finish_timestamp.monotonic) },
517 { "LogLevel", bus_manager_append_log_level, "s", 0, 0, bus_manager_set_log_level },
518 { "LogTarget", bus_manager_append_log_target, "s", 0, 0, bus_manager_set_log_target },
519 { "NNames", bus_manager_append_n_names, "u", 0 },
520 { "NJobs", bus_manager_append_n_jobs, "u", 0 },
521 { "NInstalledJobs",bus_property_append_uint32, "u", offsetof(Manager, n_installed_jobs) },
522 { "NFailedJobs", bus_property_append_uint32, "u", offsetof(Manager, n_failed_jobs) },
523 { "Progress", bus_manager_append_progress, "d", 0 },
524 { "Environment", bus_property_append_strv, "as", offsetof(Manager, environment), true },
525 { "ConfirmSpawn", bus_property_append_bool, "b", offsetof(Manager, confirm_spawn) },
526 { "ShowStatus", bus_property_append_bool, "b", offsetof(Manager, show_status) },
527 { "UnitPath", bus_property_append_strv, "as", offsetof(Manager, lookup_paths.unit_path), true },
528 { "NotifySocket", bus_property_append_string, "s", offsetof(Manager, notify_socket), true },
529 { "ControlGroupHierarchy", bus_property_append_string, "s", offsetof(Manager, cgroup_hierarchy), true },
530 { "MountAuto", bus_property_append_bool, "b", offsetof(Manager, mount_auto) },
531 { "SwapAuto", bus_property_append_bool, "b", offsetof(Manager, swap_auto) },
532 { "DefaultControllers", bus_property_append_strv, "as", offsetof(Manager, default_controllers), true },
533 { "DefaultStandardOutput", bus_manager_append_exec_output, "s", offsetof(Manager, default_std_output) },
534 { "DefaultStandardError", bus_manager_append_exec_output, "s", offsetof(Manager, default_std_error) },
535 { "RuntimeWatchdogUSec", bus_property_append_usec, "t", offsetof(Manager, runtime_watchdog), },
536 { "ShutdownWatchdogUSec", bus_property_append_usec, "t", offsetof(Manager, shutdown_watchdog), },
537 #ifdef HAVE_SYSV_COMPAT
538 { "SysVConsole", bus_property_append_bool, "b", offsetof(Manager, sysv_console) },
539 { "SysVInitPath", bus_property_append_strv, "as", offsetof(Manager, lookup_paths.sysvinit_path), true },
540 { "SysVRcndPath", bus_property_append_strv, "as", offsetof(Manager, lookup_paths.sysvrcnd_path), true },
545 static DBusHandlerResult bus_manager_message_handler(DBusConnection *connection, DBusMessage *message, void *data) {
550 DBusMessage *reply = NULL;
552 JobType job_type = _JOB_TYPE_INVALID;
553 bool reload_if_possible = false;
560 dbus_error_init(&error);
562 member = dbus_message_get_member(message);
564 if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "GetUnit")) {
568 if (!dbus_message_get_args(
571 DBUS_TYPE_STRING, &name,
573 return bus_send_error_reply(connection, message, &error, -EINVAL);
575 if (!(u = manager_get_unit(m, name))) {
576 dbus_set_error(&error, BUS_ERROR_NO_SUCH_UNIT, "Unit %s is not loaded.", name);
577 return bus_send_error_reply(connection, message, &error, -ENOENT);
580 if (!(reply = dbus_message_new_method_return(message)))
583 if (!(path = unit_dbus_path(u)))
586 if (!dbus_message_append_args(
588 DBUS_TYPE_OBJECT_PATH, &path,
591 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "GetUnitByPID")) {
595 if (!dbus_message_get_args(
598 DBUS_TYPE_UINT32, &pid,
600 return bus_send_error_reply(connection, message, &error, -EINVAL);
602 if (!(u = cgroup_unit_by_pid(m, (pid_t) pid))) {
603 dbus_set_error(&error, BUS_ERROR_NO_SUCH_UNIT, "No unit for PID %lu is loaded.", (unsigned long) pid);
604 return bus_send_error_reply(connection, message, &error, -ENOENT);
607 if (!(reply = dbus_message_new_method_return(message)))
610 if (!(path = unit_dbus_path(u)))
613 if (!dbus_message_append_args(
615 DBUS_TYPE_OBJECT_PATH, &path,
618 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "LoadUnit")) {
622 if (!dbus_message_get_args(
625 DBUS_TYPE_STRING, &name,
627 return bus_send_error_reply(connection, message, &error, -EINVAL);
629 if ((r = manager_load_unit(m, name, NULL, &error, &u)) < 0)
630 return bus_send_error_reply(connection, message, &error, r);
632 if (!(reply = dbus_message_new_method_return(message)))
635 if (!(path = unit_dbus_path(u)))
638 if (!dbus_message_append_args(
640 DBUS_TYPE_OBJECT_PATH, &path,
644 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "StartUnit"))
645 job_type = JOB_START;
646 else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "StartUnitReplace"))
647 job_type = JOB_START;
648 else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "StopUnit"))
650 else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ReloadUnit"))
651 job_type = JOB_RELOAD;
652 else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "RestartUnit"))
653 job_type = JOB_RESTART;
654 else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "TryRestartUnit"))
655 job_type = JOB_TRY_RESTART;
656 else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ReloadOrRestartUnit")) {
657 reload_if_possible = true;
658 job_type = JOB_RESTART;
659 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ReloadOrTryRestartUnit")) {
660 reload_if_possible = true;
661 job_type = JOB_TRY_RESTART;
662 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "KillUnit")) {
663 const char *name, *swho, *smode;
669 if (!dbus_message_get_args(
672 DBUS_TYPE_STRING, &name,
673 DBUS_TYPE_STRING, &swho,
674 DBUS_TYPE_STRING, &smode,
675 DBUS_TYPE_INT32, &signo,
677 return bus_send_error_reply(connection, message, &error, -EINVAL);
682 who = kill_who_from_string(swho);
684 return bus_send_error_reply(connection, message, &error, -EINVAL);
688 mode = KILL_CONTROL_GROUP;
690 mode = kill_mode_from_string(smode);
692 return bus_send_error_reply(connection, message, &error, -EINVAL);
695 if (signo <= 0 || signo >= _NSIG)
696 return bus_send_error_reply(connection, message, &error, -EINVAL);
698 if (!(u = manager_get_unit(m, name))) {
699 dbus_set_error(&error, BUS_ERROR_NO_SUCH_UNIT, "Unit %s is not loaded.", name);
700 return bus_send_error_reply(connection, message, &error, -ENOENT);
703 if ((r = unit_kill(u, who, mode, signo, &error)) < 0)
704 return bus_send_error_reply(connection, message, &error, r);
706 if (!(reply = dbus_message_new_method_return(message)))
709 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "GetJob")) {
713 if (!dbus_message_get_args(
716 DBUS_TYPE_UINT32, &id,
718 return bus_send_error_reply(connection, message, &error, -EINVAL);
720 if (!(j = manager_get_job(m, id))) {
721 dbus_set_error(&error, BUS_ERROR_NO_SUCH_JOB, "Job %u does not exist.", (unsigned) id);
722 return bus_send_error_reply(connection, message, &error, -ENOENT);
725 if (!(reply = dbus_message_new_method_return(message)))
728 if (!(path = job_dbus_path(j)))
731 if (!dbus_message_append_args(
733 DBUS_TYPE_OBJECT_PATH, &path,
737 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ClearJobs")) {
739 manager_clear_jobs(m);
741 if (!(reply = dbus_message_new_method_return(message)))
744 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ResetFailed")) {
746 manager_reset_failed(m);
748 if (!(reply = dbus_message_new_method_return(message)))
751 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ResetFailedUnit")) {
755 if (!dbus_message_get_args(
758 DBUS_TYPE_STRING, &name,
760 return bus_send_error_reply(connection, message, &error, -EINVAL);
762 if (!(u = manager_get_unit(m, name))) {
763 dbus_set_error(&error, BUS_ERROR_NO_SUCH_UNIT, "Unit %s is not loaded.", name);
764 return bus_send_error_reply(connection, message, &error, -ENOENT);
767 unit_reset_failed(u);
769 if (!(reply = dbus_message_new_method_return(message)))
772 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ListUnits")) {
773 DBusMessageIter iter, sub;
778 if (!(reply = dbus_message_new_method_return(message)))
781 dbus_message_iter_init_append(reply, &iter);
783 if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "(ssssssouso)", &sub))
786 HASHMAP_FOREACH_KEY(u, k, m->units, i) {
787 char *u_path, *j_path;
788 const char *description, *load_state, *active_state, *sub_state, *sjob_type, *following;
789 DBusMessageIter sub2;
796 if (!dbus_message_iter_open_container(&sub, DBUS_TYPE_STRUCT, NULL, &sub2))
799 description = unit_description(u);
800 load_state = unit_load_state_to_string(u->load_state);
801 active_state = unit_active_state_to_string(unit_active_state(u));
802 sub_state = unit_sub_state_to_string(u);
804 f = unit_following(u);
805 following = f ? f->id : "";
807 if (!(u_path = unit_dbus_path(u)))
811 job_id = (uint32_t) u->job->id;
813 if (!(j_path = job_dbus_path(u->job))) {
818 sjob_type = job_type_to_string(u->job->type);
825 if (!dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &u->id) ||
826 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &description) ||
827 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &load_state) ||
828 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &active_state) ||
829 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &sub_state) ||
830 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &following) ||
831 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_OBJECT_PATH, &u_path) ||
832 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_UINT32, &job_id) ||
833 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &sjob_type) ||
834 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_OBJECT_PATH, &j_path)) {
845 if (!dbus_message_iter_close_container(&sub, &sub2))
849 if (!dbus_message_iter_close_container(&iter, &sub))
852 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ListJobs")) {
853 DBusMessageIter iter, sub;
857 if (!(reply = dbus_message_new_method_return(message)))
860 dbus_message_iter_init_append(reply, &iter);
862 if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "(usssoo)", &sub))
865 HASHMAP_FOREACH(j, m->jobs, i) {
866 char *u_path, *j_path;
867 const char *state, *type;
869 DBusMessageIter sub2;
871 if (!dbus_message_iter_open_container(&sub, DBUS_TYPE_STRUCT, NULL, &sub2))
874 id = (uint32_t) j->id;
875 state = job_state_to_string(j->state);
876 type = job_type_to_string(j->type);
878 if (!(j_path = job_dbus_path(j)))
881 if (!(u_path = unit_dbus_path(j->unit))) {
886 if (!dbus_message_iter_append_basic(&sub2, DBUS_TYPE_UINT32, &id) ||
887 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &j->unit->id) ||
888 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &type) ||
889 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &state) ||
890 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_OBJECT_PATH, &j_path) ||
891 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_OBJECT_PATH, &u_path)) {
900 if (!dbus_message_iter_close_container(&sub, &sub2))
904 if (!dbus_message_iter_close_container(&iter, &sub))
907 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "Subscribe")) {
911 if (!(s = BUS_CONNECTION_SUBSCRIBED(m, connection))) {
912 if (!(s = set_new(string_hash_func, string_compare_func)))
915 if (!(dbus_connection_set_data(connection, m->subscribed_data_slot, s, NULL))) {
921 if (!(client = strdup(message_get_sender_with_fallback(message))))
924 if ((r = set_put(s, client)) < 0) {
926 return bus_send_error_reply(connection, message, NULL, r);
929 if (!(reply = dbus_message_new_method_return(message)))
932 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "Unsubscribe")) {
935 if (!(client = set_remove(BUS_CONNECTION_SUBSCRIBED(m, connection), (char*) message_get_sender_with_fallback(message)))) {
936 dbus_set_error(&error, BUS_ERROR_NOT_SUBSCRIBED, "Client is not subscribed.");
937 return bus_send_error_reply(connection, message, &error, -ENOENT);
942 if (!(reply = dbus_message_new_method_return(message)))
945 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "Dump")) {
950 if (!(reply = dbus_message_new_method_return(message)))
953 if (!(f = open_memstream(&dump, &size)))
956 manager_dump_units(m, f, NULL);
957 manager_dump_jobs(m, f, NULL);
967 if (!dbus_message_append_args(reply, DBUS_TYPE_STRING, &dump, DBUS_TYPE_INVALID)) {
973 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "CreateSnapshot")) {
978 if (!dbus_message_get_args(
981 DBUS_TYPE_STRING, &name,
982 DBUS_TYPE_BOOLEAN, &cleanup,
984 return bus_send_error_reply(connection, message, &error, -EINVAL);
986 if (name && name[0] == 0)
989 if ((r = snapshot_create(m, name, cleanup, &error, &s)) < 0)
990 return bus_send_error_reply(connection, message, &error, r);
992 if (!(reply = dbus_message_new_method_return(message)))
995 if (!(path = unit_dbus_path(UNIT(s))))
998 if (!dbus_message_append_args(
1000 DBUS_TYPE_OBJECT_PATH, &path,
1004 } else if (dbus_message_is_method_call(message, "org.freedesktop.DBus.Introspectable", "Introspect")) {
1005 char *introspection = NULL;
1013 if (!(reply = dbus_message_new_method_return(message)))
1016 /* We roll our own introspection code here, instead of
1017 * relying on bus_default_message_handler() because we
1018 * need to generate our introspection string
1021 if (!(f = open_memstream(&introspection, &size)))
1024 fputs(INTROSPECTION_BEGIN, f);
1026 HASHMAP_FOREACH_KEY(u, k, m->units, i) {
1032 if (!(p = bus_path_escape(k))) {
1034 free(introspection);
1038 fprintf(f, "<node name=\"unit/%s\"/>", p);
1042 HASHMAP_FOREACH(j, m->jobs, i)
1043 fprintf(f, "<node name=\"job/%lu\"/>", (unsigned long) j->id);
1045 fputs(INTROSPECTION_END, f);
1049 free(introspection);
1058 if (!dbus_message_append_args(reply, DBUS_TYPE_STRING, &introspection, DBUS_TYPE_INVALID)) {
1059 free(introspection);
1063 free(introspection);
1065 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "Reload")) {
1067 assert(!m->queued_message);
1069 /* Instead of sending the reply back right away, we
1070 * just remember that we need to and then send it
1071 * after the reload is finished. That way the caller
1072 * knows when the reload finished. */
1074 if (!(m->queued_message = dbus_message_new_method_return(message)))
1077 m->queued_message_connection = connection;
1078 m->exit_code = MANAGER_RELOAD;
1080 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "Reexecute")) {
1082 /* We don't send a reply back here, the client should
1083 * just wait for us disconnecting. */
1085 m->exit_code = MANAGER_REEXECUTE;
1087 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "Exit")) {
1089 if (m->running_as == MANAGER_SYSTEM) {
1090 dbus_set_error(&error, BUS_ERROR_NOT_SUPPORTED, "Exit is only supported for user service managers.");
1091 return bus_send_error_reply(connection, message, &error, -ENOTSUP);
1094 if (!(reply = dbus_message_new_method_return(message)))
1097 m->exit_code = MANAGER_EXIT;
1099 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "Reboot")) {
1101 if (m->running_as != MANAGER_SYSTEM) {
1102 dbus_set_error(&error, BUS_ERROR_NOT_SUPPORTED, "Reboot is only supported for system managers.");
1103 return bus_send_error_reply(connection, message, &error, -ENOTSUP);
1106 if (!(reply = dbus_message_new_method_return(message)))
1109 m->exit_code = MANAGER_REBOOT;
1111 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "PowerOff")) {
1113 if (m->running_as != MANAGER_SYSTEM) {
1114 dbus_set_error(&error, BUS_ERROR_NOT_SUPPORTED, "Powering off is only supported for system 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_POWEROFF;
1123 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "Halt")) {
1125 if (m->running_as != MANAGER_SYSTEM) {
1126 dbus_set_error(&error, BUS_ERROR_NOT_SUPPORTED, "Halting 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_HALT;
1135 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "KExec")) {
1137 if (m->running_as != MANAGER_SYSTEM) {
1138 dbus_set_error(&error, BUS_ERROR_NOT_SUPPORTED, "kexec 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_KEXEC;
1147 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "SetEnvironment")) {
1148 char **l = NULL, **e = NULL;
1150 if ((r = bus_parse_strv(message, &l)) < 0) {
1154 return bus_send_error_reply(connection, message, NULL, r);
1157 e = strv_env_merge(2, m->environment, l);
1163 if (!(reply = dbus_message_new_method_return(message))) {
1168 strv_free(m->environment);
1171 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "UnsetEnvironment")) {
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_delete(m->environment, 1, 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", "UnsetAndSetEnvironment")) {
1196 char **l_set = NULL, **l_unset = NULL, **e = NULL, **f = NULL;
1197 DBusMessageIter iter;
1199 if (!dbus_message_iter_init(message, &iter))
1202 r = bus_parse_strv_iter(&iter, &l_unset);
1207 return bus_send_error_reply(connection, message, NULL, r);
1210 if (!dbus_message_iter_next(&iter)) {
1212 return bus_send_error_reply(connection, message, NULL, -EINVAL);
1215 r = bus_parse_strv_iter(&iter, &l_set);
1221 return bus_send_error_reply(connection, message, NULL, r);
1224 e = strv_env_delete(m->environment, 1, l_unset);
1232 f = strv_env_merge(2, e, l_set);
1239 if (!(reply = dbus_message_new_method_return(message))) {
1244 strv_free(m->environment);
1246 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ListUnitFiles")) {
1247 DBusMessageIter iter, sub, sub2;
1252 reply = dbus_message_new_method_return(message);
1256 h = hashmap_new(string_hash_func, string_compare_func);
1260 r = unit_file_get_list(m->running_as == MANAGER_SYSTEM ? UNIT_FILE_SYSTEM : UNIT_FILE_USER, NULL, h);
1262 unit_file_list_free(h);
1263 dbus_message_unref(reply);
1264 return bus_send_error_reply(connection, message, NULL, r);
1267 dbus_message_iter_init_append(reply, &iter);
1269 if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "(ss)", &sub)) {
1270 unit_file_list_free(h);
1274 HASHMAP_FOREACH(item, h, i) {
1277 state = unit_file_state_to_string(item->state);
1280 if (!dbus_message_iter_open_container(&sub, DBUS_TYPE_STRUCT, NULL, &sub2) ||
1281 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &item->path) ||
1282 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &state) ||
1283 !dbus_message_iter_close_container(&sub, &sub2)) {
1284 unit_file_list_free(h);
1289 unit_file_list_free(h);
1291 if (!dbus_message_iter_close_container(&iter, &sub))
1294 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "GetUnitFileState")) {
1296 UnitFileState state;
1299 if (!dbus_message_get_args(
1302 DBUS_TYPE_STRING, &name,
1304 return bus_send_error_reply(connection, message, &error, -EINVAL);
1306 state = unit_file_get_state(m->running_as == MANAGER_SYSTEM ? UNIT_FILE_SYSTEM : UNIT_FILE_USER, NULL, name);
1308 return bus_send_error_reply(connection, message, NULL, state);
1310 s = unit_file_state_to_string(state);
1313 reply = dbus_message_new_method_return(message);
1317 if (!dbus_message_append_args(
1319 DBUS_TYPE_STRING, &s,
1322 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "EnableUnitFiles") ||
1323 dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ReenableUnitFiles") ||
1324 dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "LinkUnitFiles") ||
1325 dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "PresetUnitFiles") ||
1326 dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "MaskUnitFiles")) {
1329 DBusMessageIter iter;
1330 UnitFileScope scope = m->running_as == MANAGER_SYSTEM ? UNIT_FILE_SYSTEM : UNIT_FILE_USER;
1331 UnitFileChange *changes = NULL;
1332 unsigned n_changes = 0;
1333 dbus_bool_t runtime, force;
1334 int carries_install_info = -1;
1336 if (!dbus_message_iter_init(message, &iter))
1339 r = bus_parse_strv_iter(&iter, &l);
1344 return bus_send_error_reply(connection, message, NULL, r);
1347 if (!dbus_message_iter_next(&iter) ||
1348 bus_iter_get_basic_and_next(&iter, DBUS_TYPE_BOOLEAN, &runtime, true) < 0 ||
1349 bus_iter_get_basic_and_next(&iter, DBUS_TYPE_BOOLEAN, &force, false) < 0) {
1351 return bus_send_error_reply(connection, message, NULL, -EIO);
1354 if (streq(member, "EnableUnitFiles")) {
1355 r = unit_file_enable(scope, runtime, NULL, l, force, &changes, &n_changes);
1356 carries_install_info = r;
1357 } else if (streq(member, "ReenableUnitFiles")) {
1358 r = unit_file_reenable(scope, runtime, NULL, l, force, &changes, &n_changes);
1359 carries_install_info = r;
1360 } else if (streq(member, "LinkUnitFiles"))
1361 r = unit_file_link(scope, runtime, NULL, l, force, &changes, &n_changes);
1362 else if (streq(member, "PresetUnitFiles")) {
1363 r = unit_file_preset(scope, runtime, NULL, l, force, &changes, &n_changes);
1364 carries_install_info = r;
1365 } else if (streq(member, "MaskUnitFiles"))
1366 r = unit_file_mask(scope, runtime, NULL, l, force, &changes, &n_changes);
1368 assert_not_reached("Uh? Wrong method");
1371 bus_manager_send_unit_files_changed(m);
1374 unit_file_changes_free(changes, n_changes);
1375 return bus_send_error_reply(connection, message, NULL, r);
1378 reply = message_from_file_changes(message, changes, n_changes, carries_install_info);
1379 unit_file_changes_free(changes, n_changes);
1384 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "DisableUnitFiles") ||
1385 dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "UnmaskUnitFiles")) {
1388 DBusMessageIter iter;
1389 UnitFileScope scope = m->running_as == MANAGER_SYSTEM ? UNIT_FILE_SYSTEM : UNIT_FILE_USER;
1390 UnitFileChange *changes = NULL;
1391 unsigned n_changes = 0;
1392 dbus_bool_t runtime;
1394 if (!dbus_message_iter_init(message, &iter))
1397 r = bus_parse_strv_iter(&iter, &l);
1402 return bus_send_error_reply(connection, message, NULL, r);
1405 if (!dbus_message_iter_next(&iter) ||
1406 bus_iter_get_basic_and_next(&iter, DBUS_TYPE_BOOLEAN, &runtime, false) < 0) {
1408 return bus_send_error_reply(connection, message, NULL, -EIO);
1411 if (streq(member, "DisableUnitFiles"))
1412 r = unit_file_disable(scope, runtime, NULL, l, &changes, &n_changes);
1413 else if (streq(member, "UnmaskUnitFiles"))
1414 r = unit_file_unmask(scope, runtime, NULL, l, &changes, &n_changes);
1416 assert_not_reached("Uh? Wrong method");
1419 bus_manager_send_unit_files_changed(m);
1422 unit_file_changes_free(changes, n_changes);
1423 return bus_send_error_reply(connection, message, NULL, r);
1426 reply = message_from_file_changes(message, changes, n_changes, -1);
1427 unit_file_changes_free(changes, n_changes);
1433 const BusBoundProperties bps[] = {
1434 { "org.freedesktop.systemd1.Manager", bus_systemd_properties, systemd_property_string },
1435 { "org.freedesktop.systemd1.Manager", bus_manager_properties, m },
1438 return bus_default_message_handler(connection, message, NULL, INTERFACES_LIST, bps);
1441 if (job_type != _JOB_TYPE_INVALID) {
1442 const char *name, *smode, *old_name = NULL;
1448 if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "StartUnitReplace"))
1449 b = dbus_message_get_args(
1452 DBUS_TYPE_STRING, &old_name,
1453 DBUS_TYPE_STRING, &name,
1454 DBUS_TYPE_STRING, &smode,
1457 b = dbus_message_get_args(
1460 DBUS_TYPE_STRING, &name,
1461 DBUS_TYPE_STRING, &smode,
1465 return bus_send_error_reply(connection, message, &error, -EINVAL);
1468 if (!(u = manager_get_unit(m, old_name)) ||
1470 u->job->type != JOB_START) {
1471 dbus_set_error(&error, BUS_ERROR_NO_SUCH_JOB, "No job queued for unit %s", old_name);
1472 return bus_send_error_reply(connection, message, &error, -ENOENT);
1476 if ((mode = job_mode_from_string(smode)) == _JOB_MODE_INVALID) {
1477 dbus_set_error(&error, BUS_ERROR_INVALID_JOB_MODE, "Job mode %s is invalid.", smode);
1478 return bus_send_error_reply(connection, message, &error, -EINVAL);
1481 if ((r = manager_load_unit(m, name, NULL, &error, &u)) < 0)
1482 return bus_send_error_reply(connection, message, &error, r);
1484 if (reload_if_possible && unit_can_reload(u)) {
1485 if (job_type == JOB_RESTART)
1486 job_type = JOB_RELOAD_OR_START;
1487 else if (job_type == JOB_TRY_RESTART)
1488 job_type = JOB_RELOAD;
1491 if ((job_type == JOB_START && u->refuse_manual_start) ||
1492 (job_type == JOB_STOP && u->refuse_manual_stop) ||
1493 ((job_type == JOB_RESTART || job_type == JOB_TRY_RESTART) &&
1494 (u->refuse_manual_start || u->refuse_manual_stop))) {
1495 dbus_set_error(&error, BUS_ERROR_ONLY_BY_DEPENDENCY, "Operation refused, may be requested by dependency only.");
1496 return bus_send_error_reply(connection, message, &error, -EPERM);
1499 if ((r = manager_add_job(m, job_type, u, mode, true, &error, &j)) < 0)
1500 return bus_send_error_reply(connection, message, &error, r);
1502 if (!(j->bus_client = strdup(message_get_sender_with_fallback(message))))
1505 j->bus = connection;
1507 if (!(reply = dbus_message_new_method_return(message)))
1510 if (!(path = job_dbus_path(j)))
1513 if (!dbus_message_append_args(
1515 DBUS_TYPE_OBJECT_PATH, &path,
1521 if (!dbus_connection_send(connection, reply, NULL))
1524 dbus_message_unref(reply);
1529 return DBUS_HANDLER_RESULT_HANDLED;
1535 dbus_message_unref(reply);
1537 dbus_error_free(&error);
1539 return DBUS_HANDLER_RESULT_NEED_MEMORY;
1542 const DBusObjectPathVTable bus_manager_vtable = {
1543 .message_function = bus_manager_message_handler