2003-04-03 Havoc Pennington <hp@pobox.com>
authorHavoc Pennington <hp@redhat.com>
Thu, 3 Apr 2003 05:22:49 +0000 (05:22 +0000)
committerHavoc Pennington <hp@redhat.com>
Thu, 3 Apr 2003 05:22:49 +0000 (05:22 +0000)
* bus/config-parser.c (bus_config_parser_unref): free
list of mechanisms, bug discovered by test suite enhancements
(putting system.conf and session.conf into suite)

* test/Makefile.am, test/test-service.c: add placeholder for a
test service that we'll activate as part of test suite. Doesn't
do anything yet.

* dbus/dbus-sysdeps.c (_dbus_setenv): support unsetenv by
setting NULL value, and use system malloc not dbus_malloc()
when we have unavoidable memleakage.

* dbus/dbus-bus.c (dbus_bus_get): fix bug where bus type of 0
didn't work, and support DBUS_BUS_ACTIVATION.

* bus/activation.c (child_setup): pass our well-known bus type to
the child

* bus/config-parser.c: support <type> to specify well-known type

* doc/dbus-specification.sgml: document the env variables to
locate well-known buses and find service activator

16 files changed:
ChangeLog
bus/activation.c
bus/bus.c
bus/bus.h
bus/config-parser.c
bus/config-parser.h
bus/session.conf.in
bus/system.conf.in
configure.in
dbus/dbus-bus.c
dbus/dbus-bus.h
dbus/dbus-sysdeps.c
doc/config-file.txt
doc/dbus-specification.sgml
test/Makefile.am
test/test-service.c [new file with mode: 0644]

index 025e50f..3772119 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,28 @@
+2003-04-03  Havoc Pennington  <hp@pobox.com>
+
+       * bus/config-parser.c (bus_config_parser_unref): free 
+       list of mechanisms, bug discovered by test suite enhancements
+       (putting system.conf and session.conf into suite)
+
+       * test/Makefile.am, test/test-service.c: add placeholder for a
+       test service that we'll activate as part of test suite. Doesn't 
+       do anything yet.
+
+       * dbus/dbus-sysdeps.c (_dbus_setenv): support unsetenv by 
+       setting NULL value, and use system malloc not dbus_malloc() 
+       when we have unavoidable memleakage.
+
+       * dbus/dbus-bus.c (dbus_bus_get): fix bug where bus type of 0
+       didn't work, and support DBUS_BUS_ACTIVATION.
+       
+       * bus/activation.c (child_setup): pass our well-known bus type to
+       the child
+
+       * bus/config-parser.c: support <type> to specify well-known type
+
+       * doc/dbus-specification.sgml: document the env variables to 
+       locate well-known buses and find service activator
+
 2003-04-02  Havoc Pennington  <hp@redhat.com>
 
        * test/Makefile.am (all-local): add a rule to copy tests to
index 0dfce3f..eb56a74 100644 (file)
@@ -404,12 +404,20 @@ static void
 child_setup (void *data)
 {
   BusActivation *activation = data;
+  const char *type;
   
   /* If no memory, we simply have the child exit, so it won't try
    * to connect to the wrong thing.
    */
-  if (!_dbus_setenv ("DBUS_ADDRESS", activation->server_address))
+  if (!_dbus_setenv ("DBUS_ACTIVATION_ADDRESS", activation->server_address))
     _dbus_exit (1);
+
+  type = bus_context_get_type (activation->context);
+  if (type != NULL)
+    {
+      if (!_dbus_setenv ("DBUS_BUS_TYPE", type))
+        _dbus_exit (1);
+    }
 }
 
 dbus_bool_t
