From 287b628bd2f50d450f986cf6ab5d4d2203f9390a Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 2 Feb 2012 05:36:39 +0100 Subject: [PATCH] activation: if systemd activation is enabled look directly in systemd unit directories for services Previously when systemd bus activation was to be used by a service it had to ship two .service files: one systemd unit file, and one D-Bus activation file. Both files carry the same suffix but contain very different contents. This patch makes it unnecessary to ship the D-Bus activation file, and -- if systemd activation is enabled -- teaches D-Bus to watch the systemd unit files directly. Enumeration of bus-activatable systemd units is very easy: if a unit file (usually symlink) is named "dbus-org.freedesktop.Foobar.service" then it can be bus activated. Hence, all D-Bus needs to do is iterate through the systemd unit directories and look for all files/symlinks whose name starts with "dbus-" and ends in ".service". Opening the files is not necessary. This patch makes the search path for systemd unit files configurable closely following the semantics how native D-Bus activation file search paths are configured. The default search paths is initialized from the information of the systemd pkg-config file. This also hooks up inotify change notification with this scheme. If other init systems want a similar kind of activation this patch lays the ground work for it, in that that the search path structure gains a type enumerator which could be extended for other init systems. This currently only covers systemd integration on the system bus. (session support is out of focus since in systemd we're aiming more for the user bus than the session bus, but the user bus doesn't exist yet). --- bus/activation.c | 412 ++++++++++++++++++++++++++++++++++++++------ bus/activation.h | 4 +- bus/bus.c | 15 ++- bus/config-parser-common.c | 12 ++ bus/config-parser-common.h | 2 + bus/config-parser.c | 88 +++++++++- bus/config-parser.h | 1 + configure.ac | 5 +- dbus/dbus-sysdeps-unix.c | 20 ++ dbus/dbus-sysdeps-win.c | 14 ++ dbus/dbus-sysdeps.h | 1 + 11 files changed, 512 insertions(+), 62 deletions(-) diff --git a/bus/activation.c b/bus/activation.c index 2744e21..3fbc0a3 100644 --- a/bus/activation.c +++ b/bus/activation.c @@ -57,8 +57,15 @@ struct BusActivation DBusHashTable *environment; }; +typedef enum +{ + NATIVE_SERVICE_DIRECTORY, + SYSTEMD_SERVICE_DIRECTORY +} DBusServiceDirectoryType; + typedef struct { + DBusServiceDirectoryType type; int refcount; char *dir_c; DBusHashTable *entries; @@ -256,6 +263,7 @@ update_desktop_file_entry (BusActivation *activation, dbus_bool_t retval; _DBUS_ASSERT_ERROR_IS_CLEAR (error); + _dbus_assert (s_dir->type == NATIVE_SERVICE_DIRECTORY); retval = FALSE; name = NULL; @@ -472,6 +480,137 @@ out: } static dbus_bool_t +load_systemd_file_entry (BusActivation *activation, + BusServiceDirectory *s_dir, + DBusString *filename, + DBusError *error) +{ + BusActivationEntry *entry; + DBusStat stat_buf; + DBusString file_path; + dbus_bool_t retval; + + _DBUS_ASSERT_ERROR_IS_CLEAR (error); + _dbus_assert (s_dir->type == SYSTEMD_SERVICE_DIRECTORY); + + entry = NULL; + retval = FALSE; + + if (!_dbus_string_init (&file_path)) + { + BUS_SET_OOM (error); + return FALSE; + } + + if (!_dbus_string_append (&file_path, s_dir->dir_c) || + !_dbus_concat_dir_and_file (&file_path, filename)) + { + BUS_SET_OOM (error); + goto out; + } + + if (!_dbus_stat (&file_path, &stat_buf, NULL)) + { + dbus_set_error (error, DBUS_ERROR_FAILED, + "Can't stat the service file\n"); + goto out; + } + + if (!_dbus_stat_is_file (&stat_buf)) + { + dbus_set_error (error, DBUS_ERROR_FAILED, + "Service file is not a regular file\n"); + goto out; + } + + entry = _dbus_hash_table_lookup_string (s_dir->entries, + _dbus_string_get_const_data (filename)); + + if (entry == NULL) /* New file */ + { + int len; + char *name; + + /* Strip prefix and suffix of the file name. The caller will + have verified them for us, so we just blindly cut them off + here to get the bus name. This turns + "dbus-org.foobar.Waldo.service into org.foobar.Waldo. */ + len = _dbus_string_get_length (filename); + name = _dbus_memdup (_dbus_string_get_const_data (filename) + 5, len - 5 - 8 + 1); + if (!name) + { + BUS_SET_OOM (error); + goto out; + } + name[len - 5 - 8] = 0; + + if (_dbus_hash_table_lookup_string (activation->entries, name)) + { + dbus_set_error (error, DBUS_ERROR_FAILED, + "Service %s already exists in activation entry list\n", name); + dbus_free(name); + goto out; + } + + entry = dbus_new0 (BusActivationEntry, 1); + if (entry == NULL) + { + BUS_SET_OOM (error); + dbus_free(name); + goto out; + } + + entry->refcount = 1; + entry->s_dir = s_dir; + entry->name = name; + + /* The filename and systemd service name in this case are the + same */ + entry->systemd_service = _dbus_strdup (_dbus_string_get_const_data (filename)); + if (!entry->systemd_service) + { + BUS_SET_OOM (error); + goto out; + } + + entry->filename = _dbus_strdup (_dbus_string_get_const_data (filename)); + if (!entry->filename) + { + BUS_SET_OOM (error); + goto out; + } + + if (!_dbus_hash_table_insert_string (activation->entries, entry->name, bus_activation_entry_ref (entry))) + { + BUS_SET_OOM (error); + goto out; + } + + if (!_dbus_hash_table_insert_string (s_dir->entries, entry->filename, bus_activation_entry_ref (entry))) + { + /* Revert the insertion in the entries table */ + _dbus_hash_table_remove_string (activation->entries, entry->name); + BUS_SET_OOM (error); + goto out; + } + + _dbus_verbose ("Added \"%s\" to list of services\n", entry->name); + } + + entry->mtime = stat_buf.mtime; + retval = TRUE; + +out: + /* if these have been transferred into entry, the variables will be NULL */ + _dbus_string_free (&file_path); + + if (entry) + bus_activation_entry_unref (entry); + + return retval; +} + +static dbus_bool_t check_service_file (BusActivation *activation, BusActivationEntry *entry, BusActivationEntry **updated_entry, @@ -575,9 +714,9 @@ out: * hash entries it already added. */ static dbus_bool_t -update_directory (BusActivation *activation, - BusServiceDirectory *s_dir, - DBusError *error) +update_native_directory (BusActivation *activation, + BusServiceDirectory *s_dir, + DBusError *error) { DBusDirIter *iter; DBusString dir, filename; @@ -588,6 +727,7 @@ update_directory (BusActivation *activation, DBusString full_path; _DBUS_ASSERT_ERROR_IS_CLEAR (error); + _dbus_assert (s_dir->type == NATIVE_SERVICE_DIRECTORY); iter = NULL; desktop_file = NULL; @@ -720,6 +860,129 @@ update_directory (BusActivation *activation, } static dbus_bool_t +update_systemd_directory (BusActivation *activation, + BusServiceDirectory *s_dir, + DBusError *error) +{ + DBusDirIter *iter; + DBusString dir, filename; + DBusError tmp_error; + dbus_bool_t retval; + BusActivationEntry *entry; + DBusString full_path; + + _DBUS_ASSERT_ERROR_IS_CLEAR (error); + _dbus_assert (s_dir->type == SYSTEMD_SERVICE_DIRECTORY); + + iter = NULL; + + _dbus_string_init_const (&dir, s_dir->dir_c); + + if (!_dbus_string_init (&filename)) + { + BUS_SET_OOM (error); + return FALSE; + } + + if (!_dbus_string_init (&full_path)) + { + BUS_SET_OOM (error); + _dbus_string_free (&filename); + return FALSE; + } + + retval = FALSE; + + /* from this point it's safe to "goto out" */ + + iter = _dbus_directory_open (&dir, error); + if (iter == NULL) + { + _dbus_verbose ("Failed to open directory %s: %s\n", + s_dir->dir_c, + error ? error->message : "unknown"); + goto out; + } + + /* Now read the files */ + dbus_error_init (&tmp_error); + while (_dbus_directory_get_next_file (iter, &filename, &tmp_error)) + { + _dbus_assert (!dbus_error_is_set (&tmp_error)); + + _dbus_string_set_length (&full_path, 0); + + if (!_dbus_string_ends_with_c_str (&filename, ".service") || + !_dbus_string_starts_with_c_str (&filename, "dbus-")) + { + _dbus_verbose ("Skipping non-activation file %s\n", + _dbus_string_get_const_data (&filename)); + continue; + } + + entry = _dbus_hash_table_lookup_string (s_dir->entries, _dbus_string_get_const_data (&filename)); + if (entry) /* Already has this service file in the cache */ + continue; + + if (!_dbus_string_append (&full_path, s_dir->dir_c) || + !_dbus_concat_dir_and_file (&full_path, &filename)) + { + BUS_SET_OOM (error); + goto out; + } + + if (!load_systemd_file_entry (activation, s_dir, &filename, &tmp_error)) + { + _dbus_verbose ("Could not add %s to activation entry list: %s\n", + _dbus_string_get_const_data (&full_path), tmp_error.message); + + if (dbus_error_has_name (&tmp_error, DBUS_ERROR_NO_MEMORY)) + { + dbus_move_error (&tmp_error, error); + goto out; + } + + dbus_error_free (&tmp_error); + continue; + } + else + continue; + } + + if (dbus_error_is_set (&tmp_error)) + { + dbus_move_error (&tmp_error, error); + goto out; + } + + retval = TRUE; + + out: + if (!retval) + _DBUS_ASSERT_ERROR_IS_SET (error); + else + _DBUS_ASSERT_ERROR_IS_CLEAR (error); + + if (iter != NULL) + _dbus_directory_close (iter); + _dbus_string_free (&filename); + _dbus_string_free (&full_path); + + return retval; +} + +static dbus_bool_t +update_directory (BusActivation *activation, + BusServiceDirectory *s_dir, + DBusError *error) +{ + if (s_dir->type == SYSTEMD_SERVICE_DIRECTORY) + return update_systemd_directory (activation, s_dir, error); + else + return update_native_directory (activation, s_dir, error); +} + +static dbus_bool_t populate_environment (BusActivation *activation) { DBusString key; @@ -782,14 +1045,71 @@ out: return retval; } +static dbus_bool_t +bus_activation_reload_one (BusActivation *activation, + const char *directory, + DBusServiceDirectoryType type, + DBusError *error) +{ + char *dir; + BusServiceDirectory *s_dir; + + dir = _dbus_strdup (directory); + if (!dir) + { + BUS_SET_OOM (error); + return FALSE; + } + + s_dir = dbus_new0 (BusServiceDirectory, 1); + if (!s_dir) + { + dbus_free (dir); + BUS_SET_OOM (error); + return FALSE; + } + + s_dir->refcount = 1; + s_dir->dir_c = dir; + s_dir->type = type; + + s_dir->entries = _dbus_hash_table_new (DBUS_HASH_STRING, NULL, + (DBusFreeFunction)bus_activation_entry_unref); + + if (!s_dir->entries) + { + bus_service_directory_unref (s_dir); + BUS_SET_OOM (error); + return FALSE; + } + + if (!_dbus_hash_table_insert_string (activation->directories, s_dir->dir_c, s_dir)) + { + bus_service_directory_unref (s_dir); + BUS_SET_OOM (error); + return FALSE; + } + + /* only fail on OOM, it is ok if we can't read the directory */ + if (!update_directory (activation, s_dir, error)) + { + if (dbus_error_has_name (error, DBUS_ERROR_NO_MEMORY)) + return FALSE; + + dbus_error_free (error); + } + + return TRUE; +} + dbus_bool_t bus_activation_reload (BusActivation *activation, const DBusString *address, DBusList **directories, + DBusList **systemd_directories, DBusError *error) { DBusList *link; - char *dir; if (activation->server_address != NULL) dbus_free (activation->server_address); @@ -823,53 +1143,31 @@ bus_activation_reload (BusActivation *activation, link = _dbus_list_get_first_link (directories); while (link != NULL) { - BusServiceDirectory *s_dir; - - dir = _dbus_strdup ((const char *) link->data); - if (!dir) - { - BUS_SET_OOM (error); - goto failed; - } - - s_dir = dbus_new0 (BusServiceDirectory, 1); - if (!s_dir) - { - dbus_free (dir); - BUS_SET_OOM (error); - goto failed; - } + if (!bus_activation_reload_one (activation, + link->data, + NATIVE_SERVICE_DIRECTORY, + error)) + goto failed; - s_dir->refcount = 1; - s_dir->dir_c = dir; - - s_dir->entries = _dbus_hash_table_new (DBUS_HASH_STRING, NULL, - (DBusFreeFunction)bus_activation_entry_unref); - - if (!s_dir->entries) - { - bus_service_directory_unref (s_dir); - BUS_SET_OOM (error); - goto failed; - } + link = _dbus_list_get_next_link (directories, link); + } - if (!_dbus_hash_table_insert_string (activation->directories, s_dir->dir_c, s_dir)) - { - bus_service_directory_unref (s_dir); - BUS_SET_OOM (error); - goto failed; - } + if (bus_context_get_systemd_activation (activation->context)) + { + /* Only enumerate systemd service files when systemd activation + is enabled */ - /* only fail on OOM, it is ok if we can't read the directory */ - if (!update_directory (activation, s_dir, error)) + link = _dbus_list_get_first_link (systemd_directories); + while (link != NULL) { - if (dbus_error_has_name (error, DBUS_ERROR_NO_MEMORY)) + if (!bus_activation_reload_one (activation, + link->data, + SYSTEMD_SERVICE_DIRECTORY, + error)) goto failed; - else - dbus_error_free (error); - } - link = _dbus_list_get_next_link (directories, link); + link = _dbus_list_get_next_link (systemd_directories, link); + } } return TRUE; @@ -881,6 +1179,7 @@ BusActivation* bus_activation_new (BusContext *context, const DBusString *address, DBusList **directories, + DBusList **systemd_directories, DBusError *error) { BusActivation *activation; @@ -898,7 +1197,7 @@ bus_activation_new (BusContext *context, activation->context = context; activation->n_pending_activations = 0; - if (!bus_activation_reload (activation, address, directories, error)) + if (!bus_activation_reload (activation, address, directories, systemd_directories, error)) goto failed; /* Initialize this hash table once, we don't want to lose pending @@ -1794,14 +2093,17 @@ bus_activation_activate_service (BusActivation *activation, return FALSE; } - pending_activation->exec = _dbus_strdup (entry->exec); - if (!pending_activation->exec) + if (entry->exec) { - _dbus_verbose ("Failed to copy service exec for pending activation\n"); - BUS_SET_OOM (error); - bus_pending_activation_unref (pending_activation); - bus_pending_activation_entry_free (pending_activation_entry); - return FALSE; + pending_activation->exec = _dbus_strdup (entry->exec); + if (!pending_activation->exec) + { + _dbus_verbose ("Failed to copy service exec for pending activation\n"); + BUS_SET_OOM (error); + bus_pending_activation_unref (pending_activation); + bus_pending_activation_entry_free (pending_activation_entry); + return FALSE; + } } if (entry->systemd_service) @@ -2443,15 +2745,17 @@ do_service_reload_test (DBusString *dir, dbus_bool_t oom_test) BusActivation *activation; DBusString address; DBusList *directories; + DBusList *systemd_directories; CheckData d; directories = NULL; + systemd_directories = NULL; _dbus_string_init_const (&address, ""); if (!_dbus_list_append (&directories, _dbus_string_get_data (dir))) return FALSE; - activation = bus_activation_new (NULL, &address, &directories, NULL); + activation = bus_activation_new (NULL, &address, &directories, &systemd_directories, NULL); if (!activation) return FALSE; diff --git a/bus/activation.h b/bus/activation.h index 97f25b1..c56facd 100644 --- a/bus/activation.h +++ b/bus/activation.h @@ -31,10 +31,12 @@ BusActivation* bus_activation_new (BusContext *context, const DBusString *address, DBusList **directories, + DBusList **systemd_directories, DBusError *error); -dbus_bool_t bus_activation_reload (BusActivation *activation, +dbus_bool_t bus_activation_reload (BusActivation *activation, const DBusString *address, DBusList **directories, + DBusList **systemd_directories, DBusError *error); BusActivation* bus_activation_ref (BusActivation *activation); void bus_activation_unref (BusActivation *activation); diff --git a/bus/bus.c b/bus/bus.c index 358a910..3fb08b0 100644 --- a/bus/bus.c +++ b/bus/bus.c @@ -481,7 +481,7 @@ process_config_every_time (BusContext *context, { DBusString full_address; DBusList *link; - DBusList **dirs; + DBusList **dirs, **systemd_dirs; char *addr; const char *servicehelper; char *s; @@ -552,6 +552,7 @@ process_config_every_time (BusContext *context, /* get the service directories */ dirs = bus_config_parser_get_service_dirs (parser); + systemd_dirs = bus_config_parser_get_systemd_service_dirs (parser); /* and the service helper */ servicehelper = bus_config_parser_get_servicehelper (parser); @@ -571,12 +572,12 @@ process_config_every_time (BusContext *context, /* Create activation subsystem */ if (context->activation) { - if (!bus_activation_reload (context->activation, &full_address, dirs, error)) + if (!bus_activation_reload (context->activation, &full_address, dirs, systemd_dirs, error)) goto failed; } else { - context->activation = bus_activation_new (context, &full_address, dirs, error); + context->activation = bus_activation_new (context, &full_address, dirs, systemd_dirs, error); } if (context->activation == NULL) @@ -600,6 +601,7 @@ process_config_every_time (BusContext *context, static dbus_bool_t list_concat_new (DBusList **a, DBusList **b, + DBusList **c, DBusList **result) { DBusList *link; @@ -616,6 +618,12 @@ list_concat_new (DBusList **a, if (!_dbus_list_append (result, link->data)) goto oom; } + if (c != NULL) + for (link = _dbus_list_get_first_link (c); link; link = _dbus_list_get_next_link (c, link)) + { + if (!_dbus_list_append (result, link->data)) + goto oom; + } return TRUE; oom: @@ -666,6 +674,7 @@ process_config_postinit (BusContext *context, */ if (!list_concat_new (bus_config_parser_get_conf_dirs (parser), bus_config_parser_get_service_dirs (parser), + bus_config_parser_get_systemd_service_dirs (parser), &watched_dirs)) { BUS_SET_OOM (error); diff --git a/bus/config-parser-common.c b/bus/config-parser-common.c index c522ff4..ac5f891 100644 --- a/bus/config-parser-common.c +++ b/bus/config-parser-common.c @@ -91,10 +91,18 @@ bus_config_parser_element_name_to_type (const char *name) { return ELEMENT_STANDARD_SYSTEM_SERVICEDIRS; } + else if (strcmp (name, "standard_system_systemd_servicedirs") == 0) + { + return ELEMENT_STANDARD_SYSTEM_SYSTEMD_SERVICEDIRS; + } else if (strcmp (name, "servicedir") == 0) { return ELEMENT_SERVICEDIR; } + else if (strcmp (name, "systemd_servicedir") == 0) + { + return ELEMENT_SYSTEMD_SERVICEDIR; + } else if (strcmp (name, "include") == 0) { return ELEMENT_INCLUDE; @@ -163,8 +171,12 @@ bus_config_parser_element_type_to_name (ElementType type) return "standard_session_servicedirs"; case ELEMENT_STANDARD_SYSTEM_SERVICEDIRS: return "standard_system_servicedirs"; + case ELEMENT_STANDARD_SYSTEM_SYSTEMD_SERVICEDIRS: + return "standard_system_systemd_servicedirs"; case ELEMENT_SERVICEDIR: return "servicedir"; + case ELEMENT_SYSTEMD_SERVICEDIR: + return "systemd_servicedir"; case ELEMENT_SERVICEHELPER: return "servicehelper"; case ELEMENT_INCLUDEDIR: diff --git a/bus/config-parser-common.h b/bus/config-parser-common.h index 186bf4c..a7c1536 100644 --- a/bus/config-parser-common.h +++ b/bus/config-parser-common.h @@ -39,6 +39,7 @@ typedef enum ELEMENT_FORK, ELEMENT_PIDFILE, ELEMENT_SERVICEDIR, + ELEMENT_SYSTEMD_SERVICEDIR, ELEMENT_SERVICEHELPER, ELEMENT_INCLUDEDIR, /* this is really , but winioctl.h defines ELEMENT_TYPE */ @@ -47,6 +48,7 @@ typedef enum ELEMENT_ASSOCIATE, ELEMENT_STANDARD_SESSION_SERVICEDIRS, ELEMENT_STANDARD_SYSTEM_SERVICEDIRS, + ELEMENT_STANDARD_SYSTEM_SYSTEMD_SERVICEDIRS, ELEMENT_KEEP_UMASK, ELEMENT_SYSLOG, ELEMENT_ALLOW_ANONYMOUS diff --git a/bus/config-parser.c b/bus/config-parser.c index deee59f..2827d5f 100644 --- a/bus/config-parser.c +++ b/bus/config-parser.c @@ -99,6 +99,7 @@ struct BusConfigParser DBusList *mechanisms; /**< Auth mechanisms */ DBusList *service_dirs; /**< Directories to look for session services in */ + DBusList *systemd_service_dirs; /**< Same for systemd services */ DBusList *conf_dirs; /**< Directories to look for policy configuration in */ @@ -333,6 +334,9 @@ merge_included (BusConfigParser *parser, while ((link = _dbus_list_pop_first_link (&included->service_dirs))) service_dirs_append_link_unique_or_free (&parser->service_dirs, link); + while ((link = _dbus_list_pop_first_link (&included->systemd_service_dirs))) + service_dirs_append_link_unique_or_free (&parser->systemd_service_dirs, link); + while ((link = _dbus_list_pop_first_link (&included->conf_dirs))) _dbus_list_append_link (&parser->conf_dirs, link); @@ -503,6 +507,12 @@ bus_config_parser_unref (BusConfigParser *parser) _dbus_list_clear (&parser->service_dirs); + _dbus_list_foreach (&parser->systemd_service_dirs, + (DBusForeachFunction) dbus_free, + NULL); + + _dbus_list_clear (&parser->systemd_service_dirs); + _dbus_list_foreach (&parser->conf_dirs, (DBusForeachFunction) dbus_free, NULL); @@ -865,6 +875,32 @@ start_busconfig_child (BusConfigParser *parser, return TRUE; } + else if (element_type == ELEMENT_STANDARD_SYSTEM_SYSTEMD_SERVICEDIRS) + { + DBusList *link; + DBusList *dirs; + dirs = NULL; + + if (!check_no_attributes (parser, "standard_system_systemd_servicedirs", attribute_names, attribute_values, error)) + return FALSE; + + if (push_element (parser, ELEMENT_STANDARD_SYSTEM_SYSTEMD_SERVICEDIRS) == NULL) + { + BUS_SET_OOM (error); + return FALSE; + } + + if (!_dbus_get_standard_system_systemd_servicedirs (&dirs)) + { + BUS_SET_OOM (error); + return FALSE; + } + + while ((link = _dbus_list_pop_first_link (&dirs))) + service_dirs_append_link_unique_or_free (&parser->systemd_service_dirs, link); + + return TRUE; + } else if (element_type == ELEMENT_ALLOW_ANONYMOUS) { if (!check_no_attributes (parser, "allow_anonymous", attribute_names, attribute_values, error)) @@ -2010,6 +2046,7 @@ bus_config_parser_end_element (BusConfigParser *parser, case ELEMENT_PIDFILE: case ELEMENT_AUTH: case ELEMENT_SERVICEDIR: + case ELEMENT_SYSTEMD_SERVICEDIR: case ELEMENT_SERVICEHELPER: case ELEMENT_INCLUDEDIR: case ELEMENT_LIMIT: @@ -2040,6 +2077,7 @@ bus_config_parser_end_element (BusConfigParser *parser, case ELEMENT_ASSOCIATE: case ELEMENT_STANDARD_SESSION_SERVICEDIRS: case ELEMENT_STANDARD_SYSTEM_SERVICEDIRS: + case ELEMENT_STANDARD_SYSTEM_SYSTEMD_SERVICEDIRS: case ELEMENT_ALLOW_ANONYMOUS: break; } @@ -2335,8 +2373,9 @@ bus_config_parser_content (BusConfigParser *parser, case ELEMENT_FORK: case ELEMENT_SYSLOG: case ELEMENT_KEEP_UMASK: - case ELEMENT_STANDARD_SESSION_SERVICEDIRS: - case ELEMENT_STANDARD_SYSTEM_SERVICEDIRS: + case ELEMENT_STANDARD_SESSION_SERVICEDIRS: + case ELEMENT_STANDARD_SYSTEM_SERVICEDIRS: + case ELEMENT_STANDARD_SYSTEM_SYSTEMD_SERVICEDIRS: case ELEMENT_ALLOW_ANONYMOUS: case ELEMENT_SELINUX: case ELEMENT_ASSOCIATE: @@ -2559,6 +2598,40 @@ bus_config_parser_content (BusConfigParser *parser, } break; + case ELEMENT_SYSTEMD_SERVICEDIR: + { + char *s; + DBusString full_path; + + e->had_content = TRUE; + + if (!_dbus_string_init (&full_path)) + goto nomem; + + if (!make_full_path (&parser->basedir, content, &full_path)) + { + _dbus_string_free (&full_path); + goto nomem; + } + + if (!_dbus_string_copy_data (&full_path, &s)) + { + _dbus_string_free (&full_path); + goto nomem; + } + + /* _only_ extra session directories can be specified */ + if (!service_dirs_append_unique_or_free (&parser->systemd_service_dirs, s)) + { + _dbus_string_free (&full_path); + dbus_free (s); + goto nomem; + } + + _dbus_string_free (&full_path); + } + break; + case ELEMENT_LIMIT: { long val; @@ -2647,6 +2720,12 @@ bus_config_parser_get_service_dirs (BusConfigParser *parser) } DBusList** +bus_config_parser_get_systemd_service_dirs (BusConfigParser *parser) +{ + return &parser->systemd_service_dirs; +} + +DBusList** bus_config_parser_get_conf_dirs (BusConfigParser *parser) { return &parser->conf_dirs; @@ -3058,7 +3137,10 @@ config_parsers_equal (const BusConfigParser *a, if (!lists_of_c_strings_equal (a->service_dirs, b->service_dirs)) return FALSE; - + + if (!lists_of_c_strings_equal (a->systemd_service_dirs, b->systemd_service_dirs)) + return FALSE; + /* FIXME: compare policy */ /* FIXME: compare service selinux ID table */ diff --git a/bus/config-parser.h b/bus/config-parser.h index ba5bf74..455a121 100644 --- a/bus/config-parser.h +++ b/bus/config-parser.h @@ -69,6 +69,7 @@ dbus_bool_t bus_config_parser_get_keep_umask (BusConfigParser *parser); const char* bus_config_parser_get_pidfile (BusConfigParser *parser); const char* bus_config_parser_get_servicehelper (BusConfigParser *parser); DBusList** bus_config_parser_get_service_dirs (BusConfigParser *parser); +DBusList** bus_config_parser_get_systemd_service_dirs (BusConfigParser *parser); DBusList** bus_config_parser_get_conf_dirs (BusConfigParser *parser); BusPolicy* bus_config_parser_steal_policy (BusConfigParser *parser); void bus_config_parser_get_limits (BusConfigParser *parser, diff --git a/configure.ac b/configure.ac index 725122d..239c5e5 100644 --- a/configure.ac +++ b/configure.ac @@ -1438,7 +1438,8 @@ AS_HELP_STRING([--with-systemdsystemunitdir=DIR], [Directory for systemd service [], [ PKG_CHECK_EXISTS([systemd >= 21], - [with_systemdsystemunitdir=$($PKG_CONFIG --variable=systemdsystemunitdir systemd)], + [with_systemdsystemunitdir=$($PKG_CONFIG --variable=systemdsystemunitdir systemd) ; + systemdsystemunitpath=$($PKG_CONFIG --variable=systemdsystemunitpath systemd)], [with_systemdsystemunitdir=no]) ]) if test "x$with_systemdsystemunitdir" != xno; then @@ -1446,6 +1447,8 @@ if test "x$with_systemdsystemunitdir" != xno; then fi AM_CONDITIONAL(HAVE_SYSTEMD, [test -n "$with_systemdsystemunitdir" -a "x$with_systemdsystemunitdir" != xno ]) +AC_DEFINE_UNQUOTED(SYSTEMD_SYSTEM_UNIT_PATH, "$systemdsystemunitpath", [systemd unit search path]) + ##### Set up location for system bus socket if ! test -z "$with_system_socket"; then DBUS_SYSTEM_SOCKET=$with_system_socket diff --git a/dbus/dbus-sysdeps-unix.c b/dbus/dbus-sysdeps-unix.c index 22868e2..726aca5 100644 --- a/dbus/dbus-sysdeps-unix.c +++ b/dbus/dbus-sysdeps-unix.c @@ -3742,6 +3742,26 @@ _dbus_get_standard_system_servicedirs (DBusList **dirs) } /** + * Returns the standard directories for a system bus to look for systemd service + * activation files in + * + * @param dirs the directory list we are returning + * @returns #FALSE on OOM + */ +dbus_bool_t +_dbus_get_standard_system_systemd_servicedirs (DBusList **dirs) +{ + DBusString path; + dbus_bool_t retval; + + _dbus_string_init_const (&path, SYSTEMD_SYSTEM_UNIT_PATH); + retval = _dbus_split_paths_and_append (&path, "", dirs); + _dbus_string_free (&path); + + return retval; +} + +/** * Append the absolute path of the system.conf file * (there is no system bus on Windows so this can just * return FALSE and print a warning or something) diff --git a/dbus/dbus-sysdeps-win.c b/dbus/dbus-sysdeps-win.c index e30e92f..d9d67d7 100644 --- a/dbus/dbus-sysdeps-win.c +++ b/dbus/dbus-sysdeps-win.c @@ -3064,6 +3064,20 @@ _dbus_get_standard_system_servicedirs (DBusList **dirs) return TRUE; } +/** + * Returns the standard directories for a system bus to look for systemd service + * activation files in + * + * @param dirs the directory list we are returning + * @returns #FALSE on OOM + */ +dbus_bool_t +_dbus_get_standard_system_systemd_servicedirs (DBusList **dirs) +{ + *dirs = NULL; + return TRUE; +} + _DBUS_DEFINE_GLOBAL_LOCK (atomic); /** diff --git a/dbus/dbus-sysdeps.h b/dbus/dbus-sysdeps.h index ca73880..b1a1911 100644 --- a/dbus/dbus-sysdeps.h +++ b/dbus/dbus-sysdeps.h @@ -327,6 +327,7 @@ dbus_bool_t _dbus_path_is_absolute (const DBusString *filename); dbus_bool_t _dbus_get_standard_session_servicedirs (DBusList **dirs); dbus_bool_t _dbus_get_standard_system_servicedirs (DBusList **dirs); +dbus_bool_t _dbus_get_standard_system_systemd_servicedirs (DBusList **dirs); dbus_bool_t _dbus_append_system_config_file (DBusString *str); dbus_bool_t _dbus_append_session_config_file (DBusString *str); -- 1.7.7.4