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-server-socket.h"
00044
00045
00046
00047 #endif
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
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