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=\"signal\" type=\"i\" direction=\"in\"/>\n" \
99 " <method name=\"ResetFailedUnit\">\n" \
100 " <arg name=\"name\" type=\"s\" direction=\"in\"/>\n" \
102 " <method name=\"GetJob\">\n" \
103 " <arg name=\"id\" type=\"u\" direction=\"in\"/>\n" \
104 " <arg name=\"job\" type=\"o\" direction=\"out\"/>\n" \
106 " <method name=\"ClearJobs\"/>\n" \
107 " <method name=\"ResetFailed\"/>\n" \
108 " <method name=\"ListUnits\">\n" \
109 " <arg name=\"units\" type=\"a(ssssssouso)\" direction=\"out\"/>\n" \
111 " <method name=\"ListJobs\">\n" \
112 " <arg name=\"jobs\" type=\"a(usssoo)\" direction=\"out\"/>\n" \
114 " <method name=\"Subscribe\"/>\n" \
115 " <method name=\"Unsubscribe\"/>\n" \
116 " <method name=\"Dump\">\n" \
117 " <arg name=\"dump\" type=\"s\" direction=\"out\"/>\n" \
119 " <method name=\"CreateSnapshot\">\n" \
120 " <arg name=\"name\" type=\"s\" direction=\"in\"/>\n" \
121 " <arg name=\"cleanup\" type=\"b\" direction=\"in\"/>\n" \
122 " <arg name=\"unit\" type=\"o\" direction=\"out\"/>\n" \
124 " <method name=\"Reload\"/>\n" \
125 " <method name=\"Reexecute\"/>\n" \
126 " <method name=\"Exit\"/>\n" \
127 " <method name=\"Reboot\"/>\n" \
128 " <method name=\"PowerOff\"/>\n" \
129 " <method name=\"Halt\"/>\n" \
130 " <method name=\"KExec\"/>\n" \
131 " <method name=\"SwitchRoot\">\n" \
132 " <arg name=\"new_root\" type=\"s\" direction=\"in\"/>\n" \
133 " <arg name=\"init\" type=\"s\" direction=\"in\"/>\n" \
135 " <method name=\"SetEnvironment\">\n" \
136 " <arg name=\"names\" type=\"as\" direction=\"in\"/>\n" \
138 " <method name=\"UnsetEnvironment\">\n" \
139 " <arg name=\"names\" type=\"as\" direction=\"in\"/>\n" \
141 " <method name=\"UnsetAndSetEnvironment\">\n" \
142 " <arg name=\"unset\" type=\"as\" direction=\"in\"/>\n" \
143 " <arg name=\"set\" type=\"as\" direction=\"in\"/>\n" \
145 " <method name=\"ListUnitFiles\">\n" \
146 " <arg name=\"files\" type=\"a(ss)\" direction=\"out\"/>\n" \
148 " <method name=\"GetUnitFileState\">\n" \
149 " <arg name=\"file\" type=\"s\" direction=\"in\"/>\n" \
150 " <arg name=\"state\" type=\"s\" direction=\"out\"/>\n" \
152 " <method name=\"EnableUnitFiles\">\n" \
153 " <arg name=\"files\" type=\"as\" direction=\"in\"/>\n" \
154 " <arg name=\"runtime\" type=\"b\" direction=\"in\"/>\n" \
155 " <arg name=\"force\" type=\"b\" direction=\"in\"/>\n" \
156 " <arg name=\"carries_install_info\" type=\"b\" direction=\"out\"/>\n" \
157 " <arg name=\"changes\" type=\"a(sss)\" direction=\"out\"/>\n" \
159 " <method name=\"DisableUnitFiles\">\n" \
160 " <arg name=\"files\" type=\"as\" direction=\"in\"/>\n" \
161 " <arg name=\"runtime\" type=\"b\" direction=\"in\"/>\n" \
162 " <arg name=\"changes\" type=\"a(sss)\" direction=\"out\"/>\n" \
164 " <method name=\"ReenableUnitFiles\">\n" \
165 " <arg name=\"files\" type=\"as\" direction=\"in\"/>\n" \
166 " <arg name=\"runtime\" type=\"b\" direction=\"in\"/>\n" \
167 " <arg name=\"force\" type=\"b\" direction=\"in\"/>\n" \
168 " <arg name=\"carries_install_info\" type=\"b\" direction=\"out\"/>\n" \
169 " <arg name=\"changes\" type=\"a(sss)\" direction=\"out\"/>\n" \
171 " <method name=\"LinkUnitFiles\">\n" \
172 " <arg name=\"files\" type=\"as\" direction=\"in\"/>\n" \
173 " <arg name=\"runtime\" type=\"b\" direction=\"in\"/>\n" \
174 " <arg name=\"force\" type=\"b\" direction=\"in\"/>\n" \
175 " <arg name=\"changes\" type=\"a(sss)\" direction=\"out\"/>\n" \
177 " <method name=\"PresetUnitFiles\">\n" \
178 " <arg name=\"files\" type=\"as\" direction=\"in\"/>\n" \
179 " <arg name=\"runtime\" type=\"b\" direction=\"in\"/>\n" \
180 " <arg name=\"force\" type=\"b\" direction=\"in\"/>\n" \
181 " <arg name=\"carries_install_info\" type=\"b\" direction=\"out\"/>\n" \
182 " <arg name=\"changes\" type=\"a(sss)\" direction=\"out\"/>\n" \
184 " <method name=\"MaskUnitFiles\">\n" \
185 " <arg name=\"files\" type=\"as\" direction=\"in\"/>\n" \
186 " <arg name=\"runtime\" type=\"b\" direction=\"in\"/>\n" \
187 " <arg name=\"force\" type=\"b\" direction=\"in\"/>\n" \
188 " <arg name=\"changes\" type=\"a(sss)\" direction=\"out\"/>\n" \
190 " <method name=\"UnmaskUnitFiles\">\n" \
191 " <arg name=\"files\" type=\"as\" direction=\"in\"/>\n" \
192 " <arg name=\"runtime\" type=\"b\" direction=\"in\"/>\n" \
193 " <arg name=\"changes\" type=\"a(sss)\" direction=\"out\"/>\n" \
196 #define BUS_MANAGER_INTERFACE_SIGNALS \
197 " <signal name=\"UnitNew\">\n" \
198 " <arg name=\"id\" type=\"s\"/>\n" \
199 " <arg name=\"unit\" type=\"o\"/>\n" \
201 " <signal name=\"UnitRemoved\">\n" \
202 " <arg name=\"id\" type=\"s\"/>\n" \
203 " <arg name=\"unit\" type=\"o\"/>\n" \
205 " <signal name=\"JobNew\">\n" \
206 " <arg name=\"id\" type=\"u\"/>\n" \
207 " <arg name=\"job\" type=\"o\"/>\n" \
208 " <arg name=\"unit\" type=\"s\"/>\n" \
210 " <signal name=\"JobRemoved\">\n" \
211 " <arg name=\"id\" type=\"u\"/>\n" \
212 " <arg name=\"job\" type=\"o\"/>\n" \
213 " <arg name=\"unit\" type=\"s\"/>\n" \
214 " <arg name=\"result\" type=\"s\"/>\n" \
216 " <signal name=\"StartupFinished\">\n" \
217 " <arg name=\"kernel\" type=\"t\"/>\n" \
218 " <arg name=\"initrd\" type=\"t\"/>\n" \
219 " <arg name=\"userspace\" type=\"t\"/>\n" \
220 " <arg name=\"total\" type=\"t\"/>\n" \
222 " <signal name=\"UnitFilesChanged\"/>\n"
224 #define BUS_MANAGER_INTERFACE_PROPERTIES_GENERAL \
225 " <property name=\"Version\" type=\"s\" access=\"read\"/>\n" \
226 " <property name=\"Distribution\" type=\"s\" access=\"read\"/>\n" \
227 " <property name=\"Features\" type=\"s\" access=\"read\"/>\n" \
228 " <property name=\"Tainted\" type=\"s\" access=\"read\"/>\n" \
229 " <property name=\"InitRDTimestamp\" type=\"t\" access=\"read\"/>\n" \
230 " <property name=\"InitRDTimestampMonotonic\" type=\"t\" access=\"read\"/>\n" \
231 " <property name=\"StartupTimestamp\" type=\"t\" access=\"read\"/>\n" \
232 " <property name=\"StartupTimestampMonotonic\" type=\"t\" access=\"read\"/>\n" \
233 " <property name=\"FinishTimestamp\" type=\"t\" access=\"read\"/>\n" \
234 " <property name=\"FinishTimestampMonotonic\" type=\"t\" access=\"read\"/>\n" \
235 " <property name=\"LogLevel\" type=\"s\" access=\"readwrite\"/>\n" \
236 " <property name=\"LogTarget\" type=\"s\" access=\"readwrite\"/>\n" \
237 " <property name=\"NNames\" type=\"u\" access=\"read\"/>\n" \
238 " <property name=\"NJobs\" type=\"u\" access=\"read\"/>\n" \
239 " <property name=\"NInstalledJobs\" type=\"u\" access=\"read\"/>\n" \
240 " <property name=\"NFailedJobs\" type=\"u\" access=\"read\"/>\n" \
241 " <property name=\"Progress\" type=\"d\" access=\"read\"/>\n" \
242 " <property name=\"Environment\" type=\"as\" access=\"read\"/>\n" \
243 " <property name=\"ConfirmSpawn\" type=\"b\" access=\"read\"/>\n" \
244 " <property name=\"ShowStatus\" type=\"b\" access=\"read\"/>\n" \
245 " <property name=\"UnitPath\" type=\"as\" access=\"read\"/>\n" \
246 " <property name=\"ControlGroupHierarchy\" type=\"s\" access=\"read\"/>\n" \
247 " <property name=\"DefaultControllers\" type=\"as\" access=\"read\"/>\n" \
248 " <property name=\"DefaultStandardOutput\" type=\"s\" access=\"read\"/>\n" \
249 " <property name=\"DefaultStandardError\" type=\"s\" access=\"read\"/>\n" \
250 " <property name=\"RuntimeWatchdogUSec\" type=\"s\" access=\"readwrite\"/>\n" \
251 " <property name=\"ShutdownWatchdogUSec\" type=\"s\" access=\"readwrite\"/>\n"
253 #define BUS_MANAGER_INTERFACE_END \
256 #define BUS_MANAGER_INTERFACE \
257 BUS_MANAGER_INTERFACE_BEGIN \
258 BUS_MANAGER_INTERFACE_METHODS \
259 BUS_MANAGER_INTERFACE_SIGNALS \
260 BUS_MANAGER_INTERFACE_PROPERTIES_GENERAL \
261 BUS_MANAGER_INTERFACE_END
263 #define INTROSPECTION_BEGIN \
264 DBUS_INTROSPECT_1_0_XML_DOCTYPE_DECL_NODE \
266 BUS_MANAGER_INTERFACE \
267 BUS_PROPERTIES_INTERFACE \
269 BUS_INTROSPECTABLE_INTERFACE
271 #define INTROSPECTION_END \
274 #define INTERFACES_LIST \
275 BUS_GENERIC_INTERFACES_LIST \
276 "org.freedesktop.systemd1.Manager\0"
278 const char bus_manager_interface[] _introspect_("Manager") = BUS_MANAGER_INTERFACE;
280 static DEFINE_BUS_PROPERTY_APPEND_ENUM(bus_manager_append_exec_output, exec_output, ExecOutput);
282 static int bus_manager_append_tainted(DBusMessageIter *i, const char *property, void *data) {
285 char buf[LINE_MAX] = "", *e = buf, *p = NULL;
292 e = stpcpy(e, "split-usr:");
294 if (readlink_malloc("/etc/mtab", &p) < 0)
295 e = stpcpy(e, "mtab-not-symlink:");
299 if (access("/proc/cgroups", F_OK) < 0)
300 e = stpcpy(e, "cgroups-missing:");
302 if (hwclock_is_localtime() > 0)
303 e = stpcpy(e, "local-hwclock:");
305 /* remove the last ':' */
311 if (!dbus_message_iter_append_basic(i, DBUS_TYPE_STRING, &t))
317 static int bus_manager_append_log_target(DBusMessageIter *i, const char *property, void *data) {
323 t = log_target_to_string(log_get_target());
325 if (!dbus_message_iter_append_basic(i, DBUS_TYPE_STRING, &t))
331 static int bus_manager_set_log_target(DBusMessageIter *i, const char *property, void *data) {
337 dbus_message_iter_get_basic(i, &t);
339 return log_set_target_from_string(t);
342 static int bus_manager_append_log_level(DBusMessageIter *i, const char *property, void *data) {
348 t = log_level_to_string(log_get_max_level());
350 if (!dbus_message_iter_append_basic(i, DBUS_TYPE_STRING, &t))
356 static int bus_manager_set_log_level(DBusMessageIter *i, const char *property, void *data) {
362 dbus_message_iter_get_basic(i, &t);
364 return log_set_max_level_from_string(t);
367 static int bus_manager_append_n_names(DBusMessageIter *i, const char *property, void *data) {
375 u = hashmap_size(m->units);
377 if (!dbus_message_iter_append_basic(i, DBUS_TYPE_UINT32, &u))
383 static int bus_manager_append_n_jobs(DBusMessageIter *i, const char *property, void *data) {
391 u = hashmap_size(m->jobs);
393 if (!dbus_message_iter_append_basic(i, DBUS_TYPE_UINT32, &u))
399 static int bus_manager_append_progress(DBusMessageIter *i, const char *property, void *data) {
407 if (dual_timestamp_is_set(&m->finish_timestamp))
410 d = 1.0 - ((double) hashmap_size(m->jobs) / (double) m->n_installed_jobs);
412 if (!dbus_message_iter_append_basic(i, DBUS_TYPE_DOUBLE, &d))
418 static const char *message_get_sender_with_fallback(DBusMessage *m) {
423 if ((s = dbus_message_get_sender(m)))
426 /* When the message came in from a direct connection the
427 * message will have no sender. We fix that here. */
432 static DBusMessage *message_from_file_changes(
434 UnitFileChange *changes,
436 int carries_install_info) {
438 DBusMessageIter iter, sub, sub2;
442 reply = dbus_message_new_method_return(m);
446 dbus_message_iter_init_append(reply, &iter);
448 if (carries_install_info >= 0) {
451 b = !!carries_install_info;
452 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &b))
456 if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "(sss)", &sub))
459 for (i = 0; i < n_changes; i++) {
460 const char *type, *path, *source;
462 type = unit_file_change_type_to_string(changes[i].type);
463 path = strempty(changes[i].path);
464 source = strempty(changes[i].source);
466 if (!dbus_message_iter_open_container(&sub, DBUS_TYPE_STRUCT, NULL, &sub2) ||
467 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &type) ||
468 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &path) ||
469 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &source) ||
470 !dbus_message_iter_close_container(&sub, &sub2))
474 if (!dbus_message_iter_close_container(&iter, &sub))
480 dbus_message_unref(reply);
484 static int bus_manager_send_unit_files_changed(Manager *m) {
488 s = dbus_message_new_signal("/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", "UnitFilesChanged");
492 r = bus_broadcast(m, s);
493 dbus_message_unref(s);
498 static int bus_manager_set_runtime_watchdog_usec(DBusMessageIter *i, const char *property, void *data) {
504 dbus_message_iter_get_basic(i, t);
506 return watchdog_set_timeout(t);
509 static const char systemd_property_string[] =
514 static const BusProperty bus_systemd_properties[] = {
515 { "Version", bus_property_append_string, "s", 0 },
516 { "Distribution", bus_property_append_string, "s", sizeof(PACKAGE_STRING) },
517 { "Features", bus_property_append_string, "s", sizeof(PACKAGE_STRING) + sizeof(DISTRIBUTION) },
521 static const BusProperty bus_manager_properties[] = {
522 { "Tainted", bus_manager_append_tainted, "s", 0 },
523 { "InitRDTimestamp", bus_property_append_uint64, "t", offsetof(Manager, initrd_timestamp.realtime) },
524 { "InitRDTimestampMonotonic", bus_property_append_uint64, "t", offsetof(Manager, initrd_timestamp.monotonic) },
525 { "StartupTimestamp", bus_property_append_uint64, "t", offsetof(Manager, startup_timestamp.realtime) },
526 { "StartupTimestampMonotonic", bus_property_append_uint64, "t", offsetof(Manager, startup_timestamp.monotonic) },
527 { "FinishTimestamp", bus_property_append_uint64, "t", offsetof(Manager, finish_timestamp.realtime) },
528 { "FinishTimestampMonotonic", bus_property_append_uint64, "t", offsetof(Manager, finish_timestamp.monotonic) },
529 { "LogLevel", bus_manager_append_log_level, "s", 0, false, bus_manager_set_log_level },
530 { "LogTarget", bus_manager_append_log_target, "s", 0, false, bus_manager_set_log_target },
531 { "NNames", bus_manager_append_n_names, "u", 0 },
532 { "NJobs", bus_manager_append_n_jobs, "u", 0 },
533 { "NInstalledJobs",bus_property_append_uint32, "u", offsetof(Manager, n_installed_jobs) },
534 { "NFailedJobs", bus_property_append_uint32, "u", offsetof(Manager, n_failed_jobs) },
535 { "Progress", bus_manager_append_progress, "d", 0 },
536 { "Environment", bus_property_append_strv, "as", offsetof(Manager, environment), true },
537 { "ConfirmSpawn", bus_property_append_bool, "b", offsetof(Manager, confirm_spawn) },
538 { "ShowStatus", bus_property_append_bool, "b", offsetof(Manager, show_status) },
539 { "UnitPath", bus_property_append_strv, "as", offsetof(Manager, lookup_paths.unit_path), true },
540 { "ControlGroupHierarchy", bus_property_append_string, "s", offsetof(Manager, cgroup_hierarchy), true },
541 { "DefaultControllers", bus_property_append_strv, "as", offsetof(Manager, default_controllers), true },
542 { "DefaultStandardOutput", bus_manager_append_exec_output, "s", offsetof(Manager, default_std_output) },
543 { "DefaultStandardError", bus_manager_append_exec_output, "s", offsetof(Manager, default_std_error) },
544 { "RuntimeWatchdogUSec", bus_property_append_usec, "t", offsetof(Manager, runtime_watchdog), false, bus_manager_set_runtime_watchdog_usec },
545 { "ShutdownWatchdogUSec", bus_property_append_usec, "t", offsetof(Manager, shutdown_watchdog), false, bus_property_set_usec },
549 static DBusHandlerResult bus_manager_message_handler(DBusConnection *connection, DBusMessage *message, void *data) {
554 DBusMessage *reply = NULL;
556 JobType job_type = _JOB_TYPE_INVALID;
557 bool reload_if_possible = false;
564 dbus_error_init(&error);
566 member = dbus_message_get_member(message);
568 if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "GetUnit")) {
572 if (!dbus_message_get_args(
575 DBUS_TYPE_STRING, &name,
577 return bus_send_error_reply(connection, message, &error, -EINVAL);
579 if (!(u = manager_get_unit(m, name))) {
580 dbus_set_error(&error, BUS_ERROR_NO_SUCH_UNIT, "Unit %s is not loaded.", name);
581 return bus_send_error_reply(connection, message, &error, -ENOENT);
584 if (!(reply = dbus_message_new_method_return(message)))
587 if (!(path = unit_dbus_path(u)))
590 if (!dbus_message_append_args(
592 DBUS_TYPE_OBJECT_PATH, &path,
595 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "GetUnitByPID")) {
599 if (!dbus_message_get_args(
602 DBUS_TYPE_UINT32, &pid,
604 return bus_send_error_reply(connection, message, &error, -EINVAL);
606 if (!(u = cgroup_unit_by_pid(m, (pid_t) pid))) {
607 dbus_set_error(&error, BUS_ERROR_NO_SUCH_UNIT, "No unit for PID %lu is loaded.", (unsigned long) pid);
608 return bus_send_error_reply(connection, message, &error, -ENOENT);
611 if (!(reply = dbus_message_new_method_return(message)))
614 if (!(path = unit_dbus_path(u)))
617 if (!dbus_message_append_args(
619 DBUS_TYPE_OBJECT_PATH, &path,
622 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "LoadUnit")) {
626 if (!dbus_message_get_args(
629 DBUS_TYPE_STRING, &name,
631 return bus_send_error_reply(connection, message, &error, -EINVAL);
633 if ((r = manager_load_unit(m, name, NULL, &error, &u)) < 0)
634 return bus_send_error_reply(connection, message, &error, r);
636 if (!(reply = dbus_message_new_method_return(message)))
639 if (!(path = unit_dbus_path(u)))
642 if (!dbus_message_append_args(
644 DBUS_TYPE_OBJECT_PATH, &path,
648 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "StartUnit"))
649 job_type = JOB_START;
650 else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "StartUnitReplace"))
651 job_type = JOB_START;
652 else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "StopUnit"))
654 else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ReloadUnit"))
655 job_type = JOB_RELOAD;
656 else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "RestartUnit"))
657 job_type = JOB_RESTART;
658 else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "TryRestartUnit"))
659 job_type = JOB_TRY_RESTART;
660 else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ReloadOrRestartUnit")) {
661 reload_if_possible = true;
662 job_type = JOB_RESTART;
663 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ReloadOrTryRestartUnit")) {
664 reload_if_possible = true;
665 job_type = JOB_TRY_RESTART;
666 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "KillUnit")) {
667 const char *name, *swho;
672 if (!dbus_message_get_args(
675 DBUS_TYPE_STRING, &name,
676 DBUS_TYPE_STRING, &swho,
677 DBUS_TYPE_INT32, &signo,
679 return bus_send_error_reply(connection, message, &error, -EINVAL);
684 who = kill_who_from_string(swho);
686 return bus_send_error_reply(connection, message, &error, -EINVAL);
689 if (signo <= 0 || signo >= _NSIG)
690 return bus_send_error_reply(connection, message, &error, -EINVAL);
692 u = manager_get_unit(m, name);
694 dbus_set_error(&error, BUS_ERROR_NO_SUCH_UNIT, "Unit %s is not loaded.", name);
695 return bus_send_error_reply(connection, message, &error, -ENOENT);
698 r = unit_kill(u, who, signo, &error);
700 return bus_send_error_reply(connection, message, &error, r);
702 if (!(reply = dbus_message_new_method_return(message)))
705 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "GetJob")) {
709 if (!dbus_message_get_args(
712 DBUS_TYPE_UINT32, &id,
714 return bus_send_error_reply(connection, message, &error, -EINVAL);
716 if (!(j = manager_get_job(m, id))) {
717 dbus_set_error(&error, BUS_ERROR_NO_SUCH_JOB, "Job %u does not exist.", (unsigned) id);
718 return bus_send_error_reply(connection, message, &error, -ENOENT);
721 if (!(reply = dbus_message_new_method_return(message)))
724 if (!(path = job_dbus_path(j)))
727 if (!dbus_message_append_args(
729 DBUS_TYPE_OBJECT_PATH, &path,
733 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ClearJobs")) {
735 manager_clear_jobs(m);
737 if (!(reply = dbus_message_new_method_return(message)))
740 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ResetFailed")) {
742 manager_reset_failed(m);
744 if (!(reply = dbus_message_new_method_return(message)))
747 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ResetFailedUnit")) {
751 if (!dbus_message_get_args(
754 DBUS_TYPE_STRING, &name,
756 return bus_send_error_reply(connection, message, &error, -EINVAL);
758 if (!(u = manager_get_unit(m, name))) {
759 dbus_set_error(&error, BUS_ERROR_NO_SUCH_UNIT, "Unit %s is not loaded.", name);
760 return bus_send_error_reply(connection, message, &error, -ENOENT);
763 unit_reset_failed(u);
765 if (!(reply = dbus_message_new_method_return(message)))
768 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ListUnits")) {
769 DBusMessageIter iter, sub;
774 if (!(reply = dbus_message_new_method_return(message)))
777 dbus_message_iter_init_append(reply, &iter);
779 if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "(ssssssouso)", &sub))
782 HASHMAP_FOREACH_KEY(u, k, m->units, i) {
783 char *u_path, *j_path;
784 const char *description, *load_state, *active_state, *sub_state, *sjob_type, *following;
785 DBusMessageIter sub2;
792 if (!dbus_message_iter_open_container(&sub, DBUS_TYPE_STRUCT, NULL, &sub2))
795 description = unit_description(u);
796 load_state = unit_load_state_to_string(u->load_state);
797 active_state = unit_active_state_to_string(unit_active_state(u));
798 sub_state = unit_sub_state_to_string(u);
800 f = unit_following(u);
801 following = f ? f->id : "";
803 if (!(u_path = unit_dbus_path(u)))
807 job_id = (uint32_t) u->job->id;
809 if (!(j_path = job_dbus_path(u->job))) {
814 sjob_type = job_type_to_string(u->job->type);
821 if (!dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &u->id) ||
822 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &description) ||
823 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &load_state) ||
824 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &active_state) ||
825 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &sub_state) ||
826 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &following) ||
827 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_OBJECT_PATH, &u_path) ||
828 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_UINT32, &job_id) ||
829 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &sjob_type) ||
830 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_OBJECT_PATH, &j_path)) {
841 if (!dbus_message_iter_close_container(&sub, &sub2))
845 if (!dbus_message_iter_close_container(&iter, &sub))
848 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ListJobs")) {
849 DBusMessageIter iter, sub;
853 if (!(reply = dbus_message_new_method_return(message)))
856 dbus_message_iter_init_append(reply, &iter);
858 if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "(usssoo)", &sub))
861 HASHMAP_FOREACH(j, m->jobs, i) {
862 char *u_path, *j_path;
863 const char *state, *type;
865 DBusMessageIter sub2;
867 if (!dbus_message_iter_open_container(&sub, DBUS_TYPE_STRUCT, NULL, &sub2))
870 id = (uint32_t) j->id;
871 state = job_state_to_string(j->state);
872 type = job_type_to_string(j->type);
874 if (!(j_path = job_dbus_path(j)))
877 if (!(u_path = unit_dbus_path(j->unit))) {
882 if (!dbus_message_iter_append_basic(&sub2, DBUS_TYPE_UINT32, &id) ||
883 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &j->unit->id) ||
884 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &type) ||
885 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &state) ||
886 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_OBJECT_PATH, &j_path) ||
887 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_OBJECT_PATH, &u_path)) {
896 if (!dbus_message_iter_close_container(&sub, &sub2))
900 if (!dbus_message_iter_close_container(&iter, &sub))
903 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "Subscribe")) {
907 if (!(s = BUS_CONNECTION_SUBSCRIBED(m, connection))) {
908 if (!(s = set_new(string_hash_func, string_compare_func)))
911 if (!(dbus_connection_set_data(connection, m->subscribed_data_slot, s, NULL))) {
917 if (!(client = strdup(message_get_sender_with_fallback(message))))
920 if ((r = set_put(s, client)) < 0) {
922 return bus_send_error_reply(connection, message, NULL, r);
925 if (!(reply = dbus_message_new_method_return(message)))
928 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "Unsubscribe")) {
931 if (!(client = set_remove(BUS_CONNECTION_SUBSCRIBED(m, connection), (char*) message_get_sender_with_fallback(message)))) {
932 dbus_set_error(&error, BUS_ERROR_NOT_SUBSCRIBED, "Client is not subscribed.");
933 return bus_send_error_reply(connection, message, &error, -ENOENT);
938 if (!(reply = dbus_message_new_method_return(message)))
941 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "Dump")) {
946 if (!(reply = dbus_message_new_method_return(message)))
949 if (!(f = open_memstream(&dump, &size)))
952 manager_dump_units(m, f, NULL);
953 manager_dump_jobs(m, f, NULL);
963 if (!dbus_message_append_args(reply, DBUS_TYPE_STRING, &dump, DBUS_TYPE_INVALID)) {
969 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "CreateSnapshot")) {
974 if (!dbus_message_get_args(
977 DBUS_TYPE_STRING, &name,
978 DBUS_TYPE_BOOLEAN, &cleanup,
980 return bus_send_error_reply(connection, message, &error, -EINVAL);
982 if (name && name[0] == 0)
985 if ((r = snapshot_create(m, name, cleanup, &error, &s)) < 0)
986 return bus_send_error_reply(connection, message, &error, r);
988 if (!(reply = dbus_message_new_method_return(message)))
991 if (!(path = unit_dbus_path(UNIT(s))))
994 if (!dbus_message_append_args(
996 DBUS_TYPE_OBJECT_PATH, &path,
1000 } else if (dbus_message_is_method_call(message, "org.freedesktop.DBus.Introspectable", "Introspect")) {
1001 char *introspection = NULL;
1009 if (!(reply = dbus_message_new_method_return(message)))
1012 /* We roll our own introspection code here, instead of
1013 * relying on bus_default_message_handler() because we
1014 * need to generate our introspection string
1017 if (!(f = open_memstream(&introspection, &size)))
1020 fputs(INTROSPECTION_BEGIN, f);
1022 HASHMAP_FOREACH_KEY(u, k, m->units, i) {
1028 if (!(p = bus_path_escape(k))) {
1030 free(introspection);
1034 fprintf(f, "<node name=\"unit/%s\"/>", p);
1038 HASHMAP_FOREACH(j, m->jobs, i)
1039 fprintf(f, "<node name=\"job/%lu\"/>", (unsigned long) j->id);
1041 fputs(INTROSPECTION_END, f);
1045 free(introspection);
1054 if (!dbus_message_append_args(reply, DBUS_TYPE_STRING, &introspection, DBUS_TYPE_INVALID)) {
1055 free(introspection);
1059 free(introspection);
1061 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "Reload")) {
1063 assert(!m->queued_message);
1065 /* Instead of sending the reply back right away, we
1066 * just remember that we need to and then send it
1067 * after the reload is finished. That way the caller
1068 * knows when the reload finished. */
1070 if (!(m->queued_message = dbus_message_new_method_return(message)))
1073 m->queued_message_connection = connection;
1074 m->exit_code = MANAGER_RELOAD;
1076 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "Reexecute")) {
1078 /* We don't send a reply back here, the client should
1079 * just wait for us disconnecting. */
1081 m->exit_code = MANAGER_REEXECUTE;
1083 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "Exit")) {
1085 if (m->running_as == MANAGER_SYSTEM) {
1086 dbus_set_error(&error, BUS_ERROR_NOT_SUPPORTED, "Exit is only supported for user service managers.");
1087 return bus_send_error_reply(connection, message, &error, -ENOTSUP);
1090 if (!(reply = dbus_message_new_method_return(message)))
1093 m->exit_code = MANAGER_EXIT;
1095 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "Reboot")) {
1097 if (m->running_as != MANAGER_SYSTEM) {
1098 dbus_set_error(&error, BUS_ERROR_NOT_SUPPORTED, "Reboot is only supported for system managers.");
1099 return bus_send_error_reply(connection, message, &error, -ENOTSUP);
1102 if (!(reply = dbus_message_new_method_return(message)))
1105 m->exit_code = MANAGER_REBOOT;
1107 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "PowerOff")) {
1109 if (m->running_as != MANAGER_SYSTEM) {
1110 dbus_set_error(&error, BUS_ERROR_NOT_SUPPORTED, "Powering off is only supported for system managers.");
1111 return bus_send_error_reply(connection, message, &error, -ENOTSUP);
1114 if (!(reply = dbus_message_new_method_return(message)))
1117 m->exit_code = MANAGER_POWEROFF;
1119 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "Halt")) {
1121 if (m->running_as != MANAGER_SYSTEM) {
1122 dbus_set_error(&error, BUS_ERROR_NOT_SUPPORTED, "Halting is only supported for system managers.");
1123 return bus_send_error_reply(connection, message, &error, -ENOTSUP);
1126 if (!(reply = dbus_message_new_method_return(message)))
1129 m->exit_code = MANAGER_HALT;
1131 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "KExec")) {
1133 if (m->running_as != MANAGER_SYSTEM) {
1134 dbus_set_error(&error, BUS_ERROR_NOT_SUPPORTED, "kexec is only supported for system managers.");
1135 return bus_send_error_reply(connection, message, &error, -ENOTSUP);
1138 if (!(reply = dbus_message_new_method_return(message)))
1141 m->exit_code = MANAGER_KEXEC;
1143 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "SwitchRoot")) {
1144 const char *switch_root, *switch_root_init;
1148 if (!dbus_message_get_args(
1151 DBUS_TYPE_STRING, &switch_root,
1152 DBUS_TYPE_STRING, &switch_root_init,
1154 return bus_send_error_reply(connection, message, &error, -EINVAL);
1156 if (path_equal(switch_root, "/") || !path_is_absolute(switch_root))
1157 return bus_send_error_reply(connection, message, NULL, -EINVAL);
1159 if (!isempty(switch_root_init) && !path_is_absolute(switch_root_init))
1160 return bus_send_error_reply(connection, message, NULL, -EINVAL);
1162 if (m->running_as != MANAGER_SYSTEM) {
1163 dbus_set_error(&error, BUS_ERROR_NOT_SUPPORTED, "Switching root is only supported for system managers.");
1164 return bus_send_error_reply(connection, message, &error, -ENOTSUP);
1168 if (isempty(switch_root_init))
1169 k = access(switch_root, F_OK);
1173 p = strjoin(switch_root, "/", switch_root_init, NULL);
1177 k = access(p, X_OK);
1181 return bus_send_error_reply(connection, message, NULL, -errno);
1183 u = strdup(switch_root);
1187 if (!isempty(switch_root_init)) {
1188 v = strdup(switch_root_init);
1196 free(m->switch_root);
1197 free(m->switch_root_init);
1199 m->switch_root_init = v;
1201 reply = dbus_message_new_method_return(message);
1205 m->exit_code = MANAGER_SWITCH_ROOT;
1207 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "SetEnvironment")) {
1208 char **l = NULL, **e = NULL;
1210 if ((r = bus_parse_strv(message, &l)) < 0) {
1214 return bus_send_error_reply(connection, message, NULL, r);
1217 e = strv_env_merge(2, m->environment, l);
1223 if (!(reply = dbus_message_new_method_return(message))) {
1228 strv_free(m->environment);
1231 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "UnsetEnvironment")) {
1232 char **l = NULL, **e = NULL;
1234 if ((r = bus_parse_strv(message, &l)) < 0) {
1238 return bus_send_error_reply(connection, message, NULL, r);
1241 e = strv_env_delete(m->environment, 1, l);
1247 if (!(reply = dbus_message_new_method_return(message))) {
1252 strv_free(m->environment);
1255 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "UnsetAndSetEnvironment")) {
1256 char **l_set = NULL, **l_unset = NULL, **e = NULL, **f = NULL;
1257 DBusMessageIter iter;
1259 if (!dbus_message_iter_init(message, &iter))
1262 r = bus_parse_strv_iter(&iter, &l_unset);
1267 return bus_send_error_reply(connection, message, NULL, r);
1270 if (!dbus_message_iter_next(&iter)) {
1272 return bus_send_error_reply(connection, message, NULL, -EINVAL);
1275 r = bus_parse_strv_iter(&iter, &l_set);
1281 return bus_send_error_reply(connection, message, NULL, r);
1284 e = strv_env_delete(m->environment, 1, l_unset);
1292 f = strv_env_merge(2, e, l_set);
1299 if (!(reply = dbus_message_new_method_return(message))) {
1304 strv_free(m->environment);
1306 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ListUnitFiles")) {
1307 DBusMessageIter iter, sub, sub2;
1312 reply = dbus_message_new_method_return(message);
1316 h = hashmap_new(string_hash_func, string_compare_func);
1320 r = unit_file_get_list(m->running_as == MANAGER_SYSTEM ? UNIT_FILE_SYSTEM : UNIT_FILE_USER, NULL, h);
1322 unit_file_list_free(h);
1323 dbus_message_unref(reply);
1324 return bus_send_error_reply(connection, message, NULL, r);
1327 dbus_message_iter_init_append(reply, &iter);
1329 if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "(ss)", &sub)) {
1330 unit_file_list_free(h);
1334 HASHMAP_FOREACH(item, h, i) {
1337 state = unit_file_state_to_string(item->state);
1340 if (!dbus_message_iter_open_container(&sub, DBUS_TYPE_STRUCT, NULL, &sub2) ||
1341 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &item->path) ||
1342 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &state) ||
1343 !dbus_message_iter_close_container(&sub, &sub2)) {
1344 unit_file_list_free(h);
1349 unit_file_list_free(h);
1351 if (!dbus_message_iter_close_container(&iter, &sub))
1354 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "GetUnitFileState")) {
1356 UnitFileState state;
1359 if (!dbus_message_get_args(
1362 DBUS_TYPE_STRING, &name,
1364 return bus_send_error_reply(connection, message, &error, -EINVAL);
1366 state = unit_file_get_state(m->running_as == MANAGER_SYSTEM ? UNIT_FILE_SYSTEM : UNIT_FILE_USER, NULL, name);
1368 return bus_send_error_reply(connection, message, NULL, state);
1370 s = unit_file_state_to_string(state);
1373 reply = dbus_message_new_method_return(message);
1377 if (!dbus_message_append_args(
1379 DBUS_TYPE_STRING, &s,
1382 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "EnableUnitFiles") ||
1383 dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ReenableUnitFiles") ||
1384 dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "LinkUnitFiles") ||
1385 dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "PresetUnitFiles") ||
1386 dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "MaskUnitFiles")) {
1389 DBusMessageIter iter;
1390 UnitFileScope scope = m->running_as == MANAGER_SYSTEM ? UNIT_FILE_SYSTEM : UNIT_FILE_USER;
1391 UnitFileChange *changes = NULL;
1392 unsigned n_changes = 0;
1393 dbus_bool_t runtime, force;
1394 int carries_install_info = -1;
1396 if (!dbus_message_iter_init(message, &iter))
1399 r = bus_parse_strv_iter(&iter, &l);
1404 return bus_send_error_reply(connection, message, NULL, r);
1407 if (!dbus_message_iter_next(&iter) ||
1408 bus_iter_get_basic_and_next(&iter, DBUS_TYPE_BOOLEAN, &runtime, true) < 0 ||
1409 bus_iter_get_basic_and_next(&iter, DBUS_TYPE_BOOLEAN, &force, false) < 0) {
1411 return bus_send_error_reply(connection, message, NULL, -EIO);
1414 if (streq(member, "EnableUnitFiles")) {
1415 r = unit_file_enable(scope, runtime, NULL, l, force, &changes, &n_changes);
1416 carries_install_info = r;
1417 } else if (streq(member, "ReenableUnitFiles")) {
1418 r = unit_file_reenable(scope, runtime, NULL, l, force, &changes, &n_changes);
1419 carries_install_info = r;
1420 } else if (streq(member, "LinkUnitFiles"))
1421 r = unit_file_link(scope, runtime, NULL, l, force, &changes, &n_changes);
1422 else if (streq(member, "PresetUnitFiles")) {
1423 r = unit_file_preset(scope, runtime, NULL, l, force, &changes, &n_changes);
1424 carries_install_info = r;
1425 } else if (streq(member, "MaskUnitFiles"))
1426 r = unit_file_mask(scope, runtime, NULL, l, force, &changes, &n_changes);
1428 assert_not_reached("Uh? Wrong method");
1431 bus_manager_send_unit_files_changed(m);
1434 unit_file_changes_free(changes, n_changes);
1435 return bus_send_error_reply(connection, message, NULL, r);
1438 reply = message_from_file_changes(message, changes, n_changes, carries_install_info);
1439 unit_file_changes_free(changes, n_changes);
1444 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "DisableUnitFiles") ||
1445 dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "UnmaskUnitFiles")) {
1448 DBusMessageIter iter;
1449 UnitFileScope scope = m->running_as == MANAGER_SYSTEM ? UNIT_FILE_SYSTEM : UNIT_FILE_USER;
1450 UnitFileChange *changes = NULL;
1451 unsigned n_changes = 0;
1452 dbus_bool_t runtime;
1454 if (!dbus_message_iter_init(message, &iter))
1457 r = bus_parse_strv_iter(&iter, &l);
1462 return bus_send_error_reply(connection, message, NULL, r);
1465 if (!dbus_message_iter_next(&iter) ||
1466 bus_iter_get_basic_and_next(&iter, DBUS_TYPE_BOOLEAN, &runtime, false) < 0) {
1468 return bus_send_error_reply(connection, message, NULL, -EIO);
1471 if (streq(member, "DisableUnitFiles"))
1472 r = unit_file_disable(scope, runtime, NULL, l, &changes, &n_changes);
1473 else if (streq(member, "UnmaskUnitFiles"))
1474 r = unit_file_unmask(scope, runtime, NULL, l, &changes, &n_changes);
1476 assert_not_reached("Uh? Wrong method");
1479 bus_manager_send_unit_files_changed(m);
1482 unit_file_changes_free(changes, n_changes);
1483 return bus_send_error_reply(connection, message, NULL, r);
1486 reply = message_from_file_changes(message, changes, n_changes, -1);
1487 unit_file_changes_free(changes, n_changes);
1493 const BusBoundProperties bps[] = {
1494 { "org.freedesktop.systemd1.Manager", bus_systemd_properties, systemd_property_string },
1495 { "org.freedesktop.systemd1.Manager", bus_manager_properties, m },
1498 return bus_default_message_handler(connection, message, NULL, INTERFACES_LIST, bps);
1501 if (job_type != _JOB_TYPE_INVALID) {
1502 const char *name, *smode, *old_name = NULL;
1509 if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "StartUnitReplace"))
1510 b = dbus_message_get_args(
1513 DBUS_TYPE_STRING, &old_name,
1514 DBUS_TYPE_STRING, &name,
1515 DBUS_TYPE_STRING, &smode,
1518 b = dbus_message_get_args(
1521 DBUS_TYPE_STRING, &name,
1522 DBUS_TYPE_STRING, &smode,
1526 return bus_send_error_reply(connection, message, &error, -EINVAL);
1529 if (!(u = manager_get_unit(m, old_name)) ||
1531 u->job->type != JOB_START) {
1532 dbus_set_error(&error, BUS_ERROR_NO_SUCH_JOB, "No job queued for unit %s", old_name);
1533 return bus_send_error_reply(connection, message, &error, -ENOENT);
1537 if ((mode = job_mode_from_string(smode)) == _JOB_MODE_INVALID) {
1538 dbus_set_error(&error, BUS_ERROR_INVALID_JOB_MODE, "Job mode %s is invalid.", smode);
1539 return bus_send_error_reply(connection, message, &error, -EINVAL);
1542 if ((r = manager_load_unit(m, name, NULL, &error, &u)) < 0)
1543 return bus_send_error_reply(connection, message, &error, r);
1545 if (reload_if_possible && unit_can_reload(u)) {
1546 if (job_type == JOB_RESTART)
1547 job_type = JOB_RELOAD_OR_START;
1548 else if (job_type == JOB_TRY_RESTART)
1549 job_type = JOB_RELOAD;
1552 if (job_type == JOB_STOP && u->load_state == UNIT_ERROR && unit_active_state(u) == UNIT_INACTIVE) {
1553 dbus_set_error(&error, BUS_ERROR_NO_SUCH_UNIT, "Unit %s not loaded.", name);
1554 return bus_send_error_reply(connection, message, &error, -EPERM);
1557 if ((job_type == JOB_START && u->refuse_manual_start) ||
1558 (job_type == JOB_STOP && u->refuse_manual_stop) ||
1559 ((job_type == JOB_RESTART || job_type == JOB_TRY_RESTART) &&
1560 (u->refuse_manual_start || u->refuse_manual_stop))) {
1561 dbus_set_error(&error, BUS_ERROR_ONLY_BY_DEPENDENCY, "Operation refused, may be requested by dependency only.");
1562 return bus_send_error_reply(connection, message, &error, -EPERM);
1565 if ((r = manager_add_job(m, job_type, u, mode, true, &error, &j)) < 0)
1566 return bus_send_error_reply(connection, message, &error, r);
1568 cl = job_bus_client_new(connection, message_get_sender_with_fallback(message));
1572 LIST_PREPEND(JobBusClient, client, j->bus_client_list, cl);
1574 if (!(reply = dbus_message_new_method_return(message)))
1577 if (!(path = job_dbus_path(j)))
1580 if (!dbus_message_append_args(
1582 DBUS_TYPE_OBJECT_PATH, &path,
1588 if (!dbus_connection_send(connection, reply, NULL))
1591 dbus_message_unref(reply);
1596 return DBUS_HANDLER_RESULT_HANDLED;
1602 dbus_message_unref(reply);
1604 dbus_error_free(&error);
1606 return DBUS_HANDLER_RESULT_NEED_MEMORY;
1609 const DBusObjectPathVTable bus_manager_vtable = {
1610 .message_function = bus_manager_message_handler