mirror of
https://gitlab.freedesktop.org/dbus/dbus.git
synced 2026-05-05 14:38:10 +02:00
Add launchd implementation.
This commit is contained in:
parent
875891e823
commit
5125fc1654
3 changed files with 329 additions and 0 deletions
186
dbus/dbus-server-launchd.c
Normal file
186
dbus/dbus-server-launchd.c
Normal file
|
|
@ -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
|
||||
}
|
||||
|
||||
/** @} */
|
||||
36
dbus/dbus-server-launchd.h
Normal file
36
dbus/dbus-server-launchd.h
Normal file
|
|
@ -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 */
|
||||
|
|
@ -3314,6 +3314,108 @@ _dbus_read_local_machine_uuid (DBusGUID *machine_id,
|
|||
#define DBUS_UNIX_STANDARD_SESSION_SERVICEDIR "/dbus-1/services"
|
||||
#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
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue