diff --git a/CMakeLists.txt b/CMakeLists.txt --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -6,7 +6,7 @@ set(QT_MIN_VERSION "5.9.0") set(KF5_MIN_VERSION "5.42.0") -find_package(Qt5 ${QT_MIN_VERSION} CONFIG REQUIRED COMPONENTS Widgets Quick QuickWidgets Test) +find_package(Qt5 ${QT_MIN_VERSION} CONFIG REQUIRED COMPONENTS DBus Widgets Quick QuickWidgets Test) find_package(ECM ${KF5_MIN_VERSION} REQUIRED NO_MODULE) set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake ${ECM_MODULE_PATH} ${ECM_KDE_MODULE_DIR}) @@ -90,8 +90,26 @@ URL "https://www.freedesktop.org/software/systemd/man/loginctl.html" DESCRIPTION "Send control commands to the login manager" TYPE RUNTIME - PURPOSE "Needed for emergency unlock in case that the greeter is broken. In case your distribution does not provide loginctl please contact plasma-devel@kde.org to discuss alternatives." ) +set(HAVE_LOGINCTL ${loginctl_FOUND}) + +if ( NOT HAVE_LOGINCTL ) + find_package(ConsoleKit) + set_package_properties(ConsoleKit PROPERTIES + URL "https://github.com/ConsoleKit2/ConsoleKit2" + DESCRIPTION "Framework for tracking user login sessions" + TYPE RECOMMENDED + ) + set(HAVE_CONSOLEKIT ${ConsoleKit_FOUND}) +endif () + +if (HAVE_LOGINCTL OR HAVE_CONSOLEKIT) + set(HAVE_UNLOCK_CAPABILITY TRUE) +endif () + +add_feature_info("Unlock broken screenlocker" + HAVE_UNLOCK_CAPABILITY + "Needed for emergency unlock in case that the greeter is broken. In case your distribution does not provide loginctl or consolekit please contact plasma-devel@kde.org to discuss alternatives.") option(PAM_REQUIRED "Require building with PAM" ON) @@ -110,6 +128,10 @@ configure_file(config-unix.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config-unix.h ) configure_file(config-X11.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config-X11.h) +if (HAVE_CONSOLEKIT) + configure_file(ck-unlock-session.cmake ${CMAKE_CURRENT_BINARY_DIR}/ck-unlock-session) +endif () + # adjusting CMAKE_C_FLAGS to get wayland protocols to compile set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=gnu90") @@ -162,6 +184,7 @@ Qt5::Core Qt5::X11Extras PRIVATE + Qt5::DBus KF5::I18n KF5::IdleTime KF5::GlobalAccel @@ -206,7 +229,10 @@ configure_package_config_file("${CMAKE_CURRENT_SOURCE_DIR}/KScreenLockerConfig.cmake.in" "${CMAKE_CURRENT_BINARY_DIR}/KScreenLockerConfig.cmake" - INSTALL_DESTINATION "${CMAKECONFIG_INSTALL_PREFIX}/KScreenLocker") + INSTALL_DESTINATION "${CMAKECONFIG_INSTALL_PREFIX}/KScreenLocker") +if (HAVE_CONSOLEKIT) + install(PROGRAMS ${CMAKE_CURRENT_BINARY_DIR}/ck-unlock-session DESTINATION ${KDE_INSTALL_BINDIR}) +endif () install(TARGETS KScreenLocker EXPORT KScreenLockerTargets ${INSTALL_TARGETS_DEFAULT_ARGS} LIBRARY) install(EXPORT KScreenLockerTargets DESTINATION "${CMAKECONFIG_INSTALL_PREFIX}/KScreenLocker" FILE KScreenLockerTargets.cmake NAMESPACE PW::) diff --git a/abstractlocker.cpp b/abstractlocker.cpp --- a/abstractlocker.cpp +++ b/abstractlocker.cpp @@ -28,6 +28,7 @@ #include #include #include +#include #include @@ -49,13 +50,28 @@ QPainter p(this); p.fillRect(0, 0, width(), height(), Qt::black); if (m_greeterFailure) { - auto text = ki18n("The screen locker is broken and unlocking is not possible anymore.\n" - "In order to unlock switch to a virtual terminal (e.g. Ctrl+Alt+F2),\n" - "log in and execute the command:\n\n" - "loginctl unlock-session %1\n\n" - "Afterwards switch back to the running session (Ctrl+Alt+F%2)."); - text = text.subs(QString::fromLocal8Bit(qgetenv("XDG_SESSION_ID"))); - text = text.subs(QString::fromLocal8Bit(qgetenv("XDG_VTNR"))); + auto text = ki18n("The screen locker is broken and unlocking is not possible anymore.\n" + "In order to unlock it either ConsoleKit or LoginD is needed, none of\n" + "which could be found on your system."); + auto text_ck = ki18n("The screen locker is broken and unlocking is not possible anymore.\n" + "In order to unlock switch to a virtual terminal (e.g. Ctrl+Alt+F2),\n" + "log in as root and execute the command:\n\n" + "# ck-unlock-session \n\n"); + auto text_ld = ki18n("The screen locker is broken and unlocking is not possible anymore.\n" + "In order to unlock switch to a virtual terminal (e.g. Ctrl+Alt+F2),\n" + "log in and execute the command:\n\n" + "loginctl unlock-session %1\n\n" + "Afterwards switch back to the running session (Ctrl+Alt+F%2)."); + + auto haveService = [](QString service){return QDBusConnection::systemBus().interface()->isServiceRegistered(service);}; + if (haveService("org.freedesktop.ConsoleKit")) { + text = text_ck; + } else if (haveService("org.freedesktop.login1")) { + text = text_ld; + text = text.subs(QString::fromLocal8Bit(qgetenv("XDG_SESSION_ID"))); + text = text.subs(QString::fromLocal8Bit(qgetenv("XDG_VTNR"))); + } + p.setPen(Qt::white); QFont f = p.font(); f.setBold(true); diff --git a/ck-unlock-session.cmake b/ck-unlock-session.cmake new file mode 100644 --- /dev/null +++ b/ck-unlock-session.cmake @@ -0,0 +1,25 @@ +#!/bin/sh +# This helper script unlocks the Plasma5 screenlocker of the session given by argument, +# should the locker ever crash. +# +# Requirements: ConsoleKit[2] & qdbus +# + +# list running sesions +list_sessions () +{ + ${cklistsessions_EXECUTABLE} | grep -oE '^Session[^:]*' +} + +# unlock_session +unlock_session () +{ + ${qdbus_EXECUTABLE} --system org.freedesktop.ConsoleKit "/org/freedesktop/ConsoleKit/$1" org.freedesktop.ConsoleKit.Session.Unlock +} + +if [ $# -ne 1 ] ; then + list_sessions +else + unlock_session $1 +fi + diff --git a/cmake/Findloginctl.cmake b/cmake/FindConsoleKit.cmake copy from cmake/Findloginctl.cmake copy to cmake/FindConsoleKit.cmake --- a/cmake/Findloginctl.cmake +++ b/cmake/FindConsoleKit.cmake @@ -1,5 +1,5 @@ #============================================================================= -# Copyright 2016 Martin Gräßlin +# Copyright 2017 Tobias C. Berner # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions @@ -24,11 +24,13 @@ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF # THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #============================================================================= -find_program(loginctl_EXECUTABLE NAMES loginctl) -find_package_handle_standard_args(loginctl +find_program(cklistsessions_EXECUTABLE NAMES ck-list-sessions) +find_program(qdbus_EXECUTABLE NAMES qdbus) +find_package_handle_standard_args(ConsoleKit FOUND_VAR - loginctl_FOUND + ConsoleKit_FOUND REQUIRED_VARS - loginctl_EXECUTABLE + cklistsessions_EXECUTABLE + qdbus_EXECUTABLE ) -mark_as_advanced(loginctl_EXECUTABLE) +mark_as_advanced(ConsoleKit_FOUND cklistsessions_EXECUTABLE qdbus_EXECUTABLE) diff --git a/cmake/Findloginctl.cmake b/cmake/Findloginctl.cmake --- a/cmake/Findloginctl.cmake +++ b/cmake/Findloginctl.cmake @@ -31,4 +31,4 @@ REQUIRED_VARS loginctl_EXECUTABLE ) -mark_as_advanced(loginctl_EXECUTABLE) +mark_as_advanced(loginctl_FOUND loginctl_EXECUTABLE) diff --git a/config-kscreenlocker.h.cmake b/config-kscreenlocker.h.cmake --- a/config-kscreenlocker.h.cmake +++ b/config-kscreenlocker.h.cmake @@ -15,3 +15,4 @@ #cmakedefine01 HAVE_SECCOMP #cmakedefine01 HAVE_SIGNALFD_H #cmakedefine01 HAVE_EVENT_H +