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/>.
22 #include <sys/epoll.h>
23 #include <sys/timerfd.h>
32 #include "dbus-unit.h"
34 #include "dbus-manager.h"
35 #include "dbus-execute.h"
36 #include "dbus-kill.h"
37 #include "dbus-cgroup.h"
41 #include "bus-error.h"
42 #include "bus-errors.h"
44 #include "bus-internal.h"
45 #include "selinux-access.h"
47 #define CONNECTIONS_MAX 512
49 static void destroy_bus(Manager *m, sd_bus **bus);
51 int bus_send_queued_message(Manager *m) {
56 if (!m->queued_message)
59 assert(m->queued_message_bus);
61 /* If we cannot get rid of this message we won't dispatch any
62 * D-Bus messages, so that we won't end up wanting to queue
65 r = sd_bus_send(m->queued_message_bus, m->queued_message, NULL);
67 log_warning("Failed to send queued message: %s", strerror(-r));
69 m->queued_message = sd_bus_message_unref(m->queued_message);
70 m->queued_message_bus = sd_bus_unref(m->queued_message_bus);
75 static int signal_agent_released(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
76 Manager *m = userdata;
84 r = sd_bus_message_read(message, "s", &cgroup);
86 bus_log_parse_error(r);
90 manager_notify_cgroup_empty(m, cgroup);
92 if (m->running_as == SYSTEMD_SYSTEM && m->system_bus) {
93 /* If we are running as system manager, forward the
94 * message to the system bus */
96 r = sd_bus_send(m->system_bus, message, NULL);
98 log_warning("Failed to forward Released message: %s", strerror(-r));
104 static int signal_disconnected(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
105 Manager *m = userdata;
111 if (bus == m->api_bus)
112 destroy_bus(m, &m->api_bus);
113 if (bus == m->system_bus)
114 destroy_bus(m, &m->system_bus);
115 if (set_remove(m->private_buses, bus)) {
116 log_debug("Got disconnect on private connection.");
117 destroy_bus(m, &bus);
123 static int signal_name_owner_changed(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
124 const char *name, *old_owner, *new_owner;
125 Manager *m = userdata;
132 r = sd_bus_message_read(message, "sss", &name, &old_owner, &new_owner);
134 bus_log_parse_error(r);
138 manager_dispatch_bus_name_owner_changed(
140 isempty(old_owner) ? NULL : old_owner,
141 isempty(new_owner) ? NULL : new_owner);
146 static int signal_activation_request(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *ret_error) {
147 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
148 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
149 Manager *m = userdata;
158 r = sd_bus_message_read(message, "s", &name);
160 bus_log_parse_error(r);
164 /* In Tizen 2.4 with kdbus enabled this check not only makes no sense, it will break activation because dbus.socket is always inactive. */
165 if (m->kdbus_fd < 0 &&
166 (manager_unit_inactive_or_pending(m, SPECIAL_DBUS_SERVICE) ||
167 manager_unit_inactive_or_pending(m, SPECIAL_DBUS_SOCKET))) {
168 r = sd_bus_error_setf(&error, BUS_ERROR_SHUTTING_DOWN, "Refusing activation, D-Bus is shutting down.");
172 r = manager_load_unit(m, name, NULL, &error, &u);
176 if (u->refuse_manual_start) {
177 r = sd_bus_error_setf(&error, BUS_ERROR_ONLY_BY_DEPENDENCY, "Operation refused, %s may be requested by dependency only.", u->id);
181 r = manager_add_job(m, JOB_START, u, JOB_REPLACE, true, &error, NULL);
185 /* Successfully queued, that's it for us */
189 if (!sd_bus_error_is_set(&error))
190 sd_bus_error_set_errno(&error, r);
192 log_debug("D-Bus activation failed for %s: %s", name, bus_error_message(&error, r));
194 r = sd_bus_message_new_signal(bus, &reply, "/org/freedesktop/systemd1", "org.freedesktop.systemd1.Activator", "ActivationFailure");
196 bus_log_create_error(r);
200 r = sd_bus_message_append(reply, "sss", name, error.name, error.message);
202 bus_log_create_error(r);
206 r = sd_bus_send_to(bus, reply, "org.freedesktop.DBus", NULL);
208 log_error("Failed to respond with to bus activation request: %s", strerror(-r));
216 static int selinux_filter(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
217 Manager *m = userdata;
218 const char *verb, *path;
226 /* Our own method calls are all protected individually with
227 * selinux checks, but the built-in interfaces need to be
230 if (sd_bus_message_is_method_call(message, "org.freedesktop.DBus.Properties", "Set"))
232 else if (sd_bus_message_is_method_call(message, "org.freedesktop.DBus.Introspectable", NULL) ||
233 sd_bus_message_is_method_call(message, "org.freedesktop.DBus.Properties", NULL) ||
234 sd_bus_message_is_method_call(message, "org.freedesktop.DBus.ObjectManager", NULL) ||
235 sd_bus_message_is_method_call(message, "org.freedesktop.DBus.Peer", NULL))
240 path = sd_bus_message_get_path(message);
242 if (object_path_startswith("/org/freedesktop/systemd1", path)) {
244 r = selinux_access_check(message, verb, error);
251 if (streq_ptr(path, "/org/freedesktop/systemd1/unit/self")) {
252 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
255 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_PID, &creds);
259 r = sd_bus_creds_get_pid(creds, &pid);
263 u = manager_get_unit_by_pid(m, pid);
265 r = manager_get_job_from_dbus_path(m, path, &j);
269 manager_load_unit_from_dbus_path(m, path, NULL, &u);
275 r = selinux_unit_access_check(u, message, verb, error);
283 static int bus_job_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error) {
284 Manager *m = userdata;
294 r = manager_get_job_from_dbus_path(m, path, &j);
302 static int find_unit(Manager *m, sd_bus *bus, const char *path, Unit **unit, sd_bus_error *error) {
310 if (streq_ptr(path, "/org/freedesktop/systemd1/unit/self")) {
311 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
312 sd_bus_message *message;
315 message = sd_bus_get_current_message(bus);
319 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_PID, &creds);
323 r = sd_bus_creds_get_pid(creds, &pid);
327 u = manager_get_unit_by_pid(m, pid);
329 r = manager_load_unit_from_dbus_path(m, path, error, &u);
341 static int bus_unit_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error) {
342 Manager *m = userdata;
350 return find_unit(m, bus, path, (Unit**) found, error);
353 static int bus_unit_interface_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error) {
354 Manager *m = userdata;
364 r = find_unit(m, bus, path, &u, error);
368 if (!streq_ptr(interface, UNIT_VTABLE(u)->bus_interface))
375 static int bus_unit_cgroup_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error) {
376 Manager *m = userdata;
386 r = find_unit(m, bus, path, &u, error);
390 if (!streq_ptr(interface, UNIT_VTABLE(u)->bus_interface))
393 if (!unit_get_cgroup_context(u))
400 static int bus_cgroup_context_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error) {
401 Manager *m = userdata;
412 r = find_unit(m, bus, path, &u, error);
416 if (!streq_ptr(interface, UNIT_VTABLE(u)->bus_interface))
419 c = unit_get_cgroup_context(u);
427 static int bus_exec_context_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error) {
428 Manager *m = userdata;
439 r = find_unit(m, bus, path, &u, error);
443 if (!streq_ptr(interface, UNIT_VTABLE(u)->bus_interface))
446 c = unit_get_exec_context(u);
454 static int bus_kill_context_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error) {
455 Manager *m = userdata;
466 r = find_unit(m, bus, path, &u, error);
470 if (!streq_ptr(interface, UNIT_VTABLE(u)->bus_interface))
473 c = unit_get_kill_context(u);
481 static int bus_job_enumerate(sd_bus *bus, const char *path, void *userdata, char ***nodes, sd_bus_error *error) {
482 _cleanup_free_ char **l = NULL;
483 Manager *m = userdata;
488 l = new0(char*, hashmap_size(m->jobs)+1);
492 HASHMAP_FOREACH(j, m->jobs, i) {
493 l[k] = job_dbus_path(j);
500 assert(hashmap_size(m->jobs) == k);
508 static int bus_unit_enumerate(sd_bus *bus, const char *path, void *userdata, char ***nodes, sd_bus_error *error) {
509 _cleanup_free_ char **l = NULL;
510 Manager *m = userdata;
515 l = new0(char*, hashmap_size(m->units)+1);
519 HASHMAP_FOREACH(u, m->units, i) {
520 l[k] = unit_dbus_path(u);
533 static int bus_setup_api_vtables(Manager *m, sd_bus *bus) {
541 r = sd_bus_add_filter(bus, NULL, selinux_filter, m);
543 log_error("Failed to add SELinux access filter: %s", strerror(-r));
548 r = sd_bus_add_object_vtable(bus, NULL, "/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", bus_manager_vtable, m);
550 log_error("Failed to register Manager vtable: %s", strerror(-r));
554 r = sd_bus_add_fallback_vtable(bus, NULL, "/org/freedesktop/systemd1/job", "org.freedesktop.systemd1.Job", bus_job_vtable, bus_job_find, m);
556 log_error("Failed to register Job vtable: %s", strerror(-r));
560 r = sd_bus_add_node_enumerator(bus, NULL, "/org/freedesktop/systemd1/job", bus_job_enumerate, m);
562 log_error("Failed to add job enumerator: %s", strerror(-r));
566 r = sd_bus_add_fallback_vtable(bus, NULL, "/org/freedesktop/systemd1/unit", "org.freedesktop.systemd1.Unit", bus_unit_vtable, bus_unit_find, m);
568 log_error("Failed to register Unit vtable: %s", strerror(-r));
572 r = sd_bus_add_node_enumerator(bus, NULL, "/org/freedesktop/systemd1/unit", bus_unit_enumerate, m);
574 log_error("Failed to add job enumerator: %s", strerror(-r));
578 for (t = 0; t < _UNIT_TYPE_MAX; t++) {
579 r = sd_bus_add_fallback_vtable(bus, NULL, "/org/freedesktop/systemd1/unit", unit_vtable[t]->bus_interface, unit_vtable[t]->bus_vtable, bus_unit_interface_find, m);
581 log_error("Failed to register type specific vtable for %s: %s", unit_vtable[t]->bus_interface, strerror(-r));
585 if (unit_vtable[t]->cgroup_context_offset > 0) {
586 r = sd_bus_add_fallback_vtable(bus, NULL, "/org/freedesktop/systemd1/unit", unit_vtable[t]->bus_interface, bus_unit_cgroup_vtable, bus_unit_cgroup_find, m);
588 log_error("Failed to register control group unit vtable for %s: %s", unit_vtable[t]->bus_interface, strerror(-r));
592 r = sd_bus_add_fallback_vtable(bus, NULL, "/org/freedesktop/systemd1/unit", unit_vtable[t]->bus_interface, bus_cgroup_vtable, bus_cgroup_context_find, m);
594 log_error("Failed to register control group vtable for %s: %s", unit_vtable[t]->bus_interface, strerror(-r));
599 if (unit_vtable[t]->exec_context_offset > 0) {
600 r = sd_bus_add_fallback_vtable(bus, NULL, "/org/freedesktop/systemd1/unit", unit_vtable[t]->bus_interface, bus_exec_vtable, bus_exec_context_find, m);
602 log_error("Failed to register execute vtable for %s: %s", unit_vtable[t]->bus_interface, strerror(-r));
607 if (unit_vtable[t]->kill_context_offset > 0) {
608 r = sd_bus_add_fallback_vtable(bus, NULL, "/org/freedesktop/systemd1/unit", unit_vtable[t]->bus_interface, bus_kill_vtable, bus_kill_context_find, m);
610 log_error("Failed to register kill vtable for %s: %s", unit_vtable[t]->bus_interface, strerror(-r));
619 static int bus_setup_disconnected_match(Manager *m, sd_bus *bus) {
625 r = sd_bus_add_match(
628 "sender='org.freedesktop.DBus.Local',"
630 "path='/org/freedesktop/DBus/Local',"
631 "interface='org.freedesktop.DBus.Local',"
632 "member='Disconnected'",
633 signal_disconnected, m);
636 log_error("Failed to register match for Disconnected message: %s", strerror(-r));
643 static int bus_on_connection(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
644 _cleanup_bus_unref_ sd_bus *bus = NULL;
645 _cleanup_close_ int nfd = -1;
646 Manager *m = userdata;
653 nfd = accept4(fd, NULL, NULL, SOCK_NONBLOCK|SOCK_CLOEXEC);
655 log_warning("Failed to accept private connection, ignoring: %m");
659 if (set_size(m->private_buses) >= CONNECTIONS_MAX) {
660 log_warning("Too many concurrent connections, refusing");
664 r = set_ensure_allocated(&m->private_buses, trivial_hash_func, trivial_compare_func);
670 r = sd_bus_new(&bus);
672 log_warning("Failed to allocate new private connection bus: %s", strerror(-r));
676 r = sd_bus_set_fd(bus, nfd, nfd);
678 log_warning("Failed to set fd on new connection bus: %s", strerror(-r));
684 r = bus_check_peercred(bus);
686 log_warning("Incoming private connection from unprivileged client, refusing: %s", strerror(-r));
690 assert_se(sd_id128_randomize(&id) >= 0);
692 r = sd_bus_set_server(bus, 1, id);
694 log_warning("Failed to enable server support for new connection bus: %s", strerror(-r));
698 r = sd_bus_start(bus);
700 log_warning("Failed to start new connection bus: %s", strerror(-r));
704 r = sd_bus_attach_event(bus, m->event, SD_EVENT_PRIORITY_NORMAL);
706 log_warning("Failed to attach new connection bus to event loop: %s", strerror(-r));
710 if (m->running_as == SYSTEMD_SYSTEM) {
711 /* When we run as system instance we get the Released
712 * signal via a direct connection */
714 r = sd_bus_add_match(
718 "interface='org.freedesktop.systemd1.Agent',"
720 "path='/org/freedesktop/systemd1/agent'",
721 signal_agent_released, m);
724 log_warning("Failed to register Released match on new connection bus: %s", strerror(-r));
729 r = bus_setup_disconnected_match(m, bus);
733 r = bus_setup_api_vtables(m, bus);
735 log_warning("Failed to set up API vtables on new connection bus: %s", strerror(-r));
739 r = set_put(m->private_buses, bus);
741 log_warning("Failed to add new conenction bus to set: %s", strerror(-r));
747 log_debug("Accepted new private connection.");
752 static int bus_list_names(Manager *m, sd_bus *bus) {
753 _cleanup_strv_free_ char **names = NULL;
760 r = sd_bus_list_names(bus, &names, NULL);
762 log_error("Failed to get initial list of names: %s", strerror(-r));
766 /* This is a bit hacky, we say the owner of the name is the
767 * name itself, because we don't want the extra traffic to
768 * figure out the real owner. */
769 STRV_FOREACH(i, names)
770 manager_dispatch_bus_name_owner_changed(m, *i, NULL, *i);
775 static int bus_setup_api(Manager *m, sd_bus *bus) {
781 r = bus_setup_api_vtables(m, bus);
785 r = sd_bus_add_match(
789 "sender='org.freedesktop.DBus',"
790 "path='/org/freedesktop/DBus',"
791 "interface='org.freedesktop.DBus',"
792 "member='NameOwnerChanged'",
793 signal_name_owner_changed, m);
795 log_warning("Failed to subscribe to NameOwnerChanged signal: %s", strerror(-r));
797 r = sd_bus_add_match(
801 "sender='org.freedesktop.DBus',"
802 "path='/org/freedesktop/DBus',"
803 "interface='org.freedesktop.systemd1.Activator',"
804 "member='ActivationRequest'",
805 signal_activation_request, m);
807 log_warning("Failed to subscribe to activation signal: %s", strerror(-r));
809 /* Allow replacing of our name, to ease implementation of
810 * reexecution, where we keep the old connection open until
811 * after the new connection is set up and the name installed
812 * to allow clients to synchronously wait for reexecution to
814 r = sd_bus_request_name(bus,"org.freedesktop.systemd1", SD_BUS_NAME_REPLACE_EXISTING|SD_BUS_NAME_ALLOW_REPLACEMENT);
816 log_error("Failed to register name: %s", strerror(-r));
820 bus_list_names(m, bus);
822 log_debug("Successfully connected to API bus.");
826 static int bus_init_api(Manager *m) {
827 _cleanup_bus_unref_ sd_bus *bus = NULL;
833 /* The API and system bus is the same if we are running in system mode */
834 if (m->running_as == SYSTEMD_SYSTEM && m->system_bus)
835 bus = sd_bus_ref(m->system_bus);
837 if (m->running_as == SYSTEMD_SYSTEM)
838 r = sd_bus_open_system(&bus);
840 r = sd_bus_open_user(&bus);
843 log_debug("Failed to connect to API bus, retrying later...");
847 r = sd_bus_attach_event(bus, m->event, SD_EVENT_PRIORITY_NORMAL);
849 log_error("Failed to attach API bus to event loop: %s", strerror(-r));
853 r = bus_setup_disconnected_match(m, bus);
858 r = bus_setup_api(m, bus);
860 log_error("Failed to set up API bus: %s", strerror(-r));
870 static int bus_setup_system(Manager *m, sd_bus *bus) {
876 if (m->running_as == SYSTEMD_SYSTEM)
879 /* If we are a user instance we get the Released message via
881 r = sd_bus_add_match(
885 "interface='org.freedesktop.systemd1.Agent',"
887 "path='/org/freedesktop/systemd1/agent'",
888 signal_agent_released, m);
891 log_warning("Failed to register Released match on system bus: %s", strerror(-r));
893 log_debug("Successfully connected to system bus.");
897 static int bus_init_system(Manager *m) {
898 _cleanup_bus_unref_ sd_bus *bus = NULL;
904 /* The API and system bus is the same if we are running in system mode */
905 if (m->running_as == SYSTEMD_SYSTEM && m->api_bus) {
906 m->system_bus = sd_bus_ref(m->api_bus);
910 r = sd_bus_open_system(&bus);
912 log_debug("Failed to connect to system bus, retrying later...");
916 r = bus_setup_disconnected_match(m, bus);
920 r = sd_bus_attach_event(bus, m->event, SD_EVENT_PRIORITY_NORMAL);
922 log_error("Failed to attach system bus to event loop: %s", strerror(-r));
926 r = bus_setup_system(m, bus);
928 log_error("Failed to set up system bus: %s", strerror(-r));
938 static int bus_init_private(Manager *m) {
939 _cleanup_close_ int fd = -1;
940 union sockaddr_union sa = {
941 .un.sun_family = AF_UNIX
949 if (m->private_listen_fd >= 0)
952 /* We don't need the private socket if we have kdbus */
953 if (m->kdbus_fd >= 0)
956 if (m->running_as == SYSTEMD_SYSTEM) {
958 /* We want the private bus only when running as init */
962 strcpy(sa.un.sun_path, "/run/systemd/private");
963 salen = offsetof(union sockaddr_union, un.sun_path) + strlen("/run/systemd/private");
965 size_t left = sizeof(sa.un.sun_path);
966 char *p = sa.un.sun_path;
969 e = secure_getenv("XDG_RUNTIME_DIR");
971 log_error("Failed to determine XDG_RUNTIME_DIR");
975 left = strpcpy(&p, left, e);
976 left = strpcpy(&p, left, "/systemd/private");
978 salen = sizeof(sa.un) - left;
980 mkdir_parents_label(sa.un.sun_path, 0755);
983 unlink(sa.un.sun_path);
985 fd = socket(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
987 log_error("Failed to allocate private socket: %m");
991 r = bind(fd, &sa.sa, salen);
993 log_error("Failed to bind private socket: %m");
997 r = listen(fd, SOMAXCONN);
999 log_error("Failed to make private socket listening: %m");
1003 r = sd_event_add_io(m->event, &s, fd, EPOLLIN, bus_on_connection, m);
1005 log_error("Failed to allocate event source: %s", strerror(-r));
1009 m->private_listen_fd = fd;
1010 m->private_listen_event_source = s;
1013 log_debug("Successfully created private D-Bus server.");
1018 int bus_init(Manager *m, bool try_bus_connect) {
1021 if (try_bus_connect) {
1022 r = bus_init_system(m);
1026 r = bus_init_api(m);
1031 r = bus_init_private(m);
1038 static void destroy_bus(Manager *m, sd_bus **bus) {
1048 /* Get rid of tracked clients on this bus */
1049 if (m->subscribed && sd_bus_track_get_bus(m->subscribed) == *bus)
1050 m->subscribed = sd_bus_track_unref(m->subscribed);
1052 HASHMAP_FOREACH(j, m->jobs, i)
1053 if (j->clients && sd_bus_track_get_bus(j->clients) == *bus)
1054 j->clients = sd_bus_track_unref(j->clients);
1056 /* Get rid of queued message on this bus */
1057 if (m->queued_message_bus == *bus) {
1058 m->queued_message_bus = sd_bus_unref(m->queued_message_bus);
1060 if (m->queued_message)
1061 m->queued_message = sd_bus_message_unref(m->queued_message);
1064 /* Possibly flush unwritten data, but only if we are
1065 * unprivileged, since we don't want to sync here */
1066 if (m->running_as != SYSTEMD_SYSTEM)
1069 /* And destroy the object */
1071 *bus = sd_bus_unref(*bus);
1074 void bus_done(Manager *m) {
1080 destroy_bus(m, &m->api_bus);
1082 destroy_bus(m, &m->system_bus);
1083 while ((b = set_steal_first(m->private_buses)))
1086 set_free(m->private_buses);
1087 m->private_buses = NULL;
1089 m->subscribed = sd_bus_track_unref(m->subscribed);
1090 strv_free(m->deserialized_subscribed);
1091 m->deserialized_subscribed = NULL;
1093 if (m->private_listen_event_source)
1094 m->private_listen_event_source = sd_event_source_unref(m->private_listen_event_source);
1096 m->private_listen_fd = safe_close(m->private_listen_fd);
1098 bus_verify_polkit_async_registry_free(m->polkit_registry);
1101 int bus_fdset_add_all(Manager *m, FDSet *fds) {
1109 /* When we are about to reexecute we add all D-Bus fds to the
1110 * set to pass over to the newly executed systemd. They won't
1111 * be used there however, except thatt they are closed at the
1112 * very end of deserialization, those making it possible for
1113 * clients to synchronously wait for systemd to reexec by
1114 * simply waiting for disconnection */
1117 fd = sd_bus_get_fd(m->api_bus);
1119 fd = fdset_put_dup(fds, fd);
1125 SET_FOREACH(b, m->private_buses, i) {
1126 fd = sd_bus_get_fd(b);
1128 fd = fdset_put_dup(fds, fd);
1134 /* We don't offer any APIs on the system bus (well, unless it
1135 * is the same as the API bus) hence we don't bother with it
1141 int bus_foreach_bus(
1143 sd_bus_track *subscribed2,
1144 int (*send_message)(sd_bus *bus, void *userdata),
1151 /* Send to all direct busses, unconditionally */
1152 SET_FOREACH(b, m->private_buses, i) {
1153 r = send_message(b, userdata);
1158 /* Send to API bus, but only if somebody is subscribed */
1159 if (sd_bus_track_count(m->subscribed) > 0 ||
1160 sd_bus_track_count(subscribed2) > 0) {
1161 r = send_message(m->api_bus, userdata);
1169 void bus_track_serialize(sd_bus_track *t, FILE *f) {
1174 for (n = sd_bus_track_first(t); n; n = sd_bus_track_next(t))
1175 fprintf(f, "subscribed=%s\n", n);
1178 int bus_track_deserialize_item(char ***l, const char *line) {
1184 e = startswith(line, "subscribed=");
1188 return strv_extend(l, e);
1191 int bus_track_coldplug(Manager *m, sd_bus_track **t, char ***l) {
1198 if (!strv_isempty(*l) && m->api_bus) {
1202 r = sd_bus_track_new(m->api_bus, t, NULL, NULL);
1208 STRV_FOREACH(i, *l) {
1211 k = sd_bus_track_add_name(*t, *i);
1223 int bus_verify_manage_unit_async(Manager *m, sd_bus_message *call, sd_bus_error *error) {
1224 return bus_verify_polkit_async(call, CAP_SYS_ADMIN, "org.freedesktop.systemd1.manage-units", false, &m->polkit_registry, error);
1227 /* Same as bus_verify_manage_unit_async(), but checks for CAP_KILL instead of CAP_SYS_ADMIN */
1228 int bus_verify_manage_unit_async_for_kill(Manager *m, sd_bus_message *call, sd_bus_error *error) {
1229 return bus_verify_polkit_async(call, CAP_KILL, "org.freedesktop.systemd1.manage-units", false, &m->polkit_registry, error);
1232 int bus_verify_manage_unit_files_async(Manager *m, sd_bus_message *call, sd_bus_error *error) {
1233 return bus_verify_polkit_async(call, CAP_SYS_ADMIN, "org.freedesktop.systemd1.manage-unit-files", false, &m->polkit_registry, error);
1236 int bus_verify_reload_daemon_async(Manager *m, sd_bus_message *call, sd_bus_error *error) {
1237 return bus_verify_polkit_async(call, CAP_SYS_ADMIN, "org.freedesktop.systemd1.reload-daemon", false, &m->polkit_registry, error);