D-Bus 1.4.20
|
00001 /* dbus-server-launchd.c Server methods for interacting with launchd. 00002 * Copyright (C) 2007, Tanner Lovelace <lovelace@wayfarer.org> 00003 * Copyright (C) 2008, Colin Walters <walters@verbum.org> 00004 * Copyright (C) 2008-2009, Benjamin Reed <rangerrick@befunk.com> 00005 * Copyright (C) 2009, Jonas Bähr <jonas.baehr@web.de> 00006 * 00007 * Permission is hereby granted, free of charge, to any person 00008 * obtaining a copy of this software and associated documentation 00009 * files (the "Software"), to deal in the Software without 00010 * restriction, including without limitation the rights to use, copy, 00011 * modify, merge, publish, distribute, sublicense, and/or sell copies 00012 * of the Software, and to permit persons to whom the Software is 00013 * furnished to do so, subject to the following conditions: 00014 * 00015 * The above copyright notice and this permission notice shall be 00016 * included in all copies or substantial portions of the Software. 00017 * 00018 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 00019 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 00020 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 00021 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 00022 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 00023 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 00024 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 00025 * DEALINGS IN THE SOFTWARE. 00026 */ 00027 00028 #include <config.h> 00029 #include "dbus-server-launchd.h" 00030 00039 #ifdef DBUS_ENABLE_LAUNCHD 00040 #include <launch.h> 00041 #include <errno.h> 00042 00043 #include "dbus-server-socket.h" 00044 00045 /* put other private launchd functions here */ 00046 00047 #endif /* DBUS_ENABLE_LAUNCHD */ 00048 00063 DBusServer * 00064 _dbus_server_new_for_launchd (const char *launchd_env_var, DBusError * error) 00065 { 00066 #ifdef DBUS_ENABLE_LAUNCHD 00067 DBusServer *server; 00068 DBusString address; 00069 int launchd_fd; 00070 launch_data_t sockets_dict, checkin_response; 00071 launch_data_t checkin_request; 00072 launch_data_t listening_fd_array, listening_fd; 00073 launch_data_t environment_dict, environment_param; 00074 const char *launchd_socket_path, *display; 00075 00076 launchd_socket_path = _dbus_getenv (launchd_env_var); 00077 display = _dbus_getenv ("DISPLAY"); 00078 00079 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 00080 00081 if (launchd_socket_path == NULL || *launchd_socket_path == '\0') 00082 { 00083 dbus_set_error (error, DBUS_ERROR_BAD_ADDRESS, 00084 "launchd's environment variable %s is empty, but should contain a socket path.\n", launchd_env_var); 00085 return NULL; 00086 } 00087 00088 if (!_dbus_string_init (&address)) 00089 { 00090 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); 00091 return NULL; 00092 } 00093 if (!_dbus_string_append (&address, "unix:path=")) 00094 { 00095 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); 00096 goto l_failed_0; 00097 } 00098 if (!_dbus_string_append (&address, launchd_socket_path)) 00099 { 00100 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); 00101 goto l_failed_0; 00102 } 00103 00104 if ((checkin_request = launch_data_new_string (LAUNCH_KEY_CHECKIN)) == NULL) 00105 { 00106 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, 00107 "launch_data_new_string(\"%s\") Unable to create string.\n", 00108 LAUNCH_KEY_CHECKIN); 00109 goto l_failed_0; 00110 } 00111 00112 if ((checkin_response = launch_msg (checkin_request)) == NULL) 00113 { 00114 dbus_set_error (error, DBUS_ERROR_IO_ERROR, 00115 "launch_msg(\"%s\") IPC failure: %s\n", 00116 LAUNCH_KEY_CHECKIN, strerror (errno)); 00117 goto l_failed_0; 00118 } 00119 00120 if (LAUNCH_DATA_ERRNO == launch_data_get_type (checkin_response)) 00121 { 00122 dbus_set_error (error, DBUS_ERROR_FAILED, "Check-in failed: %s\n", 00123 strerror (launch_data_get_errno (checkin_response))); 00124 goto l_failed_0; 00125 } 00126 00127 sockets_dict = 00128 launch_data_dict_lookup (checkin_response, LAUNCH_JOBKEY_SOCKETS); 00129 if (NULL == sockets_dict) 00130 { 00131 dbus_set_error (error, DBUS_ERROR_IO_ERROR, 00132 "No sockets found to answer requests on!\n"); 00133 goto l_failed_0; 00134 } 00135 00136 listening_fd_array = 00137 launch_data_dict_lookup (sockets_dict, "unix_domain_listener"); 00138 if (NULL == listening_fd_array) 00139 { 00140 dbus_set_error (error, DBUS_ERROR_IO_ERROR, 00141 "No known sockets found to answer requests on!\n"); 00142 goto l_failed_0; 00143 } 00144 00145 if (launch_data_array_get_count (listening_fd_array) != 1) 00146 { 00147 dbus_set_error (error, DBUS_ERROR_LIMITS_EXCEEDED, 00148 "Expected 1 socket from launchd, got %d.\n", 00149 launch_data_array_get_count (listening_fd_array)); 00150 goto l_failed_0; 00151 } 00152 00153 listening_fd = launch_data_array_get_index (listening_fd_array, 0); 00154 launchd_fd = launch_data_get_fd (listening_fd); 00155 00156 _dbus_fd_set_close_on_exec (launchd_fd); 00157 00158 if (launchd_fd < 0) 00159 { 00160 _DBUS_ASSERT_ERROR_IS_SET (error); 00161 goto l_failed_0; 00162 if (display == NULL || *display == '\0') 00163 { 00164 environment_dict = launch_data_dict_lookup (checkin_response, LAUNCH_JOBKEY_USERENVIRONMENTVARIABLES); 00165 if (NULL == environment_dict) 00166 { 00167 _dbus_warn ("Unable to retrieve user environment from launchd."); 00168 } 00169 else 00170 { 00171 environment_param = launch_data_dict_lookup (environment_dict, "DISPLAY"); 00172 if (NULL == environment_param) 00173 { 00174 _dbus_warn ("Unable to retrieve DISPLAY from launchd."); 00175 } 00176 else 00177 { 00178 display = launch_data_get_string(environment_param); 00179 _dbus_setenv ("DISPLAY", display); 00180 } 00181 } 00182 } 00183 00184 } 00185 00186 server = _dbus_server_new_for_socket (&launchd_fd, 1, &address, 0); 00187 if (server == NULL) 00188 { 00189 dbus_set_error (error, DBUS_ERROR_NO_SERVER, 00190 "Unable to listen on launchd fd %d.", launchd_fd); 00191 goto l_failed_0; 00192 } 00193 00194 _dbus_string_free (&address); 00195 00196 return server; 00197 00198 l_failed_0: 00199 _dbus_string_free (&address); 00200 00201 return NULL; 00202 #else /* DBUS_ENABLE_LAUNCHD */ 00203 dbus_set_error (error, DBUS_ERROR_BAD_ADDRESS, 00204 "address type 'launchd' requested, but launchd support not compiled in"); 00205 return NULL; 00206 #endif 00207 } 00208