diff options
author | Benjamin Reed <rangerrick@befunk.com> | 2009-07-19 11:45:34 -0400 |
---|---|---|
committer | Ralf Habacker <ralf.habacker@freenet.de> | 2010-12-06 21:33:14 +0100 |
commit | f1b9aac417d8fb716d6ed19128fe429e8a41adba (patch) | |
tree | 48684c21f9471938e45f4ad2bde37ef593c9c18b | |
parent | eb66c0a9c001ea08793b38470d12611ffaafa436 (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.launchd | 61 | ||||
-rw-r--r-- | bus/Makefile.am | 8 | ||||
-rw-r--r-- | bus/org.freedesktop.dbus-session.plist.in | 31 | ||||
-rw-r--r-- | configure.in | 42 | ||||
-rw-r--r-- | dbus/Makefile.am | 8 | ||||
-rw-r--r-- | dbus/dbus-server-unix.c | 24 | ||||
-rw-r--r-- | dbus/dbus-sysdeps-unix.h | 4 | ||||
-rw-r--r-- | dbus/dbus-transport-unix.c | 53 |
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); |