summaryrefslogtreecommitdiffstats
path: root/dbus
diff options
context:
space:
mode:
authorHavoc Pennington <hp@redhat.com>2003-04-03 05:22:49 +0000
committerHavoc Pennington <hp@redhat.com>2003-04-03 05:22:49 +0000
commiteeb88949d8d2ca84d9cbe54c07e73b9907d3163e (patch)
tree9520b0d32fd0c105f41619f8d247a298f93caf9c /dbus
parent5364beac6cbfa8793fd34c7a634528a2112787f8 (diff)
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
Diffstat (limited to 'dbus')
-rw-r--r--dbus/dbus-bus.c188
-rw-r--r--dbus/dbus-bus.h5
-rw-r--r--dbus/dbus-sysdeps.c73
3 files changed, 214 insertions, 52 deletions
diff --git a/dbus/dbus-bus.c b/dbus/dbus-bus.c
index d65a3f0f..dc1762eb 100644
--- a/dbus/dbus-bus.c
+++ b/dbus/dbus-bus.c
@@ -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;
}
diff --git a/dbus/dbus-bus.h b/dbus/dbus-bus.h
index 508dc5b1..e3ec054c 100644
--- a/dbus/dbus-bus.h
+++ b/dbus/dbus-bus.h
@@ -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,
diff --git a/dbus/dbus-sysdeps.c b/dbus/dbus-sysdeps.c
index 4798aa73..17da1fbe 100644
--- a/dbus/dbus-sysdeps.c
+++ b/dbus/dbus-sysdeps.c
@@ -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
+ }
}
/**