diff --git a/.gitignore b/.gitignore
index 2936342..ea37ec6 100644
--- a/.gitignore
+++ b/.gitignore
@@ -31,3 +31,4 @@ config.h.in
*.da
*.gcov
tags
+org.freedesktop.dbus-session.plist
diff --git a/autogen.sh b/autogen.sh
index 7656133..9d77f89 100755
--- a/autogen.sh
+++ b/autogen.sh
@@ -29,6 +29,13 @@ ACLOCAL=aclocal-1.9
ACLOCAL=aclocal
}
+LIBTOOLIZE=libtoolize
+
+($LIBTOOLIZE --version) < /dev/null > /dev/null 2>&1 || {
+ # at least macports installs it as glibtoolize
+ LIBTOOLIZE=glibtoolize
+}
+
($AUTOMAKE --version) < /dev/null > /dev/null 2>&1 || {
echo
echo "You must have automake installed to compile $PROJECT."
@@ -37,7 +44,7 @@ ACLOCAL=aclocal-1.9
DIE=1
}
-(libtoolize --version) < /dev/null > /dev/null 2>&1 || {
+($LIBTOOLIZE --version) < /dev/null > /dev/null 2>&1 || {
echo
echo "You must have libtoolize installed to compile $PROJECT."
echo "Install the libtool package from ftp.gnu.org or a mirror."
@@ -58,7 +65,7 @@ if test -z "$*"; then
echo "to pass any to it, please specify them on the $0 command line."
fi
-libtoolize --copy --force
+$LIBTOOLIZE --copy --force
echo $ACLOCAL $ACLOCAL_FLAGS
$ACLOCAL $ACLOCAL_FLAGS
diff --git a/bus/Makefile.am b/bus/Makefile.am
index 3b4f69d..420742b 100644
--- a/bus/Makefile.am
+++ b/bus/Makefile.am
@@ -9,12 +9,18 @@ EFENCE=
CONFIG_IN_FILES= \
session.conf.in \
- system.conf.in
+ system.conf.in \
+ org.freedesktop.dbus-session.plist.in
config_DATA= \
session.conf \
system.conf
+if DBUS_ENABLE_LAUNCHD
+agentdir=$(LAUNCHD_AGENT_DIR)
+agent_DATA=org.freedesktop.dbus-session.plist
+endif
+
if DBUS_USE_LIBXML
XML_SOURCES=config-loader-libxml.c
endif
diff --git a/bus/org.freedesktop.dbus-session.plist.in b/bus/org.freedesktop.dbus-session.plist.in
new file mode 100644
index 0000000..6f1ad8e
--- /dev/null
+++ b/bus/org.freedesktop.dbus-session.plist.in
@@ -0,0 +1,31 @@
+
+
+
+
+ Label
+ org.freedesktop.dbus-session
+
+ ServiceIPC
+
+
+
+ OnDemand
+
+
+ ProgramArguments
+
+ @DBUS_DAEMONDIR@/dbus-daemon
+ --nofork
+ --session
+
+
+ Sockets
+
+ session
+
+ SecureSocketWithKey
+ DBUS_LAUNCHD_SESSION_BUS_SOCKET
+
+
+
+
diff --git a/bus/session.conf.in b/bus/session.conf.in
index 794eb8d..658e535 100644
--- a/bus/session.conf.in
+++ b/bus/session.conf.in
@@ -12,7 +12,7 @@
the behavior of child processes. -->
- unix:tmpdir=@DBUS_SESSION_SOCKET_DIR@
+ @DBUS_SESSION_BUS_DEFAULT_ADDRESS@
diff --git a/configure.in b/configure.in
index 511633e..33365f0 100644
--- a/configure.in
+++ b/configure.in
@@ -78,6 +78,7 @@ AC_ARG_ENABLE(inotify, AS_HELP_STRING([--enable-inotify],[build with inotify sup
AC_ARG_ENABLE(kqueue, AS_HELP_STRING([--enable-kqueue],[build with kqueue support]),enable_kqueue=$enableval,enable_kqueue=auto)
AC_ARG_ENABLE(console-owner-file, AS_HELP_STRING([--enable-console-owner-file],[enable console owner file]),enable_console_owner_file=$enableval,enable_console_owner_file=auto)
AC_ARG_ENABLE(userdb-cache, AS_HELP_STRING([--enable-userdb-cache],[build with userdb-cache support]),enable_userdb_cache=$enableval,enable_userdb_cache=yes)
+AC_ARG_ENABLE(launchd, AS_HELP_STRING([--enable-launchd],[build with launchd auto-launch support]),enable_launchd=$enableval,enable_launchd=auto)
AC_ARG_WITH(xml, AS_HELP_STRING([--with-xml=[libxml/expat]],[XML library to use]))
AC_ARG_WITH(init-scripts, AS_HELP_STRING([--with-init-scripts=[redhat]],[Style of init scripts to install]))
@@ -87,6 +88,7 @@ AC_ARG_WITH(system-pid-file, AS_HELP_STRING([--with-system-pid-file=[pidfile]],[
AC_ARG_WITH(system-socket, AS_HELP_STRING([--with-system-socket=[filename]],[UNIX domain socket for systemwide daemon]))
AC_ARG_WITH(console-auth-dir, AS_HELP_STRING([--with-console-auth-dir=[dirname]],[directory to check for console ownerhip]))
AC_ARG_WITH(console-owner-file, AS_HELP_STRING([--with-console-owner-file=[filename]],[file whose owner determines current console owner]))
+AC_ARG_WITH(launchd-agent-dir, AS_HELP_STRING([--with-launchd-agent-dir=[dirname]],[directory to put the launchd agent (default: /Library/LaunchAgents)]))
AC_ARG_WITH(dbus_user, AS_HELP_STRING([--with-dbus-user=],[User for running the DBUS daemon (messagebus)]))
AC_ARG_WITH(dbus_daemondir, AS_HELP_STRING([--with-dbus-daemondir=[dirname]],[Directory for installing the DBUS daemon]))
@@ -1026,6 +1028,46 @@ fi
AM_CONDITIONAL(DBUS_BUS_ENABLE_KQUEUE, test x$have_kqueue = xyes)
+# launchd checks
+if test x$enable_launchd = xno ; then
+ have_launchd=no
+else
+ have_launchd=yes
+ AC_CHECK_HEADER([launch.h], , have_launchd=no)
+ AC_PATH_PROG([LAUNCHCTL], [launchctl])
+ if test "x$LAUNCHCTL" = "x"; then
+ have_launchd=no
+ fi
+
+ if test x$enable_launchd = xyes -a x$have_launchd = xno ; then
+ AC_MSG_ERROR([launchd support explicitly enabled but not available])
+ fi
+fi
+
+dnl check if launchd is enabled
+if test x$have_launchd = xyes; then
+ AC_DEFINE(DBUS_ENABLE_LAUNCHD,1,[Use launchd autolaunch])
+fi
+
+AM_CONDITIONAL(DBUS_ENABLE_LAUNCHD, test x$have_launchd = xyes)
+
+if test x$have_launchd = xyes; then
+ DBUS_SESSION_BUS_DEFAULT_ADDRESS="launchd:key=session"
+else
+ DBUS_SESSION_BUS_DEFAULT_ADDRESS="unix:tmpdir=$DBUS_SESSION_SOCKET_DIR"
+fi
+AC_SUBST(DBUS_SESSION_BUS_DEFAULT_ADDRESS)
+
+
+#### Directory to place launchd agent file
+if test "x$with_launchd_agent_dir" = "x"; then
+ LAUNCHD_AGENT_DIR="/Library/LaunchAgents"
+else
+ LAUNCHD_AGENT_DIR="$with_launchd_agent_dir"
+fi
+
+AC_SUBST(LAUNCHD_AGENT_DIR)
+
dnl console owner file
if test x$enable_console_owner_file = xno ; then
have_console_owner_file=no;
@@ -1387,6 +1429,7 @@ dbus/dbus-arch-deps.h
bus/system.conf
bus/session.conf
bus/messagebus
+bus/org.freedesktop.dbus-session.plist
bus/rc.messagebus
bus/dbus-daemon.1
Makefile
@@ -1454,6 +1497,7 @@ echo "
Building Doxygen docs: ${enable_doxygen_docs}
Building XML docs: ${enable_xml_docs}
Building cache support: ${enable_userdb_cache}
+ Building launchd support: ${have_launchd}
Gettext libs (empty OK): ${INTLLIBS}
Using XML parser: ${with_xml}
Init scripts style: ${with_init_scripts}
@@ -1468,6 +1512,7 @@ echo "
System bus user: ${DBUS_USER}
Session bus services dir: ${EXPANDED_DATADIR}/dbus-1/services
'make check' socket dir: ${TEST_SOCKET_DIR}
+ launchd agent dir: ${LAUNCHD_AGENT_DIR}
"
if test x$enable_tests = xyes; then
diff --git a/dbus/Makefile.am b/dbus/Makefile.am
index e966a43..3a9c3ad 100644
--- a/dbus/Makefile.am
+++ b/dbus/Makefile.am
@@ -9,6 +9,12 @@ INCLUDES=-I$(top_builddir) -I$(top_srcdir) $(DBUS_CLIENT_CFLAGS) @PIC_CFLAGS@ -D
dbusincludedir=$(includedir)/dbus-1.0/dbus
dbusarchincludedir=$(libdir)/dbus-1.0/include/dbus
+if DBUS_ENABLE_LAUNCHD
+LAUNCHD_SOURCES = \
+ dbus-server-launchd.h \
+ dbus-server-launchd.c
+endif
+
lib_LTLIBRARIES=libdbus-1.la
dbusinclude_HEADERS= \
@@ -92,7 +98,8 @@ DBUS_LIB_SOURCES= \
dbus-uuidgen.c \
dbus-uuidgen.h \
dbus-watch.c \
- dbus-watch.h
+ dbus-watch.h \
+ $(LAUNCHD_SOURCES)
## dbus-md5.c \
## dbus-md5.h \
diff --git a/dbus/dbus-bus.c b/dbus/dbus-bus.c
index f97cce6..abbedb7 100644
--- a/dbus/dbus-bus.c
+++ b/dbus/dbus-bus.c
@@ -22,6 +22,7 @@
*
*/
+#include
#include "dbus-bus.h"
#include "dbus-protocol.h"
#include "dbus-internals.h"
@@ -29,6 +30,7 @@
#include "dbus-marshal-validate.h"
#include "dbus-threads-internal.h"
#include "dbus-connection-internal.h"
+#include "dbus-string.h"
#include
/**
@@ -147,6 +149,63 @@ get_from_env (char **connection_p,
}
static dbus_bool_t
+init_session_address (void)
+{
+ dbus_bool_t retval;
+
+ retval = FALSE;
+
+ /* First, look in the environment. This is the normal case on
+ * freedesktop.org/Unix systems. */
+ get_from_env (&bus_connection_addresses[DBUS_BUS_SESSION],
+ "DBUS_SESSION_BUS_ADDRESS");
+ if (bus_connection_addresses[DBUS_BUS_SESSION] == NULL)
+ {
+ dbus_bool_t supported;
+ DBusString addr;
+ DBusError error = DBUS_ERROR_INIT;
+
+ if (!_dbus_string_init (&addr))
+ return FALSE;
+
+ supported = FALSE;
+ /* So it's not in the environment - let's try a platform-specific method.
+ * On MacOS, this involves asking launchd. On Windows (not specified yet)
+ * we might do a COM lookup.
+ * Ignore errors - if we failed, fall back to autolaunch. */
+ retval = _dbus_lookup_session_address (&supported, &addr, &error);
+ if (supported && retval)
+ {
+ retval =_dbus_string_steal_data (&addr, &bus_connection_addresses[DBUS_BUS_SESSION]);
+ }
+ else if (supported && !retval)
+ {
+ if (dbus_error_is_set(&error))
+ _dbus_warn ("Dynamic session lookup supported but failed: %s\n", error.message);
+ else
+ _dbus_warn ("Dynamic session lookup supported but failed silently\n");
+ }
+ _dbus_string_free (&addr);
+ }
+ else
+ retval = TRUE;
+
+ if (!retval)
+ return FALSE;
+
+ /* The DBUS_SESSION_BUS_DEFAULT_ADDRESS should have really been named
+ * DBUS_SESSION_BUS_FALLBACK_ADDRESS.
+ */
+ 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;
+
+ return TRUE;
+}
+
+static dbus_bool_t
init_connections_unlocked (void)
{
if (!initialized)
@@ -198,17 +257,9 @@ init_connections_unlocked (void)
{
_dbus_verbose ("Filling in session bus address...\n");
- if (!get_from_env (&bus_connection_addresses[DBUS_BUS_SESSION],
- "DBUS_SESSION_BUS_ADDRESS"))
+ if (!init_session_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-server-launchd.c b/dbus/dbus-server-launchd.c
new file mode 100644
index 0000000..726cc91
--- /dev/null
+++ b/dbus/dbus-server-launchd.c
@@ -0,0 +1,150 @@
+/* dbus-server-launchd.c Server methods for interacting with launchd.
+ * Copyright (C) 2007, Tanner Lovelace
+ * Copyright (C) 2008, Benjamin Reed
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#include
+#include
+#include
+
+#include "dbus-server-socket.h"
+#include "dbus-server-launchd.h"
+
+/**
+ * @defgroup DBusServerLaunchd DBusServer implementations for Launchd
+ * @ingroup DBusInternals
+ * @brief Implementation details of DBusServer with Launchd support
+ *
+ * @{
+ */
+
+/**
+ * Creates a new server from launchd.
+ *
+ * @param socket_key they key to use when looking up the file descriptor from launchd
+ * @param error location to store reason for failure.
+ * @returns the new server, or #NULL on failure.
+ */
+
+DBusServer*
+_dbus_server_new_for_launchd_fd (const char *socket_key,
+ DBusError *error)
+{
+ DBusServer *server;
+ DBusString address;
+ int launchd_fd;
+ launch_data_t sockets_dict, checkin_response;
+ launch_data_t checkin_request;
+ launch_data_t listening_fd_array, listening_fd;
+
+ _DBUS_ASSERT_ERROR_IS_CLEAR (error);
+
+ if (!_dbus_string_init (&address))
+ {
+ dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
+ return NULL;
+ }
+ if (!_dbus_string_append (&address, "launchd:key="))
+ {
+ dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
+ goto l_failed_0;
+ }
+ if (!_dbus_string_append (&address, socket_key))
+ {
+ dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
+ goto l_failed_0;
+ }
+
+ if ((checkin_request = launch_data_new_string (LAUNCH_KEY_CHECKIN)) == NULL)
+ {
+ dbus_set_error (error, DBUS_ERROR_NO_MEMORY,
+ "launch_data_new_string(\"%s\") Unable to create string.\n", LAUNCH_KEY_CHECKIN);
+ goto l_failed_0;
+ }
+
+ if ((checkin_response = launch_msg (checkin_request)) == NULL)
+ {
+ dbus_set_error (error, DBUS_ERROR_IO_ERROR, "launch_msg(\"%s\") IPC failure: %s\n",
+ LAUNCH_KEY_CHECKIN, strerror (errno));
+ goto l_failed_0;
+ }
+
+ if (LAUNCH_DATA_ERRNO == launch_data_get_type (checkin_response))
+ {
+ dbus_set_error (error, DBUS_ERROR_FAILED, "Check-in failed: %s\n",
+ strerror (launch_data_get_errno (checkin_response)));
+ goto l_failed_0;
+ }
+
+ sockets_dict = launch_data_dict_lookup (checkin_response, LAUNCH_JOBKEY_SOCKETS);
+ if (NULL == sockets_dict)
+ {
+ dbus_set_error (error, DBUS_ERROR_IO_ERROR, "No sockets found to answer requests on!\n");
+ goto l_failed_0;
+ }
+
+ listening_fd_array = launch_data_dict_lookup (sockets_dict, socket_key);
+ if (NULL == listening_fd_array)
+ {
+ dbus_set_error (error, DBUS_ERROR_IO_ERROR, "No known sockets found to answer requests on!\n");
+ goto l_failed_0;
+ }
+
+ if (launch_data_array_get_count (listening_fd_array) != 1)
+ {
+ dbus_set_error (error, DBUS_ERROR_LIMITS_EXCEEDED,
+ "Expected 1 socket from launchd, got %d.\n",
+ launch_data_array_get_count (listening_fd_array));
+ goto l_failed_0;
+ }
+
+ listening_fd = launch_data_array_get_index (listening_fd_array, 0);
+ launchd_fd = launch_data_get_fd (listening_fd);
+
+ _dbus_fd_set_close_on_exec (launchd_fd);
+
+ if (launchd_fd < 0)
+ {
+ _DBUS_ASSERT_ERROR_IS_SET (error);
+ goto l_failed_0;
+ }
+
+ server = _dbus_server_new_for_socket (&launchd_fd, 1, &address);
+ if (server == NULL)
+ {
+ dbus_set_error (error, DBUS_ERROR_NO_SERVER, "Unable to listen on launchd fd %d.", launchd_fd);
+ goto l_failed_0;
+ }
+
+ _dbus_string_free (&address);
+
+ return server;
+
+ l_failed_0:
+ _dbus_string_free (&address);
+
+ return NULL;
+}
+
+/** @} */
+
diff --git a/dbus/dbus-server-launchd.h b/dbus/dbus-server-launchd.h
new file mode 100644
index 0000000..1c45aa1
--- /dev/null
+++ b/dbus/dbus-server-launchd.h
@@ -0,0 +1,37 @@
+/* dbus-server-launchd.h Server methods for interacting with launchd.
+* Copyright (C) 2008, Benjamin Reed
+*
+* Permission is hereby granted, free of charge, to any person
+* obtaining a copy of this software and associated documentation
+* files (the "Software"), to deal in the Software without
+* restriction, including without limitation the rights to use, copy,
+* modify, merge, publish, distribute, sublicense, and/or sell copies
+* of the Software, and to permit persons to whom the Software is
+* furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be
+* included in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+* DEALINGS IN THE SOFTWARE.
+*/
+
+#ifndef DBUS_SERVER_LAUNCHD_H
+#define DBUS_SERVER_LAUNCHD_H
+
+#include
+#include
+
+DBUS_BEGIN_DECLS
+
+DBusServer* _dbus_server_new_for_launchd_fd (const char *socket_fd, DBusError *error);
+
+DBUS_END_DECLS
+
+#endif /* DBUS_SERVER_LAUNCHD_H */
diff --git a/dbus/dbus-server-unix.c b/dbus/dbus-server-unix.c
index 1dda5d1..e05f174 100644
--- a/dbus/dbus-server-unix.c
+++ b/dbus/dbus-server-unix.c
@@ -21,6 +21,7 @@
*
*/
+#include
#include "dbus-internals.h"
#include "dbus-server-unix.h"
#include "dbus-server-socket.h"
@@ -29,6 +30,10 @@
#include "dbus-sysdeps-unix.h"
#include "dbus-string.h"
+#ifdef DBUS_ENABLE_LAUNCHD
+#include "dbus-server-launchd.h"
+#endif
+
/**
* @defgroup DBusServerUnix DBusServer implementations for UNIX
* @ingroup DBusInternals
@@ -145,6 +150,26 @@ _dbus_server_listen_platform_specific (DBusAddressEntry *entry,
return DBUS_SERVER_LISTEN_DID_NOT_CONNECT;
}
}
+#ifdef DBUS_ENABLE_LAUNCHD
+ else if (strcmp (method, "launchd") == 0)
+ {
+ const char *launchd_key = dbus_address_entry_get_value (entry, "key");
+ if (launchd_key == NULL)
+ launchd_key = "session";
+ *server_p = _dbus_server_new_for_launchd_fd (launchd_key, error);
+
+ if (*server_p != NULL)
+ {
+ _DBUS_ASSERT_ERROR_IS_CLEAR(error);
+ return DBUS_SERVER_LISTEN_OK;
+ }
+ else
+ {
+ _DBUS_ASSERT_ERROR_IS_SET(error);
+ return DBUS_SERVER_LISTEN_DID_NOT_CONNECT;
+ }
+ }
+#endif
else
{
/* If we don't handle the method, we return NULL with the
diff --git a/dbus/dbus-server.c b/dbus/dbus-server.c
index f04829b..47cd339 100644
diff --git a/dbus/dbus-sysdeps-unix.c b/dbus/dbus-sysdeps-unix.c
index 29d234a..6807a81 100644
--- a/dbus/dbus-sysdeps-unix.c
+++ b/dbus/dbus-sysdeps-unix.c
@@ -2841,23 +2841,30 @@ _dbus_get_tmpdir(void)
}
/**
- * Determines the address of the session bus by querying a
- * platform-specific method.
+ * Execute a subprocess, returning up to 1024 bytes of output
+ * into @p result.
*
- * If successful, returns #TRUE and appends the address to @p
- * address. If a failure happens, returns #FALSE and
+ * If successful, returns #TRUE and appends the output to @p
+ * result. If a failure happens, returns #FALSE and
* sets an error in @p error.
*
- * @param address a DBusString where the address can be stored
+ * @note It's not an error if the subprocess terminates normally
+ * without writing any data to stdout. Verify the @p result length
+ * before and after this function call to cover this case.
+ *
+ * @param progname initial path to exec
+ * @param argv NULL-terminated list of arguments
+ * @param result a DBusString where the output can be append
* @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 dbus_bool_t
+_read_subprocess_line_argv (const char *progpath,
+ const char * const *argv,
+ DBusString *result,
+ DBusError *error)
{
- static char *argv[6];
- int address_pipe[2] = { -1, -1 };
+ int result_pipe[2] = { -1, -1 };
int errors_pipe[2] = { -1, -1 };
pid_t pid;
int ret;
@@ -2876,33 +2883,11 @@ _dbus_get_autolaunch_address (DBusString *address,
return FALSE;
}
- if (!_dbus_get_local_machine_uuid_encoded (&uuid))
- {
- _DBUS_SET_OOM (error);
- goto out;
- }
-
- i = 0;
- argv[i] = "dbus-launch";
- ++i;
- argv[i] = "--autolaunch";
- ++i;
- argv[i] = _dbus_string_get_data (&uuid);
- ++i;
- argv[i] = "--binary-syntax";
- ++i;
- argv[i] = "--close-stderr";
- ++i;
- argv[i] = NULL;
- ++i;
-
- _dbus_assert (i == _DBUS_N_ELEMENTS (argv));
-
- orig_len = _dbus_string_get_length (address);
+ orig_len = _dbus_string_get_length (result);
#define READ_END 0
#define WRITE_END 1
- if (pipe (address_pipe) < 0)
+ if (pipe (result_pipe) < 0)
{
dbus_set_error (error, _dbus_error_from_errno (errno),
"Failed to create a pipe: %s",
@@ -2946,7 +2931,7 @@ _dbus_get_autolaunch_address (DBusString *address,
_dbus_verbose ("/dev/null fd %d opened\n", fd);
/* set-up stdXXX */
- close (address_pipe[READ_END]);
+ close (result_pipe[READ_END]);
close (errors_pipe[READ_END]);
close (0); /* close stdin */
close (1); /* close stdout */
@@ -2954,7 +2939,7 @@ _dbus_get_autolaunch_address (DBusString *address,
if (dup2 (fd, 0) == -1)
_exit (1);
- if (dup2 (address_pipe[WRITE_END], 1) == -1)
+ if (dup2 (result_pipe[WRITE_END], 1) == -1)
_exit (1);
if (dup2 (errors_pipe[WRITE_END], 2) == -1)
_exit (1);
@@ -2969,25 +2954,36 @@ _dbus_get_autolaunch_address (DBusString *address,
for (i = 3; i < maxfds; i++)
close (i);
- execv (DBUS_BINDIR "/dbus-launch", argv);
+ /* If it looks fully-qualified, try execv first */
+ if (progpath[0] == '/')
+ {
+ const char *progname;
+
+ execv (progpath, (char **) argv);
- /* failed, try searching PATH */
- execvp ("dbus-launch", argv);
+ /* If we failed with a direct exec, try extracting
+ the binary name and search the PATH for it */
+ progname = strrchr (progpath, '/');
+ if (progname != NULL)
+ execvp (progname+1, (char **) argv);
+ }
+ else
+ execvp (progpath, (char **) argv);
/* still nothing, we failed */
_exit (1);
}
/* parent process */
- close (address_pipe[WRITE_END]);
+ close (result_pipe[WRITE_END]);
close (errors_pipe[WRITE_END]);
- address_pipe[WRITE_END] = -1;
+ result_pipe[WRITE_END] = -1;
errors_pipe[WRITE_END] = -1;
ret = 0;
do
{
- ret = _dbus_read (address_pipe[READ_END], address, 1024);
+ ret = _dbus_read (result_pipe[READ_END], result, 1024);
}
while (ret > 0);
@@ -3000,8 +2996,7 @@ _dbus_get_autolaunch_address (DBusString *address,
/* 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)
+ if (!WIFEXITED (status) || WEXITSTATUS (status) != 0 )
{
/* The process ended with error */
DBusString error_message;
@@ -3013,14 +3008,14 @@ _dbus_get_autolaunch_address (DBusString *address,
}
while (ret > 0);
- _dbus_string_set_length (address, orig_len);
+ _dbus_string_set_length (result, orig_len);
if (_dbus_string_get_length (&error_message) > 0)
dbus_set_error (error, DBUS_ERROR_SPAWN_EXEC_FAILED,
- "dbus-launch failed to autolaunch D-Bus session: %s",
+ "Subprocess terminated abnormally with the following error: %s",
_dbus_string_get_data (&error_message));
else
dbus_set_error (error, DBUS_ERROR_SPAWN_EXEC_FAILED,
- "Failed to execute dbus-launch to autolaunch D-Bus session");
+ "Subprocess terminated abnormally without any error message");
goto out;
}
@@ -3032,19 +3027,172 @@ _dbus_get_autolaunch_address (DBusString *address,
else
_DBUS_ASSERT_ERROR_IS_SET (error);
- if (address_pipe[0] != -1)
- close (address_pipe[0]);
- if (address_pipe[1] != -1)
- close (address_pipe[1]);
+ if (result_pipe[0] != -1)
+ close (result_pipe[0]);
+ if (result_pipe[1] != -1)
+ close (result_pipe[1]);
if (errors_pipe[0] != -1)
close (errors_pipe[0]);
if (errors_pipe[1] != -1)
close (errors_pipe[1]);
+ return retval;
+}
+
+/**
+ * Returns the address of a new session bus.
+ *
+ * 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[6];
+ int i;
+ DBusString uuid;
+ dbus_bool_t retval;
+
+ _DBUS_ASSERT_ERROR_IS_CLEAR (error);
+ retval = FALSE;
+
+ if (!_dbus_string_init (&uuid))
+ {
+ _DBUS_SET_OOM (error);
+ return FALSE;
+ }
+
+ if (!_dbus_get_local_machine_uuid_encoded (&uuid))
+ {
+ _DBUS_SET_OOM (error);
+ goto out;
+ }
+
+ i = 0;
+ argv[i] = "dbus-launch";
+ ++i;
+ argv[i] = "--autolaunch";
+ ++i;
+ argv[i] = _dbus_string_get_data (&uuid);
+ ++i;
+ argv[i] = "--binary-syntax";
+ ++i;
+ argv[i] = "--close-stderr";
+ ++i;
+ argv[i] = NULL;
+ ++i;
+
+ _dbus_assert (i == _DBUS_N_ELEMENTS (argv));
+
+ retval = _read_subprocess_line_argv (DBUS_BINDIR "/dbus-launch",
+ (const char * const*) argv,
+ address, error);
+
+ out:
_dbus_string_free (&uuid);
return retval;
}
+#ifdef DBUS_ENABLE_LAUNCHD
+static dbus_bool_t
+_dbus_lookup_session_address_launchd (DBusString *address,
+ DBusError *error)
+{
+ static char *argv[4];
+ int i;
+ int orig_len;
+ dbus_bool_t retval;
+
+ _DBUS_ASSERT_ERROR_IS_CLEAR (error);
+
+ i = 0;
+ argv[i] = "launchctl";
+ ++i;
+ argv[i] = "getenv";
+ ++i;
+ argv[i] = "DBUS_LAUNCHD_SESSION_BUS_SOCKET";
+ ++i;
+ argv[i] = NULL;
+ ++i;
+
+ _dbus_assert (i == _DBUS_N_ELEMENTS (argv));
+
+ /* from launchd's environment we get only the path to the socket */
+ if (!_dbus_string_append (address, "unix:path="))
+ {
+ _DBUS_SET_OOM (error);
+ return FALSE;
+ }
+
+ orig_len = _dbus_string_get_length(address);
+ /* append the process output to address */
+ if (!_read_subprocess_line_argv(argv[0], (const char * const*) argv,
+ address, error))
+ {
+ /* reset the address */
+ _dbus_string_set_length(address, 0);
+ return FALSE;
+ }
+
+ /* test if we got something from the subprocess */
+ if (_dbus_string_get_length(address) == orig_len)
+ {
+ /* reset the address */
+ _dbus_string_set_length(address, 0);
+ dbus_set_error(error, "no socket path",
+ "launchd did not provide a socket path, "
+ "verify that org.freedesktop.dbus-session.plist is loaded!");
+ return FALSE;
+ }
+
+ /* strip the carriage-return */
+ _dbus_string_shorten(address, 1);
+ return TRUE;
+}
+#endif
+
+/**
+ * Determines the address of the session bus by querying a
+ * platform-specific method.
+ *
+ * The first parameter will be a boolean specifying whether
+ * or not a dynamic session lookup is supported on this platform.
+ *
+ * If supported is TRUE and the return value is #TRUE, the
+ * address will be appended to @p address.
+ * If a failure happens, returns #FALSE and sets an error in
+ * @p error.
+ *
+ * If supported is FALSE, ignore the return value.
+ *
+ * @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_lookup_session_address (dbus_bool_t *supported,
+ DBusString *address,
+ DBusError *error)
+{
+#ifdef DBUS_ENABLE_LAUNCHD
+ *supported = TRUE;
+ return _dbus_lookup_session_address_launchd (address, error);
+#else
+ /* On non-Mac Unix platforms, if the session address isn't already
+ * set in DBUS_SESSION_BUS_ADDRESS environment variable, we punt and
+ * fall back to the autolaunch: global default; see
+ * init_session_address in dbus/dbus-bus.c. */
+ *supported = FALSE;
+ return TRUE;
+#endif
+}
+
/**
* Reads the uuid of the machine we're running on from
* the dbus configuration. Optionally try to create it
diff --git a/dbus/dbus-sysdeps-win.c b/dbus/dbus-sysdeps-win.c
index a67e502..9cfcf92 100644
--- a/dbus/dbus-sysdeps-win.c
+++ b/dbus/dbus-sysdeps-win.c
@@ -1393,8 +1393,17 @@ _dbus_poll (DBusPollFD *fds,
#endif // USE_CHRIS_IMPL
-
-
+dbus_bool_t
+_dbus_lookup_session_address (dbus_bool_t *supported,
+ DBusString *address,
+ DBusError *error)
+{
+ /* FIXME - implement this by querying COM or some other Windows facility
+ * which is scoped per-session.
+ */
+ *supported = FALSE;
+ return TRUE;
+}
/******************************************************************************
diff --git a/dbus/dbus-sysdeps.h b/dbus/dbus-sysdeps.h
index b766f3f..6f00b04 100644
--- a/dbus/dbus-sysdeps.h
+++ b/dbus/dbus-sysdeps.h
@@ -468,6 +468,10 @@ void _dbus_log_security (const char *msg, va_list args);
dbus_bool_t _dbus_get_autolaunch_address (DBusString *address,
DBusError *error);
+dbus_bool_t _dbus_lookup_session_address (dbus_bool_t *supported,
+ DBusString *address,
+ DBusError *error);
+
/** Type representing a universally unique ID
* @todo rename to UUID instead of GUID
*/