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>
31 #include "dbus-unit.h"
33 #include "dbus-manager.h"
34 #include "dbus-execute.h"
35 #include "dbus-kill.h"
36 #include "dbus-cgroup.h"
40 #include "bus-error.h"
41 #include "bus-common-errors.h"
43 #include "bus-internal.h"
44 #include "selinux-access.h"
46 #define CONNECTIONS_MAX 4096
48 static void destroy_bus(Manager *m, sd_bus **bus);
50 int bus_send_queued_message(Manager *m) {
55 if (!m->queued_message)
58 assert(m->queued_message_bus);
60 /* If we cannot get rid of this message we won't dispatch any
61 * D-Bus messages, so that we won't end up wanting to queue
64 r = sd_bus_send(m->queued_message_bus, m->queued_message, NULL);
66 log_warning_errno(r, "Failed to send queued message: %m");
68 m->queued_message = sd_bus_message_unref(m->queued_message);
69 m->queued_message_bus = sd_bus_unref(m->queued_message_bus);
74 static int signal_agent_released(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
75 Manager *m = userdata;
83 r = sd_bus_message_read(message, "s", &cgroup);
85 bus_log_parse_error(r);
89 manager_notify_cgroup_empty(m, cgroup);
91 /* only forward to system bus if running as system instance */
92 if (m->running_as != SYSTEMD_SYSTEM || !m->system_bus)
95 r = sd_bus_message_rewind(message, 1);
99 r = sd_bus_send(m->system_bus, message, NULL);
103 log_warning_errno(r, "Failed to forward Released message: %m");
107 static int signal_disconnected(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
108 Manager *m = userdata;
114 if (bus == m->api_bus)
115 destroy_bus(m, &m->api_bus);
116 if (bus == m->system_bus)
117 destroy_bus(m, &m->system_bus);
118 if (set_remove(m->private_buses, bus)) {
119 log_debug("Got disconnect on private connection.");
120 destroy_bus(m, &bus);
126 static int signal_name_owner_changed(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
127 const char *name, *old_owner, *new_owner;
128 Manager *m = userdata;
135 r = sd_bus_message_read(message, "sss", &name, &old_owner, &new_owner);
137 bus_log_parse_error(r);
141 manager_dispatch_bus_name_owner_changed(
143 isempty(old_owner) ? NULL : old_owner,
144 isempty(new_owner) ? NULL : new_owner);
149 static int signal_activation_request(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *ret_error) {
150 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
151 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
152 Manager *m = userdata;
161 r = sd_bus_message_read(message, "s", &name);
163 bus_log_parse_error(r);
167 if (manager_unit_inactive_or_pending(m, SPECIAL_DBUS_SERVICE) ||
168 manager_unit_inactive_or_pending(m, SPECIAL_DBUS_SOCKET)) {
169 r = sd_bus_error_setf(&error, BUS_ERROR_SHUTTING_DOWN, "Refusing activation, D-Bus is shutting down.");
173 r = manager_load_unit(m, name, NULL, &error, &u);
177 if (u->refuse_manual_start) {
178 r = sd_bus_error_setf(&error, BUS_ERROR_ONLY_BY_DEPENDENCY, "Operation refused, %s may be requested by dependency only.", u->id);
182 r = manager_add_job(m, JOB_START, u, JOB_REPLACE, true, &error, NULL);
186 /* Successfully queued, that's it for us */
190 if (!sd_bus_error_is_set(&error))
191 sd_bus_error_set_errno(&error, r);
193 log_debug("D-Bus activation failed for %s: %s", name, bus_error_message(&error, r));
195 r = sd_bus_message_new_signal(bus, &reply, "/org/freedesktop/systemd1", "org.freedesktop.systemd1.Activator", "ActivationFailure");
197 bus_log_create_error(r);
201 r = sd_bus_message_append(reply, "sss", name, error.name, error.message);
203 bus_log_create_error(r);
207 r = sd_bus_send_to(bus, reply, "org.freedesktop.DBus", NULL);
209 return log_error_errno(r, "Failed to respond with to bus activation request: %m");
215 static int mac_selinux_filter(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
216 Manager *m = userdata;
217 const char *verb, *path;
225 /* Our own method calls are all protected individually with
226 * selinux checks, but the built-in interfaces need to be
229 if (sd_bus_message_is_method_call(message, "org.freedesktop.DBus.Properties", "Set"))
231 else if (sd_bus_message_is_method_call(message, "org.freedesktop.DBus.Introspectable", NULL) ||
232 sd_bus_message_is_method_call(message, "org.freedesktop.DBus.Properties", NULL) ||
233 sd_bus_message_is_method_call(message, "org.freedesktop.DBus.ObjectManager", NULL) ||
234 sd_bus_message_is_method_call(message, "org.freedesktop.DBus.Peer", NULL))
239 path = sd_bus_message_get_path(message);
241 if (object_path_startswith("/org/freedesktop/systemd1", path)) {
243 r = mac_selinux_access_check(message, verb, error);
250 if (streq_ptr(path, "/org/freedesktop/systemd1/unit/self")) {
251 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
254 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_PID, &creds);
258 r = sd_bus_creds_get_pid(creds, &pid);
262 u = manager_get_unit_by_pid(m, pid);
264 r = manager_get_job_from_dbus_path(m, path, &j);
268 manager_load_unit_from_dbus_path(m, path, NULL, &u);
274 r = mac_selinux_unit_access_check(u, message, verb, error);
282 static int bus_job_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error) {
283 Manager *m = userdata;
293 r = manager_get_job_from_dbus_path(m, path, &j);
301 static int find_unit(Manager *m, sd_bus *bus, const char *path, Unit **unit, sd_bus_error *error) {
309 if (streq_ptr(path, "/org/freedesktop/systemd1/unit/self")) {
310 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
311 sd_bus_message *message;
314 message = sd_bus_get_current_message(bus);
318 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_PID, &creds);
322 r = sd_bus_creds_get_pid(creds, &pid);
326 u = manager_get_unit_by_pid(m, pid);
328 r = manager_load_unit_from_dbus_path(m, path, error, &u);
340 static int bus_unit_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error) {
341 Manager *m = userdata;
349 return find_unit(m, bus, path, (Unit**) found, error);
352 static int bus_unit_interface_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error) {
353 Manager *m = userdata;
363 r = find_unit(m, bus, path, &u, error);
367 if (!streq_ptr(interface, UNIT_VTABLE(u)->bus_interface))
374 static int bus_unit_cgroup_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error) {
375 Manager *m = userdata;
385 r = find_unit(m, bus, path, &u, error);
389 if (!streq_ptr(interface, UNIT_VTABLE(u)->bus_interface))
392 if (!unit_get_cgroup_context(u))
399 static int bus_cgroup_context_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error) {
400 Manager *m = userdata;
411 r = find_unit(m, bus, path, &u, error);
415 if (!streq_ptr(interface, UNIT_VTABLE(u)->bus_interface))
418 c = unit_get_cgroup_context(u);
426 static int bus_exec_context_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error) {
427 Manager *m = userdata;
438 r = find_unit(m, bus, path, &u, error);
442 if (!streq_ptr(interface, UNIT_VTABLE(u)->bus_interface))
445 c = unit_get_exec_context(u);
453 static int bus_kill_context_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error) {
454 Manager *m = userdata;
465 r = find_unit(m, bus, path, &u, error);
469 if (!streq_ptr(interface, UNIT_VTABLE(u)->bus_interface))
472 c = unit_get_kill_context(u);
480 static int bus_job_enumerate(sd_bus *bus, const char *path, void *userdata, char ***nodes, sd_bus_error *error) {
481 _cleanup_free_ char **l = NULL;
482 Manager *m = userdata;
487 l = new0(char*, hashmap_size(m->jobs)+1);
491 HASHMAP_FOREACH(j, m->jobs, i) {
492 l[k] = job_dbus_path(j);
499 assert(hashmap_size(m->jobs) == k);
507 static int bus_unit_enumerate(sd_bus *bus, const char *path, void *userdata, char ***nodes, sd_bus_error *error) {
508 _cleanup_free_ char **l = NULL;
509 Manager *m = userdata;
514 l = new0(char*, hashmap_size(m->units)+1);
518 HASHMAP_FOREACH(u, m->units, i) {
519 l[k] = unit_dbus_path(u);
532 static int bus_setup_api_vtables(Manager *m, sd_bus *bus) {
540 r = sd_bus_add_filter(bus, NULL, mac_selinux_filter, m);
542 return log_error_errno(r, "Failed to add SELinux access filter: %m");
545 r = sd_bus_add_object_vtable(bus, NULL, "/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", bus_manager_vtable, m);
547 return log_error_errno(r, "Failed to register Manager vtable: %m");
549 r = sd_bus_add_fallback_vtable(bus, NULL, "/org/freedesktop/systemd1/job", "org.freedesktop.systemd1.Job", bus_job_vtable, bus_job_find, m);
551 return log_error_errno(r, "Failed to register Job vtable: %m");
553 r = sd_bus_add_node_enumerator(bus, NULL, "/org/freedesktop/systemd1/job", bus_job_enumerate, m);
555 return log_error_errno(r, "Failed to add job enumerator: %m");
557 r = sd_bus_add_fallback_vtable(bus, NULL, "/org/freedesktop/systemd1/unit", "org.freedesktop.systemd1.Unit", bus_unit_vtable, bus_unit_find, m);
559 return log_error_errno(r, "Failed to register Unit vtable: %m");
561 r = sd_bus_add_node_enumerator(bus, NULL, "/org/freedesktop/systemd1/unit", bus_unit_enumerate, m);
563 return log_error_errno(r, "Failed to add job enumerator: %m");
565 for (t = 0; t < _UNIT_TYPE_MAX; t++) {
566 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);
568 return log_error_errno(r, "Failed to register type specific vtable for %s: %m", unit_vtable[t]->bus_interface);
570 if (unit_vtable[t]->cgroup_context_offset > 0) {
571 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);
573 return log_error_errno(r, "Failed to register control group unit vtable for %s: %m", unit_vtable[t]->bus_interface);
575 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);
577 return log_error_errno(r, "Failed to register control group vtable for %s: %m", unit_vtable[t]->bus_interface);
580 if (unit_vtable[t]->exec_context_offset > 0) {
581 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);
583 return log_error_errno(r, "Failed to register execute vtable for %s: %m", unit_vtable[t]->bus_interface);
586 if (unit_vtable[t]->kill_context_offset > 0) {
587 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);
589 return log_error_errno(r, "Failed to register kill vtable for %s: %m", unit_vtable[t]->bus_interface);
596 static int bus_setup_disconnected_match(Manager *m, sd_bus *bus) {
602 r = sd_bus_add_match(
605 "sender='org.freedesktop.DBus.Local',"
607 "path='/org/freedesktop/DBus/Local',"
608 "interface='org.freedesktop.DBus.Local',"
609 "member='Disconnected'",
610 signal_disconnected, m);
613 return log_error_errno(r, "Failed to register match for Disconnected message: %m");
618 static int bus_on_connection(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
619 _cleanup_bus_unref_ sd_bus *bus = NULL;
620 _cleanup_close_ int nfd = -1;
621 Manager *m = userdata;
628 nfd = accept4(fd, NULL, NULL, SOCK_NONBLOCK|SOCK_CLOEXEC);
630 log_warning_errno(errno, "Failed to accept private connection, ignoring: %m");
634 if (set_size(m->private_buses) >= CONNECTIONS_MAX) {
635 log_warning("Too many concurrent connections, refusing");
639 r = set_ensure_allocated(&m->private_buses, NULL);
645 r = sd_bus_new(&bus);
647 log_warning_errno(r, "Failed to allocate new private connection bus: %m");
651 r = sd_bus_set_fd(bus, nfd, nfd);
653 log_warning_errno(r, "Failed to set fd on new connection bus: %m");
659 r = bus_check_peercred(bus);
661 log_warning_errno(r, "Incoming private connection from unprivileged client, refusing: %m");
665 assert_se(sd_id128_randomize(&id) >= 0);
667 r = sd_bus_set_server(bus, 1, id);
669 log_warning_errno(r, "Failed to enable server support for new connection bus: %m");
673 r = sd_bus_start(bus);
675 log_warning_errno(r, "Failed to start new connection bus: %m");
679 r = sd_bus_attach_event(bus, m->event, SD_EVENT_PRIORITY_NORMAL);
681 log_warning_errno(r, "Failed to attach new connection bus to event loop: %m");
685 if (m->running_as == SYSTEMD_SYSTEM) {
686 /* When we run as system instance we get the Released
687 * signal via a direct connection */
689 r = sd_bus_add_match(
693 "interface='org.freedesktop.systemd1.Agent',"
695 "path='/org/freedesktop/systemd1/agent'",
696 signal_agent_released, m);
699 log_warning_errno(r, "Failed to register Released match on new connection bus: %m");
704 r = bus_setup_disconnected_match(m, bus);
708 r = bus_setup_api_vtables(m, bus);
710 log_warning_errno(r, "Failed to set up API vtables on new connection bus: %m");
714 r = set_put(m->private_buses, bus);
716 log_warning_errno(r, "Failed to add new conenction bus to set: %m");
722 log_debug("Accepted new private connection.");
727 static int bus_list_names(Manager *m, sd_bus *bus) {
728 _cleanup_strv_free_ char **names = NULL;
735 r = sd_bus_list_names(bus, &names, NULL);
737 return log_error_errno(r, "Failed to get initial list of names: %m");
739 /* This is a bit hacky, we say the owner of the name is the
740 * name itself, because we don't want the extra traffic to
741 * figure out the real owner. */
742 STRV_FOREACH(i, names)
743 manager_dispatch_bus_name_owner_changed(m, *i, NULL, *i);
748 static int bus_setup_api(Manager *m, sd_bus *bus) {
754 /* Let's make sure we have enough credential bits so that we can make security and selinux decisions */
755 r = sd_bus_negotiate_creds(bus, 1,
756 SD_BUS_CREDS_PID|SD_BUS_CREDS_UID|
757 SD_BUS_CREDS_EUID|SD_BUS_CREDS_EFFECTIVE_CAPS|
758 SD_BUS_CREDS_SELINUX_CONTEXT);
760 log_warning_errno(r, "Failed to enable credential passing, ignoring: %m");
762 r = bus_setup_api_vtables(m, bus);
766 r = sd_bus_add_match(
770 "sender='org.freedesktop.DBus',"
771 "path='/org/freedesktop/DBus',"
772 "interface='org.freedesktop.DBus',"
773 "member='NameOwnerChanged'",
774 signal_name_owner_changed, m);
776 log_warning_errno(r, "Failed to subscribe to NameOwnerChanged signal: %m");
778 r = sd_bus_add_match(
782 "sender='org.freedesktop.DBus',"
783 "path='/org/freedesktop/DBus',"
784 "interface='org.freedesktop.systemd1.Activator',"
785 "member='ActivationRequest'",
786 signal_activation_request, m);
788 log_warning_errno(r, "Failed to subscribe to activation signal: %m");
790 /* Allow replacing of our name, to ease implementation of
791 * reexecution, where we keep the old connection open until
792 * after the new connection is set up and the name installed
793 * to allow clients to synchronously wait for reexecution to
795 r = sd_bus_request_name(bus,"org.freedesktop.systemd1", SD_BUS_NAME_REPLACE_EXISTING|SD_BUS_NAME_ALLOW_REPLACEMENT);
797 return log_error_errno(r, "Failed to register name: %m");
799 bus_list_names(m, bus);
801 log_debug("Successfully connected to API bus.");
805 static int bus_init_api(Manager *m) {
806 _cleanup_bus_unref_ sd_bus *bus = NULL;
812 /* The API and system bus is the same if we are running in system mode */
813 if (m->running_as == SYSTEMD_SYSTEM && m->system_bus)
814 bus = sd_bus_ref(m->system_bus);
816 if (m->running_as == SYSTEMD_SYSTEM)
817 r = sd_bus_open_system(&bus);
819 r = sd_bus_open_user(&bus);
822 log_debug("Failed to connect to API bus, retrying later...");
826 r = sd_bus_attach_event(bus, m->event, SD_EVENT_PRIORITY_NORMAL);
828 log_error_errno(r, "Failed to attach API bus to event loop: %m");
832 r = bus_setup_disconnected_match(m, bus);
837 r = bus_setup_api(m, bus);
839 log_error_errno(r, "Failed to set up API bus: %m");
849 static int bus_setup_system(Manager *m, sd_bus *bus) {
855 if (m->running_as == SYSTEMD_SYSTEM)
858 /* If we are a user instance we get the Released message via
860 r = sd_bus_add_match(
864 "interface='org.freedesktop.systemd1.Agent',"
866 "path='/org/freedesktop/systemd1/agent'",
867 signal_agent_released, m);
870 log_warning_errno(r, "Failed to register Released match on system bus: %m");
872 log_debug("Successfully connected to system bus.");
876 static int bus_init_system(Manager *m) {
877 _cleanup_bus_unref_ sd_bus *bus = NULL;
883 /* The API and system bus is the same if we are running in system mode */
884 if (m->running_as == SYSTEMD_SYSTEM && m->api_bus) {
885 m->system_bus = sd_bus_ref(m->api_bus);
889 r = sd_bus_open_system(&bus);
891 log_debug("Failed to connect to system bus, retrying later...");
895 r = bus_setup_disconnected_match(m, bus);
899 r = sd_bus_attach_event(bus, m->event, SD_EVENT_PRIORITY_NORMAL);
901 log_error_errno(r, "Failed to attach system bus to event loop: %m");
905 r = bus_setup_system(m, bus);
907 log_error_errno(r, "Failed to set up system bus: %m");
917 static int bus_init_private(Manager *m) {
918 _cleanup_close_ int fd = -1;
919 union sockaddr_union sa = {
920 .un.sun_family = AF_UNIX
928 if (m->private_listen_fd >= 0)
931 /* We don't need the private socket if we have kdbus */
932 if (m->kdbus_fd >= 0)
935 if (m->running_as == SYSTEMD_SYSTEM) {
937 /* We want the private bus only when running as init */
941 strcpy(sa.un.sun_path, "/run/systemd/private");
942 salen = offsetof(union sockaddr_union, un.sun_path) + strlen("/run/systemd/private");
944 size_t left = sizeof(sa.un.sun_path);
945 char *p = sa.un.sun_path;
948 e = secure_getenv("XDG_RUNTIME_DIR");
950 log_error("Failed to determine XDG_RUNTIME_DIR");
954 left = strpcpy(&p, left, e);
955 left = strpcpy(&p, left, "/systemd/private");
957 salen = sizeof(sa.un) - left;
960 (void) mkdir_parents_label(sa.un.sun_path, 0755);
961 (void) unlink(sa.un.sun_path);
963 fd = socket(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
965 return log_error_errno(errno, "Failed to allocate private socket: %m");
967 r = bind(fd, &sa.sa, salen);
969 return log_error_errno(errno, "Failed to bind private socket: %m");
971 r = listen(fd, SOMAXCONN);
973 return log_error_errno(errno, "Failed to make private socket listening: %m");
975 r = sd_event_add_io(m->event, &s, fd, EPOLLIN, bus_on_connection, m);
977 return log_error_errno(r, "Failed to allocate event source: %m");
979 m->private_listen_fd = fd;
980 m->private_listen_event_source = s;
983 log_debug("Successfully created private D-Bus server.");
988 int bus_init(Manager *m, bool try_bus_connect) {
991 if (try_bus_connect) {
992 r = bus_init_system(m);
1001 r = bus_init_private(m);
1008 static void destroy_bus(Manager *m, sd_bus **bus) {
1018 /* Get rid of tracked clients on this bus */
1019 if (m->subscribed && sd_bus_track_get_bus(m->subscribed) == *bus)
1020 m->subscribed = sd_bus_track_unref(m->subscribed);
1022 HASHMAP_FOREACH(j, m->jobs, i)
1023 if (j->clients && sd_bus_track_get_bus(j->clients) == *bus)
1024 j->clients = sd_bus_track_unref(j->clients);
1026 /* Get rid of queued message on this bus */
1027 if (m->queued_message_bus == *bus) {
1028 m->queued_message_bus = sd_bus_unref(m->queued_message_bus);
1030 if (m->queued_message)
1031 m->queued_message = sd_bus_message_unref(m->queued_message);
1034 /* Possibly flush unwritten data, but only if we are
1035 * unprivileged, since we don't want to sync here */
1036 if (m->running_as != SYSTEMD_SYSTEM)
1039 /* And destroy the object */
1041 *bus = sd_bus_unref(*bus);
1044 void bus_done(Manager *m) {
1050 destroy_bus(m, &m->api_bus);
1052 destroy_bus(m, &m->system_bus);
1053 while ((b = set_steal_first(m->private_buses)))
1056 set_free(m->private_buses);
1057 m->private_buses = NULL;
1059 m->subscribed = sd_bus_track_unref(m->subscribed);
1060 strv_free(m->deserialized_subscribed);
1061 m->deserialized_subscribed = NULL;
1063 if (m->private_listen_event_source)
1064 m->private_listen_event_source = sd_event_source_unref(m->private_listen_event_source);
1066 m->private_listen_fd = safe_close(m->private_listen_fd);
1068 bus_verify_polkit_async_registry_free(m->polkit_registry);
1071 int bus_fdset_add_all(Manager *m, FDSet *fds) {
1079 /* When we are about to reexecute we add all D-Bus fds to the
1080 * set to pass over to the newly executed systemd. They won't
1081 * be used there however, except thatt they are closed at the
1082 * very end of deserialization, those making it possible for
1083 * clients to synchronously wait for systemd to reexec by
1084 * simply waiting for disconnection */
1087 fd = sd_bus_get_fd(m->api_bus);
1089 fd = fdset_put_dup(fds, fd);
1095 SET_FOREACH(b, m->private_buses, i) {
1096 fd = sd_bus_get_fd(b);
1098 fd = fdset_put_dup(fds, fd);
1104 /* We don't offer any APIs on the system bus (well, unless it
1105 * is the same as the API bus) hence we don't bother with it
1111 int bus_foreach_bus(
1113 sd_bus_track *subscribed2,
1114 int (*send_message)(sd_bus *bus, void *userdata),
1121 /* Send to all direct busses, unconditionally */
1122 SET_FOREACH(b, m->private_buses, i) {
1123 r = send_message(b, userdata);
1128 /* Send to API bus, but only if somebody is subscribed */
1129 if (sd_bus_track_count(m->subscribed) > 0 ||
1130 sd_bus_track_count(subscribed2) > 0) {
1131 r = send_message(m->api_bus, userdata);
1139 void bus_track_serialize(sd_bus_track *t, FILE *f) {
1144 for (n = sd_bus_track_first(t); n; n = sd_bus_track_next(t))
1145 fprintf(f, "subscribed=%s\n", n);
1148 int bus_track_deserialize_item(char ***l, const char *line) {
1155 e = startswith(line, "subscribed=");
1159 r = strv_extend(l, e);
1166 int bus_track_coldplug(Manager *m, sd_bus_track **t, char ***l) {
1173 if (!strv_isempty(*l) && m->api_bus) {
1177 r = sd_bus_track_new(m->api_bus, t, NULL, NULL);
1183 STRV_FOREACH(i, *l) {
1186 k = sd_bus_track_add_name(*t, *i);
1198 int bus_verify_manage_units_async(Manager *m, sd_bus_message *call, sd_bus_error *error) {
1199 return bus_verify_polkit_async(call, CAP_SYS_ADMIN, "org.freedesktop.systemd1.manage-units", false, UID_INVALID, &m->polkit_registry, error);
1202 /* Same as bus_verify_manage_unit_async(), but checks for CAP_KILL instead of CAP_SYS_ADMIN */
1203 int bus_verify_manage_units_async_for_kill(Manager *m, sd_bus_message *call, sd_bus_error *error) {
1204 return bus_verify_polkit_async(call, CAP_KILL, "org.freedesktop.systemd1.manage-units", false, UID_INVALID, &m->polkit_registry, error);
1207 int bus_verify_manage_unit_files_async(Manager *m, sd_bus_message *call, sd_bus_error *error) {
1208 return bus_verify_polkit_async(call, CAP_SYS_ADMIN, "org.freedesktop.systemd1.manage-unit-files", false, UID_INVALID, &m->polkit_registry, error);
1211 int bus_verify_reload_daemon_async(Manager *m, sd_bus_message *call, sd_bus_error *error) {
1212 return bus_verify_polkit_async(call, CAP_SYS_ADMIN, "org.freedesktop.systemd1.reload-daemon", false, UID_INVALID, &m->polkit_registry, error);
1215 int bus_verify_set_environment_async(Manager *m, sd_bus_message *call, sd_bus_error *error) {
1216 return bus_verify_polkit_async(call, CAP_SYS_ADMIN, "org.freedesktop.systemd1.set-environment", false, UID_INVALID, &m->polkit_registry, error);