index 82452d0..381f631 100644 (file)
--- a/bus/bus.c
+++ b/bus/bus.c
@@ -36,6 +36,7 @@
 struct BusContext
 {
   int refcount;
+  char *type;
   char *address;
   DBusList *servers;
   BusConnections *connections;
@@ -290,6 +291,9 @@ bus_context_new (const DBusString *config_file,
       if (!_dbus_change_identity (creds.uid, creds.gid, error))
         goto failed;
     }
+
+  /* note that type may be NULL */
+  context->type = _dbus_strdup (bus_config_parser_get_type (parser));
   
   /* We have to build the address backward, so that
    * <listen> later in the config file have priority
@@ -496,12 +500,20 @@ bus_context_unref (BusContext *context)
           _dbus_hash_table_unref (context->rules_by_gid);
           context->rules_by_gid = NULL;
         }
-      
+
+      dbus_free (context->type);
       dbus_free (context->address);
       dbus_free (context);
     }
 }
 
+/* type may be NULL */
+const char*
+bus_context_get_type (BusContext *context)
+{
+  return context->type;
+}
+
 BusRegistry*
 bus_context_get_registry (BusContext  *context)
 {
index 3e2dc46..902f5fa 100644 (file)
--- a/bus/bus.h
+++ b/bus/bus.h
@@ -43,6 +43,7 @@ BusContext*     bus_context_new                      (const DBusString *config_f
 void            bus_context_shutdown                 (BusContext       *context);
 void            bus_context_ref                      (BusContext       *context);
 void            bus_context_unref                    (BusContext       *context);
+const char*     bus_context_get_type                 (BusContext       *context);
 BusRegistry*    bus_context_get_registry             (BusContext       *context);
 BusConnections* bus_context_get_connections          (BusContext       *context);
 BusActivation*  bus_context_get_activation           (BusContext       *context);
index 9e16e4f..f9473ff 100644 (file)
@@ -41,7 +41,8 @@ typedef enum
   ELEMENT_DENY,
   ELEMENT_FORK,
   ELEMENT_SERVICEDIR,
-  ELEMENT_INCLUDEDIR
+  ELEMENT_INCLUDEDIR,
+  ELEMENT_TYPE
 } ElementType;
 
 typedef struct
@@ -59,11 +60,6 @@ typedef struct
 
     struct
     {
-      char *mechanism;
-    } auth;
-
-    struct
-    {
       char *context;
       char *user;
       char *group;
@@ -89,6 +85,8 @@ struct BusConfigParser
 
   char *user;          /**< user to run as */
 
+  char *bus_type;          /**< Message bus type */
+  
   DBusList *listen_on; /**< List of addresses to listen to */
 
   DBusList *mechanisms; /**< Auth mechanisms */
@@ -129,6 +127,8 @@ element_type_to_name (ElementType type)
       return "servicedir";
     case ELEMENT_INCLUDEDIR:
       return "includedir";
+    case ELEMENT_TYPE:
+      return "type";
     }
 
   _dbus_assert_not_reached ("bad element type");
@@ -213,6 +213,13 @@ merge_included (BusConfigParser *parser,
       included->user = NULL;
     }
 
+  if (included->bus_type != NULL)
+    {
+      dbus_free (parser->bus_type);
+      parser->bus_type = included->bus_type;
+      included->bus_type = NULL;
+    }
+  
   if (included->fork)
     parser->fork = TRUE;
   
@@ -276,7 +283,8 @@ bus_config_parser_unref (BusConfigParser *parser)
         pop_element (parser);
 
       dbus_free (parser->user);
-
+      dbus_free (parser->bus_type);
+      
       _dbus_list_foreach (&parser->listen_on,
                           (DBusForeachFunction) dbus_free,
                           NULL);
@@ -289,6 +297,12 @@ bus_config_parser_unref (BusConfigParser *parser)
 
       _dbus_list_clear (&parser->service_dirs);
 
+      _dbus_list_foreach (&parser->mechanisms,
+                          (DBusForeachFunction) dbus_free,
+                          NULL);
+
+      _dbus_list_clear (&parser->mechanisms);
+      
       _dbus_string_free (&parser->basedir);
       
       dbus_free (parser);
@@ -451,7 +465,20 @@ start_busconfig_child (BusConfigParser   *parser,
 
       if (push_element (parser, ELEMENT_USER) == NULL)
         {
-          dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
+          BUS_SET_OOM (error);
+          return FALSE;
+        }
+
+      return TRUE;
+    }
+  else if (strcmp (element_name, "type") == 0)
+    {
+      if (!check_no_attributes (parser, "type", attribute_names, attribute_values, error))
+        return FALSE;
+
+      if (push_element (parser, ELEMENT_TYPE) == NULL)
+        {
+          BUS_SET_OOM (error);
           return FALSE;
         }
 
@@ -464,7 +491,7 @@ start_busconfig_child (BusConfigParser   *parser,
 
       if (push_element (parser, ELEMENT_FORK) == NULL)
         {
-          dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
+          BUS_SET_OOM (error);
           return FALSE;
         }
 
@@ -479,7 +506,7 @@ start_busconfig_child (BusConfigParser   *parser,
 
       if (push_element (parser, ELEMENT_LISTEN) == NULL)
         {
-          dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
+          BUS_SET_OOM (error);
           return FALSE;
         }
 
@@ -492,7 +519,7 @@ start_busconfig_child (BusConfigParser   *parser,
 
       if (push_element (parser, ELEMENT_AUTH) == NULL)
         {
-          dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
+          BUS_SET_OOM (error);
           return FALSE;
         }
 
@@ -505,7 +532,7 @@ start_busconfig_child (BusConfigParser   *parser,
 
       if (push_element (parser, ELEMENT_INCLUDEDIR) == NULL)
         {
-          dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
+          BUS_SET_OOM (error);
           return FALSE;
         }
 
@@ -518,7 +545,7 @@ start_busconfig_child (BusConfigParser   *parser,
 
       if (push_element (parser, ELEMENT_SERVICEDIR) == NULL)
         {
-          dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
+          BUS_SET_OOM (error);
           return FALSE;
         }
 
@@ -531,7 +558,7 @@ start_busconfig_child (BusConfigParser   *parser,
 
       if ((e = push_element (parser, ELEMENT_INCLUDE)) == NULL)
         {
-          dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
+          BUS_SET_OOM (error);
           return FALSE;
         }
 
@@ -570,7 +597,7 @@ start_busconfig_child (BusConfigParser   *parser,
 
       if ((e = push_element (parser, ELEMENT_POLICY)) == NULL)
         {
-          dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
+          BUS_SET_OOM (error);
           return FALSE;
         }
 
@@ -608,7 +635,7 @@ start_policy_child (BusConfigParser   *parser,
     {
       if (push_element (parser, ELEMENT_ALLOW) == NULL)
         {
-          dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
+          BUS_SET_OOM (error);
           return FALSE;
         }
       
@@ -618,7 +645,7 @@ start_policy_child (BusConfigParser   *parser,
     {
       if (push_element (parser, ELEMENT_DENY) == NULL)
         {
-          dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
+          BUS_SET_OOM (error);
           return FALSE;
         }
       
@@ -657,7 +684,7 @@ bus_config_parser_start_element (BusConfigParser   *parser,
           
           if (push_element (parser, ELEMENT_BUSCONFIG) == NULL)
             {
-              dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
+              BUS_SET_OOM (error);
               return FALSE;
             }
 
@@ -725,7 +752,8 @@ bus_config_parser_end_element (BusConfigParser   *parser,
        * being paranoid about XML parsers
        */
       dbus_set_error (error, DBUS_ERROR_FAILED,
-                      "XML element ended which was not the topmost element on the stack");
+                      "XML element <%s> ended but topmost element on the stack was <%s>",
+                      element_name, n);
       return FALSE;
     }
 
@@ -740,6 +768,7 @@ bus_config_parser_end_element (BusConfigParser   *parser,
 
     case ELEMENT_INCLUDE:
     case ELEMENT_USER:
+    case ELEMENT_TYPE:
     case ELEMENT_LISTEN:
     case ELEMENT_AUTH:
     case ELEMENT_SERVICEDIR:
@@ -1040,6 +1069,20 @@ bus_config_parser_content (BusConfigParser   *parser,
       }
       break;
 
+    case ELEMENT_TYPE:
+      {
+        char *s;
+
+        e->had_content = TRUE;
+
+        if (!_dbus_string_copy_data (content, &s))
+          goto nomem;
+        
+        dbus_free (parser->bus_type);
+        parser->bus_type = s;
+      }
+      break;
+      
     case ELEMENT_LISTEN:
       {
         char *s;
@@ -1149,6 +1192,12 @@ bus_config_parser_get_user (BusConfigParser *parser)
   return parser->user;
 }
 
+const char*
+bus_config_parser_get_type (BusConfigParser *parser)
+{
+  return parser->bus_type;
+}
+
 DBusList**
 bus_config_parser_get_addresses (BusConfigParser *parser)
 {
index 9b433f0..af5c826 100644 (file)
@@ -56,6 +56,7 @@ dbus_bool_t      bus_config_parser_finished      (BusConfigParser   *parser,
 
 /* Functions for extracting the parse results */
 const char* bus_config_parser_get_user         (BusConfigParser *parser);
+const char* bus_config_parser_get_type         (BusConfigParser *parser);
 DBusList**  bus_config_parser_get_addresses    (BusConfigParser *parser);
 DBusList**  bus_config_parser_get_mechanisms   (BusConfigParser *parser);
 dbus_bool_t bus_config_parser_get_fork         (BusConfigParser *parser);
index fe7aa5f..2847895 100644 (file)
@@ -5,6 +5,9 @@
 <!DOCTYPE busconfig PUBLIC "-//freedesktop//DTD D-BUS Bus Configuration 1.0//EN"
  "http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">
 <busconfig>
+  <!-- Our well-known bus type, don't change this -->
+  <type>session</type>
+
   <!-- FIXME - this is fairly complicated to fix.
        Propose the following:
          - add "unix:tmpdir=/tmp" which means unix domain transport 
@@ -18,6 +21,7 @@
            reads the address from there and sets the env variable
     -->
   <listen>unix:path=/tmp/foobar</listen>
+
   <policy context="default">
     <!-- Allow everything -->
     <allow send="*"/>
index 7752b57..15a4972 100644 (file)
@@ -11,6 +11,9 @@
  "http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">
 <busconfig>
 
+  <!-- Our well-known bus type, do not change this -->
+  <type>system</type>
+
   <!-- Run as special user -->
   <user>messagebus</user>
 
index 46e1870..fbf60d7 100644 (file)
@@ -139,7 +139,7 @@ AC_C_BIGENDIAN
 AC_CHECK_LIB(socket,socket)
 AC_CHECK_LIB(nsl,gethostbyname)
 
-AC_CHECK_FUNCS(vsnprintf vasprintf nanosleep usleep poll setenv socketpair getgrouplist)
+AC_CHECK_FUNCS(vsnprintf vasprintf nanosleep usleep poll setenv unsetenv socketpair getgrouplist)
 
 AC_CHECK_HEADERS(execinfo.h, [AC_CHECK_FUNCS(backtrace)])
 
index d65a3f0..dc1762e 100644 (file)
@@ -25,6 +25,7 @@
 #include "dbus-bus.h"
 #include "dbus-protocol.h"
 #include "dbus-internals.h"
+#include <string.h>
 
 /**
  * @defgroup DBusBus Message bus APIs
@@ -61,11 +62,132 @@ static int bus_data_slot = -1;
  */
 static int bus_data_slot_refcount = 0;
 
+/** Number of bus types */
+#define N_BUS_TYPES 3
+
+static DBusConnection *bus_connections[N_BUS_TYPES];
+static char *bus_connection_addresses[N_BUS_TYPES] = { NULL, NULL, NULL };
+
+static DBusBusType activation_bus_type = DBUS_BUS_ACTIVATION;
+
+static dbus_bool_t initialized = FALSE;
+
 /**
- * Lock for bus_data_slot and bus_data_slot_refcount
+ * Lock for globals in this file
  */
 _DBUS_DEFINE_GLOBAL_LOCK (bus);
 
+static void
+addresses_shutdown_func (void *data)
+{
+  int i;
+
+  i = 0;
+  while (i < N_BUS_TYPES)
+    {
+      if (bus_connections[i] != NULL)
+        _dbus_warn ("dbus_shutdown() called but connections were still live!");
+      
+      dbus_free (bus_connection_addresses[i]);
+      bus_connection_addresses[i] = NULL;
+      ++i;
+    }
+
+  activation_bus_type = DBUS_BUS_ACTIVATION;
+}
+
+static dbus_bool_t
+get_from_env (char           **connection_p,
+              const char      *env_var)
+{
+  const char *s;
+  
+  _dbus_assert (*connection_p == NULL);
+  
+  s = _dbus_getenv (env_var);
+  if (s == NULL || *s == '\0')
+    return TRUE; /* successfully didn't use the env var */
+  else
+    {
+      *connection_p = _dbus_strdup (s);
+      return *connection_p != NULL;
+    }
+}
+
+static dbus_bool_t
+init_connections_unlocked (void)
+{
+  if (!initialized)
+    {
+      const char *s;
+      
+      bus_connections[0] = NULL;
+      bus_connections[1] = NULL;
+      bus_connections[2] = NULL;
+
+      /* Don't init these twice, we may run this code twice if
+       * init_connections_unlocked() fails midway through.
+       */
+      
+       if (bus_connection_addresses[DBUS_BUS_SYSTEM] == NULL)
+         {
+           if (!get_from_env (&bus_connection_addresses[DBUS_BUS_SYSTEM],
+                              "DBUS_SYSTEM_BUS_ADDRESS"))
+             return FALSE;
+           
+           if (bus_connection_addresses[DBUS_BUS_SYSTEM] == NULL)
+             {
+               /* Use default system bus address if none set in environment */
+               bus_connection_addresses[DBUS_BUS_SYSTEM] =
+                 _dbus_strdup ("unix:path=" DBUS_SYSTEM_BUS_PATH);
+               if (bus_connection_addresses[DBUS_BUS_SYSTEM] == NULL)
+                 return FALSE;
+             }
+         }
+          
+      if (bus_connection_addresses[DBUS_BUS_SESSION] == NULL)
+        {
+          if (!get_from_env (&bus_connection_addresses[DBUS_BUS_SESSION],
+                             "DBUS_SESSION_BUS_ADDRESS"))
+            return FALSE;
+        }
+
+      if (bus_connection_addresses[DBUS_BUS_ACTIVATION] == NULL)
+        {
+          if (!get_from_env (&bus_connection_addresses[DBUS_BUS_ACTIVATION],
+                             "DBUS_ACTIVATION_ADDRESS"))
+            return FALSE;
+        }
+
+      s = _dbus_getenv ("DBUS_ACTIVATION_BUS_TYPE");
+
+      if (s != NULL)
+        {
+          if (strcmp (s, "system") == 0)
+            activation_bus_type = DBUS_BUS_SYSTEM;
+          else if (strcmp (s, "session") == 0)
+            activation_bus_type = DBUS_BUS_SESSION;
+        }
+
+      /* If we return FALSE we have to be sure that restarting
+       * the above code will work right
+       */
+      
+      if (!_dbus_setenv ("DBUS_ACTIVATION_ADDRESS", NULL))
+        return FALSE;
+
+      if (!_dbus_setenv ("DBUS_ACTIVATION_BUS_TYPE", NULL))
+        return FALSE;
+      
+      if (!_dbus_register_shutdown_func (addresses_shutdown_func,
+                                         NULL))
+        return FALSE;
+      
+      initialized = TRUE;
+    }
+
+  return initialized;
+}
 
 static dbus_bool_t
 data_slot_ref (void)
@@ -172,11 +294,6 @@ ensure_bus_data (DBusConnection *connection)
  * @{
  */
 
-/** Number of bus types */
-#define BUS_TYPES 2
-
-static DBusConnection *bus_connections[BUS_TYPES];
-
 /**
  * Connects to a bus daemon and registers the client with it.
  * If a connection to the bus already exists, then that connection is returned.
@@ -191,11 +308,14 @@ DBusConnection *
 dbus_bus_get (DBusBusType  type,
              DBusError   *error)
 {
-  const char *name, *value;
+  const char *address;
   DBusConnection *connection;
   BusData *bd;
+  DBusBusType address_type;
 
-  if (type <= 0 || type >= BUS_TYPES)
+  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
+  
+  if (type < 0 || type >= N_BUS_TYPES)
     {
       _dbus_assert_not_reached ("Invalid bus type specified.");
 
@@ -203,6 +323,26 @@ dbus_bus_get (DBusBusType  type,
     }
 
   _DBUS_LOCK (bus);
+
+  if (!init_connections_unlocked ())
+    {
+      _DBUS_UNLOCK (bus);
+      dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
+      return NULL;
+    }
+
+  /* We want to use the activation address even if the
+   * activating bus is the session or system bus,
+   * per the spec.
+   */
+  address_type = type;
+  
+  /* Use the real type of the activation bus for getting its
+   * connection. (If the activating bus isn't a well-known
+   * bus then activation_bus_type == DBUS_BUS_ACTIVATION)
+   */
+  if (type == DBUS_BUS_ACTIVATION)
+    type = activation_bus_type;
   
   if (bus_connections[type] != NULL)
     {
@@ -213,45 +353,27 @@ dbus_bus_get (DBusBusType  type,
       return connection;
     }
 
-  switch (type)
-    {
-    case DBUS_BUS_SESSION:
-      name = "DBUS_SESSION_BUS_ADDRESS";
-      break;
-    case DBUS_BUS_SYSTEM:
-      name = "DBUS_SYSTEM_BUS_ADDRESS";
-      break;
-    }
-
-  value = _dbus_getenv (name);
-
-  if (type == DBUS_BUS_SYSTEM &&
-      (value == NULL || *value == '\0'))
-    {
-      /* Use default system bus address if none set */
-      value = "unix:path=" DBUS_SYSTEM_BUS_PATH;
-    }
-  
-  if (value == NULL || *value == '\0')
+  address = bus_connection_addresses[address_type];
+  if (address == NULL)
     {
       dbus_set_error (error, DBUS_ERROR_FAILED,
-                     "Environment variable %s not set, address of message bus unknown",
-                      name);
+                      "Unable to determine the address of the message bus");
       _DBUS_UNLOCK (bus);
-      
       return NULL;
     }
 
-  connection = dbus_connection_open (value, error);
+  connection = dbus_connection_open (address, error);
   
   if (!connection)
     {
+      _DBUS_ASSERT_ERROR_IS_SET (error);
       _DBUS_UNLOCK (bus);
       return NULL;
     }
   
   if (!dbus_bus_register (connection, error))
     {
+      _DBUS_ASSERT_ERROR_IS_SET (error);
       dbus_connection_disconnect (connection);
       dbus_connection_unref (connection);
 
@@ -265,7 +387,7 @@ dbus_bus_get (DBusBusType  type,
 
   bd->connection = &bus_connections[type];
 
-  _DBUS_UNLOCK (bus);  
+  _DBUS_UNLOCK (bus);
   return connection;
 }
 
index 508dc5b..e3ec054 100644 (file)
@@ -33,8 +33,9 @@ DBUS_BEGIN_DECLS;
 
 typedef enum
 {
-  DBUS_BUS_SESSION, /**< The login session bus */
-  DBUS_BUS_SYSTEM /**< The system bus */
+  DBUS_BUS_SESSION,    /**< The login session bus */
+  DBUS_BUS_SYSTEM,     /**< The systemwide bus */
+  DBUS_BUS_ACTIVATION  /**< The bus that activated us, if any */
 } DBusBusType;
 
 DBusConnection *dbus_bus_get              (DBusBusType     type,
index 4798aa7..17da1fb 100644 (file)
@@ -82,37 +82,76 @@ _dbus_abort (void)
 }
 
 /**
- * Wrapper for setenv().
+ * Wrapper for setenv(). If the value is #NULL, unsets
+ * the environment variable.
+ *
+ * @todo if someone can verify it's safe, we could avoid the
+ * memleak when doing an unset.
  *
  * @param varname name of environment variable
  * @param value value of environment variable
  * @returns #TRUE on success.
  */
 dbus_bool_t
-_dbus_setenv (const char *varname, const char *value)
+_dbus_setenv (const char *varname,
+              const char *value)
 {
-#ifdef HAVE_SETENV
-  return (setenv (varname, value, TRUE) == 0);
+  _dbus_assert (varname != NULL);
+  
+  if (value == NULL)
+    {
+#ifdef HAVE_UNSETENV
+      unsetenv (varname);
+      return TRUE;
 #else
-  DBusString str;
-  char *putenv_value;
+      char *putenv_value;
+      size_t len;
 
-  if (!_dbus_string_init (&str))
-    return FALSE;
+      len = strlen (varname);
 
-  if (!_dbus_string_append (&str, varname) ||
-      !_dbus_string_append (&str, "=") ||
-      !_dbus_string_append (&str, value) ||
-      !_dbus_string_steal_data (&str, &putenv_value))
-    {
-      _dbus_string_free (&str);
-      return FALSE;
+      /* Use system malloc to avoid memleaks that dbus_malloc
+       * will get upset about.
+       */
+      
+      putenv_value = malloc (len + 1);
+      if (putenv_value == NULL)
+        return FALSE;
+
+      strcpy (putenv_value, varname);
+      
+      return (putenv (putenv_value) == 0);
+#endif
     }
+  else
+    {
+#ifdef HAVE_SETENV
+      return (setenv (varname, value, TRUE) == 0);
+#else
+      char *putenv_value;
+      size_t len;
+      size_t varname_len;
+      size_t value_len;
+
+      varname_len = strlen (varname);
+      value_len = strlen (value);
+      
+      len = varname_len + value_len + 1 /* '=' */ ;
 
-  _dbus_string_free (&str);
+      /* Use system malloc to avoid memleaks that dbus_malloc
+       * will get upset about.
+       */
+      
+      putenv_value = malloc (len + 1);
+      if (putenv_value == NULL)
+        return FALSE;
 
-  return (putenv (putenv_value) == 0);
+      strcpy (putenv_value, varname);
+      strcpy (putenv_value + varname_len, "=");
+      strcpy (putenv_value + varname_len + 1, value);
+      
+      return (putenv (putenv_value) == 0);
 #endif
+    }
 }
 
 /**
index b8230aa..8c2152b 100644 (file)
@@ -27,6 +27,15 @@ Elements:
  
     Root element.
 
+ <type>
+
+    The well-known type of the message bus. Currently known values
+    are "system" and "session"; if other values are set, they should 
+    be either added to the D-BUS specification, or namespaced.
+    The last <type> element "wins"
+
+    Example: <type>session</type>
+
  <include>
   ignore_missing="(yes|no)"   optional attribute, defaults to no
    
index 5d150e8..7e2fcb3 100644 (file)
       </para>
       <para>
         The executable launched will have the environment variable
-        <literal>DBUS_BUS_ADDRESS</literal> set to the address of the
+        <literal>DBUS_ACTIVATION_ADDRESS</literal> set to the address of the
         message bus so it can connect and register the appropriate services.
       </para>
       <para>
+        The executable being launched may want to know whether the message bus
+        activating it is one of the well-known message buses (see <xref
+        linkend="message-bus-types">). To facilitate this, the bus MUST also set
+        the <literal>DBUS_ACTIVATION_BUS_TYPE</literal> environment variable if it is one
+        of the well-known buses. The currently-defined values for this variable
+        are <literal>system</literal> for the systemwide message bus,
+        and <literal>session</literal> for the per-login-session message
+        bus. The activated executable must still connect to the address given
+        in <literal>DBUS_ACTIVATION_ADDRESS</literal>, but may assume that the
+        resulting connection is to the well-known bus.
+      </para>
+      <para>
         [FIXME there should be a timeout somewhere, either specified
         in the .service file, by the client, or just a global value
         and if the client being activated fails to connect within that
     </sect2>
 
     <sect2 id="message-bus-types">
-      <title>Standard Message Bus Instances</title>
+      <title>Well-known Message Bus Instances</title>
       <para>
         Two standard message bus instances are defined here, along with how 
         to locate them and where their service files live.
         <para>
           Each time a user logs in, a <firstterm>login session message
             bus</firstterm> may be started. All applications in the user's login
-          session may interact with one another using this message bus.  [specify
-          how to find the address of the login session message bus via
-          environment variable and/or X property]
+          session may interact with one another using this message bus.
+        </para>
+        <para>
+          The address of the login session message bus is given 
+          in the <literal>DBUS_SESSION_BUS_ADDRESS</literal> environment 
+          variable. If that variable is not set, applications may 
+          also try to read the address from the X Window System root 
+          window property <literal>_DBUS_SESSION_BUS_ADDRESS</literal>.
+          The root window property must have type <literal>STRING</literal>.
+          The environment variable should have precedence over the 
+          root window property.
         </para>
         <para>
           [FIXME specify location of .service files, probably using 
         <para>
           A computer may have a <firstterm>system message bus</firstterm>,
           accessible to all applications on the system. This message bus may be
-          used to broadcast system events, such as adding new hardware devices.
-          [specify how to find the address of the system message bus]
+          used to broadcast system events, such as adding new hardware devices, 
+          changes in the printer queue, and so forth.
+        </para>
+        <para>
+          The address of the login session message bus is given 
+          in the <literal>DBUS_SYSTEM_BUS_ADDRESS</literal> environment 
+          variable. If that variable is not set, applications should try 
+          to connect to the well-known address
+          <literal>unix:path=/var/run/dbus/system_bus_socket</literal>.
+          <footnote>
+            <para>
+              The D-BUS reference implementation actually honors the 
+              <literal>$(localstatedir)</literal> configure option 
+              for this address, on both client and server side.
+            </para>
+          </footnote>
         </para>
         <para>
           [FIXME specify location of system bus .service files]
index 3ca62d6..46a66db 100644 (file)
@@ -2,7 +2,7 @@
 INCLUDES=-I$(top_srcdir) $(DBUS_TEST_CFLAGS) 
 
 if DBUS_BUILD_TESTS
-TEST_BINARIES=echo-client echo-server unbase64 break-loader spawn-test
+TEST_BINARIES=test-service echo-client echo-server unbase64 break-loader spawn-test
 else
 TEST_BINARIES=
 endif
@@ -19,6 +19,11 @@ echo_server_SOURCES=                         \
        watch.c                                 \
        watch.h
 
+test_service_SOURCES=                          \
+       test-service.c                          \
+       watch.c                                 \
+       watch.h
+
 unbase64_SOURCES=                              \
        unbase64.c
 
@@ -39,6 +44,7 @@ TEST_LIBS=$(DBUS_TEST_LIBS) $(top_builddir)/dbus/libdbus-convenience.la
 
 echo_client_LDADD=$(TEST_LIBS)
 echo_server_LDADD=$(TEST_LIBS)
+test_service_LDADD=$(TEST_LIBS)
 unbase64_LDADD=$(TEST_LIBS)
 break_loader_LDADD= $(TEST_LIBS)
 #bus_test_LDADD=$(TEST_LIBS) $(top_builddir)/bus/libdbus-daemon.la
diff --git a/test/test-service.c b/test/test-service.c
new file mode 100644 (file)
index 0000000..a4dff0b
--- /dev/null
@@ -0,0 +1,30 @@
+#include <dbus/dbus.h>
+#include <stdio.h>
+#include "watch.h"
+
+int
+main (int    argc,
+      char **argv)
+{
+  DBusConnection *connection;
+  DBusError error;
+  DBusMessage *message;
+
+  dbus_error_init (&error);
+  connection = dbus_bus_get (DBUS_BUS_ACTIVATION, &error);
+  if (connection == NULL)
+    {
+      fprintf (stderr, "Failed to open connection to activating message bus: %s\n",
+               error.message);
+      dbus_error_free (&error);
+      return 1;
+    }
+
+  setup_connection (connection);
+  
+  do_mainloop ();
+
+  dbus_connection_unref (connection);
+  
+  return 0;
+}