diff options
-rw-r--r-- | ChangeLog | 30 | ||||
-rw-r--r-- | bus/config-parser.c | 120 | ||||
-rw-r--r-- | bus/session.conf.in | 2 | ||||
-rw-r--r-- | configure.in | 5 | ||||
-rw-r--r-- | dbus/dbus-list.h | 3 | ||||
-rw-r--r-- | dbus/dbus-sysdeps-unix.c | 206 | ||||
-rw-r--r-- | dbus/dbus-sysdeps.h | 5 | ||||
-rw-r--r-- | test/data/valid-config-files/many-rules.conf | 1 |
8 files changed, 368 insertions, 4 deletions
@@ -1,3 +1,33 @@ +2006-11-01 John (J5) Palmieri <johnp@redhat.com> + + * configure.in: expose DBUS_DATADIR + + * bus/config-parser.c: add the standard_session_servicedirs element + to the parser + (bus_config_parser_content): process the standard_session_servicedirs + element by getting the standard directories from sysdeps and merging + them into the service directory list + (test_default_session_servicedirs): make sure we get what we expect + + * bus/session.conf.in: replace the servicedir tag with the + standard_session_servicedirs tag + + * dbus/dbus-list.h: remove the typedef of DBusList and place it in + dbus-sysdeps.h to avoid circular header dependencies + + * dbus/dbus-sysdeps.h: add the typedef of DBusList + + * dbus/dbus-sysdeps-unix.c (split_paths_and_append): utility function + which takes a string of directories delimited by colons, parses them + out, appends a suffix and puts them in a list ignoring empty elements + (_dbus_get_standard_session_servicedirs): returns the standard + directories for a session bus to look for service activation files + on Unix which includes the XDG_DATA_HOME, XDG_DATA_DIRS and + DBUS_DATADIR directories + + * test/data/valid-config-files/many-rules.conf: add the + standard_session_servicedirs tag to the valid config file tests + 2006-10-30 Havoc Pennington <hp@redhat.com> * tools/dbus-launch.1, doc/TODO: capture intent to change the diff --git a/bus/config-parser.c b/bus/config-parser.c index b126eb0c..70bc441d 100644 --- a/bus/config-parser.c +++ b/bus/config-parser.c @@ -47,7 +47,8 @@ typedef enum ELEMENT_INCLUDEDIR, ELEMENT_TYPE, ELEMENT_SELINUX, - ELEMENT_ASSOCIATE + ELEMENT_ASSOCIATE, + ELEMENT_STANDARD_SESSION_SERVICEDIRS } ElementType; typedef enum @@ -161,6 +162,8 @@ element_type_to_name (ElementType type) return "fork"; case ELEMENT_PIDFILE: return "pidfile"; + case ELEMENT_STANDARD_SESSION_SERVICEDIRS: + return "standard_session_servicedirs"; case ELEMENT_SERVICEDIR: return "servicedir"; case ELEMENT_INCLUDEDIR: @@ -800,6 +803,19 @@ start_busconfig_child (BusConfigParser *parser, return TRUE; } + else if (strcmp (element_name, "standard_session_servicedirs") == 0) + { + if (!check_no_attributes (parser, "standard_session_servicedirs", attribute_names, attribute_values, error)) + return FALSE; + + if (push_element (parser, ELEMENT_STANDARD_SESSION_SERVICEDIRS) == NULL) + { + BUS_SET_OOM (error); + return FALSE; + } + + return TRUE; + } else if (strcmp (element_name, "servicedir") == 0) { if (!check_no_attributes (parser, "servicedir", attribute_names, attribute_values, error)) @@ -1927,6 +1943,7 @@ bus_config_parser_end_element (BusConfigParser *parser, case ELEMENT_FORK: case ELEMENT_SELINUX: case ELEMENT_ASSOCIATE: + case ELEMENT_STANDARD_SESSION_SERVICEDIRS: break; } @@ -2335,6 +2352,19 @@ bus_config_parser_content (BusConfigParser *parser, } } break; + case ELEMENT_STANDARD_SESSION_SERVICEDIRS: + { + DBusList *link; + DBusList *dirs; + dirs = NULL; + + if (!_dbus_get_standard_session_servicedirs (&dirs)) + goto nomem; + + while ((link = _dbus_list_pop_first_link (&dirs))) + service_dirs_append_link_unique_or_free (&parser->service_dirs, link); + } + break; case ELEMENT_SERVICEDIR: { @@ -3032,6 +3062,91 @@ process_test_equiv_subdir (const DBusString *test_base_dir, return retval; } + +static const char *test_service_dir_matches[] = + { + "/testusr/testlocal/testshare/dbus-1/services", + "/testusr/testshare/dbus-1/services", + DBUS_DATADIR"/dbus-1/services", + "/testhome/foo/.testlocal/testshare/dbus-1/services", + NULL + }; + +static dbus_bool_t +test_default_session_servicedirs (void) +{ + DBusList *dirs; + DBusList *link; + int i; + + dirs = NULL; + + printf ("Testing retriving the default session service directories\n"); + if (!_dbus_get_standard_session_servicedirs (&dirs)) + _dbus_assert_not_reached ("couldn't get stardard dirs"); + + /* make sure our defaults end with share/dbus-1/service */ + while ((link = _dbus_list_pop_first_link (&dirs))) + { + DBusString path; + + printf (" default service dir: %s\n", (char *)link->data); + _dbus_string_init_const (&path, (char *)link->data); + if (!_dbus_string_ends_with_c_str (&path, "share/dbus-1/services")) + { + printf ("error with default session service directories\n"); + return FALSE; + } + + dbus_free (link->data); + _dbus_list_free_link (link); + } + + if (!_dbus_setenv ("XDG_DATA_HOME", "/testhome/foo/.testlocal/testshare")) + _dbus_assert_not_reached ("couldn't setenv XDG_DATA_HOME"); + + if (!_dbus_setenv ("XDG_DATA_DIRS", ":/testusr/testlocal/testshare: :/testusr/testshare:")) + _dbus_assert_not_reached ("couldn't setenv XDG_DATA_DIRS"); + + if (!_dbus_get_standard_session_servicedirs (&dirs)) + _dbus_assert_not_reached ("couldn't get stardard dirs"); + + /* make sure we read and parse the env variable correctly */ + i = 0; + while ((link = _dbus_list_pop_first_link (&dirs))) + { + printf (" test service dir: %s\n", (char *)link->data); + if (test_service_dir_matches[i] == NULL) + { + printf ("more directories parsed than in match set\n"); + return FALSE; + } + + if (strcmp (test_service_dir_matches[i], + (char *)link->data) != 0) + { + printf ("%s directory does not match %s in the match set\n", + (char *)link->data, + test_service_dir_matches[i]); + return FALSE; + } + + ++i; + + dbus_free (link->data); + _dbus_list_free_link (link); + } + + if (test_service_dir_matches[i] != NULL) + { + printf ("extra data %s in the match set was not matched\n", + test_service_dir_matches[i]); + + return FALSE; + } + + return TRUE; +} dbus_bool_t bus_config_parser_test (const DBusString *test_data_dir) @@ -3043,6 +3158,9 @@ bus_config_parser_test (const DBusString *test_data_dir) return TRUE; } + if (!test_default_session_servicedirs()) + return FALSE; + if (!process_test_valid_subdir (test_data_dir, "valid-config-files", VALID)) return FALSE; diff --git a/bus/session.conf.in b/bus/session.conf.in index ac93b429..344efc54 100644 --- a/bus/session.conf.in +++ b/bus/session.conf.in @@ -10,7 +10,7 @@ <listen>unix:tmpdir=@DBUS_SESSION_SOCKET_DIR@</listen> - <servicedir>@EXPANDED_DATADIR@/dbus-1/services</servicedir> + <standard_session_servicedirs /> <policy context="default"> <!-- Allow everything to be sent --> diff --git a/configure.in b/configure.in index 2d5c713d..b4759b47 100644 --- a/configure.in +++ b/configure.in @@ -1118,6 +1118,11 @@ fi AC_SUBST(DBUS_USER) AC_DEFINE_UNQUOTED(DBUS_USER,"$DBUS_USER", [User for running the system BUS daemon]) +#### Direcotry to install data files into +DBUS_DATADIR=$EXPANDED_DATADIR +AC_SUBST(DBUS_DATADIR) +AC_DEFINE_UNQUOTED(DBUS_DATADIR,"$DBUS_DATADIR", [Directory for installing DBUS data files]) + #### Directory to install dbus-daemon if test -z "$with_dbus_daemondir" ; then DBUS_DAEMONDIR=$EXPANDED_BINDIR diff --git a/dbus/dbus-list.h b/dbus/dbus-list.h index 77e878ce..61160496 100644 --- a/dbus/dbus-list.h +++ b/dbus/dbus-list.h @@ -27,11 +27,10 @@ #include <dbus/dbus-internals.h> #include <dbus/dbus-memory.h> #include <dbus/dbus-types.h> +#include <dbus/dbus-sysdeps.h> DBUS_BEGIN_DECLS -typedef struct DBusList DBusList; - struct DBusList { DBusList *prev; /**< Previous list node. */ diff --git a/dbus/dbus-sysdeps-unix.c b/dbus/dbus-sysdeps-unix.c index 75848b71..f4afad89 100644 --- a/dbus/dbus-sysdeps-unix.c +++ b/dbus/dbus-sysdeps-unix.c @@ -29,6 +29,8 @@ #include "dbus-protocol.h" #include "dbus-transport.h" #include "dbus-string.h" +#include "dbus-userdb.h" +#include "dbus-list.h" #include <sys/types.h> #include <stdlib.h> #include <string.h> @@ -2528,4 +2530,208 @@ _dbus_read_local_machine_uuid (DBusGUID *machine_id, return _dbus_read_uuid_file (&filename, machine_id, create_if_not_found, error); } +#define DBUS_UNIX_STANDARD_SESSION_SERVICEDIR "/dbus-1/services" + +static dbus_bool_t +split_paths_and_append (DBusString *dirs, + const char *suffix, + DBusList **dir_list) +{ + /* split on colon (:) */ + int start; + int i; + int len; + char *cpath; + const DBusString file_suffix; + + start = 0; + i = 0; + + _dbus_string_init_const (&file_suffix, suffix); + + len = _dbus_string_get_length (dirs); + + while (_dbus_string_find (dirs, start, ":", &i)) + { + DBusString path; + + if (!_dbus_string_init (&path)) + goto oom; + + if (!_dbus_string_copy_len (dirs, + start, + i - start, + &path, + 0)) + { + _dbus_string_free (&path); + goto oom; + } + + _dbus_string_chop_white (&path); + + /* check for an empty path */ + if (_dbus_string_get_length (&path) == 0) + goto next; + + if (!_dbus_concat_dir_and_file (&path, + &file_suffix)) + { + _dbus_string_free (&path); + goto oom; + } + + if (!_dbus_string_copy_data(&path, &cpath)) + { + _dbus_string_free (&path); + goto oom; + } + + if (!_dbus_list_append (dir_list, cpath)) + { + _dbus_string_free (&path); + dbus_free (cpath); + goto oom; + } + + next: + _dbus_string_free (&path); + start = i + 1; + } + + if (start != len) + { + DBusString path; + + if (!_dbus_string_init (&path)) + goto oom; + + if (!_dbus_string_copy_len (dirs, + start, + len - start, + &path, + 0)) + { + _dbus_string_free (&path); + goto oom; + } + + if (!_dbus_concat_dir_and_file (&path, + &file_suffix)) + { + _dbus_string_free (&path); + goto oom; + } + + if (!_dbus_string_copy_data(&path, &cpath)) + { + _dbus_string_free (&path); + goto oom; + } + + if (!_dbus_list_append (dir_list, cpath)) + { + _dbus_string_free (&path); + dbus_free (cpath); + goto oom; + } + + _dbus_string_free (&path); + } + + return TRUE; + + oom: + _dbus_list_foreach (dir_list, (DBusForeachFunction)dbus_free, NULL); + _dbus_list_clear (dir_list); + return FALSE; +} + +/** + * Returns the standard directories for a session bus to look for service + * activation files + * + * On UNIX this should be the standard xdg freedesktop.org data directories: + * + * XDG_DATA_HOME=${XDG_DATA_HOME-$HOME/.local/share} + * XDG_DATA_DIRS=${XDG_DATA_DIRS-/usr/local/share:/usr/share} + * + * and + * + * DBUS_DATADIR + * + * @param dirs the directory list we are returning + * @returns #FALSE on OOM + */ + +dbus_bool_t +_dbus_get_standard_session_servicedirs (DBusList **dirs) +{ + const char *xdg_data_home; + const char *xdg_data_dirs; + DBusString servicedir_path; + + if (!_dbus_string_init (&servicedir_path)) + return FALSE; + + xdg_data_home = _dbus_getenv ("XDG_DATA_HOME"); + xdg_data_dirs = _dbus_getenv ("XDG_DATA_DIRS"); + + if (xdg_data_dirs != NULL) + { + if (!_dbus_string_append (&servicedir_path, xdg_data_dirs)) + goto oom; + + if (!_dbus_string_append (&servicedir_path, ":")) + goto oom; + } + else + { + if (!_dbus_string_append (&servicedir_path, "/usr/local/share:/usr/share:")) + goto oom; + } + + /* + * add configured datadir to defaults + * this may be the same as an xdg dir + * however the config parser should take + * care of duplicates + */ + if (!_dbus_string_append (&servicedir_path, DBUS_DATADIR":")) + goto oom; + + if (xdg_data_home != NULL) + { + if (!_dbus_string_append (&servicedir_path, xdg_data_home)) + goto oom; + } + else + { + const DBusString *homedir; + const DBusString local_share; + + if (!_dbus_homedir_from_current_process (&homedir)) + goto oom; + + if (!_dbus_string_append (&servicedir_path, _dbus_string_get_const_data (homedir))) + goto oom; + + _dbus_string_init_const (&local_share, "/.local/share"); + if (!_dbus_concat_dir_and_file (&servicedir_path, &local_share)) + goto oom; + } + + if (!split_paths_and_append (&servicedir_path, + DBUS_UNIX_STANDARD_SESSION_SERVICEDIR, + dirs)) + goto oom; + + _dbus_string_free (&servicedir_path); + return TRUE; + + oom: + _dbus_string_free (&servicedir_path); + return FALSE; +} + /* tests in dbus-sysdeps-util.c */ diff --git a/dbus/dbus-sysdeps.h b/dbus/dbus-sysdeps.h index eb395e05..e7b3eac0 100644 --- a/dbus/dbus-sysdeps.h +++ b/dbus/dbus-sysdeps.h @@ -59,6 +59,9 @@ DBUS_BEGIN_DECLS /** An opaque string type */ typedef struct DBusString DBusString; +/** avoid circular includes with DBusList */ +typedef struct DBusList DBusList; + #if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ > 4) #define _DBUS_GNUC_PRINTF( format_idx, arg_idx ) \ __attribute__((__format__ (__printf__, format_idx, arg_idx))) @@ -291,6 +294,8 @@ dbus_bool_t _dbus_string_get_dirname (const DBusString *filename, DBusString *dirname); dbus_bool_t _dbus_path_is_absolute (const DBusString *filename); +dbus_bool_t _dbus_get_standard_session_servicedirs (DBusList **dirs); + /** Opaque type for reading a directory listing */ typedef struct DBusDirIter DBusDirIter; diff --git a/test/data/valid-config-files/many-rules.conf b/test/data/valid-config-files/many-rules.conf index ab05909f..0a15e83c 100644 --- a/test/data/valid-config-files/many-rules.conf +++ b/test/data/valid-config-files/many-rules.conf @@ -5,6 +5,7 @@ <listen>unix:path=/foo/bar</listen> <listen>tcp:port=1234</listen> <includedir>basic.d</includedir> + <standard_session_servicedirs /> <servicedir>/usr/share/foo</servicedir> <include ignore_missing="yes">nonexistent.conf</include> <policy context="default"> |