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 " <arg name=\"dump\" type=\"s\" direction=\"out\"/>\n" \
120 " <method name=\"CreateSnapshot\">\n" \
121 " <arg name=\"name\" type=\"s\" direction=\"in\"/>\n" \
122 " <arg name=\"cleanup\" type=\"b\" direction=\"in\"/>\n" \
123 " <arg name=\"unit\" type=\"o\" direction=\"out\"/>\n" \
125 " <method name=\"Reload\"/>\n" \
126 " <method name=\"Reexecute\"/>\n" \
127 " <method name=\"Exit\"/>\n" \
128 " <method name=\"Reboot\"/>\n" \
129 " <method name=\"PowerOff\"/>\n" \
130 " <method name=\"Halt\"/>\n" \
131 " <method name=\"KExec\"/>\n" \
132 " <method name=\"SwitchRoot\">\n" \
133 " <arg name=\"new_root\" type=\"s\" direction=\"in\"/>\n" \
134 " <arg name=\"init\" type=\"s\" direction=\"in\"/>\n" \
136 " <method name=\"SetEnvironment\">\n" \
137 " <arg name=\"names\" type=\"as\" direction=\"in\"/>\n" \
139 " <method name=\"UnsetEnvironment\">\n" \
140 " <arg name=\"names\" type=\"as\" direction=\"in\"/>\n" \
142 " <method name=\"UnsetAndSetEnvironment\">\n" \
143 " <arg name=\"unset\" type=\"as\" direction=\"in\"/>\n" \
144 " <arg name=\"set\" type=\"as\" direction=\"in\"/>\n" \
146 " <method name=\"ListUnitFiles\">\n" \
147 " <arg name=\"changes\" type=\"a(ss)\" direction=\"out\"/>\n" \
149 " <method name=\"GetUnitFileState\">\n" \
150 " <arg name=\"file\" type=\"s\" direction=\"in\"/>\n" \
151 " <arg name=\"state\" type=\"s\" direction=\"out\"/>\n" \
153 " <method name=\"EnableUnitFiles\">\n" \
154 " <arg name=\"files\" type=\"as\" direction=\"in\"/>\n" \
155 " <arg name=\"runtime\" type=\"b\" direction=\"in\"/>\n" \
156 " <arg name=\"force\" type=\"b\" direction=\"in\"/>\n" \
157 " <arg name=\"carries_install_info\" type=\"b\" direction=\"out\"/>\n" \
158 " <arg name=\"changes\" type=\"a(sss)\" direction=\"out\"/>\n" \
160 " <method name=\"DisableUnitFiles\">\n" \
161 " <arg name=\"files\" type=\"as\" direction=\"in\"/>\n" \
162 " <arg name=\"runtime\" type=\"b\" direction=\"in\"/>\n" \
163 " <arg name=\"changes\" type=\"a(sss)\" direction=\"out\"/>\n" \
165 " <method name=\"ReenableUnitFiles\">\n" \
166 " <arg name=\"files\" type=\"as\" direction=\"in\"/>\n" \
167 " <arg name=\"runtime\" type=\"b\" direction=\"in\"/>\n" \
168 " <arg name=\"force\" type=\"b\" direction=\"in\"/>\n" \
169 " <arg name=\"carries_install_info\" type=\"b\" direction=\"out\"/>\n" \
170 " <arg name=\"changes\" type=\"a(sss)\" direction=\"out\"/>\n" \
172 " <method name=\"LinkUnitFiles\">\n" \
173 " <arg name=\"files\" type=\"as\" direction=\"in\"/>\n" \
174 " <arg name=\"runtime\" type=\"b\" direction=\"in\"/>\n" \
175 " <arg name=\"force\" type=\"b\" direction=\"in\"/>\n" \
176 " <arg name=\"changes\" type=\"a(sss)\" direction=\"out\"/>\n" \
178 " <method name=\"PresetUnitFiles\">\n" \
179 " <arg name=\"files\" type=\"as\" direction=\"in\"/>\n" \
180 " <arg name=\"runtime\" type=\"b\" direction=\"in\"/>\n" \
181 " <arg name=\"force\" type=\"b\" direction=\"in\"/>\n" \
182 " <arg name=\"carries_install_info\" type=\"b\" direction=\"out\"/>\n" \
183 " <arg name=\"changes\" type=\"a(sss)\" direction=\"out\"/>\n" \
185 " <method name=\"MaskUnitFiles\">\n" \
186 " <arg name=\"files\" type=\"as\" direction=\"in\"/>\n" \
187 " <arg name=\"runtime\" type=\"b\" direction=\"in\"/>\n" \
188 " <arg name=\"force\" type=\"b\" direction=\"in\"/>\n" \
189 " <arg name=\"changes\" type=\"a(sss)\" direction=\"out\"/>\n" \
191 " <method name=\"UnmaskUnitFiles\">\n" \
192 " <arg name=\"files\" type=\"as\" direction=\"in\"/>\n" \
193 " <arg name=\"runtime\" type=\"b\" direction=\"in\"/>\n" \
194 " <arg name=\"changes\" type=\"a(sss)\" direction=\"out\"/>\n" \
197 #define BUS_MANAGER_INTERFACE_SIGNALS \
198 " <signal name=\"UnitNew\">\n" \
199 " <arg name=\"id\" type=\"s\"/>\n" \
200 " <arg name=\"unit\" type=\"o\"/>\n" \
202 " <signal name=\"UnitRemoved\">\n" \
203 " <arg name=\"id\" type=\"s\"/>\n" \
204 " <arg name=\"unit\" type=\"o\"/>\n" \
206 " <signal name=\"JobNew\">\n" \
207 " <arg name=\"id\" type=\"u\"/>\n" \
208 " <arg name=\"job\" type=\"o\"/>\n" \
209 " <arg name=\"unit\" type=\"s\"/>\n" \
211 " <signal name=\"JobRemoved\">\n" \
212 " <arg name=\"id\" type=\"u\"/>\n" \
213 " <arg name=\"job\" type=\"o\"/>\n" \
214 " <arg name=\"unit\" type=\"s\"/>\n" \
215 " <arg name=\"result\" type=\"s\"/>\n" \
217 " <signal name=\"StartupFinished\">\n" \
218 " <arg name=\"kernel\" type=\"t\"/>\n" \
219 " <arg name=\"initrd\" type=\"t\"/>\n" \
220 " <arg name=\"userspace\" type=\"t\"/>\n" \
221 " <arg name=\"total\" type=\"t\"/>\n" \
223 " <signal name=\"UnitFilesChanged\"/>\n"
225 #define BUS_MANAGER_INTERFACE_PROPERTIES_GENERAL \
226 " <property name=\"Version\" type=\"s\" access=\"read\"/>\n" \
227 " <property name=\"Distribution\" type=\"s\" access=\"read\"/>\n" \
228 " <property name=\"Features\" type=\"s\" access=\"read\"/>\n" \
229 " <property name=\"Tainted\" type=\"s\" access=\"read\"/>\n" \
230 " <property name=\"InitRDTimestamp\" type=\"t\" access=\"read\"/>\n" \
231 " <property name=\"InitRDTimestampMonotonic\" type=\"t\" access=\"read\"/>\n" \
232 " <property name=\"StartupTimestamp\" type=\"t\" access=\"read\"/>\n" \
233 " <property name=\"StartupTimestampMonotonic\" type=\"t\" access=\"read\"/>\n" \
234 " <property name=\"FinishTimestamp\" type=\"t\" access=\"read\"/>\n" \
235 " <property name=\"FinishTimestampMonotonic\" type=\"t\" access=\"read\"/>\n" \
236 " <property name=\"LogLevel\" type=\"s\" access=\"readwrite\"/>\n" \
237 " <property name=\"LogTarget\" type=\"s\" access=\"readwrite\"/>\n" \
238 " <property name=\"NNames\" type=\"u\" access=\"read\"/>\n" \
239 " <property name=\"NJobs\" type=\"u\" access=\"read\"/>\n" \
240 " <property name=\"NInstalledJobs\" type=\"u\" access=\"read\"/>\n" \
241 " <property name=\"NFailedJobs\" type=\"u\" access=\"read\"/>\n" \
242 " <property name=\"Progress\" type=\"d\" access=\"read\"/>\n" \
243 " <property name=\"Environment\" type=\"as\" access=\"read\"/>\n" \
244 " <property name=\"ConfirmSpawn\" type=\"b\" access=\"read\"/>\n" \
245 " <property name=\"ShowStatus\" type=\"b\" access=\"read\"/>\n" \
246 " <property name=\"UnitPath\" type=\"as\" access=\"read\"/>\n" \
247 " <property name=\"ControlGroupHierarchy\" type=\"s\" access=\"read\"/>\n" \
248 " <property name=\"DefaultControllers\" type=\"as\" access=\"read\"/>\n" \
249 " <property name=\"DefaultStandardOutput\" type=\"s\" access=\"read\"/>\n" \
250 " <property name=\"DefaultStandardError\" type=\"s\" access=\"read\"/>\n" \
251 " <property name=\"RuntimeWatchdogUSec\" type=\"s\" access=\"readwrite\"/>\n" \
252 " <property name=\"ShutdownWatchdogUSec\" type=\"s\" access=\"readwrite\"/>\n"
254 #define BUS_MANAGER_INTERFACE_END \
257 #define BUS_MANAGER_INTERFACE \
258 BUS_MANAGER_INTERFACE_BEGIN \
259 BUS_MANAGER_INTERFACE_METHODS \
260 BUS_MANAGER_INTERFACE_SIGNALS \
261 BUS_MANAGER_INTERFACE_PROPERTIES_GENERAL \
262 BUS_MANAGER_INTERFACE_END
264 #define INTROSPECTION_BEGIN \
265 DBUS_INTROSPECT_1_0_XML_DOCTYPE_DECL_NODE \
267 BUS_MANAGER_INTERFACE \
268 BUS_PROPERTIES_INTERFACE \
270 BUS_INTROSPECTABLE_INTERFACE
272 #define INTROSPECTION_END \
275 #define INTERFACES_LIST \
276 BUS_GENERIC_INTERFACES_LIST \
277 "org.freedesktop.systemd1.Manager\0"
279 const char bus_manager_interface[] _introspect_("Manager") = BUS_MANAGER_INTERFACE;
281 static DEFINE_BUS_PROPERTY_APPEND_ENUM(bus_manager_append_exec_output, exec_output, ExecOutput);
283 static int bus_manager_append_tainted(DBusMessageIter *i, const char *property, void *data) {
286 char buf[LINE_MAX] = "", *e = buf, *p = NULL;
293 e = stpcpy(e, "split-usr:");
295 if (readlink_malloc("/etc/mtab", &p) < 0)
296 e = stpcpy(e, "mtab-not-symlink:");
300 if (access("/proc/cgroups", F_OK) < 0)
301 e = stpcpy(e, "cgroups-missing:");
303 if (hwclock_is_localtime() > 0)
304 e = stpcpy(e, "local-hwclock:");
306 /* remove the last ':' */
312 if (!dbus_message_iter_append_basic(i, DBUS_TYPE_STRING, &t))
318 static int bus_manager_append_log_target(DBusMessageIter *i, const char *property, void *data) {
324 t = log_target_to_string(log_get_target());
326 if (!dbus_message_iter_append_basic(i, DBUS_TYPE_STRING, &t))
332 static int bus_manager_set_log_target(DBusMessageIter *i, const char *property, void *data) {
338 dbus_message_iter_get_basic(i, &t);
340 return log_set_target_from_string(t);
343 static int bus_manager_append_log_level(DBusMessageIter *i, const char *property, void *data) {
349 t = log_level_to_string(log_get_max_level());
351 if (!dbus_message_iter_append_basic(i, DBUS_TYPE_STRING, &t))
357 static int bus_manager_set_log_level(DBusMessageIter *i, const char *property, void *data) {
363 dbus_message_iter_get_basic(i, &t);
365 return log_set_max_level_from_string(t);
368 static int bus_manager_append_n_names(DBusMessageIter *i, const char *property, void *data) {
376 u = hashmap_size(m->units);
378 if (!dbus_message_iter_append_basic(i, DBUS_TYPE_UINT32, &u))
384 static int bus_manager_append_n_jobs(DBusMessageIter *i, const char *property, void *data) {
392 u = hashmap_size(m->jobs);
394 if (!dbus_message_iter_append_basic(i, DBUS_TYPE_UINT32, &u))
400 static int bus_manager_append_progress(DBusMessageIter *i, const char *property, void *data) {
408 if (dual_timestamp_is_set(&m->finish_timestamp))
411 d = 1.0 - ((double) hashmap_size(m->jobs) / (double) m->n_installed_jobs);
413 if (!dbus_message_iter_append_basic(i, DBUS_TYPE_DOUBLE, &d))
419 static const char *message_get_sender_with_fallback(DBusMessage *m) {
424 if ((s = dbus_message_get_sender(m)))
427 /* When the message came in from a direct connection the
428 * message will have no sender. We fix that here. */
433 static DBusMessage *message_from_file_changes(
435 UnitFileChange *changes,
437 int carries_install_info) {
439 DBusMessageIter iter, sub, sub2;
443 reply = dbus_message_new_method_return(m);
447 dbus_message_iter_init_append(reply, &iter);
449 if (carries_install_info >= 0) {
452 b = !!carries_install_info;
453 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &b))
457 if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "(sss)", &sub))
460 for (i = 0; i < n_changes; i++) {
461 const char *type, *path, *source;
463 type = unit_file_change_type_to_string(changes[i].type);
464 path = strempty(changes[i].path);
465 source = strempty(changes[i].source);
467 if (!dbus_message_iter_open_container(&sub, DBUS_TYPE_STRUCT, NULL, &sub2) ||
468 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &type) ||
469 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &path) ||
470 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &source) ||
471 !dbus_message_iter_close_container(&sub, &sub2))
475 if (!dbus_message_iter_close_container(&iter, &sub))
481 dbus_message_unref(reply);
485 static int bus_manager_send_unit_files_changed(Manager *m) {
489 s = dbus_message_new_signal("/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", "UnitFilesChanged");
493 r = bus_broadcast(m, s);
494 dbus_message_unref(s);
499 static int bus_manager_set_runtime_watchdog_usec(DBusMessageIter *i, const char *property, void *data) {
505 dbus_message_iter_get_basic(i, t);
507 return watchdog_set_timeout(t);
510 static const char systemd_property_string[] =
515 static const BusProperty bus_systemd_properties[] = {
516 { "Version", bus_property_append_string, "s", 0 },
517 { "Distribution", bus_property_append_string, "s", sizeof(PACKAGE_STRING) },
518 { "Features", bus_property_append_string, "s", sizeof(PACKAGE_STRING) + sizeof(DISTRIBUTION) },
522 static const BusProperty bus_manager_properties[] = {
523 { "Tainted", bus_manager_append_tainted, "s", 0 },
524 { "InitRDTimestamp", bus_property_append_uint64, "t", offsetof(Manager, initrd_timestamp.realtime) },
525 { "InitRDTimestampMonotonic", bus_property_append_uint64, "t", offsetof(Manager, initrd_timestamp.monotonic) },
526 { "StartupTimestamp", bus_property_append_uint64, "t", offsetof(Manager, startup_timestamp.realtime) },
527 { "StartupTimestampMonotonic", bus_property_append_uint64, "t", offsetof(Manager, startup_timestamp.monotonic) },
528 { "FinishTimestamp", bus_property_append_uint64, "t", offsetof(Manager, finish_timestamp.realtime) },
529 { "FinishTimestampMonotonic", bus_property_append_uint64, "t", offsetof(Manager, finish_timestamp.monotonic) },
530 { "LogLevel", bus_manager_append_log_level, "s", 0, false, bus_manager_set_log_level },
531 { "LogTarget", bus_manager_append_log_target, "s", 0, false, bus_manager_set_log_target },
532 { "NNames", bus_manager_append_n_names, "u", 0 },
533 { "NJobs", bus_manager_append_n_jobs, "u", 0 },
534 { "NInstalledJobs",bus_property_append_uint32, "u", offsetof(Manager, n_installed_jobs) },
535 { "NFailedJobs", bus_property_append_uint32, "u", offsetof(Manager, n_failed_jobs) },
536 { "Progress", bus_manager_append_progress, "d", 0 },
537 { "Environment", bus_property_append_strv, "as", offsetof(Manager, environment), true },
538 { "ConfirmSpawn", bus_property_append_bool, "b", offsetof(Manager, confirm_spawn) },
539 { "ShowStatus", bus_property_append_bool, "b", offsetof(Manager, show_status) },
540 { "UnitPath", bus_property_append_strv, "as", offsetof(Manager, lookup_paths.unit_path), true },
541 { "ControlGroupHierarchy", bus_property_append_string, "s", offsetof(Manager, cgroup_hierarchy), true },
542 { "DefaultControllers", bus_property_append_strv, "as", offsetof(Manager, default_controllers), true },
543 { "DefaultStandardOutput", bus_manager_append_exec_output, "s", offsetof(Manager, default_std_output) },
544 { "DefaultStandardError", bus_manager_append_exec_output, "s", offsetof(Manager, default_std_error) },
545 { "RuntimeWatchdogUSec", bus_property_append_usec, "t", offsetof(Manager, runtime_watchdog), false, bus_manager_set_runtime_watchdog_usec },
546 { "ShutdownWatchdogUSec", bus_property_append_usec, "t", offsetof(Manager, shutdown_watchdog), false, bus_property_set_usec },
550 static DBusHandlerResult bus_manager_message_handler(DBusConnection *connection, DBusMessage *message, void *data) {
555 DBusMessage *reply = NULL;
557 JobType job_type = _JOB_TYPE_INVALID;
558 bool reload_if_possible = false;
565 dbus_error_init(&error);
567 member = dbus_message_get_member(message);
569 if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "GetUnit")) {
573 if (!dbus_message_get_args(
576 DBUS_TYPE_STRING, &name,
578 return bus_send_error_reply(connection, message, &error, -EINVAL);
580 if (!(u = manager_get_unit(m, name))) {
581 dbus_set_error(&error, BUS_ERROR_NO_SUCH_UNIT, "Unit %s is not loaded.", name);
582 return bus_send_error_reply(connection, message, &error, -ENOENT);
585 if (!(reply = dbus_message_new_method_return(message)))
588 if (!(path = unit_dbus_path(u)))
591 if (!dbus_message_append_args(
593 DBUS_TYPE_OBJECT_PATH, &path,
596 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "GetUnitByPID")) {
600 if (!dbus_message_get_args(
603 DBUS_TYPE_UINT32, &pid,
605 return bus_send_error_reply(connection, message, &error, -EINVAL);
607 if (!(u = cgroup_unit_by_pid(m, (pid_t) pid))) {
608 dbus_set_error(&error, BUS_ERROR_NO_SUCH_UNIT, "No unit for PID %lu is loaded.", (unsigned long) pid);
609 return bus_send_error_reply(connection, message, &error, -ENOENT);
612 if (!(reply = dbus_message_new_method_return(message)))
615 if (!(path = unit_dbus_path(u)))
618 if (!dbus_message_append_args(
620 DBUS_TYPE_OBJECT_PATH, &path,
623 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "LoadUnit")) {
627 if (!dbus_message_get_args(
630 DBUS_TYPE_STRING, &name,
632 return bus_send_error_reply(connection, message, &error, -EINVAL);
634 if ((r = manager_load_unit(m, name, NULL, &error, &u)) < 0)
635 return bus_send_error_reply(connection, message, &error, r);
637 if (!(reply = dbus_message_new_method_return(message)))
640 if (!(path = unit_dbus_path(u)))
643 if (!dbus_message_append_args(
645 DBUS_TYPE_OBJECT_PATH, &path,
649 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "StartUnit"))
650 job_type = JOB_START;
651 else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "StartUnitReplace"))
652 job_type = JOB_START;
653 else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "StopUnit"))
655 else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ReloadUnit"))
656 job_type = JOB_RELOAD;
657 else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "RestartUnit"))
658 job_type = JOB_RESTART;
659 else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "TryRestartUnit"))
660 job_type = JOB_TRY_RESTART;
661 else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ReloadOrRestartUnit")) {
662 reload_if_possible = true;
663 job_type = JOB_RESTART;
664 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ReloadOrTryRestartUnit")) {
665 reload_if_possible = true;
666 job_type = JOB_TRY_RESTART;
667 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "KillUnit")) {
668 const char *name, *swho, *smode;
674 if (!dbus_message_get_args(
677 DBUS_TYPE_STRING, &name,
678 DBUS_TYPE_STRING, &swho,
679 DBUS_TYPE_STRING, &smode,
680 DBUS_TYPE_INT32, &signo,
682 return bus_send_error_reply(connection, message, &error, -EINVAL);
687 who = kill_who_from_string(swho);
689 return bus_send_error_reply(connection, message, &error, -EINVAL);
693 mode = KILL_CONTROL_GROUP;
695 mode = kill_mode_from_string(smode);
697 return bus_send_error_reply(connection, message, &error, -EINVAL);
700 if (signo <= 0 || signo >= _NSIG)
701 return bus_send_error_reply(connection, message, &error, -EINVAL);
703 if (!(u = manager_get_unit(m, name))) {
704 dbus_set_error(&error, BUS_ERROR_NO_SUCH_UNIT, "Unit %s is not loaded.", name);
705 return bus_send_error_reply(connection, message, &error, -ENOENT);
708 if ((r = unit_kill(u, who, mode, signo, &error)) < 0)
709 return bus_send_error_reply(connection, message, &error, r);
711 if (!(reply = dbus_message_new_method_return(message)))
714 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "GetJob")) {
718 if (!dbus_message_get_args(
721 DBUS_TYPE_UINT32, &id,
723 return bus_send_error_reply(connection, message, &error, -EINVAL);
725 if (!(j = manager_get_job(m, id))) {
726 dbus_set_error(&error, BUS_ERROR_NO_SUCH_JOB, "Job %u does not exist.", (unsigned) id);
727 return bus_send_error_reply(connection, message, &error, -ENOENT);
730 if (!(reply = dbus_message_new_method_return(message)))
733 if (!(path = job_dbus_path(j)))
736 if (!dbus_message_append_args(
738 DBUS_TYPE_OBJECT_PATH, &path,
742 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ClearJobs")) {
744 manager_clear_jobs(m);
746 if (!(reply = dbus_message_new_method_return(message)))
749 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ResetFailed")) {
751 manager_reset_failed(m);
753 if (!(reply = dbus_message_new_method_return(message)))
756 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ResetFailedUnit")) {
760 if (!dbus_message_get_args(
763 DBUS_TYPE_STRING, &name,
765 return bus_send_error_reply(connection, message, &error, -EINVAL);
767 if (!(u = manager_get_unit(m, name))) {
768 dbus_set_error(&error, BUS_ERROR_NO_SUCH_UNIT, "Unit %s is not loaded.", name);
769 return bus_send_error_reply(connection, message, &error, -ENOENT);
772 unit_reset_failed(u);
774 if (!(reply = dbus_message_new_method_return(message)))
777 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ListUnits")) {
778 DBusMessageIter iter, sub;
783 if (!(reply = dbus_message_new_method_return(message)))
786 dbus_message_iter_init_append(reply, &iter);
788 if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "(ssssssouso)", &sub))
791 HASHMAP_FOREACH_KEY(u, k, m->units, i) {
792 char *u_path, *j_path;
793 const char *description, *load_state, *active_state, *sub_state, *sjob_type, *following;
794 DBusMessageIter sub2;
801 if (!dbus_message_iter_open_container(&sub, DBUS_TYPE_STRUCT, NULL, &sub2))
804 description = unit_description(u);
805 load_state = unit_load_state_to_string(u->load_state);
806 active_state = unit_active_state_to_string(unit_active_state(u));
807 sub_state = unit_sub_state_to_string(u);
809 f = unit_following(u);
810 following = f ? f->id : "";
812 if (!(u_path = unit_dbus_path(u)))
816 job_id = (uint32_t) u->job->id;
818 if (!(j_path = job_dbus_path(u->job))) {
823 sjob_type = job_type_to_string(u->job->type);
830 if (!dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &u->id) ||
831 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &description) ||
832 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &load_state) ||
833 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &active_state) ||
834 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &sub_state) ||
835 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &following) ||
836 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_OBJECT_PATH, &u_path) ||
837 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_UINT32, &job_id) ||
838 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &sjob_type) ||
839 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_OBJECT_PATH, &j_path)) {
850 if (!dbus_message_iter_close_container(&sub, &sub2))
854 if (!dbus_message_iter_close_container(&iter, &sub))
857 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ListJobs")) {
858 DBusMessageIter iter, sub;
862 if (!(reply = dbus_message_new_method_return(message)))
865 dbus_message_iter_init_append(reply, &iter);
867 if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "(usssoo)", &sub))
870 HASHMAP_FOREACH(j, m->jobs, i) {
871 char *u_path, *j_path;
872 const char *state, *type;
874 DBusMessageIter sub2;
876 if (!dbus_message_iter_open_container(&sub, DBUS_TYPE_STRUCT, NULL, &sub2))
879 id = (uint32_t) j->id;
880 state = job_state_to_string(j->state);
881 type = job_type_to_string(j->type);
883 if (!(j_path = job_dbus_path(j)))
886 if (!(u_path = unit_dbus_path(j->unit))) {
891 if (!dbus_message_iter_append_basic(&sub2, DBUS_TYPE_UINT32, &id) ||
892 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &j->unit->id) ||
893 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &type) ||
894 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &state) ||
895 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_OBJECT_PATH, &j_path) ||
896 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_OBJECT_PATH, &u_path)) {
905 if (!dbus_message_iter_close_container(&sub, &sub2))
909 if (!dbus_message_iter_close_container(&iter, &sub))
912 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "Subscribe")) {
916 if (!(s = BUS_CONNECTION_SUBSCRIBED(m, connection))) {
917 if (!(s = set_new(string_hash_func, string_compare_func)))
920 if (!(dbus_connection_set_data(connection, m->subscribed_data_slot, s, NULL))) {
926 if (!(client = strdup(message_get_sender_with_fallback(message))))
929 if ((r = set_put(s, client)) < 0) {
931 return bus_send_error_reply(connection, message, NULL, r);
934 if (!(reply = dbus_message_new_method_return(message)))
937 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "Unsubscribe")) {
940 if (!(client = set_remove(BUS_CONNECTION_SUBSCRIBED(m, connection), (char*) message_get_sender_with_fallback(message)))) {
941 dbus_set_error(&error, BUS_ERROR_NOT_SUBSCRIBED, "Client is not subscribed.");
942 return bus_send_error_reply(connection, message, &error, -ENOENT);
947 if (!(reply = dbus_message_new_method_return(message)))
950 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "Dump")) {
955 if (!(reply = dbus_message_new_method_return(message)))
958 if (!(f = open_memstream(&dump, &size)))
961 manager_dump_units(m, f, NULL);
962 manager_dump_jobs(m, f, NULL);
972 if (!dbus_message_append_args(reply, DBUS_TYPE_STRING, &dump, DBUS_TYPE_INVALID)) {
978 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "CreateSnapshot")) {
983 if (!dbus_message_get_args(
986 DBUS_TYPE_STRING, &name,
987 DBUS_TYPE_BOOLEAN, &cleanup,
989 return bus_send_error_reply(connection, message, &error, -EINVAL);
991 if (name && name[0] == 0)
994 if ((r = snapshot_create(m, name, cleanup, &error, &s)) < 0)
995 return bus_send_error_reply(connection, message, &error, r);
997 if (!(reply = dbus_message_new_method_return(message)))
1000 if (!(path = unit_dbus_path(UNIT(s))))
1003 if (!dbus_message_append_args(
1005 DBUS_TYPE_OBJECT_PATH, &path,
1009 } else if (dbus_message_is_method_call(message, "org.freedesktop.DBus.Introspectable", "Introspect")) {
1010 char *introspection = NULL;
1018 if (!(reply = dbus_message_new_method_return(message)))
1021 /* We roll our own introspection code here, instead of
1022 * relying on bus_default_message_handler() because we
1023 * need to generate our introspection string
1026 if (!(f = open_memstream(&introspection, &size)))
1029 fputs(INTROSPECTION_BEGIN, f);
1031 HASHMAP_FOREACH_KEY(u, k, m->units, i) {
1037 if (!(p = bus_path_escape(k))) {
1039 free(introspection);
1043 fprintf(f, "<node name=\"unit/%s\"/>", p);
1047 HASHMAP_FOREACH(j, m->jobs, i)
1048 fprintf(f, "<node name=\"job/%lu\"/>", (unsigned long) j->id);
1050 fputs(INTROSPECTION_END, f);
1054 free(introspection);
1063 if (!dbus_message_append_args(reply, DBUS_TYPE_STRING, &introspection, DBUS_TYPE_INVALID)) {
1064 free(introspection);
1068 free(introspection);
1070 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "Reload")) {
1072 assert(!m->queued_message);
1074 /* Instead of sending the reply back right away, we
1075 * just remember that we need to and then send it
1076 * after the reload is finished. That way the caller
1077 * knows when the reload finished. */
1079 if (!(m->queued_message = dbus_message_new_method_return(message)))
1082 m->queued_message_connection = connection;
1083 m->exit_code = MANAGER_RELOAD;
1085 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "Reexecute")) {
1087 /* We don't send a reply back here, the client should
1088 * just wait for us disconnecting. */
1090 m->exit_code = MANAGER_REEXECUTE;
1092 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "Exit")) {
1094 if (m->running_as == MANAGER_SYSTEM) {
1095 dbus_set_error(&error, BUS_ERROR_NOT_SUPPORTED, "Exit is only supported for user service managers.");
1096 return bus_send_error_reply(connection, message, &error, -ENOTSUP);
1099 if (!(reply = dbus_message_new_method_return(message)))
1102 m->exit_code = MANAGER_EXIT;
1104 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "Reboot")) {
1106 if (m->running_as != MANAGER_SYSTEM) {
1107 dbus_set_error(&error, BUS_ERROR_NOT_SUPPORTED, "Reboot is only supported for system managers.");
1108 return bus_send_error_reply(connection, message, &error, -ENOTSUP);
1111 if (!(reply = dbus_message_new_method_return(message)))
1114 m->exit_code = MANAGER_REBOOT;
1116 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "PowerOff")) {
1118 if (m->running_as != MANAGER_SYSTEM) {
1119 dbus_set_error(&error, BUS_ERROR_NOT_SUPPORTED, "Powering off is only supported for system managers.");
1120 return bus_send_error_reply(connection, message, &error, -ENOTSUP);
1123 if (!(reply = dbus_message_new_method_return(message)))
1126 m->exit_code = MANAGER_POWEROFF;
1128 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "Halt")) {
1130 if (m->running_as != MANAGER_SYSTEM) {
1131 dbus_set_error(&error, BUS_ERROR_NOT_SUPPORTED, "Halting is only supported for system managers.");
1132 return bus_send_error_reply(connection, message, &error, -ENOTSUP);
1135 if (!(reply = dbus_message_new_method_return(message)))
1138 m->exit_code = MANAGER_HALT;
1140 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "KExec")) {
1142 if (m->running_as != MANAGER_SYSTEM) {
1143 dbus_set_error(&error, BUS_ERROR_NOT_SUPPORTED, "kexec is only supported for system managers.");
1144 return bus_send_error_reply(connection, message, &error, -ENOTSUP);
1147 if (!(reply = dbus_message_new_method_return(message)))
1150 m->exit_code = MANAGER_KEXEC;
1152 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "SwitchRoot")) {
1153 const char *switch_root, *switch_root_init;
1157 if (!dbus_message_get_args(
1160 DBUS_TYPE_STRING, &switch_root,
1161 DBUS_TYPE_STRING, &switch_root_init,
1163 return bus_send_error_reply(connection, message, &error, -EINVAL);
1165 if (path_equal(switch_root, "/") || !path_is_absolute(switch_root))
1166 return bus_send_error_reply(connection, message, NULL, -EINVAL);
1168 if (!isempty(switch_root_init) && !path_is_absolute(switch_root_init))
1169 return bus_send_error_reply(connection, message, NULL, -EINVAL);
1171 if (m->running_as != MANAGER_SYSTEM) {
1172 dbus_set_error(&error, BUS_ERROR_NOT_SUPPORTED, "Switching root is only supported for system managers.");
1173 return bus_send_error_reply(connection, message, &error, -ENOTSUP);
1177 if (isempty(switch_root_init))
1178 k = access(switch_root, F_OK);
1182 p = join(switch_root, "/", switch_root_init, NULL);
1186 k = access(p, X_OK);
1190 return bus_send_error_reply(connection, message, NULL, -errno);
1192 u = strdup(switch_root);
1196 if (!isempty(switch_root_init)) {
1197 v = strdup(switch_root_init);
1205 free(m->switch_root);
1206 free(m->switch_root_init);
1208 m->switch_root_init = v;
1210 reply = dbus_message_new_method_return(message);
1214 m->exit_code = MANAGER_SWITCH_ROOT;
1216 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "SetEnvironment")) {
1217 char **l = NULL, **e = NULL;
1219 if ((r = bus_parse_strv(message, &l)) < 0) {
1223 return bus_send_error_reply(connection, message, NULL, r);
1226 e = strv_env_merge(2, m->environment, l);
1232 if (!(reply = dbus_message_new_method_return(message))) {
1237 strv_free(m->environment);
1240 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "UnsetEnvironment")) {
1241 char **l = NULL, **e = NULL;
1243 if ((r = bus_parse_strv(message, &l)) < 0) {
1247 return bus_send_error_reply(connection, message, NULL, r);
1250 e = strv_env_delete(m->environment, 1, l);
1256 if (!(reply = dbus_message_new_method_return(message))) {
1261 strv_free(m->environment);
1264 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "UnsetAndSetEnvironment")) {
1265 char **l_set = NULL, **l_unset = NULL, **e = NULL, **f = NULL;
1266 DBusMessageIter iter;
1268 if (!dbus_message_iter_init(message, &iter))
1271 r = bus_parse_strv_iter(&iter, &l_unset);
1276 return bus_send_error_reply(connection, message, NULL, r);
1279 if (!dbus_message_iter_next(&iter)) {
1281 return bus_send_error_reply(connection, message, NULL, -EINVAL);
1284 r = bus_parse_strv_iter(&iter, &l_set);
1290 return bus_send_error_reply(connection, message, NULL, r);
1293 e = strv_env_delete(m->environment, 1, l_unset);
1301 f = strv_env_merge(2, e, l_set);
1308 if (!(reply = dbus_message_new_method_return(message))) {
1313 strv_free(m->environment);
1315 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ListUnitFiles")) {
1316 DBusMessageIter iter, sub, sub2;
1321 reply = dbus_message_new_method_return(message);
1325 h = hashmap_new(string_hash_func, string_compare_func);
1329 r = unit_file_get_list(m->running_as == MANAGER_SYSTEM ? UNIT_FILE_SYSTEM : UNIT_FILE_USER, NULL, h);
1331 unit_file_list_free(h);
1332 dbus_message_unref(reply);
1333 return bus_send_error_reply(connection, message, NULL, r);
1336 dbus_message_iter_init_append(reply, &iter);
1338 if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "(ss)", &sub)) {
1339 unit_file_list_free(h);
1343 HASHMAP_FOREACH(item, h, i) {
1346 state = unit_file_state_to_string(item->state);
1349 if (!dbus_message_iter_open_container(&sub, DBUS_TYPE_STRUCT, NULL, &sub2) ||
1350 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &item->path) ||
1351 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &state) ||
1352 !dbus_message_iter_close_container(&sub, &sub2)) {
1353 unit_file_list_free(h);
1358 unit_file_list_free(h);
1360 if (!dbus_message_iter_close_container(&iter, &sub))
1363 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "GetUnitFileState")) {
1365 UnitFileState state;
1368 if (!dbus_message_get_args(
1371 DBUS_TYPE_STRING, &name,
1373 return bus_send_error_reply(connection, message, &error, -EINVAL);
1375 state = unit_file_get_state(m->running_as == MANAGER_SYSTEM ? UNIT_FILE_SYSTEM : UNIT_FILE_USER, NULL, name);
1377 return bus_send_error_reply(connection, message, NULL, state);
1379 s = unit_file_state_to_string(state);
1382 reply = dbus_message_new_method_return(message);
1386 if (!dbus_message_append_args(
1388 DBUS_TYPE_STRING, &s,
1391 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "EnableUnitFiles") ||
1392 dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ReenableUnitFiles") ||
1393 dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "LinkUnitFiles") ||
1394 dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "PresetUnitFiles") ||
1395 dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "MaskUnitFiles")) {
1398 DBusMessageIter iter;
1399 UnitFileScope scope = m->running_as == MANAGER_SYSTEM ? UNIT_FILE_SYSTEM : UNIT_FILE_USER;
1400 UnitFileChange *changes = NULL;
1401 unsigned n_changes = 0;
1402 dbus_bool_t runtime, force;
1403 int carries_install_info = -1;
1405 if (!dbus_message_iter_init(message, &iter))
1408 r = bus_parse_strv_iter(&iter, &l);
1413 return bus_send_error_reply(connection, message, NULL, r);
1416 if (!dbus_message_iter_next(&iter) ||
1417 bus_iter_get_basic_and_next(&iter, DBUS_TYPE_BOOLEAN, &runtime, true) < 0 ||
1418 bus_iter_get_basic_and_next(&iter, DBUS_TYPE_BOOLEAN, &force, false) < 0) {
1420 return bus_send_error_reply(connection, message, NULL, -EIO);
1423 if (streq(member, "EnableUnitFiles")) {
1424 r = unit_file_enable(scope, runtime, NULL, l, force, &changes, &n_changes);
1425 carries_install_info = r;
1426 } else if (streq(member, "ReenableUnitFiles")) {
1427 r = unit_file_reenable(scope, runtime, NULL, l, force, &changes, &n_changes);
1428 carries_install_info = r;
1429 } else if (streq(member, "LinkUnitFiles"))
1430 r = unit_file_link(scope, runtime, NULL, l, force, &changes, &n_changes);
1431 else if (streq(member, "PresetUnitFiles")) {
1432 r = unit_file_preset(scope, runtime, NULL, l, force, &changes, &n_changes);
1433 carries_install_info = r;
1434 } else if (streq(member, "MaskUnitFiles"))
1435 r = unit_file_mask(scope, runtime, NULL, l, force, &changes, &n_changes);
1437 assert_not_reached("Uh? Wrong method");
1440 bus_manager_send_unit_files_changed(m);
1443 unit_file_changes_free(changes, n_changes);
1444 return bus_send_error_reply(connection, message, NULL, r);
1447 reply = message_from_file_changes(message, changes, n_changes, carries_install_info);
1448 unit_file_changes_free(changes, n_changes);
1453 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "DisableUnitFiles") ||
1454 dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "UnmaskUnitFiles")) {
1457 DBusMessageIter iter;
1458 UnitFileScope scope = m->running_as == MANAGER_SYSTEM ? UNIT_FILE_SYSTEM : UNIT_FILE_USER;
1459 UnitFileChange *changes = NULL;
1460 unsigned n_changes = 0;
1461 dbus_bool_t runtime;
1463 if (!dbus_message_iter_init(message, &iter))
1466 r = bus_parse_strv_iter(&iter, &l);
1471 return bus_send_error_reply(connection, message, NULL, r);
1474 if (!dbus_message_iter_next(&iter) ||
1475 bus_iter_get_basic_and_next(&iter, DBUS_TYPE_BOOLEAN, &runtime, false) < 0) {
1477 return bus_send_error_reply(connection, message, NULL, -EIO);
1480 if (streq(member, "DisableUnitFiles"))
1481 r = unit_file_disable(scope, runtime, NULL, l, &changes, &n_changes);
1482 else if (streq(member, "UnmaskUnitFiles"))
1483 r = unit_file_unmask(scope, runtime, NULL, l, &changes, &n_changes);
1485 assert_not_reached("Uh? Wrong method");
1488 bus_manager_send_unit_files_changed(m);
1491 unit_file_changes_free(changes, n_changes);
1492 return bus_send_error_reply(connection, message, NULL, r);
1495 reply = message_from_file_changes(message, changes, n_changes, -1);
1496 unit_file_changes_free(changes, n_changes);
1502 const BusBoundProperties bps[] = {
1503 { "org.freedesktop.systemd1.Manager", bus_systemd_properties, systemd_property_string },
1504 { "org.freedesktop.systemd1.Manager", bus_manager_properties, m },
1507 return bus_default_message_handler(connection, message, NULL, INTERFACES_LIST, bps);
1510 if (job_type != _JOB_TYPE_INVALID) {
1511 const char *name, *smode, *old_name = NULL;
1518 if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "StartUnitReplace"))
1519 b = dbus_message_get_args(
1522 DBUS_TYPE_STRING, &old_name,
1523 DBUS_TYPE_STRING, &name,
1524 DBUS_TYPE_STRING, &smode,
1527 b = dbus_message_get_args(
1530 DBUS_TYPE_STRING, &name,
1531 DBUS_TYPE_STRING, &smode,
1535 return bus_send_error_reply(connection, message, &error, -EINVAL);
1538 if (!(u = manager_get_unit(m, old_name)) ||
1540 u->job->type != JOB_START) {
1541 dbus_set_error(&error, BUS_ERROR_NO_SUCH_JOB, "No job queued for unit %s", old_name);
1542 return bus_send_error_reply(connection, message, &error, -ENOENT);
1546 if ((mode = job_mode_from_string(smode)) == _JOB_MODE_INVALID) {
1547 dbus_set_error(&error, BUS_ERROR_INVALID_JOB_MODE, "Job mode %s is invalid.", smode);
1548 return bus_send_error_reply(connection, message, &error, -EINVAL);
1551 if ((r = manager_load_unit(m, name, NULL, &error, &u)) < 0)
1552 return bus_send_error_reply(connection, message, &error, r);
1554 if (reload_if_possible && unit_can_reload(u)) {
1555 if (job_type == JOB_RESTART)
1556 job_type = JOB_RELOAD_OR_START;
1557 else if (job_type == JOB_TRY_RESTART)
1558 job_type = JOB_RELOAD;
1561 if (job_type == JOB_STOP && u->load_state == UNIT_ERROR && unit_active_state(u) == UNIT_INACTIVE) {
1562 dbus_set_error(&error, BUS_ERROR_NO_SUCH_UNIT, "Unit %s not loaded.", name);
1563 return bus_send_error_reply(connection, message, &error, -EPERM);
1566 if ((job_type == JOB_START && u->refuse_manual_start) ||
1567 (job_type == JOB_STOP && u->refuse_manual_stop) ||
1568 ((job_type == JOB_RESTART || job_type == JOB_TRY_RESTART) &&
1569 (u->refuse_manual_start || u->refuse_manual_stop))) {
1570 dbus_set_error(&error, BUS_ERROR_ONLY_BY_DEPENDENCY, "Operation refused, may be requested by dependency only.");
1571 return bus_send_error_reply(connection, message, &error, -EPERM);
1574 if ((r = manager_add_job(m, job_type, u, mode, true, &error, &j)) < 0)
1575 return bus_send_error_reply(connection, message, &error, r);
1577 cl = job_bus_client_new(connection, message_get_sender_with_fallback(message));
1581 LIST_PREPEND(JobBusClient, client, j->bus_client_list, cl);
1583 if (!(reply = dbus_message_new_method_return(message)))
1586 if (!(path = job_dbus_path(j)))
1589 if (!dbus_message_append_args(
1591 DBUS_TYPE_OBJECT_PATH, &path,
1597 if (!dbus_connection_send(connection, reply, NULL))
1600 dbus_message_unref(reply);
1605 return DBUS_HANDLER_RESULT_HANDLED;
1611 dbus_message_unref(reply);
1613 dbus_error_free(&error);
1615 return DBUS_HANDLER_RESULT_NEED_MEMORY;
1618 const DBusObjectPathVTable bus_manager_vtable = {
1619 .message_function = bus_manager_message_handler