dbus.c revision e4e703c3076cb5060ab401a2370ab84883f2fd8f
e2fa5721c3ee5ea400b99a6463e8c1c257e20415Daniel Mack/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
e2fa5721c3ee5ea400b99a6463e8c1c257e20415Daniel Mack This file is part of systemd.
e2fa5721c3ee5ea400b99a6463e8c1c257e20415Daniel Mack Copyright 2010 Lennart Poettering
e2fa5721c3ee5ea400b99a6463e8c1c257e20415Daniel Mack systemd is free software; you can redistribute it and/or modify it
e2fa5721c3ee5ea400b99a6463e8c1c257e20415Daniel Mack under the terms of the GNU Lesser General Public License as published by
e2fa5721c3ee5ea400b99a6463e8c1c257e20415Daniel Mack the Free Software Foundation; either version 2.1 of the License, or
e2fa5721c3ee5ea400b99a6463e8c1c257e20415Daniel Mack (at your option) any later version.
e2fa5721c3ee5ea400b99a6463e8c1c257e20415Daniel Mack systemd is distributed in the hope that it will be useful, but
e2fa5721c3ee5ea400b99a6463e8c1c257e20415Daniel Mack WITHOUT ANY WARRANTY; without even the implied warranty of
e2fa5721c3ee5ea400b99a6463e8c1c257e20415Daniel Mack MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
e2fa5721c3ee5ea400b99a6463e8c1c257e20415Daniel Mack Lesser General Public License for more details.
e2fa5721c3ee5ea400b99a6463e8c1c257e20415Daniel Mack You should have received a copy of the GNU Lesser General Public License
e2fa5721c3ee5ea400b99a6463e8c1c257e20415Daniel Mack along with systemd; If not, see <http://www.gnu.org/licenses/>.
e2fa5721c3ee5ea400b99a6463e8c1c257e20415Daniel Mackstatic void destroy_bus(Manager *m, sd_bus **bus);
e2fa5721c3ee5ea400b99a6463e8c1c257e20415Daniel Mack /* If we cannot get rid of this message we won't dispatch any
e2fa5721c3ee5ea400b99a6463e8c1c257e20415Daniel Mack * D-Bus messages, so that we won't end up wanting to queue
e2fa5721c3ee5ea400b99a6463e8c1c257e20415Daniel Mack * another message. */
e2fa5721c3ee5ea400b99a6463e8c1c257e20415Daniel Mack r = sd_bus_send(m->queued_message_bus, m->queued_message, NULL);
e2fa5721c3ee5ea400b99a6463e8c1c257e20415Daniel Mack log_warning("Failed to send queued message: %s", strerror(-r));
e2fa5721c3ee5ea400b99a6463e8c1c257e20415Daniel Mack m->queued_message = sd_bus_message_unref(m->queued_message);
e2fa5721c3ee5ea400b99a6463e8c1c257e20415Daniel Mack m->queued_message_bus = sd_bus_unref(m->queued_message_bus);
e2fa5721c3ee5ea400b99a6463e8c1c257e20415Daniel Mackstatic int signal_agent_released(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
e2fa5721c3ee5ea400b99a6463e8c1c257e20415Daniel Mack if (r < 0) {
e2fa5721c3ee5ea400b99a6463e8c1c257e20415Daniel Mack if (m->running_as == SYSTEMD_SYSTEM && m->system_bus) {
e2fa5721c3ee5ea400b99a6463e8c1c257e20415Daniel Mack /* If we are running as system manager, forward the
e2fa5721c3ee5ea400b99a6463e8c1c257e20415Daniel Mack * message to the system bus */
e2fa5721c3ee5ea400b99a6463e8c1c257e20415Daniel Mack log_warning("Failed to forward Released message: %s", strerror(-r));
e2fa5721c3ee5ea400b99a6463e8c1c257e20415Daniel Mackstatic int signal_disconnected(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
e2fa5721c3ee5ea400b99a6463e8c1c257e20415Daniel Mack log_debug("Got disconnect on private connection.");
e2fa5721c3ee5ea400b99a6463e8c1c257e20415Daniel Mackstatic int signal_name_owner_changed(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
e2fa5721c3ee5ea400b99a6463e8c1c257e20415Daniel Mack r = sd_bus_message_read(message, "sss", &name, &old_owner, &new_owner);
e2fa5721c3ee5ea400b99a6463e8c1c257e20415Daniel Mack if (r < 0) {
e2fa5721c3ee5ea400b99a6463e8c1c257e20415Daniel Mackstatic int signal_activation_request(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *ret_error) {
e2fa5721c3ee5ea400b99a6463e8c1c257e20415Daniel Mack _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
e2fa5721c3ee5ea400b99a6463e8c1c257e20415Daniel Mack _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
e2fa5721c3ee5ea400b99a6463e8c1c257e20415Daniel Mack const char *name;
e2fa5721c3ee5ea400b99a6463e8c1c257e20415Daniel Mack if (r < 0) {
e2fa5721c3ee5ea400b99a6463e8c1c257e20415Daniel Mack if (manager_unit_inactive_or_pending(m, SPECIAL_DBUS_SERVICE) ||
e2fa5721c3ee5ea400b99a6463e8c1c257e20415Daniel Mack manager_unit_inactive_or_pending(m, SPECIAL_DBUS_SOCKET)) {
e2fa5721c3ee5ea400b99a6463e8c1c257e20415Daniel Mack r = sd_bus_error_setf(&error, BUS_ERROR_SHUTTING_DOWN, "Refusing activation, D-Bus is shutting down.");
e2fa5721c3ee5ea400b99a6463e8c1c257e20415Daniel Mack r = manager_load_unit(m, name, NULL, &error, &u);
c2a23db0b91faca3795099fd4b41587bac170ff7Daniel Mack r = sd_bus_error_setf(&error, BUS_ERROR_ONLY_BY_DEPENDENCY, "Operation refused, %s may be requested by dependency only.", u->id);
e2fa5721c3ee5ea400b99a6463e8c1c257e20415Daniel Mack r = manager_add_job(m, JOB_START, u, JOB_REPLACE, true, &error, NULL);
e2fa5721c3ee5ea400b99a6463e8c1c257e20415Daniel Mack /* Successfully queued, that's it for us */
r = sd_bus_message_new_signal(bus, &reply, "/org/freedesktop/systemd1", "org.freedesktop.systemd1.Activator", "ActivationFailure");
#ifdef HAVE_SELINUX
static int selinux_filter(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
Job *j;
u = j->unit;
static int bus_job_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error) {
Job *j;
assert(m);
*found = j;
Unit *u;
assert(m);
if (!message)
*unit = u;
static int bus_unit_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error) {
assert(m);
static int bus_unit_interface_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error) {
Unit *u;
assert(m);
*found = u;
static int bus_unit_cgroup_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error) {
Unit *u;
assert(m);
if (!unit_get_cgroup_context(u))
*found = u;
static int bus_cgroup_context_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error) {
CGroupContext *c;
Unit *u;
assert(m);
c = unit_get_cgroup_context(u);
*found = c;
static int bus_exec_context_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error) {
ExecContext *c;
Unit *u;
assert(m);
c = unit_get_exec_context(u);
*found = c;
static int bus_kill_context_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error) {
KillContext *c;
Unit *u;
assert(m);
c = unit_get_kill_context(u);
*found = c;
static int bus_job_enumerate(sd_bus *bus, const char *path, void *userdata, char ***nodes, sd_bus_error *error) {
Iterator i;
Job *j;
return -ENOMEM;
l[k] = job_dbus_path(j);
return -ENOMEM;
*nodes = l;
l = NULL;
static int bus_unit_enumerate(sd_bus *bus, const char *path, void *userdata, char ***nodes, sd_bus_error *error) {
Iterator i;
Unit *u;
return -ENOMEM;
l[k] = unit_dbus_path(u);
return -ENOMEM;
*nodes = l;
l = NULL;
UnitType t;
assert(m);
#ifdef HAVE_SELINUX
r = sd_bus_add_object_vtable(bus, "/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", bus_manager_vtable, m);
r = sd_bus_add_fallback_vtable(bus, "/org/freedesktop/systemd1/job", "org.freedesktop.systemd1.Job", bus_job_vtable, bus_job_find, m);
r = sd_bus_add_fallback_vtable(bus, "/org/freedesktop/systemd1/unit", "org.freedesktop.systemd1.Unit", bus_unit_vtable, bus_unit_find, m);
for (t = 0; t < _UNIT_TYPE_MAX; t++) {
r = sd_bus_add_fallback_vtable(bus, "/org/freedesktop/systemd1/unit", unit_vtable[t]->bus_interface, unit_vtable[t]->bus_vtable, bus_unit_interface_find, m);
log_error("Failed to register type specific vtable for %s: %s", unit_vtable[t]->bus_interface, strerror(-r));
r = sd_bus_add_fallback_vtable(bus, "/org/freedesktop/systemd1/unit", unit_vtable[t]->bus_interface, bus_unit_cgroup_vtable, bus_unit_cgroup_find, m);
log_error("Failed to register control group unit vtable for %s: %s", unit_vtable[t]->bus_interface, strerror(-r));
r = sd_bus_add_fallback_vtable(bus, "/org/freedesktop/systemd1/unit", unit_vtable[t]->bus_interface, bus_cgroup_vtable, bus_cgroup_context_find, m);
log_error("Failed to register control group vtable for %s: %s", unit_vtable[t]->bus_interface, strerror(-r));
r = sd_bus_add_fallback_vtable(bus, "/org/freedesktop/systemd1/unit", unit_vtable[t]->bus_interface, bus_exec_vtable, bus_exec_context_find, m);
log_error("Failed to register execute vtable for %s: %s", unit_vtable[t]->bus_interface, strerror(-r));
r = sd_bus_add_fallback_vtable(bus, "/org/freedesktop/systemd1/unit", unit_vtable[t]->bus_interface, bus_kill_vtable, bus_kill_context_find, m);
log_error("Failed to register kill vtable for %s: %s", unit_vtable[t]->bus_interface, strerror(-r));
assert(m);
r = sd_bus_add_match(
bus,
"path='/org/freedesktop/DBus/Local',"
signal_disconnected, m);
assert(s);
assert(m);
if (nfd < 0) {
log_oom();
r = sd_bus_add_match(
bus,
"interface='org.freedesktop.systemd1.Agent',"
"path='/org/freedesktop/systemd1/agent'",
assert(m);
assert(m);
r = sd_bus_add_match(
bus,
"path='/org/freedesktop/DBus',"
r = sd_bus_add_match(
bus,
"path='/org/freedesktop/DBus',"
"interface='org.freedesktop.systemd1.Activator',"
r = sd_bus_request_name(bus,"org.freedesktop.systemd1", SD_BUS_NAME_REPLACE_EXISTING|SD_BUS_NAME_ALLOW_REPLACEMENT);
if (m->api_bus)
assert(m);
r = sd_bus_add_match(
bus,
"interface='org.freedesktop.systemd1.Agent',"
"path='/org/freedesktop/systemd1/agent'",
if (m->system_bus)
sd_event_source *s;
assert(m);
if (m->private_listen_fd >= 0)
if (m->kdbus_fd >= 0)
return -EHOSTDOWN;
if (fd < 0) {
return -errno;
return -errno;
return -errno;
m->private_listen_event_source = s;
if (try_bus_connect) {
r = bus_init_system(m);
r = bus_init_api(m);
r = bus_init_private(m);
Iterator i;
Job *j;
assert(m);
if (!*bus)
if (m->queued_message)
sd_bus *b;
assert(m);
if (m->api_bus)
if (m->system_bus)
destroy_bus(m, &b);
if (m->private_listen_event_source)
if (m->private_listen_fd >= 0) {
Iterator i;
sd_bus *b;
int fd;
assert(m);
if (m->api_bus) {
if (fd >= 0) {
if (fd < 0)
return fd;
if (fd >= 0) {
if (fd < 0)
return fd;
int bus_foreach_bus(
Manager *m,
void *userdata) {
Iterator i;
sd_bus *b;
int r, ret = 0;
ret = r;
ret = r;
return ret;
assert(f);
assert(l);
return strv_extend(l, e);
assert(m);
assert(t);
assert(l);
STRV_FOREACH(i, *l) {
k = sd_bus_track_add_name(*t, *i);
strv_free(*l);
*l = NULL;