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
00325 DBusConnection *
00326 dbus_bus_get (DBusBusType type,
00327 DBusError *error)
00328 {
00329 const char *address;
00330 DBusConnection *connection;
00331 BusData *bd;
00332 DBusBusType address_type;
00333
00334 _dbus_return_val_if_fail (type >= 0 && type < N_BUS_TYPES, NULL);
00335 _dbus_return_val_if_error_is_set (error, NULL);
00336
00337 _DBUS_LOCK (bus);
00338
00339 if (!init_connections_unlocked ())
00340 {
00341 _DBUS_UNLOCK (bus);
00342 _DBUS_SET_OOM (error);
00343 return NULL;
00344 }
00345
00346
00347
00348
00349
00350 address_type = type;
00351
00352
00353
00354
00355
00356
00357 if (type == DBUS_BUS_ACTIVATION &&
00358 bus_connection_addresses[activation_bus_type] != NULL)
00359 type = activation_bus_type;
00360
00361 if (bus_connections[type] != NULL)
00362 {
00363 connection = bus_connections[type];
00364 dbus_connection_ref (connection);
00365
00366 _DBUS_UNLOCK (bus);
00367 return connection;
00368 }
00369
00370 address = bus_connection_addresses[address_type];
00371 if (address == NULL)
00372 {
00373 dbus_set_error (error, DBUS_ERROR_FAILED,
00374 "Unable to determine the address of the message bus");
00375 _DBUS_UNLOCK (bus);
00376 return NULL;
00377 }
00378
00379 connection = dbus_connection_open (address, error);
00380
00381 if (!connection)
00382 {
00383 _DBUS_ASSERT_ERROR_IS_SET (error);
00384 _DBUS_UNLOCK (bus);
00385 return NULL;
00386 }
00387
00388
00389
00390
00391 dbus_connection_set_exit_on_disconnect (connection,
00392 TRUE);
00393
00394 if (!dbus_bus_register (connection, error))
00395 {
00396 _DBUS_ASSERT_ERROR_IS_SET (error);
00397 dbus_connection_disconnect (connection);
00398 dbus_connection_unref (connection);
00399
00400 _DBUS_UNLOCK (bus);
00401 return NULL;
00402 }
00403
00404 bus_connections[type] = connection;
00405 bd = ensure_bus_data (connection);
00406 _dbus_assert (bd != NULL);
00407
00408 bd->is_well_known = TRUE;
00409
00410 _DBUS_UNLOCK (bus);
00411 return connection;
00412 }
00413
00414
00428 dbus_bool_t
00429 dbus_bus_register (DBusConnection *connection,
00430 DBusError *error)
00431 {
00432 DBusMessage *message, *reply;
00433 char *name;
00434 BusData *bd;
00435 dbus_bool_t retval;
00436
00437 _dbus_return_val_if_fail (connection != NULL, FALSE);
00438 _dbus_return_val_if_error_is_set (error, FALSE);
00439
00440 retval = FALSE;
00441
00442 bd = ensure_bus_data (connection);
00443 if (bd == NULL)
00444 {
00445 _DBUS_SET_OOM (error);
00446 return FALSE;
00447 }
00448
00449 if (bd->base_service != NULL)
00450 {
00451 _dbus_warn ("Attempt to register the same DBusConnection with the message bus, but it is already registered\n");
00452
00453
00454
00455 return TRUE;
00456 }
00457
00458 message = dbus_message_new_method_call (DBUS_SERVICE_ORG_FREEDESKTOP_DBUS,
00459 DBUS_PATH_ORG_FREEDESKTOP_DBUS,
00460 DBUS_INTERFACE_ORG_FREEDESKTOP_DBUS,
00461 "Hello");
00462
00463 if (!message)
00464 {
00465 _DBUS_SET_OOM (error);
00466 return FALSE;
00467 }
00468
00469 reply = dbus_connection_send_with_reply_and_block (connection, message, -1, error);
00470
00471 dbus_message_unref (message);
00472
00473 if (reply == NULL)
00474 goto out;
00475 else if (dbus_set_error_from_message (error, reply))
00476 goto out;
00477 else if (!dbus_message_get_args (reply, error,
00478 DBUS_TYPE_STRING, &name,
00479 DBUS_TYPE_INVALID))
00480 goto out;
00481
00482 bd->base_service = name;
00483
00484 retval = TRUE;
00485
00486 out:
00487 if (reply)
00488 dbus_message_unref (reply);
00489
00490 if (!retval)
00491 _DBUS_ASSERT_ERROR_IS_SET (error);
00492
00493 return retval;
00494 }
00495
00496
00508 dbus_bool_t
00509 dbus_bus_set_base_service (DBusConnection *connection,
00510 const char *base_service)
00511 {
00512 BusData *bd;
00513
00514 _dbus_return_val_if_fail (connection != NULL, FALSE);
00515 _dbus_return_val_if_fail (base_service != NULL, FALSE);
00516
00517 bd = ensure_bus_data (connection);
00518 if (bd == NULL)
00519 return FALSE;
00520
00521 _dbus_assert (bd->base_service == NULL);
00522
00523 bd->base_service = _dbus_strdup (base_service);
00524 return bd->base_service != NULL;
00525 }
00526
00535 const char*
00536 dbus_bus_get_base_service (DBusConnection *connection)
00537 {
00538 BusData *bd;
00539
00540 _dbus_return_val_if_fail (connection != NULL, NULL);
00541
00542 bd = ensure_bus_data (connection);
00543 if (bd == NULL)
00544 return NULL;
00545
00546 return bd->base_service;
00547 }
00548
00557 unsigned long
00558 dbus_bus_get_unix_user (DBusConnection *connection,
00559 const char *service,
00560 DBusError *error)
00561 {
00562 DBusMessage *message, *reply;
00563 dbus_uint32_t uid;
00564
00565 _dbus_return_val_if_fail (connection != NULL, DBUS_UID_UNSET);
00566 _dbus_return_val_if_fail (service != NULL, DBUS_UID_UNSET);
00567 _dbus_return_val_if_error_is_set (error, DBUS_UID_UNSET);
00568
00569 message = dbus_message_new_method_call (DBUS_SERVICE_ORG_FREEDESKTOP_DBUS,
00570 DBUS_PATH_ORG_FREEDESKTOP_DBUS,
00571 DBUS_INTERFACE_ORG_FREEDESKTOP_DBUS,
00572 "GetConnectionUnixUser");
00573
00574 if (message == NULL)
00575 {
00576 _DBUS_SET_OOM (error);
00577 return DBUS_UID_UNSET;
00578 }
00579
00580 if (!dbus_message_append_args (message,
00581 DBUS_TYPE_STRING, service,
00582 DBUS_TYPE_INVALID))
00583 {
00584 dbus_message_unref (message);
00585 _DBUS_SET_OOM (error);
00586 return DBUS_UID_UNSET;
00587 }
00588
00589 reply = dbus_connection_send_with_reply_and_block (connection, message, -1,
00590 error);
00591
00592 dbus_message_unref (message);
00593
00594 if (reply == NULL)
00595 {
00596 _DBUS_ASSERT_ERROR_IS_SET (error);
00597 return DBUS_UID_UNSET;
00598 }
00599
00600 if (dbus_set_error_from_message (error, reply))
00601 {
00602 _DBUS_ASSERT_ERROR_IS_SET (error);
00603 dbus_message_unref (reply);
00604 return DBUS_UID_UNSET;
00605 }
00606
00607 if (!dbus_message_get_args (reply, error,
00608 DBUS_TYPE_UINT32, &uid,
00609 DBUS_TYPE_INVALID))
00610 {
00611 _DBUS_ASSERT_ERROR_IS_SET (error);
00612 dbus_message_unref (reply);
00613 return DBUS_UID_UNSET;
00614 }
00615
00616 dbus_message_unref (reply);
00617
00618 return (unsigned long) uid;
00619 }
00620
00621
00637 int
00638 dbus_bus_acquire_service (DBusConnection *connection,
00639 const char *service_name,
00640 unsigned int flags,
00641 DBusError *error)
00642 {
00643 DBusMessage *message, *reply;
00644 dbus_uint32_t service_result;
00645
00646 _dbus_return_val_if_fail (connection != NULL, 0);
00647 _dbus_return_val_if_fail (service_name != NULL, 0);
00648 _dbus_return_val_if_error_is_set (error, 0);
00649
00650 message = dbus_message_new_method_call (DBUS_SERVICE_ORG_FREEDESKTOP_DBUS,
00651 DBUS_PATH_ORG_FREEDESKTOP_DBUS,
00652 DBUS_INTERFACE_ORG_FREEDESKTOP_DBUS,
00653 "AcquireService");
00654
00655 if (message == NULL)
00656 {
00657 _DBUS_SET_OOM (error);
00658 return -1;
00659 }
00660
00661 if (!dbus_message_append_args (message,
00662 DBUS_TYPE_STRING, service_name,
00663 DBUS_TYPE_UINT32, flags,
00664 DBUS_TYPE_INVALID))
00665 {
00666 dbus_message_unref (message);
00667 _DBUS_SET_OOM (error);
00668 return -1;
00669 }
00670
00671 reply = dbus_connection_send_with_reply_and_block (connection, message, -1,
00672 error);
00673
00674 dbus_message_unref (message);
00675
00676 if (reply == NULL)
00677 {
00678 _DBUS_ASSERT_ERROR_IS_SET (error);
00679 return -1;
00680 }
00681
00682 if (dbus_set_error_from_message (error, reply))
00683 {
00684 _DBUS_ASSERT_ERROR_IS_SET (error);
00685 dbus_message_unref (reply);
00686 return -1;
00687 }
00688
00689 if (!dbus_message_get_args (reply, error,
00690 DBUS_TYPE_UINT32, &service_result,
00691 DBUS_TYPE_INVALID))
00692 {
00693 _DBUS_ASSERT_ERROR_IS_SET (error);
00694 dbus_message_unref (reply);
00695 return -1;
00696 }
00697
00698 dbus_message_unref (reply);
00699
00700 return service_result;
00701 }
00702
00711 dbus_bool_t
00712 dbus_bus_service_exists (DBusConnection *connection,
00713 const char *service_name,
00714 DBusError *error)
00715 {
00716 DBusMessage *message, *reply;
00717 dbus_bool_t exists;
00718
00719 _dbus_return_val_if_fail (connection != NULL, FALSE);
00720 _dbus_return_val_if_fail (service_name != NULL, FALSE);
00721 _dbus_return_val_if_error_is_set (error, FALSE);
00722
00723 message = dbus_message_new_method_call (DBUS_SERVICE_ORG_FREEDESKTOP_DBUS,
00724 DBUS_PATH_ORG_FREEDESKTOP_DBUS,
00725 DBUS_INTERFACE_ORG_FREEDESKTOP_DBUS,
00726 "ServiceExists");
00727 if (message == NULL)
00728 {
00729 _DBUS_SET_OOM (error);
00730 return FALSE;
00731 }
00732
00733 if (!dbus_message_append_args (message,
00734 DBUS_TYPE_STRING, service_name,
00735 DBUS_TYPE_INVALID))
00736 {
00737 dbus_message_unref (message);
00738 _DBUS_SET_OOM (error);
00739 return FALSE;
00740 }
00741
00742 reply = dbus_connection_send_with_reply_and_block (connection, message, -1, error);
00743 dbus_message_unref (message);
00744
00745 if (reply == NULL)
00746 {
00747 _DBUS_ASSERT_ERROR_IS_SET (error);
00748 return FALSE;
00749 }
00750
00751 if (!dbus_message_get_args (reply, error,
00752 DBUS_TYPE_BOOLEAN, &exists,
00753 DBUS_TYPE_INVALID))
00754 {
00755 _DBUS_ASSERT_ERROR_IS_SET (error);
00756 dbus_message_unref (reply);
00757 return FALSE;
00758 }
00759
00760 dbus_message_unref (reply);
00761 return exists;
00762 }
00763
00779 dbus_bool_t
00780 dbus_bus_activate_service (DBusConnection *connection,
00781 const char *service_name,
00782 dbus_uint32_t flags,
00783 dbus_uint32_t *result,
00784 DBusError *error)
00785 {
00786 DBusMessage *msg;
00787 DBusMessage *reply;
00788
00789 msg = dbus_message_new_method_call (DBUS_SERVICE_ORG_FREEDESKTOP_DBUS,
00790 DBUS_PATH_ORG_FREEDESKTOP_DBUS,
00791 DBUS_INTERFACE_ORG_FREEDESKTOP_DBUS,
00792 "ActivateService");
00793
00794 if (!dbus_message_append_args (msg, DBUS_TYPE_STRING, service_name,
00795 DBUS_TYPE_UINT32, flags, DBUS_TYPE_INVALID))
00796 {
00797 dbus_message_unref (msg);
00798 _DBUS_SET_OOM (error);
00799 return FALSE;
00800 }
00801
00802 reply = dbus_connection_send_with_reply_and_block (connection, msg,
00803 -1, error);
00804 dbus_message_unref (msg);
00805
00806 if (reply == NULL)
00807 {
00808 _DBUS_ASSERT_ERROR_IS_SET (error);
00809 return FALSE;
00810 }
00811
00812 if (dbus_set_error_from_message (error, reply))
00813 {
00814 _DBUS_ASSERT_ERROR_IS_SET (error);
00815 dbus_message_unref (reply);
00816 return FALSE;
00817 }
00818
00819 if (result != NULL &&
00820 !dbus_message_get_args (reply, error, DBUS_TYPE_UINT32,
00821 result, DBUS_TYPE_INVALID))
00822 {
00823 _DBUS_ASSERT_ERROR_IS_SET (error);
00824 dbus_message_unref (reply);
00825 return FALSE;
00826 }
00827
00828 dbus_message_unref (reply);
00829 return TRUE;
00830 }
00831
00832 static void
00833 send_no_return_values (DBusConnection *connection,
00834 DBusMessage *msg,
00835 DBusError *error)
00836 {
00837 if (error)
00838 {
00839
00840 DBusMessage *reply;
00841
00842 reply = dbus_connection_send_with_reply_and_block (connection, msg,
00843 -1, error);
00844
00845 if (reply == NULL)
00846 _DBUS_ASSERT_ERROR_IS_SET (error);
00847 else
00848 dbus_message_unref (reply);
00849 }
00850 else
00851 {
00852
00853 dbus_message_set_no_reply (msg, TRUE);
00854 dbus_connection_send (connection, msg, NULL);
00855 }
00856 }
00857
00880 void
00881 dbus_bus_add_match (DBusConnection *connection,
00882 const char *rule,
00883 DBusError *error)
00884 {
00885 DBusMessage *msg;
00886
00887 msg = dbus_message_new_method_call (DBUS_SERVICE_ORG_FREEDESKTOP_DBUS,
00888 DBUS_PATH_ORG_FREEDESKTOP_DBUS,
00889 DBUS_INTERFACE_ORG_FREEDESKTOP_DBUS,
00890 "AddMatch");
00891
00892 if (msg == NULL)
00893 {
00894 _DBUS_SET_OOM (error);
00895 return;
00896 }
00897
00898 if (!dbus_message_append_args (msg, DBUS_TYPE_STRING, rule,
00899 DBUS_TYPE_INVALID))
00900 {
00901 dbus_message_unref (msg);
00902 _DBUS_SET_OOM (error);
00903 return;
00904 }
00905
00906 send_no_return_values (connection, msg, error);
00907
00908 dbus_message_unref (msg);
00909 }
00910
00924 void
00925 dbus_bus_remove_match (DBusConnection *connection,
00926 const char *rule,
00927 DBusError *error)
00928 {
00929 DBusMessage *msg;
00930
00931 msg = dbus_message_new_method_call (DBUS_SERVICE_ORG_FREEDESKTOP_DBUS,
00932 DBUS_PATH_ORG_FREEDESKTOP_DBUS,
00933 DBUS_INTERFACE_ORG_FREEDESKTOP_DBUS,
00934 "RemoveMatch");
00935
00936 if (!dbus_message_append_args (msg, DBUS_TYPE_STRING, rule,
00937 DBUS_TYPE_INVALID))
00938 {
00939 dbus_message_unref (msg);
00940 _DBUS_SET_OOM (error);
00941 return;
00942 }
00943
00944 send_no_return_values (connection, msg, error);
00945
00946 dbus_message_unref (msg);
00947 }
00948