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 #include "dbus-bus.h"
00026 #include "dbus-protocol.h"
00027 #include "dbus-internals.h"
00028 #include <string.h>
00029
00056 typedef struct
00057 {
00058 DBusConnection *connection;
00059 char *base_service;
00061 unsigned int is_well_known : 1;
00062 } BusData;
00063
00066 static dbus_int32_t bus_data_slot = -1;
00067
00069 #define N_BUS_TYPES 3
00070
00071 static DBusConnection *bus_connections[N_BUS_TYPES];
00072 static char *bus_connection_addresses[N_BUS_TYPES] = { NULL, NULL, NULL };
00073
00074 static DBusBusType activation_bus_type = DBUS_BUS_ACTIVATION;
00075
00076 static dbus_bool_t initialized = FALSE;
00077
00081 _DBUS_DEFINE_GLOBAL_LOCK (bus);
00082
00083 static void
00084 addresses_shutdown_func (void *data)
00085 {
00086 int i;
00087
00088 i = 0;
00089 while (i < N_BUS_TYPES)
00090 {
00091 if (bus_connections[i] != NULL)
00092 _dbus_warn ("dbus_shutdown() called but connections were still live!");
00093
00094 dbus_free (bus_connection_addresses[i]);
00095 bus_connection_addresses[i] = NULL;
00096 ++i;
00097 }
00098
00099 activation_bus_type = DBUS_BUS_ACTIVATION;
00100 }
00101
00102 static dbus_bool_t
00103 get_from_env (char **connection_p,
00104 const char *env_var)
00105 {
00106 const char *s;
00107
00108 _dbus_assert (*connection_p == NULL);
00109
00110 s = _dbus_getenv (env_var);
00111 if (s == NULL || *s == '\0')
00112 return TRUE;
00113 else
00114 {
00115 *connection_p = _dbus_strdup (s);
00116 return *connection_p != NULL;
00117 }
00118 }
00119
00120 static dbus_bool_t
00121 init_connections_unlocked (void)
00122 {
00123 if (!initialized)
00124 {
00125 const char *s;
00126 int i;
00127
00128 i = 0;
00129 while (i < N_BUS_TYPES)
00130 {
00131 bus_connections[i] = NULL;
00132 ++i;
00133 }
00134
00135
00136
00137
00138
00139 if (bus_connection_addresses[DBUS_BUS_SYSTEM] == NULL)
00140 {
00141 if (!get_from_env (&bus_connection_addresses[DBUS_BUS_SYSTEM],
00142 "DBUS_SYSTEM_BUS_ADDRESS"))
00143 return FALSE;
00144
00145 if (bus_connection_addresses[DBUS_BUS_SYSTEM] == NULL)
00146 {
00147
00148 bus_connection_addresses[DBUS_BUS_SYSTEM] =
00149 _dbus_strdup (DBUS_SYSTEM_BUS_DEFAULT_ADDRESS);
00150 if (bus_connection_addresses[DBUS_BUS_SYSTEM] == NULL)
00151 return FALSE;
00152 }
00153 }
00154
00155 if (bus_connection_addresses[DBUS_BUS_SESSION] == NULL)
00156 {
00157 if (!get_from_env (&bus_connection_addresses[DBUS_BUS_SESSION],
00158 "DBUS_SESSION_BUS_ADDRESS"))
00159 return FALSE;
00160 }
00161
00162 if (bus_connection_addresses[DBUS_BUS_ACTIVATION] == NULL)
00163 {
00164 if (!get_from_env (&bus_connection_addresses[DBUS_BUS_ACTIVATION],
00165 "DBUS_ACTIVATION_ADDRESS"))
00166 return FALSE;
00167 }
00168
00169 s = _dbus_getenv ("DBUS_ACTIVATION_BUS_TYPE");
00170
00171 if (s != NULL)
00172 {
00173 if (strcmp (s, "system") == 0)
00174 activation_bus_type = DBUS_BUS_SYSTEM;
00175 else if (strcmp (s, "session") == 0)
00176 activation_bus_type = DBUS_BUS_SESSION;
00177 }
00178
00179
00180
00181
00182
00183 if (!_dbus_setenv ("DBUS_ACTIVATION_ADDRESS", NULL))
00184 return FALSE;
00185
00186 if (!_dbus_setenv ("DBUS_ACTIVATION_BUS_TYPE", NULL))
00187 return FALSE;
00188
00189 if (!_dbus_register_shutdown_func (addresses_shutdown_func,
00190 NULL))
00191 return FALSE;
00192
00193 initialized = TRUE;
00194 }
00195
00196 return initialized;
00197 }
00198
00199 static void
00200 bus_data_free (void *data)
00201 {
00202 BusData *bd = data;
00203
00204 if (bd->is_well_known)
00205 {
00206 int i;
00207 _DBUS_LOCK (bus);
00208
00209 i = 0;
00210 while (i < N_BUS_TYPES)
00211 {
00212 if (bus_connections[i] == bd->connection)
00213 bus_connections[i] = NULL;
00214
00215 ++i;
00216 }
00217 _DBUS_UNLOCK (bus);
00218 }
00219
00220 dbus_free (bd->base_service);
00221 dbus_free (bd);
00222
00223 dbus_connection_free_data_slot (&bus_data_slot);
00224 }
00225
00226 static BusData*
00227 ensure_bus_data (DBusConnection *connection)
00228 {
00229 BusData *bd;
00230
00231 if (!dbus_connection_allocate_data_slot (&bus_data_slot))
00232 return NULL;
00233
00234 bd = dbus_connection_get_data (connection, bus_data_slot);
00235 if (bd == NULL)
00236 {
00237 bd = dbus_new0 (BusData, 1);
00238 if (bd == NULL)
00239 {
00240 dbus_connection_free_data_slot (&bus_data_slot);
00241 return NULL;
00242 }
00243
00244 bd->connection = connection;
00245
00246 if (!dbus_connection_set_data (connection, bus_data_slot, bd,
00247 bus_data_free))
00248 {
00249 dbus_free (bd);
00250 dbus_connection_free_data_slot (&bus_data_slot);
00251 return NULL;
00252 }
00253
00254
00255 }
00256 else
00257 {
00258 dbus_connection_free_data_slot (&bus_data_slot);
00259 }
00260
00261 return bd;
00262 }
00263
00265
00281 DBusConnection *
00282 dbus_bus_get (DBusBusType type,
00283 DBusError *error)
00284 {
00285 const char *address;
00286 DBusConnection *connection;
00287 BusData *bd;
00288 DBusBusType address_type;
00289
00290 _dbus_return_val_if_fail (type >= 0 && type < N_BUS_TYPES, NULL);
00291 _dbus_return_val_if_error_is_set (error, NULL);
00292
00293 _DBUS_LOCK (bus);
00294
00295 if (!init_connections_unlocked ())
00296 {
00297 _DBUS_UNLOCK (bus);
00298 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
00299 return NULL;
00300 }
00301
00302
00303
00304
00305
00306 address_type = type;
00307
00308
00309
00310
00311
00312 if (type == DBUS_BUS_ACTIVATION)
00313 type = activation_bus_type;
00314
00315 if (bus_connections[type] != NULL)
00316 {
00317 connection = bus_connections[type];
00318 dbus_connection_ref (connection);
00319
00320 _DBUS_UNLOCK (bus);
00321 return connection;
00322 }
00323
00324 address = bus_connection_addresses[address_type];
00325 if (address == NULL)
00326 {
00327 dbus_set_error (error, DBUS_ERROR_FAILED,
00328 "Unable to determine the address of the message bus");
00329 _DBUS_UNLOCK (bus);
00330 return NULL;
00331 }
00332
00333 connection = dbus_connection_open (address, error);
00334
00335 if (!connection)
00336 {
00337 _DBUS_ASSERT_ERROR_IS_SET (error);
00338 _DBUS_UNLOCK (bus);
00339 return NULL;
00340 }
00341
00342 if (!dbus_bus_register (connection, error))
00343 {
00344 _DBUS_ASSERT_ERROR_IS_SET (error);
00345 dbus_connection_disconnect (connection);
00346 dbus_connection_unref (connection);
00347
00348 _DBUS_UNLOCK (bus);
00349 return NULL;
00350 }
00351
00352 bus_connections[type] = connection;
00353 bd = ensure_bus_data (connection);
00354 _dbus_assert (bd != NULL);
00355
00356 bd->is_well_known = TRUE;
00357
00358 _DBUS_UNLOCK (bus);
00359 return connection;
00360 }
00361
00362
00376 dbus_bool_t
00377 dbus_bus_register (DBusConnection *connection,
00378 DBusError *error)
00379 {
00380 DBusMessage *message, *reply;
00381 char *name;
00382 BusData *bd;
00383 dbus_bool_t retval;
00384
00385 _dbus_return_val_if_fail (connection != NULL, FALSE);
00386 _dbus_return_val_if_error_is_set (error, FALSE);
00387
00388 retval = FALSE;
00389
00390 bd = ensure_bus_data (connection);
00391 if (bd == NULL)
00392 {
00393 _DBUS_SET_OOM (error);
00394 return FALSE;
00395 }
00396
00397 if (bd->base_service != NULL)
00398 {
00399 _dbus_warn ("Attempt to register the same DBusConnection with the message bus, but it is already registered\n");
00400
00401
00402
00403 return TRUE;
00404 }
00405
00406 message = dbus_message_new (DBUS_MESSAGE_HELLO,
00407 DBUS_SERVICE_DBUS);
00408
00409
00410 if (!message)
00411 {
00412 _DBUS_SET_OOM (error);
00413 return FALSE;
00414 }
00415
00416 reply = dbus_connection_send_with_reply_and_block (connection, message, -1, error);
00417
00418 dbus_message_unref (message);
00419
00420 if (reply == NULL)
00421 goto out;
00422 else if (dbus_set_error_from_message (error, reply))
00423 goto out;
00424 else if (!dbus_message_get_args (reply, error,
00425 DBUS_TYPE_STRING, &name,
00426 DBUS_TYPE_INVALID))
00427 goto out;
00428
00429 bd->base_service = name;
00430
00431 retval = TRUE;
00432
00433 out:
00434 if (reply)
00435 dbus_message_unref (reply);
00436
00437 if (!retval)
00438 _DBUS_ASSERT_ERROR_IS_SET (error);
00439
00440 return retval;
00441 }
00442
00443
00455 dbus_bool_t
00456 dbus_bus_set_base_service (DBusConnection *connection,
00457 const char *base_service)
00458 {
00459 BusData *bd;
00460
00461 _dbus_return_val_if_fail (connection != NULL, FALSE);
00462 _dbus_return_val_if_fail (base_service != NULL, FALSE);
00463
00464 bd = ensure_bus_data (connection);
00465 if (bd == NULL)
00466 return FALSE;
00467
00468 _dbus_assert (bd->base_service == NULL);
00469
00470 bd->base_service = _dbus_strdup (base_service);
00471 return bd->base_service != NULL;
00472 }
00473
00482 const char*
00483 dbus_bus_get_base_service (DBusConnection *connection)
00484 {
00485 BusData *bd;
00486
00487 _dbus_return_val_if_fail (connection != NULL, NULL);
00488
00489 bd = ensure_bus_data (connection);
00490 if (bd == NULL)
00491 return NULL;
00492
00493 return bd->base_service;
00494 }
00495
00511 int
00512 dbus_bus_acquire_service (DBusConnection *connection,
00513 const char *service_name,
00514 unsigned int flags,
00515 DBusError *error)
00516 {
00517 DBusMessage *message, *reply;
00518 dbus_uint32_t service_result;
00519
00520 _dbus_return_val_if_fail (connection != NULL, 0);
00521 _dbus_return_val_if_fail (service_name != NULL, 0);
00522 _dbus_return_val_if_error_is_set (error, 0);
00523
00524 message = dbus_message_new (DBUS_MESSAGE_ACQUIRE_SERVICE,
00525 DBUS_SERVICE_DBUS);
00526
00527
00528 if (message == NULL)
00529 {
00530 _DBUS_SET_OOM (error);
00531 return -1;
00532 }
00533
00534 if (!dbus_message_append_args (message,
00535 DBUS_TYPE_STRING, service_name,
00536 DBUS_TYPE_UINT32, flags,
00537 DBUS_TYPE_INVALID))
00538 {
00539 dbus_message_unref (message);
00540 _DBUS_SET_OOM (error);
00541 return -1;
00542 }
00543
00544 reply = dbus_connection_send_with_reply_and_block (connection, message, -1,
00545 error);
00546
00547 dbus_message_unref (message);
00548
00549 if (reply == NULL)
00550 {
00551 _DBUS_ASSERT_ERROR_IS_SET (error);
00552 return -1;
00553 }
00554
00555 if (dbus_set_error_from_message (error, reply))
00556 {
00557 _DBUS_ASSERT_ERROR_IS_SET (error);
00558 dbus_message_unref (reply);
00559 return -1;
00560 }
00561
00562 if (!dbus_message_get_args (reply, error,
00563 DBUS_TYPE_UINT32, &service_result,
00564 DBUS_TYPE_INVALID))
00565 {
00566 _DBUS_ASSERT_ERROR_IS_SET (error);
00567 dbus_message_unref (reply);
00568 return -1;
00569 }
00570
00571 dbus_message_unref (reply);
00572
00573 return service_result;
00574 }
00575
00586 dbus_bool_t
00587 dbus_bus_service_exists (DBusConnection *connection,
00588 const char *service_name,
00589 DBusError *error)
00590 {
00591 DBusMessage *message, *reply;
00592 unsigned int exists;
00593
00594 _dbus_return_val_if_fail (connection != NULL, FALSE);
00595 _dbus_return_val_if_fail (service_name != NULL, FALSE);
00596 _dbus_return_val_if_error_is_set (error, FALSE);
00597
00598 message = dbus_message_new (DBUS_MESSAGE_SERVICE_EXISTS,
00599 DBUS_SERVICE_DBUS);
00600 if (message == NULL)
00601 {
00602 _DBUS_SET_OOM (error);
00603 return FALSE;
00604 }
00605
00606 if (!dbus_message_append_args (message,
00607 DBUS_TYPE_STRING, service_name,
00608 DBUS_TYPE_INVALID))
00609 {
00610 dbus_message_unref (message);
00611 _DBUS_SET_OOM (error);
00612 return FALSE;
00613 }
00614
00615 reply = dbus_connection_send_with_reply_and_block (connection, message, -1, error);
00616 dbus_message_unref (message);
00617
00618 if (reply == NULL)
00619 {
00620 _DBUS_ASSERT_ERROR_IS_SET (error);
00621 return FALSE;
00622 }
00623
00624 if (!dbus_message_get_args (reply, error,
00625 DBUS_TYPE_UINT32, &exists,
00626 DBUS_TYPE_INVALID))
00627 {
00628 _DBUS_ASSERT_ERROR_IS_SET (error);
00629 return FALSE;
00630 }
00631
00632 return (exists != FALSE);
00633 }
00634
00650 dbus_bool_t
00651 dbus_bus_activate_service (DBusConnection *connection,
00652 const char *service_name,
00653 dbus_uint32_t flags,
00654 dbus_uint32_t *result,
00655 DBusError *error)
00656 {
00657 DBusMessage *msg;
00658 DBusMessage *reply;
00659
00660 msg = dbus_message_new (DBUS_MESSAGE_ACTIVATE_SERVICE,
00661 DBUS_SERVICE_DBUS);
00662
00663 if (!dbus_message_append_args (msg, DBUS_TYPE_STRING, service_name,
00664 DBUS_TYPE_UINT32, flags, DBUS_TYPE_INVALID))
00665 {
00666 dbus_message_unref (msg);
00667 _DBUS_SET_OOM (error);
00668 return FALSE;
00669 }
00670
00671 reply = dbus_connection_send_with_reply_and_block (connection, msg,
00672 -1, error);
00673 dbus_message_unref (msg);
00674
00675 if (reply == NULL)
00676 {
00677 _DBUS_ASSERT_ERROR_IS_SET (error);
00678 return FALSE;
00679 }
00680
00681 if (dbus_set_error_from_message (error, reply))
00682 {
00683 _DBUS_ASSERT_ERROR_IS_SET (error);
00684 dbus_message_unref (reply);
00685 return FALSE;
00686 }
00687
00688 if (result != NULL &&
00689 !dbus_message_get_args (reply, error, DBUS_TYPE_UINT32,
00690 result, DBUS_TYPE_INVALID))
00691 {
00692 _DBUS_ASSERT_ERROR_IS_SET (error);
00693 dbus_message_unref (reply);
00694 return FALSE;
00695 }
00696
00697 dbus_message_unref (reply);
00698 return TRUE;
00699 }
00700
00701