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 "dbus-message.h"
00029 #include <string.h>
00030
00061 typedef struct
00062 {
00063 DBusConnection *connection;
00064 char *base_service;
00066 unsigned int is_well_known : 1;
00067 } BusData;
00068
00071 static dbus_int32_t bus_data_slot = -1;
00072
00074 #define N_BUS_TYPES 3
00075
00076 static DBusConnection *bus_connections[N_BUS_TYPES];
00077 static char *bus_connection_addresses[N_BUS_TYPES] = { NULL, NULL, NULL };
00078
00079 static DBusBusType activation_bus_type = DBUS_BUS_ACTIVATION;
00080
00081 static dbus_bool_t initialized = FALSE;
00082
00086 _DBUS_DEFINE_GLOBAL_LOCK (bus);
00087
00088 static void
00089 addresses_shutdown_func (void *data)
00090 {
00091 int i;
00092
00093 i = 0;
00094 while (i < N_BUS_TYPES)
00095 {
00096 if (bus_connections[i] != NULL)
00097 _dbus_warn ("dbus_shutdown() called but connections were still live!");
00098
00099 dbus_free (bus_connection_addresses[i]);
00100 bus_connection_addresses[i] = NULL;
00101 ++i;
00102 }
00103
00104 activation_bus_type = DBUS_BUS_ACTIVATION;
00105 }
00106
00107 static dbus_bool_t
00108 get_from_env (char **connection_p,
00109 const char *env_var)
00110 {
00111 const char *s;
00112
00113 _dbus_assert (*connection_p == NULL);
00114
00115 s = _dbus_getenv (env_var);
00116 if (s == NULL || *s == '\0')
00117 return TRUE;
00118 else
00119 {
00120 *connection_p = _dbus_strdup (s);
00121 return *connection_p != NULL;
00122 }
00123 }
00124
00125 static dbus_bool_t
00126 init_connections_unlocked (void)
00127 {
00128 if (!initialized)
00129 {
00130 const char *s;
00131 int i;
00132
00133 i = 0;
00134 while (i < N_BUS_TYPES)
00135 {
00136 bus_connections[i] = NULL;
00137 ++i;
00138 }
00139
00140
00141
00142
00143
00144
00145
00146
00147 if (bus_connection_addresses[DBUS_BUS_SYSTEM] == NULL)
00148 {
00149 _dbus_verbose ("Filling in system bus address...\n");
00150
00151 if (!get_from_env (&bus_connection_addresses[DBUS_BUS_SYSTEM],
00152 "DBUS_SYSTEM_BUS_ADDRESS"))
00153 return FALSE;
00154 }
00155
00156
00157 if (bus_connection_addresses[DBUS_BUS_SYSTEM] == NULL)
00158 {
00159
00160 bus_connection_addresses[DBUS_BUS_SYSTEM] =
00161 _dbus_strdup (DBUS_SYSTEM_BUS_DEFAULT_ADDRESS);
00162 if (bus_connection_addresses[DBUS_BUS_SYSTEM] == NULL)
00163 return FALSE;
00164
00165 _dbus_verbose (" used default system bus \"%s\"\n",
00166 bus_connection_addresses[DBUS_BUS_SYSTEM]);
00167 }
00168 else
00169 _dbus_verbose (" used env var system bus \"%s\"\n",
00170 bus_connection_addresses[DBUS_BUS_SYSTEM]);
00171
00172 if (bus_connection_addresses[DBUS_BUS_SESSION] == NULL)
00173 {
00174 _dbus_verbose ("Filling in session bus address...\n");
00175
00176 if (!get_from_env (&bus_connection_addresses[DBUS_BUS_SESSION],
00177 "DBUS_SESSION_BUS_ADDRESS"))
00178 return FALSE;
00179 _dbus_verbose (" \"%s\"\n", bus_connection_addresses[DBUS_BUS_SESSION] ?
00180 bus_connection_addresses[DBUS_BUS_SESSION] : "none set");
00181 }
00182
00183 if (bus_connection_addresses[DBUS_BUS_ACTIVATION] == NULL)
00184 {
00185 _dbus_verbose ("Filling in activation bus address...\n");
00186
00187 if (!get_from_env (&bus_connection_addresses[DBUS_BUS_ACTIVATION],
00188 "DBUS_ACTIVATION_ADDRESS"))
00189 return FALSE;
00190
00191 _dbus_verbose (" \"%s\"\n", bus_connection_addresses[DBUS_BUS_ACTIVATION] ?
00192 bus_connection_addresses[DBUS_BUS_ACTIVATION] : "none set");
00193 }
00194
00195
00196 if (bus_connection_addresses[DBUS_BUS_ACTIVATION] != NULL)
00197 {
00198 s = _dbus_getenv ("DBUS_ACTIVATION_BUS_TYPE");
00199
00200 if (s != NULL)
00201 {
00202 _dbus_verbose ("Bus activation type was set to \"%s\"\n", s);
00203
00204 if (strcmp (s, "system") == 0)
00205 activation_bus_type = DBUS_BUS_SYSTEM;
00206 else if (strcmp (s, "session") == 0)
00207 activation_bus_type = DBUS_BUS_SESSION;
00208 }
00209 }
00210 else
00211 {
00212
00213 if (bus_connection_addresses[DBUS_BUS_SESSION] != NULL)
00214 {
00215 bus_connection_addresses[DBUS_BUS_ACTIVATION] =
00216 _dbus_strdup (bus_connection_addresses[DBUS_BUS_SESSION]);
00217 if (bus_connection_addresses[DBUS_BUS_ACTIVATION] == NULL)
00218 return FALSE;
00219 }
00220 }
00221
00222
00223
00224
00225
00226 if (!_dbus_setenv ("DBUS_ACTIVATION_ADDRESS", NULL))
00227 return FALSE;
00228
00229 if (!_dbus_setenv ("DBUS_ACTIVATION_BUS_TYPE", NULL))
00230 return FALSE;
00231
00232 if (!_dbus_register_shutdown_func (addresses_shutdown_func,
00233 NULL))
00234 return FALSE;
00235
00236 initialized = TRUE;
00237 }
00238
00239 return initialized;
00240 }
00241
00242 static void
00243 bus_data_free (void *data)
00244 {
00245 BusData *bd = data;
00246
00247 if (bd->is_well_known)
00248 {
00249 int i;
00250 _DBUS_LOCK (bus);
00251
00252 i = 0;
00253 while (i < N_BUS_TYPES)
00254 {
00255 if (bus_connections[i] == bd->connection)
00256 bus_connections[i] = NULL;
00257
00258 ++i;
00259 }
00260 _DBUS_UNLOCK (bus);
00261 }
00262
00263 dbus_free (bd->base_service);
00264 dbus_free (bd);
00265
00266 dbus_connection_free_data_slot (&bus_data_slot);
00267 }
00268
00269 static BusData*
00270 ensure_bus_data (DBusConnection *connection)
00271 {
00272 BusData *bd;
00273
00274 if (!dbus_connection_allocate_data_slot (&bus_data_slot))
00275 return NULL;
00276
00277 bd = dbus_connection_get_data (connection, bus_data_slot);
00278 if (bd == NULL)
00279 {
00280 bd = dbus_new0 (BusData, 1);
00281 if (bd == NULL)
00282 {
00283 dbus_connection_free_data_slot (&bus_data_slot);
00284 return NULL;
00285 }
00286
00287 bd->connection = connection;
00288
00289 if (!dbus_connection_set_data (connection, bus_data_slot, bd,
00290 bus_data_free))
00291 {
00292 dbus_free (bd);
00293 dbus_connection_free_data_slot (&bus_data_slot);
00294 return NULL;
00295 }
00296
00297
00298 }
00299 else
00300 {
00301 dbus_connection_free_data_slot (&bus_data_slot);
00302 }
00303
00304 return bd;
00305 }
00306
00308
00324 DBusConnection *
00325 dbus_bus_get (DBusBusType type,
00326 DBusError *error)
00327 {
00328 const char *address;
00329 DBusConnection *connection;
00330 BusData *bd;
00331 DBusBusType address_type;
00332
00333 _dbus_return_val_if_fail (type >= 0 && type < N_BUS_TYPES, NULL);
00334 _dbus_return_val_if_error_is_set (error, NULL);
00335
00336 _DBUS_LOCK (bus);
00337
00338 if (!init_connections_unlocked ())
00339 {
00340 _DBUS_UNLOCK (bus);
00341 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
00342 return NULL;
00343 }
00344
00345
00346
00347
00348
00349 address_type = type;
00350
00351
00352
00353
00354
00355
00356 if (type == DBUS_BUS_ACTIVATION &&
00357 bus_connection_addresses[activation_bus_type] != NULL)
00358 type = activation_bus_type;
00359
00360 if (bus_connections[type] != NULL)
00361 {
00362 connection = bus_connections[type];
00363 dbus_connection_ref (connection);
00364
00365 _DBUS_UNLOCK (bus);
00366 return connection;
00367 }
00368
00369 address = bus_connection_addresses[address_type];
00370 if (address == NULL)
00371 {
00372 dbus_set_error (error, DBUS_ERROR_FAILED,
00373 "Unable to determine the address of the message bus");
00374 _DBUS_UNLOCK (bus);
00375 return NULL;
00376 }
00377
00378 connection = dbus_connection_open (address, error);
00379
00380 if (!connection)
00381 {
00382 _DBUS_ASSERT_ERROR_IS_SET (error);
00383 _DBUS_UNLOCK (bus);
00384 return NULL;
00385 }
00386
00387
00388
00389
00390 dbus_connection_set_exit_on_disconnect (connection,
00391 TRUE);
00392
00393 if (!dbus_bus_register (connection, error))
00394 {
00395 _DBUS_ASSERT_ERROR_IS_SET (error);
00396 dbus_connection_disconnect (connection);
00397 dbus_connection_unref (connection);
00398
00399 _DBUS_UNLOCK (bus);
00400 return NULL;
00401 }
00402
00403 bus_connections[type] = connection;
00404 bd = ensure_bus_data (connection);
00405 _dbus_assert (bd != NULL);
00406
00407 bd->is_well_known = TRUE;
00408
00409 _DBUS_UNLOCK (bus);
00410 return connection;
00411 }
00412
00413
00427 dbus_bool_t
00428 dbus_bus_register (DBusConnection *connection,
00429 DBusError *error)
00430 {
00431 DBusMessage *message, *reply;
00432 char *name;
00433 BusData *bd;
00434 dbus_bool_t retval;
00435
00436 _dbus_return_val_if_fail (connection != NULL, FALSE);
00437 _dbus_return_val_if_error_is_set (error, FALSE);
00438
00439 retval = FALSE;
00440
00441 bd = ensure_bus_data (connection);
00442 if (bd == NULL)
00443 {
00444 _DBUS_SET_OOM (error);
00445 return FALSE;
00446 }
00447
00448 if (bd->base_service != NULL)
00449 {
00450 _dbus_warn ("Attempt to register the same DBusConnection with the message bus, but it is already registered\n");
00451
00452
00453
00454 return TRUE;
00455 }
00456
00457 message = dbus_message_new_method_call (DBUS_SERVICE_ORG_FREEDESKTOP_DBUS,
00458 DBUS_PATH_ORG_FREEDESKTOP_DBUS,
00459 DBUS_INTERFACE_ORG_FREEDESKTOP_DBUS,
00460 "Hello");
00461
00462 if (!message)
00463 {
00464 _DBUS_SET_OOM (error);
00465 return FALSE;
00466 }
00467
00468 reply = dbus_connection_send_with_reply_and_block (connection, message, -1, error);
00469
00470 dbus_message_unref (message);
00471
00472 if (reply == NULL)
00473 goto out;
00474 else if (dbus_set_error_from_message (error, reply))
00475 goto out;
00476 else if (!dbus_message_get_args (reply, error,
00477 DBUS_TYPE_STRING, &name,
00478 DBUS_TYPE_INVALID))
00479 goto out;
00480
00481 bd->base_service = name;
00482
00483 retval = TRUE;
00484
00485 out:
00486 if (reply)
00487 dbus_message_unref (reply);
00488
00489 if (!retval)
00490 _DBUS_ASSERT_ERROR_IS_SET (error);
00491
00492 return retval;
00493 }
00494
00495
00507 dbus_bool_t
00508 dbus_bus_set_base_service (DBusConnection *connection,
00509 const char *base_service)
00510 {
00511 BusData *bd;
00512
00513 _dbus_return_val_if_fail (connection != NULL, FALSE);
00514 _dbus_return_val_if_fail (base_service != NULL, FALSE);
00515
00516 bd = ensure_bus_data (connection);
00517 if (bd == NULL)
00518 return FALSE;
00519
00520 _dbus_assert (bd->base_service == NULL);
00521
00522 bd->base_service = _dbus_strdup (base_service);
00523 return bd->base_service != NULL;
00524 }
00525
00534 const char*
00535 dbus_bus_get_base_service (DBusConnection *connection)
00536 {
00537 BusData *bd;
00538
00539 _dbus_return_val_if_fail (connection != NULL, NULL);
00540
00541 bd = ensure_bus_data (connection);
00542 if (bd == NULL)
00543 return NULL;
00544
00545 return bd->base_service;
00546 }
00547
00563 int
00564 dbus_bus_acquire_service (DBusConnection *connection,
00565 const char *service_name,
00566 unsigned int flags,
00567 DBusError *error)
00568 {
00569 DBusMessage *message, *reply;
00570 dbus_uint32_t service_result;
00571
00572 _dbus_return_val_if_fail (connection != NULL, 0);
00573 _dbus_return_val_if_fail (service_name != NULL, 0);
00574 _dbus_return_val_if_error_is_set (error, 0);
00575
00576 message = dbus_message_new_method_call (DBUS_SERVICE_ORG_FREEDESKTOP_DBUS,
00577 DBUS_PATH_ORG_FREEDESKTOP_DBUS,
00578 DBUS_INTERFACE_ORG_FREEDESKTOP_DBUS,
00579 "AcquireService");
00580
00581 if (message == NULL)
00582 {
00583 _DBUS_SET_OOM (error);
00584 return -1;
00585 }
00586
00587 if (!dbus_message_append_args (message,
00588 DBUS_TYPE_STRING, service_name,
00589 DBUS_TYPE_UINT32, flags,
00590 DBUS_TYPE_INVALID))
00591 {
00592 dbus_message_unref (message);
00593 _DBUS_SET_OOM (error);
00594 return -1;
00595 }
00596
00597 reply = dbus_connection_send_with_reply_and_block (connection, message, -1,
00598 error);
00599
00600 dbus_message_unref (message);
00601
00602 if (reply == NULL)
00603 {
00604 _DBUS_ASSERT_ERROR_IS_SET (error);
00605 return -1;
00606 }
00607
00608 if (dbus_set_error_from_message (error, reply))
00609 {
00610 _DBUS_ASSERT_ERROR_IS_SET (error);
00611 dbus_message_unref (reply);
00612 return -1;
00613 }
00614
00615 if (!dbus_message_get_args (reply, error,
00616 DBUS_TYPE_UINT32, &service_result,
00617 DBUS_TYPE_INVALID))
00618 {
00619 _DBUS_ASSERT_ERROR_IS_SET (error);
00620 dbus_message_unref (reply);
00621 return -1;
00622 }
00623
00624 dbus_message_unref (reply);
00625
00626 return service_result;
00627 }
00628
00639 dbus_bool_t
00640 dbus_bus_service_exists (DBusConnection *connection,
00641 const char *service_name,
00642 DBusError *error)
00643 {
00644 DBusMessage *message, *reply;
00645 unsigned int exists;
00646
00647 _dbus_return_val_if_fail (connection != NULL, FALSE);
00648 _dbus_return_val_if_fail (service_name != NULL, FALSE);
00649 _dbus_return_val_if_error_is_set (error, FALSE);
00650
00651 message = dbus_message_new_method_call (DBUS_SERVICE_ORG_FREEDESKTOP_DBUS,
00652 DBUS_PATH_ORG_FREEDESKTOP_DBUS,
00653 DBUS_INTERFACE_ORG_FREEDESKTOP_DBUS,
00654 "ServiceExists");
00655 if (message == NULL)
00656 {
00657 _DBUS_SET_OOM (error);
00658 return FALSE;
00659 }
00660
00661 if (!dbus_message_append_args (message,
00662 DBUS_TYPE_STRING, service_name,
00663 DBUS_TYPE_INVALID))
00664 {
00665 dbus_message_unref (message);
00666 _DBUS_SET_OOM (error);
00667 return FALSE;
00668 }
00669
00670 reply = dbus_connection_send_with_reply_and_block (connection, message, -1, error);
00671 dbus_message_unref (message);
00672
00673 if (reply == NULL)
00674 {
00675 _DBUS_ASSERT_ERROR_IS_SET (error);
00676 return FALSE;
00677 }
00678
00679 if (!dbus_message_get_args (reply, error,
00680 DBUS_TYPE_UINT32, &exists,
00681 DBUS_TYPE_INVALID))
00682 {
00683 _DBUS_ASSERT_ERROR_IS_SET (error);
00684 return FALSE;
00685 }
00686
00687 return (exists != FALSE);
00688 }
00689
00705 dbus_bool_t
00706 dbus_bus_activate_service (DBusConnection *connection,
00707 const char *service_name,
00708 dbus_uint32_t flags,
00709 dbus_uint32_t *result,
00710 DBusError *error)
00711 {
00712 DBusMessage *msg;
00713 DBusMessage *reply;
00714
00715 msg = dbus_message_new_method_call (DBUS_SERVICE_ORG_FREEDESKTOP_DBUS,
00716 DBUS_PATH_ORG_FREEDESKTOP_DBUS,
00717 DBUS_INTERFACE_ORG_FREEDESKTOP_DBUS,
00718 "ActivateService");
00719
00720 if (!dbus_message_append_args (msg, DBUS_TYPE_STRING, service_name,
00721 DBUS_TYPE_UINT32, flags, DBUS_TYPE_INVALID))
00722 {
00723 dbus_message_unref (msg);
00724 _DBUS_SET_OOM (error);
00725 return FALSE;
00726 }
00727
00728 reply = dbus_connection_send_with_reply_and_block (connection, msg,
00729 -1, error);
00730 dbus_message_unref (msg);
00731
00732 if (reply == NULL)
00733 {
00734 _DBUS_ASSERT_ERROR_IS_SET (error);
00735 return FALSE;
00736 }
00737
00738 if (dbus_set_error_from_message (error, reply))
00739 {
00740 _DBUS_ASSERT_ERROR_IS_SET (error);
00741 dbus_message_unref (reply);
00742 return FALSE;
00743 }
00744
00745 if (result != NULL &&
00746 !dbus_message_get_args (reply, error, DBUS_TYPE_UINT32,
00747 result, DBUS_TYPE_INVALID))
00748 {
00749 _DBUS_ASSERT_ERROR_IS_SET (error);
00750 dbus_message_unref (reply);
00751 return FALSE;
00752 }
00753
00754 dbus_message_unref (reply);
00755 return TRUE;
00756 }
00757
00758 static void
00759 send_no_return_values (DBusConnection *connection,
00760 DBusMessage *msg,
00761 DBusError *error)
00762 {
00763 if (error)
00764 {
00765
00766 DBusMessage *reply;
00767
00768 reply = dbus_connection_send_with_reply_and_block (connection, msg,
00769 -1, error);
00770
00771 if (reply == NULL)
00772 {
00773 _DBUS_ASSERT_ERROR_IS_SET (error);
00774 return;
00775 }
00776
00777 if (dbus_set_error_from_message (error, reply))
00778 {
00779 _DBUS_ASSERT_ERROR_IS_SET (error);
00780 dbus_message_unref (reply);
00781 return;
00782 }
00783
00784 dbus_message_unref (reply);
00785 }
00786 else
00787 {
00788
00789 if (!dbus_connection_send (connection, msg, NULL))
00790 return;
00791 }
00792 }
00793
00816 void
00817 dbus_bus_add_match (DBusConnection *connection,
00818 const char *rule,
00819 DBusError *error)
00820 {
00821 DBusMessage *msg;
00822
00823 msg = dbus_message_new_method_call (DBUS_SERVICE_ORG_FREEDESKTOP_DBUS,
00824 DBUS_PATH_ORG_FREEDESKTOP_DBUS,
00825 DBUS_INTERFACE_ORG_FREEDESKTOP_DBUS,
00826 "AddMatch");
00827
00828 if (!dbus_message_append_args (msg, DBUS_TYPE_STRING, rule,
00829 DBUS_TYPE_INVALID))
00830 {
00831 dbus_message_unref (msg);
00832 _DBUS_SET_OOM (error);
00833 return;
00834 }
00835
00836 send_no_return_values (connection, msg, error);
00837
00838 dbus_message_unref (msg);
00839 }
00840
00854 void
00855 dbus_bus_remove_match (DBusConnection *connection,
00856 const char *rule,
00857 DBusError *error)
00858 {
00859 DBusMessage *msg;
00860
00861 msg = dbus_message_new_method_call (DBUS_SERVICE_ORG_FREEDESKTOP_DBUS,
00862 DBUS_PATH_ORG_FREEDESKTOP_DBUS,
00863 DBUS_INTERFACE_ORG_FREEDESKTOP_DBUS,
00864 "RemoveMatch");
00865
00866 if (!dbus_message_append_args (msg, DBUS_TYPE_STRING, rule,
00867 DBUS_TYPE_INVALID))
00868 {
00869 dbus_message_unref (msg);
00870 _DBUS_SET_OOM (error);
00871 return;
00872 }
00873
00874 send_no_return_values (connection, msg, error);
00875
00876 dbus_message_unref (msg);
00877 }
00878