summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBenjamin Reed <rangerrick@befunk.com>2009-07-19 11:45:34 -0400
committerRalf Habacker <ralf.habacker@freenet.de>2010-12-06 21:33:14 +0100
commitf1b9aac417d8fb716d6ed19128fe429e8a41adba (patch)
tree48684c21f9471938e45f4ad2bde37ef593c9c18b
parenteb66c0a9c001ea08793b38470d12611ffaafa436 (diff)
Enable launchd.
This patch enables support for Mac OS X's launch daemon for startup as well as sharing of the DBus session bus environment. It includes a LaunchAgent plist for automatic start of the session bus.
-rw-r--r--README.launchd61
-rw-r--r--bus/Makefile.am8
-rw-r--r--bus/org.freedesktop.dbus-session.plist.in31
-rw-r--r--configure.in42
-rw-r--r--dbus/Makefile.am8
-rw-r--r--dbus/dbus-server-unix.c24
-rw-r--r--dbus/dbus-sysdeps-unix.h4
-rw-r--r--dbus/dbus-transport-unix.c53
8 files changed, 230 insertions, 1 deletions
diff --git a/README.launchd b/README.launchd
new file mode 100644
index 00000000..701e57dd
--- /dev/null
+++ b/README.launchd
@@ -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 --git a/bus/Makefile.am b/bus/Makefile.am
index 17c0df8f..efa8ab5b 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 00000000..ac5a9d45
--- /dev/null
+++ b/bus/org.freedesktop.dbus-session.plist.in
@@ -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 --git a/configure.in b/configure.in
index 98d57009..c4e36a9d 100644
--- a/configure.in
+++ b/configure.in
@@ -137,6 +137,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]))
@@ -146,6 +147,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>],[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]))
@@ -924,6 +926,38 @@ 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 && 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;
@@ -1563,6 +1597,8 @@ AC_SUBST(DBUS_SESSION_SOCKET_DIR)
if test x$dbus_win = xyes; then
DBUS_SESSION_BUS_DEFAULT_ADDRESS="nonce-tcp:"
+elif 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
@@ -1588,6 +1624,7 @@ bus/system.conf
bus/session.conf
bus/messagebus
bus/messagebus-config
+bus/org.freedesktop.dbus-session.plist
bus/rc.messagebus
bus/dbus.service
bus/dbus.socket
@@ -1659,6 +1696,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}
@@ -1674,6 +1712,10 @@ echo "
Session bus services dir: ${EXPANDED_DATADIR}/dbus-1/services
'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 --git a/dbus/Makefile.am b/dbus/Makefile.am
index f88c7b7a..8d698ca3 100644
--- a/dbus/Makefile.am
+++ b/dbus/Makefile.am
@@ -73,6 +73,13 @@ DBUS_UTIL_arch_sources = \
dbus-sysdeps-util-win.c \
dbus-spawn-win.c
else
+
+if DBUS_ENABLE_LAUNCHD
+launchd_source = dbus-server-launchd.h dbus-server-launchd.c
+else
+launchd_source =
+endif
+
DBUS_LIB_arch_sources = \
dbus-uuidgen.c \
dbus-uuidgen.h \
@@ -80,6 +87,7 @@ DBUS_LIB_arch_sources = \
dbus-server-unix.h
DBUS_SHARED_arch_sources = \
+ $(launchd_source) \
dbus-file-unix.c \
dbus-pipe-unix.c \
dbus-sysdeps-unix.c \
diff --git a/dbus/dbus-server-unix.c b/dbus/dbus-server-unix.c
index 3e5ad6c1..70ad9654 100644
--- a/dbus/dbus-server-unix.c
+++ b/dbus/dbus-server-unix.c
@@ -25,6 +25,7 @@
#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"
@@ -178,7 +179,30 @@ _dbus_server_listen_platform_specific (DBusAddressEntry *entry,
dbus_free (fds);
return DBUS_SERVER_LISTEN_OK;
+ }
+#ifdef DBUS_ENABLE_LAUNCHD
+ 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;
+ }
}
+#endif
else
{
/* If we don't handle the method, we return NULL with the
diff --git a/dbus/dbus-sysdeps-unix.h b/dbus/dbus-sysdeps-unix.h
index 807d2cf5..d7022b07 100644
--- a/dbus/dbus-sysdeps-unix.h
+++ b/dbus/dbus-sysdeps-unix.h
@@ -81,6 +81,10 @@ dbus_bool_t _dbus_read_credentials (int client_fd,
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 --git a/dbus/dbus-transport-unix.c b/dbus/dbus-transport-unix.c
index 6a713d10..a47756f2 100644
--- a/dbus/dbus-transport-unix.c
+++ b/dbus/dbus-transport-unix.c
@@ -170,6 +170,59 @@ _dbus_transport_open_platform_specific (DBusAddressEntry *entry,
return DBUS_TRANSPORT_OPEN_OK;
}
}
+#ifdef DBUS_ENABLE_LAUNCHD
+ 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;
+ }
+ }
+#endif
else
{
_DBUS_ASSERT_ERROR_IS_CLEAR (error);