D-Bus
1.6.8
|
00001 /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ 00002 /* dbus-server-unix.c Server implementation for Unix network protocols. 00003 * 00004 * Copyright (C) 2002, 2003, 2004 Red Hat Inc. 00005 * 00006 * Licensed under the Academic Free License version 2.1 00007 * 00008 * This program is free software; you can redistribute it and/or modify 00009 * it under the terms of the GNU General Public License as published by 00010 * the Free Software Foundation; either version 2 of the License, or 00011 * (at your option) any later version. 00012 * 00013 * This program is distributed in the hope that it will be useful, 00014 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00015 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00016 * GNU General Public License for more details. 00017 * 00018 * You should have received a copy of the GNU General Public License 00019 * along with this program; if not, write to the Free Software 00020 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 00021 * 00022 */ 00023 00024 #include <config.h> 00025 #include "dbus-internals.h" 00026 #include "dbus-server-unix.h" 00027 #include "dbus-server-socket.h" 00028 #include "dbus-server-launchd.h" 00029 #include "dbus-transport-unix.h" 00030 #include "dbus-connection-internal.h" 00031 #include "dbus-sysdeps-unix.h" 00032 #include "dbus-string.h" 00033 00053 DBusServerListenResult 00054 _dbus_server_listen_platform_specific (DBusAddressEntry *entry, 00055 DBusServer **server_p, 00056 DBusError *error) 00057 { 00058 const char *method; 00059 00060 *server_p = NULL; 00061 00062 method = dbus_address_entry_get_method (entry); 00063 00064 if (strcmp (method, "unix") == 0) 00065 { 00066 const char *path = dbus_address_entry_get_value (entry, "path"); 00067 const char *tmpdir = dbus_address_entry_get_value (entry, "tmpdir"); 00068 const char *abstract = dbus_address_entry_get_value (entry, "abstract"); 00069 00070 if (path == NULL && tmpdir == NULL && abstract == NULL) 00071 { 00072 _dbus_set_bad_address(error, "unix", 00073 "path or tmpdir or abstract", 00074 NULL); 00075 return DBUS_SERVER_LISTEN_BAD_ADDRESS; 00076 } 00077 00078 if ((path && tmpdir) || 00079 (path && abstract) || 00080 (tmpdir && abstract)) 00081 { 00082 _dbus_set_bad_address(error, NULL, NULL, 00083 "cannot specify two of \"path\" and \"tmpdir\" and \"abstract\" at the same time"); 00084 return DBUS_SERVER_LISTEN_BAD_ADDRESS; 00085 } 00086 00087 if (tmpdir != NULL) 00088 { 00089 DBusString full_path; 00090 DBusString filename; 00091 00092 if (!_dbus_string_init (&full_path)) 00093 { 00094 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); 00095 return DBUS_SERVER_LISTEN_DID_NOT_CONNECT; 00096 } 00097 00098 if (!_dbus_string_init (&filename)) 00099 { 00100 _dbus_string_free (&full_path); 00101 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); 00102 return DBUS_SERVER_LISTEN_DID_NOT_CONNECT; 00103 } 00104 00105 if (!_dbus_string_append (&filename, 00106 "dbus-") || 00107 !_dbus_generate_random_ascii (&filename, 10) || 00108 !_dbus_string_append (&full_path, tmpdir) || 00109 !_dbus_concat_dir_and_file (&full_path, &filename)) 00110 { 00111 _dbus_string_free (&full_path); 00112 _dbus_string_free (&filename); 00113 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); 00114 return DBUS_SERVER_LISTEN_DID_NOT_CONNECT; 00115 } 00116 00117 /* Always use abstract namespace if possible with tmpdir */ 00118 00119 *server_p = 00120 _dbus_server_new_for_domain_socket (_dbus_string_get_const_data (&full_path), 00121 #ifdef HAVE_ABSTRACT_SOCKETS 00122 TRUE, 00123 #else 00124 FALSE, 00125 #endif 00126 error); 00127 00128 _dbus_string_free (&full_path); 00129 _dbus_string_free (&filename); 00130 } 00131 else 00132 { 00133 if (path) 00134 *server_p = _dbus_server_new_for_domain_socket (path, FALSE, error); 00135 else 00136 *server_p = _dbus_server_new_for_domain_socket (abstract, TRUE, error); 00137 } 00138 00139 if (*server_p != NULL) 00140 { 00141 _DBUS_ASSERT_ERROR_IS_CLEAR(error); 00142 return DBUS_SERVER_LISTEN_OK; 00143 } 00144 else 00145 { 00146 _DBUS_ASSERT_ERROR_IS_SET(error); 00147 return DBUS_SERVER_LISTEN_DID_NOT_CONNECT; 00148 } 00149 } 00150 else if (strcmp (method, "systemd") == 0) 00151 { 00152 int n, *fds; 00153 DBusString address; 00154 00155 n = _dbus_listen_systemd_sockets (&fds, error); 00156 if (n < 0) 00157 { 00158 _DBUS_ASSERT_ERROR_IS_SET (error); 00159 return DBUS_SERVER_LISTEN_DID_NOT_CONNECT; 00160 } 00161 00162 _dbus_string_init_const (&address, "systemd:"); 00163 00164 *server_p = _dbus_server_new_for_socket (fds, n, &address, NULL); 00165 if (*server_p == NULL) 00166 { 00167 int i; 00168 00169 for (i = 0; i < n; i++) 00170 { 00171 _dbus_close_socket (fds[i], NULL); 00172 } 00173 dbus_free (fds); 00174 00175 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); 00176 return DBUS_SERVER_LISTEN_DID_NOT_CONNECT; 00177 } 00178 00179 dbus_free (fds); 00180 00181 return DBUS_SERVER_LISTEN_OK; 00182 } 00183 #ifdef DBUS_ENABLE_LAUNCHD 00184 else if (strcmp (method, "launchd") == 0) 00185 { 00186 const char *launchd_env_var = dbus_address_entry_get_value (entry, "env"); 00187 if (launchd_env_var == NULL) 00188 { 00189 _dbus_set_bad_address (error, "launchd", "env", NULL); 00190 return DBUS_SERVER_LISTEN_DID_NOT_CONNECT; 00191 } 00192 *server_p = _dbus_server_new_for_launchd (launchd_env_var, error); 00193 00194 if (*server_p != NULL) 00195 { 00196 _DBUS_ASSERT_ERROR_IS_CLEAR(error); 00197 return DBUS_SERVER_LISTEN_OK; 00198 } 00199 else 00200 { 00201 _DBUS_ASSERT_ERROR_IS_SET(error); 00202 return DBUS_SERVER_LISTEN_DID_NOT_CONNECT; 00203 } 00204 } 00205 #endif 00206 else 00207 { 00208 /* If we don't handle the method, we return NULL with the 00209 * error unset 00210 */ 00211 _DBUS_ASSERT_ERROR_IS_CLEAR(error); 00212 return DBUS_SERVER_LISTEN_NOT_HANDLED; 00213 } 00214 } 00215 00224 DBusServer* 00225 _dbus_server_new_for_domain_socket (const char *path, 00226 dbus_bool_t abstract, 00227 DBusError *error) 00228 { 00229 DBusServer *server; 00230 int listen_fd; 00231 DBusString address; 00232 char *path_copy; 00233 DBusString path_str; 00234 00235 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 00236 00237 if (!_dbus_string_init (&address)) 00238 { 00239 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); 00240 return NULL; 00241 } 00242 00243 _dbus_string_init_const (&path_str, path); 00244 if ((abstract && 00245 !_dbus_string_append (&address, "unix:abstract=")) || 00246 (!abstract && 00247 !_dbus_string_append (&address, "unix:path=")) || 00248 !_dbus_address_append_escaped (&address, &path_str)) 00249 { 00250 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); 00251 goto failed_0; 00252 } 00253 00254 if (abstract) 00255 { 00256 path_copy = NULL; 00257 } 00258 else 00259 { 00260 path_copy = _dbus_strdup (path); 00261 if (path_copy == NULL) 00262 { 00263 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); 00264 goto failed_0; 00265 } 00266 } 00267 00268 listen_fd = _dbus_listen_unix_socket (path, abstract, error); 00269 00270 if (listen_fd < 0) 00271 { 00272 _DBUS_ASSERT_ERROR_IS_SET (error); 00273 goto failed_1; 00274 } 00275 00276 server = _dbus_server_new_for_socket (&listen_fd, 1, &address, 0); 00277 if (server == NULL) 00278 { 00279 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); 00280 goto failed_2; 00281 } 00282 00283 if (path_copy != NULL) 00284 _dbus_server_socket_own_filename(server, path_copy); 00285 00286 _dbus_string_free (&address); 00287 00288 return server; 00289 00290 failed_2: 00291 _dbus_close_socket (listen_fd, NULL); 00292 failed_1: 00293 dbus_free (path_copy); 00294 failed_0: 00295 _dbus_string_free (&address); 00296 00297 return NULL; 00298 } 00299