Skip to content

Instantly share code, notes, and snippets.

@lfranchi
Created October 4, 2009 14:51
Show Gist options
  • Save lfranchi/201422 to your computer and use it in GitHub Desktop.
Save lfranchi/201422 to your computer and use it in GitHub Desktop.
diff -Nurd dbus-1.2.16/README.launchd dbus-1.2.16-new/README.launchd
--- dbus-1.2.16/README.launchd 1969-12-31 19:00:00.000000000 -0500
+++ dbus-1.2.16-new/README.launchd 2009-09-05 08:56:49.000000000 -0400
@@ -0,0 +1,61 @@
+Launchd[1,2] replaces init, inetd and cron on Mac OS X since 10.4 "Tiger".
+dbus uses this service to provide a common session bus address for each user
+and so deprecates the X11 enabled dbus-launcher.
+
+[1] http://developer.apple.com/MacOsX/launchd.html
+[2] http://launchd.macosforge.org/
+
+
+Setup
+===
+
+Configure with --enable-launchd and --without-x (X11 should not harm but it's
+simply not necessary any more)
+After installation, to prevent a reboot, load the dbus session starter into
+launchd by executing:
+$ launchctl load /Library/LaunchAgents/org.freedesktop.dbus-session.plist
+
+You can change the launch agent dir via configure, but it's not recommended.
+Make sure to execute the above line as the actual user for which you want to
+use a session bus since launchd manages its agents on a per user basis.
+
+
+How it works
+===
+
+Launchd allocates a socket and provides the unix path to it via the variable
+DBUS_LAUNCHD_SESSION_BUS_SOCKET in launchd's environment. Every process
+spawned by launchd (or dbus-daemon, if stared by launchd) can access it through
+its own environment. Other processes can query launchd for it by executing:
+$ launchctl getenv DBUS_LAUNCHD_SESSION_BUS_SOCKET
+However, this is normally done by the dbus client lib for you.
+
+If launchd start dbus-daemon with a config file containing a "launchd:env=FOO"
+address, as the default session config does with env=DBUS_LAUNCHD_SESSION_BUS_SOCKET,
+the daemon will get the file descriptor from launchd and start listening on it.
+The environment variable is used to get the actual socket path which is passed
+to every service spawned by dbus-daemon as a result from autolaunch messages.
+Please note that it's not possible to start dbus-daemon manually when using a
+"launchd:" address. Only child processes of launchd can access the above
+mentioned file descriptor!
+
+To create custom buses just set up an other launch agent. As a quick start copy
+/Library/LaunchAgents/org.freedesktop.dbus-session.plist, change the label
+to i.e. "org.freedesktop.dbus-foo" and change the SecureSocketWithKey value,
+i.e. to "DBUS_LAUNCHD_FOO_BUS_SOCKET". This environment variable has to be set
+in the config file for your new bus in the <listen> element (see session.config).
+Then edit your /Library/LaunchAgents/org.freedesktop.dbus-foo.plist to start
+dbus-daemon with "--config-file=/opt/local/etc/dbus-1/foo.conf" instead of
+"--session". Now load the new plist onto launchd as described in the setup
+section of this document.
+Executing "launchctl export" should now give you two sockets, one in
+DBUS_LAUNCHD_SESSION_BUS_SOCKET and the new DBUS_LAUNCHD_FOO_BUS_SOCKET.
+To connect to this new bus use "launchd:env=DBUS_LAUNCHD_FOO_BUS_SOCKET".
+
+Since Mac OS X 10.5 "Leopard" you can also configure launchd to start
+dbus-daemon on demand as soon as some process connects to the socket. Since
+it's broken on 10.4 this feature is disabled per default. Look at
+/Library/LaunchAgents/org.freedesktop.dbus-session.plist to change it.
+
+On the client side, the envvar DBUS_SESSION_BUS_ADDRESS can be normally used
+but if it's not set, launchd is queried for the session bus socket.
diff -Nurd dbus-1.2.16/bus/Makefile.am dbus-1.2.16-new/bus/Makefile.am
--- dbus-1.2.16/bus/Makefile.am 2009-07-13 12:23:26.000000000 -0400
+++ dbus-1.2.16-new/bus/Makefile.am 2009-09-05 08:56:49.000000000 -0400
@@ -9,12 +9,18 @@
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 -Nurd dbus-1.2.16/bus/org.freedesktop.dbus-session.plist.in dbus-1.2.16-new/bus/org.freedesktop.dbus-session.plist.in
--- dbus-1.2.16/bus/org.freedesktop.dbus-session.plist.in 1969-12-31 19:00:00.000000000 -0500
+++ dbus-1.2.16-new/bus/org.freedesktop.dbus-session.plist.in 2009-09-05 08:56:49.000000000 -0400
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>Label</key>
+ <string>org.freedesktop.dbus-session</string>
+
+ <key>ServiceIPC</key>
+ <true/>
+
+ <!-- bug in 10.4's launchd - on-demand loading does not work -->
+ <key>OnDemand</key>
+ <false />
+
+ <key>ProgramArguments</key>
+ <array>
+ <string>@DBUS_DAEMONDIR@/dbus-daemon</string>
+ <string>--nofork</string>
+ <string>--session</string>
+ </array>
+
+ <key>Sockets</key>
+ <dict>
+ <key>unix_domain_listener</key>
+ <dict>
+ <key>SecureSocketWithKey</key>
+ <string>DBUS_LAUNCHD_SESSION_BUS_SOCKET</string>
+ </dict>
+ </dict>
+</dict>
+</plist>
diff -Nurd dbus-1.2.16/bus/session.conf.in dbus-1.2.16-new/bus/session.conf.in
--- dbus-1.2.16/bus/session.conf.in 2009-07-14 15:38:33.000000000 -0400
+++ dbus-1.2.16-new/bus/session.conf.in 2009-09-05 08:56:49.000000000 -0400
@@ -12,7 +12,7 @@
the behavior of child processes. -->
<keep_umask/>
- <listen>unix:tmpdir=@DBUS_SESSION_SOCKET_DIR@</listen>
+ <listen>@DBUS_SESSION_BUS_DEFAULT_ADDRESS@</listen>
<standard_session_servicedirs />
diff -Nurd dbus-1.2.16/configure.in dbus-1.2.16-new/configure.in
--- dbus-1.2.16/configure.in 2009-07-14 15:42:51.000000000 -0400
+++ dbus-1.2.16-new/configure.in 2009-09-05 08:56:49.000000000 -0400
@@ -78,6 +78,7 @@
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-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>],[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]))
@@ -820,6 +822,38 @@
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 && test 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)
+
+#### 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;
@@ -1279,6 +1313,14 @@
AC_SUBST(DBUS_SYSTEM_BUS_DEFAULT_ADDRESS)
AC_DEFINE_UNQUOTED(DBUS_SYSTEM_BUS_DEFAULT_ADDRESS, "$DBUS_SYSTEM_BUS_DEFAULT_ADDRESS",[The default D-Bus address of the system bus])
+# set up the session bus address
+if test x$have_launchd = xyes; then
+ DBUS_SESSION_BUS_DEFAULT_ADDRESS="launchd:env=DBUS_LAUNCHD_SESSION_BUS_SOCKET"
+else
+ DBUS_SESSION_BUS_DEFAULT_ADDRESS="unix:tmpdir=$DBUS_SESSION_SOCKET_DIR"
+fi
+AC_SUBST(DBUS_SESSION_BUS_DEFAULT_ADDRESS)
+
#### Set up the pid file
if ! test -z "$with_system_pid_file"; then
DBUS_SYSTEM_PID_FILE=$with_system_pid_file
@@ -1403,7 +1445,6 @@
DBUS_SESSION_SOCKET_DIR=$DEFAULT_SOCKET_DIR
fi
AC_DEFINE_UNQUOTED(DBUS_SESSION_SOCKET_DIR, "$DBUS_SESSION_SOCKET_DIR", [Where per-session bus puts its sockets])
-AC_SUBST(DBUS_SESSION_SOCKET_DIR)
AC_DEFINE_UNQUOTED(DBUS_UNIX, "1", [Defined on UNIX and Linux systems and not on Windows])
@@ -1425,6 +1466,7 @@
bus/system.conf
bus/session.conf
bus/messagebus
+bus/org.freedesktop.dbus-session.plist
bus/rc.messagebus
bus/dbus-daemon.1
Makefile
@@ -1492,6 +1534,7 @@
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}
@@ -1505,8 +1548,11 @@
Console owner file path: ${DBUS_CONSOLE_OWNER_FILE}
System bus user: ${DBUS_USER}
Session bus services dir: ${EXPANDED_DATADIR}/dbus-1/services
- 'make check' socket dir: ${TEST_SOCKET_DIR}
-"
+ 'make check' socket dir: ${TEST_SOCKET_DIR}"
+if test x$have_launchd = xyes; then
+ echo " launchd agent dir: ${LAUNCHD_AGENT_DIR}"
+fi
+echo
if test x$enable_tests = xyes; then
echo "NOTE: building with unit tests increases the size of the installed library and renders it insecure."
diff -Nurd dbus-1.2.16/dbus/Makefile.am dbus-1.2.16-new/dbus/Makefile.am
--- dbus-1.2.16/dbus/Makefile.am 2009-07-13 12:23:26.000000000 -0400
+++ dbus-1.2.16-new/dbus/Makefile.am 2009-09-05 08:56:49.000000000 -0400
@@ -70,6 +70,8 @@
dbus-server.c \
dbus-server-debug-pipe.c \
dbus-server-debug-pipe.h \
+ dbus-server-launchd.c \
+ dbus-server-launchd.h \
dbus-server-protected.h \
dbus-server-socket.c \
dbus-server-socket.h \
diff -Nurd dbus-1.2.16/dbus/dbus-server-launchd.c dbus-1.2.16-new/dbus/dbus-server-launchd.c
--- dbus-1.2.16/dbus/dbus-server-launchd.c 1969-12-31 19:00:00.000000000 -0500
+++ dbus-1.2.16-new/dbus/dbus-server-launchd.c 2009-09-05 10:57:51.000000000 -0400
@@ -0,0 +1,186 @@
+/* dbus-server-launchd.c Server methods for interacting with launchd.
+ * Copyright (C) 2007, Tanner Lovelace <lovelace@wayfarer.org>
+ * Copyright (C) 2008, Colin Walters <walters@verbum.org>
+ * Copyright (C) 2008-2009, Benjamin Reed <rangerrick@befunk.com>
+ * Copyright (C) 2009, Jonas Bähr<jonas.baehr@web.de>
+ *
+ * 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 <config.h>
+#include "dbus-server-launchd.h"
+
+/**
+ * @defgroup DBusServerLaunchd DBusServer implementations for Launchd
+ * @ingroup DBusInternals
+ * @brief Implementation details of DBusServer with Launchd support
+ *
+ * @{
+ */
+
+#ifdef DBUS_ENABLE_LAUNCHD
+#include <launch.h>
+#include <errno.h>
+
+#include "dbus-server-socket.h"
+
+/* put other private launchd functions here */
+
+#endif /* DBUS_ENABLE_LAUNCHD */
+
+/**
+ * @brief Creates a new server from launchd.
+ *
+ * launchd has allocaed a socket for us. We now query launchd for the
+ * file descriptor of this socket and create a server on it.
+ * In addition we inherit launchd's environment which holds a variable
+ * containing the path to the socket. This is used to init the server's
+ * address which is passed to autolaunched services.
+ *
+ * @param launchd_env_var the environment variable which holds the unix path to the socket
+ * @param error location to store reason for failure.
+ * @returns the new server, or #NULL on failure.
+ */
+
+DBusServer *
+_dbus_server_new_for_launchd (const char *launchd_env_var, DBusError * error)
+ {
+#ifdef DBUS_ENABLE_LAUNCHD
+ 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;
+ launch_data_t environment_dict, environment_param;
+ const char *launchd_socket_path;
+
+ launchd_socket_path = _dbus_getenv (launchd_env_var);
+
+ _DBUS_ASSERT_ERROR_IS_CLEAR (error);
+
+ if (launchd_socket_path == NULL || *launchd_socket_path == '\0')
+ {
+ dbus_set_error (error, DBUS_ERROR_BAD_ADDRESS,
+ "launchd's environment variable %s is empty, but should contain a socket path.\n", launchd_env_var);
+ return NULL;
+ }
+
+ if (!_dbus_string_init (&address))
+ {
+ dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
+ return NULL;
+ }
+ if (!_dbus_string_append (&address, "unix:path="))
+ {
+ dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
+ goto l_failed_0;
+ }
+ if (!_dbus_string_append (&address, launchd_socket_path))
+ {
+ 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, "unix_domain_listener");
+ 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;
+#else /* DBUS_ENABLE_LAUNCHD */
+ dbus_set_error (error, DBUS_ERROR_BAD_ADDRESS,
+ "address type 'launchd' requested, but launchd support not compiled in");
+ return NULL;
+#endif
+ }
+
+/** @} */
diff -Nurd dbus-1.2.16/dbus/dbus-server-launchd.h dbus-1.2.16-new/dbus/dbus-server-launchd.h
--- dbus-1.2.16/dbus/dbus-server-launchd.h 1969-12-31 19:00:00.000000000 -0500
+++ dbus-1.2.16-new/dbus/dbus-server-launchd.h 2009-09-05 08:56:49.000000000 -0400
@@ -0,0 +1,35 @@
+/* dbus-server-launchd.h Server methods for interacting with launchd.
+* Copyright (C) 2008, Benjamin Reed <rangerrick@befunk.com>
+*
+* 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 <dbus/dbus-internals.h>
+#include <dbus/dbus-server-protected.h>
+
+DBUS_BEGIN_DECLS
+ DBusServer * _dbus_server_new_for_launchd (const char *launchd_env_var, DBusError * error);
+
+DBUS_END_DECLS
+#endif /* DBUS_SERVER_LAUNCHD_H */
diff -Nurd dbus-1.2.16/dbus/dbus-server-unix.c dbus-1.2.16-new/dbus/dbus-server-unix.c
--- dbus-1.2.16/dbus/dbus-server-unix.c 2009-07-14 15:39:47.000000000 -0400
+++ dbus-1.2.16-new/dbus/dbus-server-unix.c 2009-09-05 10:57:51.000000000 -0400
@@ -21,9 +21,11 @@
*
*/
+#include <config.h>
#include "dbus-internals.h"
#include "dbus-server-unix.h"
#include "dbus-server-socket.h"
+#include "dbus-server-launchd.h"
#include "dbus-transport-unix.h"
#include "dbus-connection-internal.h"
#include "dbus-sysdeps-unix.h"
@@ -145,6 +147,27 @@
return DBUS_SERVER_LISTEN_DID_NOT_CONNECT;
}
}
+ else if (strcmp (method, "launchd") == 0)
+ {
+ const char *launchd_env_var = dbus_address_entry_get_value (entry, "env");
+ if (launchd_env_var == NULL)
+ {
+ _dbus_set_bad_address (error, "launchd", "env", NULL);
+ return DBUS_SERVER_LISTEN_DID_NOT_CONNECT;
+ }
+ *server_p = _dbus_server_new_for_launchd (launchd_env_var, 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;
+ }
+ }
else
{
/* If we don't handle the method, we return NULL with the
diff -Nurd dbus-1.2.16/dbus/dbus-spawn.c dbus-1.2.16-new/dbus/dbus-spawn.c
--- dbus-1.2.16/dbus/dbus-spawn.c 2009-07-14 15:39:47.000000000 -0400
+++ dbus-1.2.16-new/dbus/dbus-spawn.c 2009-09-05 10:57:51.000000000 -0400
@@ -36,6 +36,11 @@
#include <errno.h>
#endif
+#ifdef DBUS_ENABLE_LAUNCHD
+static int _launchd_allocated = 0; /* environ is, or is not, allocated */
+#include <launch.h>
+#endif
+
extern char **environ;
/**
@@ -879,6 +884,108 @@
exit (0);
}
+#ifdef DBUS_ENABLE_LAUNCHD
+static char *_launchd_cmalloc(int new_len, char *old, int old_len)
+{
+ char *new = malloc(new_len);
+
+ if (new != 0)
+ {
+ memcpy(new, old, old_len);
+ }
+ return (new);
+}
+
+static int _launchd_namelength(char *name)
+{
+ char *equal;
+
+ equal = strchr(name, '=');
+ return ((equal == 0) ? strlen(name) : (equal - name));
+}
+
+static char **_launchd_findenv(char **envp, char *name, int len)
+{
+ char **env;
+
+ for (env = envp; env && *env; env++)
+ {
+ if (strncmp(name, *env, len) == 0 && (*env)[len] == '=')
+ {
+ return (env);
+ }
+ }
+ return (0);
+}
+
+static int _launchd_addenv(char **envp, char *nameval)
+{
+ char **env;
+ int n_used; /* number of environment entries */
+ int l_used; /* bytes used excl. terminator */
+ int l_need; /* bytes needed incl. terminator */
+
+ for (env = envp; env && *env; env++)
+ {
+ n_used = env - envp;
+ l_used = n_used * sizeof(*env);
+ l_need = l_used + 2 * sizeof(*env);
+
+ env = _launchd_allocated ? (char **) realloc((char *) envp, l_need) : (char **) _launchd_cmalloc(l_need, (char *) envp, l_used);
+ if (env == 0)
+ {
+ return (-1);
+ }
+ else
+ {
+ _launchd_allocated = 1;
+ envp = env;
+ envp[n_used++] = nameval; /* add new entry */
+ envp[n_used] = 0; /* terminate list */
+ return (0);
+ }
+ }
+ return 0;
+}
+
+static int _launchd_setenv(char **envp, char *name, const char *value)
+{
+ char *destination;
+ char **env;
+ int l_name; /* length of name part */
+ int l_nameval; /* length of name=value */
+
+ /* Permit name= and =value. */
+
+ l_name = _launchd_namelength(name);
+ env = _launchd_findenv(envp, name, l_name);
+ if (env != 0)
+ {
+ return (0);
+ }
+ if (*value == '=')
+ {
+ value++;
+ }
+ l_nameval = l_name + strlen(value) + 1;
+
+ /*
+ * Use available memory if the old value is long enough. Never free an
+ * old name=value entry because it may not be allocated.
+ */
+
+ destination = (env != 0 && strlen(*env) >= l_nameval) ? *env : malloc(l_nameval + 1);
+ if (destination == 0)
+ {
+ return (-1);
+ }
+ strncpy(destination, name, l_name);
+ destination[l_name] = '=';
+ strcpy(destination + l_name + 1, value);
+ return ((env == 0) ? _launchd_addenv(env, destination) : (*env = destination, 0));
+}
+#endif
+
static void
do_exec (int child_err_report_fd,
char **argv,
@@ -890,6 +997,13 @@
int i, max_open;
#endif
+#ifdef DBUS_ENABLE_LAUNCHD
+ const char *display;
+ const char **env;
+ launch_data_t checkin_request, checkin_response;
+ launch_data_t environment_dict, environment_param;
+#endif
+
_dbus_verbose_reset ();
_dbus_verbose ("Child process has PID " DBUS_PID_FORMAT "\n",
_dbus_getpid ());
@@ -921,6 +1035,48 @@
envp = environ;
}
+#ifdef DBUS_ENABLE_LAUNCHD
+ display = _dbus_getenv ("DISPLAY");
+ if (display == NULL || *display == '\0')
+ {
+ if ((checkin_request = launch_data_new_string (LAUNCH_KEY_CHECKIN)) == NULL)
+ {
+ _dbus_warn ("Unable to create checkin string.");
+ goto launchd_display_failed;
+ }
+
+ if ((checkin_response = launch_msg (checkin_request)) == NULL)
+ {
+ _dbus_warn ("launch_msg IPC failure");
+ goto launchd_display_failed;
+ }
+
+ if (LAUNCH_DATA_ERRNO == launch_data_get_type (checkin_response))
+ {
+ _dbus_warn ("launchd check-in failed");
+ goto launchd_display_failed;
+ }
+
+ environment_dict = launch_data_dict_lookup (checkin_response, LAUNCH_JOBKEY_USERENVIRONMENTVARIABLES);
+ if (NULL == environment_dict)
+ {
+ _dbus_warn ("Unable to retrieve user environment from launchd.");
+ goto launchd_display_failed;
+ }
+
+ environment_param = launch_data_dict_lookup (environment_dict, "DISPLAY");
+ if (NULL == environment_param)
+ {
+ _dbus_warn ("Unable to retrieve DISPLAY from launchd.");
+ goto launchd_display_failed;
+ }
+
+ display = launch_data_get_string(environment_param);
+ _launchd_setenv(envp, "DISPLAY", display);
+ }
+ launchd_display_failed:
+#endif
+
execve (argv[0], argv, envp);
/* Exec failed */
diff -Nurd dbus-1.2.16/dbus/dbus-sysdeps-unix.c dbus-1.2.16-new/dbus/dbus-sysdeps-unix.c
--- dbus-1.2.16/dbus/dbus-sysdeps-unix.c 2009-07-14 15:42:38.000000000 -0400
+++ dbus-1.2.16-new/dbus/dbus-sysdeps-unix.c 2009-09-05 11:03:28.000000000 -0400
@@ -1643,7 +1643,7 @@
{
if (errno == 0)
{
- _dbus_warn ("It appears that username \"%s\" is in more than %d groups.\nProceeding with just the first %d groups.",
+ _dbus_warn ("It appears that username \"%s\" is in more than %d groups.\nProceeding with just the first %d groups.\n",
username_c, buf_count, buf_count);
}
else
@@ -3168,6 +3168,104 @@
#define DBUS_UNIX_STANDARD_SYSTEM_SERVICEDIR "/dbus-1/system-services"
/**
+ * quries launchd for a specific env var which holds the socket path.
+ * @param launchd_env_var the env var to look up
+ * @param error a DBusError to store the error in case of failure
+ * @return the value of the env var
+ */
+dbus_bool_t
+_dbus_lookup_launchd_socket (DBusString *socket_path,
+ const char *launchd_env_var,
+ DBusError *error)
+{
+#ifdef DBUS_ENABLE_LAUNCHD
+ char *argv[4];
+ int i;
+
+ _DBUS_ASSERT_ERROR_IS_CLEAR (error);
+
+ i = 0;
+ argv[i] = "launchctl";
+ ++i;
+ argv[i] = "getenv";
+ ++i;
+ argv[i] = (char*)launchd_env_var;
+ ++i;
+ argv[i] = NULL;
+ ++i;
+
+ _dbus_assert (i == _DBUS_N_ELEMENTS (argv));
+
+ if (!_read_subprocess_line_argv(argv[0], TRUE, argv, socket_path, error))
+ {
+ return FALSE;
+ }
+
+/* _DBUS_ASSERT_ERROR_IS_CLEAR (error); */
+
+ /* no error, but no result either */
+ if (_dbus_string_get_length(socket_path) == 0)
+ {
+ return FALSE;
+ }
+
+ /* strip the carriage-return */
+ _dbus_string_shorten(socket_path, 1);
+ return TRUE;
+#else /* DBUS_ENABLE_LAUNCHD */
+ dbus_set_error(error, DBUS_ERROR_NOT_SUPPORTED,
+ "can't lookup socket from launchd; launchd support not compiled in");
+ return FALSE;
+#endif
+}
+
+static dbus_bool_t
+_dbus_lookup_session_address_launchd (DBusString *address, DBusError *error)
+{
+ dbus_bool_t valid_socket;
+ DBusString socket_path;
+
+ if (!_dbus_string_init (&socket_path))
+ {
+ _DBUS_SET_OOM (error);
+ return FALSE;
+ }
+
+ valid_socket = _dbus_lookup_launchd_socket (&socket_path, "DBUS_FINK_SESSION_BUS_SOCKET", error);
+
+ if (dbus_error_is_set(error))
+ {
+ _dbus_string_free(&socket_path);
+ return FALSE;
+ }
+
+ if (!valid_socket)
+ {
+ dbus_set_error(error, "no socket path",
+ "launchd did not provide a socket path, "
+ "verify that org.freedesktop.dbus-session.plist is loaded!");
+ _dbus_string_free(&socket_path);
+ return FALSE;
+ }
+ if (!_dbus_string_append (address, "unix:path="))
+ {
+ _DBUS_SET_OOM (error);
+ _dbus_string_free(&socket_path);
+ return FALSE;
+ }
+ if (!_dbus_string_copy (&socket_path, 0, address,
+ _dbus_string_get_length (address)))
+ {
+ _DBUS_SET_OOM (error);
+ _dbus_string_free(&socket_path);
+ return FALSE;
+ }
+
+ _dbus_string_free(&socket_path);
+ return TRUE;
+}
+
+/**
* Determines the address of the session bus by querying a
* platform-specific method.
*
@@ -3191,12 +3289,17 @@
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
}
/**
diff -Nurd dbus-1.2.16/dbus/dbus-sysdeps-unix.h dbus-1.2.16-new/dbus/dbus-sysdeps-unix.h
--- dbus-1.2.16/dbus/dbus-sysdeps-unix.h 2009-07-14 15:39:47.000000000 -0400
+++ dbus-1.2.16-new/dbus/dbus-sysdeps-unix.h 2009-09-05 08:56:49.000000000 -0400
@@ -77,6 +77,10 @@
dbus_bool_t _dbus_send_credentials (int server_fd,
DBusError *error);
+dbus_bool_t _dbus_lookup_launchd_socket (DBusString *socket_path,
+ const char *launchd_env_var,
+ DBusError *error);
+
/** Information about a UNIX user */
typedef struct DBusUserInfo DBusUserInfo;
/** Information about a UNIX group */
diff -Nurd dbus-1.2.16/dbus/dbus-transport-unix.c dbus-1.2.16-new/dbus/dbus-transport-unix.c
--- dbus-1.2.16/dbus/dbus-transport-unix.c 2009-07-14 15:39:47.000000000 -0400
+++ dbus-1.2.16-new/dbus/dbus-transport-unix.c 2009-09-05 10:57:51.000000000 -0400
@@ -171,6 +171,57 @@
return DBUS_TRANSPORT_OPEN_OK;
}
}
+ else if (strcmp (method, "launchd") == 0)
+ {
+ DBusError tmp_error = DBUS_ERROR_INIT;
+ const char *launchd_env_var = dbus_address_entry_get_value (entry, "env");
+ const char *launchd_socket;
+ DBusString socket_path;
+ dbus_bool_t valid_socket;
+
+ if (!_dbus_string_init (&socket_path))
+ {
+ _DBUS_SET_OOM (error);
+ return FALSE;
+ }
+
+ if (launchd_env_var == NULL)
+ {
+ _dbus_set_bad_address (error, "launchd", "env", NULL);
+ return DBUS_TRANSPORT_OPEN_BAD_ADDRESS;
+ }
+
+ valid_socket = _dbus_lookup_launchd_socket (&socket_path, launchd_env_var, error);
+
+ if (dbus_error_is_set(error))
+ {
+ _dbus_string_free(&socket_path);
+ return DBUS_TRANSPORT_OPEN_DID_NOT_CONNECT;
+ }
+
+ if (!valid_socket)
+ {
+ dbus_set_error(&tmp_error, DBUS_ERROR_BAD_ADDRESS,
+ "launchd's env var %s does not exist", launchd_env_var);
+ dbus_error_free(error);
+ dbus_move_error(&tmp_error, error);
+ return DBUS_TRANSPORT_OPEN_DID_NOT_CONNECT;
+ }
+
+ launchd_socket = _dbus_string_get_const_data(&socket_path);
+ *transport_p = _dbus_transport_new_for_domain_socket (launchd_socket, FALSE, 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);
diff -Nurd dbus-1.2.16/dbus-xinitrc.sh dbus-1.2.16-new/dbus-xinitrc.sh
--- dbus-1.2.16/dbus-xinitrc.sh 1969-12-31 19:00:00.000000000 -0500
+++ dbus-1.2.16-new/dbus-xinitrc.sh 2009-09-05 08:56:49.000000000 -0400
@@ -0,0 +1,8 @@
+#!/bin/sh
+
+if [ -n "$DISPLAY" ]; then
+ LDISPLAY=`TMPDIR=/tmp launchctl getenv DISPLAY`
+ if [ -z "$LDISPLAY" ]; then
+ TMPDIR=/tmp launchctl setenv DISPLAY "$DISPLAY"
+ fi
+fi
diff -Nurd dbus-1.2.16/start-session-bus.sh dbus-1.2.16-new/start-session-bus.sh
--- dbus-1.2.16/start-session-bus.sh 1969-12-31 19:00:00.000000000 -0500
+++ dbus-1.2.16-new/start-session-bus.sh 2009-09-05 08:56:49.000000000 -0400
@@ -0,0 +1,7 @@
+#!/bin/sh -e
+
+if [ `TMPDIR=/tmp launchctl list 2>/dev/null | grep -c org.freedesktop.dbus-session` -eq 0 ]; then
+ TMPDIR=/tmp launchctl load "@FINKPREFIX@/share/dbus/launchd/org.freedesktop.dbus-session.plist"
+fi
+
+exit 0
diff -Nurd dbus-1.2.16/start-system-bus.sh dbus-1.2.16-new/start-system-bus.sh
--- dbus-1.2.16/start-system-bus.sh 1969-12-31 19:00:00.000000000 -0500
+++ dbus-1.2.16-new/start-system-bus.sh 2009-09-05 08:56:49.000000000 -0400
@@ -0,0 +1,17 @@
+#!/bin/sh
+
+if [ -f "@FINKPREFIX@/etc/dbus-1/disable-dbus" ]; then
+ exit 0
+fi
+
+if [ -f "@FINKPREFIX@/var/run/dbus/pid" ]; then
+ PID=`cat "@FINKPREFIX@/var/run/dbus/pid"`
+ if [ `/bin/ps -p "${PID}" 2>/dev/null | grep -c "^ *${PID} "` -eq 0 ]; then
+ rm -f "@FINKPREFIX@/var/run/dbus/pid"
+ exec "@FINKPREFIX@/bin/dbus-daemon" --system
+ fi
+else
+ exec "@FINKPREFIX@/bin/dbus-daemon" --system
+fi
+
+exit 0
diff -Nurd dbus-1.2.16/test/name-test/Makefile.am dbus-1.2.16-new/test/name-test/Makefile.am
--- dbus-1.2.16/test/name-test/Makefile.am 2009-07-14 15:38:42.000000000 -0400
+++ dbus-1.2.16-new/test/name-test/Makefile.am 2009-09-05 08:56:49.000000000 -0400
@@ -16,7 +16,7 @@
## we use noinst_PROGRAMS not check_PROGRAMS for TESTS so that we
## build even when not doing "make check"
-noinst_PROGRAMS=test-names test-pending-call-dispatch test-pending-call-timeout test-threads-init test-ids test-shutdown test-privserver test-privserver-client
+noinst_PROGRAMS=test-names test-pending-call-dispatch test-pending-call-timeout test-threads-init test-ids test-shutdown test-privserver test-privserver-client test-autolaunch
test_names_SOURCES= \
test-names.c
@@ -69,4 +69,11 @@
test_privserver_client_LDADD=$(top_builddir)/dbus/libdbus-convenience.la ../libdbus-testutils.la $(DBUS_TEST_LIBS)
test_privserver_client_LDFLAGS=@R_DYNAMIC_LDFLAG@
+test_autolaunch_SOURCES = \
+ test-autolaunch.c
+
+test_autolaunch_CFLAGS=
+test_autolaunch_LDADD=$(top_builddir)/dbus/libdbus-convenience.la ../libdbus-testutils.la $(DBUS_TEST_LIBS)
+test_autolaunch_LDFLAGS=@R_DYNAMIC_LDFLAG@
+
endif
diff -Nurd dbus-1.2.16/test/name-test/run-test.sh dbus-1.2.16-new/test/name-test/run-test.sh
--- dbus-1.2.16/test/name-test/run-test.sh 2009-07-14 15:38:42.000000000 -0400
+++ dbus-1.2.16-new/test/name-test/run-test.sh 2009-09-05 08:56:49.000000000 -0400
@@ -50,3 +50,6 @@
echo "running test-shutdown"
${DBUS_TOP_BUILDDIR}/libtool --mode=execute $DEBUG $DBUS_TOP_BUILDDIR/test/name-test/test-shutdown || die "test-shutdown failed"
+
+echo "running test-autolaunch"
+${DBUS_TOP_BUILDDIR}/libtool --mode=execute $DEBUG $DBUS_TOP_BUILDDIR/test/name-test/test-autolaunch || die "test-autolaunch failed"
diff -Nurd dbus-1.2.16/test/name-test/test-autolaunch.c dbus-1.2.16-new/test/name-test/test-autolaunch.c
--- dbus-1.2.16/test/name-test/test-autolaunch.c 1969-12-31 19:00:00.000000000 -0500
+++ dbus-1.2.16-new/test/name-test/test-autolaunch.c 2009-09-05 08:56:49.000000000 -0400
@@ -0,0 +1,31 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#include <dbus/dbus.h>
+#include "dbus/dbus-sysdeps.h"
+
+int
+main (int argc, char *argv[])
+{
+ DBusConnection *conn = NULL;
+ DBusError error;
+
+ _dbus_setenv ("DBUS_SESSION_BUS_ADDRESS", NULL);
+
+ dbus_error_init (&error);
+
+ conn = dbus_bus_get (DBUS_BUS_SESSION, &error);
+ if (dbus_error_is_set (&error))
+ {
+ fprintf (stderr, "*** Failed to autolaunch session bus: %s\n",
+ error.message);
+ dbus_error_free (&error);
+ return 1;
+ }
+
+ return 0;
+}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment