diff -Nurd dbus-1.2.24/README.launchd dbus-1.2.24-new/README.launchd --- dbus-1.2.24/README.launchd 1969-12-31 19:00:00.000000000 -0500 +++ dbus-1.2.24-new/README.launchd 2010-11-24 09:39:17.000000000 -0500 @@ -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 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.24/bus/Makefile.am dbus-1.2.24-new/bus/Makefile.am --- dbus-1.2.24/bus/Makefile.am 2010-03-23 15:01:27.000000000 -0400 +++ dbus-1.2.24-new/bus/Makefile.am 2010-11-24 09:39:17.000000000 -0500 @@ -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 @@ -192,12 +198,13 @@ $(mkinstalldirs) $(DESTDIR)$(datadir)/dbus-1/system-services $(mkinstalldirs) $(DESTDIR)$(libexecdir)/dbus-1 $(INSTALL_PROGRAM) dbus-daemon-launch-helper $(DESTDIR)$(libexecdir) - if test `id -u` -eq 0; then \ + if false; then \ chown root:$(DBUS_USER) $(DESTDIR)$(libexecdir)/dbus-daemon-launch-helper; \ chmod 4750 $(DESTDIR)$(libexecdir)/dbus-daemon-launch-helper; \ else \ echo "Not installing $(DESTDIR)$(libexecdir)/dbus-daemon-launch-helper binary setuid!"; \ echo "You'll need to manually set permissions to root:$(DBUS_USER) and permissions 4750"; \ + echo "The PostInst of this fink package will do it automatically"; \ fi #### Init scripts fun diff -Nurd dbus-1.2.24/bus/org.freedesktop.dbus-session.plist.in dbus-1.2.24-new/bus/org.freedesktop.dbus-session.plist.in --- dbus-1.2.24/bus/org.freedesktop.dbus-session.plist.in 1969-12-31 19:00:00.000000000 -0500 +++ dbus-1.2.24-new/bus/org.freedesktop.dbus-session.plist.in 2010-11-24 09:39:17.000000000 -0500 @@ -0,0 +1,31 @@ + + + + + Label + org.freedesktop.dbus-session + + ServiceIPC + + + + OnDemand + + + ProgramArguments + + @DBUS_DAEMONDIR@/dbus-daemon + --nofork + --session + + + Sockets + + unix_domain_listener + + SecureSocketWithKey + DBUS_LAUNCHD_SESSION_BUS_SOCKET + + + + diff -Nurd dbus-1.2.24/bus/session.conf.in dbus-1.2.24-new/bus/session.conf.in --- dbus-1.2.24/bus/session.conf.in 2010-03-23 15:01:27.000000000 -0400 +++ dbus-1.2.24-new/bus/session.conf.in 2010-11-24 09:39:17.000000000 -0500 @@ -12,7 +12,7 @@ the behavior of child processes. --> - unix:tmpdir=@DBUS_SESSION_SOCKET_DIR@ + @DBUS_SESSION_BUS_DEFAULT_ADDRESS@ diff -Nurd dbus-1.2.24/configure.in dbus-1.2.24-new/configure.in --- dbus-1.2.24/configure.in 2010-03-23 15:10:49.000000000 -0400 +++ dbus-1.2.24-new/configure.in 2010-11-24 09:39:17.000000000 -0500 @@ -80,6 +80,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])) @@ -89,6 +90,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 for running the DBUS daemon (messagebus)])) AC_ARG_WITH(dbus_daemondir, AS_HELP_STRING([--with-dbus-daemondir=[dirname]],[Directory for installing the DBUS daemon])) @@ -868,6 +870,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; @@ -1313,6 +1347,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 @@ -1437,7 +1479,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]) @@ -1459,6 +1500,7 @@ bus/system.conf bus/session.conf bus/messagebus +bus/org.freedesktop.dbus-session.plist bus/rc.messagebus bus/dbus-daemon.1 Makefile @@ -1527,6 +1569,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} @@ -1540,8 +1583,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.24/dbus/Makefile.am dbus-1.2.24-new/dbus/Makefile.am --- dbus-1.2.24/dbus/Makefile.am 2010-03-23 15:01:27.000000000 -0400 +++ dbus-1.2.24-new/dbus/Makefile.am 2010-11-24 09:39:17.000000000 -0500 @@ -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.24/dbus/dbus-server-launchd.c dbus-1.2.24-new/dbus/dbus-server-launchd.c --- dbus-1.2.24/dbus/dbus-server-launchd.c 1969-12-31 19:00:00.000000000 -0500 +++ dbus-1.2.24-new/dbus/dbus-server-launchd.c 2010-11-24 09:39:17.000000000 -0500 @@ -0,0 +1,186 @@ +/* dbus-server-launchd.c Server methods for interacting with launchd. + * Copyright (C) 2007, Tanner Lovelace + * Copyright (C) 2008, Colin Walters + * Copyright (C) 2008-2009, Benjamin Reed + * Copyright (C) 2009, Jonas Bähr + * + * 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 "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 +#include + +#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.24/dbus/dbus-server-launchd.h dbus-1.2.24-new/dbus/dbus-server-launchd.h --- dbus-1.2.24/dbus/dbus-server-launchd.h 1969-12-31 19:00:00.000000000 -0500 +++ dbus-1.2.24-new/dbus/dbus-server-launchd.h 2010-11-24 09:39:17.000000000 -0500 @@ -0,0 +1,35 @@ +/* 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 (const char *launchd_env_var, DBusError * error); + +DBUS_END_DECLS +#endif /* DBUS_SERVER_LAUNCHD_H */ diff -Nurd dbus-1.2.24/dbus/dbus-server-unix.c dbus-1.2.24-new/dbus/dbus-server-unix.c --- dbus-1.2.24/dbus/dbus-server-unix.c 2010-03-23 15:01:27.000000000 -0400 +++ dbus-1.2.24-new/dbus/dbus-server-unix.c 2010-11-24 09:39:17.000000000 -0500 @@ -21,9 +21,11 @@ * */ +#include #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.24/dbus/dbus-spawn.c dbus-1.2.24-new/dbus/dbus-spawn.c --- dbus-1.2.24/dbus/dbus-spawn.c 2010-03-23 15:01:27.000000000 -0400 +++ dbus-1.2.24-new/dbus/dbus-spawn.c 2010-11-24 09:39:17.000000000 -0500 @@ -36,6 +36,11 @@ #include #endif +#ifdef DBUS_ENABLE_LAUNCHD +static int _launchd_allocated = 0; /* environ is, or is not, allocated */ +#include +#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.24/dbus/dbus-sysdeps-unix.c dbus-1.2.24-new/dbus/dbus-sysdeps-unix.c --- dbus-1.2.24/dbus/dbus-sysdeps-unix.c 2010-03-23 15:01:27.000000000 -0400 +++ dbus-1.2.24-new/dbus/dbus-sysdeps-unix.c 2010-11-24 09:39:17.000000000 -0500 @@ -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 @@ -3179,6 +3179,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.finkproject.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. * @@ -3202,12 +3300,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.24/dbus/dbus-sysdeps-unix.h dbus-1.2.24-new/dbus/dbus-sysdeps-unix.h --- dbus-1.2.24/dbus/dbus-sysdeps-unix.h 2010-03-23 15:01:27.000000000 -0400 +++ dbus-1.2.24-new/dbus/dbus-sysdeps-unix.h 2010-11-24 09:39:17.000000000 -0500 @@ -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.24/dbus/dbus-transport-unix.c dbus-1.2.24-new/dbus/dbus-transport-unix.c --- dbus-1.2.24/dbus/dbus-transport-unix.c 2010-03-23 15:01:27.000000000 -0400 +++ dbus-1.2.24-new/dbus/dbus-transport-unix.c 2010-11-24 09:39:17.000000000 -0500 @@ -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.24/dbus-xinitrc.sh dbus-1.2.24-new/dbus-xinitrc.sh --- dbus-1.2.24/dbus-xinitrc.sh 1969-12-31 19:00:00.000000000 -0500 +++ dbus-1.2.24-new/dbus-xinitrc.sh 2010-11-24 09:39:17.000000000 -0500 @@ -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.24/start-session-bus.sh dbus-1.2.24-new/start-session-bus.sh --- dbus-1.2.24/start-session-bus.sh 1969-12-31 19:00:00.000000000 -0500 +++ dbus-1.2.24-new/start-session-bus.sh 2010-11-24 09:39:17.000000000 -0500 @@ -0,0 +1,7 @@ +#!/bin/sh -e + +if [ `TMPDIR=/tmp launchctl list 2>/dev/null | grep -c org.finkproject.dbus-session` -eq 0 ]; then + TMPDIR=/tmp launchctl load "@FINKPREFIX@/share/dbus/launchd/org.finkproject.dbus-session.plist" +fi + +exit 0 diff -Nurd dbus-1.2.24/start-system-bus.sh dbus-1.2.24-new/start-system-bus.sh --- dbus-1.2.24/start-system-bus.sh 1969-12-31 19:00:00.000000000 -0500 +++ dbus-1.2.24-new/start-system-bus.sh 2010-11-24 09:39:17.000000000 -0500 @@ -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.24/test/name-test/Makefile.am dbus-1.2.24-new/test/name-test/Makefile.am --- dbus-1.2.24/test/name-test/Makefile.am 2010-03-23 15:01:17.000000000 -0400 +++ dbus-1.2.24-new/test/name-test/Makefile.am 2010-11-24 09:39:17.000000000 -0500 @@ -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-pending-call-dispatch test-pending-call-timeout test-threads-init test-ids test-shutdown test-privserver test-privserver-client +noinst_PROGRAMS=test-pending-call-dispatch test-pending-call-timeout test-threads-init test-ids test-shutdown test-privserver test-privserver-client test-autolaunch test_pending_call_dispatch_SOURCES = \ test-pending-call-dispatch.c @@ -63,4 +63,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.24/test/name-test/run-test.sh dbus-1.2.24-new/test/name-test/run-test.sh --- dbus-1.2.24/test/name-test/run-test.sh 2010-03-23 15:01:17.000000000 -0400 +++ dbus-1.2.24-new/test/name-test/run-test.sh 2010-11-24 09:39:17.000000000 -0500 @@ -50,6 +50,9 @@ echo "running test activation forking" if ! python $DBUS_TOP_SRCDIR/test/name-test/test-activation-forking.py; then + +echo "running test-autolaunch" +${DBUS_TOP_BUILDDIR}/libtool --mode=execute $DEBUG $DBUS_TOP_BUILDDIR/test/name-test/test-autolaunch || die "test-autolaunch failed" echo "Failed test-activation-forking" exit 1 fi diff -Nurd dbus-1.2.24/test/name-test/test-autolaunch.c dbus-1.2.24-new/test/name-test/test-autolaunch.c --- dbus-1.2.24/test/name-test/test-autolaunch.c 1969-12-31 19:00:00.000000000 -0500 +++ dbus-1.2.24-new/test/name-test/test-autolaunch.c 2010-11-24 09:39:17.000000000 -0500 @@ -0,0 +1,31 @@ +#include +#include +#include +#ifdef HAVE_UNISTD_H +#include +#endif + +#include +#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; +}