00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include <config.h>
00025
00026 #include <stdio.h>
00027
00028 #include "dbus-internals.h"
00029 #include "dbus-connection-internal.h"
00030 #include "dbus-transport-unix.h"
00031 #include "dbus-transport-socket.h"
00032 #include "dbus-transport-protected.h"
00033 #include "dbus-watch.h"
00034 #include "dbus-sysdeps-unix.h"
00035 #include "dbus-test.h"
00036
00057 DBusTransport*
00058 _dbus_transport_new_for_domain_socket (const char *path,
00059 dbus_bool_t abstract,
00060 DBusError *error)
00061 {
00062 DBusSocket fd = DBUS_SOCKET_INIT;
00063 DBusTransport *transport;
00064 DBusString address;
00065
00066 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00067
00068 if (!_dbus_string_init (&address))
00069 {
00070 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
00071 return NULL;
00072 }
00073
00074 if ((abstract &&
00075 !_dbus_string_append (&address, "unix:abstract=")) ||
00076 (!abstract &&
00077 !_dbus_string_append (&address, "unix:path=")) ||
00078 !_dbus_string_append (&address, path))
00079 {
00080 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
00081 goto failed_0;
00082 }
00083
00084 fd.fd = _dbus_connect_unix_socket (path, abstract, error);
00085 if (fd.fd < 0)
00086 {
00087 _DBUS_ASSERT_ERROR_IS_SET (error);
00088 goto failed_0;
00089 }
00090
00091 _dbus_verbose ("Successfully connected to unix socket %s\n",
00092 path);
00093
00094 transport = _dbus_transport_new_for_socket (fd, NULL, &address);
00095 if (transport == NULL)
00096 {
00097 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
00098 goto failed_1;
00099 }
00100
00101 _dbus_string_free (&address);
00102
00103 return transport;
00104
00105 failed_1:
00106 _dbus_close_socket (fd, NULL);
00107 failed_0:
00108 _dbus_string_free (&address);
00109 return NULL;
00110 }
00111
00123 static DBusTransport*
00124 _dbus_transport_new_for_exec (const char *path,
00125 char *const argv[],
00126 DBusError *error)
00127 {
00128 DBusSocket fd = DBUS_SOCKET_INIT;
00129 DBusTransport *transport;
00130 DBusString address;
00131 unsigned i;
00132 char *escaped;
00133
00134 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00135
00136 if (!_dbus_string_init (&address))
00137 {
00138 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
00139 return NULL;
00140 }
00141
00142 escaped = dbus_address_escape_value (path);
00143 if (!escaped)
00144 {
00145 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
00146 goto failed;
00147 }
00148
00149 if (!_dbus_string_append (&address, "unixexec:path=") ||
00150 !_dbus_string_append (&address, escaped))
00151 {
00152 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
00153 dbus_free (escaped);
00154 goto failed;
00155 }
00156
00157 dbus_free (escaped);
00158
00159 if (argv)
00160 {
00161 for (i = 0; argv[i]; i++)
00162 {
00163 dbus_bool_t success;
00164
00165 escaped = dbus_address_escape_value (argv[i]);
00166 if (!escaped)
00167 {
00168 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
00169 goto failed;
00170 }
00171
00172 success = _dbus_string_append_printf (&address, ",argv%u=%s", i, escaped);
00173 dbus_free (escaped);
00174
00175 if (!success)
00176 {
00177 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
00178 goto failed;
00179 }
00180 }
00181 }
00182
00183 fd.fd = _dbus_connect_exec (path, argv, error);
00184 if (fd.fd < 0)
00185 {
00186 _DBUS_ASSERT_ERROR_IS_SET (error);
00187 goto failed;
00188 }
00189
00190 _dbus_verbose ("Successfully connected to process %s\n",
00191 path);
00192
00193 transport = _dbus_transport_new_for_socket (fd, NULL, &address);
00194 if (transport == NULL)
00195 {
00196 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
00197 goto failed;
00198 }
00199
00200 _dbus_string_free (&address);
00201
00202 return transport;
00203
00204 failed:
00205 if (fd.fd >= 0)
00206 _dbus_close_socket (fd, NULL);
00207
00208 _dbus_string_free (&address);
00209 return NULL;
00210 }
00211
00220 DBusTransportOpenResult
00221 _dbus_transport_open_platform_specific (DBusAddressEntry *entry,
00222 DBusTransport **transport_p,
00223 DBusError *error)
00224 {
00225 const char *method;
00226
00227 method = dbus_address_entry_get_method (entry);
00228 _dbus_assert (method != NULL);
00229
00230 if (strcmp (method, "unix") == 0)
00231 {
00232 const char *path = dbus_address_entry_get_value (entry, "path");
00233 const char *tmpdir = dbus_address_entry_get_value (entry, "tmpdir");
00234 const char *abstract = dbus_address_entry_get_value (entry, "abstract");
00235
00236 if (tmpdir != NULL)
00237 {
00238 _dbus_set_bad_address (error, NULL, NULL,
00239 "cannot use the \"tmpdir\" option for an address to connect to, only in an address to listen on");
00240 return DBUS_TRANSPORT_OPEN_BAD_ADDRESS;
00241 }
00242
00243 if (path == NULL && abstract == NULL)
00244 {
00245 _dbus_set_bad_address (error, "unix",
00246 "path or abstract",
00247 NULL);
00248 return DBUS_TRANSPORT_OPEN_BAD_ADDRESS;
00249 }
00250
00251 if (path != NULL && abstract != NULL)
00252 {
00253 _dbus_set_bad_address (error, NULL, NULL,
00254 "can't specify both \"path\" and \"abstract\" options in an address");
00255 return DBUS_TRANSPORT_OPEN_BAD_ADDRESS;
00256 }
00257
00258 if (path)
00259 *transport_p = _dbus_transport_new_for_domain_socket (path, FALSE,
00260 error);
00261 else
00262 *transport_p = _dbus_transport_new_for_domain_socket (abstract, TRUE,
00263 error);
00264 if (*transport_p == NULL)
00265 {
00266 _DBUS_ASSERT_ERROR_IS_SET (error);
00267 return DBUS_TRANSPORT_OPEN_DID_NOT_CONNECT;
00268 }
00269 else
00270 {
00271 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00272 return DBUS_TRANSPORT_OPEN_OK;
00273 }
00274 }
00275 else if (strcmp (method, "unixexec") == 0)
00276 {
00277 const char *path;
00278 unsigned i;
00279 char **argv;
00280
00281 path = dbus_address_entry_get_value (entry, "path");
00282 if (path == NULL)
00283 {
00284 _dbus_set_bad_address (error, NULL, NULL,
00285 "No process path specified");
00286 return DBUS_TRANSPORT_OPEN_BAD_ADDRESS;
00287 }
00288
00289
00290 for (i = 1; ; i++)
00291 {
00292 char t[4+20+1];
00293
00294 snprintf (t, sizeof(t), "argv%u", i);
00295
00296 if (!dbus_address_entry_get_value (entry, t))
00297 break;
00298 }
00299
00300
00301 argv = dbus_new0 (char*, i+1);
00302 if (!argv)
00303 {
00304 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
00305 return DBUS_TRANSPORT_OPEN_DID_NOT_CONNECT;
00306 }
00307
00308
00309 for (i = 0; ; i++)
00310 {
00311 char t[4+20+1];
00312 const char *p;
00313
00314 snprintf (t, sizeof(t), "argv%u", i);
00315
00316 p = dbus_address_entry_get_value (entry, t);
00317 if (!p)
00318 {
00319 if (i == 0)
00320
00321 p = path;
00322 else
00323 break;
00324 }
00325
00326 argv[i] = _dbus_strdup (p);
00327 if (!argv[i])
00328 {
00329 dbus_free_string_array (argv);
00330 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
00331 return DBUS_TRANSPORT_OPEN_DID_NOT_CONNECT;
00332 }
00333 }
00334
00335 *transport_p = _dbus_transport_new_for_exec (path, argv, error);
00336 dbus_free_string_array (argv);
00337
00338 if (*transport_p == NULL)
00339 {
00340 _DBUS_ASSERT_ERROR_IS_SET (error);
00341 return DBUS_TRANSPORT_OPEN_DID_NOT_CONNECT;
00342 }
00343 else
00344 {
00345 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00346 return DBUS_TRANSPORT_OPEN_OK;
00347 }
00348 }
00349 #ifdef DBUS_ENABLE_LAUNCHD
00350 else if (strcmp (method, "launchd") == 0)
00351 {
00352 DBusError tmp_error = DBUS_ERROR_INIT;
00353 const char *launchd_env_var = dbus_address_entry_get_value (entry, "env");
00354 const char *launchd_socket;
00355 DBusString socket_path;
00356 dbus_bool_t valid_socket;
00357
00358 if (!_dbus_string_init (&socket_path))
00359 {
00360 _DBUS_SET_OOM (error);
00361 return FALSE;
00362 }
00363
00364 if (launchd_env_var == NULL)
00365 {
00366 _dbus_set_bad_address (error, "launchd", "env", NULL);
00367 return DBUS_TRANSPORT_OPEN_BAD_ADDRESS;
00368 }
00369
00370 valid_socket = _dbus_lookup_launchd_socket (&socket_path, launchd_env_var, error);
00371
00372 if (dbus_error_is_set(error))
00373 {
00374 _dbus_string_free(&socket_path);
00375 return DBUS_TRANSPORT_OPEN_DID_NOT_CONNECT;
00376 }
00377
00378 if (!valid_socket)
00379 {
00380 dbus_set_error(&tmp_error, DBUS_ERROR_BAD_ADDRESS,
00381 "launchd's env var %s does not exist", launchd_env_var);
00382 dbus_error_free(error);
00383 dbus_move_error(&tmp_error, error);
00384 return DBUS_TRANSPORT_OPEN_DID_NOT_CONNECT;
00385 }
00386
00387 launchd_socket = _dbus_string_get_const_data(&socket_path);
00388 *transport_p = _dbus_transport_new_for_domain_socket (launchd_socket, FALSE, error);
00389
00390 if (*transport_p == NULL)
00391 {
00392 _DBUS_ASSERT_ERROR_IS_SET (error);
00393 return DBUS_TRANSPORT_OPEN_DID_NOT_CONNECT;
00394 }
00395 else
00396 {
00397 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00398 return DBUS_TRANSPORT_OPEN_OK;
00399 }
00400 }
00401 #endif
00402 else
00403 {
00404 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00405 return DBUS_TRANSPORT_OPEN_NOT_HANDLED;
00406 }
00407 }
00408
00411 #ifdef DBUS_ENABLE_EMBEDDED_TESTS
00412
00413 dbus_bool_t
00414 _dbus_transport_unix_test (void)
00415 {
00416 DBusConnection *c;
00417 DBusError error;
00418 dbus_bool_t ret;
00419 const char *address;
00420
00421 dbus_error_init (&error);
00422
00423 c = dbus_connection_open ("unixexec:argv0=false,argv1=foobar,path=/bin/false", &error);
00424 _dbus_assert (c != NULL);
00425 _dbus_assert (!dbus_error_is_set (&error));
00426
00427 address = _dbus_connection_get_address (c);
00428 _dbus_assert (address != NULL);
00429
00430
00431 ret = strcmp (address, "unixexec:path=/bin/false,argv0=false,argv1=foobar") == 0;
00432
00433 dbus_connection_unref (c);
00434
00435 return ret;
00436 }
00437
00438 #endif