00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
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-misc.h"
00044 #include "dbus-server-socket.h"
00045 #include "dbus-sysdeps-unix.h"
00046
00047
00048
00049 #endif
00050
00065 DBusServer *
00066 _dbus_server_new_for_launchd (const char *launchd_env_var, DBusError * error)
00067 {
00068 #ifdef DBUS_ENABLE_LAUNCHD
00069 DBusServer *server;
00070 DBusString address;
00071 int launchd_fd;
00072 launch_data_t sockets_dict, checkin_response;
00073 launch_data_t checkin_request;
00074 launch_data_t listening_fd_array, listening_fd;
00075 launch_data_t environment_dict, environment_param;
00076 const char *launchd_socket_path, *display;
00077
00078 launchd_socket_path = _dbus_getenv (launchd_env_var);
00079 display = _dbus_getenv ("DISPLAY");
00080
00081 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00082
00083 if (launchd_socket_path == NULL || *launchd_socket_path == '\0')
00084 {
00085 dbus_set_error (error, DBUS_ERROR_BAD_ADDRESS,
00086 "launchd's environment variable %s is empty, but should contain a socket path.\n", launchd_env_var);
00087 return NULL;
00088 }
00089
00090 if (!_dbus_string_init (&address))
00091 {
00092 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
00093 return NULL;
00094 }
00095 if (!_dbus_string_append (&address, "unix:path="))
00096 {
00097 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
00098 goto l_failed_0;
00099 }
00100 if (!_dbus_string_append (&address, launchd_socket_path))
00101 {
00102 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
00103 goto l_failed_0;
00104 }
00105
00106 if ((checkin_request = launch_data_new_string (LAUNCH_KEY_CHECKIN)) == NULL)
00107 {
00108 dbus_set_error (error, DBUS_ERROR_NO_MEMORY,
00109 "launch_data_new_string(\"%s\") Unable to create string.\n",
00110 LAUNCH_KEY_CHECKIN);
00111 goto l_failed_0;
00112 }
00113
00114 if ((checkin_response = launch_msg (checkin_request)) == NULL)
00115 {
00116 dbus_set_error (error, DBUS_ERROR_IO_ERROR,
00117 "launch_msg(\"%s\") IPC failure: %s\n",
00118 LAUNCH_KEY_CHECKIN, strerror (errno));
00119 goto l_failed_0;
00120 }
00121
00122 if (LAUNCH_DATA_ERRNO == launch_data_get_type (checkin_response))
00123 {
00124 dbus_set_error (error, DBUS_ERROR_FAILED, "Check-in failed: %s\n",
00125 strerror (launch_data_get_errno (checkin_response)));
00126 goto l_failed_0;
00127 }
00128
00129 sockets_dict =
00130 launch_data_dict_lookup (checkin_response, LAUNCH_JOBKEY_SOCKETS);
00131 if (NULL == sockets_dict)
00132 {
00133 dbus_set_error (error, DBUS_ERROR_IO_ERROR,
00134 "No sockets found to answer requests on!\n");
00135 goto l_failed_0;
00136 }
00137
00138 listening_fd_array =
00139 launch_data_dict_lookup (sockets_dict, "unix_domain_listener");
00140 if (NULL == listening_fd_array)
00141 {
00142 dbus_set_error (error, DBUS_ERROR_IO_ERROR,
00143 "No known sockets found to answer requests on!\n");
00144 goto l_failed_0;
00145 }
00146
00147 if (launch_data_array_get_count (listening_fd_array) != 1)
00148 {
00149 dbus_set_error (error, DBUS_ERROR_LIMITS_EXCEEDED,
00150 "Expected 1 socket from launchd, got %d.\n",
00151 launch_data_array_get_count (listening_fd_array));
00152 goto l_failed_0;
00153 }
00154
00155 listening_fd = launch_data_array_get_index (listening_fd_array, 0);
00156 launchd_fd = launch_data_get_fd (listening_fd);
00157
00158 _dbus_fd_set_close_on_exec (launchd_fd);
00159
00160 if (launchd_fd < 0)
00161 {
00162 _DBUS_ASSERT_ERROR_IS_SET (error);
00163 goto l_failed_0;
00164 if (display == NULL || *display == '\0')
00165 {
00166 environment_dict = launch_data_dict_lookup (checkin_response, LAUNCH_JOBKEY_USERENVIRONMENTVARIABLES);
00167 if (NULL == environment_dict)
00168 {
00169 _dbus_warn ("Unable to retrieve user environment from launchd.");
00170 }
00171 else
00172 {
00173 environment_param = launch_data_dict_lookup (environment_dict, "DISPLAY");
00174 if (NULL == environment_param)
00175 {
00176 _dbus_warn ("Unable to retrieve DISPLAY from launchd.");
00177 }
00178 else
00179 {
00180 display = launch_data_get_string(environment_param);
00181 dbus_setenv ("DISPLAY", display);
00182 }
00183 }
00184 }
00185
00186 }
00187
00188 server = _dbus_server_new_for_socket (&launchd_fd, 1, &address, 0, error);
00189 if (server == NULL)
00190 {
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
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