aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorMichael Albinus2026-02-07 11:32:54 +0100
committerMichael Albinus2026-02-07 11:32:54 +0100
commit89209a83b60c87d97f0c05dbf6cb29ff3cdf3d5a (patch)
tree7eb4fe230b36d619b51eeecd6c0a9868fa268b5b /src
parente1524740bef6cee52e138a086e43988a16ed703e (diff)
downloademacs-89209a83b60c87d97f0c05dbf6cb29ff3cdf3d5a.tar.gz
emacs-89209a83b60c87d97f0c05dbf6cb29ff3cdf3d5a.zip
Support D-Bus file descriptor manipulation
* doc/misc/dbus.texi (Synchronous Methods): Adapt `dbus-call-method'. (Asynchronous Methods): Adapt `dbus-call-method-asynchronously'. (File Descriptors): New chapter, replaces Inhibitor Locks. * etc/NEWS: Replace "New D-Bus functions to support systemd inhibitor locks" by "Support D-Bus file descriptor manipulation". Presentational fixes and improvements. * lisp/net/dbus.el (dbus-call-method) (dbus-call-method-asynchronously): Adapt docstring. (dbus-list-hash-table): Return (nreverse result). (dbus-monitor-goto-serial): Declare `completion'. * src/dbusbind.c (Fdbus_message_internal, xd_read_message_1): Handle `:keep-fd'. (xd_registered_inhibitor_locks, Fdbus_make_inhibitor_lock) (Fdbus_close_inhibitor_lock, Fdbus_registered_inhibitor_locks): Delete. (xd_registered_fds): New variable. (Fdbus__fd_open, Fdbus__fd_close, Fdbus__registered_fds): New DEFUNs. (Bug#79963) (syms_of_dbusbind_for_pdumper): Initialize `xd_registered_fds'. (syms_of_dbusbind): Remove subroutines `Sdbus_make_inhibitor_lock', `Sdbus_close_inhibitor_lock' and `Sdbus_registered_inhibitor_locks'. Remove symbol `Qdbus_call_method'. Declare subroutines `Sdbus__fd_open', `Sdbus__fd_close' and `Sdbus__registered_fds'. Declare symbol `QCkeep_fd'. staticpro `xd_registered_fds'. * test/lisp/net/dbus-tests.el (dbus-test10-inhibitor-locks): Delete. (dbus-test10-keep-fd, dbus-test10-open-close-fd): New tests.
Diffstat (limited to 'src')
-rw-r--r--src/dbusbind.c188
1 files changed, 105 insertions, 83 deletions
diff --git a/src/dbusbind.c b/src/dbusbind.c
index 3cf3ec9897e..98adebfb2d4 100644
--- a/src/dbusbind.c
+++ b/src/dbusbind.c
@@ -128,6 +128,8 @@ static bool xd_in_read_queued_messages = 0;
128#endif 128#endif
129 129
130/* Check whether TYPE is a basic DBusType. */ 130/* Check whether TYPE is a basic DBusType. */
131/* TODO: Shouldn't we assume, that recent D-Bus implementations carry
132 HAVE_DBUS_TYPE_IS_VALID and DBUS_TYPE_UNIX_FD? See configure.ac. */
131#ifdef HAVE_DBUS_TYPE_IS_VALID 133#ifdef HAVE_DBUS_TYPE_IS_VALID
132#define XD_BASIC_DBUS_TYPE(type) \ 134#define XD_BASIC_DBUS_TYPE(type) \
133 (dbus_type_is_valid (type) && dbus_type_is_basic (type)) 135 (dbus_type_is_valid (type) && dbus_type_is_basic (type))
@@ -309,6 +311,8 @@ XD_OBJECT_TO_STRING (Lisp_Object object)
309 } \ 311 } \
310 } while (0) 312 } while (0)
311 313
314/* TODO: Shouldn't we assume, that recent D-Bus implementations carry
315 HAVE_DBUS_VALIDATE_*? See configure.ac. */
312#if (HAVE_DBUS_VALIDATE_BUS_NAME || HAVE_DBUS_VALIDATE_PATH \ 316#if (HAVE_DBUS_VALIDATE_BUS_NAME || HAVE_DBUS_VALIDATE_PATH \
313 || HAVE_DBUS_VALIDATE_INTERFACE || HAVE_DBUS_VALIDATE_MEMBER) 317 || HAVE_DBUS_VALIDATE_INTERFACE || HAVE_DBUS_VALIDATE_MEMBER)
314#define XD_DBUS_VALIDATE_OBJECT(object, func) \ 318#define XD_DBUS_VALIDATE_OBJECT(object, func) \
@@ -1034,6 +1038,8 @@ xd_get_connection_address (Lisp_Object bus)
1034} 1038}
1035 1039
1036/* Return the file descriptor for WATCH, -1 if not found. */ 1040/* Return the file descriptor for WATCH, -1 if not found. */
1041/* TODO: Shouldn't we assume, that recent D-Bus implementations carry
1042 HAVE_DBUS_WATCH_GET_UNIX_FD? See configure.ac. */
1037static int 1043static int
1038xd_find_watch_fd (DBusWatch *watch) 1044xd_find_watch_fd (DBusWatch *watch)
1039{ 1045{
@@ -1349,6 +1355,7 @@ usage: (dbus-message-internal &rest REST) */)
1349 dbus_uint32_t serial = 0; 1355 dbus_uint32_t serial = 0;
1350 unsigned int ui_serial; 1356 unsigned int ui_serial;
1351 int timeout = -1; 1357 int timeout = -1;
1358 dbus_bool_t keepfd = FALSE;
1352 ptrdiff_t count, count0; 1359 ptrdiff_t count, count0;
1353 char signature[DBUS_MAXIMUM_SIGNATURE_LENGTH]; 1360 char signature[DBUS_MAXIMUM_SIGNATURE_LENGTH];
1354 1361
@@ -1525,6 +1532,7 @@ usage: (dbus-message-internal &rest REST) */)
1525 timeout = min (XFIXNAT (args[count+1]), INT_MAX); 1532 timeout = min (XFIXNAT (args[count+1]), INT_MAX);
1526 count = count + 2; 1533 count = count + 2;
1527 } 1534 }
1535
1528 /* Check for authorizable parameter. */ 1536 /* Check for authorizable parameter. */
1529 else if (EQ (args[count], QCauthorizable)) 1537 else if (EQ (args[count], QCauthorizable))
1530 { 1538 {
@@ -1542,6 +1550,24 @@ usage: (dbus-message-internal &rest REST) */)
1542 1550
1543 count = count + 2; 1551 count = count + 2;
1544 } 1552 }
1553
1554 /* Check for keepfd parameter. */
1555 else if (EQ (args[count], QCkeep_fd))
1556 {
1557 if (mtype != DBUS_MESSAGE_TYPE_METHOD_CALL)
1558 XD_SIGNAL1
1559 (build_string (":keep-fd is only supported on method calls"));
1560
1561 /* Ignore this keyword if unsupported. */
1562#ifdef DBUS_TYPE_UNIX_FD
1563 keepfd = TRUE;
1564#else
1565 XD_DEBUG_MESSAGE (":keep-fd not supported");
1566#endif
1567
1568 ++count;
1569 }
1570
1545 else break; 1571 else break;
1546 1572
1547 } 1573 }
@@ -1595,7 +1621,8 @@ usage: (dbus-message-internal &rest REST) */)
1595 result = list3 (QCserial, bus, INT_TO_INTEGER (serial)); 1621 result = list3 (QCserial, bus, INT_TO_INTEGER (serial));
1596 1622
1597 /* Create a hash table entry. */ 1623 /* Create a hash table entry. */
1598 Fputhash (result, handler, Vdbus_registered_objects_table); 1624 Fputhash (result, keepfd ? Fcons (handler, path) : handler,
1625 Vdbus_registered_objects_table);
1599 } 1626 }
1600 else 1627 else
1601 { 1628 {
@@ -1617,106 +1644,81 @@ usage: (dbus-message-internal &rest REST) */)
1617 return result; 1644 return result;
1618} 1645}
1619 1646
1620/* Alist of registered inhibitor locks for D-Bus. 1647/* Alist of registered file descriptors for D-Bus.
1621 An entry in this list is a list (FD WHAT WHY BLOCK). 1648 The key is an open file descriptor, retrieved via `dbus-call-method'
1622 The car of the list is a file descriptor retrieved from a 1649 or `dbus--open-fd'. The value is a string OBJECT-PATH or FILENAME,
1623 'dbus-make-inhibitor-lock` call. The cdr of the list represents the 1650 which represents the arguments the function was called with. Those
1624 three arguments 'dbus-make-inhibitor-lock` was called with. */ 1651 values are not needed for further operations; they are just shown for
1625static Lisp_Object xd_registered_inhibitor_locks; 1652 information. */
1626 1653static Lisp_Object xd_registered_fds;
1627DEFUN ("dbus-make-inhibitor-lock", Fdbus_make_inhibitor_lock, 1654
1628 Sdbus_make_inhibitor_lock, 1655DEFUN ("dbus--fd-open", Fdbus__fd_open, Sdbus__fd_open, 1, 1, 0,
1629 2, 3, 0, 1656 doc: /* Open FILENAME and return the respective read-only file descriptor. */)
1630 doc: /* Inhibit system shutdowns and sleep states. 1657 (Lisp_Object filename)
1631
1632WHAT is a colon-separated string of lock types, i.e. "shutdown",
1633"sleep", "idle", "handle-power-key", "handle-suspend-key",
1634"handle-hibernate-key", "handle-lid-switch". Example: "shutdown:idle".
1635
1636WHY is a descriptive string of why the lock is taken. Example: "Package
1637Update in Progress".
1638
1639The optional BLOCK is the mode of the inhibitor lock, either "block"
1640(BLOCK is non-nil), or "delay".
1641
1642It returns a file descriptor or nil, if the lock cannot be acquired. If
1643there is already an inhibitor lock for the triple (WHAT WHY BLOCK), this
1644lock is returned.
1645
1646For details of the arguments, see Info node `(dbus)Inhibitor Locks'. */)
1647 (Lisp_Object what, Lisp_Object why, Lisp_Object block)
1648{ 1658{
1649 CHECK_STRING (what); 1659 CHECK_STRING (filename);
1650 CHECK_STRING (why); 1660 filename = Fexpand_file_name (filename, Qnil);
1651 if (!NILP (block)) 1661 filename = ENCODE_FILE (filename);
1652 block = Qt;
1653 Lisp_Object who = build_string ("Emacs");
1654 Lisp_Object mode =
1655 (NILP (block)) ? build_string ("delay") : build_string ("block");
1656 1662
1657 /* Check, whether it is registered already. */ 1663 /* Check, whether it is registered already. */
1658 Lisp_Object triple = list3 (what, why, block); 1664 Lisp_Object registered = Frassoc (filename, xd_registered_fds);
1659 Lisp_Object registered = Frassoc (triple, xd_registered_inhibitor_locks);
1660 if (!NILP (registered)) 1665 if (!NILP (registered))
1661 return CAR_SAFE (registered); 1666 return CAR_SAFE (registered);
1662 1667
1663 /* Register lock. */ 1668 /* Open file descriptor. */
1664 Lisp_Object lock = 1669 int fd = emacs_open (SSDATA (filename), O_RDONLY, 0);
1665 calln (Qdbus_call_method, QCsystem,
1666 build_string ("org.freedesktop.login1"),
1667 build_string ("/org/freedesktop/login1"),
1668 build_string ("org.freedesktop.login1.Manager"),
1669 build_string ("Inhibit"), what, who, why, mode);
1670
1671 xd_registered_inhibitor_locks =
1672 Fcons (Fcons (lock, triple), xd_registered_inhibitor_locks);
1673 return lock;
1674}
1675 1670
1676DEFUN ("dbus-close-inhibitor-lock", Fdbus_close_inhibitor_lock, 1671 if (fd <= 0)
1677 Sdbus_close_inhibitor_lock, 1672 XD_SIGNAL2 (build_string ("Cannot open file"), filename);
1678 1, 1, 0,
1679 doc: /* Close inhibitor lock file descriptor.
1680 1673
1681LOCK, a file descriptor, must be the result of a `dbus-make-inhibitor-lock' 1674 /* Register file descriptor. */
1682call. It returns t in case of success, or nil if it isn't be possible 1675 xd_registered_fds =
1683to close the lock, or if the lock is closed already. 1676 Fcons (Fcons (INT_TO_INTEGER (fd), filename), xd_registered_fds);
1677 return INT_TO_INTEGER (fd);
1678}
1684 1679
1685For details, see Info node `(dbus)Inhibitor Locks'. */) 1680DEFUN ("dbus--fd-close", Fdbus__fd_close, Sdbus__fd_close, 1, 1, 0,
1686 (Lisp_Object lock) 1681 doc: /* Close file descriptor FD.
1682FD must be the result of a `dbus-call-method' or `dbus--fd-open' call,
1683see `dbus--registered-fds'. It returns t in case of success, or nil if
1684it isn't be possible to close the file descriptor, or if the file
1685descriptor is closed already. */)
1686 (Lisp_Object fd)
1687{ 1687{
1688 CHECK_FIXNUM (lock); 1688 CHECK_FIXNUM (fd);
1689 1689
1690 /* Check, whether it is registered. */ 1690 /* Check, whether it is registered. */
1691 Lisp_Object registered = assoc_no_quit (lock, xd_registered_inhibitor_locks); 1691 Lisp_Object registered = assoc_no_quit (fd, xd_registered_fds);
1692 if (NILP (registered)) 1692 if (NILP (registered))
1693 return Qnil; 1693 return Qnil;
1694 else 1694 else
1695 { 1695 {
1696 xd_registered_inhibitor_locks = 1696 xd_registered_fds = Fdelete (registered, xd_registered_fds);
1697 Fdelete (registered, xd_registered_inhibitor_locks); 1697 return (emacs_close (XFIXNAT (fd)) == 0) ? Qt : Qnil;
1698 return (emacs_close (XFIXNAT (lock)) == 0) ? Qt : Qnil;
1699 } 1698 }
1700} 1699}
1701 1700
1702DEFUN ("dbus-registered-inhibitor-locks", Fdbus_registered_inhibitor_locks, 1701DEFUN ("dbus--registered-fds", Fdbus__registered_fds, Sdbus__registered_fds,
1703 Sdbus_registered_inhibitor_locks,
1704 0, 0, 0, 1702 0, 0, 0,
1705 doc: /* Return registered inhibitor locks, an alist. 1703 doc: /* Return registered file descriptors, an alist.
1706This allows to check, whether other packages of the running Emacs 1704The key is an open file descriptor, retrieved via `dbus-call-method' or
1707instance have acquired an inhibitor lock as well. 1705`dbus--open-fd'. The value is a string OBJECT-PATH or FILENAME, which
1708An entry in this list is a list (FD WHAT WHY BLOCK). 1706represents the arguments the function was called with. Those values are
1709The car of the list is the file descriptor retrieved from a 1707not needed for further operations; they are just shown for information.
1710'dbus-make-inhibitor-lock` call. The cdr of the list represents the 1708
1711three arguments 'dbus-make-inhibitor-lock` was called with. */) 1709This alist allows to check, whether other packages of the running Emacs
1710instance have acquired a file descriptor as well. */)
1712 (void) 1711 (void)
1713{ 1712{
1714 /* We return a copy of xd_registered_inhibitor_locks, in order to 1713 /* We return a copy of xd_registered_fds, in order to protect it
1715 protect it against malicious manipulation. */ 1714 against malicious manipulation. */
1716 Lisp_Object registered = xd_registered_inhibitor_locks; 1715 Lisp_Object registered = xd_registered_fds;
1717 Lisp_Object result = Qnil; 1716 Lisp_Object result = Qnil;
1718 for (; !NILP (registered); registered = CDR_SAFE (registered)) 1717 for (; !NILP (registered); registered = CDR_SAFE (registered))
1719 result = Fcons (Fcopy_sequence (CAR_SAFE (registered)), result); 1718 {
1719 Lisp_Object tem = CAR_SAFE (registered);
1720 result = Fcons (Fcons (CAR_SAFE (tem), CDR_SAFE (tem)), result);
1721 }
1720 return Fnreverse (result); 1722 return Fnreverse (result);
1721} 1723}
1722 1724
@@ -1836,7 +1838,22 @@ xd_read_message_1 (DBusConnection *connection, Lisp_Object bus)
1836 Fremhash (key, Vdbus_registered_objects_table); 1838 Fremhash (key, Vdbus_registered_objects_table);
1837 1839
1838 /* Store the event. */ 1840 /* Store the event. */
1839 xd_store_event (value, args, event_args); 1841 xd_store_event (CONSP (value) ? CAR_SAFE (value) : value, args, event_args);
1842
1843#ifdef DBUS_TYPE_UNIX_FD
1844 /* Check, whether there is a file descriptor to be kept.
1845 value is (handler . path)
1846 args is ((:unix-fd NN) ...) */
1847 if (CONSP (value)
1848 && CONSP (CAR_SAFE (args))
1849 && EQ (CAR_SAFE (CAR_SAFE (args)), QCunix_fd))
1850 {
1851 xd_registered_fds =
1852 Fcons (Fcons (CAR_SAFE (CDR_SAFE (CAR_SAFE (args))),
1853 CDR_SAFE (value)),
1854 xd_registered_fds);
1855 }
1856#endif
1840 } 1857 }
1841 1858
1842 else /* DBUS_MESSAGE_TYPE_METHOD_CALL, DBUS_MESSAGE_TYPE_SIGNAL. */ 1859 else /* DBUS_MESSAGE_TYPE_METHOD_CALL, DBUS_MESSAGE_TYPE_SIGNAL. */
@@ -1972,7 +1989,7 @@ static void
1972syms_of_dbusbind_for_pdumper (void) 1989syms_of_dbusbind_for_pdumper (void)
1973{ 1990{
1974 xd_registered_buses = Qnil; 1991 xd_registered_buses = Qnil;
1975 xd_registered_inhibitor_locks = Qnil; 1992 xd_registered_fds = Qnil;
1976} 1993}
1977 1994
1978void 1995void
@@ -1980,9 +1997,9 @@ syms_of_dbusbind (void)
1980{ 1997{
1981 defsubr (&Sdbus__init_bus); 1998 defsubr (&Sdbus__init_bus);
1982 defsubr (&Sdbus_get_unique_name); 1999 defsubr (&Sdbus_get_unique_name);
1983 defsubr (&Sdbus_make_inhibitor_lock); 2000 defsubr (&Sdbus__fd_open);
1984 defsubr (&Sdbus_close_inhibitor_lock); 2001 defsubr (&Sdbus__fd_close);
1985 defsubr (&Sdbus_registered_inhibitor_locks); 2002 defsubr (&Sdbus__registered_fds);
1986 2003
1987 DEFSYM (Qdbus_message_internal, "dbus-message-internal"); 2004 DEFSYM (Qdbus_message_internal, "dbus-message-internal");
1988 defsubr (&Sdbus_message_internal); 2005 defsubr (&Sdbus_message_internal);
@@ -2007,6 +2024,11 @@ syms_of_dbusbind (void)
2007 /* Lisp symbol for method interactive authorization. */ 2024 /* Lisp symbol for method interactive authorization. */
2008 DEFSYM (QCauthorizable, ":authorizable"); 2025 DEFSYM (QCauthorizable, ":authorizable");
2009 2026
2027 /* Lisp symbol for file descriptor kept. */
2028#ifdef DBUS_TYPE_UNIX_FD
2029 DEFSYM (QCkeep_fd, ":keep-fd");
2030#endif
2031
2010 /* Lisp symbols of D-Bus types. */ 2032 /* Lisp symbols of D-Bus types. */
2011 DEFSYM (QCbyte, ":byte"); 2033 DEFSYM (QCbyte, ":byte");
2012 DEFSYM (QCboolean, ":boolean"); 2034 DEFSYM (QCboolean, ":boolean");
@@ -2143,7 +2165,7 @@ be called when the D-Bus reply message arrives. */);
2143 /* Initialize internal objects. */ 2165 /* Initialize internal objects. */
2144 pdumper_do_now_and_after_load (syms_of_dbusbind_for_pdumper); 2166 pdumper_do_now_and_after_load (syms_of_dbusbind_for_pdumper);
2145 staticpro (&xd_registered_buses); 2167 staticpro (&xd_registered_buses);
2146 staticpro (&xd_registered_inhibitor_locks); 2168 staticpro (&xd_registered_fds);
2147 2169
2148 Fprovide (intern_c_string ("dbusbind"), Qnil); 2170 Fprovide (intern_c_string ("dbusbind"), Qnil);
2149} 2171}