diff options
Diffstat (limited to 'src/dbusbind.c')
| -rw-r--r-- | src/dbusbind.c | 188 |
1 files changed, 105 insertions, 83 deletions
diff --git a/src/dbusbind.c b/src/dbusbind.c index cb705e9e92a..60ac38b5479 100644 --- a/src/dbusbind.c +++ b/src/dbusbind.c | |||
| @@ -129,6 +129,8 @@ static bool xd_in_read_queued_messages = 0; | |||
| 129 | #endif | 129 | #endif |
| 130 | 130 | ||
| 131 | /* Check whether TYPE is a basic DBusType. */ | 131 | /* Check whether TYPE is a basic DBusType. */ |
| 132 | /* TODO: Shouldn't we assume, that recent D-Bus implementations carry | ||
| 133 | HAVE_DBUS_TYPE_IS_VALID and DBUS_TYPE_UNIX_FD? See configure.ac. */ | ||
| 132 | #ifdef HAVE_DBUS_TYPE_IS_VALID | 134 | #ifdef HAVE_DBUS_TYPE_IS_VALID |
| 133 | #define XD_BASIC_DBUS_TYPE(type) \ | 135 | #define XD_BASIC_DBUS_TYPE(type) \ |
| 134 | (dbus_type_is_valid (type) && dbus_type_is_basic (type)) | 136 | (dbus_type_is_valid (type) && dbus_type_is_basic (type)) |
| @@ -310,6 +312,8 @@ XD_OBJECT_TO_STRING (Lisp_Object object) | |||
| 310 | } \ | 312 | } \ |
| 311 | } while (0) | 313 | } while (0) |
| 312 | 314 | ||
| 315 | /* TODO: Shouldn't we assume, that recent D-Bus implementations carry | ||
| 316 | HAVE_DBUS_VALIDATE_*? See configure.ac. */ | ||
| 313 | #if (HAVE_DBUS_VALIDATE_BUS_NAME || HAVE_DBUS_VALIDATE_PATH \ | 317 | #if (HAVE_DBUS_VALIDATE_BUS_NAME || HAVE_DBUS_VALIDATE_PATH \ |
| 314 | || HAVE_DBUS_VALIDATE_INTERFACE || HAVE_DBUS_VALIDATE_MEMBER) | 318 | || HAVE_DBUS_VALIDATE_INTERFACE || HAVE_DBUS_VALIDATE_MEMBER) |
| 315 | #define XD_DBUS_VALIDATE_OBJECT(object, func) \ | 319 | #define XD_DBUS_VALIDATE_OBJECT(object, func) \ |
| @@ -1044,6 +1048,8 @@ xd_get_connection_address (Lisp_Object bus) | |||
| 1044 | } | 1048 | } |
| 1045 | 1049 | ||
| 1046 | /* Return the file descriptor for WATCH, -1 if not found. */ | 1050 | /* Return the file descriptor for WATCH, -1 if not found. */ |
| 1051 | /* TODO: Shouldn't we assume, that recent D-Bus implementations carry | ||
| 1052 | HAVE_DBUS_WATCH_GET_UNIX_FD? See configure.ac. */ | ||
| 1047 | static int | 1053 | static int |
| 1048 | xd_find_watch_fd (DBusWatch *watch) | 1054 | xd_find_watch_fd (DBusWatch *watch) |
| 1049 | { | 1055 | { |
| @@ -1372,6 +1378,7 @@ usage: (dbus-message-internal &rest REST) */) | |||
| 1372 | dbus_uint32_t serial = 0; | 1378 | dbus_uint32_t serial = 0; |
| 1373 | unsigned int ui_serial; | 1379 | unsigned int ui_serial; |
| 1374 | int timeout = -1; | 1380 | int timeout = -1; |
| 1381 | dbus_bool_t keepfd = FALSE; | ||
| 1375 | ptrdiff_t count, count0; | 1382 | ptrdiff_t count, count0; |
| 1376 | char signature[DBUS_MAXIMUM_SIGNATURE_LENGTH]; | 1383 | char signature[DBUS_MAXIMUM_SIGNATURE_LENGTH]; |
| 1377 | 1384 | ||
| @@ -1548,6 +1555,7 @@ usage: (dbus-message-internal &rest REST) */) | |||
| 1548 | timeout = min (XFIXNAT (args[count+1]), INT_MAX); | 1555 | timeout = min (XFIXNAT (args[count+1]), INT_MAX); |
| 1549 | count = count + 2; | 1556 | count = count + 2; |
| 1550 | } | 1557 | } |
| 1558 | |||
| 1551 | /* Check for authorizable parameter. */ | 1559 | /* Check for authorizable parameter. */ |
| 1552 | else if (EQ (args[count], QCauthorizable)) | 1560 | else if (EQ (args[count], QCauthorizable)) |
| 1553 | { | 1561 | { |
| @@ -1565,6 +1573,24 @@ usage: (dbus-message-internal &rest REST) */) | |||
| 1565 | 1573 | ||
| 1566 | count = count + 2; | 1574 | count = count + 2; |
| 1567 | } | 1575 | } |
| 1576 | |||
| 1577 | /* Check for keepfd parameter. */ | ||
| 1578 | else if (EQ (args[count], QCkeep_fd)) | ||
| 1579 | { | ||
| 1580 | if (mtype != DBUS_MESSAGE_TYPE_METHOD_CALL) | ||
| 1581 | XD_SIGNAL1 | ||
| 1582 | (build_string (":keep-fd is only supported on method calls")); | ||
| 1583 | |||
| 1584 | /* Ignore this keyword if unsupported. */ | ||
| 1585 | #ifdef DBUS_TYPE_UNIX_FD | ||
| 1586 | keepfd = TRUE; | ||
| 1587 | #else | ||
| 1588 | XD_DEBUG_MESSAGE (":keep-fd not supported"); | ||
| 1589 | #endif | ||
| 1590 | |||
| 1591 | ++count; | ||
| 1592 | } | ||
| 1593 | |||
| 1568 | else break; | 1594 | else break; |
| 1569 | 1595 | ||
| 1570 | } | 1596 | } |
| @@ -1618,7 +1644,8 @@ usage: (dbus-message-internal &rest REST) */) | |||
| 1618 | result = list3 (QCserial, bus, INT_TO_INTEGER (serial)); | 1644 | result = list3 (QCserial, bus, INT_TO_INTEGER (serial)); |
| 1619 | 1645 | ||
| 1620 | /* Create a hash table entry. */ | 1646 | /* Create a hash table entry. */ |
| 1621 | Fputhash (result, handler, Vdbus_registered_objects_table); | 1647 | Fputhash (result, keepfd ? Fcons (handler, path) : handler, |
| 1648 | Vdbus_registered_objects_table); | ||
| 1622 | } | 1649 | } |
| 1623 | else | 1650 | else |
| 1624 | { | 1651 | { |
| @@ -1640,106 +1667,81 @@ usage: (dbus-message-internal &rest REST) */) | |||
| 1640 | return result; | 1667 | return result; |
| 1641 | } | 1668 | } |
| 1642 | 1669 | ||
| 1643 | /* Alist of registered inhibitor locks for D-Bus. | 1670 | /* Alist of registered file descriptors for D-Bus. |
| 1644 | An entry in this list is a list (FD WHAT WHY BLOCK). | 1671 | The key is an open file descriptor, retrieved via `dbus-call-method' |
| 1645 | The car of the list is a file descriptor retrieved from a | 1672 | or `dbus--open-fd'. The value is a string OBJECT-PATH or FILENAME, |
| 1646 | 'dbus-make-inhibitor-lock` call. The cdr of the list represents the | 1673 | which represents the arguments the function was called with. Those |
| 1647 | three arguments 'dbus-make-inhibitor-lock` was called with. */ | 1674 | values are not needed for further operations; they are just shown for |
| 1648 | static Lisp_Object xd_registered_inhibitor_locks; | 1675 | information. */ |
| 1649 | 1676 | static Lisp_Object xd_registered_fds; | |
| 1650 | DEFUN ("dbus-make-inhibitor-lock", Fdbus_make_inhibitor_lock, | 1677 | |
| 1651 | Sdbus_make_inhibitor_lock, | 1678 | DEFUN ("dbus--fd-open", Fdbus__fd_open, Sdbus__fd_open, 1, 1, 0, |
| 1652 | 2, 3, 0, | 1679 | doc: /* Open FILENAME and return the respective read-only file descriptor. */) |
| 1653 | doc: /* Inhibit system shutdowns and sleep states. | 1680 | (Lisp_Object filename) |
| 1654 | |||
| 1655 | WHAT is a colon-separated string of lock types, i.e. "shutdown", | ||
| 1656 | "sleep", "idle", "handle-power-key", "handle-suspend-key", | ||
| 1657 | "handle-hibernate-key", "handle-lid-switch". Example: "shutdown:idle". | ||
| 1658 | |||
| 1659 | WHY is a descriptive string of why the lock is taken. Example: "Package | ||
| 1660 | Update in Progress". | ||
| 1661 | |||
| 1662 | The optional BLOCK is the mode of the inhibitor lock, either "block" | ||
| 1663 | (BLOCK is non-nil), or "delay". | ||
| 1664 | |||
| 1665 | It returns a file descriptor or nil, if the lock cannot be acquired. If | ||
| 1666 | there is already an inhibitor lock for the triple (WHAT WHY BLOCK), this | ||
| 1667 | lock is returned. | ||
| 1668 | |||
| 1669 | For details of the arguments, see Info node `(dbus)Inhibitor Locks'. */) | ||
| 1670 | (Lisp_Object what, Lisp_Object why, Lisp_Object block) | ||
| 1671 | { | 1681 | { |
| 1672 | CHECK_STRING (what); | 1682 | CHECK_STRING (filename); |
| 1673 | CHECK_STRING (why); | 1683 | filename = Fexpand_file_name (filename, Qnil); |
| 1674 | if (!NILP (block)) | 1684 | filename = ENCODE_FILE (filename); |
| 1675 | block = Qt; | ||
| 1676 | Lisp_Object who = build_string ("Emacs"); | ||
| 1677 | Lisp_Object mode = | ||
| 1678 | (NILP (block)) ? build_string ("delay") : build_string ("block"); | ||
| 1679 | 1685 | ||
| 1680 | /* Check, whether it is registered already. */ | 1686 | /* Check, whether it is registered already. */ |
| 1681 | Lisp_Object triple = list3 (what, why, block); | 1687 | Lisp_Object registered = Frassoc (filename, xd_registered_fds); |
| 1682 | Lisp_Object registered = Frassoc (triple, xd_registered_inhibitor_locks); | ||
| 1683 | if (!NILP (registered)) | 1688 | if (!NILP (registered)) |
| 1684 | return CAR_SAFE (registered); | 1689 | return CAR_SAFE (registered); |
| 1685 | 1690 | ||
| 1686 | /* Register lock. */ | 1691 | /* Open file descriptor. */ |
| 1687 | Lisp_Object lock = | 1692 | int fd = emacs_open (SSDATA (filename), O_RDONLY, 0); |
| 1688 | calln (Qdbus_call_method, QCsystem, | ||
| 1689 | build_string ("org.freedesktop.login1"), | ||
| 1690 | build_string ("/org/freedesktop/login1"), | ||
| 1691 | build_string ("org.freedesktop.login1.Manager"), | ||
| 1692 | build_string ("Inhibit"), what, who, why, mode); | ||
| 1693 | |||
| 1694 | xd_registered_inhibitor_locks = | ||
| 1695 | Fcons (Fcons (lock, triple), xd_registered_inhibitor_locks); | ||
| 1696 | return lock; | ||
| 1697 | } | ||
| 1698 | 1693 | ||
| 1699 | DEFUN ("dbus-close-inhibitor-lock", Fdbus_close_inhibitor_lock, | 1694 | if (fd <= 0) |
| 1700 | Sdbus_close_inhibitor_lock, | 1695 | XD_SIGNAL2 (build_string ("Cannot open file"), filename); |
| 1701 | 1, 1, 0, | ||
| 1702 | doc: /* Close inhibitor lock file descriptor. | ||
| 1703 | 1696 | ||
| 1704 | LOCK, a file descriptor, must be the result of a `dbus-make-inhibitor-lock' | 1697 | /* Register file descriptor. */ |
| 1705 | call. It returns t in case of success, or nil if it isn't be possible | 1698 | xd_registered_fds = |
| 1706 | to close the lock, or if the lock is closed already. | 1699 | Fcons (Fcons (INT_TO_INTEGER (fd), filename), xd_registered_fds); |
| 1700 | return INT_TO_INTEGER (fd); | ||
| 1701 | } | ||
| 1707 | 1702 | ||
| 1708 | For details, see Info node `(dbus)Inhibitor Locks'. */) | 1703 | DEFUN ("dbus--fd-close", Fdbus__fd_close, Sdbus__fd_close, 1, 1, 0, |
| 1709 | (Lisp_Object lock) | 1704 | doc: /* Close file descriptor FD. |
| 1705 | FD must be the result of a `dbus-call-method' or `dbus--fd-open' call, | ||
| 1706 | see `dbus--registered-fds'. It returns t in case of success, or nil if | ||
| 1707 | it isn't be possible to close the file descriptor, or if the file | ||
| 1708 | descriptor is closed already. */) | ||
| 1709 | (Lisp_Object fd) | ||
| 1710 | { | 1710 | { |
| 1711 | CHECK_FIXNUM (lock); | 1711 | CHECK_FIXNUM (fd); |
| 1712 | 1712 | ||
| 1713 | /* Check, whether it is registered. */ | 1713 | /* Check, whether it is registered. */ |
| 1714 | Lisp_Object registered = assoc_no_quit (lock, xd_registered_inhibitor_locks); | 1714 | Lisp_Object registered = assoc_no_quit (fd, xd_registered_fds); |
| 1715 | if (NILP (registered)) | 1715 | if (NILP (registered)) |
| 1716 | return Qnil; | 1716 | return Qnil; |
| 1717 | else | 1717 | else |
| 1718 | { | 1718 | { |
| 1719 | xd_registered_inhibitor_locks = | 1719 | xd_registered_fds = Fdelete (registered, xd_registered_fds); |
| 1720 | Fdelete (registered, xd_registered_inhibitor_locks); | 1720 | return (emacs_close (XFIXNAT (fd)) == 0) ? Qt : Qnil; |
| 1721 | return (emacs_close (XFIXNAT (lock)) == 0) ? Qt : Qnil; | ||
| 1722 | } | 1721 | } |
| 1723 | } | 1722 | } |
| 1724 | 1723 | ||
| 1725 | DEFUN ("dbus-registered-inhibitor-locks", Fdbus_registered_inhibitor_locks, | 1724 | DEFUN ("dbus--registered-fds", Fdbus__registered_fds, Sdbus__registered_fds, |
| 1726 | Sdbus_registered_inhibitor_locks, | ||
| 1727 | 0, 0, 0, | 1725 | 0, 0, 0, |
| 1728 | doc: /* Return registered inhibitor locks, an alist. | 1726 | doc: /* Return registered file descriptors, an alist. |
| 1729 | This allows to check, whether other packages of the running Emacs | 1727 | The key is an open file descriptor, retrieved via `dbus-call-method' or |
| 1730 | instance have acquired an inhibitor lock as well. | 1728 | `dbus--open-fd'. The value is a string OBJECT-PATH or FILENAME, which |
| 1731 | An entry in this list is a list (FD WHAT WHY BLOCK). | 1729 | represents the arguments the function was called with. Those values are |
| 1732 | The car of the list is the file descriptor retrieved from a | 1730 | not needed for further operations; they are just shown for information. |
| 1733 | 'dbus-make-inhibitor-lock` call. The cdr of the list represents the | 1731 | |
| 1734 | three arguments 'dbus-make-inhibitor-lock` was called with. */) | 1732 | This alist allows to check, whether other packages of the running Emacs |
| 1733 | instance have acquired a file descriptor as well. */) | ||
| 1735 | (void) | 1734 | (void) |
| 1736 | { | 1735 | { |
| 1737 | /* We return a copy of xd_registered_inhibitor_locks, in order to | 1736 | /* We return a copy of xd_registered_fds, in order to protect it |
| 1738 | protect it against malicious manipulation. */ | 1737 | against malicious manipulation. */ |
| 1739 | Lisp_Object registered = xd_registered_inhibitor_locks; | 1738 | Lisp_Object registered = xd_registered_fds; |
| 1740 | Lisp_Object result = Qnil; | 1739 | Lisp_Object result = Qnil; |
| 1741 | for (; !NILP (registered); registered = CDR_SAFE (registered)) | 1740 | for (; !NILP (registered); registered = CDR_SAFE (registered)) |
| 1742 | result = Fcons (Fcopy_sequence (CAR_SAFE (registered)), result); | 1741 | { |
| 1742 | Lisp_Object tem = CAR_SAFE (registered); | ||
| 1743 | result = Fcons (Fcons (CAR_SAFE (tem), CDR_SAFE (tem)), result); | ||
| 1744 | } | ||
| 1743 | return Fnreverse (result); | 1745 | return Fnreverse (result); |
| 1744 | } | 1746 | } |
| 1745 | 1747 | ||
| @@ -1859,7 +1861,22 @@ xd_read_message_1 (DBusConnection *connection, Lisp_Object bus) | |||
| 1859 | Fremhash (key, Vdbus_registered_objects_table); | 1861 | Fremhash (key, Vdbus_registered_objects_table); |
| 1860 | 1862 | ||
| 1861 | /* Store the event. */ | 1863 | /* Store the event. */ |
| 1862 | xd_store_event (value, args, event_args); | 1864 | xd_store_event (CONSP (value) ? CAR_SAFE (value) : value, args, event_args); |
| 1865 | |||
| 1866 | #ifdef DBUS_TYPE_UNIX_FD | ||
| 1867 | /* Check, whether there is a file descriptor to be kept. | ||
| 1868 | value is (handler . path) | ||
| 1869 | args is ((:unix-fd NN) ...) */ | ||
| 1870 | if (CONSP (value) | ||
| 1871 | && CONSP (CAR_SAFE (args)) | ||
| 1872 | && EQ (CAR_SAFE (CAR_SAFE (args)), QCunix_fd)) | ||
| 1873 | { | ||
| 1874 | xd_registered_fds = | ||
| 1875 | Fcons (Fcons (CAR_SAFE (CDR_SAFE (CAR_SAFE (args))), | ||
| 1876 | CDR_SAFE (value)), | ||
| 1877 | xd_registered_fds); | ||
| 1878 | } | ||
| 1879 | #endif | ||
| 1863 | } | 1880 | } |
| 1864 | 1881 | ||
| 1865 | else /* DBUS_MESSAGE_TYPE_METHOD_CALL, DBUS_MESSAGE_TYPE_SIGNAL. */ | 1882 | else /* DBUS_MESSAGE_TYPE_METHOD_CALL, DBUS_MESSAGE_TYPE_SIGNAL. */ |
| @@ -1995,7 +2012,7 @@ static void | |||
| 1995 | syms_of_dbusbind_for_pdumper (void) | 2012 | syms_of_dbusbind_for_pdumper (void) |
| 1996 | { | 2013 | { |
| 1997 | xd_registered_buses = Qnil; | 2014 | xd_registered_buses = Qnil; |
| 1998 | xd_registered_inhibitor_locks = Qnil; | 2015 | xd_registered_fds = Qnil; |
| 1999 | } | 2016 | } |
| 2000 | 2017 | ||
| 2001 | void | 2018 | void |
| @@ -2003,9 +2020,9 @@ syms_of_dbusbind (void) | |||
| 2003 | { | 2020 | { |
| 2004 | defsubr (&Sdbus__init_bus); | 2021 | defsubr (&Sdbus__init_bus); |
| 2005 | defsubr (&Sdbus_get_unique_name); | 2022 | defsubr (&Sdbus_get_unique_name); |
| 2006 | defsubr (&Sdbus_make_inhibitor_lock); | 2023 | defsubr (&Sdbus__fd_open); |
| 2007 | defsubr (&Sdbus_close_inhibitor_lock); | 2024 | defsubr (&Sdbus__fd_close); |
| 2008 | defsubr (&Sdbus_registered_inhibitor_locks); | 2025 | defsubr (&Sdbus__registered_fds); |
| 2009 | 2026 | ||
| 2010 | DEFSYM (Qdbus_message_internal, "dbus-message-internal"); | 2027 | DEFSYM (Qdbus_message_internal, "dbus-message-internal"); |
| 2011 | defsubr (&Sdbus_message_internal); | 2028 | defsubr (&Sdbus_message_internal); |
| @@ -2030,6 +2047,11 @@ syms_of_dbusbind (void) | |||
| 2030 | /* Lisp symbol for method interactive authorization. */ | 2047 | /* Lisp symbol for method interactive authorization. */ |
| 2031 | DEFSYM (QCauthorizable, ":authorizable"); | 2048 | DEFSYM (QCauthorizable, ":authorizable"); |
| 2032 | 2049 | ||
| 2050 | /* Lisp symbol for file descriptor kept. */ | ||
| 2051 | #ifdef DBUS_TYPE_UNIX_FD | ||
| 2052 | DEFSYM (QCkeep_fd, ":keep-fd"); | ||
| 2053 | #endif | ||
| 2054 | |||
| 2033 | /* Lisp symbols of D-Bus types. */ | 2055 | /* Lisp symbols of D-Bus types. */ |
| 2034 | DEFSYM (QCbyte, ":byte"); | 2056 | DEFSYM (QCbyte, ":byte"); |
| 2035 | DEFSYM (QCboolean, ":boolean"); | 2057 | DEFSYM (QCboolean, ":boolean"); |
| @@ -2166,7 +2188,7 @@ be called when the D-Bus reply message arrives. */); | |||
| 2166 | /* Initialize internal objects. */ | 2188 | /* Initialize internal objects. */ |
| 2167 | pdumper_do_now_and_after_load (syms_of_dbusbind_for_pdumper); | 2189 | pdumper_do_now_and_after_load (syms_of_dbusbind_for_pdumper); |
| 2168 | staticpro (&xd_registered_buses); | 2190 | staticpro (&xd_registered_buses); |
| 2169 | staticpro (&xd_registered_inhibitor_locks); | 2191 | staticpro (&xd_registered_fds); |
| 2170 | 2192 | ||
| 2171 | Fprovide (intern_c_string ("dbusbind"), Qnil); | 2193 | Fprovide (intern_c_string ("dbusbind"), Qnil); |
| 2172 | } | 2194 | } |