aboutsummaryrefslogtreecommitdiffstats
path: root/src/dbusbind.c
diff options
context:
space:
mode:
authorMichael Albinus2020-09-26 11:38:23 +0200
committerMichael Albinus2020-09-26 11:38:23 +0200
commitc540f3323da96eadf41ccfa4e23ec2a5124343b8 (patch)
tree6f513dd3abad6c8e8a61bd2cc939bd5cd9a9461f /src/dbusbind.c
parentc98c7def046c5f6b1ac50fda46e32545b5e2ba37 (diff)
downloademacs-c540f3323da96eadf41ccfa4e23ec2a5124343b8.tar.gz
emacs-c540f3323da96eadf41ccfa4e23ec2a5124343b8.zip
Add D-Bus monitor
* lisp/net/dbus.el (dbus-interface-monitoring): New defconst. (dbus-call-method, dbus-call-method-asynchronously) (dbus-send-signal, dbus-method-return-internal) (dbus-method-error-internal, dbus-check-arguments): Accept also :system-private and :session-private. (dbus-check-event, dbus-event-path-name) (dbus-event-interface-name) (dbus-event-member-name, dbus-property-handler) (dbus-handle-bus-disconnect): Adapt according to new structure. (dbus-handle-event): Handle also monitor events. (dbus-event-destination-name, dbus-event-handler) (dbus-event-arguments, dbus-register-monitor, dbus-monitor-handler): New defuns. * src/dbusbind.c (XD_DBUS_VALIDATE_BUS_ADDRESS, xd_remove_watch) (Fdbus__init_bus): Accept also :system-private and :session-private. (xd_read_message_1): Add destination and error_name to dbus-event. Handle monitor events. (syms_of_dbusbind): Declare QCsystem_private, QCsession_private and QCmonitor. (dbus-registered-objects-table): Fix docstring.
Diffstat (limited to 'src/dbusbind.c')
-rw-r--r--src/dbusbind.c139
1 files changed, 107 insertions, 32 deletions
diff --git a/src/dbusbind.c b/src/dbusbind.c
index 4c5ab485803..09f0317be91 100644
--- a/src/dbusbind.c
+++ b/src/dbusbind.c
@@ -44,7 +44,10 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
44 44
45/* Alist of D-Bus buses we are polling for messages. 45/* Alist of D-Bus buses we are polling for messages.
46 The key is the symbol or string of the bus, and the value is the 46 The key is the symbol or string of the bus, and the value is the
47 connection address. */ 47 connection address. For every bus, just one connection is counted.
48 If there shall be a second connection to the same bus, a different
49 symbol or string for the bus must be chosen. On Lisp level, a bus
50 stands for the associated connection. */
48static Lisp_Object xd_registered_buses; 51static Lisp_Object xd_registered_buses;
49 52
50/* Whether we are reading a D-Bus event. */ 53/* Whether we are reading a D-Bus event. */
@@ -279,10 +282,13 @@ XD_OBJECT_TO_STRING (Lisp_Object object)
279 else \ 282 else \
280 { \ 283 { \
281 CHECK_SYMBOL (bus); \ 284 CHECK_SYMBOL (bus); \
282 if (!(EQ (bus, QCsystem) || EQ (bus, QCsession))) \ 285 if (!(EQ (bus, QCsystem) || EQ (bus, QCsession) \
286 || EQ (bus, QCsystem_private) \
287 || EQ (bus, QCsession_private))) \
283 XD_SIGNAL2 (build_string ("Wrong bus name"), bus); \ 288 XD_SIGNAL2 (build_string ("Wrong bus name"), bus); \
284 /* We do not want to have an autolaunch for the session bus. */ \ 289 /* We do not want to have an autolaunch for the session bus. */ \
285 if (EQ (bus, QCsession) && session_bus_address == NULL) \ 290 if ((EQ (bus, QCsession) || EQ (bus, QCsession_private)) \
291 && session_bus_address == NULL) \
286 XD_SIGNAL2 (build_string ("No connection to bus"), bus); \ 292 XD_SIGNAL2 (build_string ("No connection to bus"), bus); \
287 } \ 293 } \
288 } while (0) 294 } while (0)
@@ -968,8 +974,9 @@ xd_lisp_dbus_to_dbus (Lisp_Object bus)
968 return xmint_pointer (bus); 974 return xmint_pointer (bus);
969} 975}
970 976
971/* Return D-Bus connection address. BUS is either a Lisp symbol, 977/* Return D-Bus connection address.
972 :system or :session, or a string denoting the bus address. */ 978 BUS is either a Lisp symbol, :system, :session, :system-private or
979 :session-private, or a string denoting the bus address. */
973static DBusConnection * 980static DBusConnection *
974xd_get_connection_address (Lisp_Object bus) 981xd_get_connection_address (Lisp_Object bus)
975{ 982{
@@ -1031,7 +1038,8 @@ xd_add_watch (DBusWatch *watch, void *data)
1031} 1038}
1032 1039
1033/* Stop monitoring WATCH for possible I/O. 1040/* Stop monitoring WATCH for possible I/O.
1034 DATA is the used bus, either a string or QCsystem or QCsession. */ 1041 DATA is the used bus, either a string or QCsystem, QCsession,
1042 QCsystem_private or QCsession_private. */
1035static void 1043static void
1036xd_remove_watch (DBusWatch *watch, void *data) 1044xd_remove_watch (DBusWatch *watch, void *data)
1037{ 1045{
@@ -1046,7 +1054,7 @@ xd_remove_watch (DBusWatch *watch, void *data)
1046 /* Unset session environment. */ 1054 /* Unset session environment. */
1047#if 0 1055#if 0
1048 /* This is buggy, since unsetenv is not thread-safe. */ 1056 /* This is buggy, since unsetenv is not thread-safe. */
1049 if (XSYMBOL (QCsession) == data) 1057 if (XSYMBOL (QCsession) == data) || (XSYMBOL (QCsession_private) == data)
1050 { 1058 {
1051 XD_DEBUG_MESSAGE ("unsetenv DBUS_SESSION_BUS_ADDRESS"); 1059 XD_DEBUG_MESSAGE ("unsetenv DBUS_SESSION_BUS_ADDRESS");
1052 unsetenv ("DBUS_SESSION_BUS_ADDRESS"); 1060 unsetenv ("DBUS_SESSION_BUS_ADDRESS");
@@ -1120,6 +1128,11 @@ can be a string denoting the address of the corresponding bus. For
1120the system and session buses, this function is called when loading 1128the system and session buses, this function is called when loading
1121`dbus.el', there is no need to call it again. 1129`dbus.el', there is no need to call it again.
1122 1130
1131A special case is BUS being the symbol `:system-private' or
1132`:session-private'. These symbols still denote the system or session
1133bus, but using a private connection. They should not be used outside
1134dbus.el.
1135
1123The function returns a number, which counts the connections this Emacs 1136The function returns a number, which counts the connections this Emacs
1124session has established to the BUS under the same unique name (see 1137session has established to the BUS under the same unique name (see
1125`dbus-get-unique-name'). It depends on the libraries Emacs is linked 1138`dbus-get-unique-name'). It depends on the libraries Emacs is linked
@@ -1142,6 +1155,10 @@ this connection to those buses. */)
1142 ptrdiff_t refcount; 1155 ptrdiff_t refcount;
1143 1156
1144 /* Check parameter. */ 1157 /* Check parameter. */
1158 if (!NILP (private))
1159 bus = EQ (bus, QCsystem)
1160 ? QCsystem_private
1161 : EQ (bus, QCsession) ? QCsession_private : bus;
1145 XD_DBUS_VALIDATE_BUS_ADDRESS (bus); 1162 XD_DBUS_VALIDATE_BUS_ADDRESS (bus);
1146 1163
1147 /* Close bus if it is already open. */ 1164 /* Close bus if it is already open. */
@@ -1169,8 +1186,9 @@ this connection to those buses. */)
1169 1186
1170 else 1187 else
1171 { 1188 {
1172 DBusBusType bustype = (EQ (bus, QCsystem) 1189 DBusBusType bustype
1173 ? DBUS_BUS_SYSTEM : DBUS_BUS_SESSION); 1190 = EQ (bus, QCsystem) || EQ (bus, QCsystem_private)
1191 ? DBUS_BUS_SYSTEM : DBUS_BUS_SESSION;
1174 if (NILP (private)) 1192 if (NILP (private))
1175 connection = dbus_bus_get (bustype, &derror); 1193 connection = dbus_bus_get (bustype, &derror);
1176 else 1194 else
@@ -1184,9 +1202,9 @@ this connection to those buses. */)
1184 XD_SIGNAL2 (build_string ("No connection to bus"), bus); 1202 XD_SIGNAL2 (build_string ("No connection to bus"), bus);
1185 1203
1186 /* If it is not the system or session bus, we must register 1204 /* If it is not the system or session bus, we must register
1187 ourselves. Otherwise, we have called dbus_bus_get, which has 1205 ourselves. Otherwise, we have called dbus_bus_get{_private},
1188 configured us to exit if the connection closes - we undo this 1206 which has configured us to exit if the connection closes - we
1189 setting. */ 1207 undo this setting. */
1190 if (STRINGP (bus)) 1208 if (STRINGP (bus))
1191 dbus_bus_register (connection, &derror); 1209 dbus_bus_register (connection, &derror);
1192 else 1210 else
@@ -1215,6 +1233,9 @@ this connection to those buses. */)
1215 dbus_error_free (&derror); 1233 dbus_error_free (&derror);
1216 } 1234 }
1217 1235
1236 XD_DEBUG_MESSAGE ("Registered buses: %s",
1237 XD_OBJECT_TO_STRING (xd_registered_buses));
1238
1218 /* Return reference counter. */ 1239 /* Return reference counter. */
1219 refcount = xd_get_connection_references (connection); 1240 refcount = xd_get_connection_references (connection);
1220 XD_DEBUG_MESSAGE ("Bus %s, Reference counter %"pD"d", 1241 XD_DEBUG_MESSAGE ("Bus %s, Reference counter %"pD"d",
@@ -1533,8 +1554,8 @@ usage: (dbus-message-internal &rest REST) */)
1533} 1554}
1534 1555
1535/* Read one queued incoming message of the D-Bus BUS. 1556/* Read one queued incoming message of the D-Bus BUS.
1536 BUS is either a Lisp symbol, :system or :session, or a string denoting 1557 BUS is either a Lisp symbol, :system, :session, :system-private or
1537 the bus address. */ 1558 :session-private, or a string denoting the bus address. */
1538static void 1559static void
1539xd_read_message_1 (DBusConnection *connection, Lisp_Object bus) 1560xd_read_message_1 (DBusConnection *connection, Lisp_Object bus)
1540{ 1561{
@@ -1546,7 +1567,7 @@ xd_read_message_1 (DBusConnection *connection, Lisp_Object bus)
1546 int mtype; 1567 int mtype;
1547 dbus_uint32_t serial; 1568 dbus_uint32_t serial;
1548 unsigned int ui_serial; 1569 unsigned int ui_serial;
1549 const char *uname, *path, *interface, *member, *error_name; 1570 const char *uname, *destination, *path, *interface, *member, *error_name;
1550 1571
1551 dmessage = dbus_connection_pop_message (connection); 1572 dmessage = dbus_connection_pop_message (connection);
1552 1573
@@ -1579,6 +1600,7 @@ xd_read_message_1 (DBusConnection *connection, Lisp_Object bus)
1579 ? dbus_message_get_reply_serial (dmessage) 1600 ? dbus_message_get_reply_serial (dmessage)
1580 : dbus_message_get_serial (dmessage); 1601 : dbus_message_get_serial (dmessage);
1581 uname = dbus_message_get_sender (dmessage); 1602 uname = dbus_message_get_sender (dmessage);
1603 destination = dbus_message_get_destination (dmessage);
1582 path = dbus_message_get_path (dmessage); 1604 path = dbus_message_get_path (dmessage);
1583 interface = dbus_message_get_interface (dmessage); 1605 interface = dbus_message_get_interface (dmessage);
1584 member = dbus_message_get_member (dmessage); 1606 member = dbus_message_get_member (dmessage);
@@ -1586,7 +1608,8 @@ xd_read_message_1 (DBusConnection *connection, Lisp_Object bus)
1586 1608
1587 XD_DEBUG_MESSAGE ("Event received: %s %u %s %s %s %s %s %s", 1609 XD_DEBUG_MESSAGE ("Event received: %s %u %s %s %s %s %s %s",
1588 XD_MESSAGE_TYPE_TO_STRING (mtype), 1610 XD_MESSAGE_TYPE_TO_STRING (mtype),
1589 ui_serial, uname, path, interface, member, error_name, 1611 ui_serial, uname, destination, path, interface,
1612 mtype == DBUS_MESSAGE_TYPE_ERROR ? error_name : member,
1590 XD_OBJECT_TO_STRING (args)); 1613 XD_OBJECT_TO_STRING (args));
1591 1614
1592 if (mtype == DBUS_MESSAGE_TYPE_INVALID) 1615 if (mtype == DBUS_MESSAGE_TYPE_INVALID)
@@ -1601,7 +1624,7 @@ xd_read_message_1 (DBusConnection *connection, Lisp_Object bus)
1601 1624
1602 /* There shall be exactly one entry. Construct an event. */ 1625 /* There shall be exactly one entry. Construct an event. */
1603 if (NILP (value)) 1626 if (NILP (value))
1604 goto cleanup; 1627 goto monitor;
1605 1628
1606 /* Remove the entry. */ 1629 /* Remove the entry. */
1607 Fremhash (key, Vdbus_registered_objects_table); 1630 Fremhash (key, Vdbus_registered_objects_table);
@@ -1610,11 +1633,8 @@ xd_read_message_1 (DBusConnection *connection, Lisp_Object bus)
1610 EVENT_INIT (event); 1633 EVENT_INIT (event);
1611 event.kind = DBUS_EVENT; 1634 event.kind = DBUS_EVENT;
1612 event.frame_or_window = Qnil; 1635 event.frame_or_window = Qnil;
1613 event.arg = 1636 /* Handler. */
1614 Fcons (value, 1637 event.arg = Fcons (value, args);
1615 (mtype == DBUS_MESSAGE_TYPE_ERROR)
1616 ? Fcons (list2 (QCstring, build_string (error_name)), args)
1617 : args);
1618 } 1638 }
1619 1639
1620 else /* DBUS_MESSAGE_TYPE_METHOD_CALL, DBUS_MESSAGE_TYPE_SIGNAL. */ 1640 else /* DBUS_MESSAGE_TYPE_METHOD_CALL, DBUS_MESSAGE_TYPE_SIGNAL. */
@@ -1622,7 +1642,7 @@ xd_read_message_1 (DBusConnection *connection, Lisp_Object bus)
1622 /* Vdbus_registered_objects_table requires non-nil interface and 1642 /* Vdbus_registered_objects_table requires non-nil interface and
1623 member. */ 1643 member. */
1624 if ((interface == NULL) || (member == NULL)) 1644 if ((interface == NULL) || (member == NULL))
1625 goto cleanup; 1645 goto monitor;
1626 1646
1627 /* Search for a registered function of the message. */ 1647 /* Search for a registered function of the message. */
1628 key = list4 (mtype == DBUS_MESSAGE_TYPE_METHOD_CALL ? QCmethod : QCsignal, 1648 key = list4 (mtype == DBUS_MESSAGE_TYPE_METHOD_CALL ? QCmethod : QCsignal,
@@ -1647,6 +1667,7 @@ xd_read_message_1 (DBusConnection *connection, Lisp_Object bus)
1647 EVENT_INIT (event); 1667 EVENT_INIT (event);
1648 event.kind = DBUS_EVENT; 1668 event.kind = DBUS_EVENT;
1649 event.frame_or_window = Qnil; 1669 event.frame_or_window = Qnil;
1670 /* Handler. */
1650 event.arg 1671 event.arg
1651 = Fcons (CAR_SAFE (CDR_SAFE (CDR_SAFE (CDR_SAFE (key)))), args); 1672 = Fcons (CAR_SAFE (CDR_SAFE (CDR_SAFE (CDR_SAFE (key)))), args);
1652 break; 1673 break;
@@ -1655,16 +1676,22 @@ xd_read_message_1 (DBusConnection *connection, Lisp_Object bus)
1655 } 1676 }
1656 1677
1657 if (NILP (value)) 1678 if (NILP (value))
1658 goto cleanup; 1679 goto monitor;
1659 } 1680 }
1660 1681
1661 /* Add type, serial, uname, path, interface and member to the event. */ 1682 /* Add type, serial, uname, destination, path, interface and member
1662 event.arg = Fcons ((member == NULL ? Qnil : build_string (member)), 1683 or error_name to the event. */
1663 event.arg); 1684 event.arg
1685 = Fcons (mtype == DBUS_MESSAGE_TYPE_ERROR
1686 ? error_name == NULL ? Qnil : build_string (error_name)
1687 : member == NULL ? Qnil : build_string (member),
1688 event.arg);
1664 event.arg = Fcons ((interface == NULL ? Qnil : build_string (interface)), 1689 event.arg = Fcons ((interface == NULL ? Qnil : build_string (interface)),
1665 event.arg); 1690 event.arg);
1666 event.arg = Fcons ((path == NULL ? Qnil : build_string (path)), 1691 event.arg = Fcons ((path == NULL ? Qnil : build_string (path)),
1667 event.arg); 1692 event.arg);
1693 event.arg = Fcons ((destination == NULL ? Qnil : build_string (destination)),
1694 event.arg);
1668 event.arg = Fcons ((uname == NULL ? Qnil : build_string (uname)), 1695 event.arg = Fcons ((uname == NULL ? Qnil : build_string (uname)),
1669 event.arg); 1696 event.arg);
1670 event.arg = Fcons (INT_TO_INTEGER (serial), event.arg); 1697 event.arg = Fcons (INT_TO_INTEGER (serial), event.arg);
@@ -1678,14 +1705,58 @@ xd_read_message_1 (DBusConnection *connection, Lisp_Object bus)
1678 1705
1679 XD_DEBUG_MESSAGE ("Event stored: %s", XD_OBJECT_TO_STRING (event.arg)); 1706 XD_DEBUG_MESSAGE ("Event stored: %s", XD_OBJECT_TO_STRING (event.arg));
1680 1707
1708 /* Monitor. */
1709 monitor:
1710 /* Search for a registered function of the message. */
1711 key = list2 (QCmonitor, bus);
1712 value = Fgethash (key, Vdbus_registered_objects_table, Qnil);
1713
1714 /* There shall be exactly one entry. Construct an event. */
1715 if (NILP (value))
1716 goto cleanup;
1717
1718 /* Construct an event. */
1719 EVENT_INIT (event);
1720 event.kind = DBUS_EVENT;
1721 event.frame_or_window = Qnil;
1722
1723 /* Add type, serial, uname, destination, path, interface, member
1724 or error_name and handler to the event. */
1725 event.arg
1726 = Fcons (CAR_SAFE (CDR_SAFE (CDR_SAFE (CDR_SAFE (CAR_SAFE (value))))),
1727 args);
1728 event.arg
1729 = Fcons (mtype == DBUS_MESSAGE_TYPE_ERROR
1730 ? error_name == NULL ? Qnil : build_string (error_name)
1731 : member == NULL ? Qnil : build_string (member),
1732 event.arg);
1733 event.arg = Fcons ((interface == NULL ? Qnil : build_string (interface)),
1734 event.arg);
1735 event.arg = Fcons ((path == NULL ? Qnil : build_string (path)),
1736 event.arg);
1737 event.arg = Fcons ((destination == NULL ? Qnil : build_string (destination)),
1738 event.arg);
1739 event.arg = Fcons ((uname == NULL ? Qnil : build_string (uname)),
1740 event.arg);
1741 event.arg = Fcons (INT_TO_INTEGER (serial), event.arg);
1742 event.arg = Fcons (make_fixnum (mtype), event.arg);
1743
1744 /* Add the bus symbol to the event. */
1745 event.arg = Fcons (bus, event.arg);
1746
1747 /* Store it into the input event queue. */
1748 kbd_buffer_store_event (&event);
1749
1750 XD_DEBUG_MESSAGE ("Monitor event stored: %s", XD_OBJECT_TO_STRING (event.arg));
1751
1681 /* Cleanup. */ 1752 /* Cleanup. */
1682 cleanup: 1753 cleanup:
1683 dbus_message_unref (dmessage); 1754 dbus_message_unref (dmessage);
1684} 1755}
1685 1756
1686/* Read queued incoming messages of the D-Bus BUS. 1757/* Read queued incoming messages of the D-Bus BUS.
1687 BUS is either a Lisp symbol, :system or :session, or a string denoting 1758 BUS is either a Lisp symbol, :system, :session, :system-private or
1688 the bus address. */ 1759 :session-private, or a string denoting the bus address. */
1689static Lisp_Object 1760static Lisp_Object
1690xd_read_message (Lisp_Object bus) 1761xd_read_message (Lisp_Object bus)
1691{ 1762{
@@ -1762,6 +1833,8 @@ syms_of_dbusbind (void)
1762 /* Lisp symbols of the system and session buses. */ 1833 /* Lisp symbols of the system and session buses. */
1763 DEFSYM (QCsystem, ":system"); 1834 DEFSYM (QCsystem, ":system");
1764 DEFSYM (QCsession, ":session"); 1835 DEFSYM (QCsession, ":session");
1836 DEFSYM (QCsystem_private, ":system-private");
1837 DEFSYM (QCsession_private, ":session-private");
1765 1838
1766 /* Lisp symbol for method call timeout. */ 1839 /* Lisp symbol for method call timeout. */
1767 DEFSYM (QCtimeout, ":timeout"); 1840 DEFSYM (QCtimeout, ":timeout");
@@ -1788,10 +1861,11 @@ syms_of_dbusbind (void)
1788 DEFSYM (QCdict_entry, ":dict-entry"); 1861 DEFSYM (QCdict_entry, ":dict-entry");
1789 1862
1790 /* Lisp symbols of objects in `dbus-registered-objects-table'. 1863 /* Lisp symbols of objects in `dbus-registered-objects-table'.
1791 `:property', which does exist there as well, is not used here. */ 1864 `:property', which does exist there as well, is not declared here. */
1792 DEFSYM (QCserial, ":serial"); 1865 DEFSYM (QCserial, ":serial");
1793 DEFSYM (QCmethod, ":method"); 1866 DEFSYM (QCmethod, ":method");
1794 DEFSYM (QCsignal, ":signal"); 1867 DEFSYM (QCsignal, ":signal");
1868 DEFSYM (QCmonitor, ":monitor");
1795 1869
1796 DEFVAR_LISP ("dbus-compiled-version", 1870 DEFVAR_LISP ("dbus-compiled-version",
1797 Vdbus_compiled_version, 1871 Vdbus_compiled_version,
@@ -1867,8 +1941,9 @@ path of the sending object. All of them can be nil, which means a
1867wildcard then. 1941wildcard then.
1868 1942
1869OBJECT is either the handler to be called when a D-Bus message, which 1943OBJECT is either the handler to be called when a D-Bus message, which
1870matches the key criteria, arrives (TYPE `:method' and `:signal'), or a 1944matches the key criteria, arrives (TYPE `:method', `:signal' and
1871list (ACCESS EMITS-SIGNAL VALUE) for TYPE `:property'. 1945`:monitor'), or a list (ACCESS EMITS-SIGNAL VALUE) for TYPE
1946`:property'.
1872 1947
1873For entries of type `:signal', there is also a fifth element RULE, 1948For entries of type `:signal', there is also a fifth element RULE,
1874which keeps the match string the signal is registered with. 1949which keeps the match string the signal is registered with.