X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=blobdiff_plain;f=src%2Fdbus1-generator%2Fdbus1-generator.c;h=10a33efee5f0fe013d575ec61206dcd9e8e5e036;hb=00d75e5752f68a7b5d066158fdf0adffcaa9a7f2;hp=31ec56e7ec1f00c41690d0d29c1539c3ad6d6006;hpb=4c3a127cb631cf5efe8a6aab3fb2884e9044ef2d;p=elogind.git diff --git a/src/dbus1-generator/dbus1-generator.c b/src/dbus1-generator/dbus1-generator.c index 31ec56e7e..10a33efee 100644 --- a/src/dbus1-generator/dbus1-generator.c +++ b/src/dbus1-generator/dbus1-generator.c @@ -28,7 +28,7 @@ #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, @@ -40,9 +40,11 @@ static int create_dbus_files( _cleanup_free_ char *b = NULL, *s = NULL, *lnk = NULL; _cleanup_fclose_ FILE *f = NULL; + int r; assert(path); assert(name); + assert(service || exec); if (!service) { _cleanup_free_ char *a = NULL; @@ -51,21 +53,20 @@ static int create_dbus_files( if (!s) return log_oom(); - a = strjoin(arg_dest, "/", s, NULL); + a = strjoin(arg_dest_late, "/", s, NULL); if (!a) return log_oom(); f = fopen(a, "wxe"); - if (!f) { - log_error("Failed to create %s: %m", a); - return -errno; - } + if (!f) + return log_error_errno(errno, "Failed to create %s: %m", a); fprintf(f, "# Automatically generated by systemd-dbus1-generator\n\n" "[Unit]\n" - "Source=%s\n" - "Description=DBUS1: %s\n\n" + "SourcePath=%s\n" + "Description=DBUS1: %s\n" + "Documentation=man:systemd-dbus1-generator(8)\n\n" "[Service]\n" "ExecStart=%s\n" "Type=dbus\n" @@ -83,58 +84,65 @@ static int create_dbus_files( 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_ADDRESS "\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_ADDRESS_FMT ";" UNIX_USER_BUS_ADDRESS_FMT "\n", + getuid(), run); + } } - fflush(f); - if (ferror(f)) { - log_error("Failed to write %s: %m", a); - return -errno; - } + r = fflush_and_check(f); + if (r < 0) + return log_error_errno(r, "Failed to write %s: %m", a); + + fclose(f); + f = NULL; service = s; } - b = strjoin(arg_dest, "/", name, ".busname", NULL); + b = strjoin(arg_dest_late, "/", name, ".busname", NULL); if (!b) return log_oom(); f = fopen(b, "wxe"); - if (!f) { - log_error("Failed to create %s: %m", b); - return -errno; - } + if (!f) + return log_error_errno(errno, "Failed to create %s: %m", b); fprintf(f, "# Automatically generated by systemd-dbus1-generator\n\n" "[Unit]\n" - "Source=%s\n" - "Description=DBUS1: %s\n\n" + "SourcePath=%s\n" + "Description=DBUS1: %s\n" + "Documentation=man:systemd-dbus1-generator(8)\n\n" "[BusName]\n" "Name=%s\n" - "Service=%s\n", + "Service=%s\n" + "AllowWorld=talk\n", path, name, name, service); - fflush(f); - if (ferror(f)) { - log_error("Failed to write %s: %m", b); - return -errno; - } + r = fflush_and_check(f); + if (r < 0) + return log_error_errno(r, "Failed to write %s: %m", b); - 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); - return -errno; - } + if (symlink(b, lnk)) + return log_error_errno(errno, "Failed to create symlink %s: %m", lnk); return 0; } @@ -142,34 +150,24 @@ static int create_dbus_files( static int add_dbus(const char *path, const char *fname, const char *type) { _cleanup_free_ char *name = NULL, *exec = NULL, *user = NULL, *service = NULL; - ConfigTableItem table[] = { + const ConfigTableItem table[] = { { "D-BUS Service", "Name", config_parse_string, 0, &name }, { "D-BUS Service", "Exec", config_parse_string, 0, &exec }, { "D-BUS Service", "User", config_parse_string, 0, &user }, { "D-BUS Service", "SystemdService", config_parse_string, 0, &service }, }; - _cleanup_fclose_ FILE *f = NULL; - _cleanup_free_ char *p = NULL; + char *p; int r; assert(path); assert(fname); - p = strjoin(path, "/", fname, NULL); - if (!p) - return log_oom(); - - f = fopen(p, "re"); - if (!f) { - if (errno == -ENOENT) - return 0; - - log_error("Failed to read %s: %m", p); - return -errno; - } - - r = config_parse(NULL, p, f, "D-BUS Service\0", config_item_table_lookup, table, true, false, NULL); + p = strappenda(path, "/", fname); + r = config_parse(NULL, p, NULL, + "D-BUS Service\0", + config_item_table_lookup, table, + true, false, true, NULL); if (r < 0) return r; @@ -189,7 +187,7 @@ static int add_dbus(const char *path, const char *fname, const char *type) { } 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; } @@ -212,30 +210,20 @@ static int add_dbus(const char *path, const char *fname, const char *type) { 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; - log_error("Failed to enumerate D-Bus activated services: %m"); + log_error_errno(errno, "Failed to enumerate D-Bus activated services: %m"); return -errno; } @@ -246,7 +234,7 @@ static int parse_dbus_fragments(void) { 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; } @@ -254,20 +242,58 @@ static int parse_dbus_fragments(void) { return r; fail: - log_error("Failed to read D-Bus services directory: %m"); + log_error_errno(errno, "Failed to read D-Bus services directory: %m"); 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) + return log_error_errno(errno, "Failed to create symlink %s: %m", t); + + 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) + return log_error_errno(errno, "Failed to create symlink %s: %m", t); + + 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) + return log_error_errno(errno, "Failed to create symlink %s: %m", t); + + t = strappenda(arg_dest, "/" SPECIAL_DBUS_SERVICE); + if (symlink("/dev/null", t) < 0) + return log_error_errno(errno, "Failed to mask %s: %m", t); + + 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(); @@ -275,10 +301,31 @@ int main(int argc, char *argv[]) { umask(0022); - if (access("/dev/kdbus/control", F_OK) < 0) + if (access("/sys/fs/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 + return log_error_errno(r, "Failed to determine whether we are running as user or system instance: %m"); + + 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; }