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 #define BUS_MANAGER_INTERFACE_BEGIN \
36 " <interface name=\"org.freedesktop.systemd1.Manager\">\n"
38 #define BUS_MANAGER_INTERFACE_METHODS \
39 " <method name=\"GetUnit\">\n" \
40 " <arg name=\"name\" type=\"s\" direction=\"in\"/>\n" \
41 " <arg name=\"unit\" type=\"o\" direction=\"out\"/>\n" \
43 " <method name=\"GetUnitByPID\">\n" \
44 " <arg name=\"pid\" type=\"u\" direction=\"in\"/>\n" \
45 " <arg name=\"unit\" type=\"o\" direction=\"out\"/>\n" \
47 " <method name=\"LoadUnit\">\n" \
48 " <arg name=\"name\" type=\"s\" direction=\"in\"/>\n" \
49 " <arg name=\"unit\" type=\"o\" direction=\"out\"/>\n" \
51 " <method name=\"StartUnit\">\n" \
52 " <arg name=\"name\" type=\"s\" direction=\"in\"/>\n" \
53 " <arg name=\"mode\" type=\"s\" direction=\"in\"/>\n" \
54 " <arg name=\"job\" type=\"o\" direction=\"out\"/>\n" \
56 " <method name=\"StartUnitReplace\">\n" \
57 " <arg name=\"old_unit\" type=\"s\" direction=\"in\"/>\n" \
58 " <arg name=\"new_unit\" type=\"s\" direction=\"in\"/>\n" \
59 " <arg name=\"mode\" type=\"s\" direction=\"in\"/>\n" \
60 " <arg name=\"job\" type=\"o\" direction=\"out\"/>\n" \
62 " <method name=\"StopUnit\">\n" \
63 " <arg name=\"name\" type=\"s\" direction=\"in\"/>\n" \
64 " <arg name=\"mode\" type=\"s\" direction=\"in\"/>\n" \
65 " <arg name=\"job\" type=\"o\" direction=\"out\"/>\n" \
67 " <method name=\"ReloadUnit\">\n" \
68 " <arg name=\"name\" type=\"s\" direction=\"in\"/>\n" \
69 " <arg name=\"mode\" type=\"s\" direction=\"in\"/>\n" \
70 " <arg name=\"job\" type=\"o\" direction=\"out\"/>\n" \
72 " <method name=\"RestartUnit\">\n" \
73 " <arg name=\"name\" type=\"s\" direction=\"in\"/>\n" \
74 " <arg name=\"mode\" type=\"s\" direction=\"in\"/>\n" \
75 " <arg name=\"job\" type=\"o\" direction=\"out\"/>\n" \
77 " <method name=\"TryRestartUnit\">\n" \
78 " <arg name=\"name\" type=\"s\" direction=\"in\"/>\n" \
79 " <arg name=\"mode\" type=\"s\" direction=\"in\"/>\n" \
80 " <arg name=\"job\" type=\"o\" direction=\"out\"/>\n" \
82 " <method name=\"ReloadOrRestartUnit\">\n" \
83 " <arg name=\"name\" type=\"s\" direction=\"in\"/>\n" \
84 " <arg name=\"mode\" type=\"s\" direction=\"in\"/>\n" \
85 " <arg name=\"job\" type=\"o\" direction=\"out\"/>\n" \
87 " <method name=\"ReloadOrTryRestartUnit\">\n" \
88 " <arg name=\"name\" type=\"s\" direction=\"in\"/>\n" \
89 " <arg name=\"mode\" type=\"s\" direction=\"in\"/>\n" \
90 " <arg name=\"job\" type=\"o\" direction=\"out\"/>\n" \
92 " <method name=\"KillUnit\">\n" \
93 " <arg name=\"name\" type=\"s\" direction=\"in\"/>\n" \
94 " <arg name=\"who\" type=\"s\" direction=\"in\"/>\n" \
95 " <arg name=\"mode\" type=\"s\" direction=\"in\"/>\n" \
96 " <arg name=\"signal\" type=\"i\" direction=\"in\"/>\n" \
98 " <method name=\"ResetFailedUnit\">\n" \
99 " <arg name=\"name\" type=\"s\" direction=\"in\"/>\n" \
101 " <method name=\"GetJob\">\n" \
102 " <arg name=\"id\" type=\"u\" direction=\"in\"/>\n" \
103 " <arg name=\"job\" type=\"o\" direction=\"out\"/>\n" \
105 " <method name=\"ClearJobs\"/>\n" \
106 " <method name=\"ResetFailed\"/>\n" \
107 " <method name=\"ListUnits\">\n" \
108 " <arg name=\"units\" type=\"a(ssssssouso)\" direction=\"out\"/>\n" \
110 " <method name=\"ListJobs\">\n" \
111 " <arg name=\"jobs\" type=\"a(usssoo)\" direction=\"out\"/>\n" \
113 " <method name=\"Subscribe\"/>\n" \
114 " <method name=\"Unsubscribe\"/>\n" \
115 " <method name=\"Dump\"/>\n" \
116 " <method name=\"CreateSnapshot\">\n" \
117 " <arg name=\"name\" type=\"s\" direction=\"in\"/>\n" \
118 " <arg name=\"cleanup\" type=\"b\" direction=\"in\"/>\n" \
119 " <arg name=\"unit\" type=\"o\" direction=\"out\"/>\n" \
121 " <method name=\"Reload\"/>\n" \
122 " <method name=\"Reexecute\"/>\n" \
123 " <method name=\"Exit\"/>\n" \
124 " <method name=\"Reboot\"/>\n" \
125 " <method name=\"PowerOff\"/>\n" \
126 " <method name=\"Halt\"/>\n" \
127 " <method name=\"KExec\"/>\n" \
128 " <method name=\"SetEnvironment\">\n" \
129 " <arg name=\"names\" type=\"as\" direction=\"in\"/>\n" \
131 " <method name=\"UnsetEnvironment\">\n" \
132 " <arg name=\"names\" type=\"as\" direction=\"in\"/>\n" \
134 " <method name=\"UnsetAndSetEnvironment\">\n" \
135 " <arg name=\"unset\" type=\"as\" direction=\"in\"/>\n" \
136 " <arg name=\"set\" type=\"as\" direction=\"in\"/>\n" \
138 " <method name=\"ListUnitFiles\">\n" \
139 " <arg name=\"changes\" type=\"a(ss)\" direction=\"out\"/>\n" \
141 " <method name=\"GetUnitFileState\">\n" \
142 " <arg name=\"file\" type=\"s\" direction=\"in\"/>\n" \
143 " <arg name=\"state\" type=\"s\" direction=\"out\"/>\n" \
145 " <method name=\"EnableUnitFiles\">\n" \
146 " <arg name=\"files\" type=\"as\" direction=\"in\"/>\n" \
147 " <arg name=\"runtime\" type=\"b\" direction=\"in\"/>\n" \
148 " <arg name=\"force\" type=\"b\" direction=\"in\"/>\n" \
149 " <arg name=\"carries_install_info\" type=\"b\" direction=\"out\"/>\n" \
150 " <arg name=\"changes\" type=\"a(sss)\" direction=\"out\"/>\n" \
152 " <method name=\"DisableUnitFiles\">\n" \
153 " <arg name=\"files\" type=\"as\" direction=\"in\"/>\n" \
154 " <arg name=\"runtime\" type=\"b\" direction=\"in\"/>\n" \
155 " <arg name=\"changes\" type=\"a(sss)\" direction=\"out\"/>\n" \
157 " <method name=\"ReenableUnitFiles\">\n" \
158 " <arg name=\"files\" type=\"as\" direction=\"in\"/>\n" \
159 " <arg name=\"runtime\" type=\"b\" direction=\"in\"/>\n" \
160 " <arg name=\"force\" type=\"b\" direction=\"in\"/>\n" \
161 " <arg name=\"carries_install_info\" type=\"b\" direction=\"out\"/>\n" \
162 " <arg name=\"changes\" type=\"a(sss)\" direction=\"out\"/>\n" \
164 " <method name=\"LinkUnitFiles\">\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=\"changes\" type=\"a(sss)\" direction=\"out\"/>\n" \
170 " <method name=\"PresetUnitFiles\">\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=\"carries_install_info\" type=\"b\" direction=\"out\"/>\n" \
175 " <arg name=\"changes\" type=\"a(sss)\" direction=\"out\"/>\n" \
177 " <method name=\"MaskUnitFiles\">\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=\"changes\" type=\"a(sss)\" direction=\"out\"/>\n" \
183 " <method name=\"UnmaskUnitFiles\">\n" \
184 " <arg name=\"files\" type=\"as\" direction=\"in\"/>\n" \
185 " <arg name=\"runtime\" type=\"b\" direction=\"in\"/>\n" \
186 " <arg name=\"changes\" type=\"a(sss)\" direction=\"out\"/>\n" \
189 #define BUS_MANAGER_INTERFACE_SIGNALS \
190 " <signal name=\"UnitNew\">\n" \
191 " <arg name=\"id\" type=\"s\"/>\n" \
192 " <arg name=\"unit\" type=\"o\"/>\n" \
194 " <signal name=\"UnitRemoved\">\n" \
195 " <arg name=\"id\" type=\"s\"/>\n" \
196 " <arg name=\"unit\" type=\"o\"/>\n" \
198 " <signal name=\"JobNew\">\n" \
199 " <arg name=\"id\" type=\"u\"/>\n" \
200 " <arg name=\"job\" type=\"o\"/>\n" \
201 " <arg name=\"unit\" type=\"s\"/>\n" \
203 " <signal name=\"JobRemoved\">\n" \
204 " <arg name=\"id\" type=\"u\"/>\n" \
205 " <arg name=\"job\" type=\"o\"/>\n" \
206 " <arg name=\"unit\" type=\"s\"/>\n" \
207 " <arg name=\"result\" type=\"s\"/>\n" \
209 " <signal name=\"StartupFinished\">\n" \
210 " <arg name=\"kernel\" type=\"t\"/>\n" \
211 " <arg name=\"initrd\" type=\"t\"/>\n" \
212 " <arg name=\"userspace\" type=\"t\"/>\n" \
213 " <arg name=\"total\" type=\"t\"/>\n" \
215 " <signal name=\"UnitFilesChanged\"/>\n"
217 #define BUS_MANAGER_INTERFACE_PROPERTIES_GENERAL \
218 " <property name=\"Version\" type=\"s\" access=\"read\"/>\n" \
219 " <property name=\"Distribution\" type=\"s\" access=\"read\"/>\n" \
220 " <property name=\"Features\" type=\"s\" access=\"read\"/>\n" \
221 " <property name=\"Tainted\" type=\"s\" access=\"read\"/>\n" \
222 " <property name=\"RunningAs\" type=\"s\" access=\"read\"/>\n" \
223 " <property name=\"InitRDTimestamp\" type=\"t\" access=\"read\"/>\n" \
224 " <property name=\"InitRDTimestampMonotonic\" type=\"t\" access=\"read\"/>\n" \
225 " <property name=\"StartupTimestamp\" type=\"t\" access=\"read\"/>\n" \
226 " <property name=\"StartupTimestampMonotonic\" type=\"t\" access=\"read\"/>\n" \
227 " <property name=\"FinishTimestamp\" type=\"t\" access=\"read\"/>\n" \
228 " <property name=\"FinishTimestampMonotonic\" type=\"t\" access=\"read\"/>\n" \
229 " <property name=\"LogLevel\" type=\"s\" access=\"readwrite\"/>\n" \
230 " <property name=\"LogTarget\" type=\"s\" access=\"readwrite\"/>\n" \
231 " <property name=\"NNames\" type=\"u\" access=\"read\"/>\n" \
232 " <property name=\"NJobs\" type=\"u\" access=\"read\"/>\n" \
233 " <property name=\"NInstalledJobs\" type=\"u\" access=\"read\"/>\n" \
234 " <property name=\"NFailedJobs\" type=\"u\" access=\"read\"/>\n" \
235 " <property name=\"Progress\" type=\"d\" access=\"read\"/>\n" \
236 " <property name=\"Environment\" type=\"as\" access=\"read\"/>\n" \
237 " <property name=\"ConfirmSpawn\" type=\"b\" access=\"read\"/>\n" \
238 " <property name=\"ShowStatus\" type=\"b\" access=\"read\"/>\n" \
239 " <property name=\"UnitPath\" type=\"as\" access=\"read\"/>\n" \
240 " <property name=\"NotifySocket\" type=\"s\" access=\"read\"/>\n" \
241 " <property name=\"ControlGroupHierarchy\" type=\"s\" access=\"read\"/>\n" \
242 " <property name=\"DefaultControllers\" type=\"as\" access=\"read\"/>\n" \
243 " <property name=\"DefaultStandardOutput\" type=\"s\" access=\"read\"/>\n" \
244 " <property name=\"DefaultStandardError\" type=\"s\" access=\"read\"/>\n" \
245 " <property name=\"RuntimeWatchdogUSec\" type=\"s\" access=\"readwrite\"/>\n" \
246 " <property name=\"ShutdownWatchdogUSec\" type=\"s\" access=\"readwrite\"/>\n" \
247 " <property name=\"HaveWatchdog\" type=\"b\" access=\"read\"/>\n"
249 #ifdef HAVE_SYSV_COMPAT
250 #define BUS_MANAGER_INTERFACE_PROPERTIES_SYSV \
251 " <property name=\"SysVConsole\" type=\"b\" access=\"read\"/>\n" \
252 " <property name=\"SysVInitPath\" type=\"as\" access=\"read\"/>\n" \
253 " <property name=\"SysVRcndPath\" type=\"as\" access=\"read\"/>\n"
255 #define BUS_MANAGER_INTERFACE_PROPERTIES_SYSV
258 #define BUS_MANAGER_INTERFACE_END \
261 #define BUS_MANAGER_INTERFACE \
262 BUS_MANAGER_INTERFACE_BEGIN \
263 BUS_MANAGER_INTERFACE_METHODS \
264 BUS_MANAGER_INTERFACE_SIGNALS \
265 BUS_MANAGER_INTERFACE_PROPERTIES_GENERAL \
266 BUS_MANAGER_INTERFACE_PROPERTIES_SYSV \
267 BUS_MANAGER_INTERFACE_END
269 #define INTROSPECTION_BEGIN \
270 DBUS_INTROSPECT_1_0_XML_DOCTYPE_DECL_NODE \
272 BUS_MANAGER_INTERFACE \
273 BUS_PROPERTIES_INTERFACE \
275 BUS_INTROSPECTABLE_INTERFACE
277 #define INTROSPECTION_END \
280 #define INTERFACES_LIST \
281 BUS_GENERIC_INTERFACES_LIST \
282 "org.freedesktop.systemd1.Manager\0"
284 const char bus_manager_interface[] _introspect_("Manager") = BUS_MANAGER_INTERFACE;
286 static DEFINE_BUS_PROPERTY_APPEND_ENUM(bus_manager_append_running_as, manager_running_as, ManagerRunningAs);
287 static DEFINE_BUS_PROPERTY_APPEND_ENUM(bus_manager_append_exec_output, exec_output, ExecOutput);
289 static int bus_manager_append_tainted(DBusMessageIter *i, const char *property, void *data) {
292 char buf[LINE_MAX] = "", *e = buf, *p = NULL;
299 e = stpcpy(e, "split-usr:");
301 if (readlink_malloc("/etc/mtab", &p) < 0)
302 e = stpcpy(e, "mtab-not-symlink:");
306 if (access("/proc/cgroups", F_OK) < 0)
307 stpcpy(e, "cgroups-missing:");
309 if (hwclock_is_localtime() > 0)
310 stpcpy(e, "local-hwclock:");
312 if (endswith(buf, ":"))
313 buf[strlen(buf)-1] = 0;
317 if (!dbus_message_iter_append_basic(i, DBUS_TYPE_STRING, &t))
323 static int bus_manager_append_log_target(DBusMessageIter *i, const char *property, void *data) {
329 t = log_target_to_string(log_get_target());
331 if (!dbus_message_iter_append_basic(i, DBUS_TYPE_STRING, &t))
337 static int bus_manager_set_log_target(DBusMessageIter *i, const char *property, void *data) {
343 dbus_message_iter_get_basic(i, &t);
345 return log_set_target_from_string(t);
348 static int bus_manager_append_log_level(DBusMessageIter *i, const char *property, void *data) {
354 t = log_level_to_string(log_get_max_level());
356 if (!dbus_message_iter_append_basic(i, DBUS_TYPE_STRING, &t))
362 static int bus_manager_set_log_level(DBusMessageIter *i, const char *property, void *data) {
368 dbus_message_iter_get_basic(i, &t);
370 return log_set_max_level_from_string(t);
373 static int bus_manager_append_n_names(DBusMessageIter *i, const char *property, void *data) {
381 u = hashmap_size(m->units);
383 if (!dbus_message_iter_append_basic(i, DBUS_TYPE_UINT32, &u))
389 static int bus_manager_append_n_jobs(DBusMessageIter *i, const char *property, void *data) {
397 u = hashmap_size(m->jobs);
399 if (!dbus_message_iter_append_basic(i, DBUS_TYPE_UINT32, &u))
405 static int bus_manager_append_progress(DBusMessageIter *i, const char *property, void *data) {
413 if (dual_timestamp_is_set(&m->finish_timestamp))
416 d = 1.0 - ((double) hashmap_size(m->jobs) / (double) m->n_installed_jobs);
418 if (!dbus_message_iter_append_basic(i, DBUS_TYPE_DOUBLE, &d))
424 static const char *message_get_sender_with_fallback(DBusMessage *m) {
429 if ((s = dbus_message_get_sender(m)))
432 /* When the message came in from a direct connection the
433 * message will have no sender. We fix that here. */
438 static DBusMessage *message_from_file_changes(
440 UnitFileChange *changes,
442 int carries_install_info) {
444 DBusMessageIter iter, sub, sub2;
448 reply = dbus_message_new_method_return(m);
452 dbus_message_iter_init_append(reply, &iter);
454 if (carries_install_info >= 0) {
457 b = !!carries_install_info;
458 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &b))
462 if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "(sss)", &sub))
465 for (i = 0; i < n_changes; i++) {
466 const char *type, *path, *source;
468 type = unit_file_change_type_to_string(changes[i].type);
469 path = strempty(changes[i].path);
470 source = strempty(changes[i].source);
472 if (!dbus_message_iter_open_container(&sub, DBUS_TYPE_STRUCT, NULL, &sub2) ||
473 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &type) ||
474 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &path) ||
475 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &source) ||
476 !dbus_message_iter_close_container(&sub, &sub2))
480 if (!dbus_message_iter_close_container(&iter, &sub))
486 dbus_message_unref(reply);
490 static int bus_manager_send_unit_files_changed(Manager *m) {
494 s = dbus_message_new_signal("/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", "UnitFilesChanged");
498 r = bus_broadcast(m, s);
499 dbus_message_unref(s);
504 static int bus_manager_append_have_watchdog(DBusMessageIter *i, const char *property, void *data) {
510 b = access("/dev/watchdog", F_OK) >= 0;
512 if (!dbus_message_iter_append_basic(i, DBUS_TYPE_BOOLEAN, &b))
518 static int bus_manager_set_runtime_watchdog_usec(DBusMessageIter *i, const char *property, void *data) {
524 dbus_message_iter_get_basic(i, t);
526 return watchdog_set_timeout(t);
529 static const char systemd_property_string[] =
534 static const BusProperty bus_systemd_properties[] = {
535 { "Version", bus_property_append_string, "s", 0 },
536 { "Distribution", bus_property_append_string, "s", sizeof(PACKAGE_STRING) },
537 { "Features", bus_property_append_string, "s", sizeof(PACKAGE_STRING) + sizeof(DISTRIBUTION) },
541 static const BusProperty bus_manager_properties[] = {
542 { "RunningAs", bus_manager_append_running_as, "s", offsetof(Manager, running_as) },
543 { "Tainted", bus_manager_append_tainted, "s", 0 },
544 { "InitRDTimestamp", bus_property_append_uint64, "t", offsetof(Manager, initrd_timestamp.realtime) },
545 { "InitRDTimestampMonotonic", bus_property_append_uint64, "t", offsetof(Manager, initrd_timestamp.monotonic) },
546 { "StartupTimestamp", bus_property_append_uint64, "t", offsetof(Manager, startup_timestamp.realtime) },
547 { "StartupTimestampMonotonic", bus_property_append_uint64, "t", offsetof(Manager, startup_timestamp.monotonic) },
548 { "FinishTimestamp", bus_property_append_uint64, "t", offsetof(Manager, finish_timestamp.realtime) },
549 { "FinishTimestampMonotonic", bus_property_append_uint64, "t", offsetof(Manager, finish_timestamp.monotonic) },
550 { "LogLevel", bus_manager_append_log_level, "s", 0, false, bus_manager_set_log_level },
551 { "LogTarget", bus_manager_append_log_target, "s", 0, false, bus_manager_set_log_target },
552 { "NNames", bus_manager_append_n_names, "u", 0 },
553 { "NJobs", bus_manager_append_n_jobs, "u", 0 },
554 { "NInstalledJobs",bus_property_append_uint32, "u", offsetof(Manager, n_installed_jobs) },
555 { "NFailedJobs", bus_property_append_uint32, "u", offsetof(Manager, n_failed_jobs) },
556 { "Progress", bus_manager_append_progress, "d", 0 },
557 { "Environment", bus_property_append_strv, "as", offsetof(Manager, environment), true },
558 { "ConfirmSpawn", bus_property_append_bool, "b", offsetof(Manager, confirm_spawn) },
559 { "ShowStatus", bus_property_append_bool, "b", offsetof(Manager, show_status) },
560 { "UnitPath", bus_property_append_strv, "as", offsetof(Manager, lookup_paths.unit_path), true },
561 { "NotifySocket", bus_property_append_string, "s", offsetof(Manager, notify_socket), true },
562 { "ControlGroupHierarchy", bus_property_append_string, "s", offsetof(Manager, cgroup_hierarchy), true },
563 { "DefaultControllers", bus_property_append_strv, "as", offsetof(Manager, default_controllers), true },
564 { "DefaultStandardOutput", bus_manager_append_exec_output, "s", offsetof(Manager, default_std_output) },
565 { "DefaultStandardError", bus_manager_append_exec_output, "s", offsetof(Manager, default_std_error) },
566 { "RuntimeWatchdogUSec", bus_property_append_usec, "t", offsetof(Manager, runtime_watchdog), false, bus_manager_set_runtime_watchdog_usec },
567 { "ShutdownWatchdogUSec", bus_property_append_usec, "t", offsetof(Manager, shutdown_watchdog), false, bus_property_set_usec },
568 { "HaveWatchdog", bus_manager_append_have_watchdog, "b", 0 },
569 #ifdef HAVE_SYSV_COMPAT
570 { "SysVConsole", bus_property_append_bool, "b", offsetof(Manager, sysv_console) },
571 { "SysVInitPath", bus_property_append_strv, "as", offsetof(Manager, lookup_paths.sysvinit_path), true },
572 { "SysVRcndPath", bus_property_append_strv, "as", offsetof(Manager, lookup_paths.sysvrcnd_path), true },
577 static DBusHandlerResult bus_manager_message_handler(DBusConnection *connection, DBusMessage *message, void *data) {
582 DBusMessage *reply = NULL;
584 JobType job_type = _JOB_TYPE_INVALID;
585 bool reload_if_possible = false;
592 dbus_error_init(&error);
594 member = dbus_message_get_member(message);
596 if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "GetUnit")) {
600 if (!dbus_message_get_args(
603 DBUS_TYPE_STRING, &name,
605 return bus_send_error_reply(connection, message, &error, -EINVAL);
607 if (!(u = manager_get_unit(m, name))) {
608 dbus_set_error(&error, BUS_ERROR_NO_SUCH_UNIT, "Unit %s is not loaded.", name);
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", "GetUnitByPID")) {
627 if (!dbus_message_get_args(
630 DBUS_TYPE_UINT32, &pid,
632 return bus_send_error_reply(connection, message, &error, -EINVAL);
634 if (!(u = cgroup_unit_by_pid(m, (pid_t) pid))) {
635 dbus_set_error(&error, BUS_ERROR_NO_SUCH_UNIT, "No unit for PID %lu is loaded.", (unsigned long) pid);
636 return bus_send_error_reply(connection, message, &error, -ENOENT);
639 if (!(reply = dbus_message_new_method_return(message)))
642 if (!(path = unit_dbus_path(u)))
645 if (!dbus_message_append_args(
647 DBUS_TYPE_OBJECT_PATH, &path,
650 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "LoadUnit")) {
654 if (!dbus_message_get_args(
657 DBUS_TYPE_STRING, &name,
659 return bus_send_error_reply(connection, message, &error, -EINVAL);
661 if ((r = manager_load_unit(m, name, NULL, &error, &u)) < 0)
662 return bus_send_error_reply(connection, message, &error, r);
664 if (!(reply = dbus_message_new_method_return(message)))
667 if (!(path = unit_dbus_path(u)))
670 if (!dbus_message_append_args(
672 DBUS_TYPE_OBJECT_PATH, &path,
676 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "StartUnit"))
677 job_type = JOB_START;
678 else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "StartUnitReplace"))
679 job_type = JOB_START;
680 else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "StopUnit"))
682 else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ReloadUnit"))
683 job_type = JOB_RELOAD;
684 else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "RestartUnit"))
685 job_type = JOB_RESTART;
686 else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "TryRestartUnit"))
687 job_type = JOB_TRY_RESTART;
688 else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ReloadOrRestartUnit")) {
689 reload_if_possible = true;
690 job_type = JOB_RESTART;
691 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ReloadOrTryRestartUnit")) {
692 reload_if_possible = true;
693 job_type = JOB_TRY_RESTART;
694 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "KillUnit")) {
695 const char *name, *swho, *smode;
701 if (!dbus_message_get_args(
704 DBUS_TYPE_STRING, &name,
705 DBUS_TYPE_STRING, &swho,
706 DBUS_TYPE_STRING, &smode,
707 DBUS_TYPE_INT32, &signo,
709 return bus_send_error_reply(connection, message, &error, -EINVAL);
714 who = kill_who_from_string(swho);
716 return bus_send_error_reply(connection, message, &error, -EINVAL);
720 mode = KILL_CONTROL_GROUP;
722 mode = kill_mode_from_string(smode);
724 return bus_send_error_reply(connection, message, &error, -EINVAL);
727 if (signo <= 0 || signo >= _NSIG)
728 return bus_send_error_reply(connection, message, &error, -EINVAL);
730 if (!(u = manager_get_unit(m, name))) {
731 dbus_set_error(&error, BUS_ERROR_NO_SUCH_UNIT, "Unit %s is not loaded.", name);
732 return bus_send_error_reply(connection, message, &error, -ENOENT);
735 if ((r = unit_kill(u, who, mode, signo, &error)) < 0)
736 return bus_send_error_reply(connection, message, &error, r);
738 if (!(reply = dbus_message_new_method_return(message)))
741 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "GetJob")) {
745 if (!dbus_message_get_args(
748 DBUS_TYPE_UINT32, &id,
750 return bus_send_error_reply(connection, message, &error, -EINVAL);
752 if (!(j = manager_get_job(m, id))) {
753 dbus_set_error(&error, BUS_ERROR_NO_SUCH_JOB, "Job %u does not exist.", (unsigned) id);
754 return bus_send_error_reply(connection, message, &error, -ENOENT);
757 if (!(reply = dbus_message_new_method_return(message)))
760 if (!(path = job_dbus_path(j)))
763 if (!dbus_message_append_args(
765 DBUS_TYPE_OBJECT_PATH, &path,
769 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ClearJobs")) {
771 manager_clear_jobs(m);
773 if (!(reply = dbus_message_new_method_return(message)))
776 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ResetFailed")) {
778 manager_reset_failed(m);
780 if (!(reply = dbus_message_new_method_return(message)))
783 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ResetFailedUnit")) {
787 if (!dbus_message_get_args(
790 DBUS_TYPE_STRING, &name,
792 return bus_send_error_reply(connection, message, &error, -EINVAL);
794 if (!(u = manager_get_unit(m, name))) {
795 dbus_set_error(&error, BUS_ERROR_NO_SUCH_UNIT, "Unit %s is not loaded.", name);
796 return bus_send_error_reply(connection, message, &error, -ENOENT);
799 unit_reset_failed(u);
801 if (!(reply = dbus_message_new_method_return(message)))
804 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ListUnits")) {
805 DBusMessageIter iter, sub;
810 if (!(reply = dbus_message_new_method_return(message)))
813 dbus_message_iter_init_append(reply, &iter);
815 if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "(ssssssouso)", &sub))
818 HASHMAP_FOREACH_KEY(u, k, m->units, i) {
819 char *u_path, *j_path;
820 const char *description, *load_state, *active_state, *sub_state, *sjob_type, *following;
821 DBusMessageIter sub2;
828 if (!dbus_message_iter_open_container(&sub, DBUS_TYPE_STRUCT, NULL, &sub2))
831 description = unit_description(u);
832 load_state = unit_load_state_to_string(u->load_state);
833 active_state = unit_active_state_to_string(unit_active_state(u));
834 sub_state = unit_sub_state_to_string(u);
836 f = unit_following(u);
837 following = f ? f->id : "";
839 if (!(u_path = unit_dbus_path(u)))
843 job_id = (uint32_t) u->job->id;
845 if (!(j_path = job_dbus_path(u->job))) {
850 sjob_type = job_type_to_string(u->job->type);
857 if (!dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &u->id) ||
858 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &description) ||
859 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &load_state) ||
860 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &active_state) ||
861 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &sub_state) ||
862 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &following) ||
863 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_OBJECT_PATH, &u_path) ||
864 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_UINT32, &job_id) ||
865 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &sjob_type) ||
866 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_OBJECT_PATH, &j_path)) {
877 if (!dbus_message_iter_close_container(&sub, &sub2))
881 if (!dbus_message_iter_close_container(&iter, &sub))
884 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ListJobs")) {
885 DBusMessageIter iter, sub;
889 if (!(reply = dbus_message_new_method_return(message)))
892 dbus_message_iter_init_append(reply, &iter);
894 if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "(usssoo)", &sub))
897 HASHMAP_FOREACH(j, m->jobs, i) {
898 char *u_path, *j_path;
899 const char *state, *type;
901 DBusMessageIter sub2;
903 if (!dbus_message_iter_open_container(&sub, DBUS_TYPE_STRUCT, NULL, &sub2))
906 id = (uint32_t) j->id;
907 state = job_state_to_string(j->state);
908 type = job_type_to_string(j->type);
910 if (!(j_path = job_dbus_path(j)))
913 if (!(u_path = unit_dbus_path(j->unit))) {
918 if (!dbus_message_iter_append_basic(&sub2, DBUS_TYPE_UINT32, &id) ||
919 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &j->unit->id) ||
920 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &type) ||
921 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &state) ||
922 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_OBJECT_PATH, &j_path) ||
923 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_OBJECT_PATH, &u_path)) {
932 if (!dbus_message_iter_close_container(&sub, &sub2))
936 if (!dbus_message_iter_close_container(&iter, &sub))
939 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "Subscribe")) {
943 if (!(s = BUS_CONNECTION_SUBSCRIBED(m, connection))) {
944 if (!(s = set_new(string_hash_func, string_compare_func)))
947 if (!(dbus_connection_set_data(connection, m->subscribed_data_slot, s, NULL))) {
953 if (!(client = strdup(message_get_sender_with_fallback(message))))
956 if ((r = set_put(s, client)) < 0) {
958 return bus_send_error_reply(connection, message, NULL, r);
961 if (!(reply = dbus_message_new_method_return(message)))
964 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "Unsubscribe")) {
967 if (!(client = set_remove(BUS_CONNECTION_SUBSCRIBED(m, connection), (char*) message_get_sender_with_fallback(message)))) {
968 dbus_set_error(&error, BUS_ERROR_NOT_SUBSCRIBED, "Client is not subscribed.");
969 return bus_send_error_reply(connection, message, &error, -ENOENT);
974 if (!(reply = dbus_message_new_method_return(message)))
977 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "Dump")) {
982 if (!(reply = dbus_message_new_method_return(message)))
985 if (!(f = open_memstream(&dump, &size)))
988 manager_dump_units(m, f, NULL);
989 manager_dump_jobs(m, f, NULL);
999 if (!dbus_message_append_args(reply, DBUS_TYPE_STRING, &dump, DBUS_TYPE_INVALID)) {
1005 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "CreateSnapshot")) {
1007 dbus_bool_t cleanup;
1010 if (!dbus_message_get_args(
1013 DBUS_TYPE_STRING, &name,
1014 DBUS_TYPE_BOOLEAN, &cleanup,
1016 return bus_send_error_reply(connection, message, &error, -EINVAL);
1018 if (name && name[0] == 0)
1021 if ((r = snapshot_create(m, name, cleanup, &error, &s)) < 0)
1022 return bus_send_error_reply(connection, message, &error, r);
1024 if (!(reply = dbus_message_new_method_return(message)))
1027 if (!(path = unit_dbus_path(UNIT(s))))
1030 if (!dbus_message_append_args(
1032 DBUS_TYPE_OBJECT_PATH, &path,
1036 } else if (dbus_message_is_method_call(message, "org.freedesktop.DBus.Introspectable", "Introspect")) {
1037 char *introspection = NULL;
1045 if (!(reply = dbus_message_new_method_return(message)))
1048 /* We roll our own introspection code here, instead of
1049 * relying on bus_default_message_handler() because we
1050 * need to generate our introspection string
1053 if (!(f = open_memstream(&introspection, &size)))
1056 fputs(INTROSPECTION_BEGIN, f);
1058 HASHMAP_FOREACH_KEY(u, k, m->units, i) {
1064 if (!(p = bus_path_escape(k))) {
1066 free(introspection);
1070 fprintf(f, "<node name=\"unit/%s\"/>", p);
1074 HASHMAP_FOREACH(j, m->jobs, i)
1075 fprintf(f, "<node name=\"job/%lu\"/>", (unsigned long) j->id);
1077 fputs(INTROSPECTION_END, f);
1081 free(introspection);
1090 if (!dbus_message_append_args(reply, DBUS_TYPE_STRING, &introspection, DBUS_TYPE_INVALID)) {
1091 free(introspection);
1095 free(introspection);
1097 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "Reload")) {
1099 assert(!m->queued_message);
1101 /* Instead of sending the reply back right away, we
1102 * just remember that we need to and then send it
1103 * after the reload is finished. That way the caller
1104 * knows when the reload finished. */
1106 if (!(m->queued_message = dbus_message_new_method_return(message)))
1109 m->queued_message_connection = connection;
1110 m->exit_code = MANAGER_RELOAD;
1112 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "Reexecute")) {
1114 /* We don't send a reply back here, the client should
1115 * just wait for us disconnecting. */
1117 m->exit_code = MANAGER_REEXECUTE;
1119 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "Exit")) {
1121 if (m->running_as == MANAGER_SYSTEM) {
1122 dbus_set_error(&error, BUS_ERROR_NOT_SUPPORTED, "Exit is only supported for user service 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_EXIT;
1131 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "Reboot")) {
1133 if (m->running_as != MANAGER_SYSTEM) {
1134 dbus_set_error(&error, BUS_ERROR_NOT_SUPPORTED, "Reboot 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_REBOOT;
1143 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "PowerOff")) {
1145 if (m->running_as != MANAGER_SYSTEM) {
1146 dbus_set_error(&error, BUS_ERROR_NOT_SUPPORTED, "Powering off is only supported for system managers.");
1147 return bus_send_error_reply(connection, message, &error, -ENOTSUP);
1150 if (!(reply = dbus_message_new_method_return(message)))
1153 m->exit_code = MANAGER_POWEROFF;
1155 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "Halt")) {
1157 if (m->running_as != MANAGER_SYSTEM) {
1158 dbus_set_error(&error, BUS_ERROR_NOT_SUPPORTED, "Halting is only supported for system managers.");
1159 return bus_send_error_reply(connection, message, &error, -ENOTSUP);
1162 if (!(reply = dbus_message_new_method_return(message)))
1165 m->exit_code = MANAGER_HALT;
1167 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "KExec")) {
1169 if (m->running_as != MANAGER_SYSTEM) {
1170 dbus_set_error(&error, BUS_ERROR_NOT_SUPPORTED, "kexec is only supported for system managers.");
1171 return bus_send_error_reply(connection, message, &error, -ENOTSUP);
1174 if (!(reply = dbus_message_new_method_return(message)))
1177 m->exit_code = MANAGER_KEXEC;
1179 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "SetEnvironment")) {
1180 char **l = NULL, **e = NULL;
1182 if ((r = bus_parse_strv(message, &l)) < 0) {
1186 return bus_send_error_reply(connection, message, NULL, r);
1189 e = strv_env_merge(2, m->environment, l);
1195 if (!(reply = dbus_message_new_method_return(message))) {
1200 strv_free(m->environment);
1203 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "UnsetEnvironment")) {
1204 char **l = NULL, **e = NULL;
1206 if ((r = bus_parse_strv(message, &l)) < 0) {
1210 return bus_send_error_reply(connection, message, NULL, r);
1213 e = strv_env_delete(m->environment, 1, l);
1219 if (!(reply = dbus_message_new_method_return(message))) {
1224 strv_free(m->environment);
1227 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "UnsetAndSetEnvironment")) {
1228 char **l_set = NULL, **l_unset = NULL, **e = NULL, **f = NULL;
1229 DBusMessageIter iter;
1231 if (!dbus_message_iter_init(message, &iter))
1234 r = bus_parse_strv_iter(&iter, &l_unset);
1239 return bus_send_error_reply(connection, message, NULL, r);
1242 if (!dbus_message_iter_next(&iter)) {
1244 return bus_send_error_reply(connection, message, NULL, -EINVAL);
1247 r = bus_parse_strv_iter(&iter, &l_set);
1253 return bus_send_error_reply(connection, message, NULL, r);
1256 e = strv_env_delete(m->environment, 1, l_unset);
1264 f = strv_env_merge(2, e, l_set);
1271 if (!(reply = dbus_message_new_method_return(message))) {
1276 strv_free(m->environment);
1278 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ListUnitFiles")) {
1279 DBusMessageIter iter, sub, sub2;
1284 reply = dbus_message_new_method_return(message);
1288 h = hashmap_new(string_hash_func, string_compare_func);
1292 r = unit_file_get_list(m->running_as == MANAGER_SYSTEM ? UNIT_FILE_SYSTEM : UNIT_FILE_USER, NULL, h);
1294 unit_file_list_free(h);
1295 dbus_message_unref(reply);
1296 return bus_send_error_reply(connection, message, NULL, r);
1299 dbus_message_iter_init_append(reply, &iter);
1301 if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "(ss)", &sub)) {
1302 unit_file_list_free(h);
1306 HASHMAP_FOREACH(item, h, i) {
1309 state = unit_file_state_to_string(item->state);
1312 if (!dbus_message_iter_open_container(&sub, DBUS_TYPE_STRUCT, NULL, &sub2) ||
1313 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &item->path) ||
1314 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &state) ||
1315 !dbus_message_iter_close_container(&sub, &sub2)) {
1316 unit_file_list_free(h);
1321 unit_file_list_free(h);
1323 if (!dbus_message_iter_close_container(&iter, &sub))
1326 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "GetUnitFileState")) {
1328 UnitFileState state;
1331 if (!dbus_message_get_args(
1334 DBUS_TYPE_STRING, &name,
1336 return bus_send_error_reply(connection, message, &error, -EINVAL);
1338 state = unit_file_get_state(m->running_as == MANAGER_SYSTEM ? UNIT_FILE_SYSTEM : UNIT_FILE_USER, NULL, name);
1340 return bus_send_error_reply(connection, message, NULL, state);
1342 s = unit_file_state_to_string(state);
1345 reply = dbus_message_new_method_return(message);
1349 if (!dbus_message_append_args(
1351 DBUS_TYPE_STRING, &s,
1354 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "EnableUnitFiles") ||
1355 dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ReenableUnitFiles") ||
1356 dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "LinkUnitFiles") ||
1357 dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "PresetUnitFiles") ||
1358 dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "MaskUnitFiles")) {
1361 DBusMessageIter iter;
1362 UnitFileScope scope = m->running_as == MANAGER_SYSTEM ? UNIT_FILE_SYSTEM : UNIT_FILE_USER;
1363 UnitFileChange *changes = NULL;
1364 unsigned n_changes = 0;
1365 dbus_bool_t runtime, force;
1366 int carries_install_info = -1;
1368 if (!dbus_message_iter_init(message, &iter))
1371 r = bus_parse_strv_iter(&iter, &l);
1376 return bus_send_error_reply(connection, message, NULL, r);
1379 if (!dbus_message_iter_next(&iter) ||
1380 bus_iter_get_basic_and_next(&iter, DBUS_TYPE_BOOLEAN, &runtime, true) < 0 ||
1381 bus_iter_get_basic_and_next(&iter, DBUS_TYPE_BOOLEAN, &force, false) < 0) {
1383 return bus_send_error_reply(connection, message, NULL, -EIO);
1386 if (streq(member, "EnableUnitFiles")) {
1387 r = unit_file_enable(scope, runtime, NULL, l, force, &changes, &n_changes);
1388 carries_install_info = r;
1389 } else if (streq(member, "ReenableUnitFiles")) {
1390 r = unit_file_reenable(scope, runtime, NULL, l, force, &changes, &n_changes);
1391 carries_install_info = r;
1392 } else if (streq(member, "LinkUnitFiles"))
1393 r = unit_file_link(scope, runtime, NULL, l, force, &changes, &n_changes);
1394 else if (streq(member, "PresetUnitFiles")) {
1395 r = unit_file_preset(scope, runtime, NULL, l, force, &changes, &n_changes);
1396 carries_install_info = r;
1397 } else if (streq(member, "MaskUnitFiles"))
1398 r = unit_file_mask(scope, runtime, NULL, l, force, &changes, &n_changes);
1400 assert_not_reached("Uh? Wrong method");
1403 bus_manager_send_unit_files_changed(m);
1406 unit_file_changes_free(changes, n_changes);
1407 return bus_send_error_reply(connection, message, NULL, r);
1410 reply = message_from_file_changes(message, changes, n_changes, carries_install_info);
1411 unit_file_changes_free(changes, n_changes);
1416 } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "DisableUnitFiles") ||
1417 dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "UnmaskUnitFiles")) {
1420 DBusMessageIter iter;
1421 UnitFileScope scope = m->running_as == MANAGER_SYSTEM ? UNIT_FILE_SYSTEM : UNIT_FILE_USER;
1422 UnitFileChange *changes = NULL;
1423 unsigned n_changes = 0;
1424 dbus_bool_t runtime;
1426 if (!dbus_message_iter_init(message, &iter))
1429 r = bus_parse_strv_iter(&iter, &l);
1434 return bus_send_error_reply(connection, message, NULL, r);
1437 if (!dbus_message_iter_next(&iter) ||
1438 bus_iter_get_basic_and_next(&iter, DBUS_TYPE_BOOLEAN, &runtime, false) < 0) {
1440 return bus_send_error_reply(connection, message, NULL, -EIO);
1443 if (streq(member, "DisableUnitFiles"))
1444 r = unit_file_disable(scope, runtime, NULL, l, &changes, &n_changes);
1445 else if (streq(member, "UnmaskUnitFiles"))
1446 r = unit_file_unmask(scope, runtime, NULL, l, &changes, &n_changes);
1448 assert_not_reached("Uh? Wrong method");
1451 bus_manager_send_unit_files_changed(m);
1454 unit_file_changes_free(changes, n_changes);
1455 return bus_send_error_reply(connection, message, NULL, r);
1458 reply = message_from_file_changes(message, changes, n_changes, -1);
1459 unit_file_changes_free(changes, n_changes);
1465 const BusBoundProperties bps[] = {
1466 { "org.freedesktop.systemd1.Manager", bus_systemd_properties, systemd_property_string },
1467 { "org.freedesktop.systemd1.Manager", bus_manager_properties, m },
1470 return bus_default_message_handler(connection, message, NULL, INTERFACES_LIST, bps);
1473 if (job_type != _JOB_TYPE_INVALID) {
1474 const char *name, *smode, *old_name = NULL;
1481 if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "StartUnitReplace"))
1482 b = dbus_message_get_args(
1485 DBUS_TYPE_STRING, &old_name,
1486 DBUS_TYPE_STRING, &name,
1487 DBUS_TYPE_STRING, &smode,
1490 b = dbus_message_get_args(
1493 DBUS_TYPE_STRING, &name,
1494 DBUS_TYPE_STRING, &smode,
1498 return bus_send_error_reply(connection, message, &error, -EINVAL);
1501 if (!(u = manager_get_unit(m, old_name)) ||
1503 u->job->type != JOB_START) {
1504 dbus_set_error(&error, BUS_ERROR_NO_SUCH_JOB, "No job queued for unit %s", old_name);
1505 return bus_send_error_reply(connection, message, &error, -ENOENT);
1509 if ((mode = job_mode_from_string(smode)) == _JOB_MODE_INVALID) {
1510 dbus_set_error(&error, BUS_ERROR_INVALID_JOB_MODE, "Job mode %s is invalid.", smode);
1511 return bus_send_error_reply(connection, message, &error, -EINVAL);
1514 if ((r = manager_load_unit(m, name, NULL, &error, &u)) < 0)
1515 return bus_send_error_reply(connection, message, &error, r);
1517 if (reload_if_possible && unit_can_reload(u)) {
1518 if (job_type == JOB_RESTART)
1519 job_type = JOB_RELOAD_OR_START;
1520 else if (job_type == JOB_TRY_RESTART)
1521 job_type = JOB_RELOAD;
1524 if ((job_type == JOB_START && u->refuse_manual_start) ||
1525 (job_type == JOB_STOP && u->refuse_manual_stop) ||
1526 ((job_type == JOB_RESTART || job_type == JOB_TRY_RESTART) &&
1527 (u->refuse_manual_start || u->refuse_manual_stop))) {
1528 dbus_set_error(&error, BUS_ERROR_ONLY_BY_DEPENDENCY, "Operation refused, may be requested by dependency only.");
1529 return bus_send_error_reply(connection, message, &error, -EPERM);
1532 if ((r = manager_add_job(m, job_type, u, mode, true, &error, &j)) < 0)
1533 return bus_send_error_reply(connection, message, &error, r);
1535 cl = job_bus_client_new(connection, message_get_sender_with_fallback(message));
1539 LIST_PREPEND(JobBusClient, client, j->bus_client_list, cl);
1541 if (!(reply = dbus_message_new_method_return(message)))
1544 if (!(path = job_dbus_path(j)))
1547 if (!dbus_message_append_args(
1549 DBUS_TYPE_OBJECT_PATH, &path,
1555 if (!dbus_connection_send(connection, reply, NULL))
1558 dbus_message_unref(reply);
1563 return DBUS_HANDLER_RESULT_HANDLED;
1569 dbus_message_unref(reply);
1571 dbus_error_free(&error);
1573 return DBUS_HANDLER_RESULT_NEED_MEMORY;
1576 const DBusObjectPathVTable bus_manager_vtable = {
1577 .message_function = bus_manager_message_handler