diff options
author | Thiago Macieira <thiago@kde.org> | 2006-09-30 19:38:34 +0000 |
---|---|---|
committer | Thiago Macieira <thiago@kde.org> | 2006-09-30 19:38:34 +0000 |
commit | f6fa010403cb2badd88ce096ae91f664418508d1 (patch) | |
tree | 67227726b518356870813b33bc346bda9be32e18 /dbus | |
parent | 5f292c611fc60bf3115dcf3d1213fdedc36fc65c (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.c | 7 | ||||
-rw-r--r-- | dbus/dbus-connection.c | 2 | ||||
-rw-r--r-- | dbus/dbus-internals.h | 2 | ||||
-rw-r--r-- | dbus/dbus-sysdeps-unix.c | 113 | ||||
-rw-r--r-- | dbus/dbus-sysdeps.h | 3 | ||||
-rw-r--r-- | dbus/dbus-transport.c | 107 |
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 |