diff options
| author | Joakim Verona | 2010-10-18 22:05:07 +0200 |
|---|---|---|
| committer | Joakim Verona | 2010-10-18 22:05:07 +0200 |
| commit | 13cfe8df462ab8da9f0028e16cc84dcaceaca3d1 (patch) | |
| tree | 723f254768f9e503504ab4c8b68801f80a56591a /src/dbusbind.c | |
| parent | 35f4b80a934b299b3b18e62f5db44f64c240e65b (diff) | |
| parent | e48eb34332dc91de823314090451459ba2ffacbf (diff) | |
| download | emacs-13cfe8df462ab8da9f0028e16cc84dcaceaca3d1.tar.gz emacs-13cfe8df462ab8da9f0028e16cc84dcaceaca3d1.zip | |
merge from upstream
Diffstat (limited to 'src/dbusbind.c')
| -rw-r--r-- | src/dbusbind.c | 239 |
1 files changed, 112 insertions, 127 deletions
diff --git a/src/dbusbind.c b/src/dbusbind.c index 3b6f0e543bb..683b7cb583b 100644 --- a/src/dbusbind.c +++ b/src/dbusbind.c | |||
| @@ -19,7 +19,6 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ | |||
| 19 | #include <config.h> | 19 | #include <config.h> |
| 20 | 20 | ||
| 21 | #ifdef HAVE_DBUS | 21 | #ifdef HAVE_DBUS |
| 22 | #include <stdlib.h> | ||
| 23 | #include <stdio.h> | 22 | #include <stdio.h> |
| 24 | #include <dbus/dbus.h> | 23 | #include <dbus/dbus.h> |
| 25 | #include <setjmp.h> | 24 | #include <setjmp.h> |
| @@ -27,6 +26,7 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ | |||
| 27 | #include "frame.h" | 26 | #include "frame.h" |
| 28 | #include "termhooks.h" | 27 | #include "termhooks.h" |
| 29 | #include "keyboard.h" | 28 | #include "keyboard.h" |
| 29 | #include "process.h" | ||
| 30 | 30 | ||
| 31 | 31 | ||
| 32 | /* Subroutines. */ | 32 | /* Subroutines. */ |
| @@ -799,71 +799,84 @@ xd_initialize (Lisp_Object bus, int raise_error) | |||
| 799 | return connection; | 799 | return connection; |
| 800 | } | 800 | } |
| 801 | 801 | ||
| 802 | 802 | /* Return the file descriptor for WATCH, -1 if not found. */ | |
| 803 | /* Add connection file descriptor to input_wait_mask, in order to | 803 | static int |
| 804 | let select() detect, whether a new message has been arrived. */ | 804 | xd_find_watch_fd (DBusWatch *watch) |
| 805 | dbus_bool_t | ||
| 806 | xd_add_watch (DBusWatch *watch, void *data) | ||
| 807 | { | 805 | { |
| 808 | /* We check only for incoming data. */ | ||
| 809 | if (dbus_watch_get_flags (watch) & DBUS_WATCH_READABLE) | ||
| 810 | { | ||
| 811 | #if HAVE_DBUS_WATCH_GET_UNIX_FD | 806 | #if HAVE_DBUS_WATCH_GET_UNIX_FD |
| 812 | /* TODO: Reverse these on Win32, which prefers the opposite. */ | 807 | /* TODO: Reverse these on Win32, which prefers the opposite. */ |
| 813 | int fd = dbus_watch_get_unix_fd(watch); | 808 | int fd = dbus_watch_get_unix_fd (watch); |
| 814 | if (fd == -1) | 809 | if (fd == -1) |
| 815 | fd = dbus_watch_get_socket(watch); | 810 | fd = dbus_watch_get_socket (watch); |
| 816 | #else | 811 | #else |
| 817 | int fd = dbus_watch_get_fd(watch); | 812 | int fd = dbus_watch_get_fd (watch); |
| 818 | #endif | 813 | #endif |
| 819 | XD_DEBUG_MESSAGE ("fd %d", fd); | 814 | return fd; |
| 815 | } | ||
| 820 | 816 | ||
| 821 | if (fd == -1) | 817 | /* Prototype. */ |
| 822 | return FALSE; | 818 | static void |
| 819 | xd_read_queued_messages (int fd, void *data, int for_read); | ||
| 823 | 820 | ||
| 824 | /* Add the file descriptor to input_wait_mask. */ | 821 | /* Start monitoring WATCH for possible I/O. */ |
| 825 | add_keyboard_wait_descriptor (fd); | 822 | static dbus_bool_t |
| 826 | } | 823 | xd_add_watch (DBusWatch *watch, void *data) |
| 824 | { | ||
| 825 | unsigned int flags = dbus_watch_get_flags (watch); | ||
| 826 | int fd = xd_find_watch_fd (watch); | ||
| 827 | 827 | ||
| 828 | /* Return. */ | 828 | XD_DEBUG_MESSAGE ("fd %d, write %d, enabled %d", |
| 829 | fd, flags & DBUS_WATCH_WRITABLE, | ||
| 830 | dbus_watch_get_enabled (watch)); | ||
| 831 | |||
| 832 | if (fd == -1) | ||
| 833 | return FALSE; | ||
| 834 | |||
| 835 | if (dbus_watch_get_enabled (watch)) | ||
| 836 | { | ||
| 837 | if (flags & DBUS_WATCH_WRITABLE) | ||
| 838 | add_write_fd (fd, xd_read_queued_messages, data); | ||
| 839 | if (flags & DBUS_WATCH_READABLE) | ||
| 840 | add_read_fd (fd, xd_read_queued_messages, data); | ||
| 841 | } | ||
| 829 | return TRUE; | 842 | return TRUE; |
| 830 | } | 843 | } |
| 831 | 844 | ||
| 832 | /* Remove connection file descriptor from input_wait_mask. DATA is | 845 | /* Stop monitoring WATCH for possible I/O. |
| 833 | the used bus, either a string or QCdbus_system_bus or | 846 | DATA is the used bus, either a string or QCdbus_system_bus or |
| 834 | QCdbus_session_bus. */ | 847 | QCdbus_session_bus. */ |
| 835 | void | 848 | static void |
| 836 | xd_remove_watch (DBusWatch *watch, void *data) | 849 | xd_remove_watch (DBusWatch *watch, void *data) |
| 837 | { | 850 | { |
| 838 | /* We check only for incoming data. */ | 851 | unsigned int flags = dbus_watch_get_flags (watch); |
| 839 | if (dbus_watch_get_flags (watch) & DBUS_WATCH_READABLE) | 852 | int fd = xd_find_watch_fd (watch); |
| 840 | { | ||
| 841 | #if HAVE_DBUS_WATCH_GET_UNIX_FD | ||
| 842 | /* TODO: Reverse these on Win32, which prefers the opposite. */ | ||
| 843 | int fd = dbus_watch_get_unix_fd(watch); | ||
| 844 | if (fd == -1) | ||
| 845 | fd = dbus_watch_get_socket(watch); | ||
| 846 | #else | ||
| 847 | int fd = dbus_watch_get_fd(watch); | ||
| 848 | #endif | ||
| 849 | XD_DEBUG_MESSAGE ("fd %d", fd); | ||
| 850 | 853 | ||
| 851 | if (fd == -1) | 854 | XD_DEBUG_MESSAGE ("fd %d", fd); |
| 852 | return; | ||
| 853 | 855 | ||
| 854 | /* Unset session environment. */ | 856 | if (fd == -1) |
| 855 | if ((data != NULL) && (data == (void*) XHASH (QCdbus_session_bus))) | 857 | return; |
| 856 | { | ||
| 857 | XD_DEBUG_MESSAGE ("unsetenv DBUS_SESSION_BUS_ADDRESS"); | ||
| 858 | unsetenv ("DBUS_SESSION_BUS_ADDRESS"); | ||
| 859 | } | ||
| 860 | 858 | ||
| 861 | /* Remove the file descriptor from input_wait_mask. */ | 859 | /* Unset session environment. */ |
| 862 | delete_keyboard_wait_descriptor (fd); | 860 | if (data != NULL && data == (void*) XHASH (QCdbus_session_bus)) |
| 861 | { | ||
| 862 | XD_DEBUG_MESSAGE ("unsetenv DBUS_SESSION_BUS_ADDRESS"); | ||
| 863 | unsetenv ("DBUS_SESSION_BUS_ADDRESS"); | ||
| 863 | } | 864 | } |
| 864 | 865 | ||
| 865 | /* Return. */ | 866 | if (flags & DBUS_WATCH_WRITABLE) |
| 866 | return; | 867 | delete_write_fd (fd); |
| 868 | if (flags & DBUS_WATCH_READABLE) | ||
| 869 | delete_read_fd (fd); | ||
| 870 | } | ||
| 871 | |||
| 872 | /* Toggle monitoring WATCH for possible I/O. */ | ||
| 873 | static void | ||
| 874 | xd_toggle_watch (DBusWatch *watch, void *data) | ||
| 875 | { | ||
| 876 | if (dbus_watch_get_enabled (watch)) | ||
| 877 | xd_add_watch (watch, data); | ||
| 878 | else | ||
| 879 | xd_remove_watch (watch, data); | ||
| 867 | } | 880 | } |
| 868 | 881 | ||
| 869 | DEFUN ("dbus-init-bus", Fdbus_init_bus, Sdbus_init_bus, 1, 1, 0, | 882 | DEFUN ("dbus-init-bus", Fdbus_init_bus, Sdbus_init_bus, 1, 1, 0, |
| @@ -880,12 +893,16 @@ DEFUN ("dbus-init-bus", Fdbus_init_bus, Sdbus_init_bus, 1, 1, 0, | |||
| 880 | if (!dbus_connection_set_watch_functions (connection, | 893 | if (!dbus_connection_set_watch_functions (connection, |
| 881 | xd_add_watch, | 894 | xd_add_watch, |
| 882 | xd_remove_watch, | 895 | xd_remove_watch, |
| 883 | NULL, (void*) XHASH (bus), NULL)) | 896 | xd_toggle_watch, |
| 897 | (void*) XHASH (bus), NULL)) | ||
| 884 | XD_SIGNAL1 (build_string ("Cannot add watch functions")); | 898 | XD_SIGNAL1 (build_string ("Cannot add watch functions")); |
| 885 | 899 | ||
| 886 | /* Add bus to list of registered buses. */ | 900 | /* Add bus to list of registered buses. */ |
| 887 | Vdbus_registered_buses = Fcons (bus, Vdbus_registered_buses); | 901 | Vdbus_registered_buses = Fcons (bus, Vdbus_registered_buses); |
| 888 | 902 | ||
| 903 | /* We do not want to abort. */ | ||
| 904 | putenv ("DBUS_FATAL_WARNINGS=0"); | ||
| 905 | |||
| 889 | /* Return. */ | 906 | /* Return. */ |
| 890 | return Qnil; | 907 | return Qnil; |
| 891 | } | 908 | } |
| @@ -1288,9 +1305,6 @@ usage: (dbus-call-method-asynchronously BUS SERVICE PATH INTERFACE METHOD HANDLE | |||
| 1288 | result = Qnil; | 1305 | result = Qnil; |
| 1289 | } | 1306 | } |
| 1290 | 1307 | ||
| 1291 | /* Flush connection to ensure the message is handled. */ | ||
| 1292 | dbus_connection_flush (connection); | ||
| 1293 | |||
| 1294 | XD_DEBUG_MESSAGE ("Message sent"); | 1308 | XD_DEBUG_MESSAGE ("Message sent"); |
| 1295 | 1309 | ||
| 1296 | /* Cleanup. */ | 1310 | /* Cleanup. */ |
| @@ -1379,9 +1393,6 @@ usage: (dbus-method-return-internal BUS SERIAL SERVICE &rest ARGS) */) | |||
| 1379 | if (!dbus_connection_send (connection, dmessage, NULL)) | 1393 | if (!dbus_connection_send (connection, dmessage, NULL)) |
| 1380 | XD_SIGNAL1 (build_string ("Cannot send message")); | 1394 | XD_SIGNAL1 (build_string ("Cannot send message")); |
| 1381 | 1395 | ||
| 1382 | /* Flush connection to ensure the message is handled. */ | ||
| 1383 | dbus_connection_flush (connection); | ||
| 1384 | |||
| 1385 | XD_DEBUG_MESSAGE ("Message sent"); | 1396 | XD_DEBUG_MESSAGE ("Message sent"); |
| 1386 | 1397 | ||
| 1387 | /* Cleanup. */ | 1398 | /* Cleanup. */ |
| @@ -1471,9 +1482,6 @@ usage: (dbus-method-error-internal BUS SERIAL SERVICE &rest ARGS) */) | |||
| 1471 | if (!dbus_connection_send (connection, dmessage, NULL)) | 1482 | if (!dbus_connection_send (connection, dmessage, NULL)) |
| 1472 | XD_SIGNAL1 (build_string ("Cannot send message")); | 1483 | XD_SIGNAL1 (build_string ("Cannot send message")); |
| 1473 | 1484 | ||
| 1474 | /* Flush connection to ensure the message is handled. */ | ||
| 1475 | dbus_connection_flush (connection); | ||
| 1476 | |||
| 1477 | XD_DEBUG_MESSAGE ("Message sent"); | 1485 | XD_DEBUG_MESSAGE ("Message sent"); |
| 1478 | 1486 | ||
| 1479 | /* Cleanup. */ | 1487 | /* Cleanup. */ |
| @@ -1589,9 +1597,6 @@ usage: (dbus-send-signal BUS SERVICE PATH INTERFACE SIGNAL &rest ARGS) */) | |||
| 1589 | if (!dbus_connection_send (connection, dmessage, NULL)) | 1597 | if (!dbus_connection_send (connection, dmessage, NULL)) |
| 1590 | XD_SIGNAL1 (build_string ("Cannot send message")); | 1598 | XD_SIGNAL1 (build_string ("Cannot send message")); |
| 1591 | 1599 | ||
| 1592 | /* Flush connection to ensure the message is handled. */ | ||
| 1593 | dbus_connection_flush (connection); | ||
| 1594 | |||
| 1595 | XD_DEBUG_MESSAGE ("Signal sent"); | 1600 | XD_DEBUG_MESSAGE ("Signal sent"); |
| 1596 | 1601 | ||
| 1597 | /* Cleanup. */ | 1602 | /* Cleanup. */ |
| @@ -1601,76 +1606,26 @@ usage: (dbus-send-signal BUS SERVICE PATH INTERFACE SIGNAL &rest ARGS) */) | |||
| 1601 | return Qt; | 1606 | return Qt; |
| 1602 | } | 1607 | } |
| 1603 | 1608 | ||
| 1604 | /* Check, whether there is pending input in the message queue of the | 1609 | /* Read one queued incoming message of the D-Bus BUS. |
| 1605 | D-Bus BUS. BUS is either a Lisp symbol, :system or :session, or a | 1610 | BUS is either a Lisp symbol, :system or :session, or a string denoting |
| 1606 | string denoting the bus address. */ | 1611 | the bus address. */ |
| 1607 | int | 1612 | static void |
| 1608 | xd_get_dispatch_status (Lisp_Object bus) | 1613 | xd_read_message_1 (DBusConnection *connection, Lisp_Object bus) |
| 1609 | { | ||
| 1610 | DBusConnection *connection; | ||
| 1611 | |||
| 1612 | /* Open a connection to the bus. */ | ||
| 1613 | connection = xd_initialize (bus, FALSE); | ||
| 1614 | if (connection == NULL) return FALSE; | ||
| 1615 | |||
| 1616 | /* Non blocking read of the next available message. */ | ||
| 1617 | dbus_connection_read_write (connection, 0); | ||
| 1618 | |||
| 1619 | /* Return. */ | ||
| 1620 | return | ||
| 1621 | (dbus_connection_get_dispatch_status (connection) | ||
| 1622 | == DBUS_DISPATCH_DATA_REMAINS) | ||
| 1623 | ? TRUE : FALSE; | ||
| 1624 | } | ||
| 1625 | |||
| 1626 | /* Check for queued incoming messages from the buses. */ | ||
| 1627 | int | ||
| 1628 | xd_pending_messages (void) | ||
| 1629 | { | ||
| 1630 | Lisp_Object busp = Vdbus_registered_buses; | ||
| 1631 | |||
| 1632 | while (!NILP (busp)) | ||
| 1633 | { | ||
| 1634 | /* We do not want to have an autolaunch for the session bus. */ | ||
| 1635 | if (EQ ((CAR_SAFE (busp)), QCdbus_session_bus) | ||
| 1636 | && getenv ("DBUS_SESSION_BUS_ADDRESS") == NULL) | ||
| 1637 | continue; | ||
| 1638 | |||
| 1639 | if (xd_get_dispatch_status (CAR_SAFE (busp))) | ||
| 1640 | return TRUE; | ||
| 1641 | |||
| 1642 | busp = CDR_SAFE (busp); | ||
| 1643 | } | ||
| 1644 | |||
| 1645 | return FALSE; | ||
| 1646 | } | ||
| 1647 | |||
| 1648 | /* Read queued incoming message of the D-Bus BUS. BUS is either a | ||
| 1649 | Lisp symbol, :system or :session, or a string denoting the bus | ||
| 1650 | address. */ | ||
| 1651 | static Lisp_Object | ||
| 1652 | xd_read_message (Lisp_Object bus) | ||
| 1653 | { | 1614 | { |
| 1654 | Lisp_Object args, key, value; | 1615 | Lisp_Object args, key, value; |
| 1655 | struct gcpro gcpro1; | 1616 | struct gcpro gcpro1; |
| 1656 | struct input_event event; | 1617 | struct input_event event; |
| 1657 | DBusConnection *connection; | ||
| 1658 | DBusMessage *dmessage; | 1618 | DBusMessage *dmessage; |
| 1659 | DBusMessageIter iter; | 1619 | DBusMessageIter iter; |
| 1660 | unsigned int dtype; | 1620 | unsigned int dtype; |
| 1661 | int mtype, serial; | 1621 | int mtype, serial; |
| 1662 | const char *uname, *path, *interface, *member; | 1622 | const char *uname, *path, *interface, *member; |
| 1663 | 1623 | ||
| 1664 | /* Open a connection to the bus. */ | ||
| 1665 | connection = xd_initialize (bus, TRUE); | ||
| 1666 | |||
| 1667 | /* Non blocking read of the next available message. */ | ||
| 1668 | dbus_connection_read_write (connection, 0); | ||
| 1669 | dmessage = dbus_connection_pop_message (connection); | 1624 | dmessage = dbus_connection_pop_message (connection); |
| 1670 | 1625 | ||
| 1671 | /* Return if there is no queued message. */ | 1626 | /* Return if there is no queued message. */ |
| 1672 | if (dmessage == NULL) | 1627 | if (dmessage == NULL) |
| 1673 | return Qnil; | 1628 | return; |
| 1674 | 1629 | ||
| 1675 | /* Collect the parameters. */ | 1630 | /* Collect the parameters. */ |
| 1676 | args = Qnil; | 1631 | args = Qnil; |
| @@ -1801,22 +1756,49 @@ xd_read_message (Lisp_Object bus) | |||
| 1801 | cleanup: | 1756 | cleanup: |
| 1802 | dbus_message_unref (dmessage); | 1757 | dbus_message_unref (dmessage); |
| 1803 | 1758 | ||
| 1804 | RETURN_UNGCPRO (Qnil); | 1759 | UNGCPRO; |
| 1805 | } | 1760 | } |
| 1806 | 1761 | ||
| 1807 | /* Read queued incoming messages from all buses. */ | 1762 | /* Read queued incoming messages of the D-Bus BUS. |
| 1808 | void | 1763 | BUS is either a Lisp symbol, :system or :session, or a string denoting |
| 1809 | xd_read_queued_messages (void) | 1764 | the bus address. */ |
| 1765 | static Lisp_Object | ||
| 1766 | xd_read_message (Lisp_Object bus) | ||
| 1767 | { | ||
| 1768 | /* Open a connection to the bus. */ | ||
| 1769 | DBusConnection *connection = xd_initialize (bus, TRUE); | ||
| 1770 | |||
| 1771 | /* Non blocking read of the next available message. */ | ||
| 1772 | dbus_connection_read_write (connection, 0); | ||
| 1773 | |||
| 1774 | while (dbus_connection_get_dispatch_status (connection) | ||
| 1775 | != DBUS_DISPATCH_COMPLETE) | ||
| 1776 | xd_read_message_1 (connection, bus); | ||
| 1777 | return Qnil; | ||
| 1778 | } | ||
| 1779 | |||
| 1780 | /* Callback called when something is ready to read or write. */ | ||
| 1781 | static void | ||
| 1782 | xd_read_queued_messages (int fd, void *data, int for_read) | ||
| 1810 | { | 1783 | { |
| 1811 | Lisp_Object busp = Vdbus_registered_buses; | 1784 | Lisp_Object busp = Vdbus_registered_buses; |
| 1785 | Lisp_Object bus = Qnil; | ||
| 1786 | |||
| 1787 | /* Find bus related to fd. */ | ||
| 1788 | if (data != NULL) | ||
| 1789 | while (!NILP (busp)) | ||
| 1790 | { | ||
| 1791 | if (data == (void*) XHASH (CAR_SAFE (busp))) | ||
| 1792 | bus = CAR_SAFE (busp); | ||
| 1793 | busp = CDR_SAFE (busp); | ||
| 1794 | } | ||
| 1795 | |||
| 1796 | if (NILP(bus)) | ||
| 1797 | return; | ||
| 1812 | 1798 | ||
| 1799 | /* We ignore all Lisp errors during the call. */ | ||
| 1813 | xd_in_read_queued_messages = 1; | 1800 | xd_in_read_queued_messages = 1; |
| 1814 | while (!NILP (busp)) | 1801 | internal_catch (Qdbus_error, xd_read_message, bus); |
| 1815 | { | ||
| 1816 | /* We ignore all Lisp errors during the call. */ | ||
| 1817 | internal_catch (Qdbus_error, xd_read_message, CAR_SAFE (busp)); | ||
| 1818 | busp = CDR_SAFE (busp); | ||
| 1819 | } | ||
| 1820 | xd_in_read_queued_messages = 0; | 1802 | xd_in_read_queued_messages = 0; |
| 1821 | } | 1803 | } |
| 1822 | 1804 | ||
| @@ -2181,6 +2163,9 @@ be called when the D-Bus reply message arrives. */); | |||
| 2181 | doc: /* If non-nil, debug messages of D-Bus bindings are raised. */); | 2163 | doc: /* If non-nil, debug messages of D-Bus bindings are raised. */); |
| 2182 | #ifdef DBUS_DEBUG | 2164 | #ifdef DBUS_DEBUG |
| 2183 | Vdbus_debug = Qt; | 2165 | Vdbus_debug = Qt; |
| 2166 | /* We can also set environment variable DBUS_VERBOSE=1 in order to | ||
| 2167 | see more traces. This requires libdbus-1 to be configured with | ||
| 2168 | --enable-verbose-mode. */ | ||
| 2184 | #else | 2169 | #else |
| 2185 | Vdbus_debug = Qnil; | 2170 | Vdbus_debug = Qnil; |
| 2186 | #endif | 2171 | #endif |