D-Bus  1.6.12
dbus-server-launchd.c
1 /* dbus-server-launchd.c Server methods for interacting with launchd.
2  * Copyright (C) 2007, Tanner Lovelace <lovelace@wayfarer.org>
3  * Copyright (C) 2008, Colin Walters <walters@verbum.org>
4  * Copyright (C) 2008-2009, Benjamin Reed <rangerrick@befunk.com>
5  * Copyright (C) 2009, Jonas Bähr <jonas.baehr@web.de>
6  *
7  * Permission is hereby granted, free of charge, to any person
8  * obtaining a copy of this software and associated documentation
9  * files (the "Software"), to deal in the Software without
10  * restriction, including without limitation the rights to use, copy,
11  * modify, merge, publish, distribute, sublicense, and/or sell copies
12  * of the Software, and to permit persons to whom the Software is
13  * furnished to do so, subject to the following conditions:
14  *
15  * The above copyright notice and this permission notice shall be
16  * included in all copies or substantial portions of the Software.
17  *
18  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
22  * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
23  * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
25  * DEALINGS IN THE SOFTWARE.
26  */
27 
28 #include <config.h>
29 #include "dbus-server-launchd.h"
30 
39 #ifdef DBUS_ENABLE_LAUNCHD
40 #include <launch.h>
41 #include <errno.h>
42 
43 #include "dbus-server-socket.h"
44 
45 /* put other private launchd functions here */
46 
47 #endif /* DBUS_ENABLE_LAUNCHD */
48 
63 DBusServer *
64 _dbus_server_new_for_launchd (const char *launchd_env_var, DBusError * error)
65  {
66 #ifdef DBUS_ENABLE_LAUNCHD
67  DBusServer *server;
68  DBusString address;
69  int launchd_fd;
70  launch_data_t sockets_dict, checkin_response;
71  launch_data_t checkin_request;
72  launch_data_t listening_fd_array, listening_fd;
73  launch_data_t environment_dict, environment_param;
74  const char *launchd_socket_path, *display;
75 
76  launchd_socket_path = _dbus_getenv (launchd_env_var);
77  display = _dbus_getenv ("DISPLAY");
78 
79  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
80 
81  if (launchd_socket_path == NULL || *launchd_socket_path == '\0')
82  {
84  "launchd's environment variable %s is empty, but should contain a socket path.\n", launchd_env_var);
85  return NULL;
86  }
87 
88  if (!_dbus_string_init (&address))
89  {
91  return NULL;
92  }
93  if (!_dbus_string_append (&address, "unix:path="))
94  {
96  goto l_failed_0;
97  }
98  if (!_dbus_string_append (&address, launchd_socket_path))
99  {
101  goto l_failed_0;
102  }
103 
104  if ((checkin_request = launch_data_new_string (LAUNCH_KEY_CHECKIN)) == NULL)
105  {
107  "launch_data_new_string(\"%s\") Unable to create string.\n",
108  LAUNCH_KEY_CHECKIN);
109  goto l_failed_0;
110  }
111 
112  if ((checkin_response = launch_msg (checkin_request)) == NULL)
113  {
115  "launch_msg(\"%s\") IPC failure: %s\n",
116  LAUNCH_KEY_CHECKIN, strerror (errno));
117  goto l_failed_0;
118  }
119 
120  if (LAUNCH_DATA_ERRNO == launch_data_get_type (checkin_response))
121  {
122  dbus_set_error (error, DBUS_ERROR_FAILED, "Check-in failed: %s\n",
123  strerror (launch_data_get_errno (checkin_response)));
124  goto l_failed_0;
125  }
126 
127  sockets_dict =
128  launch_data_dict_lookup (checkin_response, LAUNCH_JOBKEY_SOCKETS);
129  if (NULL == sockets_dict)
130  {
132  "No sockets found to answer requests on!\n");
133  goto l_failed_0;
134  }
135 
136  listening_fd_array =
137  launch_data_dict_lookup (sockets_dict, "unix_domain_listener");
138  if (NULL == listening_fd_array)
139  {
141  "No known sockets found to answer requests on!\n");
142  goto l_failed_0;
143  }
144 
145  if (launch_data_array_get_count (listening_fd_array) != 1)
146  {
148  "Expected 1 socket from launchd, got %d.\n",
149  launch_data_array_get_count (listening_fd_array));
150  goto l_failed_0;
151  }
152 
153  listening_fd = launch_data_array_get_index (listening_fd_array, 0);
154  launchd_fd = launch_data_get_fd (listening_fd);
155 
156  _dbus_fd_set_close_on_exec (launchd_fd);
157 
158  if (launchd_fd < 0)
159  {
160  _DBUS_ASSERT_ERROR_IS_SET (error);
161  goto l_failed_0;
162  if (display == NULL || *display == '\0')
163  {
164  environment_dict = launch_data_dict_lookup (checkin_response, LAUNCH_JOBKEY_USERENVIRONMENTVARIABLES);
165  if (NULL == environment_dict)
166  {
167  _dbus_warn ("Unable to retrieve user environment from launchd.");
168  }
169  else
170  {
171  environment_param = launch_data_dict_lookup (environment_dict, "DISPLAY");
172  if (NULL == environment_param)
173  {
174  _dbus_warn ("Unable to retrieve DISPLAY from launchd.");
175  }
176  else
177  {
178  display = launch_data_get_string(environment_param);
179  _dbus_setenv ("DISPLAY", display);
180  }
181  }
182  }
183 
184  }
185 
186  server = _dbus_server_new_for_socket (&launchd_fd, 1, &address, 0);
187  if (server == NULL)
188  {
190  "Unable to listen on launchd fd %d.", launchd_fd);
191  goto l_failed_0;
192  }
193 
194  _dbus_string_free (&address);
195 
196  return server;
197 
198  l_failed_0:
199  _dbus_string_free (&address);
200 
201  return NULL;
202 #else /* DBUS_ENABLE_LAUNCHD */
204  "address type 'launchd' requested, but launchd support not compiled in");
205  return NULL;
206 #endif
207  }
208 
dbus_bool_t _dbus_string_append(DBusString *str, const char *buffer)
Appends a nul-terminated C-style string to a DBusString.
Definition: dbus-string.c:913
#define NULL
A null pointer, defined appropriately for C or C++.
DBusServer * _dbus_server_new_for_launchd(const char *launchd_env_var, DBusError *error)
Creates a new server from launchd.
Internals of DBusServer object.
dbus_bool_t _dbus_string_init(DBusString *str)
Initializes a string.
Definition: dbus-string.c:175
#define DBUS_ERROR_IO_ERROR
Something went wrong reading or writing to a socket, for example.
const char * _dbus_getenv(const char *varname)
Wrapper for getenv().
Definition: dbus-sysdeps.c:183
#define DBUS_ERROR_NO_SERVER
Unable to connect to server (probably caused by ECONNREFUSED on a socket).
void _dbus_fd_set_close_on_exec(intptr_t fd)
Sets the file descriptor to be close on exec.
dbus_bool_t _dbus_setenv(const char *varname, const char *value)
Wrapper for setenv().
Definition: dbus-sysdeps.c:112
void _dbus_warn(const char *format,...)
Prints a warning message to stderr.
DBusServer * _dbus_server_new_for_socket(int *fds, int n_fds, const DBusString *address, DBusNonceFile *noncefile)
Creates a new server listening on the given file descriptor.
Object representing an exception.
Definition: dbus-errors.h:48
#define DBUS_ERROR_BAD_ADDRESS
A D-Bus bus address was malformed.
void dbus_set_error(DBusError *error, const char *name, const char *format,...)
Assigns an error name and message to a DBusError.
Definition: dbus-errors.c:354
void _dbus_string_free(DBusString *str)
Frees a string created by _dbus_string_init().
Definition: dbus-string.c:242
#define DBUS_ERROR_FAILED
A generic error; &quot;something went wrong&quot; - see the error message for more.
#define DBUS_ERROR_NO_MEMORY
There was not enough memory to complete an operation.
#define DBUS_ERROR_LIMITS_EXCEEDED
Some limited resource is exhausted.