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 512
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 if (m->running_as == SYSTEMD_SYSTEM && m->system_bus) {
92 /* If we are running as system manager, forward the
93 * message to the system bus */
95 r = sd_bus_send(m->system_bus, message, NULL);
97 log_warning_errno(r, "Failed to forward Released message: %m");
103 static int signal_disconnected(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
104 Manager *m = userdata;
110 if (bus == m->api_bus)
111 destroy_bus(m, &m->api_bus);
112 if (bus == m->system_bus)
113 destroy_bus(m, &m->system_bus);
114 if (set_remove(m->private_buses, bus)) {
115 log_debug("Got disconnect on private connection.");
116 destroy_bus(m, &bus);
122 static int signal_name_owner_changed(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
123 const char *name, *old_owner, *new_owner;
124 Manager *m = userdata;
131 r = sd_bus_message_read(message, "sss", &name, &old_owner, &new_owner);
133 bus_log_parse_error(r);
137 manager_dispatch_bus_name_owner_changed(
139 isempty(old_owner) ? NULL : old_owner,
140 isempty(new_owner) ? NULL : new_owner);
145 static int signal_activation_request(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *ret_error) {
146 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
147 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
148 Manager *m = userdata;
157 r = sd_bus_message_read(message, "s", &name);
159 bus_log_parse_error(r);
163 if (manager_unit_inactive_or_pending(m, SPECIAL_DBUS_SERVICE) ||
164 manager_unit_inactive_or_pending(m, SPECIAL_DBUS_SOCKET)) {
165 r = sd_bus_error_setf(&error, BUS_ERROR_SHUTTING_DOWN, "Refusing activation, D-Bus is shutting down.");
169 r = manager_load_unit(m, name, NULL, &error, &u);
173 if (u->refuse_manual_start) {
174 r = sd_bus_error_setf(&error, BUS_ERROR_ONLY_BY_DEPENDENCY, "Operation refused, %s may be requested by dependency only.", u->id);
178 r = manager_add_job(m, JOB_START, u, JOB_REPLACE, true, &error, NULL);
182 /* Successfully queued, that's it for us */
186 if (!sd_bus_error_is_set(&error))
187 sd_bus_error_set_errno(&error, r);
189 log_debug("D-Bus activation failed for %s: %s", name, bus_error_message(&error, r));
191 r = sd_bus_message_new_signal(bus, &reply, "/org/freedesktop/systemd1", "org.freedesktop.systemd1.Activator", "ActivationFailure");
193 bus_log_create_error(r);
197 r = sd_bus_message_append(reply, "sss", name, error.name, error.message);
199 bus_log_create_error(r);
203 r = sd_bus_send_to(bus, reply, "org.freedesktop.DBus", NULL);
205 return log_error_errno(r, "Failed to respond with to bus activation request: %m");
211 static int mac_selinux_filter(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
212 Manager *m = userdata;
213 const char *verb, *path;
221 /* Our own method calls are all protected individually with
222 * selinux checks, but the built-in interfaces need to be
225 if (sd_bus_message_is_method_call(message, "org.freedesktop.DBus.Properties", "Set"))
227 else if (sd_bus_message_is_method_call(message, "org.freedesktop.DBus.Introspectable", NULL) ||
228 sd_bus_message_is_method_call(message, "org.freedesktop.DBus.Properties", NULL) ||
229 sd_bus_message_is_method_call(message, "org.freedesktop.DBus.ObjectManager", NULL) ||
230 sd_bus_message_is_method_call(message, "org.freedesktop.DBus.Peer", NULL))
235 path = sd_bus_message_get_path(message);
237 if (object_path_startswith("/org/freedesktop/systemd1", path)) {
239 r = mac_selinux_access_check(message, verb, error);
246 if (streq_ptr(path, "/org/freedesktop/systemd1/unit/self")) {
247 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
250 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_PID, &creds);
254 r = sd_bus_creds_get_pid(creds, &pid);
258 u = manager_get_unit_by_pid(m, pid);
260 r = manager_get_job_from_dbus_path(m, path, &j);
264 manager_load_unit_from_dbus_path(m, path, NULL, &u);
270 r = mac_selinux_unit_access_check(u, message, verb, error);
278 static int bus_job_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error) {
279 Manager *m = userdata;
289 r = manager_get_job_from_dbus_path(m, path, &j);
297 static int find_unit(Manager *m, sd_bus *bus, const char *path, Unit **unit, sd_bus_error *error) {
305 if (streq_ptr(path, "/org/freedesktop/systemd1/unit/self")) {
306 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
307 sd_bus_message *message;
310 message = sd_bus_get_current_message(bus);
314 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_PID, &creds);
318 r = sd_bus_creds_get_pid(creds, &pid);
322 u = manager_get_unit_by_pid(m, pid);
324 r = manager_load_unit_from_dbus_path(m, path, error, &u);
336 static int bus_unit_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error) {
337 Manager *m = userdata;
345 return find_unit(m, bus, path, (Unit**) found, error);
348 static int bus_unit_interface_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error) {
349 Manager *m = userdata;
359 r = find_unit(m, bus, path, &u, error);
363 if (!streq_ptr(interface, UNIT_VTABLE(u)->bus_interface))
370 static int bus_unit_cgroup_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error) {
371 Manager *m = userdata;
381 r = find_unit(m, bus, path, &u, error);
385 if (!streq_ptr(interface, UNIT_VTABLE(u)->bus_interface))
388 if (!unit_get_cgroup_context(u))
395 static int bus_cgroup_context_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error) {
396 Manager *m = userdata;
407 r = find_unit(m, bus, path, &u, error);
411 if (!streq_ptr(interface, UNIT_VTABLE(u)->bus_interface))
414 c = unit_get_cgroup_context(u);
422 static int bus_exec_context_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error) {
423 Manager *m = userdata;
434 r = find_unit(m, bus, path, &u, error);
438 if (!streq_ptr(interface, UNIT_VTABLE(u)->bus_interface))
441 c = unit_get_exec_context(u);
449 static int bus_kill_context_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error) {
450 Manager *m = userdata;
461 r = find_unit(m, bus, path, &u, error);
465 if (!streq_ptr(interface, UNIT_VTABLE(u)->bus_interface))
468 c = unit_get_kill_context(u);
476 static int bus_job_enumerate(sd_bus *bus, const char *path, void *userdata, char ***nodes, sd_bus_error *error) {
477 _cleanup_free_ char **l = NULL;
478 Manager *m = userdata;
483 l = new0(char*, hashmap_size(m->jobs)+1);
487 HASHMAP_FOREACH(j, m->jobs, i) {
488 l[k] = job_dbus_path(j);
495 assert(hashmap_size(m->jobs) == k);
503 static int bus_unit_enumerate(sd_bus *bus, const char *path, void *userdata, char ***nodes, sd_bus_error *error) {
504 _cleanup_free_ char **l = NULL;
505 Manager *m = userdata;
510 l = new0(char*, hashmap_size(m->units)+1);
514 HASHMAP_FOREACH(u, m->units, i) {
515 l[k] = unit_dbus_path(u);
528 static int bus_setup_api_vtables(Manager *m, sd_bus *bus) {
536 r = sd_bus_add_filter(bus, NULL, mac_selinux_filter, m);
538 return log_error_errno(r, "Failed to add SELinux access filter: %m");
541 r = sd_bus_add_object_vtable(bus, NULL, "/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", bus_manager_vtable, m);
543 return log_error_errno(r, "Failed to register Manager vtable: %m");
545 r = sd_bus_add_fallback_vtable(bus, NULL, "/org/freedesktop/systemd1/job", "org.freedesktop.systemd1.Job", bus_job_vtable, bus_job_find, m);
547 return log_error_errno(r, "Failed to register Job vtable: %m");
549 r = sd_bus_add_node_enumerator(bus, NULL, "/org/freedesktop/systemd1/job", bus_job_enumerate, m);
551 return log_error_errno(r, "Failed to add job enumerator: %m");
553 r = sd_bus_add_fallback_vtable(bus, NULL, "/org/freedesktop/systemd1/unit", "org.freedesktop.systemd1.Unit", bus_unit_vtable, bus_unit_find, m);
555 return log_error_errno(r, "Failed to register Unit vtable: %m");
557 r = sd_bus_add_node_enumerator(bus, NULL, "/org/freedesktop/systemd1/unit", bus_unit_enumerate, m);
559 return log_error_errno(r, "Failed to add job enumerator: %m");
561 for (t = 0; t < _UNIT_TYPE_MAX; t++) {
562 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);
564 return log_error_errno(r, "Failed to register type specific vtable for %s: %m", unit_vtable[t]->bus_interface);
566 if (unit_vtable[t]->cgroup_context_offset > 0) {
567 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);
569 return log_error_errno(r, "Failed to register control group unit vtable for %s: %m", unit_vtable[t]->bus_interface);
571 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);
573 return log_error_errno(r, "Failed to register control group vtable for %s: %m", unit_vtable[t]->bus_interface);
576 if (unit_vtable[t]->exec_context_offset > 0) {
577 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);
579 return log_error_errno(r, "Failed to register execute vtable for %s: %m", unit_vtable[t]->bus_interface);
582 if (unit_vtable[t]->kill_context_offset > 0) {
583 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);
585 return log_error_errno(r, "Failed to register kill vtable for %s: %m", unit_vtable[t]->bus_interface);
592 static int bus_setup_disconnected_match(Manager *m, sd_bus *bus) {
598 r = sd_bus_add_match(
601 "sender='org.freedesktop.DBus.Local',"
603 "path='/org/freedesktop/DBus/Local',"
604 "interface='org.freedesktop.DBus.Local',"
605 "member='Disconnected'",
606 signal_disconnected, m);
609 return log_error_errno(r, "Failed to register match for Disconnected message: %m");
614 static int bus_on_connection(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
615 _cleanup_bus_unref_ sd_bus *bus = NULL;
616 _cleanup_close_ int nfd = -1;
617 Manager *m = userdata;
624 nfd = accept4(fd, NULL, NULL, SOCK_NONBLOCK|SOCK_CLOEXEC);
626 log_warning_errno(errno, "Failed to accept private connection, ignoring: %m");
630 if (set_size(m->private_buses) >= CONNECTIONS_MAX) {
631 log_warning("Too many concurrent connections, refusing");
635 r = set_ensure_allocated(&m->private_buses, NULL);
641 r = sd_bus_new(&bus);
643 log_warning_errno(r, "Failed to allocate new private connection bus: %m");
647 r = sd_bus_set_fd(bus, nfd, nfd);
649 log_warning_errno(r, "Failed to set fd on new connection bus: %m");
655 r = bus_check_peercred(bus);
657 log_warning_errno(r, "Incoming private connection from unprivileged client, refusing: %m");
661 assert_se(sd_id128_randomize(&id) >= 0);
663 r = sd_bus_set_server(bus, 1, id);
665 log_warning_errno(r, "Failed to enable server support for new connection bus: %m");
669 r = sd_bus_start(bus);
671 log_warning_errno(r, "Failed to start new connection bus: %m");
675 r = sd_bus_attach_event(bus, m->event, SD_EVENT_PRIORITY_NORMAL);
677 log_warning_errno(r, "Failed to attach new connection bus to event loop: %m");
681 if (m->running_as == SYSTEMD_SYSTEM) {
682 /* When we run as system instance we get the Released
683 * signal via a direct connection */
685 r = sd_bus_add_match(
689 "interface='org.freedesktop.systemd1.Agent',"
691 "path='/org/freedesktop/systemd1/agent'",
692 signal_agent_released, m);
695 log_warning_errno(r, "Failed to register Released match on new connection bus: %m");
700 r = bus_setup_disconnected_match(m, bus);
704 r = bus_setup_api_vtables(m, bus);
706 log_warning_errno(r, "Failed to set up API vtables on new connection bus: %m");
710 r = set_put(m->private_buses, bus);
712 log_warning_errno(r, "Failed to add new conenction bus to set: %m");
718 log_debug("Accepted new private connection.");
723 static int bus_list_names(Manager *m, sd_bus *bus) {
724 _cleanup_strv_free_ char **names = NULL;
731 r = sd_bus_list_names(bus, &names, NULL);
733 return log_error_errno(r, "Failed to get initial list of names: %m");
735 /* This is a bit hacky, we say the owner of the name is the
736 * name itself, because we don't want the extra traffic to
737 * figure out the real owner. */
738 STRV_FOREACH(i, names)
739 manager_dispatch_bus_name_owner_changed(m, *i, NULL, *i);
744 static int bus_setup_api(Manager *m, sd_bus *bus) {
750 /* Let's make sure we have enough credential bits so that we can make security and selinux decisions */
751 r = sd_bus_negotiate_creds(bus, 1,
752 SD_BUS_CREDS_PID|SD_BUS_CREDS_UID|
753 SD_BUS_CREDS_EUID|SD_BUS_CREDS_EFFECTIVE_CAPS|
754 SD_BUS_CREDS_SELINUX_CONTEXT);
756 log_warning_errno(r, "Failed to enable credential passing, ignoring: %m");
758 r = bus_setup_api_vtables(m, bus);
762 r = sd_bus_add_match(
766 "sender='org.freedesktop.DBus',"
767 "path='/org/freedesktop/DBus',"
768 "interface='org.freedesktop.DBus',"
769 "member='NameOwnerChanged'",
770 signal_name_owner_changed, m);
772 log_warning_errno(r, "Failed to subscribe to NameOwnerChanged signal: %m");
774 r = sd_bus_add_match(
778 "sender='org.freedesktop.DBus',"
779 "path='/org/freedesktop/DBus',"
780 "interface='org.freedesktop.systemd1.Activator',"
781 "member='ActivationRequest'",
782 signal_activation_request, m);
784 log_warning_errno(r, "Failed to subscribe to activation signal: %m");
786 /* Allow replacing of our name, to ease implementation of
787 * reexecution, where we keep the old connection open until
788 * after the new connection is set up and the name installed
789 * to allow clients to synchronously wait for reexecution to
791 r = sd_bus_request_name(bus,"org.freedesktop.systemd1", SD_BUS_NAME_REPLACE_EXISTING|SD_BUS_NAME_ALLOW_REPLACEMENT);
793 return log_error_errno(r, "Failed to register name: %m");
795 bus_list_names(m, bus);
797 log_debug("Successfully connected to API bus.");
801 static int bus_init_api(Manager *m) {
802 _cleanup_bus_unref_ sd_bus *bus = NULL;
808 /* The API and system bus is the same if we are running in system mode */
809 if (m->running_as == SYSTEMD_SYSTEM && m->system_bus)
810 bus = sd_bus_ref(m->system_bus);
812 if (m->running_as == SYSTEMD_SYSTEM)
813 r = sd_bus_open_system(&bus);
815 r = sd_bus_open_user(&bus);
818 log_debug("Failed to connect to API bus, retrying later...");
822 r = sd_bus_attach_event(bus, m->event, SD_EVENT_PRIORITY_NORMAL);
824 log_error_errno(r, "Failed to attach API bus to event loop: %m");
828 r = bus_setup_disconnected_match(m, bus);
833 r = bus_setup_api(m, bus);
835 log_error_errno(r, "Failed to set up API bus: %m");
845 static int bus_setup_system(Manager *m, sd_bus *bus) {
851 if (m->running_as == SYSTEMD_SYSTEM)
854 /* If we are a user instance we get the Released message via
856 r = sd_bus_add_match(
860 "interface='org.freedesktop.systemd1.Agent',"
862 "path='/org/freedesktop/systemd1/agent'",
863 signal_agent_released, m);
866 log_warning_errno(r, "Failed to register Released match on system bus: %m");
868 log_debug("Successfully connected to system bus.");
872 static int bus_init_system(Manager *m) {
873 _cleanup_bus_unref_ sd_bus *bus = NULL;
879 /* The API and system bus is the same if we are running in system mode */
880 if (m->running_as == SYSTEMD_SYSTEM && m->api_bus) {
881 m->system_bus = sd_bus_ref(m->api_bus);
885 r = sd_bus_open_system(&bus);
887 log_debug("Failed to connect to system bus, retrying later...");
891 r = bus_setup_disconnected_match(m, bus);
895 r = sd_bus_attach_event(bus, m->event, SD_EVENT_PRIORITY_NORMAL);
897 log_error_errno(r, "Failed to attach system bus to event loop: %m");
901 r = bus_setup_system(m, bus);
903 log_error_errno(r, "Failed to set up system bus: %m");
913 static int bus_init_private(Manager *m) {
914 _cleanup_close_ int fd = -1;
915 union sockaddr_union sa = {
916 .un.sun_family = AF_UNIX
924 if (m->private_listen_fd >= 0)
927 /* We don't need the private socket if we have kdbus */
928 if (m->kdbus_fd >= 0)
931 if (m->running_as == SYSTEMD_SYSTEM) {
933 /* We want the private bus only when running as init */
937 strcpy(sa.un.sun_path, "/run/systemd/private");
938 salen = offsetof(union sockaddr_union, un.sun_path) + strlen("/run/systemd/private");
940 size_t left = sizeof(sa.un.sun_path);
941 char *p = sa.un.sun_path;
944 e = secure_getenv("XDG_RUNTIME_DIR");
946 log_error("Failed to determine XDG_RUNTIME_DIR");
950 left = strpcpy(&p, left, e);
951 left = strpcpy(&p, left, "/systemd/private");
953 salen = sizeof(sa.un) - left;
956 (void) mkdir_parents_label(sa.un.sun_path, 0755);
957 (void) unlink(sa.un.sun_path);
959 fd = socket(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
961 return log_error_errno(errno, "Failed to allocate private socket: %m");
963 r = bind(fd, &sa.sa, salen);
965 return log_error_errno(errno, "Failed to bind private socket: %m");
967 r = listen(fd, SOMAXCONN);
969 return log_error_errno(errno, "Failed to make private socket listening: %m");
971 r = sd_event_add_io(m->event, &s, fd, EPOLLIN, bus_on_connection, m);
973 return log_error_errno(r, "Failed to allocate event source: %m");
975 m->private_listen_fd = fd;
976 m->private_listen_event_source = s;
979 log_debug("Successfully created private D-Bus server.");
984 int bus_init(Manager *m, bool try_bus_connect) {
987 if (try_bus_connect) {
988 r = bus_init_system(m);
997 r = bus_init_private(m);
1004 static void destroy_bus(Manager *m, sd_bus **bus) {
1014 /* Get rid of tracked clients on this bus */
1015 if (m->subscribed && sd_bus_track_get_bus(m->subscribed) == *bus)
1016 m->subscribed = sd_bus_track_unref(m->subscribed);
1018 HASHMAP_FOREACH(j, m->jobs, i)
1019 if (j->clients && sd_bus_track_get_bus(j->clients) == *bus)
1020 j->clients = sd_bus_track_unref(j->clients);
1022 /* Get rid of queued message on this bus */
1023 if (m->queued_message_bus == *bus) {
1024 m->queued_message_bus = sd_bus_unref(m->queued_message_bus);
1026 if (m->queued_message)
1027 m->queued_message = sd_bus_message_unref(m->queued_message);
1030 /* Possibly flush unwritten data, but only if we are
1031 * unprivileged, since we don't want to sync here */
1032 if (m->running_as != SYSTEMD_SYSTEM)
1035 /* And destroy the object */
1037 *bus = sd_bus_unref(*bus);
1040 void bus_done(Manager *m) {
1046 destroy_bus(m, &m->api_bus);
1048 destroy_bus(m, &m->system_bus);
1049 while ((b = set_steal_first(m->private_buses)))
1052 set_free(m->private_buses);
1053 m->private_buses = NULL;
1055 m->subscribed = sd_bus_track_unref(m->subscribed);
1056 strv_free(m->deserialized_subscribed);
1057 m->deserialized_subscribed = NULL;
1059 if (m->private_listen_event_source)
1060 m->private_listen_event_source = sd_event_source_unref(m->private_listen_event_source);
1062 m->private_listen_fd = safe_close(m->private_listen_fd);
1064 bus_verify_polkit_async_registry_free(m->polkit_registry);
1067 int bus_fdset_add_all(Manager *m, FDSet *fds) {
1075 /* When we are about to reexecute we add all D-Bus fds to the
1076 * set to pass over to the newly executed systemd. They won't
1077 * be used there however, except thatt they are closed at the
1078 * very end of deserialization, those making it possible for
1079 * clients to synchronously wait for systemd to reexec by
1080 * simply waiting for disconnection */
1083 fd = sd_bus_get_fd(m->api_bus);
1085 fd = fdset_put_dup(fds, fd);
1091 SET_FOREACH(b, m->private_buses, i) {
1092 fd = sd_bus_get_fd(b);
1094 fd = fdset_put_dup(fds, fd);
1100 /* We don't offer any APIs on the system bus (well, unless it
1101 * is the same as the API bus) hence we don't bother with it
1107 int bus_foreach_bus(
1109 sd_bus_track *subscribed2,
1110 int (*send_message)(sd_bus *bus, void *userdata),
1117 /* Send to all direct busses, unconditionally */
1118 SET_FOREACH(b, m->private_buses, i) {
1119 r = send_message(b, userdata);
1124 /* Send to API bus, but only if somebody is subscribed */
1125 if (sd_bus_track_count(m->subscribed) > 0 ||
1126 sd_bus_track_count(subscribed2) > 0) {
1127 r = send_message(m->api_bus, userdata);
1135 void bus_track_serialize(sd_bus_track *t, FILE *f) {
1140 for (n = sd_bus_track_first(t); n; n = sd_bus_track_next(t))
1141 fprintf(f, "subscribed=%s\n", n);
1144 int bus_track_deserialize_item(char ***l, const char *line) {
1151 e = startswith(line, "subscribed=");
1155 r = strv_extend(l, e);
1162 int bus_track_coldplug(Manager *m, sd_bus_track **t, char ***l) {
1169 if (!strv_isempty(*l) && m->api_bus) {
1173 r = sd_bus_track_new(m->api_bus, t, NULL, NULL);
1179 STRV_FOREACH(i, *l) {
1182 k = sd_bus_track_add_name(*t, *i);
1194 int bus_verify_manage_units_async(Manager *m, sd_bus_message *call, sd_bus_error *error) {
1195 return bus_verify_polkit_async(call, CAP_SYS_ADMIN, "org.freedesktop.systemd1.manage-units", false, UID_INVALID, &m->polkit_registry, error);
1198 /* Same as bus_verify_manage_unit_async(), but checks for CAP_KILL instead of CAP_SYS_ADMIN */
1199 int bus_verify_manage_units_async_for_kill(Manager *m, sd_bus_message *call, sd_bus_error *error) {
1200 return bus_verify_polkit_async(call, CAP_KILL, "org.freedesktop.systemd1.manage-units", false, UID_INVALID, &m->polkit_registry, error);
1203 int bus_verify_manage_unit_files_async(Manager *m, sd_bus_message *call, sd_bus_error *error) {
1204 return bus_verify_polkit_async(call, CAP_SYS_ADMIN, "org.freedesktop.systemd1.manage-unit-files", false, UID_INVALID, &m->polkit_registry, error);
1207 int bus_verify_reload_daemon_async(Manager *m, sd_bus_message *call, sd_bus_error *error) {
1208 return bus_verify_polkit_async(call, CAP_SYS_ADMIN, "org.freedesktop.systemd1.reload-daemon", false, UID_INVALID, &m->polkit_registry, error);
1211 int bus_verify_set_environment_async(Manager *m, sd_bus_message *call, sd_bus_error *error) {
1212 return bus_verify_polkit_async(call, CAP_SYS_ADMIN, "org.freedesktop.systemd1.set-environment", false, UID_INVALID, &m->polkit_registry, error);