summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBenjamin Reed <rangerrick@befunk.com>2009-07-19 11:44:50 -0400
committerRalf Habacker <ralf.habacker@freenet.de>2010-12-06 21:33:06 +0100
commit5125fc165454e81849a5b20c1e75b4f74bdbcd2c (patch)
tree4433fcde04dc634e018d66b4666c064be1db0e22
parent875891e8239ffad736f42b01564680a18ec8f453 (diff)
Add launchd implementation.
-rw-r--r--dbus/dbus-server-launchd.c186
-rw-r--r--dbus/dbus-server-launchd.h36
-rw-r--r--dbus/dbus-sysdeps-unix.c107
3 files changed, 329 insertions, 0 deletions
diff --git a/dbus/dbus-server-launchd.c b/dbus/dbus-server-launchd.c
new file mode 100644
index 00000000..83d384df
--- /dev/null
+++ b/dbus/dbus-server-launchd.c
@@ -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, 0);
+ 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 --git a/dbus/dbus-server-launchd.h b/dbus/dbus-server-launchd.h
new file mode 100644
index 00000000..269b9143
--- /dev/null
+++ b/dbus/dbus-server-launchd.h
@@ -0,0 +1,36 @@
+/* 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 --git a/dbus/dbus-sysdeps-unix.c b/dbus/dbus-sysdeps-unix.c
index 23d4aa74..97a6a4a3 100644
--- a/dbus/dbus-sysdeps-unix.c
+++ b/dbus/dbus-sysdeps-unix.c
@@ -3315,6 +3315,108 @@ _dbus_read_local_machine_uuid (DBusGUID *machine_id,
#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;
+ }
+
+ /* 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)
+{
+#ifdef DBUS_ENABLE_LAUNCHD
+ 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_LAUNCHD_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;
+#else
+ dbus_set_error(error, DBUS_ERROR_NOT_SUPPORTED,
+ "can't lookup session address from launchd; launchd support not compiled in");
+ return FALSE;
+#endif
+}
+
+/**
* Determines the address of the session bus by querying a
* platform-specific method.
*
@@ -3338,12 +3440,17 @@ _dbus_lookup_session_address (dbus_bool_t *supported,
DBusString *address,
DBusError *error)
{
+#ifdef DBUS_ENABLE_LAUNCHD
+ *supported = TRUE;
+ return _dbus_lookup_session_address_launchd (address, error);
+#else
/* On non-Mac Unix platforms, if the session address isn't already
* set in DBUS_SESSION_BUS_ADDRESS environment variable, we punt and
* fall back to the autolaunch: global default; see
* init_session_address in dbus/dbus-bus.c. */
*supported = FALSE;
return TRUE;
+#endif
}
/**