#include <sys/un.h>
#include <sys/timex.h>
#include <sys/utsname.h>
-#include <unistd.h>
#include "kdbus.h"
#include "sd-bus.h"
#include "def.h"
#include "unit-name.h"
#include "bus-control.h"
+#include "cgroup-util.h"
#define CLIENTS_MAX 1024
#define MATCHES_MAX 1024
Match *first;
first = hashmap_get(m->client->matches, m->match);
- if (first) {
- LIST_REMOVE(matches, first, m);
- assert_se(hashmap_replace(m->client->matches, m->match, first) >= 0);
- } else
+ LIST_REMOVE(matches, first, m);
+ if (first)
+ assert_se(hashmap_replace(m->client->matches, first->match, first) >= 0);
+ else
hashmap_remove(m->client->matches, m->match);
m->client->n_matches--;
return r;
}
-static int get_creds(sd_bus *bus, sd_bus_message *m, uint64_t mask, sd_bus_creds **_creds, sd_bus_error *error) {
+static int get_creds_by_name(sd_bus *bus, const char *name, uint64_t mask, sd_bus_creds **_creds, sd_bus_error *error) {
_cleanup_bus_creds_unref_ sd_bus_creds *c = NULL;
- const char *name;
int r;
assert(bus);
- assert(m);
+ assert(name);
assert(_creds);
- r = sd_bus_message_read(m, "s", &name);
- if (r < 0)
- return r;
-
assert_return(service_name_is_valid(name), -EINVAL);
r = sd_bus_get_owner(bus, name, mask, &c);
return 0;
}
+
+static int get_creds_by_message(sd_bus *bus, sd_bus_message *m, uint64_t mask, sd_bus_creds **_creds, sd_bus_error *error) {
+ const char *name;
+ int r;
+
+ assert(bus);
+ assert(m);
+ assert(_creds);
+
+ r = sd_bus_message_read(m, "s", &name);
+ if (r < 0)
+ return r;
+
+ return get_creds_by_name(bus, name, mask, _creds, error);
+}
+
static int driver_get_security_context(sd_bus *bus, sd_bus_message *m, void *userdata, sd_bus_error *error) {
_cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
_cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
int r;
- r = get_creds(bus, m, SD_BUS_CREDS_SELINUX_CONTEXT, &creds, error);
+ r = get_creds_by_message(bus, m, SD_BUS_CREDS_SELINUX_CONTEXT, &creds, error);
if (r < 0)
return r;
_cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
int r;
- r = get_creds(bus, m, SD_BUS_CREDS_PID, &creds, error);
+ r = get_creds_by_message(bus, m, SD_BUS_CREDS_PID, &creds, error);
if (r < 0)
return r;
_cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
int r;
- r = get_creds(bus, m, SD_BUS_CREDS_UID, &creds, error);
+ r = get_creds_by_message(bus, m, SD_BUS_CREDS_UID, &creds, error);
if (r < 0)
return r;
static int driver_get_name_owner(sd_bus *bus, sd_bus_message *m, void *userdata, sd_bus_error *error) {
_cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
+ const char *name;
int r;
- r = get_creds(bus, m, SD_BUS_CREDS_UNIQUE_NAME, &creds, error);
+ r = sd_bus_message_read(m, "s", &name);
+ if (r < 0)
+ return r;
+
+ /* Here's a special exception for compatibility with dbus1:
+ * the bus name of the driver is owned by itself, not by a
+ * unique ID. */
+ if (streq(name, "org.freedesktop.DBus"))
+ return sd_bus_reply_method_return(m, "s", "org.freedesktop.DBus");
+
+ r = get_creds_by_name(bus, name, SD_BUS_CREDS_UNIQUE_NAME, &creds, error);
if (r < 0)
return r;
return sd_bus_reply_method_return(m, "u", BUS_START_REPLY_SUCCESS);
}
+static int driver_update_environment(sd_bus*bus, sd_bus_message *m, void *userdata, sd_bus_error *error) {
+ _cleanup_bus_message_unref_ sd_bus_message *msg = NULL;
+ _cleanup_strv_free_ char **args = NULL;
+ int r;
+
+ r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "{ss}");
+ if (r < 0)
+ return r;
+
+ while ((r = sd_bus_message_enter_container(m, SD_BUS_TYPE_DICT_ENTRY, "ss")) > 0) {
+ _cleanup_free_ char *s = NULL;
+ const char *key;
+ const char *value;
+
+ r = sd_bus_message_read(m, "ss", &key, &value);
+ if (r < 0)
+ return r;
+
+ s = strjoin(key, "=", value, NULL);
+ if (!s)
+ return ENOMEM;
+
+ r = strv_extend(&args, s);
+ if (r < 0)
+ return r;
+
+ r = sd_bus_message_exit_container(m);
+ if (r < 0)
+ return r;
+ }
+
+ r = sd_bus_message_exit_container(m);
+ if (r < 0)
+ return r;
+
+ if (!args)
+ return -EINVAL;
+
+ r = sd_bus_message_new_method_call(
+ bus,
+ "org.freedesktop.systemd1",
+ "/org/freedesktop/systemd1",
+ "org.freedesktop.systemd1.Manager",
+ "SetEnvironment",
+ &msg);
+ if (r < 0)
+ return r;
+
+ r = sd_bus_message_append_strv(msg, args);
+ if (r < 0)
+ return r;
+
+ r = sd_bus_call(bus, msg, 0, NULL, NULL);
+ if (r < 0)
+ return r;
+
+ return sd_bus_reply_method_return(m, NULL);
+}
+
static int driver_unsupported(sd_bus *bus, sd_bus_message *m, void *userdata, sd_bus_error *error) {
return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "%s() is not supported", sd_bus_message_get_member(m));
}
SD_BUS_METHOD("RemoveMatch", "s", NULL, driver_remove_match, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD("RequestName", "su", "u", driver_request_name, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD("StartServiceByName", "su", "u", driver_start_service_by_name, SD_BUS_VTABLE_UNPRIVILEGED),
- SD_BUS_METHOD("UpdateActivationEnvironment", "a{ss}", NULL, driver_unsupported, SD_BUS_VTABLE_DEPRECATED),
+ SD_BUS_METHOD("UpdateActivationEnvironment", "a{ss}", NULL, driver_update_environment, 0),
SD_BUS_SIGNAL("NameAcquired", "s", SD_BUS_VTABLE_DEPRECATED),
SD_BUS_SIGNAL("NameLost", "s", SD_BUS_VTABLE_DEPRECATED),
SD_BUS_SIGNAL("NameOwnerChanged", "sss", 0),
SD_BUS_VTABLE_END
};
+static int find_object(
+ sd_bus *bus,
+ const char *path,
+ const char *interface,
+ void *userdata,
+ void **ret_found,
+ sd_bus_error *ret_error) {
+
+ /* We support the driver interface on exactly two different
+ * paths: the root and the entry point object. This is a bit
+ * different from the original dbus-daemon which supported it
+ * on any path. */
+
+ if (streq_ptr(path, "/"))
+ return 1;
+
+ if (streq_ptr(path, "/org/freedesktop/DBus"))
+ return 1;
+
+ return 0;
+}
+
+static int node_enumerator(
+ sd_bus *bus,
+ const char *path,
+ void *userdata,
+ char ***ret_nodes,
+ sd_bus_error *ret_error) {
+
+ char **l;
+
+ l = strv_new("/", "/org/freedesktop/DBus", NULL);
+ if (!l)
+ return -ENOMEM;
+
+ *ret_nodes = l;
+ return 0;
+}
+
static int connect_bus(Context *c) {
int r;
assert(c);
- r = sd_bus_default_system(&c->bus);
+ r = sd_bus_default(&c->bus);
if (r < 0) {
log_error("Failed to create bus: %s", strerror(-r));
return r;
return -EPERM;
}
- r = sd_bus_add_object_vtable(c->bus, "/org/freedesktop/DBus", "org.freedesktop.DBus", driver_vtable, c);
+ r = sd_bus_add_fallback_vtable(c->bus, "/", "org.freedesktop.DBus", driver_vtable, find_object, c);
if (r < 0) {
log_error("Failed to add manager object vtable: %s", strerror(-r));
return r;
}
+ r = sd_bus_add_node_enumerator(c->bus, "/", node_enumerator, c);
+ if (r < 0) {
+ log_error("Failed to add node enumerator: %s", strerror(-r));
+ return r;
+ }
+
r = sd_bus_request_name(c->bus, "org.freedesktop.DBus", 0);
if (r < 0) {
log_error("Unable to request name: %s", strerror(-r));
sd_event_unref(context.event);
return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
-
}