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"
252 #define BUS_MANAGER_INTERFACE_END \
255 #define BUS_MANAGER_INTERFACE \
256 BUS_MANAGER_INTERFACE_BEGIN \
257 BUS_MANAGER_INTERFACE_METHODS \
258 BUS_MANAGER_INTERFACE_SIGNALS \
259 BUS_MANAGER_INTERFACE_PROPERTIES_GENERAL \
260 BUS_MANAGER_INTERFACE_END
262 #define INTROSPECTION_BEGIN \
263 DBUS_INTROSPECT_1_0_XML_DOCTYPE_DECL_NODE \
265 BUS_MANAGER_INTERFACE \
266 BUS_PROPERTIES_INTERFACE \
268 BUS_INTROSPECTABLE_INTERFACE
270 #define INTROSPECTION_END \
273 #define INTERFACES_LIST \
274 BUS_GENERIC_INTERFACES_LIST \
275 "org.freedesktop.systemd1.Manager\0"
277 const char bus_manager_interface[] _introspect_("Manager") = BUS_MANAGER_INTERFACE;
279 static DEFINE_BUS_PROPERTY_APPEND_ENUM(bus_manager_append_exec_output, exec_output, ExecOutput);
281 static int bus_manager_append_tainted(DBusMessageIter *i, const char *property, void *data) {
284 char buf[LINE_MAX] = "", *e = buf, *p = NULL;
291 e = stpcpy(e, "split-usr:");
293 if (readlink_malloc("/etc/mtab", &p) < 0)
294 e = stpcpy(e, "mtab-not-symlink:");
298 if (access("/proc/cgroups", F_OK) < 0)
299 e = stpcpy(e, "cgroups-missing:");
301 if (hwclock_is_localtime() > 0)
302 e = stpcpy(e, "local-hwclock:");
304 /* remove the last ':' */
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_set_runtime_watchdog_usec(DBusMessageIter *i, const char *property, void *data) {
503 dbus_message_iter_get_basic(i, t);
505 return watchdog_set_timeout(t);
508 static const char systemd_property_string[] =
513 static const BusProperty bus_systemd_properties[] = {
514 { "Version", bus_property_append_string, "s", 0 },
515 { "Distribution", bus_property_append_string, "s", sizeof(PACKAGE_STRING) },
516 { "Features", bus_property_append_string, "s", sizeof(PACKAGE_STRING) + sizeof(DISTRIBUTION) },
520 static const BusProperty bus_manager_properties[] = {
521 { "Tainted", bus_manager_append_tainted, "s", 0 },
522 { "InitRDTimestamp", bus_property_append_uint64, "t", offsetof(Manager, initrd_timestamp.realtime) },
523 { "InitRDTimestampMonotonic", bus_property_append_uint64, "t", offsetof(Manager, initrd_timestamp.monotonic) },
524 { "StartupTimestamp", bus_property_append_uint64, "t", offsetof(Manager, startup_timestamp.realtime) },
525 { "StartupTimestampMonotonic", bus_property_append_uint64, "t", offsetof(Manager, startup_timestamp.monotonic) },
526 { "FinishTimestamp", bus_property_append_uint64, "t", offsetof(Manager, finish_timestamp.realtime) },
527 { "FinishTimestampMonotonic", bus_property_append_uint64, "t", offsetof(Manager, finish_timestamp.monotonic) },
528 { "LogLevel", bus_manager_append_log_level, "s", 0, false, bus_manager_set_log_level },
529 { "LogTarget", bus_manager_append_log_target, "s", 0, false, bus_manager_set_log_target },
530 { "NNames", bus_manager_append_n_names, "u", 0 },
531 { "NJobs", bus_manager_append_n_jobs, "u", 0 },
532 { "NInstalledJobs",bus_property_append_uint32, "u", offsetof(Manager, n_installed_jobs) },
533 { "NFailedJobs", bus_property_append_uint32, "u", offsetof(Manager, n_failed_jobs) },
534 { "Progress", bus_manager_append_progress, "d", 0 },
535 { "Environment", bus_property_append_strv, "as", offsetof(Manager, environment), true },
536 { "ConfirmSpawn", bus_property_append_bool, "b", offsetof(Manager, confirm_spawn) },
537 { "ShowStatus", bus_property_append_bool, "b", offsetof(Manager, show_status) },
538 { "UnitPath", bus_property_append_strv, "as", offsetof(Manager, lookup_paths.unit_path), true },
539 { "ControlGroupHierarchy", bus_property_append_string, "s", offsetof(Manager, cgroup_hierarchy), true },
540 { "DefaultControllers", bus_property_append_strv, "as", offsetof(Manager, default_controllers), true },
541 { "DefaultStandardOutput", bus_manager_append_exec_output, "s", offsetof(Manager, default_std_output) },
542 { "DefaultStandardError", bus_manager_append_exec_output, "s", offsetof(Manager, default_std_error) },
543 { "RuntimeWatchdogUSec", bus_property_append_usec, "t", offsetof(Manager, runtime_watchdog), false, bus_manager_set_runtime_watchdog_usec },
544 { "ShutdownWatchdogUSec", bus_property_append_usec, "t", offsetof(Manager, shutdown_watchdog), false, bus_property_set_usec },
548 static DBusHandlerResult bus_manager_message_handler(DBusConnection *connection, DBusMessage *message, void *data) {
553 DBusMessage *reply = NULL;
555 JobType job_type = _JOB_TYPE_INVALID;
556 bool reload_if_possible = false;
563 dbus_error_init(&error);
565 member = dbus_message_get_member(message);
567 if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "GetUnit")) {
571 if (!dbus_message_get_args(
574 DBUS_TYPE_STRING, &name,
576 return bus_send_error_reply(connection, message, &error, -EINVAL);
578 if (!(u = manager_get_unit(m, name))) {
579 dbus_set_error(&error, BUS_ERROR_NO_SUCH_UNIT, "Unit %s is not loaded.", name);
580 return bus_send_error_reply(connection, message, &error, -ENOENT);
583 if (!(reply = dbus_message_new_method_return(message)))
586 if (!(path = unit_dbus_path(u)))
589 if (!dbus_message_append_args(
591 DBUS_TYPE_OBJECT_PATH, &path,
594 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "GetUnitByPID")) {
598 if (!dbus_message_get_args(
601 DBUS_TYPE_UINT32, &pid,
603 return bus_send_error_reply(connection, message, &error, -EINVAL);
605 if (!(u = cgroup_unit_by_pid(m, (pid_t) pid))) {
606 dbus_set_error(&error, BUS_ERROR_NO_SUCH_UNIT, "No unit for PID %lu is loaded.", (unsigned long) pid);
607 return bus_send_error_reply(connection, message, &error, -ENOENT);
610 if (!(reply = dbus_message_new_method_return(message)))
613 if (!(path = unit_dbus_path(u)))
616 if (!dbus_message_append_args(
618 DBUS_TYPE_OBJECT_PATH, &path,
621 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "LoadUnit")) {
625 if (!dbus_message_get_args(
628 DBUS_TYPE_STRING, &name,
630 return bus_send_error_reply(connection, message, &error, -EINVAL);
632 if ((r = manager_load_unit(m, name, NULL, &error, &u)) < 0)
633 return bus_send_error_reply(connection, message, &error, r);
635 if (!(reply = dbus_message_new_method_return(message)))
638 if (!(path = unit_dbus_path(u)))
641 if (!dbus_message_append_args(
643 DBUS_TYPE_OBJECT_PATH, &path,
647 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "StartUnit"))
648 job_type = JOB_START;
649 else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "StartUnitReplace"))
650 job_type = JOB_START;
651 else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "StopUnit"))
653 else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ReloadUnit"))
654 job_type = JOB_RELOAD;
655 else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "RestartUnit"))
656 job_type = JOB_RESTART;
657 else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "TryRestartUnit"))
658 job_type = JOB_TRY_RESTART;
659 else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ReloadOrRestartUnit")) {
660 reload_if_possible = true;
661 job_type = JOB_RESTART;
662 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ReloadOrTryRestartUnit")) {
663 reload_if_possible = true;
664 job_type = JOB_TRY_RESTART;
665 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "KillUnit")) {
666 const char *name, *swho, *smode;
672 if (!dbus_message_get_args(
675 DBUS_TYPE_STRING, &name,
676 DBUS_TYPE_STRING, &swho,
677 DBUS_TYPE_STRING, &smode,
678 DBUS_TYPE_INT32, &signo,
680 return bus_send_error_reply(connection, message, &error, -EINVAL);
685 who = kill_who_from_string(swho);
687 return bus_send_error_reply(connection, message, &error, -EINVAL);
691 mode = KILL_CONTROL_GROUP;
693 mode = kill_mode_from_string(smode);
695 return bus_send_error_reply(connection, message, &error, -EINVAL);
698 if (signo <= 0 || signo >= _NSIG)
699 return bus_send_error_reply(connection, message, &error, -EINVAL);
701 if (!(u = manager_get_unit(m, name))) {
702 dbus_set_error(&error, BUS_ERROR_NO_SUCH_UNIT, "Unit %s is not loaded.", name);
703 return bus_send_error_reply(connection, message, &error, -ENOENT);
706 if ((r = unit_kill(u, who, mode, signo, &error)) < 0)
707 return bus_send_error_reply(connection, message, &error, r);
709 if (!(reply = dbus_message_new_method_return(message)))
712 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "GetJob")) {
716 if (!dbus_message_get_args(
719 DBUS_TYPE_UINT32, &id,
721 return bus_send_error_reply(connection, message, &error, -EINVAL);
723 if (!(j = manager_get_job(m, id))) {
724 dbus_set_error(&error, BUS_ERROR_NO_SUCH_JOB, "Job %u does not exist.", (unsigned) id);
725 return bus_send_error_reply(connection, message, &error, -ENOENT);
728 if (!(reply = dbus_message_new_method_return(message)))
731 if (!(path = job_dbus_path(j)))
734 if (!dbus_message_append_args(
736 DBUS_TYPE_OBJECT_PATH, &path,
740 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ClearJobs")) {
742 manager_clear_jobs(m);
744 if (!(reply = dbus_message_new_method_return(message)))
747 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ResetFailed")) {
749 manager_reset_failed(m);
751 if (!(reply = dbus_message_new_method_return(message)))
754 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ResetFailedUnit")) {
758 if (!dbus_message_get_args(
761 DBUS_TYPE_STRING, &name,
763 return bus_send_error_reply(connection, message, &error, -EINVAL);
765 if (!(u = manager_get_unit(m, name))) {
766 dbus_set_error(&error, BUS_ERROR_NO_SUCH_UNIT, "Unit %s is not loaded.", name);
767 return bus_send_error_reply(connection, message, &error, -ENOENT);
770 unit_reset_failed(u);
772 if (!(reply = dbus_message_new_method_return(message)))
775 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ListUnits")) {
776 DBusMessageIter iter, sub;
781 if (!(reply = dbus_message_new_method_return(message)))
784 dbus_message_iter_init_append(reply, &iter);
786 if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "(ssssssouso)", &sub))
789 HASHMAP_FOREACH_KEY(u, k, m->units, i) {
790 char *u_path, *j_path;
791 const char *description, *load_state, *active_state, *sub_state, *sjob_type, *following;
792 DBusMessageIter sub2;
799 if (!dbus_message_iter_open_container(&sub, DBUS_TYPE_STRUCT, NULL, &sub2))
802 description = unit_description(u);
803 load_state = unit_load_state_to_string(u->load_state);
804 active_state = unit_active_state_to_string(unit_active_state(u));
805 sub_state = unit_sub_state_to_string(u);
807 f = unit_following(u);
808 following = f ? f->id : "";
810 if (!(u_path = unit_dbus_path(u)))
814 job_id = (uint32_t) u->job->id;
816 if (!(j_path = job_dbus_path(u->job))) {
821 sjob_type = job_type_to_string(u->job->type);
828 if (!dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &u->id) ||
829 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &description) ||
830 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &load_state) ||
831 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &active_state) ||
832 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &sub_state) ||
833 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &following) ||
834 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_OBJECT_PATH, &u_path) ||
835 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_UINT32, &job_id) ||
836 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &sjob_type) ||
837 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_OBJECT_PATH, &j_path)) {
848 if (!dbus_message_iter_close_container(&sub, &sub2))
852 if (!dbus_message_iter_close_container(&iter, &sub))
855 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ListJobs")) {
856 DBusMessageIter iter, sub;
860 if (!(reply = dbus_message_new_method_return(message)))
863 dbus_message_iter_init_append(reply, &iter);
865 if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "(usssoo)", &sub))
868 HASHMAP_FOREACH(j, m->jobs, i) {
869 char *u_path, *j_path;
870 const char *state, *type;
872 DBusMessageIter sub2;
874 if (!dbus_message_iter_open_container(&sub, DBUS_TYPE_STRUCT, NULL, &sub2))
877 id = (uint32_t) j->id;
878 state = job_state_to_string(j->state);
879 type = job_type_to_string(j->type);
881 if (!(j_path = job_dbus_path(j)))
884 if (!(u_path = unit_dbus_path(j->unit))) {
889 if (!dbus_message_iter_append_basic(&sub2, DBUS_TYPE_UINT32, &id) ||
890 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &j->unit->id) ||
891 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &type) ||
892 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &state) ||
893 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_OBJECT_PATH, &j_path) ||
894 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_OBJECT_PATH, &u_path)) {
903 if (!dbus_message_iter_close_container(&sub, &sub2))
907 if (!dbus_message_iter_close_container(&iter, &sub))
910 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "Subscribe")) {
914 if (!(s = BUS_CONNECTION_SUBSCRIBED(m, connection))) {
915 if (!(s = set_new(string_hash_func, string_compare_func)))
918 if (!(dbus_connection_set_data(connection, m->subscribed_data_slot, s, NULL))) {
924 if (!(client = strdup(message_get_sender_with_fallback(message))))
927 if ((r = set_put(s, client)) < 0) {
929 return bus_send_error_reply(connection, message, NULL, r);
932 if (!(reply = dbus_message_new_method_return(message)))
935 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "Unsubscribe")) {
938 if (!(client = set_remove(BUS_CONNECTION_SUBSCRIBED(m, connection), (char*) message_get_sender_with_fallback(message)))) {
939 dbus_set_error(&error, BUS_ERROR_NOT_SUBSCRIBED, "Client is not subscribed.");
940 return bus_send_error_reply(connection, message, &error, -ENOENT);
945 if (!(reply = dbus_message_new_method_return(message)))
948 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "Dump")) {
953 if (!(reply = dbus_message_new_method_return(message)))
956 if (!(f = open_memstream(&dump, &size)))
959 manager_dump_units(m, f, NULL);
960 manager_dump_jobs(m, f, NULL);
970 if (!dbus_message_append_args(reply, DBUS_TYPE_STRING, &dump, DBUS_TYPE_INVALID)) {
976 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "CreateSnapshot")) {
981 if (!dbus_message_get_args(
984 DBUS_TYPE_STRING, &name,
985 DBUS_TYPE_BOOLEAN, &cleanup,
987 return bus_send_error_reply(connection, message, &error, -EINVAL);
989 if (name && name[0] == 0)
992 if ((r = snapshot_create(m, name, cleanup, &error, &s)) < 0)
993 return bus_send_error_reply(connection, message, &error, r);
995 if (!(reply = dbus_message_new_method_return(message)))
998 if (!(path = unit_dbus_path(UNIT(s))))
1001 if (!dbus_message_append_args(
1003 DBUS_TYPE_OBJECT_PATH, &path,
1007 } else if (dbus_message_is_method_call(message, "org.freedesktop.DBus.Introspectable", "Introspect")) {
1008 char *introspection = NULL;
1016 if (!(reply = dbus_message_new_method_return(message)))
1019 /* We roll our own introspection code here, instead of
1020 * relying on bus_default_message_handler() because we
1021 * need to generate our introspection string
1024 if (!(f = open_memstream(&introspection, &size)))
1027 fputs(INTROSPECTION_BEGIN, f);
1029 HASHMAP_FOREACH_KEY(u, k, m->units, i) {
1035 if (!(p = bus_path_escape(k))) {
1037 free(introspection);
1041 fprintf(f, "<node name=\"unit/%s\"/>", p);
1045 HASHMAP_FOREACH(j, m->jobs, i)
1046 fprintf(f, "<node name=\"job/%lu\"/>", (unsigned long) j->id);
1048 fputs(INTROSPECTION_END, f);
1052 free(introspection);
1061 if (!dbus_message_append_args(reply, DBUS_TYPE_STRING, &introspection, DBUS_TYPE_INVALID)) {
1062 free(introspection);
1066 free(introspection);
1068 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "Reload")) {
1070 assert(!m->queued_message);
1072 /* Instead of sending the reply back right away, we
1073 * just remember that we need to and then send it
1074 * after the reload is finished. That way the caller
1075 * knows when the reload finished. */
1077 if (!(m->queued_message = dbus_message_new_method_return(message)))
1080 m->queued_message_connection = connection;
1081 m->exit_code = MANAGER_RELOAD;
1083 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "Reexecute")) {
1085 /* We don't send a reply back here, the client should
1086 * just wait for us disconnecting. */
1088 m->exit_code = MANAGER_REEXECUTE;
1090 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "Exit")) {
1092 if (m->running_as == MANAGER_SYSTEM) {
1093 dbus_set_error(&error, BUS_ERROR_NOT_SUPPORTED, "Exit is only supported for user service managers.");
1094 return bus_send_error_reply(connection, message, &error, -ENOTSUP);
1097 if (!(reply = dbus_message_new_method_return(message)))
1100 m->exit_code = MANAGER_EXIT;
1102 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "Reboot")) {
1104 if (m->running_as != MANAGER_SYSTEM) {
1105 dbus_set_error(&error, BUS_ERROR_NOT_SUPPORTED, "Reboot is only supported for system managers.");
1106 return bus_send_error_reply(connection, message, &error, -ENOTSUP);
1109 if (!(reply = dbus_message_new_method_return(message)))
1112 m->exit_code = MANAGER_REBOOT;
1114 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "PowerOff")) {
1116 if (m->running_as != MANAGER_SYSTEM) {
1117 dbus_set_error(&error, BUS_ERROR_NOT_SUPPORTED, "Powering off is only supported for system managers.");
1118 return bus_send_error_reply(connection, message, &error, -ENOTSUP);
1121 if (!(reply = dbus_message_new_method_return(message)))
1124 m->exit_code = MANAGER_POWEROFF;
1126 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "Halt")) {
1128 if (m->running_as != MANAGER_SYSTEM) {
1129 dbus_set_error(&error, BUS_ERROR_NOT_SUPPORTED, "Halting is only supported for system managers.");
1130 return bus_send_error_reply(connection, message, &error, -ENOTSUP);
1133 if (!(reply = dbus_message_new_method_return(message)))
1136 m->exit_code = MANAGER_HALT;
1138 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "KExec")) {
1140 if (m->running_as != MANAGER_SYSTEM) {
1141 dbus_set_error(&error, BUS_ERROR_NOT_SUPPORTED, "kexec is only supported for system managers.");
1142 return bus_send_error_reply(connection, message, &error, -ENOTSUP);
1145 if (!(reply = dbus_message_new_method_return(message)))
1148 m->exit_code = MANAGER_KEXEC;
1150 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "SwitchRoot")) {
1151 const char *switch_root, *switch_root_init;
1155 if (!dbus_message_get_args(
1158 DBUS_TYPE_STRING, &switch_root,
1159 DBUS_TYPE_STRING, &switch_root_init,
1161 return bus_send_error_reply(connection, message, &error, -EINVAL);
1163 if (path_equal(switch_root, "/") || !path_is_absolute(switch_root))
1164 return bus_send_error_reply(connection, message, NULL, -EINVAL);
1166 if (!isempty(switch_root_init) && !path_is_absolute(switch_root_init))
1167 return bus_send_error_reply(connection, message, NULL, -EINVAL);
1169 if (m->running_as != MANAGER_SYSTEM) {
1170 dbus_set_error(&error, BUS_ERROR_NOT_SUPPORTED, "Switching root is only supported for system managers.");
1171 return bus_send_error_reply(connection, message, &error, -ENOTSUP);
1175 if (isempty(switch_root_init))
1176 k = access(switch_root, F_OK);
1180 p = join(switch_root, "/", switch_root_init, NULL);
1184 k = access(p, X_OK);
1188 return bus_send_error_reply(connection, message, NULL, -errno);
1190 u = strdup(switch_root);
1194 if (!isempty(switch_root_init)) {
1195 v = strdup(switch_root_init);
1203 free(m->switch_root);
1204 free(m->switch_root_init);
1206 m->switch_root_init = v;
1208 reply = dbus_message_new_method_return(message);
1212 m->exit_code = MANAGER_SWITCH_ROOT;
1214 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "SetEnvironment")) {
1215 char **l = NULL, **e = NULL;
1217 if ((r = bus_parse_strv(message, &l)) < 0) {
1221 return bus_send_error_reply(connection, message, NULL, r);
1224 e = strv_env_merge(2, m->environment, l);
1230 if (!(reply = dbus_message_new_method_return(message))) {
1235 strv_free(m->environment);
1238 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "UnsetEnvironment")) {
1239 char **l = NULL, **e = NULL;
1241 if ((r = bus_parse_strv(message, &l)) < 0) {
1245 return bus_send_error_reply(connection, message, NULL, r);
1248 e = strv_env_delete(m->environment, 1, l);
1254 if (!(reply = dbus_message_new_method_return(message))) {
1259 strv_free(m->environment);
1262 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "UnsetAndSetEnvironment")) {
1263 char **l_set = NULL, **l_unset = NULL, **e = NULL, **f = NULL;
1264 DBusMessageIter iter;
1266 if (!dbus_message_iter_init(message, &iter))
1269 r = bus_parse_strv_iter(&iter, &l_unset);
1274 return bus_send_error_reply(connection, message, NULL, r);
1277 if (!dbus_message_iter_next(&iter)) {
1279 return bus_send_error_reply(connection, message, NULL, -EINVAL);
1282 r = bus_parse_strv_iter(&iter, &l_set);
1288 return bus_send_error_reply(connection, message, NULL, r);
1291 e = strv_env_delete(m->environment, 1, l_unset);
1299 f = strv_env_merge(2, e, l_set);
1306 if (!(reply = dbus_message_new_method_return(message))) {
1311 strv_free(m->environment);
1313 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ListUnitFiles")) {
1314 DBusMessageIter iter, sub, sub2;
1319 reply = dbus_message_new_method_return(message);
1323 h = hashmap_new(string_hash_func, string_compare_func);
1327 r = unit_file_get_list(m->running_as == MANAGER_SYSTEM ? UNIT_FILE_SYSTEM : UNIT_FILE_USER, NULL, h);
1329 unit_file_list_free(h);
1330 dbus_message_unref(reply);
1331 return bus_send_error_reply(connection, message, NULL, r);
1334 dbus_message_iter_init_append(reply, &iter);
1336 if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "(ss)", &sub)) {
1337 unit_file_list_free(h);
1341 HASHMAP_FOREACH(item, h, i) {
1344 state = unit_file_state_to_string(item->state);
1347 if (!dbus_message_iter_open_container(&sub, DBUS_TYPE_STRUCT, NULL, &sub2) ||
1348 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &item->path) ||
1349 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &state) ||
1350 !dbus_message_iter_close_container(&sub, &sub2)) {
1351 unit_file_list_free(h);
1356 unit_file_list_free(h);
1358 if (!dbus_message_iter_close_container(&iter, &sub))
1361 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "GetUnitFileState")) {
1363 UnitFileState state;
1366 if (!dbus_message_get_args(
1369 DBUS_TYPE_STRING, &name,
1371 return bus_send_error_reply(connection, message, &error, -EINVAL);
1373 state = unit_file_get_state(m->running_as == MANAGER_SYSTEM ? UNIT_FILE_SYSTEM : UNIT_FILE_USER, NULL, name);
1375 return bus_send_error_reply(connection, message, NULL, state);
1377 s = unit_file_state_to_string(state);
1380 reply = dbus_message_new_method_return(message);
1384 if (!dbus_message_append_args(
1386 DBUS_TYPE_STRING, &s,
1389 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "EnableUnitFiles") ||
1390 dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ReenableUnitFiles") ||
1391 dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "LinkUnitFiles") ||
1392 dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "PresetUnitFiles") ||
1393 dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "MaskUnitFiles")) {
1396 DBusMessageIter iter;
1397 UnitFileScope scope = m->running_as == MANAGER_SYSTEM ? UNIT_FILE_SYSTEM : UNIT_FILE_USER;
1398 UnitFileChange *changes = NULL;
1399 unsigned n_changes = 0;
1400 dbus_bool_t runtime, force;
1401 int carries_install_info = -1;
1403 if (!dbus_message_iter_init(message, &iter))
1406 r = bus_parse_strv_iter(&iter, &l);
1411 return bus_send_error_reply(connection, message, NULL, r);
1414 if (!dbus_message_iter_next(&iter) ||
1415 bus_iter_get_basic_and_next(&iter, DBUS_TYPE_BOOLEAN, &runtime, true) < 0 ||
1416 bus_iter_get_basic_and_next(&iter, DBUS_TYPE_BOOLEAN, &force, false) < 0) {
1418 return bus_send_error_reply(connection, message, NULL, -EIO);
1421 if (streq(member, "EnableUnitFiles")) {
1422 r = unit_file_enable(scope, runtime, NULL, l, force, &changes, &n_changes);
1423 carries_install_info = r;
1424 } else if (streq(member, "ReenableUnitFiles")) {
1425 r = unit_file_reenable(scope, runtime, NULL, l, force, &changes, &n_changes);
1426 carries_install_info = r;
1427 } else if (streq(member, "LinkUnitFiles"))
1428 r = unit_file_link(scope, runtime, NULL, l, force, &changes, &n_changes);
1429 else if (streq(member, "PresetUnitFiles")) {
1430 r = unit_file_preset(scope, runtime, NULL, l, force, &changes, &n_changes);
1431 carries_install_info = r;
1432 } else if (streq(member, "MaskUnitFiles"))
1433 r = unit_file_mask(scope, runtime, NULL, l, force, &changes, &n_changes);
1435 assert_not_reached("Uh? Wrong method");
1438 bus_manager_send_unit_files_changed(m);
1441 unit_file_changes_free(changes, n_changes);
1442 return bus_send_error_reply(connection, message, NULL, r);
1445 reply = message_from_file_changes(message, changes, n_changes, carries_install_info);
1446 unit_file_changes_free(changes, n_changes);
1451 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "DisableUnitFiles") ||
1452 dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "UnmaskUnitFiles")) {
1455 DBusMessageIter iter;
1456 UnitFileScope scope = m->running_as == MANAGER_SYSTEM ? UNIT_FILE_SYSTEM : UNIT_FILE_USER;
1457 UnitFileChange *changes = NULL;
1458 unsigned n_changes = 0;
1459 dbus_bool_t runtime;
1461 if (!dbus_message_iter_init(message, &iter))
1464 r = bus_parse_strv_iter(&iter, &l);
1469 return bus_send_error_reply(connection, message, NULL, r);
1472 if (!dbus_message_iter_next(&iter) ||
1473 bus_iter_get_basic_and_next(&iter, DBUS_TYPE_BOOLEAN, &runtime, false) < 0) {
1475 return bus_send_error_reply(connection, message, NULL, -EIO);
1478 if (streq(member, "DisableUnitFiles"))
1479 r = unit_file_disable(scope, runtime, NULL, l, &changes, &n_changes);
1480 else if (streq(member, "UnmaskUnitFiles"))
1481 r = unit_file_unmask(scope, runtime, NULL, l, &changes, &n_changes);
1483 assert_not_reached("Uh? Wrong method");
1486 bus_manager_send_unit_files_changed(m);
1489 unit_file_changes_free(changes, n_changes);
1490 return bus_send_error_reply(connection, message, NULL, r);
1493 reply = message_from_file_changes(message, changes, n_changes, -1);
1494 unit_file_changes_free(changes, n_changes);
1500 const BusBoundProperties bps[] = {
1501 { "org.freedesktop.systemd1.Manager", bus_systemd_properties, systemd_property_string },
1502 { "org.freedesktop.systemd1.Manager", bus_manager_properties, m },
1505 return bus_default_message_handler(connection, message, NULL, INTERFACES_LIST, bps);
1508 if (job_type != _JOB_TYPE_INVALID) {
1509 const char *name, *smode, *old_name = NULL;
1516 if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "StartUnitReplace"))
1517 b = dbus_message_get_args(
1520 DBUS_TYPE_STRING, &old_name,
1521 DBUS_TYPE_STRING, &name,
1522 DBUS_TYPE_STRING, &smode,
1525 b = dbus_message_get_args(
1528 DBUS_TYPE_STRING, &name,
1529 DBUS_TYPE_STRING, &smode,
1533 return bus_send_error_reply(connection, message, &error, -EINVAL);
1536 if (!(u = manager_get_unit(m, old_name)) ||
1538 u->job->type != JOB_START) {
1539 dbus_set_error(&error, BUS_ERROR_NO_SUCH_JOB, "No job queued for unit %s", old_name);
1540 return bus_send_error_reply(connection, message, &error, -ENOENT);
1544 if ((mode = job_mode_from_string(smode)) == _JOB_MODE_INVALID) {
1545 dbus_set_error(&error, BUS_ERROR_INVALID_JOB_MODE, "Job mode %s is invalid.", smode);
1546 return bus_send_error_reply(connection, message, &error, -EINVAL);
1549 if ((r = manager_load_unit(m, name, NULL, &error, &u)) < 0)
1550 return bus_send_error_reply(connection, message, &error, r);
1552 if (reload_if_possible && unit_can_reload(u)) {
1553 if (job_type == JOB_RESTART)
1554 job_type = JOB_RELOAD_OR_START;
1555 else if (job_type == JOB_TRY_RESTART)
1556 job_type = JOB_RELOAD;
1559 if (job_type == JOB_STOP && u->load_state == UNIT_ERROR && unit_active_state(u) == UNIT_INACTIVE) {
1560 dbus_set_error(&error, BUS_ERROR_NO_SUCH_UNIT, "Unit %s not loaded.", name);
1561 return bus_send_error_reply(connection, message, &error, -EPERM);
1564 if ((job_type == JOB_START && u->refuse_manual_start) ||
1565 (job_type == JOB_STOP && u->refuse_manual_stop) ||
1566 ((job_type == JOB_RESTART || job_type == JOB_TRY_RESTART) &&
1567 (u->refuse_manual_start || u->refuse_manual_stop))) {
1568 dbus_set_error(&error, BUS_ERROR_ONLY_BY_DEPENDENCY, "Operation refused, may be requested by dependency only.");
1569 return bus_send_error_reply(connection, message, &error, -EPERM);
1572 if ((r = manager_add_job(m, job_type, u, mode, true, &error, &j)) < 0)
1573 return bus_send_error_reply(connection, message, &error, r);
1575 cl = job_bus_client_new(connection, message_get_sender_with_fallback(message));
1579 LIST_PREPEND(JobBusClient, client, j->bus_client_list, cl);
1581 if (!(reply = dbus_message_new_method_return(message)))
1584 if (!(path = job_dbus_path(j)))
1587 if (!dbus_message_append_args(
1589 DBUS_TYPE_OBJECT_PATH, &path,
1595 if (!dbus_connection_send(connection, reply, NULL))
1598 dbus_message_unref(reply);
1603 return DBUS_HANDLER_RESULT_HANDLED;
1609 dbus_message_unref(reply);
1611 dbus_error_free(&error);
1613 return DBUS_HANDLER_RESULT_NEED_MEMORY;
1616 const DBusObjectPathVTable bus_manager_vtable = {
1617 .message_function = bus_manager_message_handler