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
00556 unsigned long
00557 dbus_bus_get_unix_user (DBusConnection *connection,
00558 const char *service,
00559 DBusError *error)
00560 {
00561 DBusMessage *message, *reply;
00562 dbus_uint32_t uid;
00563
00564 _dbus_return_val_if_fail (connection != NULL, DBUS_UID_UNSET);
00565 _dbus_return_val_if_fail (service != NULL, DBUS_UID_UNSET);
00566 _dbus_return_val_if_error_is_set (error, DBUS_UID_UNSET);
00567
00568 message = dbus_message_new_method_call (DBUS_SERVICE_ORG_FREEDESKTOP_DBUS,
00569 DBUS_PATH_ORG_FREEDESKTOP_DBUS,
00570 DBUS_INTERFACE_ORG_FREEDESKTOP_DBUS,
00571 "GetConnectionUnixUser");
00572
00573 if (message == NULL)
00574 {
00575 _DBUS_SET_OOM (error);
00576 return DBUS_UID_UNSET;
00577 }
00578
00579 if (!dbus_message_append_args (message,
00580 DBUS_TYPE_STRING, service,
00581 DBUS_TYPE_INVALID))
00582 {
00583 dbus_message_unref (message);
00584 _DBUS_SET_OOM (error);
00585 return DBUS_UID_UNSET;
00586 }
00587
00588 reply = dbus_connection_send_with_reply_and_block (connection, message, -1,
00589 error);
00590
00591 dbus_message_unref (message);
00592
00593 if (reply == NULL)
00594 {
00595 _DBUS_ASSERT_ERROR_IS_SET (error);
00596 return DBUS_UID_UNSET;
00597 }
00598
00599 if (dbus_set_error_from_message (error, reply))
00600 {
00601 _DBUS_ASSERT_ERROR_IS_SET (error);
00602 dbus_message_unref (reply);
00603 return DBUS_UID_UNSET;
00604 }
00605
00606 if (!dbus_message_get_args (reply, error,
00607 DBUS_TYPE_UINT32, &uid,
00608 DBUS_TYPE_INVALID))
00609 {
00610 _DBUS_ASSERT_ERROR_IS_SET (error);
00611 dbus_message_unref (reply);
00612 return DBUS_UID_UNSET;
00613 }
00614
00615 dbus_message_unref (reply);
00616
00617 return (unsigned long) uid;
00618 }
00619
00620
00636 int
00637 dbus_bus_acquire_service (DBusConnection *connection,
00638 const char *service_name,
00639 unsigned int flags,
00640 DBusError *error)
00641 {
00642 DBusMessage *message, *reply;
00643 dbus_uint32_t service_result;
00644
00645 _dbus_return_val_if_fail (connection != NULL, 0);
00646 _dbus_return_val_if_fail (service_name != NULL, 0);
00647 _dbus_return_val_if_error_is_set (error, 0);
00648
00649 message = dbus_message_new_method_call (DBUS_SERVICE_ORG_FREEDESKTOP_DBUS,
00650 DBUS_PATH_ORG_FREEDESKTOP_DBUS,
00651 DBUS_INTERFACE_ORG_FREEDESKTOP_DBUS,
00652 "AcquireService");
00653
00654 if (message == NULL)
00655 {
00656 _DBUS_SET_OOM (error);
00657 return -1;
00658 }
00659
00660 if (!dbus_message_append_args (message,
00661 DBUS_TYPE_STRING, service_name,
00662 DBUS_TYPE_UINT32, flags,
00663 DBUS_TYPE_INVALID))
00664 {
00665 dbus_message_unref (message);
00666 _DBUS_SET_OOM (error);
00667 return -1;
00668 }
00669
00670 reply = dbus_connection_send_with_reply_and_block (connection, message, -1,
00671 error);
00672
00673 dbus_message_unref (message);
00674
00675 if (reply == NULL)
00676 {
00677 _DBUS_ASSERT_ERROR_IS_SET (error);
00678 return -1;
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 -1;
00686 }
00687
00688 if (!dbus_message_get_args (reply, error,
00689 DBUS_TYPE_UINT32, &service_result,
00690 DBUS_TYPE_INVALID))
00691 {
00692 _DBUS_ASSERT_ERROR_IS_SET (error);
00693 dbus_message_unref (reply);
00694 return -1;
00695 }
00696
00697 dbus_message_unref (reply);
00698
00699 return service_result;
00700 }
00701
00710 dbus_bool_t
00711 dbus_bus_service_exists (DBusConnection *connection,
00712 const char *service_name,
00713 DBusError *error)
00714 {
00715 DBusMessage *message, *reply;
00716 dbus_bool_t exists;
00717
00718 _dbus_return_val_if_fail (connection != NULL, FALSE);
00719 _dbus_return_val_if_fail (service_name != NULL, FALSE);
00720 _dbus_return_val_if_error_is_set (error, FALSE);
00721
00722 message = dbus_message_new_method_call (DBUS_SERVICE_ORG_FREEDESKTOP_DBUS,
00723 DBUS_PATH_ORG_FREEDESKTOP_DBUS,
00724 DBUS_INTERFACE_ORG_FREEDESKTOP_DBUS,
00725 "ServiceExists");
00726 if (message == NULL)
00727 {
00728 _DBUS_SET_OOM (error);
00729 return FALSE;
00730 }
00731
00732 if (!dbus_message_append_args (message,
00733 DBUS_TYPE_STRING, service_name,
00734 DBUS_TYPE_INVALID))
00735 {
00736 dbus_message_unref (message);
00737 _DBUS_SET_OOM (error);
00738 return FALSE;
00739 }
00740
00741 reply = dbus_connection_send_with_reply_and_block (connection, message, -1, error);
00742 dbus_message_unref (message);
00743
00744 if (reply == NULL)
00745 {
00746 _DBUS_ASSERT_ERROR_IS_SET (error);
00747 return FALSE;
00748 }
00749
00750 if (!dbus_message_get_args (reply, error,
00751 DBUS_TYPE_BOOLEAN, &exists,
00752 DBUS_TYPE_INVALID))
00753 {
00754 _DBUS_ASSERT_ERROR_IS_SET (error);
00755 dbus_message_unref (reply);
00756 return FALSE;
00757 }
00758
00759 dbus_message_unref (reply);
00760 return exists;
00761 }
00762
00778 dbus_bool_t
00779 dbus_bus_activate_service (DBusConnection *connection,
00780 const char *service_name,
00781 dbus_uint32_t flags,
00782 dbus_uint32_t *result,
00783 DBusError *error)
00784 {
00785 DBusMessage *msg;
00786 DBusMessage *reply;
00787
00788 msg = dbus_message_new_method_call (DBUS_SERVICE_ORG_FREEDESKTOP_DBUS,
00789 DBUS_PATH_ORG_FREEDESKTOP_DBUS,
00790 DBUS_INTERFACE_ORG_FREEDESKTOP_DBUS,
00791 "ActivateService");
00792
00793 if (!dbus_message_append_args (msg, DBUS_TYPE_STRING, service_name,
00794 DBUS_TYPE_UINT32, flags, DBUS_TYPE_INVALID))
00795 {
00796 dbus_message_unref (msg);
00797 _DBUS_SET_OOM (error);
00798 return FALSE;
00799 }
00800
00801 reply = dbus_connection_send_with_reply_and_block (connection, msg,
00802 -1, error);
00803 dbus_message_unref (msg);
00804
00805 if (reply == NULL)
00806 {
00807 _DBUS_ASSERT_ERROR_IS_SET (error);
00808 return FALSE;
00809 }
00810
00811 if (dbus_set_error_from_message (error, reply))
00812 {
00813 _DBUS_ASSERT_ERROR_IS_SET (error);
00814 dbus_message_unref (reply);
00815 return FALSE;
00816 }
00817
00818 if (result != NULL &&
00819 !dbus_message_get_args (reply, error, DBUS_TYPE_UINT32,
00820 result, DBUS_TYPE_INVALID))
00821 {
00822 _DBUS_ASSERT_ERROR_IS_SET (error);
00823 dbus_message_unref (reply);
00824 return FALSE;
00825 }
00826
00827 dbus_message_unref (reply);
00828 return TRUE;
00829 }
00830
00831 static void
00832 send_no_return_values (DBusConnection *connection,
00833 DBusMessage *msg,
00834 DBusError *error)
00835 {
00836 if (error)
00837 {
00838
00839 DBusMessage *reply;
00840
00841 reply = dbus_connection_send_with_reply_and_block (connection, msg,
00842 -1, error);
00843
00844 if (reply == NULL)
00845 {
00846 _DBUS_ASSERT_ERROR_IS_SET (error);
00847 return;
00848 }
00849
00850 if (dbus_set_error_from_message (error, reply))
00851 {
00852 _DBUS_ASSERT_ERROR_IS_SET (error);
00853 dbus_message_unref (reply);
00854 return;
00855 }
00856
00857 dbus_message_unref (reply);
00858 }
00859 else
00860 {
00861
00862 if (!dbus_connection_send (connection, msg, NULL))
00863 return;
00864 }
00865 }
00866
00889 void
00890 dbus_bus_add_match (DBusConnection *connection,
00891 const char *rule,
00892 DBusError *error)
00893 {
00894 DBusMessage *msg;
00895
00896 msg = dbus_message_new_method_call (DBUS_SERVICE_ORG_FREEDESKTOP_DBUS,
00897 DBUS_PATH_ORG_FREEDESKTOP_DBUS,
00898 DBUS_INTERFACE_ORG_FREEDESKTOP_DBUS,
00899 "AddMatch");
00900
00901 if (!dbus_message_append_args (msg, DBUS_TYPE_STRING, rule,
00902 DBUS_TYPE_INVALID))
00903 {
00904 dbus_message_unref (msg);
00905 _DBUS_SET_OOM (error);
00906 return;
00907 }
00908
00909 send_no_return_values (connection, msg, error);
00910
00911 dbus_message_unref (msg);
00912 }
00913
00927 void
00928 dbus_bus_remove_match (DBusConnection *connection,
00929 const char *rule,
00930 DBusError *error)
00931 {
00932 DBusMessage *msg;
00933
00934 msg = dbus_message_new_method_call (DBUS_SERVICE_ORG_FREEDESKTOP_DBUS,
00935 DBUS_PATH_ORG_FREEDESKTOP_DBUS,
00936 DBUS_INTERFACE_ORG_FREEDESKTOP_DBUS,
00937 "RemoveMatch");
00938
00939 if (!dbus_message_append_args (msg, DBUS_TYPE_STRING, rule,
00940 DBUS_TYPE_INVALID))
00941 {
00942 dbus_message_unref (msg);
00943 _DBUS_SET_OOM (error);
00944 return;
00945 }
00946
00947 send_no_return_values (connection, msg, error);
00948
00949 dbus_message_unref (msg);
00950 }
00951