summaryrefslogtreecommitdiffstats
path: root/dbus
diff options
context:
space:
mode:
authorThiago Macieira <thiago@kde.org>2006-09-30 19:38:34 +0000
committerThiago Macieira <thiago@kde.org>2006-09-30 19:38:34 +0000
commitf6fa010403cb2badd88ce096ae91f664418508d1 (patch)
tree67227726b518356870813b33bc346bda9be32e18 /dbus
parent5f292c611fc60bf3115dcf3d1213fdedc36fc65c (diff)
* configure.in: add DBUS_BINDIR as a #define to C source code.
* tools/dbus-launch.c * tools/dbus-launch.h * tools/dbus-launch-x11.c: * tools/dbus-launch.1: Add the --autolaunch option to dbus-launch, which makes it scan for an existing session started with --autolaunch. With that option, it also creates an X11 window and saves the bus address and PID to it. * dbus/dbus-sysdeps.h: * dbus/dbus-sysdeps-unix.c (_dbus_get_autolaunch_address): Add a function that runs "dbus-launch --autolaunch" to retrieve the running D-Bus session address (or start one if none was running) * dbus/dbus-transport.c: Add the handler for the "autolaunch:" address protocol, which tries to get the running session from dbus-launch. * dbus/dbus-bus.c: * dbus/dbus-internals.h: Make "autolaunch:" be the default D-Bus session bus address. * dbus/dbus-connection.c: Fix horrible typo in error message.
Diffstat (limited to 'dbus')
-rw-r--r--dbus/dbus-bus.c7
-rw-r--r--dbus/dbus-connection.c2
-rw-r--r--dbus/dbus-internals.h2
-rw-r--r--dbus/dbus-sysdeps-unix.c113
-rw-r--r--dbus/dbus-sysdeps.h3
-rw-r--r--dbus/dbus-transport.c107
6 files changed, 232 insertions, 2 deletions
diff --git a/dbus/dbus-bus.c b/dbus/dbus-bus.c
index 5f5c3395..eb6b3ab3 100644
--- a/dbus/dbus-bus.c
+++ b/dbus/dbus-bus.c
@@ -175,6 +175,13 @@ init_connections_unlocked (void)
if (!get_from_env (&bus_connection_addresses[DBUS_BUS_SESSION],
"DBUS_SESSION_BUS_ADDRESS"))
return FALSE;
+
+ if (bus_connection_addresses[DBUS_BUS_SESSION] == NULL)
+ bus_connection_addresses[DBUS_BUS_SESSION] =
+ _dbus_strdup (DBUS_SESSION_BUS_DEFAULT_ADDRESS);
+ if (bus_connection_addresses[DBUS_BUS_SESSION] == NULL)
+ return FALSE;
+
_dbus_verbose (" \"%s\"\n", bus_connection_addresses[DBUS_BUS_SESSION] ?
bus_connection_addresses[DBUS_BUS_SESSION] : "none set");
}
diff --git a/dbus/dbus-connection.c b/dbus/dbus-connection.c
index 2b4dd8d8..d60816c3 100644
--- a/dbus/dbus-connection.c
+++ b/dbus/dbus-connection.c
@@ -2783,7 +2783,7 @@ _dbus_connection_block_pending_call (DBusPendingCall *pending)
error_msg = generate_local_error_message (client_serial,
DBUS_ERROR_DISCONNECTED,
- "Connection was dissconnected before a reply was recived");
+ "Connection was disconnected before a reply was received");
/* on OOM error_msg is set to NULL */
complete_pending_call_and_unlock (connection, pending, error_msg);
diff --git a/dbus/dbus-internals.h b/dbus/dbus-internals.h
index a12821db..520d6dfe 100644
--- a/dbus/dbus-internals.h
+++ b/dbus/dbus-internals.h
@@ -37,6 +37,8 @@
DBUS_BEGIN_DECLS
+#define DBUS_SESSION_BUS_DEFAULT_ADDRESS "autolaunch:"
+
void _dbus_warn (const char *format,
...) _DBUS_GNUC_PRINTF (1, 2);
diff --git a/dbus/dbus-sysdeps-unix.c b/dbus/dbus-sysdeps-unix.c
index 38adebb1..c0540175 100644
--- a/dbus/dbus-sysdeps-unix.c
+++ b/dbus/dbus-sysdeps-unix.c
@@ -27,6 +27,7 @@
#include "dbus-sysdeps-unix.h"
#include "dbus-threads.h"
#include "dbus-protocol.h"
+#include "dbus-transport.h"
#include "dbus-string.h"
#include <sys/types.h>
#include <stdlib.h>
@@ -2275,6 +2276,118 @@ _dbus_get_tmpdir(void)
return tmpdir;
}
+/**
+ * Determines the address of the session bus by querying a
+ * platform-specific method.
+ *
+ * If successful, returns #TRUE and appends the address to @p
+ * address. If a failure happens, returns #FALSE and
+ * sets an error in @p error.
+ *
+ * @param address a DBusString where the address can be stored
+ * @param error a DBusError to store the error in case of failure
+ * @returns #TRUE on success, #FALSE if an error happened
+ */
+dbus_bool_t
+_dbus_get_autolaunch_address (DBusString *address, DBusError *error)
+{
+ static char *argv[] = { DBUS_BINDIR "/dbus-launch", "--autolaunch",
+ "--binary-syntax", NULL };
+ int address_pipe[2];
+ pid_t pid;
+ int ret;
+ int status;
+ int orig_len = _dbus_string_get_length (address);
+
+ _DBUS_ASSERT_ERROR_IS_CLEAR (error);
+
+#define READ_END 0
+#define WRITE_END 1
+ if (pipe (address_pipe) < 0)
+ {
+ dbus_set_error (error, _dbus_error_from_errno (errno),
+ "Failed to create a pipe: %s",
+ _dbus_strerror (errno));
+ _dbus_verbose ("Failed to create a pipe to call dbus-launch: %s\n",
+ _dbus_strerror (errno));
+ return FALSE;
+ }
+
+ pid = fork ();
+ if (pid < 0)
+ {
+ dbus_set_error (error, _dbus_error_from_errno (errno),
+ "Failed to fork(): %s",
+ _dbus_strerror (errno));
+ _dbus_verbose ("Failed to fork() to call dbus-launch: %s\n",
+ _dbus_strerror (errno));
+ return FALSE;
+ }
+
+ if (pid == 0)
+ {
+ /* child process */
+ int fd = open ("/dev/null", O_RDWR);
+ if (fd == -1)
+ /* huh?! can't open /dev/null? */
+ _exit (1);
+
+ /* set-up stdXXX */
+ close (address_pipe[READ_END]);
+ close (0); /* close stdin */
+ close (1); /* close stdout */
+ close (2); /* close stderr */
+
+ if (dup2 (fd, 0) == -1)
+ _exit (1);
+ if (dup2 (address_pipe[WRITE_END], 1) == -1)
+ _exit (1);
+ if (dup2 (fd, 2) == -1)
+ _exit (1);
+
+ close (fd);
+ close (address_pipe[WRITE_END]);
+
+ execv (argv[0], argv);
+
+ /* failed, try searching PATH */
+ argv[0] = "dbus-launch";
+ execvp ("dbus-launch", argv);
+
+ /* still nothing, we failed */
+ _exit (1);
+ }
+
+ /* parent process */
+ close (address_pipe[WRITE_END]);
+ ret = 0;
+ do
+ {
+ ret = _dbus_read (address_pipe[READ_END], address, 1024);
+ }
+ while (ret > 0);
+
+ /* reap the child process to avoid it lingering as zombie */
+ do
+ {
+ ret = waitpid (pid, &status, 0);
+ }
+ while (ret == -1 && errno == EINTR);
+
+ /* We succeeded if the process exited with status 0 and
+ anything was read */
+ if (!WIFEXITED (status) || WEXITSTATUS (status) != 0 ||
+ _dbus_string_get_length (address) == orig_len)
+ {
+ /* The process ended with error */
+ _dbus_string_set_length (address, orig_len);
+ dbus_set_error (error, DBUS_ERROR_SPAWN_EXEC_FAILED,
+ "Failed to execute dbus-launch to autolaunch D-Bus session");
+ return FALSE;
+ }
+ return TRUE;
+}
+
/** @} end of sysdeps */
/* tests in dbus-sysdeps-util.c */
diff --git a/dbus/dbus-sysdeps.h b/dbus/dbus-sysdeps.h
index c1ed533a..3541a721 100644
--- a/dbus/dbus-sysdeps.h
+++ b/dbus/dbus-sysdeps.h
@@ -376,6 +376,9 @@ dbus_bool_t _dbus_user_at_console (const char *username,
dbus_bool_t _dbus_parse_uid (const DBusString *uid_str,
dbus_uid_t *uid);
+dbus_bool_t _dbus_get_autolaunch_address (DBusString *address,
+ DBusError *error);
+
DBUS_END_DECLS
#endif /* DBUS_SYSDEPS_H */
diff --git a/dbus/dbus-transport.c b/dbus/dbus-transport.c
index 89d79ffe..f43dd3d2 100644
--- a/dbus/dbus-transport.c
+++ b/dbus/dbus-transport.c
@@ -201,13 +201,118 @@ _dbus_transport_finalize_base (DBusTransport *transport)
dbus_free (transport->expected_guid);
}
+
+/**
+ * Verifies if a given D-Bus address is a valid address
+ * by attempting to connect to it. If it is, returns the
+ * opened DBusTransport object. If it isn't, returns #NULL
+ * and sets @p error.
+ *
+ * @param error address where an error can be returned.
+ * @returns a new transport, or #NULL on failure.
+ */
+static DBusTransport*
+check_address (const char *address, DBusError *error)
+{
+ DBusAddressEntry **entries;
+ DBusTransport *transport = NULL;
+ int len, i;
+
+ _dbus_assert (address != NULL);
+ _dbus_assert (*address != '\0');
+
+ if (!dbus_parse_address (address, &entries, &len, error))
+ return FALSE; /* not a valid address */
+
+ for (i = 0; i < len; i++)
+ {
+ transport = _dbus_transport_open (entries[i], error);
+ if (transport != NULL)
+ break;
+ }
+
+ dbus_address_entries_free (entries);
+ return transport;
+}
+
+/**
+ * Creates a new transport for the "autostart" method.
+ * This creates a client-side of a transport.
+ *
+ * @param error address where an error can be returned.
+ * @returns a new transport, or #NULL on failure.
+ */
+static DBusTransport*
+_dbus_transport_new_for_autolaunch (DBusError *error)
+{
+ DBusString address;
+ DBusTransport *result = NULL;
+
+ _DBUS_ASSERT_ERROR_IS_CLEAR (error);
+
+ if (!_dbus_string_init (&address))
+ {
+ dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
+ return NULL;
+ }
+
+ if (!_dbus_get_autolaunch_address (&address, error))
+ {
+ _DBUS_ASSERT_ERROR_IS_SET (error);
+ goto out;
+ }
+
+ result = check_address (_dbus_string_get_const_data (&address), error);
+ if (result == NULL)
+ _DBUS_ASSERT_ERROR_IS_SET (error);
+ else
+ _DBUS_ASSERT_ERROR_IS_CLEAR (error);
+
+ out:
+ _dbus_string_free (&address);
+ return result;
+}
+
+static DBusTransportOpenResult
+_dbus_transport_open_autolaunch (DBusAddressEntry *entry,
+ DBusTransport **transport_p,
+ DBusError *error)
+{
+ const char *method;
+
+ method = dbus_address_entry_get_method (entry);
+ _dbus_assert (method != NULL);
+
+ if (strcmp (method, "autolaunch") == 0)
+ {
+ *transport_p = _dbus_transport_new_for_autolaunch (error);
+
+ if (*transport_p == NULL)
+ {
+ _DBUS_ASSERT_ERROR_IS_SET (error);
+ return DBUS_TRANSPORT_OPEN_DID_NOT_CONNECT;
+ }
+ else
+ {
+ _DBUS_ASSERT_ERROR_IS_CLEAR (error);
+ return DBUS_TRANSPORT_OPEN_OK;
+ }
+ }
+ else
+ {
+ _DBUS_ASSERT_ERROR_IS_CLEAR (error);
+ return DBUS_TRANSPORT_OPEN_NOT_HANDLED;
+ }
+}
+
static const struct {
DBusTransportOpenResult (* func) (DBusAddressEntry *entry,
DBusTransport **transport_p,
DBusError *error);
} open_funcs[] = {
{ _dbus_transport_open_socket },
- { _dbus_transport_open_platform_specific }
+ { _dbus_transport_open_platform_specific },
+ { _dbus_transport_open_autolaunch }
#ifdef DBUS_BUILD_TESTS
, { _dbus_transport_open_debug_pipe }
#endif