diff --git a/CMakeLists.txt b/CMakeLists.txt index 4d662d9..9c0bf12 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -248,14 +248,6 @@ write_basic_package_version_file( COMPATIBILITY SameMajorVersion ) -# Configure Auth config file -configure_package_config_file( - "${CMAKE_CURRENT_SOURCE_DIR}/data/AuthConfig.cmake.in" - "${CMAKE_CURRENT_BINARY_DIR}/data/AuthConfig.cmake" - INSTALL_DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/DDM - PATH_VARS CMAKE_INSTALL_PREFIX -) - # Configure Common config file configure_package_config_file( "${CMAKE_CURRENT_SOURCE_DIR}/data/CommonConfig.cmake.in" @@ -269,7 +261,6 @@ install( FILES "${CMAKE_CURRENT_BINARY_DIR}/data/DDMConfig.cmake" "${CMAKE_CURRENT_BINARY_DIR}/data/DDMConfigVersion.cmake" - "${CMAKE_CURRENT_BINARY_DIR}/data/AuthConfig.cmake" "${CMAKE_CURRENT_BINARY_DIR}/data/CommonConfig.cmake" DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/DDM ) diff --git a/REUSE.toml b/REUSE.toml index f3b1e7c..5d004f3 100644 --- a/REUSE.toml +++ b/REUSE.toml @@ -69,7 +69,7 @@ SPDX-FileCopyrightText = "None" SPDX-License-Identifier = "GPL-2.0-or-later" [[annotations]] -path = ["releng/prepare-relnotes", "src/daemon/Auth.cpp", "src/daemon/Auth.h", "src/common/ConfigReader.cpp", "src/common/ConfigReader.h", "src/common/Configuration.cpp", "src/common/Configuration.h", "src/common/MessageHandler.h", "src/common/Messages.h", "src/common/SafeDataStream.cpp", "src/common/SafeDataStream.h", "src/common/Session.cpp", "src/common/Session.h", "src/common/SignalHandler.cpp", "src/common/SignalHandler.h", "src/common/SocketWriter.cpp", "src/common/SocketWriter.h", "src/common/ThemeConfig.cpp", "src/common/ThemeConfig.h", "src/common/ThemeMetadata.cpp", "src/common/ThemeMetadata.h", "src/common/VirtualTerminal.cpp", "src/common/VirtualTerminal.h", "src/common/XAuth.cpp", "src/common/XAuth.h", "src/daemon/DaemonApp.cpp", "src/daemon/DaemonApp.h", "src/daemon/Display.cpp", "src/daemon/Display.h", "src/daemon/DisplayManager.cpp", "src/daemon/DisplayManager.h", "src/daemon/DisplayServer.cpp", "src/daemon/DisplayServer.h", "src/daemon/Greeter.cpp", "src/daemon/Greeter.h", "src/daemon/PowerManager.cpp", "src/daemon/PowerManager.h", "src/daemon/Seat.cpp", "src/daemon/Seat.h", "src/daemon/SeatManager.cpp", "src/daemon/SeatManager.h", "src/daemon/SocketServer.cpp", "src/daemon/SocketServer.h", "src/daemon/TreelandConnector.cpp", "src/daemon/TreelandConnector.h", "src/daemon/Utils.h", "src/daemon/WaylandDisplayServer.cpp", "src/daemon/WaylandDisplayServer.h", "src/daemon/XorgDisplayServer.cpp", "src/daemon/XorgDisplayServer.h", "src/daemon/XorgUserDisplayServer.cpp", "src/daemon/XorgUserDisplayServer.h", "src/greeter/GreeterApp.h", "src/greeter/GreeterProxy.cpp", "src/greeter/GreeterProxy.h", "src/greeter/SessionModel.cpp", "src/greeter/SessionModel.h", "src/greeter/UserModel.cpp", "src/greeter/UserModel.h", "src/daemon/Pam.cpp", "src/daemon/Pam.h", "src/daemon/UserSession.cpp", "src/daemon/UserSession.h", "src/common/LogindDBusTypes.cpp", "src/common/LogindDBusTypes.h", "src/greeter/GreeterApp.cpp"] +path = ["releng/prepare-relnotes", "src/daemon/Auth.cpp", "src/daemon/Auth.h", "src/common/ConfigReader.cpp", "src/common/ConfigReader.h", "src/common/Configuration.cpp", "src/common/Configuration.h", "src/common/MessageHandler.h", "src/common/Messages.h", "src/common/SafeDataStream.cpp", "src/common/SafeDataStream.h", "src/common/Session.cpp", "src/common/Session.h", "src/common/SignalHandler.cpp", "src/common/SignalHandler.h", "src/common/SocketWriter.cpp", "src/common/SocketWriter.h", "src/common/ThemeConfig.cpp", "src/common/ThemeConfig.h", "src/common/ThemeMetadata.cpp", "src/common/ThemeMetadata.h", "src/common/VirtualTerminal.cpp", "src/common/VirtualTerminal.h", "src/common/XAuth.cpp", "src/common/XAuth.h", "src/daemon/DaemonApp.cpp", "src/daemon/DaemonApp.h", "src/daemon/Display.cpp", "src/daemon/Display.h", "src/daemon/DisplayManager.cpp", "src/daemon/DisplayManager.h", "src/daemon/PowerManager.cpp", "src/daemon/PowerManager.h", "src/daemon/Seat.cpp", "src/daemon/Seat.h", "src/daemon/SeatManager.cpp", "src/daemon/SeatManager.h", "src/daemon/SocketServer.cpp", "src/daemon/SocketServer.h", "src/daemon/TreelandConnector.cpp", "src/daemon/TreelandConnector.h", "src/daemon/Utils.h", "src/daemon/XorgDisplayServer.cpp", "src/daemon/XorgDisplayServer.h", "src/greeter/GreeterApp.h", "src/greeter/GreeterProxy.cpp", "src/greeter/GreeterProxy.h", "src/greeter/SessionModel.cpp", "src/greeter/SessionModel.h", "src/greeter/UserModel.cpp", "src/greeter/UserModel.h", "src/daemon/Pam.cpp", "src/daemon/Pam.h", "src/daemon/UserSession.cpp", "src/daemon/UserSession.h", "src/common/LogindDBusTypes.cpp", "src/common/LogindDBusTypes.h", "src/greeter/GreeterApp.cpp"] precedence = "aggregate" SPDX-FileCopyrightText = "None" SPDX-License-Identifier = "GPL-2.0-or-later" diff --git a/data/AuthConfig.cmake.in b/data/AuthConfig.cmake.in deleted file mode 100644 index 4404212..0000000 --- a/data/AuthConfig.cmake.in +++ /dev/null @@ -1,34 +0,0 @@ -@PACKAGE_INIT@ - -# 导入 AuthTargets 文件 -include("${CMAKE_CURRENT_LIST_DIR}/AuthTargets.cmake") - -# 如果定义了 COMPONENTS 选项,则导出相应的信息 -if(DEFINED COMPONENTS) - foreach(comp ${COMPONENTS}) - if(comp STREQUAL "Auth") - set(Auth_FOUND TRUE) - set(Auth_INCLUDE_DIRS "${CMAKE_INSTALL_PREFIX}/include/ddm") - set(Auth_LIBRARIES Auth) - else() - message(FATAL_ERROR "Unknown component: ${comp}") - endif() - endforeach() -endif() - -# 如果没有定义 COMPONENTS 选项,则默认导出所有信息 -if(NOT DEFINED COMPONENTS OR "${COMPONENTS}" STREQUAL "Auth") - set(Auth_FOUND TRUE) - set(Auth_INCLUDE_DIRS "${CMAKE_INSTALL_PREFIX}/include/ddm") - set(Auth_LIBRARIES Auth) -endif() - -# 检查是否找到了相应的组件 -if(NOT Auth_FOUND) - message(FATAL_ERROR "Auth component not found.") -endif() - -# 导出 Auth 的头文件路径和库文件 -set(Auth_INCLUDE_DIRS ${Auth_INCLUDE_DIRS} ${Auth_INCLUDE_DIRS} PARENT_SCOPE) -set(Auth_LIBRARIES ${Auth_LIBRARIES} ${Auth_LIBRARIES} PARENT_SCOPE) - diff --git a/data/DDMConfig.cmake.in b/data/DDMConfig.cmake.in index 65e63d5..2a47273 100644 --- a/data/DDMConfig.cmake.in +++ b/data/DDMConfig.cmake.in @@ -7,7 +7,6 @@ set(DDM_VERSION_PATCH @DDM_VERSION_PATCH@) set(DDM_VERSION @DDM_VERSION_STRING@) # 导入 Auth 和 Common 模块的配置文件 -include("${CMAKE_CURRENT_LIST_DIR}/AuthConfig.cmake") include("${CMAKE_CURRENT_LIST_DIR}/CommonConfig.cmake") # 导出 DDM 相关的信息 @@ -18,12 +17,7 @@ set(DDM_LIBRARIES Auth Common) # 如果定义了 COMPONENTS 选项,则导出相应的信息 if(DEFINED COMPONENTS) foreach(comp ${COMPONENTS}) - if(comp STREQUAL "Auth") - set(DDM_FOUND TRUE) - set(DDM_AUTH_FOUND TRUE) - set(DDM_INCLUDE_DIRS ${DDM_INCLUDE_DIRS} ${Auth_INCLUDE_DIRS}) - set(DDM_LIBRARIES ${DDM_LIBRARIES} ${Auth_LIBRARIES}) - elseif(comp STREQUAL "Common") + if(comp STREQUAL "Common") set(DDM_FOUND TRUE) set(DDM_COMMON_FOUND TRUE) set(DDM_INCLUDE_DIRS ${DDM_INCLUDE_DIRS} ${Common_INCLUDE_DIRS}) @@ -35,7 +29,7 @@ if(DEFINED COMPONENTS) endif() # 如果没有定义 COMPONENTS 选项,则默认导出所有信息 -if(NOT DEFINED COMPONENTS OR "${COMPONENTS}" STREQUAL "Auth;Common") +if(NOT DEFINED COMPONENTS OR "${COMPONENTS}" STREQUAL "Common") set(DDM_FOUND TRUE) set(DDM_INCLUDE_DIRS ${DDM_INCLUDE_DIRS} PARENT_SCOPE) set(DDM_LIBRARIES ${DDM_LIBRARIES} PARENT_SCOPE) diff --git a/src/daemon/Auth.cpp b/src/daemon/Auth.cpp index 002211b..673728f 100644 --- a/src/daemon/Auth.cpp +++ b/src/daemon/Auth.cpp @@ -36,88 +36,78 @@ namespace DDM { , id(++lastId) , m_pam(new Pam(this)) , m_session(new UserSession(this)) { - connect(this, &Auth::finished, this, [this] { - active = false; - }); + connect(m_session, + QOverload::of(&QProcess::finished), + this, + &Auth::userProcessFinished); } Auth::~Auth() { stop(); } -#define LOGIN_FAILED \ - const QString displayId = environment.value(QStringLiteral("DISPLAY")); \ - const QString vt = environment.value(QStringLiteral("XDG_VTNR")); \ - utmpLogin(vt, displayId, user, 0, false); \ - Q_EMIT finished(AUTH_ERROR); \ - return; - - void Auth::start(const QByteArray &secret) { - Q_ASSERT(getuid() == 0); - - active = true; + bool Auth::authenticate(const QByteArray &secret) { m_pam->user = user; if (!m_pam->start()) { - Q_EMIT authentication(user, false, identifyOnly); - LOGIN_FAILED + utmpLogin(std::to_string(tty).c_str(), display, user, 0, false); + return false; } - if (!skipAuth && !m_pam->authenticate(secret)) { - Q_EMIT authentication(user, false, identifyOnly); - LOGIN_FAILED + utmpLogin(std::to_string(tty).c_str(), display, user, 0, false); + return false; } + active = true; + return true; + } - Q_EMIT authentication(user, true, identifyOnly); - - if (!sessionPath.isEmpty()) { - auto sessionEnv = m_pam->openSession(environment); - if (!sessionEnv.has_value()) { - Q_EMIT sessionStarted(false, 0); - Q_EMIT finished(SESSION_ERROR); - return; - } - - QProcessEnvironment env = *sessionEnv; - xdgSessionId = env.value(QStringLiteral("XDG_SESSION_ID")).toInt(); - Q_EMIT sessionStarted(true, xdgSessionId); - - struct passwd *pw; - pw = getpwnam(qPrintable(user)); - if (pw) { - env.insert(QStringLiteral("HOME"), QString::fromLocal8Bit(pw->pw_dir)); - env.insert(QStringLiteral("PWD"), QString::fromLocal8Bit(pw->pw_dir)); - env.insert(QStringLiteral("SHELL"), QString::fromLocal8Bit(pw->pw_shell)); - env.insert(QStringLiteral("USER"), QString::fromLocal8Bit(pw->pw_name)); - env.insert(QStringLiteral("LOGNAME"), QString::fromLocal8Bit(pw->pw_name)); - } - m_session->setProcessEnvironment(env); - m_session->start(); - - // write successful login to utmp/wtmp - const QString displayId = env.value(QStringLiteral("DISPLAY")); - const QString vt = env.value(QStringLiteral("XDG_VTNR")); - // cache pid for session end - utmpLogin(vt, displayId, user, m_session->processId(), true); + int Auth::openSession(const QProcessEnvironment &env) { + Q_ASSERT(active); + auto ret = m_pam->openSession(env); + if (!ret.has_value()) + return -1; + m_env = *ret; + xdgSessionId = m_env.value(QStringLiteral("XDG_SESSION_ID")).toInt(); + return xdgSessionId; + } + + void Auth::startUserProcess(const QString &command, Display::DisplayServerType type, const QByteArray &cookie) { + Q_ASSERT(!m_env.isEmpty()); + QProcessEnvironment env = m_env; + struct passwd *pw = getpwnam(qPrintable(user)); + if (pw) { + env.insert(QStringLiteral("HOME"), QString::fromLocal8Bit(pw->pw_dir)); + env.insert(QStringLiteral("PWD"), QString::fromLocal8Bit(pw->pw_dir)); + env.insert(QStringLiteral("SHELL"), QString::fromLocal8Bit(pw->pw_shell)); + env.insert(QStringLiteral("USER"), QString::fromLocal8Bit(pw->pw_name)); + env.insert(QStringLiteral("LOGNAME"), QString::fromLocal8Bit(pw->pw_name)); } - return; + m_session->setProcessEnvironment(env); + m_session->start(command, type, cookie); + + // write successful login to utmp/wtmp + const QString displayId = env.value(QStringLiteral("DISPLAY")); + const QString vt = env.value(QStringLiteral("XDG_VTNR")); + // cache pid for session end + utmpLogin(vt, displayId, user, m_session->processId(), true); } void Auth::stop() { - Q_ASSERT(getuid() == 0); - + if (!active) + return; + active = false; qint64 pid = m_session->processId(); - m_session->stop(); - if (!identifyOnly && m_pam->sessionOpened) { + if (m_session->state() != QProcess::NotRunning) + m_session->stop(); + if (m_pam->sessionOpened) m_pam->closeSession(); - } // write logout to utmp/wtmp - if (pid <= 0) - return; - QProcessEnvironment env = m_session->processEnvironment(); - QString vt = env.value(QStringLiteral("XDG_VTNR")); - QString displayId = env.value(QStringLiteral("DISPLAY")); - utmpLogout(vt, displayId, pid); + if (pid > 0) { + QProcessEnvironment env = m_session->processEnvironment(); + QString vt = env.value(QStringLiteral("XDG_VTNR")); + QString displayId = env.value(QStringLiteral("DISPLAY")); + utmpLogout(vt, displayId, pid); + } } void Auth::utmpLogin(const QString &vt, const QString &displayName, const QString &user, qint64 pid, bool authSuccessful) { diff --git a/src/daemon/Auth.h b/src/daemon/Auth.h index 39a942f..844a8af 100644 --- a/src/daemon/Auth.h +++ b/src/daemon/Auth.h @@ -21,7 +21,7 @@ #ifndef DDM_AUTH_H #define DDM_AUTH_H -#include "Session.h" +#include "Display.h" #include #include @@ -36,39 +36,29 @@ namespace DDM { Auth(QObject *parent); ~Auth(); - enum ExitStatus { - SUCCESS = 0, - AUTH_ERROR, - SESSION_ERROR, - OTHER_ERROR, - DISPLAYSERVER_ERROR, - TTY_ERROR, - }; - Q_ENUM(ExitStatus) - bool active{ false }; - QString displayServerCmd{}; - QString sessionPath{}; - Session::Type sessionType{ Session::UnknownSession }; - QString sessionFileName{}; QString user{}; QByteArray cookie{}; - bool autologin{ false }; - bool greeter{ false }; bool singleMode{ false }; - bool identifyOnly{ false }; bool skipAuth{ false }; - QProcessEnvironment environment{ }; + int id{ 0 }; static int lastId; QString sessionId{}; + QString display{}; int tty{ 0 }; int xdgSessionId{ 0 }; public Q_SLOTS: /** * Sets up the environment and starts the authentication */ - void start(const QByteArray &secret); + bool authenticate(const QByteArray &secret); + + int openSession(const QProcessEnvironment &env); + + void startUserProcess(const QString &command, + Display::DisplayServerType type, + const QByteArray &cookie = QByteArray()); /** * Indicates that we do not need the process anymore. @@ -77,33 +67,16 @@ namespace DDM { Q_SIGNALS: /** - * Emitted when authentication phase finishes - * - * @note If you want to set some environment variables for the session right before the - * session is started, connect to this signal using a blocking connection and insert anything - * you need in the slot. - * @param user username - * @param success true if succeeded - */ - void authentication(QString user, bool success, bool identifyOnly); - - /** - * Emitted when session starting phase finishes - * - * @param success true if succeeded - */ - void sessionStarted(bool success, int xdgSessionId); - - /** - * Emitted when the session ends. - * - * @param success true if every underlying task went fine - */ - void finished(Auth::ExitStatus status); + * Emitted when the session ends. + * + * @param success true if every underlying task went fine + */ + void userProcessFinished(int status); private: Pam *m_pam { nullptr }; UserSession *m_session{ nullptr }; + QProcessEnvironment m_env{}; /** * Write utmp/wtmp/btmp records when a user logs in diff --git a/src/daemon/CMakeLists.txt b/src/daemon/CMakeLists.txt index 013f325..885c12f 100644 --- a/src/daemon/CMakeLists.txt +++ b/src/daemon/CMakeLists.txt @@ -29,8 +29,6 @@ set(DAEMON_SOURCES DaemonApp.cpp Display.cpp DisplayManager.cpp - DisplayServer.cpp - Greeter.cpp Pam.cpp PowerManager.cpp Seat.cpp @@ -39,12 +37,7 @@ set(DAEMON_SOURCES TreelandConnector.cpp UserSession.cpp XorgDisplayServer.cpp - XorgUserDisplayServer.cpp - XorgUserDisplayServer.h - WaylandDisplayServer.cpp - WaylandDisplayServer.h - SingleWaylandDisplayServer.h - SingleWaylandDisplayServer.cpp + TreelandDisplayServer.cpp ${TREELAND_DDM_SOURCE} ) diff --git a/src/daemon/Display.cpp b/src/daemon/Display.cpp index e6c2ff7..54d452c 100644 --- a/src/daemon/Display.cpp +++ b/src/daemon/Display.cpp @@ -21,16 +21,14 @@ #include "Display.h" +#include "Auth.h" #include "Configuration.h" #include "DaemonApp.h" #include "DisplayManager.h" #include "XorgDisplayServer.h" -#include "XorgUserDisplayServer.h" -#include "SingleWaylandDisplayServer.h" +#include "TreelandDisplayServer.h" #include "Seat.h" #include "SocketServer.h" -#include "Greeter.h" -#include "Utils.h" #include "Messages.h" #include "SocketWriter.h" @@ -55,14 +53,12 @@ #include "Login1Manager.h" #include "Login1Session.h" #include "VirtualTerminal.h" -#include "WaylandDisplayServer.h" #include "config.h" -static int s_ttyFailures = 0; #define STRINGIFY(x) #x namespace DDM { - bool isTtyInUse(const QString &desiredTty) { + static bool isTtyInUse(const QString &desiredTty) { if (Logind::isAvailable()) { OrgFreedesktopLogin1ManagerInterface manager(Logind::serviceName(), Logind::managerPath(), QDBusConnection::systemBus()); auto reply = manager.ListSessions(); @@ -81,7 +77,7 @@ namespace DDM { return false; } - int fetchAvailableVt() { + static int fetchAvailableVt() { if (!isTtyInUse(QStringLiteral("tty" STRINGIFY(DDM_INITIAL_VT)))) { return DDM_INITIAL_VT; } @@ -92,64 +88,22 @@ namespace DDM { return VirtualTerminal::setUpNewVt(); } - Display::DisplayServerType Display::defaultDisplayServerType() - { - const QString &displayServerType = mainConfig.DisplayServer.get().toLower(); - DisplayServerType ret; - if (displayServerType == QStringLiteral("x11-user")) { - ret = X11UserDisplayServerType; - } else if (displayServerType == QStringLiteral("wayland")) { - ret = WaylandDisplayServerType; - } else if (displayServerType == QStringLiteral("single")) { - ret = SingleCompositerServerType; - } else { - if (displayServerType != QLatin1String("x11")) { - qWarning("\"%s\" is an invalid value for General.DisplayServer: fall back to \"x11\"", - qPrintable(displayServerType)); - } - ret = X11DisplayServerType; - } - return ret; - } + Display::Display(Seat *parent) + : QObject(parent) + , seat(parent) + , m_socketServer(new SocketServer(this)) { - Display::Display(Seat *parent, DisplayServerType serverType) - : QObject(parent), - m_displayServerType(serverType), - m_seat(parent), - m_socketServer(new SocketServer(this)), - m_greeter(new Greeter(this)) - { // Create display server - switch (m_displayServerType) { - case X11DisplayServerType: - m_terminalId = VirtualTerminal::setUpNewVt(); - m_displayServer = new XorgDisplayServer(this); - break; - case X11UserDisplayServerType: - m_terminalId = fetchAvailableVt(); - m_displayServer = new XorgUserDisplayServer(this); - m_greeter->setDisplayServerCommand(XorgUserDisplayServer::command(this)); - break; - case WaylandDisplayServerType: - m_terminalId = fetchAvailableVt(); - m_displayServer = new WaylandDisplayServer(this); - m_greeter->setDisplayServerCommand(mainConfig.Wayland.CompositorCommand.get()); - break; - case SingleCompositerServerType: - m_terminalId = fetchAvailableVt(); - m_displayServer = new SingleWaylandDisplayServer(m_socketServer, this); - m_greeter->setDisplayServerCommand(mainConfig.Single.CompositorCommand.get()); - m_greeter->setSingleMode(); - // Record current VT as ddm user session - DaemonApp::instance()->displayManager()->AddSession({}, seat()->name(), "ddm", static_cast(VirtualTerminal::currentVt())); - break; - } + terminalId = fetchAvailableVt(); + qDebug("Using VT %d", terminalId); + m_treeland = new TreelandDisplayServer(m_socketServer, this); - qDebug("Using VT %d", m_terminalId); - - // restart display after display server ended - connect(m_displayServer, &DisplayServer::started, this, &Display::displayServerStarted); - connect(m_displayServer, &DisplayServer::stopped, this, &Display::stop); + // Record current VT as ddm user session + DaemonApp::instance()->displayManager()->AddSession( + {}, + seat->name(), + "ddm", + static_cast(VirtualTerminal::currentVt())); // connect connected signal connect(m_socketServer, &SocketServer::connected, this, &Display::connected); @@ -166,72 +120,21 @@ namespace DDM { // connect login result signals connect(this, &Display::loginFailed, m_socketServer, &SocketServer::loginFailed); connect(this, &Display::loginSucceeded, m_socketServer, &SocketServer::loginSucceeded); - - connect(m_greeter, &Greeter::failed, this, &Display::stop); - connect(m_greeter, &Greeter::ttyFailed, this, [this] { - ++s_ttyFailures; - if (s_ttyFailures > 5) { - QCoreApplication::exit(23); - } - // It might be the case that we are trying a tty that has been taken over by a - // different process. In such a case, switch back to the initial one and try again. - VirtualTerminal::jumpToVt(DDM_INITIAL_VT, true); - stop(); - }); - connect(m_greeter, &Greeter::displayServerFailed, this, &Display::displayServerFailed); - connect(m_greeter, &Greeter::greeterStarted, this, [this] { - if (m_currentAuth) { - switchToUser(m_currentAuth->user, m_currentAuth->xdgSessionId); - } - }); } Display::~Display() { - for (auto *item : m_auths) { - disconnect(item, &Auth::finished, this, &Display::slotHelperFinished); - } + for (auto *item : m_auths) + disconnect(item, &Auth::userProcessFinished, this, &Display::userProcessFinished); stop(); } - Display::DisplayServerType Display::displayServerType() const - { - return m_displayServerType; - } - - DisplayServer *Display::displayServer() const - { - return m_displayServer; - } - - int Display::terminalId() const { - // TODO: if not use single wayland mode, m_auths only have one element. - return !m_auths.isEmpty() && m_auths.first()->active ? m_sessionTerminalId : m_terminalId; - } - - const QString &Display::name() const { - return m_displayServer->display(); - } - - QString Display::sessionType() const { - return m_displayServer->sessionType(); - } - - Seat *Display::seat() const { - return m_seat; - } - void Display::switchToUser(const QString &user, int xdgSessionId) { - if (user == "dde") { - m_greeter->setUserActivated(false); - } - if (xdgSessionId <= 0) { qFatal() << "Invalid xdg session id" << xdgSessionId << "for user" << user; return; } - auto* server = reinterpret_cast(m_displayServer); - server->activateUser(user, xdgSessionId); + m_treeland->activateUser(user, xdgSessionId); if (Logind::isAvailable()) { OrgFreedesktopLogin1ManagerInterface manager(Logind::serviceName(), Logind::managerPath(), QDBusConnection::systemBus()); @@ -240,90 +143,28 @@ namespace DDM { } bool Display::start() { - return m_started || m_displayServer->start(); - } - - bool Display::attemptAutologin() { - Session::Type sessionType = Session::X11Session; - - // determine session type - QString autologinSession = mainConfig.Autologin.Session.get(); - // not configured: try last successful logged in - if (autologinSession.isEmpty()) { - autologinSession = stateConfig.Last.Session.get(); - } - if (findSessionEntry(mainConfig.Wayland.SessionDir.get(), autologinSession)) { - sessionType = Session::WaylandSession; - } else if (findSessionEntry(mainConfig.X11.SessionDir.get(), autologinSession)) { - sessionType = Session::X11Session; - } else { - qCritical() << "Unable to find autologin session entry" << autologinSession; - return false; - } - - Session session; - session.setTo(sessionType, autologinSession); - - startAuth(mainConfig.Autologin.User.get(), QString(), session); - - return true; - } - - void Display::displayServerStarted() { - // check flag if (m_started) - return; - - // setup display - m_displayServer->setupDisplay(); - - // log message - qDebug() << "Display server started."; - - if ((daemonApp->first || mainConfig.Autologin.Relogin.get()) && - !mainConfig.Autologin.User.get().isEmpty()) { - // reset first flag - daemonApp->first = false; + return true; - // set flags - m_started = true; - - bool success = attemptAutologin(); - if (success) { - return; - } else { - qWarning() << "Autologin failed!"; - } - } + VirtualTerminal::jumpToVt(terminalId, false); + if (!m_treeland->start()) + return false; // start socket server - m_socketServer->start(m_displayServer->display()); + m_socketServer->start("treeland"); // Update dbus info DaemonApp::instance()->displayManager()->setAuthInfo(m_socketServer->socketAddress()); - if (!daemonApp->testing()) { - // change the owner and group of the socket to avoid permission denied errors - struct passwd *pw = getpwnam("dde"); - if (pw) { - if (chown(qPrintable(m_socketServer->socketAddress()), pw->pw_uid, pw->pw_gid) == -1) { - qWarning() << "Failed to change owner of the socket"; - return; - } - } - } - - m_greeter->setSocket(m_socketServer->socketAddress()); - m_greeter->setTheme(findGreeterTheme()); - - // start greeter - m_greeter->start(); - - // reset first flag - daemonApp->first = false; + // change the owner and group of the socket to avoid permission denied errors + struct passwd *pw = getpwnam("dde"); + if (pw && chown(qPrintable(m_socketServer->socketAddress()), pw->pw_uid, pw->pw_gid) == -1) + qWarning() << "Failed to change owner of the socket"; // set flags m_started = true; + + return true; } void Display::stop() { @@ -331,9 +172,6 @@ namespace DDM { if (!m_started) return; - // stop the greeter - m_greeter->stop(); - for (auto *item : m_auths) { item->stop(); } @@ -341,10 +179,11 @@ namespace DDM { // stop socket server m_socketServer->stop(); + if (m_x11Server) + m_x11Server->stop(); + // stop display server - m_displayServer->blockSignals(true); - m_displayServer->stop(); - m_displayServer->blockSignals(false); + m_treeland->stop(); // reset flag m_started = false; @@ -357,7 +196,7 @@ namespace DDM { m_socket = socket; // send logined user (for possible crash recovery) SocketWriter writer(socket); - for (Auth *auth : loginedSession()) { + for (Auth *auth : m_auths) { if (auth->active) writer << quint32(DaemonMessages::UserLoggedIn) << auth->user << auth->xdgSessionId; } @@ -399,59 +238,31 @@ namespace DDM { startIdentify(user, password); } - QString Display::findGreeterTheme() const { - QString themeName = mainConfig.Theme.Current.get(); - - // an unconfigured theme means the user wants to load the - // default theme from the resources - if (themeName.isEmpty()) - return QString(); - - QDir dir(mainConfig.Theme.ThemeDir.get()); - - // return the default theme if it exists - if (dir.exists(themeName)) - return dir.absoluteFilePath(themeName); - - // otherwise use the embedded theme - qWarning() << "The configured theme" << themeName << "doesn't exist, using the embedded theme instead"; - return QString(); - } - - bool Display::findSessionEntry(const QStringList &dirPaths, const QString &name) const { - const QFileInfo fileInfo(name); - QString fileName = name; - - // append extension - const QString extension = QStringLiteral(".desktop"); - if (!fileName.endsWith(extension)) - fileName += extension; - - for (const auto &path: dirPaths) { - QDir dir = path; - - // Given an absolute path: Check that it matches dir - if (fileInfo.isAbsolute() && fileInfo.absolutePath() != dir.absolutePath()) - continue; - - if (dir.exists(fileName)) - return true; - } - return false; - } - void Display::startIdentify(const QString &user, const QString &password) { qDebug() << "start Identify user" << user; - auto *auth = new Auth(this); - auth->setObjectName("userIdentify"); - m_auths.push_back(auth); + Auth auth(this); + auth.setObjectName("userIdentify"); - connect(auth, &Auth::authentication, this, &Display::slotAuthenticationFinished); - connect(auth, &Auth::finished, this, &Display::slotHelperFinished); + auth.user = user; + if (auth.authenticate(password.toLocal8Bit())) { + DaemonApp::instance()->displayManager()->setLastActivatedUser(user); + if (mainConfig.Users.RememberLastUser.get()) + stateConfig.Last.User.set(user); + else + stateConfig.Last.User.setDefault(); + stateConfig.save(); - auth->user = user; - auth->identifyOnly = true; - auth->start(password.toLocal8Bit()); + m_treeland->onLoginSucceeded(user); + // TODO: Use exact ID when there're multiple sessions for a user + int xdgSessionId = 0; + for (auto *auth : std::as_const(m_auths)) { + if (auth->user == user && auth->xdgSessionId > 0) { + xdgSessionId = auth->xdgSessionId; + break; + } + } + switchToUser(user, xdgSessionId); + } } void Display::startAuth(const QString &user, const QString &password, const Session &session) { @@ -465,14 +276,8 @@ namespace DDM { } } - if (!auth) { + if (!auth) auth = new Auth(this); - m_auths << auth; - } - - connect(auth, &Auth::authentication, this, &Display::slotAuthenticationFinished); - connect(auth, &Auth::sessionStarted, this, &Display::slotSessionStarted); - connect(auth, &Auth::finished, this, &Display::slotHelperFinished); if (auth->active) { qWarning() << "Existing authentication ongoing, aborting"; @@ -493,230 +298,103 @@ namespace DDM { return; } - m_reuseSessionId = QString(); - - if (Logind::isAvailable() && mainConfig.Users.ReuseSession.get()) { - OrgFreedesktopLogin1ManagerInterface manager(Logind::serviceName(), Logind::managerPath(), QDBusConnection::systemBus()); - auto reply = manager.ListSessions(); - reply.waitForFinished(); + auth->user = user; + auth->tty = terminalId; + auth->singleMode = session.isSingleMode(); + if (!auth->authenticate(password.toLocal8Bit())) + return; - const auto info = reply.value(); - for(const SessionInfo &s : reply.value()) { - if (s.userName == user) { - OrgFreedesktopLogin1SessionInterface session(Logind::serviceName(), s.sessionPath.path(), QDBusConnection::systemBus()); - if (session.service() == QLatin1String("dde") && session.state() == QLatin1String("online")) { - m_reuseSessionId = s.sessionId; - break; - } - } - } - } + // some information + qDebug() << "Session" << session.fileName() << "selected, command:" << session.exec() + << "for VT" << auth->tty; - auth->tty = m_terminalId; - if ((session.type() == Session::WaylandSession && m_displayServerType == X11DisplayServerType) || (m_greeter->isRunning() && m_displayServerType != X11DisplayServerType) || (m_displayServerType == SingleCompositerServerType)) { - // Create a new VT when we need to have another compositor running - auth->tty = VirtualTerminal::setUpNewVt(); - } + DaemonApp::instance()->displayManager()->setLastActivatedUser(user); - // some information - qDebug() << "Session" << session.fileName() << "selected, command:" << session.exec() << "for VT" << auth->tty; + // save last user and last session + if (mainConfig.Users.RememberLastUser.get()) + stateConfig.Last.User.set(auth->user); + else + stateConfig.Last.User.setDefault(); + if (mainConfig.Users.RememberLastSession.get()) + stateConfig.Last.Session.set(session.fileName()); + else + stateConfig.Last.Session.setDefault(); + stateConfig.save(); QProcessEnvironment env; env.insert(session.additionalEnv()); - env.insert(QStringLiteral("PATH"), mainConfig.Users.DefaultPath.get()); - // session id - { - const QString sessionId = QStringLiteral("Session%1").arg(daemonApp->newSessionId()); - daemonApp->displayManager()->AddSession(sessionId, seat()->name(), user, auth->tty); - env.insert(QStringLiteral("XDG_SESSION_PATH"), daemonApp->displayManager()->sessionPath(sessionId)); - auth->sessionId = sessionId; - } + const QString sessionId = QStringLiteral("Session%1").arg(daemonApp->newSessionId()); + daemonApp->displayManager()->AddSession(sessionId, seat->name(), user, auth->tty); + daemonApp->displayManager()->setLastSession(sessionId); + env.insert(QStringLiteral("XDG_SESSION_PATH"), daemonApp->displayManager()->sessionPath(sessionId)); + auth->sessionId = sessionId; + env.insert(QStringLiteral("PATH"), mainConfig.Users.DefaultPath.get()); env.insert(QStringLiteral("DESKTOP_SESSION"), session.desktopSession()); if (!session.desktopNames().isEmpty()) env.insert(QStringLiteral("XDG_CURRENT_DESKTOP"), session.desktopNames()); env.insert(QStringLiteral("XDG_SESSION_CLASS"), QStringLiteral("user")); env.insert(QStringLiteral("XDG_SESSION_TYPE"), session.xdgSessionType()); env.insert(QStringLiteral("XDG_VTNR"), QString::number(auth->tty)); - env.insert(QStringLiteral("XDG_SEAT"), seat()->name()); - env.insert(QStringLiteral("XDG_SEAT_PATH"), daemonApp->displayManager()->seatPath(seat()->name())); - -#ifdef HAVE_SYSTEMD + env.insert(QStringLiteral("XDG_SEAT"), seat->name()); + env.insert(QStringLiteral("XDG_SEAT_PATH"), daemonApp->displayManager()->seatPath(seat->name())); env.insert(QStringLiteral("XDG_SESSION_DESKTOP"), session.desktopNames()); -#endif - if (session.xdgSessionType() == QLatin1String("x11")) { - if (m_displayServerType == X11DisplayServerType) - env.insert(QStringLiteral("DISPLAY"), name()); - else - auth->displayServerCmd = XorgUserDisplayServer::command(this); - } else { - if (m_displayServerType == DisplayServerType::SingleCompositerServerType) { - env.insert("DDE_CURRENT_COMPOSITOR", "TreeLand"); + DisplayServerType type; + QByteArray cookie; + if (session.isSingleMode()) { + type = Treeland; + env.insert("DDE_CURRENT_COMPOSITOR", "TreeLand"); + m_treeland->onLoginSucceeded(user); + } else if (session.xdgSessionType() == QLatin1String("x11")) { + type = X11; + + // stop treeland + m_treeland->stop(); + sleep(1); // give some time to treeland to stop before starting Xorg + + m_x11Server = new XorgDisplayServer(this); + connect(m_x11Server, &XorgDisplayServer::stopped, this, &Display::stop); + if (!m_x11Server->start(auth->tty)) { + qCritical() << "Failed to start X11 display server"; + return; } - - auth->displayServerCmd = QStringLiteral(); - } - - auth->user = user; - auth->sessionType = session.type(); - auth->sessionFileName = session.fileName(); - if (m_reuseSessionId.isNull()) { - auth->sessionPath = session.exec(); - } - auth->environment.insert(env); - auth->singleMode = session.isSingleMode(); - auth->start(password.toLocal8Bit()); - } - - void Display::slotAuthenticationFinished(const QString &user, bool success, bool identifyOnly) { - Auth* auth = nullptr; - - if(identifyOnly){ - auto ret = std::find_if(m_auths.crbegin(),m_auths.crend(),[&user](Auth *ptr) { qDebug() << ptr->user; return ptr->user == user;}); - Q_ASSERT(ret != m_auths.crend()); - auth = *ret; + m_x11Server->setupDisplay(); + env.insert(QStringLiteral("DISPLAY"), m_x11Server->display); + cookie = m_x11Server->cookie(); } else { - auto ret = std::find_if(m_auths.cbegin(),m_auths.cend(),[&user](Auth *ptr) { return ptr->user == user;}); - Q_ASSERT(ret != m_auths.cend()); - auth = *ret; + type = Wayland; + // stop treeland + m_treeland->stop(); + sleep(1); // give some time to treeland to stop before starting Wayland session } - Q_ASSERT(auth && auth->identifyOnly == identifyOnly); - - m_currentAuth = auth; - m_greeter->setUserActivated(success); - DaemonApp::instance()->displayManager()->setLastActivatedUser(user); - - if (success) { - if (!m_reuseSessionId.isNull()) { - OrgFreedesktopLogin1ManagerInterface manager(Logind::serviceName(), Logind::managerPath(), QDBusConnection::systemBus()); - manager.UnlockSession(m_reuseSessionId); - manager.ActivateSession(m_reuseSessionId); - m_started = true; - } else { - if (qobject_cast(m_displayServer)) - auth->cookie = qobject_cast(m_displayServer)->cookie(); - } - - // save last user and last session - if (mainConfig.Users.RememberLastUser.get()) - stateConfig.Last.User.set(auth->user); - else - stateConfig.Last.User.setDefault(); - if (mainConfig.Users.RememberLastSession.get()) - stateConfig.Last.Session.set(auth->sessionFileName); - else - stateConfig.Last.Session.setDefault(); - stateConfig.save(); - - if (auth->identifyOnly) { - auto* server = reinterpret_cast(m_displayServer); - server->onLoginSucceeded(user); - // TODO: Use exact ID when there're multiple sessions for a user - int xdgSessionId = 0; - for (auto *auth : m_auths) - if (auth->user == user && auth->xdgSessionId > 0) { - xdgSessionId = auth->xdgSessionId; - break; - } - switchToUser(user, xdgSessionId); - } else if (auth->singleMode) { - auto* server = reinterpret_cast(m_displayServer); - server->onLoginSucceeded(user); - } else { - if (m_socket) { - emit loginSucceeded(m_socket, user); - daemonApp->displayManager()->setLastSession(auth->sessionId); - } - - // Stop the original suit of displayServer since it has finished its job. - disconnect(m_displayServer, &DisplayServer::stopped, this, &Display::stop); - m_displayServer->stop(); - delete m_displayServer; - m_greeter->stop(); - delete m_greeter; - m_currentAuth->stop(); - m_socketServer->stop(); - delete m_socketServer; - - // Start the target displayServer - m_terminalId = m_sessionTerminalId = fetchAvailableVt(); - m_started = false; - - if (auth->sessionType == Session::X11Session) { - m_displayServer = new XorgDisplayServer(this); - m_displayServerType = X11DisplayServerType; - } else { - m_displayServer = new WaylandDisplayServer(this); - m_displayServerType = WaylandDisplayServerType; - } - connect(m_displayServer, &DisplayServer::started, this, &Display::displayServerStarted); - connect(m_displayServer, &DisplayServer::stopped, this, &Display::stop); - - m_socketServer = new SocketServer(this); - - // The greeter here is used to start user session. - m_greeter = new Greeter(this); - m_greeter->setDisplayServerCommand(auth->sessionPath); - m_greeter->setUser(user); - m_greeter->setSkipAuth(); + int xdgSessionId = auth->openSession(env); + if (xdgSessionId <= 0) { + auth->stop(); + delete auth; + return; + } + if (type == Treeland) + switchToUser(auth->user, xdgSessionId); - connect(m_greeter, &Greeter::failed, this, &Display::stop); - connect(m_greeter, &Greeter::displayServerFailed, this, &Display::displayServerFailed); - connect(m_greeter, &Greeter::succeed, this, &Display::stop); + connect(auth, &Auth::userProcessFinished, this, &Display::userProcessFinished); + auth->startUserProcess(session.exec(), type, cookie); - m_displayServer->start(); - } - } - m_socket = nullptr; + m_auths << auth; } - void Display::slotHelperFinished(Auth::ExitStatus status) { + void Display::userProcessFinished([[maybe_unused]] int status) { Auth* auth = qobject_cast(sender()); - // Don't restart greeter and display server unless ddm-helper exited - // with an internal error or the user session finished successfully, - // we want to avoid greeter from restarting when an authentication - // error happens (in this case we want to show the message from the - // greeter - - if (m_currentAuth == auth) { - m_currentAuth = nullptr; - DaemonApp::instance()->displayManager()->setLastActivatedUser(""); - } - - m_auths.removeOne(auth); - auth->deleteLater(); - - if(!auth->identifyOnly) { - daemonApp->displayManager()->RemoveSession(auth->sessionId); - if (m_displayServerType == DisplayServerType::SingleCompositerServerType) { - auto* server = reinterpret_cast(m_displayServer); - // TODO: switch to greeter - server->activateUser("dde", 0); - - // TODO: only current user logout will reset greeter state - m_greeter->setUserActivated(false); - return; - } - } - // Don't restart display when ddm-helper crashed (exit code 9) - if (status != Auth::AUTH_ERROR && status != Auth::ExitStatus(9) && m_displayServerType != DisplayServerType::SingleCompositerServerType) - stop(); - } + daemonApp->displayManager()->RemoveSession(auth->sessionId); - void Display::slotSessionStarted(bool success, int xdgSessionId) { - qDebug() << "Session started" << success; - Auth* auth = qobject_cast(sender()); - if (auth->singleMode) { - switchToUser(auth->user, xdgSessionId); - } + m_auths.removeOne(auth); + delete auth; - if (success && m_displayServerType != SingleCompositerServerType) { - QTimer::singleShot(5000, m_greeter, &Greeter::stop); - } + // TODO: switch to greeter + m_treeland->activateUser("dde", 0); } } diff --git a/src/daemon/Display.h b/src/daemon/Display.h index 593dbca..b052fb2 100644 --- a/src/daemon/Display.h +++ b/src/daemon/Display.h @@ -26,50 +26,35 @@ #include #include -#include "Auth.h" #include "Session.h" class QLocalSocket; namespace DDM { - class Authenticator; - class DisplayServer; + class Auth; + class XorgDisplayServer; + class TreelandDisplayServer; class Seat; class SocketServer; - class Greeter; class Display : public QObject { Q_OBJECT Q_DISABLE_COPY(Display) public: enum DisplayServerType { - X11DisplayServerType, - X11UserDisplayServerType, - WaylandDisplayServerType, - SingleCompositerServerType + X11, + Wayland, + Treeland }; Q_ENUM(DisplayServerType) - static DisplayServerType defaultDisplayServerType(); - explicit Display(Seat *parent, DisplayServerType serverType); + explicit Display(Seat *parent); ~Display(); - DisplayServerType displayServerType() const; - DisplayServer *displayServer() const; - - int terminalId() const; - - const QString &name() const; - - QString sessionType() const; - QString reuseSessionId() const { return m_reuseSessionId; } - - Seat *seat() const; void switchToUser(const QString &user, int xdgSessionId); - QVector loginedSession() const { - return m_auths; - } + Seat *seat{ nullptr }; + int terminalId = 0; public slots: bool start(); @@ -83,46 +68,27 @@ namespace DDM { int id); void unlock(QLocalSocket *socket, const QString &user, const QString &password); - bool attemptAutologin(); - void displayServerStarted(); signals: void stopped(); - void displayServerFailed(); void loginFailed(QLocalSocket *socket, const QString &user); void loginSucceeded(QLocalSocket *socket, const QString &user); private: - QString findGreeterTheme() const; - bool findSessionEntry(const QStringList &dirPaths, const QString &name) const; - void startAuth(const QString &user, const QString &password, const Session &session); void startIdentify(const QString &user, const QString &password); - DisplayServerType m_displayServerType = X11DisplayServerType; - - bool m_relogin { true }; - bool m_started { false }; - - int m_terminalId = 0; - int m_sessionTerminalId = 0; - - QString m_reuseSessionId; - + bool m_started{ false }; QVector m_auths; - Auth* m_currentAuth { nullptr }; - DisplayServer *m_displayServer { nullptr }; - Seat *m_seat { nullptr }; + TreelandDisplayServer *m_treeland{ nullptr }; + XorgDisplayServer *m_x11Server{ nullptr }; SocketServer *m_socketServer { nullptr }; QPointer m_socket; - Greeter *m_greeter { nullptr }; private slots: - void slotAuthenticationFinished(const QString &user, bool success, bool identifyOnly); - void slotSessionStarted(bool success, int xdgSessionId); - void slotHelperFinished(Auth::ExitStatus status); + void userProcessFinished(int status); }; } diff --git a/src/daemon/DisplayServer.cpp b/src/daemon/DisplayServer.cpp deleted file mode 100644 index c71c9c8..0000000 --- a/src/daemon/DisplayServer.cpp +++ /dev/null @@ -1,36 +0,0 @@ -/*************************************************************************** -* Copyright (c) 2014 Pier Luigi Fiorini -* Copyright (c) 2013 Abdurrahman AVCI -* -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the -* Free Software Foundation, Inc., -* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -***************************************************************************/ - -#include "DisplayServer.h" - -#include "Display.h" - -namespace DDM { - DisplayServer::DisplayServer(Display *parent) : QObject(parent), m_displayPtr(parent) { - } - - Display *DisplayServer::displayPtr() const { - return m_displayPtr; - } - - const QString &DisplayServer::display() const { - return m_display; - } -} diff --git a/src/daemon/DisplayServer.h b/src/daemon/DisplayServer.h deleted file mode 100644 index 417161a..0000000 --- a/src/daemon/DisplayServer.h +++ /dev/null @@ -1,63 +0,0 @@ -/*************************************************************************** -* Copyright (c) 2014 Pier Luigi Fiorini -* Copyright (c) 2013 Abdurrahman AVCI -* -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the -* Free Software Foundation, Inc., -* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -***************************************************************************/ - -#ifndef DDM_DISPLAYSERVER_H -#define DDM_DISPLAYSERVER_H - -#include - -class QProcess; - -namespace DDM { - class Display; - - class DisplayServer : public QObject { - Q_OBJECT - Q_DISABLE_COPY(DisplayServer) - public: - explicit DisplayServer(Display *parent); - - Display *displayPtr() const; - - const QString &display() const; - - virtual QString sessionType() const = 0; - - public slots: - virtual bool start() = 0; - virtual void stop() = 0; - virtual void finished() = 0; - virtual void setupDisplay() = 0; - - signals: - void started(); - void stopped(); - - protected: - bool m_started { false }; - - QString m_display; - - private: - Display *m_displayPtr { nullptr }; - }; -} - -#endif // DDM_DISPLAYSERVER_H diff --git a/src/daemon/Greeter.cpp b/src/daemon/Greeter.cpp deleted file mode 100644 index 3d948e5..0000000 --- a/src/daemon/Greeter.cpp +++ /dev/null @@ -1,388 +0,0 @@ -/*************************************************************************** -* Copyright (c) 2013 Abdurrahman AVCI -* -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the -* Free Software Foundation, Inc., -* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -***************************************************************************/ - -#include "Greeter.h" - -#include "Configuration.h" -#include "Constants.h" -#include "DaemonApp.h" -#include "DisplayManager.h" -#include "Seat.h" -#include "ThemeConfig.h" -#include "ThemeMetadata.h" -#include "Display.h" -#include "XorgDisplayServer.h" -#include "XorgUserDisplayServer.h" -#include "WaylandDisplayServer.h" -#include "PowerManager.h" - -#include -#include -#include -#include - -namespace DDM { - Greeter::Greeter(Display *parent) - : QObject(parent) - , m_display(parent) - , m_tryTimer(new QTimer(this)) - { - m_metadata = new ThemeMetadata(QString()); - m_themeConfig = new ThemeConfig(QString()); - - connect(m_tryTimer, &QTimer::timeout, this, &Greeter::greeterStarted); - - m_tryTimer->setSingleShot(true); - m_tryTimer->setInterval(500); - } - - Greeter::~Greeter() { - stop(); - - delete m_metadata; - delete m_themeConfig; - } - - void Greeter::setSocket(const QString &socket) { - m_socket = socket; - } - - void Greeter::setTheme(const QString &theme) { - m_themePath = theme; - - if (theme.isEmpty()) { - m_metadata->setTo(QString()); - m_themeConfig->setTo(QString()); - } else { - const QString path = QStringLiteral("%1/metadata.desktop").arg(m_themePath); - m_metadata->setTo(path); - - QString configFile = QStringLiteral("%1/%2").arg(m_themePath).arg(m_metadata->configFile()); - m_themeConfig->setTo(configFile); - } - } - - void Greeter::setSingleMode(bool on) - { - m_singleMode = on; - } - - void Greeter::setUser(const QString &user) { - m_user = user; - } - - void Greeter::setSkipAuth(bool on) { - m_skipAuth = on; - } - - void Greeter::setUserActivated(bool active) { - m_userActivated = active; - } - - QString Greeter::displayServerCommand() const - { - return m_displayServerCmd; - } - - void Greeter::setDisplayServerCommand(const QString &cmd) - { - m_displayServerCmd = cmd; - } - - bool Greeter::start() { - // check flag - if (m_started) - return false; - - // themes - QString xcursorTheme = mainConfig.Theme.CursorTheme.get(); - if (m_themeConfig->contains(QLatin1String("cursorTheme"))) - xcursorTheme = m_themeConfig->value(QLatin1String("cursorTheme")).toString(); - QString xcursorSize = mainConfig.Theme.CursorSize.get(); - if (m_themeConfig->contains(QLatin1String("cursorSize"))) - xcursorSize = m_themeConfig->value(QLatin1String("cursorSize")).toString(); - QString platformTheme; - if (m_themeConfig->contains(QLatin1String("platformTheme"))) - platformTheme = m_themeConfig->value(QLatin1String("platformTheme")).toString(); - QString style; - if (m_themeConfig->contains(QLatin1String("style"))) - style = m_themeConfig->value(QLatin1String("style")).toString(); - - // greeter command - QStringList args; - args << QLatin1String("--socket") << m_socket; - - if (!m_themePath.isEmpty()) - args << QLatin1String("--theme") << m_themePath; - if (!platformTheme.isEmpty()) - args << QLatin1String("-platformtheme") << platformTheme; - if (!style.isEmpty()) - args << QLatin1String("-style") << style; - - Q_ASSERT(m_display); - auto *displayServer = m_display->displayServer(); - - if (daemonApp->testing()) { - // create process - m_process = new QProcess(this); - - // delete process on finish - connect(m_process, QOverload::of(&QProcess::finished), this, &Greeter::finished); - - connect(m_process, &QProcess::readyReadStandardOutput, this, &Greeter::onReadyReadStandardOutput); - connect(m_process, &QProcess::readyReadStandardError, this, &Greeter::onReadyReadStandardError); - - // log message - qDebug() << "Greeter starting..."; - - args << QStringLiteral("--test-mode"); - - if (m_display->displayServerType() == Display::X11DisplayServerType) { - // set process environment - QProcessEnvironment env = QProcessEnvironment::systemEnvironment(); - env.insert(QStringLiteral("DISPLAY"), m_display->name()); - env.insert(QStringLiteral("XAUTHORITY"), qobject_cast(displayServer)->authPath()); - env.insert(QStringLiteral("XCURSOR_THEME"), xcursorTheme); - if (!xcursorSize.isEmpty()) - env.insert(QStringLiteral("XCURSOR_SIZE"), xcursorSize); - m_process->setProcessEnvironment(env); - } - // Greeter command - if (!m_singleMode) { - m_process->start(QStringLiteral("%1/ddm-greeter").arg(QStringLiteral(BIN_INSTALL_DIR)), args); - } - - //if we fail to start bail immediately, and don't block in waitForStarted - if (m_process->state() == QProcess::NotRunning) { - qCritical() << "Greeter failed to launch."; - return false; - } - // wait for greeter to start - if (!m_process->waitForStarted()) { - // log message - qCritical() << "Failed to start greeter."; - - // return fail - return false; - } - - // log message - qDebug() << "Greeter started."; - - // set flag - m_started = true; - } else { - // authentication - m_auth = new Auth(this); - connect(m_auth, &Auth::sessionStarted, this, &Greeter::onSessionStarted); - connect(m_auth, &Auth::finished, this, &Greeter::onHelperFinished); - - // command - QStringList cmd; - if (!m_singleMode) { - cmd << QStringLiteral("%1/ddm-greeter").arg(QStringLiteral(BIN_INSTALL_DIR)); - } - - cmd << args; - - // greeter environment - QProcessEnvironment env; - QProcessEnvironment sysenv = QProcessEnvironment::systemEnvironment(); - - insertEnvironmentList({QStringLiteral("LANG"), QStringLiteral("LANGUAGE"), - QStringLiteral("LC_CTYPE"), QStringLiteral("LC_NUMERIC"), QStringLiteral("LC_TIME"), QStringLiteral("LC_COLLATE"), - QStringLiteral("LC_MONETARY"), QStringLiteral("LC_MESSAGES"), QStringLiteral("LC_PAPER"), QStringLiteral("LC_NAME"), - QStringLiteral("LC_ADDRESS"), QStringLiteral("LC_TELEPHONE"), QStringLiteral("LC_MEASUREMENT"), QStringLiteral("LC_IDENTIFICATION"), - QStringLiteral("LD_LIBRARY_PATH"), - QStringLiteral("QML2_IMPORT_PATH"), - QStringLiteral("QT_PLUGIN_PATH"), - QStringLiteral("XDG_DATA_DIRS") - }, sysenv, env); - - env.insert(QStringLiteral("PATH"), mainConfig.Users.DefaultPath.get()); - env.insert(QStringLiteral("XCURSOR_THEME"), xcursorTheme); - if (!xcursorSize.isEmpty()) - env.insert(QStringLiteral("XCURSOR_SIZE"), xcursorSize); - env.insert(QStringLiteral("XDG_SEAT"), m_display->seat()->name()); - env.insert(QStringLiteral("XDG_SEAT_PATH"), daemonApp->displayManager()->seatPath(m_display->seat()->name())); - env.insert(QStringLiteral("XDG_SESSION_PATH"), daemonApp->displayManager()->sessionPath(QStringLiteral("Session%1").arg(daemonApp->newSessionId()))); - if (m_display->seat()->name() == QLatin1String("seat0")) - env.insert(QStringLiteral("XDG_VTNR"), QString::number(m_display->terminalId())); - env.insert(QStringLiteral("XDG_SESSION_CLASS"), QStringLiteral("greeter")); - env.insert(QStringLiteral("XDG_SESSION_TYPE"), m_display->sessionType()); - if (m_display->displayServerType() == Display::X11DisplayServerType) { - env.insert(QStringLiteral("DISPLAY"), m_display->name()); - env.insert(QStringLiteral("QT_QPA_PLATFORM"), QStringLiteral("xcb")); - if (m_display->sessionType() == "x11") - m_auth->cookie = qobject_cast(displayServer)->cookie(); - } else if (m_display->displayServerType() == Display::WaylandDisplayServerType) { - env.insert(QStringLiteral("QT_QPA_PLATFORM"), QStringLiteral("wayland")); - env.insert(QStringLiteral("QT_WAYLAND_SHELL_INTEGRATION"), QStringLiteral("fullscreen-shell-v1")); - } else if (m_display->displayServerType() == Display::SingleCompositerServerType) { - env.insert(QStringLiteral("QT_QPA_PLATFORM"), QStringLiteral("wayland")); - env.insert(QStringLiteral("QT_WAYLAND_SHELL_INTEGRATION"), QStringLiteral("fullscreen-shell-v1")); - } - m_auth->environment.insert(env); - - // log message - qDebug() << "Greeter starting..."; - - // start greeter - m_auth->user = m_user; - QString displayServerCmd = m_displayServerCmd; - if (m_singleMode) { - displayServerCmd += " --lockscreen"; - } - m_auth->displayServerCmd = displayServerCmd; - m_auth->greeter = true; - m_auth->sessionPath = cmd.join(QLatin1Char(' ')); - m_auth->singleMode = m_singleMode; - - // TODO: single compositer mode not need greeter - if (m_singleMode) { - return true; - } - - if (m_skipAuth) { - m_auth->skipAuth = true; - } - - m_auth->start(""); - - m_tryTimer->start(); - } - - // return success - return true; - } - - void Greeter::insertEnvironmentList(QStringList names, QProcessEnvironment sourceEnv, QProcessEnvironment &targetEnv) { - for (QStringList::const_iterator it = names.constBegin(); it != names.constEnd(); ++it) - if (sourceEnv.contains(*it)) - targetEnv.insert(*it, sourceEnv.value(*it)); - } - - void Greeter::stop() { - // check flag - if (!m_started) - return; - - // log message - qDebug() << "Greeter stopping..."; - - if (daemonApp->testing()) { - // terminate process - m_process->terminate(); - - // wait for finished - if (!m_process->waitForFinished(5000)) - m_process->kill(); - } else { - m_auth->stop(); - } - } - - void Greeter::finished() { - // check flag - if (!m_started) - return; - - // reset flag - m_started = false; - - // log message - qDebug() << "Greeter stopped."; - - // clean up - if (m_process) { - m_process->deleteLater(); - m_process = nullptr; - } - } - - void Greeter::onSessionStarted(bool success,[[maybe_unused]] int xdgSessionId) { - // set flag - m_started = success; - - // log message - if (success) - qDebug() << "Greeter session started successfully"; - else - qDebug() << "Greeter session failed to start"; - } - - void Greeter::onHelperFinished(Auth::ExitStatus status) { - if (m_singleMode && m_currentRetry <= m_maxRetry) { - m_currentRetry += 1; - qDebug() << "Restart treeland"; - QString displayServerCmd = m_displayServerCmd; - if (!m_userActivated) { - displayServerCmd += " --lockscreen"; - } - m_auth->displayServerCmd = displayServerCmd; - m_auth->start(""); - - if (m_tryTimer->isActive()) { - m_tryTimer->stop(); - } - - m_tryTimer->start(); - return; - } - - // reset flag - m_started = false; - - // log message - qDebug() << "Greeter stopped." << status; - - // clean up - m_auth->deleteLater(); - m_auth = nullptr; - - if (status == Auth::DISPLAYSERVER_ERROR) { - Q_EMIT displayServerFailed(); - } else if (status == Auth::TTY_ERROR) { - Q_EMIT ttyFailed(); - } else if (status == Auth::SESSION_ERROR) { - Q_EMIT failed(); - } else if (status == Auth::SUCCESS) { - Q_EMIT succeed(); - } - } - - bool Greeter::isRunning() const { - return (m_process && m_process->state() == QProcess::Running) - || (m_auth && m_auth->active); - } - - void Greeter::onReadyReadStandardError() - { - if (m_process) { - qDebug() << "Greeter errors:" << m_process->readAllStandardError().constData(); - } - } - - void Greeter::onReadyReadStandardOutput() - { - if (m_process) { - qDebug() << "Greeter output:" << m_process->readAllStandardOutput().constData(); - } - } -} diff --git a/src/daemon/Greeter.h b/src/daemon/Greeter.h deleted file mode 100644 index c3ee9f6..0000000 --- a/src/daemon/Greeter.h +++ /dev/null @@ -1,95 +0,0 @@ -/*************************************************************************** -* Copyright (c) 2013 Abdurrahman AVCI -* -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the -* Free Software Foundation, Inc., -* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -***************************************************************************/ - -#ifndef DDM_GREETER_H -#define DDM_GREETER_H - -#include - -#include "Auth.h" - -class QProcess; -class QTimer; - -namespace DDM { - class Display; - class ThemeMetadata; - class ThemeConfig; - - class Greeter : public QObject { - Q_OBJECT - Q_DISABLE_COPY(Greeter) - public: - explicit Greeter(Display *parent = 0); - ~Greeter(); - - void setSocket(const QString &socket); - void setTheme(const QString &theme); - void setSingleMode(bool on = true); - void setUser(const QString &user); - void setSkipAuth(bool on = true); - void setUserActivated(bool active); - - QString displayServerCommand() const; - void setDisplayServerCommand(const QString &cmd); - bool isRunning() const; - - public slots: - bool start(); - void stop(); - void finished(); - - private slots: - void onSessionStarted(bool success, int xdgSessionId); - void onHelperFinished(Auth::ExitStatus status); - void onReadyReadStandardOutput(); - void onReadyReadStandardError(); - - signals: - void ttyFailed(); - void failed(); - void displayServerFailed(); - void succeed(); - void greeterStarted(); - - private: - bool m_started { false }; - bool m_singleMode { false }; - bool m_userActivated { false }; - int m_currentRetry { 0 }; - int m_maxRetry{ 3 }; - QString m_user = QStringLiteral("dde"); - bool m_skipAuth { false }; - - Display * const m_display { nullptr }; - QString m_socket; - QString m_themePath; - QString m_displayServerCmd; - ThemeMetadata *m_metadata { nullptr }; - ThemeConfig *m_themeConfig { nullptr }; - - Auth *m_auth { nullptr }; - QProcess *m_process { nullptr }; - QTimer *m_tryTimer { nullptr }; - - static void insertEnvironmentList(QStringList names, QProcessEnvironment sourceEnv, QProcessEnvironment &targetEnv); - }; -} - -#endif // DDM_GREETER_H diff --git a/src/daemon/Pam.cpp b/src/daemon/Pam.cpp index 4c8bf0b..200ac19 100644 --- a/src/daemon/Pam.cpp +++ b/src/daemon/Pam.cpp @@ -131,7 +131,7 @@ namespace DDM { qWarning() << "[PAM] openSession:" << pam_strerror(d->handle, d->ret); \ return std::nullopt; \ } - std::optional Pam::openSession(QProcessEnvironment sessionEnv) { + std::optional Pam::openSession(const QProcessEnvironment &sessionEnv) { qDebug() << "[PAM] Opening session for user" << user; d->ret = pam_setcred(d->handle, PAM_ESTABLISH_CRED); diff --git a/src/daemon/Pam.h b/src/daemon/Pam.h index 4b35792..a0aecbf 100644 --- a/src/daemon/Pam.h +++ b/src/daemon/Pam.h @@ -41,7 +41,7 @@ namespace DDM { * Open PAM session with given environment variables * @return Environment variables set by PAM modules on success, std::nullopt on failure */ - std::optional openSession(QProcessEnvironment sessionEnv); + std::optional openSession(const QProcessEnvironment &sessionEnv); /** * Close PAM session * @return true on success, false on failure diff --git a/src/daemon/Seat.cpp b/src/daemon/Seat.cpp index 73afb03..ecd86df 100644 --- a/src/daemon/Seat.cpp +++ b/src/daemon/Seat.cpp @@ -37,18 +37,18 @@ namespace DDM { Seat::Seat(const QString &name, QObject *parent) : QObject(parent), m_name(name) { - createDisplay(Display::defaultDisplayServerType()); + createDisplay(); } const QString &Seat::name() const { return m_name; } - void Seat::createDisplay(Display::DisplayServerType serverType) { + void Seat::createDisplay() { //reload config if needed mainConfig.load(); - if (Display::defaultDisplayServerType() == Display::SingleCompositerServerType && !m_displays.isEmpty()) { + if (!m_displays.isEmpty()) { auto display = m_displays.first(); display->switchToUser("dde", 0); return; @@ -56,24 +56,10 @@ namespace DDM { // create a new display qDebug() << "Adding new display..."; - Display *display = new Display(this, serverType); + Display *display = new Display(this); // restart display on stop connect(display, &Display::stopped, this, &Seat::displayStopped); - connect(display, &Display::displayServerFailed, this, [this, display] { - removeDisplay(display); - - // If we failed to create a display with wayland or rootful x11, try with - // x11-user. There's a chance it might work. It's a handy fallback - // since the alternative is a black screen - if (display->displayServerType() != Display::X11UserDisplayServerType) { - qWarning() << "Failed to launch the display server, falling back to DisplayServer=x11-user"; - createDisplay(Display::X11UserDisplayServerType); - } else if (m_displays.isEmpty()) { - qWarning() << "Failed to launch a DisplayServer=x11-user session, aborting"; - QCoreApplication::instance()->exit(12); - } - }); // add display to the list m_displays << display; @@ -89,10 +75,10 @@ namespace DDM { // It's possible that the system isn't ready yet (driver not loaded, // device not enumerated, ...). It's not possible to tell when that changes, // so try a few times with a delay in between. - qWarning() << "Attempt" << tryNr << "starting the Display server on vt" << display->terminalId() << "failed"; + qWarning() << "Attempt" << tryNr << "starting the Display server on vt" << display->terminalId << "failed"; if(tryNr >= 3) { - qCritical() << "Could not start Display server on vt" << display->terminalId(); + qCritical() << "Could not start Display server on vt" << display->terminalId; return; } @@ -119,26 +105,20 @@ namespace DDM { Display *display = qobject_cast(sender()); OrgFreedesktopLogin1ManagerInterface manager(Logind::serviceName(), Logind::managerPath(), QDBusConnection::systemBus()); std::optional nextVt; - auto reusing = display->reuseSessionId(); - if (manager.isValid() && !reusing.isEmpty()) { - auto sessionPath = manager.GetSession(reusing); - OrgFreedesktopLogin1SessionInterface sessionIface(Logind::serviceName(), sessionPath.value().path(), QDBusConnection::systemBus()); - nextVt = QStringView(sessionIface.tTY()).mid(3).toInt(); // we need to convert ttyN to N - } // remove display removeDisplay(display); // restart otherwise if (m_displays.isEmpty()) { - createDisplay(Display::defaultDisplayServerType()); + createDisplay(); } // If there is still a session running on some display, // switch to last display in display vector. // Set vt_auto to true, so let the kernel handle the // vt switch automatically (VT_AUTO). else if (!nextVt) { - int disp = m_displays.last()->terminalId(); + int disp = m_displays.last()->terminalId; if (disp != -1) nextVt = disp; } diff --git a/src/daemon/Seat.h b/src/daemon/Seat.h index 741ddc8..a631b8c 100644 --- a/src/daemon/Seat.h +++ b/src/daemon/Seat.h @@ -34,7 +34,7 @@ namespace DDM { explicit Seat(const QString &name, QObject *parent = 0); const QString &name() const; - void createDisplay(Display::DisplayServerType serverType); + void createDisplay(); public slots: void removeDisplay(DDM::Display* display); diff --git a/src/daemon/SeatManager.cpp b/src/daemon/SeatManager.cpp index 9453237..62dd054 100644 --- a/src/daemon/SeatManager.cpp +++ b/src/daemon/SeatManager.cpp @@ -149,7 +149,7 @@ namespace DDM { return; // switch to greeter - m_seats.value(name)->createDisplay(Display::defaultDisplayServerType()); + m_seats.value(name)->createDisplay(); } void DDM::SeatManager::logindSeatAdded(const QString& name, const QDBusObjectPath& objectPath) diff --git a/src/daemon/SingleWaylandDisplayServer.h b/src/daemon/SingleWaylandDisplayServer.h deleted file mode 100644 index 2b11077..0000000 --- a/src/daemon/SingleWaylandDisplayServer.h +++ /dev/null @@ -1,45 +0,0 @@ -// Copyright (C) 2023 Dingyuan Zhang . -// SPDX-License-Identifier: GPL-2.0-or-later - -#include "DisplayServer.h" - -#include -#include - -class QLocalSocket; -class QLocalServer; - -namespace DDM { - class SocketServer; -} - -class SingleWaylandDisplayServer : public DDM::DisplayServer -{ - Q_OBJECT - Q_DISABLE_COPY(SingleWaylandDisplayServer) -public: - explicit SingleWaylandDisplayServer(DDM::SocketServer *socketServer, DDM::Display *parent); - ~SingleWaylandDisplayServer(); - - QString sessionType() const; - - void setDisplayName(const QString &displayName); - -Q_SIGNALS: - void createWaylandSocketFinished(); - -public Q_SLOTS: - bool start(); - void stop(); - void finished(); - void setupDisplay(); - void activateUser(const QString &user, int xdgSessionId); - QString getUserWaylandSocket(const QString &user) const; - void onLoginFailed(const QString &user); - void onLoginSucceeded(const QString &user); - -private: - DDM::SocketServer *m_socketServer; - QList m_greeterSockets; - QMap m_waylandSockets; -}; diff --git a/src/daemon/SingleWaylandDisplayServer.cpp b/src/daemon/TreelandDisplayServer.cpp similarity index 64% rename from src/daemon/SingleWaylandDisplayServer.cpp rename to src/daemon/TreelandDisplayServer.cpp index dfcc984..fabe2d2 100644 --- a/src/daemon/SingleWaylandDisplayServer.cpp +++ b/src/daemon/TreelandDisplayServer.cpp @@ -1,14 +1,10 @@ // Copyright (C) 2023 Dingyuan Zhang . // SPDX-License-Identifier: GPL-2.0-or-later -#include "SingleWaylandDisplayServer.h" -#include "DaemonApp.h" -#include "DisplayManager.h" +#include "TreelandDisplayServer.h" #include "Messages.h" #include "SocketServer.h" -#include "Constants.h" #include "SocketWriter.h" -#include "Utils.h" #include "Display.h" #include @@ -26,10 +22,9 @@ using namespace DDM; -SingleWaylandDisplayServer::SingleWaylandDisplayServer(SocketServer *socketServer, Display *parent) - : DDM::DisplayServer(parent) - , m_socketServer(socketServer) -{ +TreelandDisplayServer::TreelandDisplayServer(SocketServer *socketServer, Display *parent) + : QObject(parent) + , m_socketServer(socketServer) { connect(m_socketServer, &SocketServer::connected, this, [this, parent](QLocalSocket *socket) { m_greeterSockets << socket; }); @@ -38,22 +33,11 @@ SingleWaylandDisplayServer::SingleWaylandDisplayServer(SocketServer *socketServe }); } -SingleWaylandDisplayServer::~SingleWaylandDisplayServer() { +TreelandDisplayServer::~TreelandDisplayServer() { stop(); } -QString SingleWaylandDisplayServer::sessionType() const -{ - return QStringLiteral("wayland"); -} - -void SingleWaylandDisplayServer::setDisplayName(const QString &displayName) -{ - m_display = displayName; -} - -bool SingleWaylandDisplayServer::start() -{ +bool TreelandDisplayServer::start() { // Check flag if (m_started) return false; @@ -66,13 +50,11 @@ bool SingleWaylandDisplayServer::start() // Set flag m_started = true; - emit started(); return true; } -void SingleWaylandDisplayServer::stop() -{ +void TreelandDisplayServer::stop() { // Check flag if (!m_started) return; @@ -83,18 +65,9 @@ void SingleWaylandDisplayServer::stop() // Reset flag m_started = false; - emit stopped(); -} - -void SingleWaylandDisplayServer::finished() -{ -} - -void SingleWaylandDisplayServer::setupDisplay() -{ } -void SingleWaylandDisplayServer::activateUser(const QString &user, int xdgSessionId) { +void TreelandDisplayServer::activateUser(const QString &user, int xdgSessionId) { for (auto greeter : m_greeterSockets) { if (user == "dde") { SocketWriter(greeter) << quint32(DaemonMessages::SwitchToGreeter); @@ -104,17 +77,13 @@ void SingleWaylandDisplayServer::activateUser(const QString &user, int xdgSessio } } -QString SingleWaylandDisplayServer::getUserWaylandSocket(const QString &user) const { - return m_waylandSockets.value(user); -} - -void SingleWaylandDisplayServer::onLoginFailed(const QString &user) { +void TreelandDisplayServer::onLoginFailed(const QString &user) { for (auto greeter : m_greeterSockets) { SocketWriter(greeter) << quint32(DaemonMessages::LoginFailed) << user; } } -void SingleWaylandDisplayServer::onLoginSucceeded(const QString &user) { +void TreelandDisplayServer::onLoginSucceeded(const QString &user) { for (auto greeter : m_greeterSockets) { SocketWriter(greeter) << quint32(DaemonMessages::LoginSucceeded) << user; } diff --git a/src/daemon/TreelandDisplayServer.h b/src/daemon/TreelandDisplayServer.h new file mode 100644 index 0000000..4ae5979 --- /dev/null +++ b/src/daemon/TreelandDisplayServer.h @@ -0,0 +1,33 @@ +// Copyright (C) 2023 Dingyuan Zhang . +// SPDX-License-Identifier: GPL-2.0-or-later + +#include +#include + +class QLocalSocket; +class QLocalServer; + +namespace DDM { + class Display; + class SocketServer; + + class TreelandDisplayServer : public QObject { + Q_OBJECT + Q_DISABLE_COPY(TreelandDisplayServer) + public: + explicit TreelandDisplayServer(DDM::SocketServer *socketServer, Display *parent); + ~TreelandDisplayServer(); + + public Q_SLOTS: + bool start(); + void stop(); + void activateUser(const QString &user, int xdgSessionId); + void onLoginFailed(const QString &user); + void onLoginSucceeded(const QString &user); + + private: + SocketServer *m_socketServer; + QList m_greeterSockets; + bool m_started{ false }; + }; +} diff --git a/src/daemon/UserSession.cpp b/src/daemon/UserSession.cpp index 018150e..1d07e6a 100644 --- a/src/daemon/UserSession.cpp +++ b/src/daemon/UserSession.cpp @@ -23,7 +23,8 @@ #include #include "Configuration.h" -#include "Constants.h" +#include "DaemonApp.h" +#include "TreelandConnector.h" #include "UserSession.h" #include "Auth.h" #include "VirtualTerminal.h" @@ -45,77 +46,68 @@ namespace DDM { UserSession::UserSession(Auth *parent) - : QProcess(parent) - , m_auth(parent) - { - connect(this, - QOverload::of(&QProcess::finished), - this, - [this](int code) { - Q_EMIT m_auth->finished(static_cast(code)); - }); + : QProcess(parent) { setChildProcessModifier(std::bind(&UserSession::childModifier, this)); } - void UserSession::start() { + void UserSession::start(const QString &command, Display::DisplayServerType type, const QByteArray &cookie) { QProcessEnvironment env = processEnvironment(); - if (m_auth->singleMode) { + switch (type) { + case Display::Treeland: { setProgram(mainConfig.Single.SessionCommand.get()); - setArguments(QStringList{ m_auth->sessionPath }); - qInfo() << "Starting Wayland user session:" << program() << m_auth->sessionPath; + setArguments(QStringList{ command }); + qInfo() << "Starting Wayland user session:" << program() << command; QProcess::start(); closeWriteChannel(); closeReadChannel(QProcess::StandardOutput); + return; } - else { - // If the Xorg display server was already started, write the passed - // auth cookie to /tmp/xauth_XXXXXX. This is done in the parent process - // so that it can clean up the file on session end. - if (env.value(QStringLiteral("XDG_SESSION_TYPE")) == QLatin1String("x11")) { - QByteArray cookie = m_auth->cookie; - if (cookie.isEmpty()) { - qCritical() << "Can't start X11 session with empty auth cookie"; - return; - } - // Create the Xauthority file - // Place it into /tmp, which is guaranteed to be read/writeable by - // everyone while having the sticky bit set to avoid messing with - // other's files. - m_xauthFile.setFileTemplate(QStringLiteral("/tmp/xauth_XXXXXX")); - - if (!m_xauthFile.open()) { - qCritical() << "Could not create the Xauthority file"; - return; - } + case Display::X11: { + if (cookie.isEmpty()) { + qCritical() << "Can't start X11 session with empty auth cookie"; + return; + } + // Create the Xauthority file + // Place it into /tmp, which is guaranteed to be read/writeable by + // everyone while having the sticky bit set to avoid messing with + // other's files. + m_xauthFile.setFileTemplate(QStringLiteral("/tmp/xauth_XXXXXX")); + + if (!m_xauthFile.open()) { + qCritical() << "Could not create the Xauthority file"; + return; + } - QString display = processEnvironment().value(QStringLiteral("DISPLAY")); + QString display = env.value(QStringLiteral("DISPLAY")); - if (!XAuth::writeCookieToFile(display, m_xauthFile.fileName(), cookie)) { - qCritical() << "Failed to write the Xauthority file"; - m_xauthFile.close(); - return; - } - - env.insert(QStringLiteral("XAUTHORITY"), m_xauthFile.fileName()); - setProcessEnvironment(env); - - QString command = QStringLiteral("%1 \"%2\"").arg(mainConfig.X11.SessionCommand.get()).arg(m_auth->sessionPath); - qInfo() << "Starting X11 session:" << m_auth->displayServerCmd << command; - auto args = QProcess::splitCommand(m_auth->displayServerCmd); - setProgram(args.takeFirst()); - setArguments(args); - QProcess::start(); - } else if (env.value(QStringLiteral("XDG_SESSION_TYPE")) == QLatin1String("wayland")) { - setProgram(mainConfig.Wayland.SessionCommand.get()); - setArguments(QStringList{ m_auth->sessionPath }); - qInfo() << "Starting Wayland user session:" << program() << m_auth->sessionPath; - QProcess::start(); - closeWriteChannel(); - closeReadChannel(QProcess::StandardOutput); - } else { - qCritical() << "Unable to run user session: unknown session type"; + if (!XAuth::writeCookieToFile(display, m_xauthFile.fileName(), cookie)) { + qCritical() << "Failed to write the Xauthority file"; + m_xauthFile.close(); + return; } + + env.insert(QStringLiteral("XAUTHORITY"), m_xauthFile.fileName()); + setProcessEnvironment(env); + + qInfo() << "Starting X11 user session:" << command; + setProgram(mainConfig.X11.SessionCommand.get()); + setArguments(QStringList{ command }); + QProcess::start(); + return; + } + case Display::Wayland: { + setProgram(mainConfig.Wayland.SessionCommand.get()); + setArguments(QStringList{ command }); + qInfo() << "Starting Wayland user session:" << program() << command; + QProcess::start(); + closeWriteChannel(); + closeReadChannel(QProcess::StandardOutput); + return; + } + default: { + qCritical() << "Unable to run user session: unknown session type"; + } } } @@ -123,30 +115,25 @@ namespace DDM { { if (state() != QProcess::NotRunning) { terminate(); - const bool isGreeter = processEnvironment().value(QStringLiteral("XDG_SESSION_CLASS")) == QLatin1String("greeter"); - - // Wait longer for a session than a greeter - if (!waitForFinished(isGreeter ? 5000 : 60000)) { + if (!waitForFinished(60000)) { kill(); if (!waitForFinished(5000)) { qWarning() << "Could not fully finish the process" << program(); } } } else { - Q_EMIT finished(Auth::OTHER_ERROR); + Q_EMIT finished(1); } } void UserSession::childModifier() { // Session type QString sessionType = processEnvironment().value(QStringLiteral("XDG_SESSION_TYPE")); - QString sessionClass = processEnvironment().value(QStringLiteral("XDG_SESSION_CLASS")); - const bool hasDisplayServer = !m_auth->displayServerCmd.isEmpty(); - const bool waylandUserSession = sessionType == QLatin1String("wayland") && sessionClass == QLatin1String("user"); + const bool waylandUserSession = sessionType == QLatin1String("wayland"); // When the display server is part of the session, we leak the VT into // the session as stdin so that it stays open without races - if (hasDisplayServer || waylandUserSession) { + if (waylandUserSession) { // open VT and get the fd int vtNumber = processEnvironment().value(QStringLiteral("XDG_VTNR")).toInt(); QString ttyString = VirtualTerminal::path(vtNumber); @@ -169,8 +156,7 @@ namespace DDM { if (setsid() < 0) { qCritical("Failed to set pid %lld as leader of the new session and process group: %s", QCoreApplication::applicationPid(), strerror(errno)); - _exit(Auth::OTHER_ERROR); - + _exit(1); } // take control of the tty @@ -178,11 +164,11 @@ namespace DDM { if (ioctl(STDIN_FILENO, TIOCSCTTY, 1) < 0) { const auto error = strerror(errno); qCritical().nospace() << "Failed to take control of " << ttyString << " (" << QFileInfo(ttyString).owner() << "): " << error; - _exit(Auth::TTY_ERROR); + _exit(1); } if (ioctl(STDIN_FILENO, KDSKBMODE, K_OFF) == -1) { qCritical().nospace() << "Failed to set keyboard mode to K_OFF"; - _exit(Auth::TTY_ERROR); + _exit(1); } } @@ -195,11 +181,11 @@ namespace DDM { int fd = ::open(qPrintable(ns), O_RDONLY); if (fd < 0) { qCritical("open(%s) failed: %s", qPrintable(ns), strerror(errno)); - exit(Auth::OTHER_ERROR); + exit(1); } if (setns(fd, 0) != 0) { qCritical("setns(open(%s), 0) failed: %s", qPrintable(ns), strerror(errno)); - exit(Auth::OTHER_ERROR); + exit(1); } ::close(fd); } @@ -214,7 +200,7 @@ namespace DDM { QScopedPointer buffer(static_cast(malloc(bufsize))); if (buffer.isNull()) { qCritical() << "Could not allocate buffer of size" << bufsize; - exit(Auth::OTHER_ERROR); + exit(1); } int err = getpwnam_r(username.constData(), &pw, buffer.data(), bufsize, &rpw); if (rpw == NULL) { @@ -222,18 +208,18 @@ namespace DDM { qCritical() << "getpwnam_r(" << username << ") username not found!"; else qCritical() << "getpwnam_r(" << username << ") failed with error: " << strerror(err); - exit(Auth::OTHER_ERROR); + exit(1); } const int xauthHandle = m_xauthFile.handle(); if (xauthHandle != -1 && fchown(xauthHandle, pw.pw_uid, pw.pw_gid) != 0) { qCritical() << "fchown failed for" << m_xauthFile.fileName(); - exit(Auth::OTHER_ERROR); + exit(1); } if (setgid(pw.pw_gid) != 0) { qCritical() << "setgid(" << pw.pw_gid << ") failed for user: " << username; - exit(Auth::OTHER_ERROR); + exit(1); } // fetch ambient groups from PAM's environment; @@ -245,7 +231,7 @@ namespace DDM { if ((n_pam_groups = getgroups(n_pam_groups, pam_groups)) == -1) { qCritical() << "getgroups() failed to fetch supplemental" << "PAM groups for user:" << username; - exit(Auth::OTHER_ERROR); + exit(1); } } else { n_pam_groups = 0; @@ -262,7 +248,7 @@ namespace DDM { &n_user_groups)) == -1 ) { qCritical() << "getgrouplist(" << pw.pw_name << ", " << pw.pw_gid << ") failed"; - exit(Auth::OTHER_ERROR); + exit(1); } } @@ -278,7 +264,7 @@ namespace DDM { // setgroups(2) handles duplicate groups if (setgroups(n_groups, groups) != 0) { qCritical() << "setgroups() failed for user: " << username; - exit (Auth::OTHER_ERROR); + exit (1); } delete[] groups; } @@ -287,49 +273,47 @@ namespace DDM { if (setuid(pw.pw_uid) != 0) { qCritical() << "setuid(" << pw.pw_uid << ") failed for user: " << username; - exit(Auth::OTHER_ERROR); + exit(1); } if (chdir(pw.pw_dir) != 0) { qCritical() << "chdir(" << pw.pw_dir << ") failed for user: " << username; qCritical() << "verify directory exist and has sufficient permissions"; - exit(Auth::OTHER_ERROR); + exit(1); } - if (sessionClass != QLatin1String("greeter")) { - //we cannot use setStandardError file as this code is run in the child process - //we want to redirect after we setuid so that the log file is owned by the user + //we cannot use setStandardError file as this code is run in the child process + //we want to redirect after we setuid so that the log file is owned by the user - // determine stderr log file based on session type - QString sessionLog = QStringLiteral("%1/%2") - .arg(QString::fromLocal8Bit(pw.pw_dir)) - .arg(sessionType == QLatin1String("x11") - ? mainConfig.X11.SessionLogFile.get() - : mainConfig.Wayland.SessionLogFile.get()); + // determine stderr log file based on session type + QString sessionLog = QStringLiteral("%1/%2") + .arg(QString::fromLocal8Bit(pw.pw_dir)) + .arg(sessionType == QLatin1String("x11") + ? mainConfig.X11.SessionLogFile.get() + : mainConfig.Wayland.SessionLogFile.get()); - // create the path - QFileInfo finfo(sessionLog); - QDir().mkpath(finfo.absolutePath()); + // create the path + QFileInfo finfo(sessionLog); + QDir().mkpath(finfo.absolutePath()); - //swap the stderr pipe of this subprcess into a file - int fd = ::open(qPrintable(sessionLog), O_WRONLY | O_CREAT | O_TRUNC, 0600); - if (fd >= 0) + //swap the stderr pipe of this subprcess into a file + int fd = ::open(qPrintable(sessionLog), O_WRONLY | O_CREAT | O_TRUNC, 0600); + if (fd >= 0) { dup2 (fd, STDERR_FILENO); ::close(fd); } else { - qWarning() << "Could not open stderr to" << sessionLog; - } + qWarning() << "Could not open stderr to" << sessionLog; + } - //redirect any stdout to /dev/null - fd = ::open("/dev/null", O_WRONLY); - if (fd >= 0) + //redirect any stdout to /dev/null + fd = ::open("/dev/null", O_WRONLY); + if (fd >= 0) { dup2 (fd, STDOUT_FILENO); ::close(fd); } else { - qWarning() << "Could not redirect stdout"; - } + qWarning() << "Could not redirect stdout"; } } } diff --git a/src/daemon/UserSession.h b/src/daemon/UserSession.h index 8cb2599..1e35f53 100644 --- a/src/daemon/UserSession.h +++ b/src/daemon/UserSession.h @@ -26,6 +26,8 @@ #include #include +#include "Display.h" + namespace DDM { class Auth; class XOrgUserHelper; @@ -36,7 +38,9 @@ namespace DDM { public: explicit UserSession(Auth *parent); - void start(); + void start(const QString &command, + Display::DisplayServerType type, + const QByteArray &cookie = QByteArray()); void stop(); /** @@ -49,7 +53,6 @@ namespace DDM { void childModifier(); QTemporaryFile m_xauthFile; - Auth *m_auth; }; } diff --git a/src/daemon/WaylandDisplayServer.cpp b/src/daemon/WaylandDisplayServer.cpp deleted file mode 100644 index aab0da1..0000000 --- a/src/daemon/WaylandDisplayServer.cpp +++ /dev/null @@ -1,80 +0,0 @@ -/*************************************************************************** -* Copyright (c) 2021 Pier Luigi Fiorini -* -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the -* Free Software Foundation, Inc., -* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -***************************************************************************/ - -#include "WaylandDisplayServer.h" - -#include "Display.h" - -#include - -namespace DDM { - -WaylandDisplayServer::WaylandDisplayServer(Display *parent) - : DisplayServer(parent) -{ -} - -WaylandDisplayServer::~WaylandDisplayServer() -{ - stop(); -} - -QString WaylandDisplayServer::sessionType() const -{ - return QStringLiteral("wayland"); -} - -void WaylandDisplayServer::setDisplayName(const QString &displayName) -{ - m_display = displayName; -} - -bool WaylandDisplayServer::start() -{ - // Check flag - if (m_started) - return false; - - // Set flag - m_started = true; - emit started(); - - return true; -} - -void WaylandDisplayServer::stop() -{ - // Check flag - if (!m_started) - return; - - // Reset flag - m_started = false; - emit stopped(); -} - -void WaylandDisplayServer::finished() -{ -} - -void WaylandDisplayServer::setupDisplay() -{ -} - -} // namespace DDM diff --git a/src/daemon/WaylandDisplayServer.h b/src/daemon/WaylandDisplayServer.h deleted file mode 100644 index c4d8417..0000000 --- a/src/daemon/WaylandDisplayServer.h +++ /dev/null @@ -1,48 +0,0 @@ -/*************************************************************************** -* Copyright (c) 2021 Pier Luigi Fiorini -* -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the -* Free Software Foundation, Inc., -* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -***************************************************************************/ - -#ifndef DDM_WAYLANDDISPLAYSERVER_H -#define DDM_WAYLANDDISPLAYSERVER_H - -#include "DisplayServer.h" - -namespace DDM { - -class WaylandDisplayServer : public DisplayServer -{ - Q_OBJECT - Q_DISABLE_COPY(WaylandDisplayServer) -public: - explicit WaylandDisplayServer(Display *parent); - ~WaylandDisplayServer(); - - QString sessionType() const; - - void setDisplayName(const QString &displayName); - -public Q_SLOTS: - bool start(); - void stop(); - void finished(); - void setupDisplay(); -}; - -} // namespace DDM - -#endif // DDM_WAYLANDDISPLAYSERVER_H diff --git a/src/daemon/XorgDisplayServer.cpp b/src/daemon/XorgDisplayServer.cpp index 96afe25..9d01caa 100644 --- a/src/daemon/XorgDisplayServer.cpp +++ b/src/daemon/XorgDisplayServer.cpp @@ -39,9 +39,8 @@ #include namespace DDM { - XorgDisplayServer::XorgDisplayServer(Display *parent) : DisplayServer(parent) { - if (daemonApp->testing()) - m_xauth.setAuthDirectory(QStringLiteral(".")); + XorgDisplayServer::XorgDisplayServer(Display *parent) + : QObject(parent) { m_xauth.setup(); } @@ -49,23 +48,11 @@ namespace DDM { stop(); } - const QString &XorgDisplayServer::display() const { - return m_display; - } - - QString XorgDisplayServer::authPath() const { - return m_xauth.authPath(); - } - - QString XorgDisplayServer::sessionType() const { - return QStringLiteral("x11"); - } - const QByteArray XorgDisplayServer::cookie() const { return m_xauth.cookie(); } - bool XorgDisplayServer::start() { + bool XorgDisplayServer::start(int vt) { // check flag if (m_started) return false; @@ -87,8 +74,8 @@ namespace DDM { // generate auth file. // For the X server's copy, the display number doesn't matter. // An empty file would result in no access control! - m_display = QStringLiteral(":0"); - if(!m_xauth.addCookie(m_display)) { + display = QStringLiteral(":0"); + if(!m_xauth.addCookie(display)) { qCritical() << "Failed to write xauth file"; return false; } @@ -110,19 +97,12 @@ namespace DDM { // start display server QStringList args; - if (!daemonApp->testing()) { - process->setProgram(mainConfig.X11.ServerPath.get()); - args << mainConfig.X11.ServerArguments.get().split(QLatin1Char(' '), Qt::SkipEmptyParts) - << QStringLiteral("-background") << QStringLiteral("none") - << QStringLiteral("-seat") << displayPtr()->seat()->name() - << QStringLiteral("vt%1").arg(displayPtr()->terminalId()); - } else { - process->setProgram(mainConfig.X11.XephyrPath.get()); - args << QStringLiteral("-br") - << QStringLiteral("-screen") << QStringLiteral("800x600"); - } - - args << QStringLiteral("-auth") << m_xauth.authPath() + process->setProgram(mainConfig.X11.ServerPath.get()); + args << mainConfig.X11.ServerArguments.get().split(QLatin1Char(' '), Qt::SkipEmptyParts) + << QStringLiteral("-background") << QStringLiteral("none") + << QStringLiteral("-seat") << static_cast(parent())->seat->name() + << QStringLiteral("vt%1").arg(vt) + << QStringLiteral("-auth") << m_xauth.authPath() << QStringLiteral("-noreset") << QStringLiteral("-displayfd") << QString::number(pipeFds[1]); @@ -166,15 +146,15 @@ namespace DDM { } displayNumber.prepend(QByteArray(":")); displayNumber.remove(displayNumber.size() -1, 1); // trim trailing whitespace - m_display = QString::fromLocal8Bit(displayNumber); + display = QString::fromLocal8Bit(displayNumber); // close our pipe close(pipeFds[0]); // The file is also used by the greeter, which does care about the // display number. Write the proper entry, if it's different. - if(m_display != QStringLiteral(":0")) { - if(!m_xauth.addCookie(m_display)) { + if(display != QStringLiteral(":0")) { + if(!m_xauth.addCookie(display)) { qCritical() << "Failed to write xauth file"; stop(); return false; @@ -182,8 +162,6 @@ namespace DDM { } changeOwner(m_xauth.authPath()); - emit started(); - // set flag m_started = true; @@ -232,7 +210,7 @@ namespace DDM { // set process environment QProcessEnvironment env; - env.insert(QStringLiteral("DISPLAY"), m_display); + env.insert(QStringLiteral("DISPLAY"), display); env.insert(QStringLiteral("HOME"), QStringLiteral("/")); env.insert(QStringLiteral("PATH"), mainConfig.Users.DefaultPath.get()); env.insert(QStringLiteral("SHELL"), QStringLiteral("/bin/sh")); @@ -263,7 +241,7 @@ namespace DDM { // set process environment QProcessEnvironment env; - env.insert(QStringLiteral("DISPLAY"), m_display); + env.insert(QStringLiteral("DISPLAY"), display); env.insert(QStringLiteral("HOME"), QStringLiteral("/")); env.insert(QStringLiteral("PATH"), mainConfig.Users.DefaultPath.get()); env.insert(QStringLiteral("XAUTHORITY"), m_xauth.authPath()); diff --git a/src/daemon/XorgDisplayServer.h b/src/daemon/XorgDisplayServer.h index a41ef6c..6998bb2 100644 --- a/src/daemon/XorgDisplayServer.h +++ b/src/daemon/XorgDisplayServer.h @@ -21,33 +21,36 @@ #ifndef DDM_XORGDISPLAYSERVER_H #define DDM_XORGDISPLAYSERVER_H -#include "DisplayServer.h" #include "XAuth.h" class QProcess; namespace DDM { - class XorgDisplayServer : public DisplayServer { + class Display; + + class XorgDisplayServer : public QObject { Q_OBJECT Q_DISABLE_COPY(XorgDisplayServer) public: explicit XorgDisplayServer(Display *parent); ~XorgDisplayServer(); - const QString &display() const; - QString authPath() const; + const QByteArray cookie() const; - QString sessionType() const; + QString display{}; - const QByteArray cookie() const; + Q_SIGNALS: + void stopped(); public slots: - bool start(); + bool start(int vt); void stop(); void finished(); void setupDisplay(); private: + bool m_started { false }; + XAuth m_xauth; QProcess *process { nullptr }; diff --git a/src/daemon/XorgUserDisplayServer.cpp b/src/daemon/XorgUserDisplayServer.cpp deleted file mode 100644 index 6a12c94..0000000 --- a/src/daemon/XorgUserDisplayServer.cpp +++ /dev/null @@ -1,102 +0,0 @@ -/*************************************************************************** -* Copyright (c) 2021 Pier Luigi Fiorini -* -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the -* Free Software Foundation, Inc., -* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -***************************************************************************/ - -#include "Configuration.h" -#include "DaemonApp.h" -#include "Display.h" -#include "Seat.h" -#include "XorgUserDisplayServer.h" - -namespace DDM { - -XorgUserDisplayServer::XorgUserDisplayServer(Display *parent) - : DisplayServer(parent) -{ -} - -XorgUserDisplayServer::~XorgUserDisplayServer() -{ - stop(); -} - -QString XorgUserDisplayServer::sessionType() const -{ - return QStringLiteral("x11"); -} - -void XorgUserDisplayServer::setDisplayName(const QString &displayName) -{ - m_display = displayName; -} - -QString XorgUserDisplayServer::command(Display *display) -{ - QStringList args; - - if (daemonApp->testing()) { - args << mainConfig.X11.XephyrPath.get() - << QStringLiteral("-br") - << QStringLiteral("-screen") << QStringLiteral("800x600"); - } else { - args << mainConfig.X11.ServerPath.get() - << mainConfig.X11.ServerArguments.get().split(QLatin1Char(' '), Qt::SkipEmptyParts) - << QStringLiteral("-background") << QStringLiteral("none") - << QStringLiteral("-seat") << display->seat()->name() - << QStringLiteral("-noreset") - << QStringLiteral("-keeptty") - << QStringLiteral("-novtswitch") - << QStringLiteral("-verbose") << QStringLiteral("3"); - } - - return args.join(QLatin1Char(' ')); -} - -bool XorgUserDisplayServer::start() -{ - // Check flag - if (m_started) - return false; - - // Set flag - m_started = true; - emit started(); - - return true; -} - -void XorgUserDisplayServer::stop() -{ - // Check flag - if (!m_started) - return; - - // Reset flag - m_started = false; - emit stopped(); -} - -void XorgUserDisplayServer::finished() -{ -} - -void XorgUserDisplayServer::setupDisplay() -{ -} - -} // namespace DDM diff --git a/src/daemon/XorgUserDisplayServer.h b/src/daemon/XorgUserDisplayServer.h deleted file mode 100644 index 9186fb9..0000000 --- a/src/daemon/XorgUserDisplayServer.h +++ /dev/null @@ -1,53 +0,0 @@ -/*************************************************************************** -* Copyright (c) 2021 Pier Luigi Fiorini -* -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the -* Free Software Foundation, Inc., -* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -***************************************************************************/ - -#ifndef DDM_XORGUSERDISPLAYSERVER_H -#define DDM_XORGUSERDISPLAYSERVER_H - -#include "DisplayServer.h" -#include "XAuth.h" - -class QProcess; - -namespace DDM { - -class XorgUserDisplayServer : public DisplayServer -{ - Q_OBJECT - Q_DISABLE_COPY(XorgUserDisplayServer) -public: - explicit XorgUserDisplayServer(Display *parent); - ~XorgUserDisplayServer(); - - QString sessionType() const; - - void setDisplayName(const QString &displayName); - - static QString command(Display *display); - -public Q_SLOTS: - bool start(); - void stop(); - void finished(); - void setupDisplay(); -}; - -} // namespace DDM - -#endif // DDM_XORGUSERDISPLAYSERVER_H