* configure.in: expose DBUS_DATADIR
authorJohn (J5) Palmieri <johnp@redhat.com>
Wed, 1 Nov 2006 23:30:46 +0000 (23:30 +0000)
committerJohn (J5) Palmieri <johnp@redhat.com>
Wed, 1 Nov 2006 23:30:46 +0000 (23:30 +0000)
* 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

ChangeLog
bus/config-parser.c
bus/session.conf.in
configure.in
dbus/dbus-list.h
dbus/dbus-sysdeps-unix.c
dbus/dbus-sysdeps.h
test/data/valid-config-files/many-rules.conf

index 4842a13..cad03d5 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -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
index b126eb0..70bc441 100644 (file)
@@ -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;
 
index ac93b42..344efc5 100644 (file)
@@ -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 -->
index 2d5c713..b4759b4 100644 (file)
@@ -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
index 77e878c..6116049 100644 (file)
 #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. */
index 75848b7..f4afad8 100644 (file)
@@ -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 */
index eb395e0..e7b3eac 100644 (file)
@@ -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;
 
index ab05909..0a15e83 100644 (file)
@@ -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">