#include "unit-name.h"
#include "cgroup-util.h"
-static const char *arg_dest = "/tmp";
+static const char *arg_dest_late = "/tmp", *arg_dest = "/tmp";
static int create_dbus_files(
const char *path,
assert(path);
assert(name);
+ assert(service || exec);
if (!service) {
_cleanup_free_ char *a = NULL;
if (!s)
return log_oom();
- a = strjoin(arg_dest, "/", s, NULL);
+ a = strjoin(arg_dest_late, "/", s, NULL);
if (!a)
return log_oom();
fprintf(f,
"# Automatically generated by systemd-dbus1-generator\n\n"
"[Unit]\n"
- "Source=%s\n"
+ "SourcePath=%s\n"
"Description=DBUS1: %s\n\n"
"[Service]\n"
"ExecStart=%s\n"
fprintf(f, "Environment=DBUS_STARTER_BUS_TYPE=%s\n", type);
if (streq(type, "system"))
- fprintf(f, "Environment=DBUS_STARTER_ADDRESS=kernel:/dev/kdbus/0-system\n");
- else if (streq(type, "session"))
- fprintf(f, "Environment=DBUS_STARTER_ADDRESS=kernel:/dev/kdbus/%lu-user\n", (unsigned long) getuid());
+ fprintf(f, "Environment=DBUS_STARTER_ADDRESS=" DEFAULT_SYSTEM_BUS_PATH "\n");
+ else if (streq(type, "session")) {
+ char *run;
+
+ run = getenv("XDG_RUNTIME_DIR");
+ if (!run) {
+ log_error("XDG_RUNTIME_DIR not set.");
+ return -EINVAL;
+ }
+
+ fprintf(f, "Environment=DBUS_STARTER_ADDRESS="KERNEL_USER_BUS_FMT ";" UNIX_USER_BUS_FMT "\n",
+ (unsigned long) getuid(), run);
+ }
}
fflush(f);
service = s;
}
- b = strjoin(arg_dest, "/", name, ".busname", NULL);
+ b = strjoin(arg_dest_late, "/", name, ".busname", NULL);
if (!b)
return log_oom();
fprintf(f,
"# Automatically generated by systemd-dbus1-generator\n\n"
"[Unit]\n"
- "Source=%s\n"
+ "SourcePath=%s\n"
"Description=DBUS1: %s\n\n"
"[BusName]\n"
"Name=%s\n"
return -errno;
}
- lnk = strjoin(arg_dest, "/" SPECIAL_BUSNAMES_TARGET ".wants/", name, ".busname", NULL);
+ lnk = strjoin(arg_dest_late, "/" SPECIAL_BUSNAMES_TARGET ".wants/", name, ".busname", NULL);
if (!lnk)
return log_oom();
mkdir_parents_label(lnk, 0755);
if (symlink(b, lnk)) {
- log_error("Failed to create symlinks %s: %m", lnk);
+ log_error("Failed to create symlink %s: %m", lnk);
return -errno;
}
}
if (service) {
- if (!unit_name_is_valid(service, false)) {
+ if (!unit_name_is_valid(service, TEMPLATE_INVALID)) {
log_warning("Unit name %s is not valid, ignoring.", service);
return 0;
}
return create_dbus_files(p, name, service, exec, user, type);
}
-static int parse_dbus_fragments(void) {
+static int parse_dbus_fragments(const char *path, const char *type) {
_cleanup_closedir_ DIR *d = NULL;
struct dirent *de;
- const char *p, *type;
int r;
- r = cg_pid_get_owner_uid(0, NULL);
- if (r >= 0) {
- p = "/usr/share/dbus-1/services";
- type = "session";
- } else if (r == -ENOENT) {
- p = "/usr/share/dbus-1/system-services";
- type = "system";
- } else if (r < 0) {
- log_error("Failed to determine whether we are running as user or system instance: %s", strerror(-r));
- return r;
- }
+ assert(path);
+ assert(type);
- d = opendir(p);
+ d = opendir(path);
if (!d) {
if (errno == -ENOENT)
return 0;
if (!endswith(de->d_name, ".service"))
continue;
- q = add_dbus(p, de->d_name, type);
+ q = add_dbus(path, de->d_name, type);
if (q < 0)
r = q;
}
return -errno;
}
+static int link_busnames_target(const char *units) {
+ const char *f, *t;
+
+ f = strappenda(units, "/" SPECIAL_BUSNAMES_TARGET);
+ t = strappenda(arg_dest, "/" SPECIAL_BASIC_TARGET ".wants/" SPECIAL_BUSNAMES_TARGET);
+
+ mkdir_parents_label(t, 0755);
+ if (symlink(f, t) < 0) {
+ log_error("Failed to create symlink %s: %m", t);
+ return -errno;
+ }
+
+ return 0;
+}
+
+static int link_compatibility(const char *units) {
+ const char *f, *t;
+
+ f = strappenda(units, "/systemd-bus-proxyd.socket");
+ t = strappenda(arg_dest, "/" SPECIAL_DBUS_SOCKET);
+ mkdir_parents_label(t, 0755);
+ if (symlink(f, t) < 0) {
+ log_error("Failed to create symlink %s: %m", t);
+ return -errno;
+ }
+
+ f = strappenda(units, "/systemd-bus-proxyd.socket");
+ t = strappenda(arg_dest, "/" SPECIAL_SOCKETS_TARGET ".wants/systemd-bus-proxyd.socket");
+ mkdir_parents_label(t, 0755);
+ if (symlink(f, t) < 0) {
+ log_error("Failed to create symlink %s: %m", t);
+ return -errno;
+ }
+
+ t = strappenda(arg_dest, "/" SPECIAL_DBUS_SERVICE);
+ if (symlink("/dev/null", t) < 0) {
+ log_error("Failed to mask %s: %m", t);
+ return -errno;
+ }
+
+ return 0;
+}
+
int main(int argc, char *argv[]) {
- int r;
+ const char *path, *type, *units;
+ int r, q;
if (argc > 1 && argc != 4) {
log_error("This program takes three or no arguments.");
return EXIT_FAILURE;
}
- if (argc > 1)
- arg_dest = argv[3];
+ if (argc > 1) {
+ arg_dest = argv[1];
+ arg_dest_late = argv[3];
+ }
log_set_target(LOG_TARGET_SAFE);
log_parse_environment();
if (access("/dev/kdbus/control", F_OK) < 0)
return 0;
- r = parse_dbus_fragments();
+ r = cg_pid_get_owner_uid(0, NULL);
+ if (r >= 0) {
+ path = "/usr/share/dbus-1/services";
+ type = "session";
+ units = USER_DATA_UNIT_PATH;
+ } else if (r == -ENOENT) {
+ path = "/usr/share/dbus-1/system-services";
+ type = "system";
+ units = SYSTEM_DATA_UNIT_PATH;
+ } else {
+ log_error("Failed to determine whether we are running as user or system instance: %s", strerror(-r));
+ return r;
+ }
+
+ r = parse_dbus_fragments(path, type);
+
+ /* FIXME: One day this should just be pulled in statically from basic.target */
+ q = link_busnames_target(units);
+ if (q < 0)
+ r = q;
+
+ q = link_compatibility(units);
+ if (q < 0)
+ r = q;
return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
}