driver.c revision 8873c90f99303f9cc308f15f8d03e637911f5b9e
1/* -*- mode: C; c-file-style: "gnu" -*- */ 2/* driver.c Bus client (driver) 3 * 4 * Copyright (C) 2003 CodeFactory AB 5 * Copyright (C) 2003, 2004 Red Hat, Inc. 6 * 7 * Licensed under the Academic Free License version 2.1 8 * 9 * This program is free software; you can redistribute it and/or modify 10 * it under the terms of the GNU General Public License as published by 11 * the Free Software Foundation; either version 2 of the License, or 12 * (at your option) any later version. 13 * 14 * This program is distributed in the hope that it will be useful, 15 * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 * GNU General Public License for more details. 18 * 19 * You should have received a copy of the GNU General Public License 20 * along with this program; if not, write to the Free Software 21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 22 * 23 */ 24 25#include "activation.h" 26#include "connection.h" 27#include "driver.h" 28#include "dispatch.h" 29#include "services.h" 30#include "signals.h" 31#include "utils.h" 32#include <dbus/dbus-string.h> 33#include <dbus/dbus-internals.h> 34#include <string.h> 35 36static dbus_bool_t bus_driver_send_welcome_message (DBusConnection *connection, 37 DBusMessage *hello_message, 38 BusTransaction *transaction, 39 DBusError *error); 40 41dbus_bool_t 42bus_driver_send_service_owner_changed (const char *service_name, 43 const char *old_owner, 44 const char *new_owner, 45 BusTransaction *transaction, 46 DBusError *error) 47{ 48 DBusMessage *message; 49 dbus_bool_t retval; 50 const char *null_service; 51 52 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 53 54 null_service = ""; 55 _dbus_verbose ("sending name owner changed: %s [%s -> %s]\n", 56 service_name, 57 old_owner ? old_owner : null_service, 58 new_owner ? new_owner : null_service); 59 60 message = dbus_message_new_signal (DBUS_PATH_ORG_FREEDESKTOP_DBUS, 61 DBUS_INTERFACE_ORG_FREEDESKTOP_DBUS, 62 "NameOwnerChanged"); 63 64 if (message == NULL) 65 { 66 BUS_SET_OOM (error); 67 return FALSE; 68 } 69 70 if (!dbus_message_set_sender (message, DBUS_SERVICE_ORG_FREEDESKTOP_DBUS)) 71 goto oom; 72 73 if (!dbus_message_append_args (message, 74 DBUS_TYPE_STRING, &service_name, 75 DBUS_TYPE_STRING, old_owner ? &old_owner : &null_service, 76 DBUS_TYPE_STRING, new_owner ? &new_owner : &null_service, 77 DBUS_TYPE_INVALID)) 78 goto oom; 79 80 _dbus_assert (dbus_message_has_signature (message, "sss")); 81 82 retval = bus_dispatch_matches (transaction, NULL, NULL, message, error); 83 dbus_message_unref (message); 84 85 return retval; 86 87 oom: 88 dbus_message_unref (message); 89 BUS_SET_OOM (error); 90 return FALSE; 91} 92 93dbus_bool_t 94bus_driver_send_service_lost (DBusConnection *connection, 95 const char *service_name, 96 BusTransaction *transaction, 97 DBusError *error) 98{ 99 DBusMessage *message; 100 101 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 102 103 message = dbus_message_new_signal (DBUS_PATH_ORG_FREEDESKTOP_DBUS, 104 DBUS_INTERFACE_ORG_FREEDESKTOP_DBUS, 105 "NameLost"); 106 107 if (message == NULL) 108 { 109 BUS_SET_OOM (error); 110 return FALSE; 111 } 112 113 if (!dbus_message_set_destination (message, bus_connection_get_name (connection)) || 114 !dbus_message_append_args (message, 115 DBUS_TYPE_STRING, &service_name, 116 DBUS_TYPE_INVALID)) 117 { 118 dbus_message_unref (message); 119 BUS_SET_OOM (error); 120 return FALSE; 121 } 122 123 if (!bus_transaction_send_from_driver (transaction, connection, message)) 124 { 125 dbus_message_unref (message); 126 BUS_SET_OOM (error); 127 return FALSE; 128 } 129 else 130 { 131 dbus_message_unref (message); 132 return TRUE; 133 } 134} 135 136dbus_bool_t 137bus_driver_send_service_acquired (DBusConnection *connection, 138 const char *service_name, 139 BusTransaction *transaction, 140 DBusError *error) 141{ 142 DBusMessage *message; 143 144 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 145 146 message = dbus_message_new_signal (DBUS_PATH_ORG_FREEDESKTOP_DBUS, 147 DBUS_INTERFACE_ORG_FREEDESKTOP_DBUS, 148 "NameAcquired"); 149 150 if (message == NULL) 151 { 152 BUS_SET_OOM (error); 153 return FALSE; 154 } 155 156 if (!dbus_message_set_destination (message, bus_connection_get_name (connection)) || 157 !dbus_message_append_args (message, 158 DBUS_TYPE_STRING, &service_name, 159 DBUS_TYPE_INVALID)) 160 { 161 dbus_message_unref (message); 162 BUS_SET_OOM (error); 163 return FALSE; 164 } 165 166 if (!bus_transaction_send_from_driver (transaction, connection, message)) 167 { 168 dbus_message_unref (message); 169 BUS_SET_OOM (error); 170 return FALSE; 171 } 172 else 173 { 174 dbus_message_unref (message); 175 return TRUE; 176 } 177} 178 179static dbus_bool_t 180create_unique_client_name (BusRegistry *registry, 181 DBusString *str) 182{ 183 /* We never want to use the same unique client name twice, because 184 * we want to guarantee that if you send a message to a given unique 185 * name, you always get the same application. So we use two numbers 186 * for INT_MAX * INT_MAX combinations, should be pretty safe against 187 * wraparound. 188 */ 189 /* FIXME these should be in BusRegistry rather than static vars */ 190 static int next_major_number = 0; 191 static int next_minor_number = 0; 192 int len; 193 194 len = _dbus_string_get_length (str); 195 196 while (TRUE) 197 { 198 /* start out with 1-0, go to 1-1, 1-2, 1-3, 199 * up to 1-MAXINT, then 2-0, 2-1, etc. 200 */ 201 if (next_minor_number <= 0) 202 { 203 next_major_number += 1; 204 next_minor_number = 0; 205 if (next_major_number <= 0) 206 _dbus_assert_not_reached ("INT_MAX * INT_MAX clients were added"); 207 } 208 209 _dbus_assert (next_major_number > 0); 210 _dbus_assert (next_minor_number >= 0); 211 212 /* appname:MAJOR-MINOR */ 213 214 if (!_dbus_string_append (str, ":")) 215 return FALSE; 216 217 if (!_dbus_string_append_int (str, next_major_number)) 218 return FALSE; 219 220 if (!_dbus_string_append (str, ".")) 221 return FALSE; 222 223 if (!_dbus_string_append_int (str, next_minor_number)) 224 return FALSE; 225 226 next_minor_number += 1; 227 228 /* Check if a client with the name exists */ 229 if (bus_registry_lookup (registry, str) == NULL) 230 break; 231 232 /* drop the number again, try the next one. */ 233 _dbus_string_set_length (str, len); 234 } 235 236 return TRUE; 237} 238 239static dbus_bool_t 240bus_driver_handle_hello (DBusConnection *connection, 241 BusTransaction *transaction, 242 DBusMessage *message, 243 DBusError *error) 244{ 245 DBusString unique_name; 246 BusService *service; 247 dbus_bool_t retval; 248 BusRegistry *registry; 249 BusConnections *connections; 250 251 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 252 253 if (bus_connection_is_active (connection)) 254 { 255 /* We already handled an Hello message for this connection. */ 256 dbus_set_error (error, DBUS_ERROR_FAILED, 257 "Already handled an Hello message"); 258 return FALSE; 259 } 260 261 /* Note that when these limits are exceeded we don't disconnect the 262 * connection; we just sort of leave it hanging there until it times 263 * out or disconnects itself or is dropped due to the max number of 264 * incomplete connections. It's even OK if the connection wants to 265 * retry the hello message, we support that. 266 */ 267 connections = bus_connection_get_connections (connection); 268 if (!bus_connections_check_limits (connections, connection, 269 error)) 270 { 271 _DBUS_ASSERT_ERROR_IS_SET (error); 272 return FALSE; 273 } 274 275 if (!_dbus_string_init (&unique_name)) 276 { 277 BUS_SET_OOM (error); 278 return FALSE; 279 } 280 281 retval = FALSE; 282 283 registry = bus_connection_get_registry (connection); 284 285 if (!create_unique_client_name (registry, &unique_name)) 286 { 287 BUS_SET_OOM (error); 288 goto out_0; 289 } 290 291 if (!bus_connection_complete (connection, &unique_name, error)) 292 { 293 _DBUS_ASSERT_ERROR_IS_SET (error); 294 goto out_0; 295 } 296 297 if (!dbus_message_set_sender (message, 298 bus_connection_get_name (connection))) 299 { 300 BUS_SET_OOM (error); 301 goto out_0; 302 } 303 304 if (!bus_driver_send_welcome_message (connection, message, transaction, error)) 305 goto out_0; 306 307 /* Create the service */ 308 service = bus_registry_ensure (registry, 309 &unique_name, connection, transaction, error); 310 if (service == NULL) 311 goto out_0; 312 313 bus_service_set_prohibit_replacement (service, TRUE); 314 315 _dbus_assert (bus_connection_is_active (connection)); 316 retval = TRUE; 317 318 out_0: 319 _dbus_string_free (&unique_name); 320 return retval; 321} 322 323static dbus_bool_t 324bus_driver_send_welcome_message (DBusConnection *connection, 325 DBusMessage *hello_message, 326 BusTransaction *transaction, 327 DBusError *error) 328{ 329 DBusMessage *welcome; 330 const char *name; 331 332 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 333 334 name = bus_connection_get_name (connection); 335 _dbus_assert (name != NULL); 336 337 welcome = dbus_message_new_method_return (hello_message); 338 if (welcome == NULL) 339 { 340 BUS_SET_OOM (error); 341 return FALSE; 342 } 343 344 if (!dbus_message_append_args (welcome, 345 DBUS_TYPE_STRING, &name, 346 DBUS_TYPE_INVALID)) 347 { 348 dbus_message_unref (welcome); 349 BUS_SET_OOM (error); 350 return FALSE; 351 } 352 353 _dbus_assert (dbus_message_has_signature (welcome, "s")); 354 355 if (!bus_transaction_send_from_driver (transaction, connection, welcome)) 356 { 357 dbus_message_unref (welcome); 358 BUS_SET_OOM (error); 359 return FALSE; 360 } 361 else 362 { 363 dbus_message_unref (welcome); 364 return TRUE; 365 } 366} 367 368static dbus_bool_t 369bus_driver_handle_list_services (DBusConnection *connection, 370 BusTransaction *transaction, 371 DBusMessage *message, 372 DBusError *error) 373{ 374 DBusMessage *reply; 375 int len; 376 char **services; 377 BusRegistry *registry; 378 int i; 379 DBusMessageIter iter; 380 DBusMessageIter sub; 381 382 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 383 384 registry = bus_connection_get_registry (connection); 385 386 reply = dbus_message_new_method_return (message); 387 if (reply == NULL) 388 { 389 BUS_SET_OOM (error); 390 return FALSE; 391 } 392 393 if (!bus_registry_list_services (registry, &services, &len)) 394 { 395 dbus_message_unref (reply); 396 BUS_SET_OOM (error); 397 return FALSE; 398 } 399 400 dbus_message_iter_init_append (reply, &iter); 401 402 if (!dbus_message_iter_open_container (&iter, DBUS_TYPE_ARRAY, 403 DBUS_TYPE_STRING_AS_STRING, 404 &sub)) 405 { 406 dbus_free_string_array (services); 407 dbus_message_unref (reply); 408 BUS_SET_OOM (error); 409 return FALSE; 410 } 411 412 i = 0; 413 while (i < len) 414 { 415 if (!dbus_message_iter_append_basic (&sub, DBUS_TYPE_STRING, 416 &services[i])) 417 { 418 dbus_free_string_array (services); 419 dbus_message_unref (reply); 420 BUS_SET_OOM (error); 421 return FALSE; 422 } 423 ++i; 424 } 425 426 if (!dbus_message_iter_close_container (&iter, &sub)) 427 { 428 dbus_free_string_array (services); 429 dbus_message_unref (reply); 430 BUS_SET_OOM (error); 431 return FALSE; 432 } 433 434 dbus_free_string_array (services); 435 436 if (!bus_transaction_send_from_driver (transaction, connection, reply)) 437 { 438 dbus_message_unref (reply); 439 BUS_SET_OOM (error); 440 return FALSE; 441 } 442 else 443 { 444 dbus_message_unref (reply); 445 return TRUE; 446 } 447} 448 449static dbus_bool_t 450bus_driver_handle_acquire_service (DBusConnection *connection, 451 BusTransaction *transaction, 452 DBusMessage *message, 453 DBusError *error) 454{ 455 DBusMessage *reply; 456 DBusString service_name; 457 const char *name; 458 int service_reply; 459 dbus_uint32_t flags; 460 dbus_bool_t retval; 461 BusRegistry *registry; 462 463 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 464 465 registry = bus_connection_get_registry (connection); 466 467 if (!dbus_message_get_args (message, error, 468 DBUS_TYPE_STRING, &name, 469 DBUS_TYPE_UINT32, &flags, 470 DBUS_TYPE_INVALID)) 471 return FALSE; 472 473 _dbus_verbose ("Trying to own service %s with flags 0x%x\n", name, flags); 474 475 retval = FALSE; 476 reply = NULL; 477 478 _dbus_string_init_const (&service_name, name); 479 480 if (!bus_registry_acquire_service (registry, connection, 481 &service_name, flags, 482 &service_reply, transaction, 483 error)) 484 goto out; 485 486 reply = dbus_message_new_method_return (message); 487 if (reply == NULL) 488 { 489 BUS_SET_OOM (error); 490 goto out; 491 } 492 493 if (!dbus_message_append_args (reply, DBUS_TYPE_UINT32, &service_reply, DBUS_TYPE_INVALID)) 494 { 495 BUS_SET_OOM (error); 496 goto out; 497 } 498 499 if (!bus_transaction_send_from_driver (transaction, connection, reply)) 500 { 501 BUS_SET_OOM (error); 502 goto out; 503 } 504 505 retval = TRUE; 506 507 out: 508 if (reply) 509 dbus_message_unref (reply); 510 return retval; 511} 512 513static dbus_bool_t 514bus_driver_handle_service_exists (DBusConnection *connection, 515 BusTransaction *transaction, 516 DBusMessage *message, 517 DBusError *error) 518{ 519 DBusMessage *reply; 520 DBusString service_name; 521 BusService *service; 522 dbus_bool_t service_exists; 523 const char *name; 524 dbus_bool_t retval; 525 BusRegistry *registry; 526 527 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 528 529 registry = bus_connection_get_registry (connection); 530 531 if (!dbus_message_get_args (message, error, 532 DBUS_TYPE_STRING, &name, 533 DBUS_TYPE_INVALID)) 534 return FALSE; 535 536 retval = FALSE; 537 538 if (strcmp (name, DBUS_SERVICE_ORG_FREEDESKTOP_DBUS) == 0) 539 { 540 service_exists = TRUE; 541 } 542 else 543 { 544 _dbus_string_init_const (&service_name, name); 545 service = bus_registry_lookup (registry, &service_name); 546 service_exists = service != NULL; 547 } 548 549 reply = dbus_message_new_method_return (message); 550 if (reply == NULL) 551 { 552 BUS_SET_OOM (error); 553 goto out; 554 } 555 556 if (!dbus_message_append_args (reply, 557 DBUS_TYPE_BOOLEAN, &service_exists, 558 0)) 559 { 560 BUS_SET_OOM (error); 561 goto out; 562 } 563 564 if (!bus_transaction_send_from_driver (transaction, connection, reply)) 565 { 566 BUS_SET_OOM (error); 567 goto out; 568 } 569 570 retval = TRUE; 571 572 out: 573 if (reply) 574 dbus_message_unref (reply); 575 576 return retval; 577} 578 579static dbus_bool_t 580bus_driver_handle_activate_service (DBusConnection *connection, 581 BusTransaction *transaction, 582 DBusMessage *message, 583 DBusError *error) 584{ 585 dbus_uint32_t flags; 586 const char *name; 587 dbus_bool_t retval; 588 BusActivation *activation; 589 590 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 591 592 activation = bus_connection_get_activation (connection); 593 594 if (!dbus_message_get_args (message, error, 595 DBUS_TYPE_STRING, &name, 596 DBUS_TYPE_UINT32, &flags, 597 DBUS_TYPE_INVALID)) 598 { 599 _DBUS_ASSERT_ERROR_IS_SET (error); 600 _dbus_verbose ("No memory to get arguments to StartServiceByName\n"); 601 return FALSE; 602 } 603 604 retval = FALSE; 605 606 if (!bus_activation_activate_service (activation, connection, transaction, FALSE, 607 message, name, error)) 608 { 609 _DBUS_ASSERT_ERROR_IS_SET (error); 610 _dbus_verbose ("bus_activation_activate_service() failed\n"); 611 goto out; 612 } 613 614 retval = TRUE; 615 616 out: 617 return retval; 618} 619 620static dbus_bool_t 621send_ack_reply (DBusConnection *connection, 622 BusTransaction *transaction, 623 DBusMessage *message, 624 DBusError *error) 625{ 626 DBusMessage *reply; 627 628 reply = dbus_message_new_method_return (message); 629 if (reply == NULL) 630 { 631 BUS_SET_OOM (error); 632 return FALSE; 633 } 634 635 if (!bus_transaction_send_from_driver (transaction, connection, reply)) 636 { 637 BUS_SET_OOM (error); 638 dbus_message_unref (reply); 639 return FALSE; 640 } 641 642 dbus_message_unref (reply); 643 644 return TRUE; 645} 646 647static dbus_bool_t 648bus_driver_handle_add_match (DBusConnection *connection, 649 BusTransaction *transaction, 650 DBusMessage *message, 651 DBusError *error) 652{ 653 BusMatchRule *rule; 654 const char *text; 655 DBusString str; 656 BusMatchmaker *matchmaker; 657 658 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 659 660 text = NULL; 661 rule = NULL; 662 663 if (bus_connection_get_n_match_rules (connection) >= 664 bus_context_get_max_match_rules_per_connection (bus_transaction_get_context (transaction))) 665 { 666 dbus_set_error (error, DBUS_ERROR_LIMITS_EXCEEDED, 667 "Connection \"%s\" is not allowed to add more match rules " 668 "(increase limits in configuration file if required)", 669 bus_connection_is_active (connection) ? 670 bus_connection_get_name (connection) : 671 "(inactive)"); 672 goto failed; 673 } 674 675 if (!dbus_message_get_args (message, error, 676 DBUS_TYPE_STRING, &text, 677 DBUS_TYPE_INVALID)) 678 { 679 _dbus_verbose ("No memory to get arguments to AddMatch\n"); 680 goto failed; 681 } 682 683 _dbus_string_init_const (&str, text); 684 685 rule = bus_match_rule_parse (connection, &str, error); 686 if (rule == NULL) 687 goto failed; 688 689 matchmaker = bus_connection_get_matchmaker (connection); 690 691 if (!bus_matchmaker_add_rule (matchmaker, rule)) 692 { 693 BUS_SET_OOM (error); 694 goto failed; 695 } 696 697 if (!send_ack_reply (connection, transaction, 698 message, error)) 699 { 700 bus_matchmaker_remove_rule (matchmaker, rule); 701 goto failed; 702 } 703 704 bus_match_rule_unref (rule); 705 706 return TRUE; 707 708 failed: 709 _DBUS_ASSERT_ERROR_IS_SET (error); 710 if (rule) 711 bus_match_rule_unref (rule); 712 return FALSE; 713} 714 715static dbus_bool_t 716bus_driver_handle_remove_match (DBusConnection *connection, 717 BusTransaction *transaction, 718 DBusMessage *message, 719 DBusError *error) 720{ 721 BusMatchRule *rule; 722 const char *text; 723 DBusString str; 724 BusMatchmaker *matchmaker; 725 726 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 727 728 text = NULL; 729 rule = NULL; 730 731 if (!dbus_message_get_args (message, error, 732 DBUS_TYPE_STRING, &text, 733 DBUS_TYPE_INVALID)) 734 { 735 _dbus_verbose ("No memory to get arguments to RemoveMatch\n"); 736 goto failed; 737 } 738 739 _dbus_string_init_const (&str, text); 740 741 rule = bus_match_rule_parse (connection, &str, error); 742 if (rule == NULL) 743 goto failed; 744 745 /* Send the ack before we remove the rule, since the ack is undone 746 * on transaction cancel, but rule removal isn't. 747 */ 748 if (!send_ack_reply (connection, transaction, 749 message, error)) 750 goto failed; 751 752 matchmaker = bus_connection_get_matchmaker (connection); 753 754 if (!bus_matchmaker_remove_rule_by_value (matchmaker, rule, error)) 755 goto failed; 756 757 bus_match_rule_unref (rule); 758 759 return TRUE; 760 761 failed: 762 _DBUS_ASSERT_ERROR_IS_SET (error); 763 if (rule) 764 bus_match_rule_unref (rule); 765 return FALSE; 766} 767 768static dbus_bool_t 769bus_driver_handle_get_service_owner (DBusConnection *connection, 770 BusTransaction *transaction, 771 DBusMessage *message, 772 DBusError *error) 773{ 774 const char *text; 775 const char *base_name; 776 DBusString str; 777 BusRegistry *registry; 778 BusService *service; 779 DBusMessage *reply; 780 781 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 782 783 registry = bus_connection_get_registry (connection); 784 785 text = NULL; 786 reply = NULL; 787 788 if (! dbus_message_get_args (message, error, 789 DBUS_TYPE_STRING, &text, 790 DBUS_TYPE_INVALID)) 791 goto failed; 792 793 _dbus_string_init_const (&str, text); 794 service = bus_registry_lookup (registry, &str); 795 if (service == NULL) 796 { 797 dbus_set_error (error, 798 DBUS_ERROR_NAME_HAS_NO_OWNER, 799 "Could not get owner of name '%s': no such name", text); 800 goto failed; 801 } 802 803 base_name = bus_connection_get_name (bus_service_get_primary_owner (service)); 804 if (base_name == NULL) 805 { 806 /* FIXME - how is this error possible? */ 807 dbus_set_error (error, 808 DBUS_ERROR_FAILED, 809 "Could not determine unique name for '%s'", text); 810 goto failed; 811 } 812 _dbus_assert (*base_name == ':'); 813 814 reply = dbus_message_new_method_return (message); 815 if (reply == NULL) 816 goto oom; 817 818 if (! dbus_message_append_args (reply, 819 DBUS_TYPE_STRING, &base_name, 820 DBUS_TYPE_INVALID)) 821 goto oom; 822 823 if (! bus_transaction_send_from_driver (transaction, connection, reply)) 824 goto oom; 825 826 dbus_message_unref (reply); 827 828 return TRUE; 829 830 oom: 831 BUS_SET_OOM (error); 832 833 failed: 834 _DBUS_ASSERT_ERROR_IS_SET (error); 835 if (reply) 836 dbus_message_unref (reply); 837 return FALSE; 838} 839 840static dbus_bool_t 841bus_driver_handle_get_connection_unix_user (DBusConnection *connection, 842 BusTransaction *transaction, 843 DBusMessage *message, 844 DBusError *error) 845{ 846 const char *service; 847 DBusString str; 848 BusRegistry *registry; 849 BusService *serv; 850 DBusConnection *conn; 851 DBusMessage *reply; 852 unsigned long uid; 853 dbus_uint32_t uid32; 854 855 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 856 857 registry = bus_connection_get_registry (connection); 858 859 service = NULL; 860 reply = NULL; 861 862 if (! dbus_message_get_args (message, error, 863 DBUS_TYPE_STRING, &service, 864 DBUS_TYPE_INVALID)) 865 goto failed; 866 867 _dbus_verbose ("asked for UID of connection %s\n", service); 868 869 _dbus_string_init_const (&str, service); 870 serv = bus_registry_lookup (registry, &str); 871 if (serv == NULL) 872 { 873 dbus_set_error (error, 874 DBUS_ERROR_NAME_HAS_NO_OWNER, 875 "Could not get UID of name '%s': no such name", service); 876 goto failed; 877 } 878 879 conn = bus_service_get_primary_owner (serv); 880 881 reply = dbus_message_new_method_return (message); 882 if (reply == NULL) 883 goto oom; 884 885 if (!dbus_connection_get_unix_user (conn, &uid)) 886 { 887 dbus_set_error (error, 888 DBUS_ERROR_FAILED, 889 "Could not determine UID for '%s'", service); 890 goto failed; 891 } 892 893 uid32 = uid; 894 if (! dbus_message_append_args (reply, 895 DBUS_TYPE_UINT32, &uid32, 896 DBUS_TYPE_INVALID)) 897 goto oom; 898 899 if (! bus_transaction_send_from_driver (transaction, connection, reply)) 900 goto oom; 901 902 dbus_message_unref (reply); 903 904 return TRUE; 905 906 oom: 907 BUS_SET_OOM (error); 908 909 failed: 910 _DBUS_ASSERT_ERROR_IS_SET (error); 911 if (reply) 912 dbus_message_unref (reply); 913 return FALSE; 914} 915 916static dbus_bool_t 917bus_driver_handle_get_connection_unix_process_id (DBusConnection *connection, 918 BusTransaction *transaction, 919 DBusMessage *message, 920 DBusError *error) 921{ 922 const char *service; 923 DBusString str; 924 BusRegistry *registry; 925 BusService *serv; 926 DBusConnection *conn; 927 DBusMessage *reply; 928 unsigned long pid; 929 dbus_uint32_t pid32; 930 931 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 932 933 registry = bus_connection_get_registry (connection); 934 935 service = NULL; 936 reply = NULL; 937 938 if (! dbus_message_get_args (message, error, 939 DBUS_TYPE_STRING, &service, 940 DBUS_TYPE_INVALID)) 941 goto failed; 942 943 _dbus_verbose ("asked for PID of connection %s\n", service); 944 945 _dbus_string_init_const (&str, service); 946 serv = bus_registry_lookup (registry, &str); 947 if (serv == NULL) 948 { 949 dbus_set_error (error, 950 DBUS_ERROR_NAME_HAS_NO_OWNER, 951 "Could not get PID of name '%s': no such name", service); 952 goto failed; 953 } 954 955 conn = bus_service_get_primary_owner (serv); 956 957 reply = dbus_message_new_method_return (message); 958 if (reply == NULL) 959 goto oom; 960 961 if (!dbus_connection_get_unix_process_id (conn, &pid)) 962 { 963 dbus_set_error (error, 964 DBUS_ERROR_UNIX_PROCESS_ID_UNKNOWN, 965 "Could not determine PID for '%s'", service); 966 goto failed; 967 } 968 969 pid32 = pid; 970 if (! dbus_message_append_args (reply, 971 DBUS_TYPE_UINT32, &pid32, 972 DBUS_TYPE_INVALID)) 973 goto oom; 974 975 if (! bus_transaction_send_from_driver (transaction, connection, reply)) 976 goto oom; 977 978 dbus_message_unref (reply); 979 980 return TRUE; 981 982 oom: 983 BUS_SET_OOM (error); 984 985 failed: 986 _DBUS_ASSERT_ERROR_IS_SET (error); 987 if (reply) 988 dbus_message_unref (reply); 989 return FALSE; 990} 991 992static dbus_bool_t 993bus_driver_handle_reload_config (DBusConnection *connection, 994 BusTransaction *transaction, 995 DBusMessage *message, 996 DBusError *error) 997{ 998 BusContext *context; 999 dbus_bool_t retval; 1000 1001 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 1002 1003 retval = FALSE; 1004 1005 context = bus_connection_get_context (connection); 1006 if (!bus_context_reload_config (context, error)) 1007 { 1008 _DBUS_ASSERT_ERROR_IS_SET (error); 1009 goto out; 1010 } 1011 1012 retval = TRUE; 1013 1014 out: 1015 return retval; 1016} 1017 1018/* For speed it might be useful to sort this in order of 1019 * frequency of use (but doesn't matter with only a few items 1020 * anyhow) 1021 */ 1022struct 1023{ 1024 const char *name; 1025 dbus_bool_t (* handler) (DBusConnection *connection, 1026 BusTransaction *transaction, 1027 DBusMessage *message, 1028 DBusError *error); 1029} message_handlers[] = { 1030 { "RequestName", bus_driver_handle_acquire_service }, 1031 { "StartServiceByName", bus_driver_handle_activate_service }, 1032 { "Hello", bus_driver_handle_hello }, 1033 { "NameHasOwner", bus_driver_handle_service_exists }, 1034 { "ListNames", bus_driver_handle_list_services }, 1035 { "AddMatch", bus_driver_handle_add_match }, 1036 { "RemoveMatch", bus_driver_handle_remove_match }, 1037 { "GetNameOwner", bus_driver_handle_get_service_owner }, 1038 { "GetConnectionUnixUser", bus_driver_handle_get_connection_unix_user }, 1039 { "GetConnectionUnixProcessID", bus_driver_handle_get_connection_unix_process_id }, 1040 { "ReloadConfig", bus_driver_handle_reload_config } 1041}; 1042 1043dbus_bool_t 1044bus_driver_handle_message (DBusConnection *connection, 1045 BusTransaction *transaction, 1046 DBusMessage *message, 1047 DBusError *error) 1048{ 1049 const char *name, *sender; 1050 int i; 1051 1052 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 1053 1054 if (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_METHOD_CALL) 1055 { 1056 _dbus_verbose ("Driver got a non-method-call message, ignoring\n"); 1057 return TRUE; /* we just ignore this */ 1058 } 1059 1060 _dbus_assert (dbus_message_get_interface (message) != NULL); 1061 _dbus_assert (dbus_message_get_member (message) != NULL); 1062 1063 name = dbus_message_get_member (message); 1064 sender = dbus_message_get_sender (message); 1065 1066 if (strcmp (dbus_message_get_interface (message), 1067 DBUS_INTERFACE_ORG_FREEDESKTOP_DBUS) != 0) 1068 { 1069 _dbus_verbose ("Driver got message to unknown interface \"%s\"\n", 1070 dbus_message_get_interface (message)); 1071 goto unknown; 1072 } 1073 1074 _dbus_verbose ("Driver got a method call: %s\n", 1075 dbus_message_get_member (message)); 1076 1077 /* security checks should have kept this from getting here */ 1078 _dbus_assert (sender != NULL || strcmp (name, "Hello") == 0); 1079 1080 if (dbus_message_get_reply_serial (message) != 0) 1081 { 1082 _dbus_verbose ("Client sent a reply to the bus driver, ignoring it\n"); 1083 return TRUE; 1084 } 1085 1086 i = 0; 1087 while (i < _DBUS_N_ELEMENTS (message_handlers)) 1088 { 1089 if (strcmp (message_handlers[i].name, name) == 0) 1090 { 1091 _dbus_verbose ("Running driver handler for %s\n", name); 1092 if ((* message_handlers[i].handler) (connection, transaction, message, error)) 1093 { 1094 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 1095 _dbus_verbose ("Driver handler succeeded\n"); 1096 return TRUE; 1097 } 1098 else 1099 { 1100 _DBUS_ASSERT_ERROR_IS_SET (error); 1101 _dbus_verbose ("Driver handler returned failure\n"); 1102 return FALSE; 1103 } 1104 } 1105 1106 ++i; 1107 } 1108 1109 unknown: 1110 _dbus_verbose ("No driver handler for message \"%s\"\n", 1111 name); 1112 1113 dbus_set_error (error, DBUS_ERROR_UNKNOWN_METHOD, 1114 "%s does not understand message %s", 1115 DBUS_SERVICE_ORG_FREEDESKTOP_DBUS, name); 1116 1117 return FALSE; 1118} 1119 1120void 1121bus_driver_remove_connection (DBusConnection *connection) 1122{ 1123 /* FIXME Does nothing for now, should unregister the connection 1124 * with the bus driver. 1125 */ 1126} 1127