From b0008edcb57712eaf95dbcc3ee610ab8727a9919 Mon Sep 17 00:00:00 2001 From: fufesou Date: Tue, 18 Aug 2026 15:02:50 +0800 Subject: [PATCH] refact: remove linux headless (#15866) * refact: remove linux headless Signed-off-by: fufesou * fix(linux): probe DRM availability asynchronously on login Signed-off-by: fufesou * revert changes in drm_capturer.rs Signed-off-by: fufesou * Update submodule hbb_common Signed-off-by: fufesou * docs(linux): clarify DRM availability comments Remove stale headless and unauthenticated-request wording, and document the Available-only login-screen gate. Signed-off-by: fufesou * fix(linux): remove unreachable session cleanup branch Remove the obsolete empty-session path and clarify the intended use of cached DRM availability. Signed-off-by: fufesou --------- Signed-off-by: fufesou --- .github/workflows/ci.yml | 1 - .github/workflows/flutter-build.yml | 5 - .github/workflows/playground.yml | 1 - Cargo.lock | 44 +- Cargo.toml | 1 - Dockerfile | 1 - README.md | 6 +- appimage/AppImageBuilder-aarch64.yml | 1 - appimage/AppImageBuilder-x86_64.yml | 1 - build.py | 16 +- docs/README-DE.md | 6 +- docs/README-ES.md | 6 +- docs/README-KR.md | 6 +- docs/README-NO.md | 6 +- docs/README-PTBR.md | 6 +- docs/README-RO.md | 6 +- docs/README-RU.md | 8 +- docs/README-UA.md | 6 +- flatpak/rustdesk.json | 14 +- flutter/lib/common/widgets/dialog.dart | 123 +- flutter/lib/common/widgets/toolbar.dart | 14 +- flutter/lib/consts.dart | 2 - .../desktop/pages/desktop_setting_page.dart | 4 - flutter/lib/models/model.dart | 10 +- flutter/lib/web/bridge.dart | 4 - libs/hbb_common | 2 +- res/PKGBUILD | 2 +- res/pam.d/rustdesk.debian | 5 - res/pam.d/rustdesk.suse | 5 - res/rpm-flutter-suse.spec | 2 +- res/rpm-flutter.spec | 2 +- res/rpm-suse.spec | 2 +- res/rpm.spec | 2 +- res/startwm.sh | 130 -- res/xorg.conf | 30 - src/client.rs | 84 +- src/common.rs | 2 +- src/core_main.rs | 8 - src/flutter.rs | 22 +- src/flutter_ffi.rs | 8 - src/lang/ar.rs | 10 - src/lang/be.rs | 10 - src/lang/bg.rs | 10 - src/lang/ca.rs | 10 - src/lang/cn.rs | 10 - src/lang/cs.rs | 10 - src/lang/da.rs | 10 - src/lang/de.rs | 10 - src/lang/el.rs | 10 - src/lang/en.rs | 10 - src/lang/eo.rs | 10 - src/lang/es.rs | 10 - src/lang/et.rs | 10 - src/lang/eu.rs | 10 - src/lang/fa.rs | 10 - src/lang/fi.rs | 10 - src/lang/fr.rs | 10 - src/lang/ge.rs | 10 - src/lang/gu.rs | 10 - src/lang/he.rs | 10 - src/lang/hi.rs | 10 - src/lang/hr.rs | 10 - src/lang/hu.rs | 10 - src/lang/id.rs | 10 - src/lang/it.rs | 10 - src/lang/ja.rs | 10 - src/lang/ko.rs | 10 - src/lang/kz.rs | 10 - src/lang/lt.rs | 10 - src/lang/lv.rs | 10 - src/lang/ml.rs | 10 - src/lang/nb.rs | 10 - src/lang/nl.rs | 10 - src/lang/pl.rs | 10 - src/lang/pt_PT.rs | 10 - src/lang/ptbr.rs | 10 - src/lang/ro.rs | 10 - src/lang/ru.rs | 10 - src/lang/sc.rs | 10 - src/lang/sk.rs | 10 - src/lang/sl.rs | 10 - src/lang/sq.rs | 10 - src/lang/sr.rs | 10 - src/lang/sv.rs | 10 - src/lang/ta.rs | 10 - src/lang/template.rs | 10 - src/lang/th.rs | 10 - src/lang/tr.rs | 10 - src/lang/tw.rs | 10 - src/lang/uk.rs | 10 - src/lang/vi.rs | 10 - src/platform/linux.rs | 65 +- src/platform/linux_desktop_manager.rs | 1363 ----------------- src/platform/mod.rs | 3 - src/rendezvous_mediator.rs | 5 - src/server/connection.rs | 424 +---- src/server/drm_capturer.rs | 20 +- src/ui/common.tis | 24 - src/ui/msgbox.tis | 59 +- 99 files changed, 133 insertions(+), 2944 deletions(-) delete mode 100644 res/pam.d/rustdesk.debian delete mode 100644 res/pam.d/rustdesk.suse delete mode 100755 res/startwm.sh delete mode 100644 res/xorg.conf delete mode 100644 src/platform/linux_desktop_manager.rs diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 173eda9f4..3e8373cdc 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -124,7 +124,6 @@ jobs: gcc \ git \ g++ \ - libpam0g-dev \ libasound2-dev \ libunwind-dev \ libgstreamer1.0-dev \ diff --git a/.github/workflows/flutter-build.yml b/.github/workflows/flutter-build.yml index 81a448a90..3a76412da 100644 --- a/.github/workflows/flutter-build.yml +++ b/.github/workflows/flutter-build.yml @@ -1009,7 +1009,6 @@ jobs: libgstreamer1.0-dev \ libgstreamer-plugins-base1.0-dev \ libgtk-3-dev \ - libpam0g-dev \ libpulse-dev \ libva-dev \ libxcb-randr0-dev \ @@ -1283,7 +1282,6 @@ jobs: libgstreamer1.0-dev \ libgstreamer-plugins-base1.0-dev \ libgtk-3-dev \ - libpam0g-dev \ libpulse-dev \ libva-dev \ libxcb-randr0-dev \ @@ -1574,7 +1572,6 @@ jobs: libgstreamer1.0-dev \ libgstreamer-plugins-base1.0-dev \ libgtk-3-dev \ - libpam0g-dev \ libpulse-dev \ libva-dev \ libxcb-randr0-dev \ @@ -1896,7 +1893,6 @@ jobs: libgstreamer1.0-dev \ libgstreamer-plugins-base1.0-dev \ libgtk-3-dev \ - libpam0g-dev \ libpulse-dev \ libva-dev \ libxcb-randr0-dev \ @@ -2126,7 +2122,6 @@ jobs: libgstreamer-plugins-base1.0-dev \ libgtk-3-dev \ liblzma-dev \ - libpam0g-dev \ libpulse-dev \ libva-dev \ libxcb-randr0-dev \ diff --git a/.github/workflows/playground.yml b/.github/workflows/playground.yml index 41b9c0c13..765bcf7f7 100644 --- a/.github/workflows/playground.yml +++ b/.github/workflows/playground.yml @@ -271,7 +271,6 @@ jobs: libgstreamer1.0-dev \ libgstreamer-plugins-base1.0-dev \ libgtk-3-dev \ - libpam0g-dev \ libpulse-dev \ libva-dev \ libvdpau-dev \ diff --git a/Cargo.lock b/Cargo.lock index 9272b562a..7448d84c3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3791,7 +3791,7 @@ dependencies = [ "toml 0.7.8", "tungstenite", "url", - "users 0.11.0", + "users", "uuid", "webpki-roots 1.0.9", "webrtc", @@ -5932,37 +5932,6 @@ dependencies = [ "winapi 0.3.9", ] -[[package]] -name = "pam" -version = "0.7.0" -source = "git+https://github.com/rustdesk-org/pam#7bfd25510202cd269292cbdd7c71f3977a6fd762" -dependencies = [ - "libc", - "pam-macros", - "pam-sys", - "users 0.10.0", -] - -[[package]] -name = "pam-macros" -version = "0.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c94f3b9b97df3c6d4e51a14916639b24e02c7d15d1dba686ce9b1118277cb811" -dependencies = [ - "proc-macro2 1.0.93", - "quote 1.0.36", - "syn 1.0.109", -] - -[[package]] -name = "pam-sys" -version = "1.0.0-alpha4" -source = "git+https://github.com/rustdesk-org/pam-sys?branch=fix/v1.0.0-alpha4_gnuc_va_list#3337c9bb9a9c68d7497ec8c93cad2368c26091b7" -dependencies = [ - "bindgen 0.59.2", - "libc", -] - [[package]] name = "pango" version = "0.18.3" @@ -7266,7 +7235,6 @@ dependencies = [ "once_cell", "openssl", "os-version", - "pam", "parity-tokio-ipc", "percent-encoding", "piet", @@ -9301,16 +9269,6 @@ version = "2.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "daf8dba3b7eb870caf1ddeed7bc9d2a049f3cfdfae7cb521b087cc33ae4c49da" -[[package]] -name = "users" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa4227e95324a443c9fcb06e03d4d85e91aabe9a5a02aa818688b6918b6af486" -dependencies = [ - "libc", - "log", -] - [[package]] name = "users" version = "0.11.0" diff --git a/Cargo.toml b/Cargo.toml index 588cbd96a..7d08cb3f1 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -189,7 +189,6 @@ async-process = "1.7" evdev = { git="https://github.com/rustdesk-org/evdev" } dbus = "0.9" dbus-crossroads = "0.5" -pam = { git="https://github.com/rustdesk-org/pam" } x11-clipboard = {git="https://github.com/clslaid/x11-clipboard", branch = "feat/store-batch", optional = true} x11rb = {version = "0.12", features = ["all-extensions"], optional = true} percent-encoding = {version = "2.3", optional = true} diff --git a/Dockerfile b/Dockerfile index f0e4e4a4a..e6c95ad52 100644 --- a/Dockerfile +++ b/Dockerfile @@ -19,7 +19,6 @@ RUN apt update -y && \ libxcb-shape0-dev \ libxcb-xfixes0-dev \ libasound2-dev \ - libpam0g-dev \ libpulse-dev \ make \ wget \ diff --git a/README.md b/README.md index 1bb120c81..08f3f9d57 100644 --- a/README.md +++ b/README.md @@ -66,19 +66,19 @@ Please download Sciter dynamic library yourself. ```sh sudo apt install -y zip g++ gcc git curl wget nasm yasm libgtk-3-dev clang libxcb-randr0-dev libxdo-dev \ libxfixes-dev libxcb-shape0-dev libxcb-xfixes0-dev libasound2-dev libpulse-dev cmake make \ - libclang-dev ninja-build libgstreamer1.0-dev libgstreamer-plugins-base1.0-dev libpam0g-dev + libclang-dev ninja-build libgstreamer1.0-dev libgstreamer-plugins-base1.0-dev ``` ### openSUSE Tumbleweed ```sh -sudo zypper install gcc-c++ git curl wget nasm yasm gcc gtk3-devel clang libxcb-devel libXfixes-devel cmake alsa-lib-devel gstreamer-devel gstreamer-plugins-base-devel xdotool-devel pam-devel +sudo zypper install gcc-c++ git curl wget nasm yasm gcc gtk3-devel clang libxcb-devel libXfixes-devel cmake alsa-lib-devel gstreamer-devel gstreamer-plugins-base-devel xdotool-devel ``` ### Fedora 28 (CentOS 8) ```sh -sudo yum -y install gcc-c++ git curl wget nasm yasm gcc gtk3-devel clang libxcb-devel libxdo-devel libXfixes-devel pulseaudio-libs-devel cmake alsa-lib-devel gstreamer1-devel gstreamer1-plugins-base-devel pam-devel +sudo yum -y install gcc-c++ git curl wget nasm yasm gcc gtk3-devel clang libxcb-devel libxdo-devel libXfixes-devel pulseaudio-libs-devel cmake alsa-lib-devel gstreamer1-devel gstreamer1-plugins-base-devel ``` ### Arch (Manjaro) diff --git a/appimage/AppImageBuilder-aarch64.yml b/appimage/AppImageBuilder-aarch64.yml index bad4e84db..1ccb51665 100644 --- a/appimage/AppImageBuilder-aarch64.yml +++ b/appimage/AppImageBuilder-aarch64.yml @@ -58,7 +58,6 @@ AppDir: - libpulse0 - packagekit-gtk3-module - libcanberra-gtk3-module - - libpam0g - libdrm2 exclude: - humanity-icon-theme diff --git a/appimage/AppImageBuilder-x86_64.yml b/appimage/AppImageBuilder-x86_64.yml index 7cd52b89a..30b48e7da 100644 --- a/appimage/AppImageBuilder-x86_64.yml +++ b/appimage/AppImageBuilder-x86_64.yml @@ -61,7 +61,6 @@ AppDir: - libpulse0 - packagekit-gtk3-module - libcanberra-gtk3-module - - libpam0g - libdrm2 exclude: - humanity-icon-theme diff --git a/build.py b/build.py index 6b770f993..4f1953662 100755 --- a/build.py +++ b/build.py @@ -364,7 +364,7 @@ Version: %s Architecture: %s Maintainer: rustdesk Homepage: https://rustdesk.com -Depends: libgtk-3-0t64 | libgtk-3-0, libxcb-randr0, libxdo3 | libxdo4, libxfixes3, libxcb-shape0, libxcb-xfixes0, libasound2t64 | libasound2, libsystemd0, curl, libva2, libva-drm2, libva-x11-2, libgstreamer-plugins-base1.0-0, libpam0g, gstreamer1.0-pipewire%s +Depends: libgtk-3-0t64 | libgtk-3-0, libxcb-randr0, libxdo3 | libxdo4, libxfixes3, libxcb-shape0, libxcb-xfixes0, libasound2t64 | libasound2, libsystemd0, curl, libva2, libva-drm2, libva-x11-2, libgstreamer-plugins-base1.0-0, gstreamer1.0-pipewire%s Recommends: libayatana-appindicator3-1 Description: A remote control software. @@ -704,8 +704,6 @@ def build_flutter_deb(version, features): system2('flutter build linux --release') system2('mkdir -p tmpdeb/usr/bin/') system2('mkdir -p tmpdeb/usr/share/rustdesk') - system2('mkdir -p tmpdeb/etc/rustdesk/') - system2('mkdir -p tmpdeb/etc/pam.d/') system2('mkdir -p tmpdeb/usr/share/rustdesk/files/systemd/') system2('mkdir -p tmpdeb/usr/share/icons/hicolor/256x256/apps/') system2('mkdir -p tmpdeb/usr/share/icons/hicolor/scalable/apps/') @@ -724,12 +722,6 @@ def build_flutter_deb(version, features): 'cp ../res/rustdesk.desktop tmpdeb/usr/share/applications/rustdesk.desktop') system2( 'cp ../res/rustdesk-link.desktop tmpdeb/usr/share/applications/rustdesk-link.desktop') - system2( - 'cp ../res/startwm.sh tmpdeb/etc/rustdesk/') - system2( - 'cp ../res/xorg.conf tmpdeb/etc/rustdesk/') - system2( - 'cp ../res/pam.d/rustdesk.debian tmpdeb/etc/pam.d/rustdesk') system2( "echo \"#!/bin/sh\" >> tmpdeb/usr/share/rustdesk/files/polkit && chmod a+x tmpdeb/usr/share/rustdesk/files/polkit") # Bundle libdrmtap.so only when this build actually enabled the `drm` feature, so stock packages @@ -1132,13 +1124,7 @@ def main(): 'cp res/rustdesk.desktop tmpdeb/usr/share/applications/rustdesk.desktop') system2( 'cp res/rustdesk-link.desktop tmpdeb/usr/share/applications/rustdesk-link.desktop') - os.system('mkdir -p tmpdeb/etc/rustdesk/') - os.system('cp -a res/startwm.sh tmpdeb/etc/rustdesk/') - os.system('mkdir -p tmpdeb/etc/X11/rustdesk/') - os.system('cp res/xorg.conf tmpdeb/etc/X11/rustdesk/') os.system('cp -a DEBIAN/* tmpdeb/DEBIAN/') - os.system('mkdir -p tmpdeb/etc/pam.d/') - os.system('cp pam.d/rustdesk.debian tmpdeb/etc/pam.d/rustdesk') system2('strip tmpdeb/usr/bin/rustdesk') system2('mkdir -p tmpdeb/usr/share/rustdesk') system2('mv tmpdeb/usr/bin/rustdesk tmpdeb/usr/share/rustdesk/') diff --git a/docs/README-DE.md b/docs/README-DE.md index f76e00fe5..91ba5a08c 100644 --- a/docs/README-DE.md +++ b/docs/README-DE.md @@ -66,19 +66,19 @@ Bitte laden Sie die dynamische Bibliothek Sciter selbst herunter. ```sh sudo apt install -y zip g++ gcc git curl wget nasm yasm libgtk-3-dev clang libxcb-randr0-dev libxdo-dev \ libxfixes-dev libxcb-shape0-dev libxcb-xfixes0-dev libasound2-dev libpulse-dev cmake make \ - libclang-dev ninja-build libgstreamer1.0-dev libgstreamer-plugins-base1.0-dev libpam0g-dev + libclang-dev ninja-build libgstreamer1.0-dev libgstreamer-plugins-base1.0-dev ``` ### openSUSE Tumbleweed ```sh -sudo zypper install gcc-c++ git curl wget nasm yasm gcc gtk3-devel clang libxcb-devel libXfixes-devel cmake alsa-lib-devel gstreamer-devel gstreamer-plugins-base-devel xdotool-devel pam-devel +sudo zypper install gcc-c++ git curl wget nasm yasm gcc gtk3-devel clang libxcb-devel libXfixes-devel cmake alsa-lib-devel gstreamer-devel gstreamer-plugins-base-devel xdotool-devel ``` ### Fedora 28 (CentOS 8) ```sh -sudo yum -y install gcc-c++ git curl wget nasm yasm gcc gtk3-devel clang libxcb-devel libxdo-devel libXfixes-devel pulseaudio-libs-devel cmake alsa-lib-devel gstreamer1-devel gstreamer1-plugins-base-devel pam-devel +sudo yum -y install gcc-c++ git curl wget nasm yasm gcc gtk3-devel clang libxcb-devel libxdo-devel libXfixes-devel pulseaudio-libs-devel cmake alsa-lib-devel gstreamer1-devel gstreamer1-plugins-base-devel ``` ### Arch (Manjaro) diff --git a/docs/README-ES.md b/docs/README-ES.md index 88cce46ad..bdf099ffd 100644 --- a/docs/README-ES.md +++ b/docs/README-ES.md @@ -62,19 +62,19 @@ Por favor descarga la librería dinámica de Sciter tú mismo. ```sh sudo apt install -y zip g++ gcc git curl wget nasm yasm libgtk-3-dev clang libxcb-randr0-dev libxdo-dev \ libxfixes-dev libxcb-shape0-dev libxcb-xfixes0-dev libasound2-dev libpulse-dev cmake make \ - libclang-dev ninja-build libgstreamer1.0-dev libgstreamer-plugins-base1.0-dev libpam0g-dev + libclang-dev ninja-build libgstreamer1.0-dev libgstreamer-plugins-base1.0-dev ``` ### openSUSE Tumbleweed ```sh -sudo zypper install gcc-c++ git curl wget nasm yasm gcc gtk3-devel clang libxcb-devel libXfixes-devel cmake alsa-lib-devel gstreamer-devel gstreamer-plugins-base-devel xdotool-devel pam-devel +sudo zypper install gcc-c++ git curl wget nasm yasm gcc gtk3-devel clang libxcb-devel libXfixes-devel cmake alsa-lib-devel gstreamer-devel gstreamer-plugins-base-devel xdotool-devel ``` ### Fedora 28 (CentOS 8) ```sh -sudo yum -y install gcc-c++ git curl wget nasm yasm gcc gtk3-devel clang libxcb-devel libxdo-devel libXfixes-devel pulseaudio-libs-devel cmake alsa-lib-devel gstreamer1-devel gstreamer1-plugins-base-devel pam-devel +sudo yum -y install gcc-c++ git curl wget nasm yasm gcc gtk3-devel clang libxcb-devel libxdo-devel libXfixes-devel pulseaudio-libs-devel cmake alsa-lib-devel gstreamer1-devel gstreamer1-plugins-base-devel ``` ### Arch (Manjaro) diff --git a/docs/README-KR.md b/docs/README-KR.md index 354cfe708..687ba24e6 100644 --- a/docs/README-KR.md +++ b/docs/README-KR.md @@ -66,19 +66,19 @@ Sciter 동적 라이브러리를 직접 다운로드하세요. ```sh sudo apt install -y zip g++ gcc git curl wget nasm yasm libgtk-3-dev clang libxcb-randr0-dev libxdo-dev \ libxfixes-dev libxcb-shape0-dev libxcb-xfixes0-dev libasound2-dev libpulse-dev cmake make \ - libclang-dev ninja-build libgstreamer1.0-dev libgstreamer-plugins-base1.0-dev libpam0g-dev + libclang-dev ninja-build libgstreamer1.0-dev libgstreamer-plugins-base1.0-dev ``` ### openSUSE Tumbleweed ```sh -sudo zypper install gcc-c++ git curl wget nasm yasm gcc gtk3-devel clang libxcb-devel libXfixes-devel cmake alsa-lib-devel gstreamer-devel gstreamer-plugins-base-devel xdotool-devel pam-devel +sudo zypper install gcc-c++ git curl wget nasm yasm gcc gtk3-devel clang libxcb-devel libXfixes-devel cmake alsa-lib-devel gstreamer-devel gstreamer-plugins-base-devel xdotool-devel ``` ### Fedora 28 (CentOS 8) ```sh -sudo yum -y install gcc-c++ git curl wget nasm yasm gcc gtk3-devel clang libxcb-devel libxdo-devel libXfixes-devel pulseaudio-libs-devel cmake alsa-lib-devel gstreamer1-devel gstreamer1-plugins-base-devel pam-devel +sudo yum -y install gcc-c++ git curl wget nasm yasm gcc gtk3-devel clang libxcb-devel libxdo-devel libXfixes-devel pulseaudio-libs-devel cmake alsa-lib-devel gstreamer1-devel gstreamer1-plugins-base-devel ``` ### Arch (Manjaro) diff --git a/docs/README-NO.md b/docs/README-NO.md index 9aac6d943..609795996 100644 --- a/docs/README-NO.md +++ b/docs/README-NO.md @@ -62,19 +62,19 @@ Venligst last ned Sciters dynamiske bibliotek selv. ```sh sudo apt install -y zip g++ gcc git curl wget nasm yasm libgtk-3-dev clang libxcb-randr0-dev libxdo-dev \ libxfixes-dev libxcb-shape0-dev libxcb-xfixes0-dev libasound2-dev libpulse-dev cmake make \ - libclang-dev ninja-build libgstreamer1.0-dev libgstreamer-plugins-base1.0-dev libpam0g-dev + libclang-dev ninja-build libgstreamer1.0-dev libgstreamer-plugins-base1.0-dev ``` ### openSUSE Tumbleweed ```sh -sudo zypper install gcc-c++ git curl wget nasm yasm gcc gtk3-devel clang libxcb-devel libXfixes-devel cmake alsa-lib-devel gstreamer-devel gstreamer-plugins-base-devel xdotool-devel pam-devel +sudo zypper install gcc-c++ git curl wget nasm yasm gcc gtk3-devel clang libxcb-devel libXfixes-devel cmake alsa-lib-devel gstreamer-devel gstreamer-plugins-base-devel xdotool-devel ``` ### Fedora 28 (CentOS 8) ```sh -sudo yum -y install gcc-c++ git curl wget nasm yasm gcc gtk3-devel clang libxcb-devel libxdo-devel libXfixes-devel pulseaudio-libs-devel cmake alsa-lib-devel gstreamer1-devel gstreamer1-plugins-base-devel pam-devel +sudo yum -y install gcc-c++ git curl wget nasm yasm gcc gtk3-devel clang libxcb-devel libxdo-devel libXfixes-devel pulseaudio-libs-devel cmake alsa-lib-devel gstreamer1-devel gstreamer1-plugins-base-devel ``` ### Arch (Manjaro) diff --git a/docs/README-PTBR.md b/docs/README-PTBR.md index bd16806ef..332967ea2 100644 --- a/docs/README-PTBR.md +++ b/docs/README-PTBR.md @@ -64,19 +64,19 @@ Por favor, faça o download da biblioteca dinâmica do Sciter por conta própria ### Ubuntu 18 (Debian 10) ```sh -sudo apt install -y zip g++ gcc git curl wget nasm yasm libgtk-3-dev clang libxcb-randr0-dev libxdo-dev libxfixes-dev libxcb-shape0-dev libxcb-xfixes0-dev libasound2-dev libpulse-dev cmake make libclang-dev ninja-build libgstreamer1.0-dev libgstreamer-plugins-base1.0-dev libpam0g-dev +sudo apt install -y zip g++ gcc git curl wget nasm yasm libgtk-3-dev clang libxcb-randr0-dev libxdo-dev libxfixes-dev libxcb-shape0-dev libxcb-xfixes0-dev libasound2-dev libpulse-dev cmake make libclang-dev ninja-build libgstreamer1.0-dev libgstreamer-plugins-base1.0-dev ``` ### openSUSE Tumbleweed ```sh -sudo zypper install gcc-c++ git curl wget nasm yasm gcc gtk3-devel clang libxcb-devel libXfixes-devel cmake alsa-lib-devel gstreamer-devel gstreamer-plugins-base-devel xdotool-devel pam-devel +sudo zypper install gcc-c++ git curl wget nasm yasm gcc gtk3-devel clang libxcb-devel libXfixes-devel cmake alsa-lib-devel gstreamer-devel gstreamer-plugins-base-devel xdotool-devel ``` ### Fedora 28 (CentOS 8) ```sh -sudo yum -y install gcc-c++ git curl wget nasm yasm gcc gtk3-devel clang libxcb-devel libxdo-devel libXfixes-devel pulseaudio-libs-devel cmake alsa-lib-devel gstreamer1-devel gstreamer1-plugins-base-devel pam-devel +sudo yum -y install gcc-c++ git curl wget nasm yasm gcc gtk3-devel clang libxcb-devel libxdo-devel libXfixes-devel pulseaudio-libs-devel cmake alsa-lib-devel gstreamer1-devel gstreamer1-plugins-base-devel ``` ### Arch (Manjaro) diff --git a/docs/README-RO.md b/docs/README-RO.md index d2b748e47..0f2f17466 100644 --- a/docs/README-RO.md +++ b/docs/README-RO.md @@ -66,19 +66,19 @@ Te rugăm să descarci singur librăria dinamică Sciter. ```sh sudo apt install -y zip g++ gcc git curl wget nasm yasm libgtk-3-dev clang libxcb-randr0-dev libxdo-dev \ libxfixes-dev libxcb-shape0-dev libxcb-xfixes0-dev libasound2-dev libpulse-dev cmake make \ - libclang-dev ninja-build libgstreamer1.0-dev libgstreamer-plugins-base1.0-dev libpam0g-dev + libclang-dev ninja-build libgstreamer1.0-dev libgstreamer-plugins-base1.0-dev ``` ### openSUSE Tumbleweed ```sh -sudo zypper install gcc-c++ git curl wget nasm yasm gcc gtk3-devel clang libxcb-devel libXfixes-devel cmake alsa-lib-devel gstreamer-devel gstreamer-plugins-base-devel xdotool-devel pam-devel +sudo zypper install gcc-c++ git curl wget nasm yasm gcc gtk3-devel clang libxcb-devel libXfixes-devel cmake alsa-lib-devel gstreamer-devel gstreamer-plugins-base-devel xdotool-devel ``` ### Fedora 28 (CentOS 8) ```sh -sudo yum -y install gcc-c++ git curl wget nasm yasm gcc gtk3-devel clang libxcb-devel libxdo-devel libXfixes-devel pulseaudio-libs-devel cmake alsa-lib-devel gstreamer1-devel gstreamer1-plugins-base-devel pam-devel +sudo yum -y install gcc-c++ git curl wget nasm yasm gcc gtk3-devel clang libxcb-devel libxdo-devel libXfixes-devel pulseaudio-libs-devel cmake alsa-lib-devel gstreamer1-devel gstreamer1-plugins-base-devel ``` ### Arch (Manjaro) diff --git a/docs/README-RU.md b/docs/README-RU.md index c3c208066..e3e97d8ca 100644 --- a/docs/README-RU.md +++ b/docs/README-RU.md @@ -68,19 +68,19 @@ RustDesk приветствует вклад каждого. Ознакомьт ```sh sudo apt install -y zip g++ gcc git curl wget nasm yasm libgtk-3-dev clang libxcb-randr0-dev libxdo-dev \ libxfixes-dev libxcb-shape0-dev libxcb-xfixes0-dev libasound2-dev libpulse-dev cmake make \ - libclang-dev ninja-build libgstreamer1.0-dev libgstreamer-plugins-base1.0-dev libpam0g-dev + libclang-dev ninja-build libgstreamer1.0-dev libgstreamer-plugins-base1.0-dev ``` ### openSUSE Tumbleweed ```sh -sudo zypper install gcc-c++ git curl wget nasm yasm gcc gtk3-devel clang libxcb-devel libXfixes-devel cmake alsa-lib-devel gstreamer-devel gstreamer-plugins-base-devel xdotool-devel pam-devel +sudo zypper install gcc-c++ git curl wget nasm yasm gcc gtk3-devel clang libxcb-devel libXfixes-devel cmake alsa-lib-devel gstreamer-devel gstreamer-plugins-base-devel xdotool-devel ``` ### Fedora 28 (CentOS 8) ```sh -sudo yum -y install gcc-c++ git curl wget nasm yasm gcc gtk3-devel clang libxcb-devel libxdo-devel libXfixes-devel pulseaudio-libs-devel cmake alsa-lib-devel gstreamer1-devel gstreamer1-plugins-base-devel pam-devel +sudo yum -y install gcc-c++ git curl wget nasm yasm gcc gtk3-devel clang libxcb-devel libxdo-devel libXfixes-devel pulseaudio-libs-devel cmake alsa-lib-devel gstreamer1-devel gstreamer1-plugins-base-devel ``` ### Arch (Manjaro) @@ -179,4 +179,4 @@ target/release/rustdesk ![Передача файлов](https://github.com/rustdesk/rustdesk/assets/28412477/39511ad3-aa9a-4f8c-8947-1cce286a46ad) -![TCP-туннелирование](https://github.com/rustdesk/rustdesk/assets/28412477/78e8708f-e87e-4570-8373-1360033ea6c5) \ No newline at end of file +![TCP-туннелирование](https://github.com/rustdesk/rustdesk/assets/28412477/78e8708f-e87e-4570-8373-1360033ea6c5) diff --git a/docs/README-UA.md b/docs/README-UA.md index 3da69acad..12d98dbdf 100644 --- a/docs/README-UA.md +++ b/docs/README-UA.md @@ -59,19 +59,19 @@ RustDesk вітає внесок кожного. Ознайомтеся з [CONT ```sh sudo apt install -y zip g++ gcc git curl wget nasm yasm libgtk-3-dev clang libxcb-randr0-dev libxdo-dev \ libxfixes-dev libxcb-shape0-dev libxcb-xfixes0-dev libasound2-dev libpulse-dev cmake make \ - libclang-dev ninja-build libgstreamer1.0-dev libgstreamer-plugins-base1.0-dev libpam0g-dev + libclang-dev ninja-build libgstreamer1.0-dev libgstreamer-plugins-base1.0-dev ``` ### openSUSE Tumbleweed ```sh -sudo zypper install gcc-c++ git curl wget nasm yasm gcc gtk3-devel clang libxcb-devel libXfixes-devel cmake alsa-lib-devel gstreamer-devel gstreamer-plugins-base-devel xdotool-devel pam-devel +sudo zypper install gcc-c++ git curl wget nasm yasm gcc gtk3-devel clang libxcb-devel libXfixes-devel cmake alsa-lib-devel gstreamer-devel gstreamer-plugins-base-devel xdotool-devel ``` ### Fedora 28 (CentOS 8) ```sh -sudo yum -y install gcc-c++ git curl wget nasm yasm gcc gtk3-devel clang libxcb-devel libxdo-devel libXfixes-devel pulseaudio-libs-devel cmake alsa-lib-devel gstreamer1-devel gstreamer1-plugins-base-devel pam-devel +sudo yum -y install gcc-c++ git curl wget nasm yasm gcc gtk3-devel clang libxcb-devel libxdo-devel libXfixes-devel pulseaudio-libs-devel cmake alsa-lib-devel gstreamer1-devel gstreamer1-plugins-base-devel ``` ### Arch (Manjaro) diff --git a/flatpak/rustdesk.json b/flatpak/rustdesk.json index 2418ac2a6..108a4ba1d 100644 --- a/flatpak/rustdesk.json +++ b/flatpak/rustdesk.json @@ -21,18 +21,6 @@ } ] }, - { - "name": "pam", - "buildsystem": "autotools", - "config-opts": ["--disable-selinux"], - "sources": [ - { - "type": "archive", - "url": "https://github.com/linux-pam/linux-pam/releases/download/v1.3.1/Linux-PAM-1.3.1.tar.xz", - "sha256": "eff47a4ecd833fbf18de9686632a70ee8d0794b79aecb217ebd0ce11db4cd0db" - } - ] - }, { "name": "rustdesk", "buildsystem": "simple", @@ -63,4 +51,4 @@ "--socket=pulseaudio", "--talk-name=org.freedesktop.Flatpak" ] -} \ No newline at end of file +} diff --git a/flutter/lib/common/widgets/dialog.dart b/flutter/lib/common/widgets/dialog.dart index f80603802..f009c051c 100644 --- a/flutter/lib/common/widgets/dialog.dart +++ b/flutter/lib/common/widgets/dialog.dart @@ -936,26 +936,19 @@ void enterPasswordDialog( ); } -void enterUserLoginDialog( - SessionID sessionId, - OverlayDialogManager dialogManager, - String osAccountDescTip, - bool canRememberAccount) async { +void enterUserLoginDialog(SessionID sessionId, + OverlayDialogManager dialogManager, String osAccountDescTip) async { await _connectDialog( sessionId, dialogManager, osUsernameController: TextEditingController(), osPasswordController: TextEditingController(), osAccountDescTip: osAccountDescTip, - canRememberAccount: canRememberAccount, ); } -void enterUserLoginAndPasswordDialog( - SessionID sessionId, - OverlayDialogManager dialogManager, - String osAccountDescTip, - bool canRememberAccount) async { +void enterUserLoginAndPasswordDialog(SessionID sessionId, + OverlayDialogManager dialogManager, String osAccountDescTip) async { await _connectDialog( sessionId, dialogManager, @@ -963,7 +956,6 @@ void enterUserLoginAndPasswordDialog( osPasswordController: TextEditingController(), passwordController: TextEditingController(), osAccountDescTip: osAccountDescTip, - canRememberAccount: canRememberAccount, ); } @@ -974,7 +966,6 @@ _connectDialog( TextEditingController? osPasswordController, TextEditingController? passwordController, String? osAccountDescTip, - bool canRememberAccount = true, }) async { final errUsername = ''.obs; var rememberPassword = false; @@ -982,11 +973,6 @@ _connectDialog( rememberPassword = await bind.sessionGetRemember(sessionId: sessionId) ?? false; } - var rememberAccount = false; - if (canRememberAccount && osUsernameController != null) { - rememberAccount = - await bind.sessionGetRemember(sessionId: sessionId) ?? false; - } if (osUsernameController != null) { osUsernameController.addListener(() { if (errUsername.value.isNotEmpty) { @@ -1014,12 +1000,6 @@ _connectDialog( final osPassword = osPasswordController?.text.trim() ?? ''; final password = passwordController?.text.trim() ?? ''; if (passwordController != null && password.isEmpty) return; - if (rememberAccount) { - bind.sessionPeerOption( - sessionId: sessionId, name: 'os-username', value: osUsername); - bind.sessionPeerOption( - sessionId: sessionId, name: 'os-password', value: osPassword); - } gFFI.login( osUsername, osPassword, @@ -1096,16 +1076,6 @@ _connectDialog( controller: osPasswordController, autoFocus: false, ), - if (canRememberAccount) - rememberWidget( - translate('remember_account_tip'), - rememberAccount, - (v) { - if (v != null) { - setState(() => rememberAccount = v); - } - }, - ), ], ); } @@ -1542,91 +1512,6 @@ showSetOSPassword( }); } -showSetOSAccount( - SessionID sessionId, - OverlayDialogManager dialogManager, -) async { - final usernameController = TextEditingController(); - final passwdController = TextEditingController(); - var username = - await bind.sessionGetOption(sessionId: sessionId, arg: 'os-username') ?? - ''; - var password = - await bind.sessionGetOption(sessionId: sessionId, arg: 'os-password') ?? - ''; - usernameController.text = username; - passwdController.text = password; - dialogManager.show((setState, close, context) { - submit() { - final username = usernameController.text.trim(); - final password = usernameController.text.trim(); - bind.sessionPeerOption( - sessionId: sessionId, name: 'os-username', value: username); - bind.sessionPeerOption( - sessionId: sessionId, name: 'os-password', value: password); - close(); - } - - descWidget(String text) { - return Column( - children: [ - Align( - alignment: Alignment.centerLeft, - child: Text( - text, - maxLines: 3, - softWrap: true, - overflow: TextOverflow.ellipsis, - style: TextStyle(fontSize: 16), - ), - ), - Container( - height: 8, - ), - ], - ); - } - - return CustomAlertDialog( - title: Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Icon(Icons.password_rounded, color: MyTheme.accent), - Text(translate('OS Account')).paddingOnly(left: 10), - ], - ), - content: Column( - mainAxisSize: MainAxisSize.min, - children: [ - descWidget(translate("os_account_desk_tip")), - DialogTextField( - title: translate(DialogTextField.kUsernameTitle), - controller: usernameController, - prefixIcon: DialogTextField.kUsernameIcon, - errorText: null, - ), - PasswordWidget(controller: passwdController), - ], - ), - actions: [ - dialogButton( - "Cancel", - icon: Icon(Icons.close_rounded), - onPressed: close, - isOutline: true, - ), - dialogButton( - "OK", - icon: Icon(Icons.done_rounded), - onPressed: submit, - ), - ], - onSubmit: submit, - onCancel: close, - ); - }); -} - Widget buildNoteTextField({ required TextEditingController controller, required VoidCallback onEscape, diff --git a/flutter/lib/common/widgets/toolbar.dart b/flutter/lib/common/widgets/toolbar.dart index 0e4c5b7a5..c3896b097 100644 --- a/flutter/lib/common/widgets/toolbar.dart +++ b/flutter/lib/common/widgets/toolbar.dart @@ -349,12 +349,12 @@ List toolbarControls(BuildContext context, String id, FFI ffi) { showRequestElevationDialog(sessionId, ffi.dialogManager)), ); } - // osAccount / osPassword + // osPassword if (isDefaultConn && perms['keyboard'] != false) { v.add( TTextMenu( child: Row(children: [ - Text(translate(pi.isHeadless ? 'OS Account' : 'OS Password')), + Text(translate('OS Password')), ]), trailingIcon: Transform.scale( scale: (isDesktop || isWebDesktop) ? 0.8 : 1, @@ -363,18 +363,12 @@ List toolbarControls(BuildContext context, String id, FFI ffi) { if (isMobile && Navigator.canPop(context)) { Navigator.pop(context); } - if (pi.isHeadless) { - showSetOSAccount(sessionId, ffi.dialogManager); - } else { - handleOsPasswordEditIcon(sessionId, ffi.dialogManager); - } + handleOsPasswordEditIcon(sessionId, ffi.dialogManager); }, icon: Icon(Icons.edit, color: isMobile ? MyTheme.accent : null), ), ), - onPressed: () => pi.isHeadless - ? showSetOSAccount(sessionId, ffi.dialogManager) - : handleOsPasswordAction(sessionId, ffi.dialogManager), + onPressed: () => handleOsPasswordAction(sessionId, ffi.dialogManager), ), ); } diff --git a/flutter/lib/consts.dart b/flutter/lib/consts.dart index 6c22057f9..9eb21665a 100644 --- a/flutter/lib/consts.dart +++ b/flutter/lib/consts.dart @@ -18,7 +18,6 @@ const kKeyMapMode = 'map'; const kKeyTranslateMode = 'translate'; const String kPlatformAdditionsIsWayland = "is_wayland"; -const String kPlatformAdditionsHeadless = "headless"; const String kPlatformAdditionsIsInstalled = "is_installed"; const String kPlatformAdditionsIddImpl = "idd_impl"; const String kPlatformAdditionsRustDeskVirtualDisplays = @@ -164,7 +163,6 @@ const String kOptionEnableConfirmClosingTabs = "enable-confirm-closing-tabs"; const String kOptionAllowAlwaysSoftwareRender = "allow-always-software-render"; const String kOptionEnableCheckUpdate = "enable-check-update"; const String kOptionAllowAutoUpdate = "allow-auto-update"; -const String kOptionAllowLinuxHeadless = "allow-linux-headless"; const String kOptionAllowRemoveWallpaper = "allow-remove-wallpaper"; const String kOptionStopService = "stop-service"; const String kOptionDirectxCapture = "enable-directx-capture"; diff --git a/flutter/lib/desktop/pages/desktop_setting_page.dart b/flutter/lib/desktop/pages/desktop_setting_page.dart index a67facfa9..c696ad510 100644 --- a/flutter/lib/desktop/pages/desktop_setting_page.dart +++ b/flutter/lib/desktop/pages/desktop_setting_page.dart @@ -586,10 +586,6 @@ class _GeneralState extends State<_General> { )); } - if (!isWeb && bind.mainShowOption(key: kOptionAllowLinuxHeadless)) { - children.add(_OptionCheckBox( - context, 'Allow linux headless', kOptionAllowLinuxHeadless)); - } if (!bind.isDisableAccount()) { children.add(_OptionCheckBox( context, diff --git a/flutter/lib/models/model.dart b/flutter/lib/models/model.dart index 7bab906bc..74f72021b 100644 --- a/flutter/lib/models/model.dart +++ b/flutter/lib/models/model.dart @@ -908,17 +908,12 @@ class FfiModel with ChangeNotifier { enter2FaDialog(sessionId, dialogManager); } else if (type == 'input-password') { enterPasswordDialog(sessionId, dialogManager); - } else if (type == 'session-login' || type == 'session-re-login') { - enterUserLoginDialog(sessionId, dialogManager, 'login_linux_tip', true); - } else if (type == 'session-login-password') { - enterUserLoginAndPasswordDialog( - sessionId, dialogManager, 'login_linux_tip', true); } else if (type == 'terminal-admin-login') { enterUserLoginDialog( - sessionId, dialogManager, 'terminal-admin-login-tip', false); + sessionId, dialogManager, 'terminal-admin-login-tip'); } else if (type == 'terminal-admin-login-password') { enterUserLoginAndPasswordDialog( - sessionId, dialogManager, 'terminal-admin-login-tip', false); + sessionId, dialogManager, 'terminal-admin-login-tip'); } else if (type == 'restarting') { // Treat restart messages as reconnect control events. Rust still sends // title/text for legacy UI and translation reuse; Flutter keeps the last @@ -4168,7 +4163,6 @@ class PeerInfo with ChangeNotifier { RxBool isSet = false.obs; bool get isWayland => platformAdditions[kPlatformAdditionsIsWayland] == true; - bool get isHeadless => platformAdditions[kPlatformAdditionsHeadless] == true; bool get isInstalled => platform != kPeerPlatformWindows || platformAdditions[kPlatformAdditionsIsInstalled] == true; diff --git a/flutter/lib/web/bridge.dart b/flutter/lib/web/bridge.dart index b59c769da..f4a082941 100644 --- a/flutter/lib/web/bridge.dart +++ b/flutter/lib/web/bridge.dart @@ -762,10 +762,6 @@ class RustdeskImpl { throw UnimplementedError("mainGetError"); } - bool mainShowOption({required String key, dynamic hint}) { - throw UnimplementedError("mainShowOption"); - } - Future mainSetOption( {required String key, required String value, dynamic hint}) { js.context.callMethod('setByName', [ diff --git a/libs/hbb_common b/libs/hbb_common index f124c0a5d..b2b1ac453 160000 --- a/libs/hbb_common +++ b/libs/hbb_common @@ -1 +1 @@ -Subproject commit f124c0a5d49a4a13381902124b65364ff28fa541 +Subproject commit b2b1ac453d1d694046f63be20d792d608dac1c93 diff --git a/res/PKGBUILD b/res/PKGBUILD index 8f3cc9c81..b3b64f311 100644 --- a/res/PKGBUILD +++ b/res/PKGBUILD @@ -7,7 +7,7 @@ arch=('x86_64') url="" license=('AGPL-3.0') groups=() -depends=('gtk3' 'xdotool' 'libxcb' 'libxfixes' 'alsa-lib' 'libva' 'libappindicator-gtk3' 'pam' 'gst-plugins-base' 'gst-plugin-pipewire') +depends=('gtk3' 'xdotool' 'libxcb' 'libxfixes' 'alsa-lib' 'libva' 'libappindicator-gtk3' 'gst-plugins-base' 'gst-plugin-pipewire') makedepends=() checkdepends=() optdepends=() diff --git a/res/pam.d/rustdesk.debian b/res/pam.d/rustdesk.debian deleted file mode 100644 index 789ce8f7c..000000000 --- a/res/pam.d/rustdesk.debian +++ /dev/null @@ -1,5 +0,0 @@ -#%PAM-1.0 -@include common-auth -@include common-account -@include common-session -@include common-password diff --git a/res/pam.d/rustdesk.suse b/res/pam.d/rustdesk.suse deleted file mode 100644 index a7c7836ce..000000000 --- a/res/pam.d/rustdesk.suse +++ /dev/null @@ -1,5 +0,0 @@ -#%PAM-1.0 -auth include common-auth -account include common-account -session include common-session -password include common-password diff --git a/res/rpm-flutter-suse.spec b/res/rpm-flutter-suse.spec index ea7dd8a40..5b8a0d416 100644 --- a/res/rpm-flutter-suse.spec +++ b/res/rpm-flutter-suse.spec @@ -5,7 +5,7 @@ Summary: RPM package License: GPL-3.0 URL: https://rustdesk.com Vendor: rustdesk -Requires: gtk3 libxcb1 libXfixes3 alsa-utils libXtst6 libva2 pam gstreamer-plugins-base gstreamer-plugin-pipewire +Requires: gtk3 libxcb1 libXfixes3 alsa-utils libXtst6 libva2 gstreamer-plugins-base gstreamer-plugin-pipewire Recommends: libayatana-appindicator3-1 xdotool Provides: libdesktop_drop_plugin.so()(64bit), libdesktop_multi_window_plugin.so()(64bit), libfile_selector_linux_plugin.so()(64bit), libflutter_custom_cursor_plugin.so()(64bit), libflutter_linux_gtk.so()(64bit), libscreen_retriever_plugin.so()(64bit), libtray_manager_plugin.so()(64bit), liburl_launcher_linux_plugin.so()(64bit), libwindow_manager_plugin.so()(64bit), libwindow_size_plugin.so()(64bit), libtexture_rgba_renderer_plugin.so()(64bit) diff --git a/res/rpm-flutter.spec b/res/rpm-flutter.spec index 272148d91..70fef6325 100644 --- a/res/rpm-flutter.spec +++ b/res/rpm-flutter.spec @@ -5,7 +5,7 @@ Summary: RPM package License: GPL-3.0 URL: https://rustdesk.com Vendor: rustdesk -Requires: gtk3 libxcb libXfixes alsa-lib libva pam gstreamer1-plugins-base +Requires: gtk3 libxcb libXfixes alsa-lib libva gstreamer1-plugins-base Recommends: libayatana-appindicator-gtk3 libxdo Provides: libdesktop_drop_plugin.so()(64bit), libdesktop_multi_window_plugin.so()(64bit), libfile_selector_linux_plugin.so()(64bit), libflutter_custom_cursor_plugin.so()(64bit), libflutter_linux_gtk.so()(64bit), libscreen_retriever_plugin.so()(64bit), libtray_manager_plugin.so()(64bit), liburl_launcher_linux_plugin.so()(64bit), libwindow_manager_plugin.so()(64bit), libwindow_size_plugin.so()(64bit), libtexture_rgba_renderer_plugin.so()(64bit) diff --git a/res/rpm-suse.spec b/res/rpm-suse.spec index 14364eb77..b2f64d5b1 100644 --- a/res/rpm-suse.spec +++ b/res/rpm-suse.spec @@ -3,7 +3,7 @@ Version: 1.1.9 Release: 0 Summary: RPM package License: GPL-3.0 -Requires: gtk3 libxcb1 libXfixes3 alsa-utils libXtst6 libva2 pam gstreamer-plugins-base gstreamer-plugin-pipewire +Requires: gtk3 libxcb1 libXfixes3 alsa-utils libXtst6 libva2 gstreamer-plugins-base gstreamer-plugin-pipewire Recommends: libayatana-appindicator3-1 xdotool # https://docs.fedoraproject.org/en-US/packaging-guidelines/Scriptlets/ diff --git a/res/rpm.spec b/res/rpm.spec index 8aaf2508c..18eb46c75 100644 --- a/res/rpm.spec +++ b/res/rpm.spec @@ -5,7 +5,7 @@ Summary: RPM package License: GPL-3.0 URL: https://rustdesk.com Vendor: rustdesk -Requires: gtk3 libxcb libXfixes alsa-lib libva2 pam gstreamer1-plugins-base +Requires: gtk3 libxcb libXfixes alsa-lib libva2 gstreamer1-plugins-base Recommends: libayatana-appindicator-gtk3 libxdo # https://docs.fedoraproject.org/en-US/packaging-guidelines/Scriptlets/ diff --git a/res/startwm.sh b/res/startwm.sh deleted file mode 100755 index 04e7a5a18..000000000 --- a/res/startwm.sh +++ /dev/null @@ -1,130 +0,0 @@ -#!/usr/bin/env bash - -# This script is derived from https://github.com/neutrinolabs/xrdp/sesman/startwm.sh. - -# -# This script is an example. You might need to edit this script -# depending on your distro if it doesn't work for you. -# -# Uncomment the following line for debug: -# exec xterm - - -# Execution sequence for interactive login shell - pseudocode -# -# IF /etc/profile is readable THEN -# execute ~/.bash_profile -# END IF -# IF ~/.bash_profile is readable THEN -# execute ~/.bash_profile -# ELSE -# IF ~/.bash_login is readable THEN -# execute ~/.bash_login -# ELSE -# IF ~/.profile is readable THEN -# execute ~/.profile -# END IF -# END IF -# END IF -pre_start() -{ - if [ -r /etc/profile ]; then - . /etc/profile - fi - if [ -r ~/.bash_profile ]; then - . ~/.bash_profile - else - if [ -r ~/.bash_login ]; then - . ~/.bash_login - else - if [ -r ~/.profile ]; then - . ~/.profile - fi - fi - fi - return 0 -} - -# When logging out from the interactive shell, the execution sequence is: -# -# IF ~/.bash_logout exists THEN -# execute ~/.bash_logout -# END IF -post_start() -{ - if [ -r ~/.bash_logout ]; then - . ~/.bash_logout - fi - return 0 -} - -#start the window manager -wm_start() -{ - if [ -r /etc/default/locale ]; then - . /etc/default/locale - export LANG LANGUAGE - fi - - # debian - if [ -r /etc/X11/Xsession ]; then - pre_start - . /etc/X11/Xsession - post_start - exit 0 - fi - - # alpine - # Don't use /etc/X11/xinit/Xsession - it doesn't work - if [ -f /etc/alpine-release ]; then - if [ -f /etc/X11/xinit/xinitrc ]; then - pre_start - /etc/X11/xinit/xinitrc - post_start - else - echo "** xinit package isn't installed" >&2 - exit 1 - fi - fi - - # el - if [ -r /etc/X11/xinit/Xsession ]; then - pre_start - . /etc/X11/xinit/Xsession - post_start - exit 0 - fi - - # suse - if [ -r /etc/X11/xdm/Xsession ]; then - # since the following script run a user login shell, - # do not execute the pseudo login shell scripts - . /etc/X11/xdm/Xsession - exit 0 - elif [ -r /usr/etc/X11/xdm/Xsession ]; then - . /usr/etc/X11/xdm/Xsession - exit 0 - fi - - pre_start - xterm - post_start -} - -#. /etc/environment -#export PATH=$PATH -#export LANG=$LANG - -# change PATH to be what your environment needs usually what is in -# /etc/environment -#PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games" -#export PATH=$PATH - -# for PATH and LANG from /etc/environment -# pam will auto process the environment file if /etc/pam.d/xrdp-sesman -# includes -# auth required pam_env.so readenv=1 - -wm_start - -exit 1 diff --git a/res/xorg.conf b/res/xorg.conf deleted file mode 100644 index fe1539995..000000000 --- a/res/xorg.conf +++ /dev/null @@ -1,30 +0,0 @@ -Section "Monitor" - Identifier "Dummy Monitor" - - # Default HorizSync 31.50 - 48.00 kHz - HorizSync 5.0 - 150.0 - # Default VertRefresh 50.00 - 70.00 Hz - VertRefresh 5.0 - 100.0 - - # Taken from https://www.xpra.org/xorg.conf - Modeline "1920x1080" 23.53 1920 1952 2040 2072 1080 1106 1108 1135 - Modeline "1280x720" 27.41 1280 1312 1416 1448 720 737 740 757 -EndSection - -Section "Device" - Identifier "Dummy VideoCard" - Driver "dummy" - # Default VideoRam 4096 - # (1920 * 1080 * 4) / 1024 = 8100 - VideoRam 8100 -EndSection - -Section "Screen" - Identifier "Dummy Screen" - Device "Dummy VideoCard" - Monitor "Dummy Monitor" - SubSection "Display" - Depth 24 - Modes "1920x1080" "1280x720" - EndSubSection -EndSection \ No newline at end of file diff --git a/src/client.rs b/src/client.rs index e1e4c8034..73cf466eb 100644 --- a/src/client.rs +++ b/src/client.rs @@ -101,18 +101,6 @@ const RESTART_REMOTE_DEVICE_GRACE: Duration = Duration::from_secs(5 * 60); pub const VIDEO_QUEUE_SIZE: usize = 120; const MAX_DECODE_FAIL_COUNTER: usize = 3; -#[cfg(target_os = "linux")] -pub const LOGIN_MSG_DESKTOP_NOT_INITED: &str = "Desktop env is not inited"; -pub const LOGIN_MSG_DESKTOP_SESSION_NOT_READY: &str = "Desktop session not ready"; -pub const LOGIN_MSG_DESKTOP_XSESSION_FAILED: &str = "Desktop xsession failed"; -pub const LOGIN_MSG_DESKTOP_SESSION_ANOTHER_USER: &str = "Desktop session another user login"; -pub const LOGIN_MSG_DESKTOP_XORG_NOT_FOUND: &str = "Desktop xorg not found"; -// ls /usr/share/xsessions/ -pub const LOGIN_MSG_DESKTOP_NO_DESKTOP: &str = "Desktop none"; -pub const LOGIN_MSG_DESKTOP_SESSION_NOT_READY_PASSWORD_EMPTY: &str = - "Desktop session not ready, password empty"; -pub const LOGIN_MSG_DESKTOP_SESSION_NOT_READY_PASSWORD_WRONG: &str = - "Desktop session not ready, password wrong"; pub const LOGIN_MSG_PASSWORD_EMPTY: &str = "Empty Password"; pub const LOGIN_MSG_PASSWORD_WRONG: &str = "Wrong Password"; pub const LOGIN_MSG_2FA_WRONG: &str = "Wrong 2FA Code"; @@ -2739,6 +2727,16 @@ impl LoginConfigHandler { } else { Bytes::new() }; + let os_login: MessageField = if self.conn_type == ConnType::TERMINAL { + Some(OSLogin { + username: os_username, + password: os_password, + ..Default::default() + }) + .into() + } else { + Default::default() + }; let mut lr = LoginRequest { username: pure_id, password: password.into(), @@ -2748,12 +2746,7 @@ impl LoginConfigHandler { option: self.get_option_message(true).into(), session_id: self.session_id, version: crate::VERSION.to_string(), - os_login: Some(OSLogin { - username: os_username, - password: os_password, - ..Default::default() - }) - .into(), + os_login, hwid, avatar, ..Default::default() @@ -3348,55 +3341,12 @@ struct LoginErrorMsgBox { lazy_static::lazy_static! { static ref LOGIN_ERROR_MAP: Arc> = { - use config::LINK_HEADLESS_LINUX_SUPPORT; let map = HashMap::from([(LOGIN_SCREEN_WAYLAND, LoginErrorMsgBox{ msgtype: "error", title: "Login Error", text: "Login screen using Wayland is not supported", link: "https://rustdesk.com/docs/en/manual/linux/#login-screen", try_again: true, - }), (LOGIN_MSG_DESKTOP_SESSION_NOT_READY, LoginErrorMsgBox{ - msgtype: "session-login", - title: "", - text: "", - link: "", - try_again: true, - }), (LOGIN_MSG_DESKTOP_XSESSION_FAILED, LoginErrorMsgBox{ - msgtype: "session-re-login", - title: "", - text: "", - link: "", - try_again: true, - }), (LOGIN_MSG_DESKTOP_SESSION_ANOTHER_USER, LoginErrorMsgBox{ - msgtype: "info-nocancel", - title: "another_user_login_title_tip", - text: "another_user_login_text_tip", - link: "", - try_again: false, - }), (LOGIN_MSG_DESKTOP_XORG_NOT_FOUND, LoginErrorMsgBox{ - msgtype: "info-nocancel", - title: "xorg_not_found_title_tip", - text: "xorg_not_found_text_tip", - link: LINK_HEADLESS_LINUX_SUPPORT, - try_again: true, - }), (LOGIN_MSG_DESKTOP_NO_DESKTOP, LoginErrorMsgBox{ - msgtype: "info-nocancel", - title: "no_desktop_title_tip", - text: "no_desktop_text_tip", - link: LINK_HEADLESS_LINUX_SUPPORT, - try_again: true, - }), (LOGIN_MSG_DESKTOP_SESSION_NOT_READY_PASSWORD_EMPTY, LoginErrorMsgBox{ - msgtype: "session-login-password", - title: "", - text: "", - link: "", - try_again: true, - }), (LOGIN_MSG_DESKTOP_SESSION_NOT_READY_PASSWORD_WRONG, LoginErrorMsgBox{ - msgtype: "session-login-re-password", - title: "", - text: "", - link: "", - try_again: true, }), (LOGIN_MSG_NO_PASSWORD_ACCESS, LoginErrorMsgBox{ msgtype: "wait-remote-accept-nook", title: "Prompt", @@ -3665,17 +3615,7 @@ pub async fn handle_hash( hasher.finalize()[..].into() }; - let is_terminal = lc.read().unwrap().conn_type.eq(&ConnType::TERMINAL); - let (os_username, os_password) = if is_terminal { - ("".to_owned(), "".to_owned()) - } else { - ( - lc.read().unwrap().get_option("os-username"), - lc.read().unwrap().get_option("os-password"), - ) - }; - - send_login(lc.clone(), os_username, os_password, password, peer).await; + send_login(lc.clone(), String::new(), String::new(), password, peer).await; lc.write().unwrap().hash = hash; true } diff --git a/src/common.rs b/src/common.rs index 09fa1b4ca..9b22cbca2 100644 --- a/src/common.rs +++ b/src/common.rs @@ -105,7 +105,7 @@ lazy_static::lazy_static! { // Is server logic running. The server code can invoked to run by the main process if --server is not running. static ref SERVER_RUNNING: Arc> = Default::default(); static ref IS_MAIN: bool = std::env::args().nth(1).map_or(true, |arg| !arg.starts_with("--")); - static ref IS_CM: bool = std::env::args().nth(1) == Some("--cm".to_owned()) || std::env::args().nth(1) == Some("--cm-no-ui".to_owned()); + static ref IS_CM: bool = std::env::args().nth(1) == Some("--cm".to_owned()); } pub struct SimpleCallOnReturn { diff --git a/src/core_main.rs b/src/core_main.rs index 3a190f114..9b3d76f0a 100644 --- a/src/core_main.rs +++ b/src/core_main.rs @@ -713,14 +713,6 @@ pub fn core_main() -> Option> { // call connection manager to establish connections // meanwhile, return true to call flutter window to show control panel crate::ui_interface::start_option_status_sync(); - } else if args[0] == "--cm-no-ui" { - #[cfg(feature = "flutter")] - #[cfg(not(any(target_os = "android", target_os = "ios")))] - { - crate::ui_interface::start_option_status_sync(); - crate::flutter::connection_manager::start_cm_no_ui(); - } - return None; } else if args[0] == "--whiteboard" { #[cfg(not(any(target_os = "android", target_os = "ios")))] { diff --git a/src/flutter.rs b/src/flutter.rs index 87c9c02af..1ed44ee49 100644 --- a/src/flutter.rs +++ b/src/flutter.rs @@ -1552,20 +1552,8 @@ pub mod connection_manager { } } - #[inline] #[cfg(not(any(target_os = "android", target_os = "ios")))] - pub fn start_cm_no_ui() { - start_listen_ipc(false); - } - - #[inline] - #[cfg(not(any(target_os = "android", target_os = "ios")))] - fn start_listen_ipc_thread() { - start_listen_ipc(true); - } - - #[cfg(not(any(target_os = "android", target_os = "ios")))] - fn start_listen_ipc(new_thread: bool) { + fn start_listen_ipc() { use crate::ui_cm_interface::{start_ipc, ConnectionManager}; #[cfg(target_os = "linux")] @@ -1574,17 +1562,13 @@ pub mod connection_manager { let cm = ConnectionManager { ui_handler: FlutterHandler {}, }; - if new_thread { - std::thread::spawn(move || start_ipc(cm)); - } else { - start_ipc(cm); - } + std::thread::spawn(move || start_ipc(cm)); } #[inline] pub fn cm_init() { #[cfg(not(any(target_os = "android", target_os = "ios")))] - start_listen_ipc_thread(); + start_listen_ipc(); } #[cfg(target_os = "android")] diff --git a/src/flutter_ffi.rs b/src/flutter_ffi.rs index 091fcef25..f840ed282 100644 --- a/src/flutter_ffi.rs +++ b/src/flutter_ffi.rs @@ -962,14 +962,6 @@ pub fn main_get_error() -> String { get_error() } -pub fn main_show_option(_key: String) -> SyncReturn { - #[cfg(target_os = "linux")] - if _key.eq(config::keys::OPTION_ALLOW_LINUX_HEADLESS) { - return SyncReturn(true); - } - SyncReturn(false) -} - pub fn main_set_option(key: String, value: String) { #[cfg(target_os = "android")] { diff --git a/src/lang/ar.rs b/src/lang/ar.rs index 61044da3e..04d982ba9 100644 --- a/src/lang/ar.rs +++ b/src/lang/ar.rs @@ -464,17 +464,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("identical_file_tip", "هذا الملف مطابق لملف موجود عن القرين."), ("show_monitors_tip", "عرض الشاشات في شريط الادوات"), ("View Mode", "وضع العرض"), - ("login_linux_tip", "تحتاج الى تسجيل الدخول حساب لينكس البعيد وتفعيل جلسة سطح مكتب X"), ("verify_rustdesk_password_tip", "تحقق من كلمة مرور RustDesk"), - ("remember_account_tip", "تذكر هذا الحساب"), - ("os_account_desk_tip", "هذا الحساب مستخدم لتسجيل الدخول الى سطح المكتب البعيد وتفعيل الجلسة"), - ("OS Account", "حساب نظام التشغيل"), - ("another_user_login_title_tip", "مستخدم اخر مسجل دخول حاليا"), - ("another_user_login_text_tip", "قطع الاتصال"), - ("xorg_not_found_title_tip", "Xorg غير موجود"), - ("xorg_not_found_text_tip", "الرجاء تثبيت Xorg"), - ("no_desktop_title_tip", "لا يتوفر سطح مكتب"), - ("no_desktop_text_tip", "الرجاء تثبيت سطح مكتب GNOME"), ("No need to elevate", "لا حاجة للارتقاء"), ("System Sound", "صوت النظام"), ("Default", "الافتراضي"), diff --git a/src/lang/be.rs b/src/lang/be.rs index 1159dac84..6d2c93882 100644 --- a/src/lang/be.rs +++ b/src/lang/be.rs @@ -464,17 +464,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("identical_file_tip", "Файл ідэнтычны файлу абанента"), ("show_monitors_tip", "Паказваць маніторы на панэлі інструментаў"), ("View Mode", "Рэжым прагляду"), - ("login_linux_tip", "Каб уключыць сеанс працоўнага стала X, трэба ўвайсці ў аддалены ўліковы запіс Linux."), ("verify_rustdesk_password_tip", "Пацвердзіць пароль RustDesk"), - ("remember_account_tip", "Запомніць гэты ўліковы запіс"), - ("os_account_desk_tip", "Гэты ўліковы запіс выкарыстоўваецца для ўваходу ў аддаленую аперацыйную сістэму і ўключэння сеанса працоўнага стала ў рэжыме headless."), - ("OS Account", "Акаўнт АС"), - ("another_user_login_title_tip", "Іншы карыстальнік ужо ўвайшоў у сістэму"), - ("another_user_login_text_tip", "Адключыць"), - ("xorg_not_found_title_tip", "Xorg не знойдзены"), - ("xorg_not_found_text_tip", "Усталюйце Xorg"), - ("no_desktop_title_tip", "Няма даступных працоўных сталоў"), - ("no_desktop_text_tip", "Усталюйце GNOME Desktop"), ("No need to elevate", "Павышэнне правоў не патрабуецца"), ("System Sound", "Сістэмны гук"), ("Default", "Стандартна"), diff --git a/src/lang/bg.rs b/src/lang/bg.rs index 568ec085e..83c98545e 100644 --- a/src/lang/bg.rs +++ b/src/lang/bg.rs @@ -464,17 +464,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("identical_file_tip", "Файлът съвпада с този от другата страна."), ("show_monitors_tip", "Показване на мониторите в лентата с инструменти"), ("View Mode", "Режим на изглед"), - ("login_linux_tip", "Трябва да влезете в отдалечен Linux акаунт, за да активирате X сесия на работния плот"), ("verify_rustdesk_password_tip", "Проверете RustDesk паролата"), - ("remember_account_tip", "Запомнете този акаунт"), - ("os_account_desk_tip", "Този акаунт се използва за влизане в отдалечената операционна система и позволява на десктоп сесия без моинитор"), - ("OS Account", "Профил в операционната система"), - ("another_user_login_title_tip", "Друг потребител вече е влязъл"), - ("another_user_login_text_tip", "Прекъснете връзката"), - ("xorg_not_found_title_tip", "Xorg не е намерен"), - ("xorg_not_found_text_tip", "Моля, инсталирайте Xorg"), - ("no_desktop_title_tip", "Няма наличен работен плот"), - ("no_desktop_text_tip", "Моля, инсталирайте работен плот GNOME"), ("No need to elevate", "Няма нужда за повишаване на права"), ("System Sound", "Системен звук"), ("Default", "По подразбиране"), diff --git a/src/lang/ca.rs b/src/lang/ca.rs index 3bc9c6375..9b0ebb085 100644 --- a/src/lang/ca.rs +++ b/src/lang/ca.rs @@ -464,17 +464,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("identical_file_tip", "Aquest fitxer és idèntic al del client."), ("show_monitors_tip", "Mostra les pantalles a la barra d'eines"), ("View Mode", "Mode espectador"), - ("login_linux_tip", "És necessari que inicieu prèviament sessió amb un entorn d'escriptori x11 habilitat"), ("verify_rustdesk_password_tip", "Verifica la contrasenya del RustDesk"), - ("remember_account_tip", "Recorda aquest compte"), - ("os_account_desk_tip", "S'utilitza aquest compte per iniciar la sessió al sistema remot i habilitar el mode sense cap pantalla connectada"), - ("OS Account", "Compte d'usuari"), - ("another_user_login_title_tip", "Altre usuari ha iniciat ja una sessió"), - ("another_user_login_text_tip", "Desconnecta"), - ("xorg_not_found_title_tip", "No s'ha trobat l'entorn Xorg"), - ("xorg_not_found_text_tip", "Instal·leu el Xorg"), - ("no_desktop_title_tip", "Cap escriptori disponible"), - ("no_desktop_text_tip", "Instal·leu l'entorn d'escriptori GNOME"), ("No need to elevate", "No calen permisos ampliats"), ("System Sound", "So del sistema"), ("Default", "per defecte"), diff --git a/src/lang/cn.rs b/src/lang/cn.rs index b64824731..191c25908 100644 --- a/src/lang/cn.rs +++ b/src/lang/cn.rs @@ -464,17 +464,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("identical_file_tip", "此文件与对方的一致"), ("show_monitors_tip", "在工具栏上显示监视器"), ("View Mode", "浏览模式"), - ("login_linux_tip", "登录被控端的 Linux 账户,才能启用 X 桌面"), ("verify_rustdesk_password_tip", "验证 RustDesk 密码"), - ("remember_account_tip", "记住此账户"), - ("os_account_desk_tip", "在无显示器的环境下,此账户用于登录被控系统,并启用桌面"), - ("OS Account", "系统账户"), - ("another_user_login_title_tip", "其他用户已登录"), - ("another_user_login_text_tip", "断开"), - ("xorg_not_found_title_tip", "Xorg 未安装"), - ("xorg_not_found_text_tip", "请安装 Xorg"), - ("no_desktop_title_tip", "desktop 未安装"), - ("no_desktop_text_tip", "请安装 desktop"), ("No need to elevate", "无需提升权限"), ("System Sound", "系统音频"), ("Default", "默认"), diff --git a/src/lang/cs.rs b/src/lang/cs.rs index fd32948ad..1d214e024 100644 --- a/src/lang/cs.rs +++ b/src/lang/cs.rs @@ -464,17 +464,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("identical_file_tip", "Tento soubor je totožný se souborem partnera."), ("show_monitors_tip", "Zobrazit monitory na panelu nástrojů"), ("View Mode", "Režim zobrazení"), - ("login_linux_tip", "Chcete-li povolit relaci plochy X, musíte se přihlásit ke vzdálenému účtu systému Linux."), ("verify_rustdesk_password_tip", "Ověření hesla RustDesk"), - ("remember_account_tip", "Zapamatovat si tento účet"), - ("os_account_desk_tip", "Tento účet se používá k přihlášení do vzdáleného operačního systému a k povolení relace plochy v režimu headless."), - ("OS Account", "Účet operačního systému"), - ("another_user_login_title_tip", "Další uživatel je již přihlášen"), - ("another_user_login_text_tip", "Odpojit"), - ("xorg_not_found_title_tip", "Xorg nebyl nalezen"), - ("xorg_not_found_text_tip", "Prosím, nainstalujte Xorg"), - ("no_desktop_title_tip", "Není k dispozici žádná plocha"), - ("no_desktop_text_tip", "Nainstalujte si prosím prostředí GNOME"), ("No need to elevate", "Není třeba navýšení"), ("System Sound", "Systémový zvuk"), ("Default", "Výchozí"), diff --git a/src/lang/da.rs b/src/lang/da.rs index 3edbb9d2d..4cf509e98 100644 --- a/src/lang/da.rs +++ b/src/lang/da.rs @@ -464,17 +464,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("identical_file_tip", "Denne fil er identisk med modpartens."), ("show_monitors_tip", "Vis skærme i værktøjsbjælken"), ("View Mode", "Visningstilstand"), - ("login_linux_tip", "Du skal logge på en fjernstyret Linux konto for at aktivere en X skrivebordssession"), ("verify_rustdesk_password_tip", "Bekræft RustDesk adgangskode"), - ("remember_account_tip", "Husk denne konto"), - ("os_account_desk_tip", "Denne konto benyttes til at logge på fjernsystemet, og aktivere skrivebordssessionen i hovedløs tilstand"), - ("OS Account", "Styresystem konto"), - ("another_user_login_title_tip", "En anden bruger er allerede logget ind"), - ("another_user_login_text_tip", "Frakobl"), - ("xorg_not_found_title_tip", "Xorg ikke fundet"), - ("xorg_not_found_text_tip", "Installér venlist Xorg"), - ("no_desktop_title_tip", "Intet skrivebordsmiljø er tilgængeligt"), - ("no_desktop_text_tip", "Installér venligst GNOME skrivebordet"), ("No need to elevate", "Ingen grund til at elevere"), ("System Sound", "Systemlyd"), ("Default", "Standard"), diff --git a/src/lang/de.rs b/src/lang/de.rs index dcddb94fa..833be3fca 100644 --- a/src/lang/de.rs +++ b/src/lang/de.rs @@ -464,17 +464,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("identical_file_tip", "Diese Datei ist identisch mit der Datei der Gegenstelle."), ("show_monitors_tip", "Bildschirme in der Symbolleiste anzeigen"), ("View Mode", "Ansichtsmodus"), - ("login_linux_tip", "Sie müssen sich an einem entfernten Linux-Konto anmelden, um eine X-Desktop-Sitzung zu eröffnen."), ("verify_rustdesk_password_tip", "RustDesk-Passwort bestätigen"), - ("remember_account_tip", "Dieses Konto merken"), - ("os_account_desk_tip", "Dieses Konto wird verwendet, um sich beim entfernten Betriebssystem anzumelden und die Desktop-Sitzung im Headless-Modus zu aktivieren."), - ("OS Account", "Betriebssystem-Konto"), - ("another_user_login_title_tip", "Ein anderer Benutzer ist bereits angemeldet."), - ("another_user_login_text_tip", "Trennen"), - ("xorg_not_found_title_tip", "Xorg nicht gefunden."), - ("xorg_not_found_text_tip", "Bitte installieren Sie Xorg."), - ("no_desktop_title_tip", "Es ist keine Desktopumgebung verfügbar."), - ("no_desktop_text_tip", "Bitte installieren Sie den GNOME-Desktop."), ("No need to elevate", "Erhöhung der Rechte nicht erforderlich"), ("System Sound", "Systemsound"), ("Default", "Systemstandard"), diff --git a/src/lang/el.rs b/src/lang/el.rs index 28088a6bd..cc7591ea3 100644 --- a/src/lang/el.rs +++ b/src/lang/el.rs @@ -464,17 +464,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("identical_file_tip", "Αυτό το αρχείο είναι πανομοιότυπο με αυτό του απομακρυσμένου σταθμού."), ("show_monitors_tip", "Εμφάνιση οθονών στη γραμμή εργαλείων"), ("View Mode", "Λειτουργία προβολής"), - ("login_linux_tip", "Πρέπει να συνδεθείτε σε έναν απομακρυσμένο λογαριασμό Linux για να ενεργοποιήσετε μια συνεδρία επιφάνειας εργασίας X"), ("verify_rustdesk_password_tip", "Επιβεβαιώστε τον κωδικό του RustDesk"), - ("remember_account_tip", "Απομνημόνευση αυτού του λογαριασμού"), - ("os_account_desk_tip", "Αυτός ο λογαριασμός χρησιμοποιείται για σύνδεση στο απομακρυσμένο λειτουργικό σύστημα και ενεργοποίηση της συνεδρίας επιφάνειας εργασίας σε headless"), - ("OS Account", "Λογαριασμός λειτουργικού συστήματος"), - ("another_user_login_title_tip", "Υπάρχει ήδη άλλος συνδεδεμένος χρήστης"), - ("another_user_login_text_tip", "Αποσύνδεση"), - ("xorg_not_found_title_tip", "Δεν βρέθηκε το Xorg"), - ("xorg_not_found_text_tip", "Παρακαλώ εγκαταστήστε το Xorg"), - ("no_desktop_title_tip", "Δεν υπάρχει διαθέσιμο περιβάλλον επιφάνειας εργασίας"), - ("no_desktop_text_tip", "Παρακαλώ εγκαταστήστε το περιβάλλον GNOME"), ("No need to elevate", "Δεν χρειάζεται ανύψωση"), ("System Sound", "Ήχος συστήματος"), ("Default", "Προκαθορισμένο"), diff --git a/src/lang/en.rs b/src/lang/en.rs index fcd68a300..227a7e29e 100644 --- a/src/lang/en.rs +++ b/src/lang/en.rs @@ -155,17 +155,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("identical_file_tip", "This file is identical with the peer's one."), ("show_monitors_tip", "Show monitors in toolbar"), ("View Mode", "View mode"), - ("login_linux_tip", "You need to login to remote Linux account to enable a X desktop session"), ("verify_rustdesk_password_tip", "Verify RustDesk password"), - ("remember_account_tip", "Remember this account"), - ("os_account_desk_tip", "This account is used to login the remote OS and enable the desktop session in headless"), - ("OS Account", "OS account"), - ("another_user_login_title_tip", "Another user already logged in"), - ("another_user_login_text_tip", "Disconnect"), - ("xorg_not_found_title_tip", "Xorg not found"), - ("xorg_not_found_text_tip", "Please install Xorg"), - ("no_desktop_title_tip", "No desktop environment is available"), - ("no_desktop_text_tip", "Please install GNOME desktop"), ("System Sound", "System sound"), ("Copy Fingerprint", "Copy fingerprint"), ("no fingerprints", "No fingerprints"), diff --git a/src/lang/eo.rs b/src/lang/eo.rs index 8ff0c573e..48a49f96d 100644 --- a/src/lang/eo.rs +++ b/src/lang/eo.rs @@ -464,17 +464,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("identical_file_tip", "Ĉi tiu dosiero estas identa kun tiu de la samulo."), ("show_monitors_tip", "Montri monitorojn en la ilobreto"), ("View Mode", "Rigarda reĝimo"), - ("login_linux_tip", "Vi devas ensaluti al la fora Linuksa konto por ebligi X-labortablan sesion"), ("verify_rustdesk_password_tip", "Kontroli RustDesk-pasvorton"), - ("remember_account_tip", "Memori ĉi tiun konton"), - ("os_account_desk_tip", "Ĉi tiu konto estas uzata por ensaluti al la fora operaciumo kaj ebligi la labortablan sesion en senekrana reĝimo"), - ("OS Account", "Konto de operaciumo"), - ("another_user_login_title_tip", "Alia uzanto jam ensalutis"), - ("another_user_login_text_tip", "Malkonekti"), - ("xorg_not_found_title_tip", "Xorg ne trovita"), - ("xorg_not_found_text_tip", "Bonvolu instali Xorg"), - ("no_desktop_title_tip", "Neniu labortabla medio disponeblas"), - ("no_desktop_text_tip", "Bonvolu instali GNOME-labortablon"), ("No need to elevate", "Ne necesas altigi"), ("System Sound", "Sistema sono"), ("Default", "Implicita"), diff --git a/src/lang/es.rs b/src/lang/es.rs index 43eefdbdb..b481fce7f 100644 --- a/src/lang/es.rs +++ b/src/lang/es.rs @@ -464,17 +464,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("identical_file_tip", "Este archivo es idéntico al del par."), ("show_monitors_tip", "Mostrar monitores en la barra de herramientas"), ("View Mode", "Modo Vista"), - ("login_linux_tip", "Necesitas iniciar sesión con la cueneta del Linux remoto para activar una sesión de escritorio X"), ("verify_rustdesk_password_tip", "Verificar la contraseña de RustDesk"), - ("remember_account_tip", "Recordar esta cuenta"), - ("os_account_desk_tip", "Esta cueneta se usa para iniciar sesión en el sistema operativo remoto y habilitar la sesión de escritorio en headless."), - ("OS Account", "Cuenta del SO"), - ("another_user_login_title_tip", "Otro usuario ya ha iniciado sesión"), - ("another_user_login_text_tip", "Desconectar"), - ("xorg_not_found_title_tip", "Xorg no hallado"), - ("xorg_not_found_text_tip", "Por favor, instala Xorg"), - ("no_desktop_title_tip", "No hay escritorio disponible"), - ("no_desktop_text_tip", "Por favor, instala GNOME Desktop"), ("No need to elevate", "No es necesario elevar privilegios"), ("System Sound", "Sonido del Sistema"), ("Default", "Predeterminado"), diff --git a/src/lang/et.rs b/src/lang/et.rs index a4bbf543c..d916df419 100644 --- a/src/lang/et.rs +++ b/src/lang/et.rs @@ -464,17 +464,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("identical_file_tip", "See fail on partneri omaga identne."), ("show_monitors_tip", "Kuva kuvarid tööriistaribal"), ("View Mode", "Kuvarežiim"), - ("login_linux_tip", "X-töölaua seansi lubamiseks pead sisse logima Linuxi kaugkontosse."), ("verify_rustdesk_password_tip", "Kinnita RustDeski parool"), - ("remember_account_tip", "Jäta see konto meelde"), - ("os_account_desk_tip", "Seda kontot kasutatakse kaug-opsüsteemi sisselogimiseks ja töölaua seansi lubamiseks headless-režiimis."), - ("OS Account", "Opsüsteemi konto"), - ("another_user_login_title_tip", "Teine kasutaja on juba sisse logitud"), - ("another_user_login_text_tip", "Ühenda lahti"), - ("xorg_not_found_title_tip", "Xorg-i ei leitud"), - ("xorg_not_found_text_tip", "Palun paigalda Xorg"), - ("no_desktop_title_tip", "Töölaud pole saadaval"), - ("no_desktop_text_tip", "Palun paigalda GNOME Desktop"), ("No need to elevate", "Kõrgendamine pole vajalik"), ("System Sound", "Süsteemiheli"), ("Default", "Vaikimisi"), diff --git a/src/lang/eu.rs b/src/lang/eu.rs index 338c3dfbe..e74f3a285 100644 --- a/src/lang/eu.rs +++ b/src/lang/eu.rs @@ -464,17 +464,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("identical_file_tip", "Fitxategi hau parekidearen berdina da."), ("show_monitors_tip", "Erakutsi monitoreak tresna-barran"), ("View Mode", "Ikuspen modua"), - ("login_linux_tip", "Urruneko Linux kontu batera hasi behar duzu saioa X mahaigain saio bat gaitzeko"), ("verify_rustdesk_password_tip", "Berretsi RustDesk pasahitza"), - ("remember_account_tip", "Gogoratu kontu hau"), - ("os_account_desk_tip", "Kontu hau bururik gabe urruneko SE hasi eta mahaigaineko saioa gaitzeko erabiltzen da"), - ("OS Account", "SE kontua"), - ("another_user_login_title_tip", "Beste erabiltzaile batek saioa hasi du dagoeneko"), - ("another_user_login_text_tip", "Deskonektatu"), - ("xorg_not_found_title_tip", "Ez da Xorg aurkitu"), - ("xorg_not_found_text_tip", "Mesedez, instalatu ezazu Xorg"), - ("no_desktop_title_tip", "Ez dago mahaigainik eskuragarri"), - ("no_desktop_text_tip", "Mesedez, instalatu ezazu GNOME Desktop"), ("No need to elevate", "Ez da beharrezkoa pribilegioen maila igotzea"), ("System Sound", "Sistemaren soinua"), ("Default", "Lehenetsia"), diff --git a/src/lang/fa.rs b/src/lang/fa.rs index f905d4b76..c9fd7b45e 100644 --- a/src/lang/fa.rs +++ b/src/lang/fa.rs @@ -464,17 +464,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("identical_file_tip", "این فایل با فایل همتا یکسان است."), ("show_monitors_tip", "نمایش مانیتورها در نوار ابزار"), ("View Mode", "حالت مشاهده"), - ("login_linux_tip", "برای فعال کردن دسکتاپ X، باید به حساب لینوکس راه دور وارد شوید"), ("verify_rustdesk_password_tip", "رمز عبور RustDesk را تأیید کنید"), - ("remember_account_tip", "این حساب را به خاطر بسپارید"), - ("os_account_desk_tip", "این حساب برای ورود به سیستم عامل راه دور و فعال کردن جلسه دسکتاپ در هدلس استفاده می شود"), - ("OS Account", "حساب کاربری سیستم عامل"), - ("another_user_login_title_tip", "کاربر دیگری قبلاً وارد شده است"), - ("another_user_login_text_tip", "قطع شدن"), - ("xorg_not_found_title_tip", "پیدا نشد Xorg"), - ("xorg_not_found_text_tip", "لطفا Xorg را نصب کنید"), - ("no_desktop_title_tip", "هیچ دسکتاپی در دسترس نیست"), - ("no_desktop_text_tip", "لطفا دسکتاپ گنوم را نصب کنید"), ("No need to elevate", "نیازی به ارتقاء نیست"), ("System Sound", "صدای سیستم"), ("Default", "پیش فرض"), diff --git a/src/lang/fi.rs b/src/lang/fi.rs index c9b6442e3..9cb8e8de1 100644 --- a/src/lang/fi.rs +++ b/src/lang/fi.rs @@ -464,17 +464,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("identical_file_tip", "Saman niminen tiedosto on jo olemassa"), ("show_monitors_tip", "Näytä kaikki käytettävissä olevat näytöt"), ("View Mode", "Näkymätila"), - ("login_linux_tip", "Kirjaudu sisään Linux käyttäjätunnuksellasi"), ("verify_rustdesk_password_tip", "Vahvista RustDesk salasanasi kirjautumista varten"), - ("remember_account_tip", "Muista tilini kirjautumista varten"), - ("os_account_desk_tip", "Käytä käyttöjärjestelmän käyttäjätiliä kirjautumiseen"), - ("OS Account", "Käyttöjärjestelmän tili"), - ("another_user_login_title_tip", "Toinen käyttäjä on kirjautunut sisään"), - ("another_user_login_text_tip", "Etäistunto keskeytetään, koska toinen käyttäjä on ottanut hallinnan."), - ("xorg_not_found_title_tip", "Xorg ei löydy"), - ("xorg_not_found_text_tip", "X11 palvelinta ei löydetty. Vaihda Xorg ympäristöön jatkaaksesi."), - ("no_desktop_title_tip", "Työpöytää ei havaittu"), - ("no_desktop_text_tip", "Työpöytäympäristöä ei löydy. Asenna esimerkiksi GNOME tai XFCE."), ("No need to elevate", "Oikeuksien korotusta ei tarvita"), ("System Sound", "Järjestelmän ääni"), ("Default", "Oletus"), diff --git a/src/lang/fr.rs b/src/lang/fr.rs index cb78c5ff5..5b3204053 100644 --- a/src/lang/fr.rs +++ b/src/lang/fr.rs @@ -464,17 +464,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("identical_file_tip", "Ce fichier est identique à celui sur l’appareil distant."), ("show_monitors_tip", "Afficher les écrans dans la barre d’outils"), ("View Mode", "Mode vue"), - ("login_linux_tip", "Vous devez vous connecter au compte Linux distant pour établir une session de bureau X"), ("verify_rustdesk_password_tip", "Vérifier le mot de passe RustDesk"), - ("remember_account_tip", "Se souvenir de ce compte"), - ("os_account_desk_tip", "Ce compte est utilisé pour se connecter au système d’exploitation distant et activer la session de bureau en mode sans affichage"), - ("OS Account", "Compte du système d’exploitation"), - ("another_user_login_title_tip", "Un autre utilisateur est déjà connecté"), - ("another_user_login_text_tip", "Déconnecter"), - ("xorg_not_found_title_tip", "Xorg introuvable"), - ("xorg_not_found_text_tip", "Veuillez installer Xorg"), - ("no_desktop_title_tip", "Aucun environnement de bureau n’est disponible"), - ("no_desktop_text_tip", "Veuillez installer l’environnement de bureau GNOME"), ("No need to elevate", "Élever les privilèges n’est pas nécessaire"), ("System Sound", "Son système"), ("Default", "Défaut"), diff --git a/src/lang/ge.rs b/src/lang/ge.rs index d1c76c69f..988570095 100644 --- a/src/lang/ge.rs +++ b/src/lang/ge.rs @@ -464,17 +464,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("identical_file_tip", "ფაილი იდენტურია დისტანციურ კვანძზე არსებული ფაილის"), ("show_monitors_tip", "მონიტორების ჩვენება ხელსაწყოთა პანელზე"), ("View Mode", "ნახვის რეჟიმი"), - ("login_linux_tip", "X სამუშაო მაგიდის სესიის ჩასართავად, საჭიროა დისტანციურ Linux ანგარიშში შესვლა."), ("verify_rustdesk_password_tip", "დაადასტურეთ RustDesk-ის პაროლი"), - ("remember_account_tip", "დაიმახსოვრეთ ეს ანგარიში"), - ("os_account_desk_tip", "ეს ანგარიში გამოიყენება დისტანციურ ოპერაციულ სისტემაში შესასვლელად და headless რეჟიმში სამუშაო მაგიდის სესიის ჩასართავად."), - ("OS Account", "ოპერაციული სისტემის ანგარიში"), - ("another_user_login_title_tip", "სხვა მომხმარებელი უკვე შესულია სისტემაში"), - ("another_user_login_text_tip", "გათიშვა"), - ("xorg_not_found_title_tip", "Xorg ვერ მოიძებნა"), - ("xorg_not_found_text_tip", "დააინსტალირეთ Xorg"), - ("no_desktop_title_tip", "სამუშაო მაგიდა არ არის ხელმისაწვდომი"), - ("no_desktop_text_tip", "დააინსტალირეთ GNOME Desktop"), ("No need to elevate", "უფლებების აწევა არ არის საჭირო"), ("System Sound", "სისტემური ხმა"), ("Default", "ნაგულისხმევი"), diff --git a/src/lang/gu.rs b/src/lang/gu.rs index 8efa89e31..7825c5204 100644 --- a/src/lang/gu.rs +++ b/src/lang/gu.rs @@ -464,17 +464,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("identical_file_tip", "આ ફાઇલ પહેલેથી જ અસ્તિત્વમાં છે."), ("show_monitors_tip", "ટૂલબારમાં મોનિટર બતાવો"), ("View Mode", "વ્યુ મોડ"), - ("login_linux_tip", "રિમોટ Linux સત્ર માટે તમારે લોગિન કરવું પડશે"), ("verify_rustdesk_password_tip", "RustDesk પાસવર્ડ ચકાસો"), - ("remember_account_tip", "આ ખાતું યાદ રાખો"), - ("os_account_desk_tip", "એક્સેસ માટે OS ખાતાનો ઉપયોગ કરો"), - ("OS Account", "OS ખાતું"), - ("another_user_login_title_tip", "બીજો યુઝર પહેલેથી લોગિન છે"), - ("another_user_login_text_tip", "ડિસ્કનેક્ટ કરો અને ફરી પ્રયાસ કરો"), - ("xorg_not_found_title_tip", "Xorg મળ્યું નથી"), - ("xorg_not_found_text_tip", "કૃપા કરીને Xorg ઇન્સ્ટોલ કરો"), - ("no_desktop_title_tip", "કોઈ ડેસ્કટોપ ઉપલબ્ધ નથી"), - ("no_desktop_text_tip", "કૃપા કરીને Linux ડેસ્કટોપ ઇન્સ્ટોલ કરો"), ("No need to elevate", "એલિવેટ કરવાની જરૂર નથી"), ("System Sound", "સિસ્ટમ સાઉન્ડ"), ("Default", "ડિફોલ્ટ"), diff --git a/src/lang/he.rs b/src/lang/he.rs index 643359526..1183a3cbb 100644 --- a/src/lang/he.rs +++ b/src/lang/he.rs @@ -464,17 +464,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("identical_file_tip", "קובץ זה זהה לקובץ שבצד העמית."), ("show_monitors_tip", "הצג מסכים בסרגל כלים"), ("View Mode", "מצב תצוגה"), - ("login_linux_tip", "עליך להתחבר לחשבון Linux מרוחק כדי לאפשר פעילות שולחן עבודה X"), ("verify_rustdesk_password_tip", "אמת סיסמת RustDesk"), - ("remember_account_tip", "זכור חשבון זה"), - ("os_account_desk_tip", "חשבון זה משמש להתחברות למערכת ההפעלה המרוחקת ולהפעלת שולחן עבודה במצב לא מקוון"), - ("OS Account", "חשבון מערכת הפעלה"), - ("another_user_login_title_tip", "משתמש אחר כבר התחבר"), - ("another_user_login_text_tip", "נתק"), - ("xorg_not_found_title_tip", "Xorg לא נמצא"), - ("xorg_not_found_text_tip", "אנא התקן Xorg"), - ("no_desktop_title_tip", "אין שולחן עבודה זמין"), - ("no_desktop_text_tip", "אנא התקן שולחן עבודה GNOME"), ("No need to elevate", "אין צורך בהעלאת הרשאות"), ("System Sound", "צליל מערכת"), ("Default", "ברירת מחדל"), diff --git a/src/lang/hi.rs b/src/lang/hi.rs index 250a6c963..d73b381c0 100644 --- a/src/lang/hi.rs +++ b/src/lang/hi.rs @@ -464,17 +464,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("identical_file_tip", "यह फ़ाइल पहले से ही मौजूद है।"), ("show_monitors_tip", "टूलबार में मॉनिटर दिखाएं"), ("View Mode", "व्यू मोड"), - ("login_linux_tip", "रिमोट Linux सत्र शुरू करने के लिए आपको लॉगिन करना होगा"), ("verify_rustdesk_password_tip", "RustDesk पासवर्ड सत्यापित करें"), - ("remember_account_tip", "इस खाते को याद रखें"), - ("os_account_desk_tip", "रिमोट डेस्कटॉप को एक्सेस करने के लिए OS खाते का उपयोग करें"), - ("OS Account", "OS खाता"), - ("another_user_login_title_tip", "एक अन्य उपयोगकर्ता पहले से ही लॉगिन है"), - ("another_user_login_text_tip", "डिस्कनेक्ट करें और पुनः प्रयास करें"), - ("xorg_not_found_title_tip", "Xorg नहीं मिला"), - ("xorg_not_found_text_tip", "कृपया Xorg इंस्टॉल करें"), - ("no_desktop_title_tip", "कोई डेस्कटॉप उपलब्ध नहीं है"), - ("no_desktop_text_tip", "कृपया Linux डेस्कटॉप इंस्टॉल करें"), ("No need to elevate", "एलीवेट करने की आवश्यकता नहीं है"), ("System Sound", "सिस्टम साउंड"), ("Default", "डिफ़ॉल्ट"), diff --git a/src/lang/hr.rs b/src/lang/hr.rs index 46a559bc2..7a0f9d3cf 100644 --- a/src/lang/hr.rs +++ b/src/lang/hr.rs @@ -464,17 +464,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("identical_file_tip", "Ova je datoteka identična partnerskoj datoteci."), ("show_monitors_tip", "Prikažite monitore na alatnoj traci"), ("View Mode", "Način prikaza"), - ("login_linux_tip", "Da biste omogućili sesiju X radne površine, morate se prijaviti na udaljeni Linux račun."), ("verify_rustdesk_password_tip", "Provjera lozinke za RustDesk"), - ("remember_account_tip", "Zapamti ovaj račun"), - ("os_account_desk_tip", "Ovaj se račun koristi za prijavu na udaljeni operativni sustav i za omogućavanje sesije radne površine u bezglavom načinu rada."), - ("OS Account", "Račun operativnog sustava"), - ("another_user_login_title_tip", "Drugi korisnik je već prijavljen"), - ("another_user_login_text_tip", "Prekini vezu"), - ("xorg_not_found_title_tip", "Xorg nije pronađen"), - ("xorg_not_found_text_tip", "Molimo instalirajte Xorg"), - ("no_desktop_title_tip", "Nema dostupne radne površine"), - ("no_desktop_text_tip", "Molimo instalirajte GNOME"), ("No need to elevate", "Nije potrebno povećanje"), ("System Sound", "Zvuk sustava"), ("Default", "Zadano"), diff --git a/src/lang/hu.rs b/src/lang/hu.rs index 9e10eecb0..705dc867c 100644 --- a/src/lang/hu.rs +++ b/src/lang/hu.rs @@ -464,17 +464,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("identical_file_tip", "Ez a fájl megegyezik a távoli állomás fájljával."), ("show_monitors_tip", "Képernyők megjelenítése az eszköztáron"), ("View Mode", "Nézet mód"), - ("login_linux_tip", "Az X-asztal munkamenet megnyitásához be kell jelentkeznie egy távoli Linux-fiókba."), ("verify_rustdesk_password_tip", "RustDesk jelszó megerősítése"), - ("remember_account_tip", "Emlékezzen erre a fiókra"), - ("os_account_desk_tip", "Ezzel a fiókkal bejelentkezhet a távoli operációs rendszerbe, és aktiválhatja az asztali munkamenetet fej nélküli módban."), - ("OS Account", "OS fiók"), - ("another_user_login_title_tip", "Egy másik felhasználó már bejelentkezett."), - ("another_user_login_text_tip", "Különálló"), - ("xorg_not_found_title_tip", "Xorg nem található."), - ("xorg_not_found_text_tip", "Telepítse az Xorgot."), - ("no_desktop_title_tip", "Nem áll rendelkezésre asztali környezet."), - ("no_desktop_text_tip", "Telepítse a GNOME asztali környezetet."), ("No need to elevate", "Nem szükséges megemelni"), ("System Sound", "Rendszer hangok"), ("Default", "Alapértelmezett"), diff --git a/src/lang/id.rs b/src/lang/id.rs index ae313d69d..25c12040d 100644 --- a/src/lang/id.rs +++ b/src/lang/id.rs @@ -464,17 +464,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("identical_file_tip", "Data ini identik dengan milik rekan"), ("show_monitors_tip", "Tampilkan monitor di toolbar"), ("View Mode", "Mode Tampilan"), - ("login_linux_tip", "Anda harus masuk ke akun remote linux untuk mengaktifkan sesi X desktop"), ("verify_rustdesk_password_tip", "Verifikasi Kata Sandi RustDesk"), - ("remember_account_tip", "Ingat akun ini"), - ("os_account_desk_tip", "Akun ini digunakan untuk masuk ke sistem operasi remote dan mengaktifkan sesi desktop dalam mode tanpa tampilan (headless)"), - ("OS Account", "Akun OS"), - ("another_user_login_title_tip", "Akun ini sedang digunakan"), - ("another_user_login_text_tip", "Putuskan koneksi diperangkat lain"), - ("xorg_not_found_title_tip", "Xorg tidak ditemukan"), - ("xorg_not_found_text_tip", "Silahkan install Xorg"), - ("no_desktop_title_tip", "Desktop tidak tersedia"), - ("no_desktop_text_tip", "Silahkan install GNOME Desktop"), ("No need to elevate", "Tidak perlu elevasi"), ("System Sound", "Suara Sistem"), ("Default", "Default"), diff --git a/src/lang/it.rs b/src/lang/it.rs index 1cac8ccee..330e5577a 100644 --- a/src/lang/it.rs +++ b/src/lang/it.rs @@ -464,17 +464,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("identical_file_tip", "Questo file è identico a quello nel dispositivo remoto."), ("show_monitors_tip", "Visualizza schermi nella barra strumenti"), ("View Mode", "Modalità visualizzazione"), - ("login_linux_tip", "Accedi all'account Linux remoto"), ("verify_rustdesk_password_tip", "Conferma password RustDesk"), - ("remember_account_tip", "Ricorda questo account"), - ("os_account_desk_tip", "Questo account viene usato per accedere al sistema operativo remoto e attivare la sessione desktop in modalità non presidiata."), - ("OS Account", "Account sistema operativo"), - ("another_user_login_title_tip", "È già loggato un altro utente."), - ("another_user_login_text_tip", "Separato"), - ("xorg_not_found_title_tip", "Xorg non trovato."), - ("xorg_not_found_text_tip", "Installa Xorg."), - ("no_desktop_title_tip", "Non è presente alcun ambiente desktop disponibile."), - ("no_desktop_text_tip", "Installa il desktop GNOME."), ("No need to elevate", "Elevazione dei privilegi non richiesta"), ("System Sound", "Dispositivo audio sistema"), ("Default", "Predefinita"), diff --git a/src/lang/ja.rs b/src/lang/ja.rs index 30cedf355..f9ae7777e 100644 --- a/src/lang/ja.rs +++ b/src/lang/ja.rs @@ -464,17 +464,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("identical_file_tip", "このファイルはリモートコンピューターと同一です。"), ("show_monitors_tip", "ツールバーにディスプレイを表示する"), ("View Mode", "表示モード"), - ("login_linux_tip", "X デスクトップのセッションにログインするには、リモートコンピューターのLinuxアカウントにログインする必要があります。"), ("verify_rustdesk_password_tip", "RustDesk のパスワードを確認する"), - ("remember_account_tip", "このアカウントを記憶する"), - ("os_account_desk_tip", "このアカウントは、リモートコンピューターの OS にログインし、ヘッドレスでセッションを有効化するために使用されます。"), - ("OS Account", "OS のアカウント"), - ("another_user_login_title_tip", "他のユーザーがすでにログインしています"), - ("another_user_login_text_tip", "切断しました"), - ("xorg_not_found_title_tip", "Xorg サーバーが見つかりませんでした。"), - ("xorg_not_found_text_tip", "Xorg をインストールしてください"), - ("no_desktop_title_tip", "デスクトップ環境が見つかりませんでした。"), - ("no_desktop_text_tip", "GNOME デスクトップ環境をインストールしてください"), ("No need to elevate", "権限昇格の必要はありません"), ("System Sound", "システム音声"), ("Default", "既定"), diff --git a/src/lang/ko.rs b/src/lang/ko.rs index ca23c65ac..f7da53b3f 100644 --- a/src/lang/ko.rs +++ b/src/lang/ko.rs @@ -464,17 +464,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("identical_file_tip", "이 파일은 상대방의 파일과 일치합니다."), ("show_monitors_tip", "도구 모음에 모니터 표시"), ("View Mode", "보기 모드"), - ("login_linux_tip", "X 데스크탑을 활성화하려면 제어되는 터미널의 Linux 계정에 로그인하세요"), ("verify_rustdesk_password_tip", "RustDesk 비밀번호 확인"), - ("remember_account_tip", "이 계정 기억하기"), - ("os_account_desk_tip", "이 계정은 원격 OS에 로그인하고 헤드리스에서 데스크탑 세션을 활성화하는 데 사용됩니다."), - ("OS Account", "OS 계정"), - ("another_user_login_title_tip", "다른 사용자가 이미 로그인했습니다"), - ("another_user_login_text_tip", "연결 끊기"), - ("xorg_not_found_title_tip", "Xorg를 찾을 수 없습니다"), - ("xorg_not_found_text_tip", "Xorg를 설치해 주세요"), - ("no_desktop_title_tip", "사용 가능한 데스크탑 환경이 없습니다"), - ("no_desktop_text_tip", "GNOME 데스크탑을 설치해 주세요"), ("No need to elevate", "권한 상승이 필요없습니다"), ("System Sound", "시스템 소리"), ("Default", "기본"), diff --git a/src/lang/kz.rs b/src/lang/kz.rs index a194ed19f..89121acca 100644 --- a/src/lang/kz.rs +++ b/src/lang/kz.rs @@ -464,17 +464,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("identical_file_tip", "Бұл файыл пирдікімен бірдей."), ("show_monitors_tip", "Мониторларды құралдар тақтасында көрсету"), ("View Mode", "Көру модасы"), - ("login_linux_tip", "X жұмыс үстелі сешін іске қосу үшін қашықтағы Linux есепкісіне кіруіңіз керек"), ("verify_rustdesk_password_tip", "RustDesk құпия сөзін тексеру"), - ("remember_account_tip", "Бұл есепкіні есте сақтау"), - ("os_account_desk_tip", "Бұл есепкі қашықтағы OS-қа кіру және headless режимде жұмыс үстелі сешін іске қосу үшін қолданылады"), - ("OS Account", "OS есепкісі"), - ("another_user_login_title_tip", "Басқа қолданушы әлдеқашан кіріп қойған"), - ("another_user_login_text_tip", "Ажырату"), - ("xorg_not_found_title_tip", "Xorg табылмады"), - ("xorg_not_found_text_tip", "Xorg орнатуды өтінеміз"), - ("no_desktop_title_tip", "Жұмыс үстелі ортасы қолжетімсіз"), - ("no_desktop_text_tip", "GNOME жұмыс үстелін орнатуды өтінеміз"), ("No need to elevate", "Артықшылықты көтерудің қажеті жоқ"), ("System Sound", "Жүйе дыбысы"), ("Default", "Әдепкі"), diff --git a/src/lang/lt.rs b/src/lang/lt.rs index 4a638b697..eb19f21c2 100644 --- a/src/lang/lt.rs +++ b/src/lang/lt.rs @@ -464,17 +464,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("identical_file_tip", "Failas yra identiškas nuotoliniame kompiuteryje esančiam failui."), ("show_monitors_tip", "Rodyti monitorius įrankių juostoje"), ("View Mode", "Peržiūros režimas"), - ("login_linux_tip", "Norėdami įjungti X darbalaukio seansą, turite būti prisijungę prie nuotolinės Linux paskyros."), ("verify_rustdesk_password_tip", "Įveskite kliento RustDesk slaptažodį"), - ("remember_account_tip", "Prisiminti šią paskyrą"), - ("os_account_desk_tip", "Ši paskyra naudojama norint prisijungti prie nuotolinės OS ir įgalinti darbalaukio seansą režimu headless"), - ("OS Account", "OS paskyra"), - ("another_user_login_title_tip", "Kitas vartotojas jau yra prisijungęs"), - ("another_user_login_text_tip", "Atjungti"), - ("xorg_not_found_title_tip", "Xorg nerastas"), - ("xorg_not_found_text_tip", "Prašom įdiegti Xorg"), - ("no_desktop_title_tip", "Nėra pasiekiamų nuotolinių darbalaukių"), - ("no_desktop_text_tip", "Prašom įdiegti GNOME Desktop"), ("No need to elevate", "Teisių kelti nereikia"), ("System Sound", "Sistemos garsas"), ("Default", "Numatytasis"), diff --git a/src/lang/lv.rs b/src/lang/lv.rs index f0a3ebcff..fe853cdff 100644 --- a/src/lang/lv.rs +++ b/src/lang/lv.rs @@ -464,17 +464,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("identical_file_tip", "Šis fails ir identisks sesijas failam."), ("show_monitors_tip", "Rādīt monitorus rīkjoslā"), ("View Mode", "Skatīšanas režīms"), - ("login_linux_tip", "Jums ir jāpiesakās attālajā Linux kontā, lai iespējotu X darbvirsmas sesiju"), ("verify_rustdesk_password_tip", "Pārbaudīt RustDesk paroli"), - ("remember_account_tip", "Atcerēties šo kontu"), - ("os_account_desk_tip", "Šis konts tiek izmantots, lai pieteiktos attālajā operētājsistēmā un iespējotu darbvirsmas sesiju fonā"), - ("OS Account", "OS konts"), - ("another_user_login_title_tip", "Cits lietotājs jau ir pieteicies"), - ("another_user_login_text_tip", "Atvienot"), - ("xorg_not_found_title_tip", "Xorg nav atrasts"), - ("xorg_not_found_text_tip", "Lūdzu, instalējiet Xorg"), - ("no_desktop_title_tip", "Nav pieejama darbvirsma"), - ("no_desktop_text_tip", "Lūdzu, instalējiet GNOME darbvirsmu"), ("No need to elevate", "Nav nepieciešams paaugstināt"), ("System Sound", "Sistēmas skaņa"), ("Default", "Noklusējums"), diff --git a/src/lang/ml.rs b/src/lang/ml.rs index b982ee49f..fe8534a0e 100644 --- a/src/lang/ml.rs +++ b/src/lang/ml.rs @@ -464,17 +464,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("identical_file_tip", "ഈ ഫയൽ നിലവിലുണ്ട്."), ("show_monitors_tip", "ടൂൾബാറിൽ മോണിറ്ററുകൾ കാണിക്കുക"), ("View Mode", "വ്യൂ മോഡ്"), - ("login_linux_tip", "റിമോട്ട് ലിനക്സ് സെഷനായി ലോഗിൻ ചെയ്യണം"), ("verify_rustdesk_password_tip", "RustDesk പാസ്‌വേഡ് പരിശോധിക്കുക"), - ("remember_account_tip", "ഈ അക്കൗണ്ട് ഓർമ്മിക്കുക"), - ("os_account_desk_tip", "ആക്‌സസിനായി OS അക്കൗണ്ട് ഉപയോഗിക്കുക"), - ("OS Account", "OS അക്കൗണ്ട്"), - ("another_user_login_title_tip", "മറ്റൊരു ഉപയോക്താവ് ലോഗിൻ ചെയ്തിട്ടുണ്ട്"), - ("another_user_login_text_tip", "വിച്ഛേദിച്ച ശേഷം വീണ്ടും ശ്രമിക്കുക"), - ("xorg_not_found_title_tip", "Xorg കണ്ടെത്താനായില്ല"), - ("xorg_not_found_text_tip", "ദയവായി Xorg ഇൻസ്റ്റാൾ ചെയ്യുക"), - ("no_desktop_title_tip", "ഡെസ്ക്ടോപ്പ് ലഭ്യമല്ല"), - ("no_desktop_text_tip", "ദയവായി ലിനക്സ് ഡെസ്ക്ടോപ്പ് ഇൻസ്റ്റാൾ ചെയ്യുക"), ("No need to elevate", "എലവേറ്റ് ചെയ്യേണ്ടതില്ല"), ("System Sound", "സിസ്റ്റം സൗണ്ട്"), ("Default", "ഡിഫോൾട്ട്"), diff --git a/src/lang/nb.rs b/src/lang/nb.rs index 7dba8d4a5..45bd5c540 100644 --- a/src/lang/nb.rs +++ b/src/lang/nb.rs @@ -464,17 +464,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("identical_file_tip", "Denne filen er identisk med motpartens fil."), ("show_monitors_tip", "Vis skjermer i verktøylinjen"), ("View Mode", "Visningsmodus"), - ("login_linux_tip", "Du må logge inn på den eksterne Linux-kontoen for å aktivere en X-skrivebordssesjon"), ("verify_rustdesk_password_tip", "Verifiser RustDesk-passord"), - ("remember_account_tip", "Husk denne kontoen"), - ("os_account_desk_tip", "Denne kontoen brukes til å logge inn på det eksterne operativsystemet og aktivere skrivebordssesjonen i hodeløs modus"), - ("OS Account", "OS-konto"), - ("another_user_login_title_tip", "En annen bruker er allerede logget inn"), - ("another_user_login_text_tip", "Koble fra"), - ("xorg_not_found_title_tip", "Xorg ikke funnet"), - ("xorg_not_found_text_tip", "Vennligst installer Xorg"), - ("no_desktop_title_tip", "Ingen skrivebordsmiljø er tilgjengelig"), - ("no_desktop_text_tip", "Vennligst installer GNOME-skrivebordet"), ("No need to elevate", "Ikke behov for elevering"), ("System Sound", "Systemlyd"), ("Default", "Standard"), diff --git a/src/lang/nl.rs b/src/lang/nl.rs index 0470a4b4f..b0d21f97f 100644 --- a/src/lang/nl.rs +++ b/src/lang/nl.rs @@ -464,17 +464,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("identical_file_tip", "Dit bestand is identiek aan het bestand van het externe station."), ("show_monitors_tip", "Monitoren weergeven in de werkbalk"), ("View Mode", "Toeschouwermodus"), - ("login_linux_tip", "Toegang tot het externe Linux-account"), ("verify_rustdesk_password_tip", "Bevestiging wachtwoord RustDesk"), - ("remember_account_tip", "Onthoud dit account"), - ("os_account_desk_tip", "Dit account wordt gebruikt om toegang te krijgen tot het externe besturingssysteem en de bureaubladsessie in onbeheerde modus te activeren."), - ("OS Account", "Besturingssysteem account"), - ("another_user_login_title_tip", "Een andere gebruiker is al ingelogd."), - ("another_user_login_text_tip", "Afzonderlijk"), - ("xorg_not_found_title_tip", "Xorg niet gevonden."), - ("xorg_not_found_text_tip", "Installeer Xorg."), - ("no_desktop_title_tip", "Er is geen desktop beschikbaar."), - ("no_desktop_text_tip", "Installeer de GNOME desktop."), ("No need to elevate", "Niet nodig om te verhogen"), ("System Sound", "Systeemgeluid"), ("Default", "Standaard"), diff --git a/src/lang/pl.rs b/src/lang/pl.rs index 44efea50c..120183803 100644 --- a/src/lang/pl.rs +++ b/src/lang/pl.rs @@ -464,17 +464,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("identical_file_tip", "Ten plik jest identyczny z plikiem na drugim komputerze."), ("show_monitors_tip", "Pokaż monitory w zasobniku"), ("View Mode", "Tylko podgląd (wyłącza możliwość interakcji)"), - ("login_linux_tip", "Musisz zalogować się na zdalne konto, by zezwolić na sesję pulpitu X"), ("verify_rustdesk_password_tip", "Weryfikuj hasło RustDesk"), - ("remember_account_tip", "Zapamiętaj to konto"), - ("os_account_desk_tip", "To konto jest używane do logowania do zdalnych systemów i włącza bezobsługowe sesje pulpitu"), - ("OS Account", "Konto systemowe"), - ("another_user_login_title_tip", "Inny użytkownik jest już zalogowany"), - ("another_user_login_text_tip", "Rozłącz"), - ("xorg_not_found_title_tip", "Nie znaleziono Xorg"), - ("xorg_not_found_text_tip", "Proszę zainstalować Xorg"), - ("no_desktop_title_tip", "Żaden pulpit nie jest dostępny"), - ("no_desktop_text_tip", "Proszę zainstalować pulpit GNOME"), ("No need to elevate", "Podniesienie uprawnień nie jest wymagane"), ("System Sound", "Dźwięk systemowy"), ("Default", "Domyślne"), diff --git a/src/lang/pt_PT.rs b/src/lang/pt_PT.rs index a162522bb..7d033b363 100644 --- a/src/lang/pt_PT.rs +++ b/src/lang/pt_PT.rs @@ -464,17 +464,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("identical_file_tip", "Este ficheiro é idêntico ao do destino."), ("show_monitors_tip", "Mostrar monitores na barra de ferramentas"), ("View Mode", "Modo de visualização"), - ("login_linux_tip", "É necessário iniciar sessão na conta Linux remota para ativar uma sessão de ambiente de trabalho X"), ("verify_rustdesk_password_tip", "Verificar palavra-passe do RustDesk"), - ("remember_account_tip", "Memorizar esta conta"), - ("os_account_desk_tip", "Esta conta é usada para iniciar sessão no SO remoto e ativar a sessão de ambiente de trabalho em modo headless"), - ("OS Account", "Conta do SO"), - ("another_user_login_title_tip", "Outro utilizador já tem sessão iniciada"), - ("another_user_login_text_tip", "Desligar"), - ("xorg_not_found_title_tip", "Xorg não encontrado"), - ("xorg_not_found_text_tip", "Instale o Xorg"), - ("no_desktop_title_tip", "Não há nenhum ambiente de trabalho disponível"), - ("no_desktop_text_tip", "Instale o ambiente de trabalho GNOME"), ("No need to elevate", "Não é necessário elevar"), ("System Sound", "Som do sistema"), ("Default", "Predefinido"), diff --git a/src/lang/ptbr.rs b/src/lang/ptbr.rs index 070fc0b7b..897ef1735 100644 --- a/src/lang/ptbr.rs +++ b/src/lang/ptbr.rs @@ -464,17 +464,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("identical_file_tip", "Este arquivo é idêntico ao do parceiro."), ("show_monitors_tip", "Mostrar telas na barra de ferramentas"), ("View Mode", "Modo de visualização"), - ("login_linux_tip", "Você precisa fazer login na conta Linux remota para habilitar uma sessão de desktop X"), ("verify_rustdesk_password_tip", "Verifique a senha do RustDesk"), - ("remember_account_tip", "Lembrar desta conta"), - ("os_account_desk_tip", "Esta conta é usada para fazer login no Sistema Operacional remoto e habilitar a sessão da área de trabalho em headless"), - ("OS Account", "Conta do Sistema Operacional"), - ("another_user_login_title_tip", "Outro usuário já está logado"), - ("another_user_login_text_tip", "Desconectar"), - ("xorg_not_found_title_tip", "Xorg não encontrado"), - ("xorg_not_found_text_tip", "Por favor, instale o Xorg"), - ("no_desktop_title_tip", "Nenhuma área de trabalho está disponível"), - ("no_desktop_text_tip", "Por favor, instale a área de trabalho do GNOME"), ("No need to elevate", "Não há necessidade de elevar"), ("System Sound", "Som do Sistema"), ("Default", "Padrão"), diff --git a/src/lang/ro.rs b/src/lang/ro.rs index 5bc7a5e02..aee37cf94 100644 --- a/src/lang/ro.rs +++ b/src/lang/ro.rs @@ -464,17 +464,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("identical_file_tip", "Acest fișier este identic cu cel al dispozitivului pereche."), ("show_monitors_tip", "Afișează monitoare în bara de instrumente"), ("View Mode", "Mod vizualizare"), - ("login_linux_tip", "Este necesar să te conectezi la contul de Linux de la distanță pentru a începe o sesiune cu un desktop care folosește X11"), ("verify_rustdesk_password_tip", "Verifică parola RustDesk"), - ("remember_account_tip", "Reține contul"), - ("os_account_desk_tip", "Acest cont este utilizat pentru conectarea la sistemul de operare la distanță și începerea sesiunii cu desktopul în modul fără afișaj."), - ("OS Account", "Cont OS"), - ("another_user_login_title_tip", "Un alt utilizator este deja conectat"), - ("another_user_login_text_tip", "Deconectare"), - ("xorg_not_found_title_tip", "Xorg nu a fost găsit"), - ("xorg_not_found_text_tip", "Instalează Xorg"), - ("no_desktop_title_tip", "Nu este disponibil niciun mediu desktop"), - ("no_desktop_text_tip", "Instalează mediul desktop GNOME"), ("No need to elevate", "Nu sunt necesare permisiuni de administrator"), ("System Sound", "Sunet sistem"), ("Default", "Implicit"), diff --git a/src/lang/ru.rs b/src/lang/ru.rs index a0ca5affe..834fcd565 100644 --- a/src/lang/ru.rs +++ b/src/lang/ru.rs @@ -464,17 +464,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("identical_file_tip", "Файл идентичен файлу на удалённом узле"), ("show_monitors_tip", "Показывать мониторы на панели инструментов"), ("View Mode", "Режим просмотра"), - ("login_linux_tip", "Чтобы включить сеанс рабочего стола X, необходимо войти в удалённый аккаунт Linux."), ("verify_rustdesk_password_tip", "Подтвердить пароль RustDesk"), - ("remember_account_tip", "Запомнить этот аккаунт"), - ("os_account_desk_tip", "Этот аккаунт используется для входа в удалённую ОС и включения сеанса рабочего стола в режиме headless."), - ("OS Account", "Аккаунт ОС"), - ("another_user_login_title_tip", "Другой пользователь уже вошёл в систему"), - ("another_user_login_text_tip", "Отключить"), - ("xorg_not_found_title_tip", "Xorg не найден"), - ("xorg_not_found_text_tip", "Установите Xorg"), - ("no_desktop_title_tip", "Нет доступных рабочих столов"), - ("no_desktop_text_tip", "Установите GNOME Desktop"), ("No need to elevate", "Повышение прав не требуется"), ("System Sound", "Системный звук"), ("Default", "По умолчанию"), diff --git a/src/lang/sc.rs b/src/lang/sc.rs index 1228e9876..59d0967c6 100644 --- a/src/lang/sc.rs +++ b/src/lang/sc.rs @@ -464,17 +464,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("identical_file_tip", "Custu archìviu est pretzisu a su chi b'at in su dispositivu remotu."), ("show_monitors_tip", "Mustra sos ischermos in s'istanga de sos trastes"), ("View Mode", "Modalidade de visualizatzione"), - ("login_linux_tip", "Intra a su contu de Linux remotu"), ("verify_rustdesk_password_tip", "Cunfirma sa crae de RustDesk"), - ("remember_account_tip", "Ammenta custu contu"), - ("os_account_desk_tip", "Custu contu s'impreat pro intrare a su sistema operativu remotu e ativare sa sessione de s'elaboradore in modalidade non presidiada."), - ("OS Account", "Contu sistema operativu"), - ("another_user_login_title_tip", "Un'àteru utente at giai fatu s'atzessu."), - ("another_user_login_text_tip", "Separadu"), - ("xorg_not_found_title_tip", "Xorg no atzapadu."), - ("xorg_not_found_text_tip", "Installa Xorg."), - ("no_desktop_title_tip", "Non b'at perunu ambiente de elaboradore a disponimentu."), - ("no_desktop_text_tip", "Installa s'ambiente de elaboradore GNOME."), ("No need to elevate", "Crèschida de sos privilègios non pedida"), ("System Sound", "Dispositivu àudio de sistema"), ("Default", "Predefinida"), diff --git a/src/lang/sk.rs b/src/lang/sk.rs index 5460e2b19..f01cf6e3a 100644 --- a/src/lang/sk.rs +++ b/src/lang/sk.rs @@ -464,17 +464,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("identical_file_tip", "Tento súbor je identický so súborom partnera."), ("show_monitors_tip", "Zobraziť monitory na paneli nástrojov"), ("View Mode", "Režim zobrazenia"), - ("login_linux_tip", "Ak chcete povoliť reláciu Desktop X, musíte sa prihlásiť do vzdialeného konta Linuxu."), ("verify_rustdesk_password_tip", "Overenie hesla RustDesk"), - ("remember_account_tip", "Zapamätať si tento účet"), - ("os_account_desk_tip", "Toto konto sa používa na prihlásenie do vzdialeného operačného systému a na povolenie relácie pracovnej plochy v režime headless."), - ("OS Account", "Účet operačného systému"), - ("another_user_login_title_tip", "Ďalší používateľ je už prihlásený"), - ("another_user_login_text_tip", "Odpojiť"), - ("xorg_not_found_title_tip", "Xorg nebol nájdený"), - ("xorg_not_found_text_tip", "Prosím, nainštalujte Xorg"), - ("no_desktop_title_tip", "Nie je k dispozícii žiadna plocha"), - ("no_desktop_text_tip", "Nainštalujte si prostredie GNOME"), ("No need to elevate", "Navýšenie nie je potrebné"), ("System Sound", "Systémový zvuk"), ("Default", "Predvolené"), diff --git a/src/lang/sl.rs b/src/lang/sl.rs index d9d5fd172..04a0dd0e2 100644 --- a/src/lang/sl.rs +++ b/src/lang/sl.rs @@ -464,17 +464,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("identical_file_tip", "Datoteka je enaka partnerjevi"), ("show_monitors_tip", "Prikaži monitorje v orodni vrstici"), ("View Mode", "Način prikazovanja"), - ("login_linux_tip", "Prijaviti se morate v oddaljeni Linux račun in omogočiti namizno sejo X."), ("verify_rustdesk_password_tip", "Preveri geslo za RustDesk"), - ("remember_account_tip", "Zapomni si ta račun"), - ("os_account_desk_tip", "Ta račun se uporabi za prijavo v oddaljeni sistem in omogči namizno sejo v napravi brez monitorja."), - ("OS Account", "Račun operacijskega sistema"), - ("another_user_login_title_tip", "Prijavljen je že drug uporabnik"), - ("another_user_login_text_tip", "Prekini"), - ("xorg_not_found_title_tip", "Xorg ni najden"), - ("xorg_not_found_text_tip", "Namestite Xorg"), - ("no_desktop_title_tip", "Namizno okolje ni na voljo"), - ("no_desktop_text_tip", "Namestite GNOME"), ("No need to elevate", "Povzdig pravic ni potreben"), ("System Sound", "Sistemski zvok"), ("Default", "Privzeto"), diff --git a/src/lang/sq.rs b/src/lang/sq.rs index 40b1060e7..2fb1c811d 100644 --- a/src/lang/sq.rs +++ b/src/lang/sq.rs @@ -464,17 +464,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("identical_file_tip", "Ky skedar është identik me atë të peer-it."), ("show_monitors_tip", "Shfaq monitorët në shiritin e veglave"), ("View Mode", "Modaliteti i pamjes"), - ("login_linux_tip", "Duhet të hyni në llogarinë Linux në distancë për të aktivizuar një seancë desktopi X"), ("verify_rustdesk_password_tip", "Verifiko fjalëkalimin e RustDesk"), - ("remember_account_tip", "Mbaj mend këtë llogari"), - ("os_account_desk_tip", "Kjo llogari përdoret për të hyrë në OS-në në distancë dhe për të aktivizuar seancën e desktopit pa ekran"), - ("OS Account", "Llogaria e OS"), - ("another_user_login_title_tip", "Një përdorues tjetër ka hyrë tashmë"), - ("another_user_login_text_tip", "Shkëput"), - ("xorg_not_found_title_tip", "Xorg nuk u gjet"), - ("xorg_not_found_text_tip", "Ju lutemi instaloni Xorg"), - ("no_desktop_title_tip", "Nuk ka asnjë mjedis desktopi të disponueshëm"), - ("no_desktop_text_tip", "Ju lutemi instaloni desktopin GNOME"), ("No need to elevate", "Nuk ka nevojë për ngritje privilegjesh"), ("System Sound", "Tingulli i sistemit"), ("Default", "I parazgjedhur"), diff --git a/src/lang/sr.rs b/src/lang/sr.rs index 390afb5e5..e1b0e703d 100644 --- a/src/lang/sr.rs +++ b/src/lang/sr.rs @@ -464,17 +464,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("identical_file_tip", "Ova datoteka je identična sa onom kod klijenta."), ("show_monitors_tip", "Prikaži monitore u traci alata"), ("View Mode", "Režim prikaza"), - ("login_linux_tip", "Potrebno je da se prijavite na udaljeni Linux nalog da biste omogućili X desktop sesiju"), ("verify_rustdesk_password_tip", "Potvrdi RustDesk lozinku"), - ("remember_account_tip", "Zapamti ovaj nalog"), - ("os_account_desk_tip", "Ovaj nalog se koristi za prijavu na udaljeni OS i omogućavanje desktop sesije u headless režimu"), - ("OS Account", "OS nalog"), - ("another_user_login_title_tip", "Drugi korisnik je već prijavljen"), - ("another_user_login_text_tip", "Prekini vezu"), - ("xorg_not_found_title_tip", "Xorg nije pronađen"), - ("xorg_not_found_text_tip", "Molimo instalirajte Xorg"), - ("no_desktop_title_tip", "Nijedno desktop okruženje nije dostupno"), - ("no_desktop_text_tip", "Molimo instalirajte GNOME desktop"), ("No need to elevate", "Nema potrebe za podizanjem privilegija"), ("System Sound", "Sistemski zvuk"), ("Default", "Podrazumevano"), diff --git a/src/lang/sv.rs b/src/lang/sv.rs index 142f18338..594efa688 100644 --- a/src/lang/sv.rs +++ b/src/lang/sv.rs @@ -464,17 +464,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("identical_file_tip", "Den här filen är identisk med klientens."), ("show_monitors_tip", "Visa skärmar i verktygsfältet"), ("View Mode", "Visningsläge"), - ("login_linux_tip", "Du måste logga in på Linux-fjärrkontot för att aktivera en X-skrivbordssession"), ("verify_rustdesk_password_tip", "Verifiera RustDesk-lösenord"), - ("remember_account_tip", "Kom ihåg detta konto"), - ("os_account_desk_tip", "Detta konto används för att logga in på fjärroperativsystemet och aktivera skrivbordssessionen i obevakat läge"), - ("OS Account", "OS-konto"), - ("another_user_login_title_tip", "En annan användare är redan inloggad"), - ("another_user_login_text_tip", "Koppla ifrån"), - ("xorg_not_found_title_tip", "Xorg hittades inte"), - ("xorg_not_found_text_tip", "Installera Xorg"), - ("no_desktop_title_tip", "Ingen skrivbordsmiljö är tillgänglig"), - ("no_desktop_text_tip", "Installera GNOME-skrivbordet"), ("No need to elevate", "Ingen behörighetshöjning behövs"), ("System Sound", "Systemljud"), ("Default", "Standard"), diff --git a/src/lang/ta.rs b/src/lang/ta.rs index c6221a841..8a4afde95 100644 --- a/src/lang/ta.rs +++ b/src/lang/ta.rs @@ -464,17 +464,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("identical_file_tip", "ஒரே_மாதிரியான_கோப்பு_குறிப்பு"), ("show_monitors_tip", "மானிட்டர்களை_காட்டு_குறிப்பு"), ("View Mode", "காட்சி முறை"), - ("login_linux_tip", "லினக்ஸ்_உள்நுழைவு_குறிப்பு"), ("verify_rustdesk_password_tip", "rustdesk_கடவுச்சொல்_சரிபார்ப்பு_குறிப்பு"), - ("remember_account_tip", "கணக்கை_நினைவில்_கொள்_குறிப்பு"), - ("os_account_desk_tip", "os_கணக்கு_டெஸ்க்_குறிப்பு"), - ("OS Account", "OS கணக்கு"), - ("another_user_login_title_tip", "மற்றொரு_பயனர்_உள்நுழைவு_தலைப்பு_குறிப்பு"), - ("another_user_login_text_tip", "மற்றொரு_பயனர்_உள்நுழைவு_உரை_குறிப்பு"), - ("xorg_not_found_title_tip", "xorg_காணப்படவில்லை_தலைப்பு_குறிப்பு"), - ("xorg_not_found_text_tip", "xorg_காணப்படவில்லை_உரை_குறிப்பு"), - ("no_desktop_title_tip", "டெஸ்க்டாப்_இல்லை_தலைப்பு_குறிப்பு"), - ("no_desktop_text_tip", "டெஸ்க்டாப்_இல்லை_உரை_குறிப்பு"), ("No need to elevate", "உயர்த்த தேவையில்லை"), ("System Sound", "சிஸ்டம் ஒலி"), ("Default", "இயல்புநிலை"), diff --git a/src/lang/template.rs b/src/lang/template.rs index c529dfada..83497a0f6 100644 --- a/src/lang/template.rs +++ b/src/lang/template.rs @@ -464,17 +464,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("identical_file_tip", ""), ("show_monitors_tip", ""), ("View Mode", ""), - ("login_linux_tip", ""), ("verify_rustdesk_password_tip", ""), - ("remember_account_tip", ""), - ("os_account_desk_tip", ""), - ("OS Account", ""), - ("another_user_login_title_tip", ""), - ("another_user_login_text_tip", ""), - ("xorg_not_found_title_tip", ""), - ("xorg_not_found_text_tip", ""), - ("no_desktop_title_tip", ""), - ("no_desktop_text_tip", ""), ("No need to elevate", ""), ("System Sound", ""), ("Default", ""), diff --git a/src/lang/th.rs b/src/lang/th.rs index d956e7144..31f314726 100644 --- a/src/lang/th.rs +++ b/src/lang/th.rs @@ -464,17 +464,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("identical_file_tip", "ไฟล์นี้เหมือนกับไฟล์ของอีกฝั่ง"), ("show_monitors_tip", "แสดงหน้าจอในแถบเครื่องมือ"), ("View Mode", "โหมดการดู"), - ("login_linux_tip", "คุณจำเป็นจะต้องเข้าสู่ระบบไปยังบัญชีลินุกซ์ปลายทางเพื่อใช้งานเดสก์ท็อปเซสชัน X"), ("verify_rustdesk_password_tip", "ยืนยันความถูกต้องรหัสผ่านของ RustDesk"), - ("remember_account_tip", "จดจำบัญชีนี้"), - ("os_account_desk_tip", "บัญชีนี้จะถูกใช้ในการเข้าสู่ระบบเครื่องปลายทางและเริ่มใช้งานเดสก์ท็อปเซสชันแบบ headless"), - ("OS Account", "บัญชีระบบปฏิบัติการ"), - ("another_user_login_title_tip", "ผู้ใช้งานอื่นเข้าสู่ระบบอยู่แล้ว"), - ("another_user_login_text_tip", "ยกเลิกการเชื่อมต่อ"), - ("xorg_not_found_title_tip", "ไม่พบ Xorg"), - ("xorg_not_found_text_tip", "กรุณาติดตั้ง Xorg"), - ("no_desktop_title_tip", "ไม่มีหน้าเดสก์ท็อปที่ใช้งานได้"), - ("no_desktop_text_tip", "กรุณาติดตั้ง GNOME เดสกท็อป"), ("No need to elevate", "ไม่จำเป็นต้องยกระดับสิทธิ์การใช้งาน"), ("System Sound", "เสียงของระบบ"), ("Default", "ค่าเริ่มต้น"), diff --git a/src/lang/tr.rs b/src/lang/tr.rs index 1f0c3dcd8..66ac42a1c 100644 --- a/src/lang/tr.rs +++ b/src/lang/tr.rs @@ -464,17 +464,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("identical_file_tip", "Bu dosya, cihazın dosyası ile aynıdır."), ("show_monitors_tip", "Monitörleri araç çubuğunda göster"), ("View Mode", "Görünüm Modu"), - ("login_linux_tip", "X masaüstü oturumu başlatmak için uzaktaki Linux hesabına giriş yapmanız gerekiyor"), ("verify_rustdesk_password_tip", "RustDesk parolasını doğrulayın"), - ("remember_account_tip", "Bu hesabı hatırla"), - ("os_account_desk_tip", "Bu hesap, uzaktaki işletim sistemine giriş yapmak ve başsız masaüstü oturumunu etkinleştirmek için kullanılır."), - ("OS Account", "İşletim Sistemi Hesabı"), - ("another_user_login_title_tip", "Başka bir kullanıcı zaten oturum açtı"), - ("another_user_login_text_tip", "Bağlantıyı Kapat"), - ("xorg_not_found_title_tip", "Xorg bulunamadı"), - ("xorg_not_found_text_tip", "Lütfen Xorg'u yükleyin"), - ("no_desktop_title_tip", "Masaüstü mevcut değil"), - ("no_desktop_text_tip", "Lütfen GNOME masaüstünü yükleyin"), ("No need to elevate", "Yükseltmeye gerek yok"), ("System Sound", "Sistem Sesi"), ("Default", "Varsayılan"), diff --git a/src/lang/tw.rs b/src/lang/tw.rs index eb05f9e7c..b35322d10 100644 --- a/src/lang/tw.rs +++ b/src/lang/tw.rs @@ -464,17 +464,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("identical_file_tip", "此檔案與對方的檔案一致。"), ("show_monitors_tip", "在工具列中顯示顯示器"), ("View Mode", "瀏覽模式"), - ("login_linux_tip", "需要登入到遠端 Linux 使用者帳戶才能啟用 X 桌面環境"), ("verify_rustdesk_password_tip", "驗證 RustDesk 密碼"), - ("remember_account_tip", "記住此使用者帳戶"), - ("os_account_desk_tip", "此使用者帳戶將用於登入遠端作業系統並啟用無頭模式 (headless mode) 的桌面連線"), - ("OS Account", "作業系統使用者帳戶"), - ("another_user_login_title_tip", "另一個使用者已經登入"), - ("another_user_login_text_tip", "斷開連線"), - ("xorg_not_found_title_tip", "找不到 Xorg"), - ("xorg_not_found_text_tip", "請安裝 Xorg"), - ("no_desktop_title_tip", "沒有可用的桌面環境"), - ("no_desktop_text_tip", "請安裝 GNOME 桌面"), ("No need to elevate", "不需要提升權限"), ("System Sound", "系統音效"), ("Default", "預設"), diff --git a/src/lang/uk.rs b/src/lang/uk.rs index 4b61936e4..281b9cd6c 100644 --- a/src/lang/uk.rs +++ b/src/lang/uk.rs @@ -464,17 +464,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("identical_file_tip", "Цей файл ідентичний з тим, що на вузлі"), ("show_monitors_tip", "Показувати монітори на панелі інструментів"), ("View Mode", "Режим перегляду"), - ("login_linux_tip", "Вам необхідно увійти у віддалений обліковий запис Linux, щоб увімкнути стільничний сеанс X"), ("verify_rustdesk_password_tip", "Перевірте пароль RustDesk"), - ("remember_account_tip", "Запамʼятати цей обліковий запис"), - ("os_account_desk_tip", "Цей обліковий запис використовується для входу до віддаленої ОС та вмикання сеансу стільниці в режимі без графічного інтерфейсу"), - ("OS Account", "Користувач ОС"), - ("another_user_login_title_tip", "Інший користувач вже в системі"), - ("another_user_login_text_tip", "Відʼєднатися"), - ("xorg_not_found_title_tip", "Xorg не знайдено"), - ("xorg_not_found_text_tip", "Будь ласка, встановіть Xorg"), - ("no_desktop_title_tip", "Жодне стільничне середовище не доступне"), - ("no_desktop_text_tip", "Будь ласка, встановіть стільничне середовище GNOME"), ("No need to elevate", "Немає потреби в розширенні прав"), ("System Sound", "Системний звук"), ("Default", "Типово"), diff --git a/src/lang/vi.rs b/src/lang/vi.rs index a3102800b..c9b28b949 100644 --- a/src/lang/vi.rs +++ b/src/lang/vi.rs @@ -464,17 +464,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("identical_file_tip", "Tệp này giống hệt ở phía đối tác."), ("show_monitors_tip", "Hiện màn hình trên thanh công cụ"), ("View Mode", "Chế độ xem"), - ("login_linux_tip", "Cần đăng nhập tài khoản Linux để kích hoạt X session."), ("verify_rustdesk_password_tip", "Xác thực mật khẩu RustDesk"), - ("remember_account_tip", "Nhớ tài khoản này"), - ("os_account_desk_tip", "Tài khoản OS được dùng để đăng nhập và chạy session không màn hình (headless)."), - ("OS Account", "Tài khoản OS"), - ("another_user_login_title_tip", "Người dùng khác đã đăng nhập"), - ("another_user_login_text_tip", "Ngắt kết nối hiện tại"), - ("xorg_not_found_title_tip", "Không tìm thấy Xorg"), - ("xorg_not_found_text_tip", "Vui lòng cài đặt Xorg"), - ("no_desktop_title_tip", "Không có desktop"), - ("no_desktop_text_tip", "Vui lòng cài đặt GNOME hoặc desktop khác."), ("No need to elevate", "Không cần nâng quyền"), ("System Sound", "Âm thanh hệ thống"), ("Default", "Mặc định"), diff --git a/src/platform/linux.rs b/src/platform/linux.rs index f67952e9b..d187b0ec2 100644 --- a/src/platform/linux.rs +++ b/src/platform/linux.rs @@ -14,7 +14,7 @@ use hbb_common::{ allow_err, anyhow::anyhow, bail, - config::{keys::OPTION_ALLOW_LINUX_HEADLESS, Config}, + config::Config, libc::{c_char, c_int, c_long, c_uint, c_ulong, c_void}, log, message_proto::{DisplayInfo, Resolution}, @@ -235,11 +235,6 @@ pub struct xcb_xfixes_get_cursor_image { pub pixels: *const c_long, } -#[inline] -pub fn is_headless_allowed() -> bool { - Config::get_option(OPTION_ALLOW_LINUX_HEADLESS) == "Y" -} - #[inline] pub fn is_login_screen_wayland() -> bool { let values = get_values_of_seat0_with_gdm_wayland(&[0, 2]); @@ -863,18 +858,6 @@ fn stop_rustdesk_servers() { )); } -#[inline] -fn stop_subprocess() { - let _ = run_cmds(&format!( - r##"ps -ef | grep '/etc/{}/xorg.conf' | grep -v grep | awk '{{print $2}}' | xargs -r kill -9"##, - crate::get_app_name().to_lowercase(), - )); - let _ = run_cmds(&format!( - r##"ps -ef | grep -E '{} +--cm-no-ui' | grep -v grep | awk '{{print $2}}' | xargs -r kill -9"##, - crate::get_app_name().to_lowercase(), - )); -} - fn should_start_server( try_x11: bool, is_display_changed: bool, @@ -888,13 +871,7 @@ fn should_start_server( let mut start_new = false; let mut should_kill = false; - if desktop.is_headless() { - if !uid.is_empty() { - // From having a monitor to not having a monitor. - *uid = "".to_owned(); - should_kill = true; - } - } else if is_display_changed || desktop.uid != *uid && !desktop.uid.is_empty() { + if is_display_changed || desktop.uid != *uid && !desktop.uid.is_empty() { *uid = desktop.uid.clone(); if try_x11 { set_x11_env(&desktop); @@ -953,7 +930,6 @@ fn force_stop_server() { pub fn start_os_service() { check_if_stop_service(); stop_rustdesk_servers(); - stop_subprocess(); start_uinput_service(); std::thread::spawn(|| { @@ -1003,8 +979,7 @@ pub fn start_os_service() { desktop.refresh(); update_active_user_lookup_cache(&desktop); - // Duplicate logic here with should_start_server - // Login wayland will try to start a headless --server. + // Duplicate logic here with should_start_server. if desktop.username == "root" || desktop.is_login_wayland() { // try kill subprocess "--server" stop_server(&mut user_server); @@ -1019,7 +994,6 @@ pub fn start_os_service() { &mut last_restart, &mut server, ) { - stop_subprocess(); force_stop_server(); // Run the login-screen --server as the active seat0 session user (the greeter // account) rather than root, so the DRM capture GPU/EGL convert never loads the @@ -1072,7 +1046,6 @@ pub fn start_os_service() { &mut last_restart, &mut user_server, ) { - stop_subprocess(); force_stop_server(); start_server(Some(&desktop), &mut user_server); } @@ -1082,17 +1055,14 @@ pub fn start_os_service() { stop_server(&mut server); } - let keeps_headless = sid.is_empty() && desktop.is_headless(); let keeps_session = sid == desktop.sid; - if keeps_headless || keeps_session { + if keeps_session { // for fixing https://github.com/rustdesk/rustdesk/issues/3129 to avoid too much dbus calling, sleep_millis(500); } else { sleep_millis(super::SERVICE_INTERVAL); } - if !desktop.is_headless() { - sid = desktop.sid.clone(); - } + sid = desktop.sid.clone(); } if let Some(ps) = user_server.take().as_mut() { @@ -1249,7 +1219,6 @@ fn is_flatpak() -> bool { std::path::PathBuf::from("/.flatpak-info").exists() } -// Headless is enabled, always return true. pub fn is_prelogin() -> bool { if is_flatpak() { return false; @@ -1860,7 +1829,6 @@ mod desktop { pub xauth: String, pub home: String, pub dbus: String, - pub is_rustdesk_subprocess: bool, pub wl_display: String, } @@ -1875,11 +1843,6 @@ mod desktop { super::is_gdm_user(&self.username) && self.protocol == DISPLAY_SERVER_WAYLAND } - #[inline] - pub fn is_headless(&self) -> bool { - self.sid.is_empty() || self.is_rustdesk_subprocess - } - fn get_display_xauth_wayland(&mut self) { for _ in 1..=10 { // Prefer Wayland-related variables first when multiple portal processes match. @@ -2117,25 +2080,11 @@ mod desktop { last } - fn set_is_subprocess(&mut self) { - self.is_rustdesk_subprocess = false; - let cmd = format!( - "ps -ef | grep '{}/xorg.conf' | grep -v grep | wc -l", - crate::get_app_name().to_lowercase() - ); - if let Ok(res) = run_cmds(&cmd) { - if res.trim() != "0" { - self.is_rustdesk_subprocess = true; - } - } - } - pub fn refresh(&mut self) { if !self.sid.is_empty() && is_active_and_seat0(&self.sid) { // Xwayland display and xauth may not be available in a short time after login. if is_xwayland_running() && !self.is_login_wayland() { self.get_display_xauth_xwayland(); - self.is_rustdesk_subprocess = false; } else if self.is_wayland() { self.get_display_xauth_wayland(); } @@ -2145,7 +2094,6 @@ mod desktop { let seat0_values = get_values_of_seat0_with_gdm_wayland(&[0, 1, 2]); if seat0_values[0].is_empty() { *self = Self::default(); - self.is_rustdesk_subprocess = false; return; } @@ -2156,7 +2104,6 @@ mod desktop { if self.is_login_wayland() { self.display = "".to_owned(); self.xauth = "".to_owned(); - self.is_rustdesk_subprocess = false; // Resolve HOME even on this path. Upstream returned without it because nothing then // consumed a login-Wayland Desktop, but the drm build starts a `--server` as the // greeter uid here, and a child with no HOME has nowhere to put its config. The @@ -2183,11 +2130,9 @@ mod desktop { } else { self.get_display_xauth_wayland(); } - self.is_rustdesk_subprocess = false; } else { self.get_display_x11(); self.get_xauth_x11(); - self.set_is_subprocess(); } } } diff --git a/src/platform/linux_desktop_manager.rs b/src/platform/linux_desktop_manager.rs deleted file mode 100644 index 573dfa018..000000000 --- a/src/platform/linux_desktop_manager.rs +++ /dev/null @@ -1,1363 +0,0 @@ -use super::{linux::*, ResultType}; -use crate::client::{ - LOGIN_MSG_DESKTOP_NO_DESKTOP, LOGIN_MSG_DESKTOP_SESSION_ANOTHER_USER, - LOGIN_MSG_DESKTOP_SESSION_NOT_READY, LOGIN_MSG_DESKTOP_XORG_NOT_FOUND, - LOGIN_MSG_DESKTOP_XSESSION_FAILED, LOGIN_MSG_PASSWORD_WRONG, -}; -use hbb_common::{ - allow_err, bail, log, - rand::prelude::*, - tokio::time, - users::{get_user_by_name, os::unix::UserExt, User}, -}; -use pam; -use std::{ - collections::HashMap, - os::unix::process::CommandExt, - path::Path, - process::{Child, Command}, - sync::{ - atomic::{AtomicBool, AtomicUsize, Ordering}, - mpsc::{sync_channel, SyncSender}, - Arc, Mutex, - }, - time::{Duration, Instant}, -}; - -#[derive(Clone, Debug, Default, PartialEq, Eq)] -struct Seat0Snapshot { - sequence: usize, - username: Option>, -} - -lazy_static::lazy_static! { - static ref DESKTOP_RUNNING: Arc = Arc::new(AtomicBool::new(false)); - static ref DESKTOP_MANAGER: Arc>> = Arc::new(Mutex::new(None)); - /// Last settled "who owns seat0" answer, for the PRE-AUTH path only; see `is_headless`. - static ref SEAT0_SNAPSHOT: Mutex = Mutex::new(Seat0Snapshot::default()); - static ref SEAT0_NEXT_REFRESH: Mutex> = Mutex::new(None); -} - -static SEAT0_REFRESH_IN_FLIGHT: AtomicBool = AtomicBool::new(false); -const FIRST_SEAT0_QUERY_SEQUENCE: usize = 1; -static SEAT0_QUERY_SEQUENCE: AtomicUsize = AtomicUsize::new(FIRST_SEAT0_QUERY_SEQUENCE); -const SEAT0_REFRESH_INTERVAL: Duration = Duration::from_secs(1); - -#[derive(Debug)] -struct DesktopManager { - child_username: String, - child_exit: Arc, - is_child_running: Arc, -} - -fn check_desktop_manager() { - let mut desktop_manager = DESKTOP_MANAGER.lock().unwrap(); - if let Some(desktop_manager) = &mut (*desktop_manager) { - if desktop_manager.is_child_running.load(Ordering::SeqCst) { - return; - } - desktop_manager.child_exit.store(true, Ordering::SeqCst); - } -} - -pub fn start_xdesktop() { - debug_assert!(crate::is_server()); - std::thread::spawn(|| { - DesktopManager::recover_orphaned_session(); - *DESKTOP_MANAGER.lock().unwrap() = Some(DesktopManager::new()); - // Seed the pre-auth snapshot now, off the connection path: without this the first - // connection of every server process would read no snapshot at all. - kick_seat0_refresh(); - - let interval = time::Duration::from_millis(super::SERVICE_INTERVAL); - DESKTOP_RUNNING.store(true, Ordering::SeqCst); - while DESKTOP_RUNNING.load(Ordering::SeqCst) { - check_desktop_manager(); - std::thread::sleep(interval); - } - log::info!("xdesktop child thread exit"); - }); -} - -pub fn stop_xdesktop() { - DESKTOP_RUNNING.store(false, Ordering::SeqCst); - *DESKTOP_MANAGER.lock().unwrap() = None; -} - -fn detect_headless() -> Option<&'static str> { - match run_cmds(&format!("which {}", DesktopManager::get_xorg())) { - Ok(output) => { - if output.trim().is_empty() { - return Some(LOGIN_MSG_DESKTOP_XORG_NOT_FOUND); - } - } - _ => { - return Some(LOGIN_MSG_DESKTOP_XORG_NOT_FOUND); - } - } - - match run_cmds("ls /usr/share/xsessions/") { - Ok(output) => { - if output.trim().is_empty() { - return Some(LOGIN_MSG_DESKTOP_NO_DESKTOP); - } - } - _ => { - return Some(LOGIN_MSG_DESKTOP_NO_DESKTOP); - } - } - - None -} - -#[derive(Copy, Clone, Debug, Eq, PartialEq)] -enum XSessionStartErrorKind { - Auth, - Env, -} - -const XSESSION_AUTH_FAILURE_DETAIL: &str = "authentication failed"; - -#[derive(Debug)] -struct XSessionStartError { - kind: XSessionStartErrorKind, - detail: String, -} - -impl XSessionStartError { - fn auth(detail: String) -> Self { - Self { - kind: XSessionStartErrorKind::Auth, - detail, - } - } - - fn env(detail: String) -> Self { - Self { - kind: XSessionStartErrorKind::Env, - detail, - } - } -} - -impl std::fmt::Display for XSessionStartError { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "{}", self.detail) - } -} - -fn map_xsession_start_error_to_login_msg(kind: XSessionStartErrorKind) -> &'static str { - match kind { - XSessionStartErrorKind::Auth => LOGIN_MSG_PASSWORD_WRONG, - XSessionStartErrorKind::Env => LOGIN_MSG_DESKTOP_XSESSION_FAILED, - } -} - -pub fn try_start_desktop(_username: &str, _passsword: &str) -> String { - debug_assert!(crate::is_server()); - if _username.is_empty() { - let username = get_username(); - if username.is_empty() { - if let Some(msg) = detect_headless() { - msg - } else { - LOGIN_MSG_DESKTOP_SESSION_NOT_READY - } - } else { - "" - } - .to_owned() - } else { - let username = get_username(); - log::debug!("try_start_desktop, username: {}, _username: {}", &username, &_username); - if username == _username { - // No need to verify password here. - return "".to_owned(); - } - if !username.is_empty() { - // Another user is logged in. No need to start a new xsession. - return "".to_owned(); - } - - if let Some(msg) = detect_headless() { - return msg.to_owned(); - } - - match try_start_x_session(_username, _passsword) { - Ok((username, x11_ready)) => { - if x11_ready { - if _username != username { - LOGIN_MSG_DESKTOP_SESSION_ANOTHER_USER.to_owned() - } else { - "".to_owned() - } - } else { - LOGIN_MSG_DESKTOP_SESSION_NOT_READY.to_owned() - } - } - Err(e) => { - match e.kind { - XSessionStartErrorKind::Auth => { - log::warn!("Failed to authenticate xsession user {}", e); - } - XSessionStartErrorKind::Env => { - log::error!("Failed to start xsession {}", e); - } - } - map_xsession_start_error_to_login_msg(e.kind).to_owned() - } - } - } -} - -fn try_start_x_session(username: &str, password: &str) -> Result<(String, bool), XSessionStartError> { - // Seat0 is read BEFORE the manager lock: the lookup runs loginctl, and at a greeter the DRM - // probe, and holding DESKTOP_MANAGER across those waits serializes every other caller. - let seat0_username = refresh_seat0_snapshot(); - let mut desktop_manager = DESKTOP_MANAGER.lock().unwrap(); - if let Some(desktop_manager) = &mut (*desktop_manager) { - if let Some(seat0_username) = seat0_username { - return Ok((seat0_username, true)); - } - - let _ = desktop_manager.try_start_x_session(username, password)?; - log::debug!( - "try_start_x_session, username: {}, {:?}", - &username, - &desktop_manager - ); - Ok(( - desktop_manager.child_username.clone(), - desktop_manager.is_running(), - )) - } else { - Err(XSessionStartError::env( - crate::client::LOGIN_MSG_DESKTOP_NOT_INITED.to_owned(), - )) - } -} - -#[inline] -/// The PRE-AUTH form: connection setup asks this before the peer has authenticated, so it must -/// not run loginctl or wait on the DRM probe (an unauthenticated client would occupy a worker, -/// and every connection would serialize behind the same lookup). It answers from the last -/// settled snapshot and refreshes it off-thread; the decisions that ENFORCE — `get_username`, -/// `try_start_x_session` — stay fresh. -pub fn is_headless() -> bool { - if DESKTOP_MANAGER.lock().unwrap().is_none() { - return false; - } - let cached = SEAT0_SNAPSHOT.lock().unwrap().username.clone(); - kick_seat0_refresh(); - // No snapshot yet answers NOT headless: guessing in the headless direction would show the - // OS-login flow over a live Wayland greeter, which reads as an empty seat0 too. A false - // only delays the headless flow until the first refresh lands, and the snapshot is seeded - // from `start_xdesktop`, so the empty window is server start, not every connection. - cached.map_or(false, |answer| answer.is_none()) -} - -/// A free function on purpose: it runs loginctl (and at a greeter the DRM probe), so no caller -/// may reach it while holding `DESKTOP_MANAGER` — that mutex held across subprocess or IPC waits -/// serializes every connection behind one slow lookup. -fn supported_display_seat0_username() -> Option { - // Read seat0 fresh on every query: the values cached in `DesktopManager::new()` go stale - // across a logout or fast-user-switch, which would skip the greeter probe below and hand - // back the previous session owner. Queried here and not in `new()` also because the read - // there hides greeters. - let seat0_values = get_values_of_seat0(&[0, 2]); - let seat0_username = seat0_values[1].clone(); - #[cfg(feature = "drm")] - if seat0_username.is_empty() || is_gdm_user(&seat0_username) { - if let Some(username) = drm_login_screen_seat0_username() { - return Some(username); - } - } - if seat0_username.is_empty() { - None - } else if is_gdm_user(&seat0_username) - && get_display_server_of_session(&seat0_values[0]) == DISPLAY_SERVER_WAYLAND - { - None - } else { - Some(seat0_username) - } -} - -fn select_newer_seat0_snapshot(current: Seat0Snapshot, candidate: Seat0Snapshot) -> Seat0Snapshot { - if candidate.sequence > current.sequence { - candidate - } else { - current - } -} - -fn refresh_seat0_snapshot() -> Option { - let sequence = SEAT0_QUERY_SEQUENCE.fetch_add(1, Ordering::Relaxed); - let fresh = supported_display_seat0_username(); - let candidate = Seat0Snapshot { - sequence, - username: Some(fresh.clone()), - }; - let mut snapshot = SEAT0_SNAPSHOT.lock().unwrap(); - let current = std::mem::take(&mut *snapshot); - *snapshot = select_newer_seat0_snapshot(current, candidate); - fresh -} - -/// Clears the single-flight flag on every exit, including a panic in the refresh thread; without -/// it a panic would freeze `is_headless` on a stale snapshot for the process lifetime. -struct Seat0RefreshGuard; -impl Drop for Seat0RefreshGuard { - fn drop(&mut self) { - SEAT0_REFRESH_IN_FLIGHT.store(false, Ordering::Release); - } -} - -/// Refresh the snapshot off-thread with a process-wide rate limit and single-flight. -fn kick_seat0_refresh() { - let now = Instant::now(); - { - let mut next_refresh = SEAT0_NEXT_REFRESH.lock().unwrap(); - let (next, should_refresh) = schedule_seat0_refresh(*next_refresh, now); - *next_refresh = next; - if !should_refresh { - return; - } - } - if SEAT0_REFRESH_IN_FLIGHT.swap(true, Ordering::AcqRel) { - return; - } - let guard = Seat0RefreshGuard; - if let Err(err) = std::thread::Builder::new() - .name("seat0-snapshot".into()) - .spawn(move || { - let _guard = guard; - let _ = refresh_seat0_snapshot(); - }) - { - log::warn!("Could not spawn the seat0 snapshot refresh thread: {err}"); - } -} - -/// The Wayland greeter on seat0, if the DRM backend can capture and inject into it. -#[cfg(feature = "drm")] -fn drm_login_screen_seat0_username() -> Option { - // An operator-forced X11 wins over greeter adoption: adopting would rebuild exactly the - // inconsistency the forced gate exists to prevent — a session admitted for DRM serving - // while capture and input route down the X11 path. - if crate::platform::linux::display_server_forced() && crate::platform::linux::is_x11() { - return None; - } - let values = get_values_of_seat0_with_gdm_wayland(&[0, 2]); - if !is_gdm_user(&values[1]) - || get_display_server_of_session(&values[0]) != DISPLAY_SERVER_WAYLAND - { - return None; - } - // The cached tri-state, never the probing form: this runs on the unauthenticated login path, - // so it must not wait out a probe deadline. Only a definitive unavailable hands the seat to - // X11; an unsettled result keeps the maybe-live greeter (settling happens off-thread). - if crate::server::drm_capturer::availability_cached() - == crate::server::drm_capturer::Availability::Unavailable - { - return None; - } - Some(values[1].clone()) -} - -fn cached_username_from_state( - seat0_username: Option, - managed_session: Option<(&str, bool)>, -) -> String { - if let Some(username) = seat0_username { - return username; - } - match managed_session { - Some((username, true)) => username.to_owned(), - _ => String::new(), - } -} - -fn schedule_seat0_refresh(next_refresh: Option, now: Instant) -> (Option, bool) { - if next_refresh.is_some_and(|deadline| now < deadline) { - return (next_refresh, false); - } - (Some(now + SEAT0_REFRESH_INTERVAL), true) -} - -/// Returns the last settled username without running external commands. -pub fn get_cached_username() -> String { - let seat0_username = SEAT0_SNAPSHOT.lock().unwrap().username.clone().flatten(); - let username = { - let manager = DESKTOP_MANAGER.lock().unwrap(); - let Some(manager) = manager.as_ref() else { - return String::new(); - }; - cached_username_from_state( - seat0_username, - Some((&manager.child_username, manager.is_running())), - ) - }; - if username.is_empty() { - kick_seat0_refresh(); - } - username -} - -pub fn get_username() -> String { - if DESKTOP_MANAGER.lock().unwrap().is_none() { - return "".to_owned(); - } - // Computed with the manager lock RELEASED: the lookup runs loginctl, and at a greeter the - // DRM probe, and holding DESKTOP_MANAGER across those waits serializes every caller behind - // one slow probe. - if let Some(seat0_username) = refresh_seat0_snapshot() { - return seat0_username; - } - match &*DESKTOP_MANAGER.lock().unwrap() { - Some(manager) => { - if manager.is_running() && !manager.child_username.is_empty() { - manager.child_username.clone() - } else { - "".to_owned() - } - } - None => "".to_owned(), - } -} - -impl Drop for DesktopManager { - fn drop(&mut self) { - self.stop_children(); - } -} - -impl DesktopManager { - fn fatal_exit() { - std::process::exit(0); - } - - pub fn new() -> Self { - Self { - child_username: "".to_owned(), - child_exit: Arc::new(AtomicBool::new(true)), - is_child_running: Arc::new(AtomicBool::new(false)), - } - } - - #[inline] - fn get_xauth() -> String { - let xauth = get_env_var("XAUTHORITY"); - if xauth.is_empty() { - "/tmp/.Xauthority".to_owned() - } else { - xauth - } - } - - #[inline] - fn is_running(&self) -> bool { - self.is_child_running.load(Ordering::SeqCst) - } - - fn try_start_x_session( - &mut self, - username: &str, - password: &str, - ) -> Result<(), XSessionStartError> { - match get_user_by_name(username) { - Some(userinfo) => { - let mut client = pam::Client::with_password(&pam_get_service_name()) - .map_err(|e| XSessionStartError::env(format!("failed to init pam client, {}", e)))?; - client - .conversation_mut() - .set_credentials(username, password); - match client.authenticate() { - Ok(_) => { - if self.is_running() { - return Ok(()); - } - - match self.start_x_session(&userinfo, username, password) { - Ok(_) => { - log::info!("Succeeded to start x11"); - self.child_username = username.to_string(); - Ok(()) - } - Err(e) => { - Err(XSessionStartError::env(format!( - "failed to start x session, {}", - e - ))) - } - } - } - Err(_e) => { - Err(XSessionStartError::auth( - XSESSION_AUTH_FAILURE_DETAIL.to_owned(), - )) - } - } - } - None => { - Err(XSessionStartError::auth( - XSESSION_AUTH_FAILURE_DETAIL.to_owned(), - )) - } - } - } - - // The logic mainly from https://github.com/neutrinolabs/xrdp/blob/34fe9b60ebaea59e8814bbc3ca5383cabaa1b869/sesman/session.c#L334. - fn get_avail_display() -> ResultType { - let display_range = 0..51; - for i in display_range.clone() { - if Self::is_x_server_running(i) { - continue; - } - return Ok(i); - } - bail!("No available display found in range {:?}", display_range) - } - - #[inline] - fn is_x_server_running(display: u32) -> bool { - Path::new(&format!("/tmp/.X11-unix/X{}", display)).exists() - || Path::new(&format!("/tmp/.X{}-lock", display)).exists() - } - - fn start_x_session( - &mut self, - userinfo: &User, - username: &str, - password: &str, - ) -> ResultType<()> { - self.stop_children(); - - let display_num = Self::get_avail_display()?; - // "xServer_ip:display_num.screen_num" - - let uid = userinfo.uid(); - let gid = userinfo.primary_group_id(); - let envs = HashMap::from([ - ("SHELL", userinfo.shell().to_string_lossy().to_string()), - ("PATH", "/sbin:/bin:/usr/bin:/usr/local/bin".to_owned()), - ("USER", username.to_string()), - ("UID", userinfo.uid().to_string()), - ("HOME", userinfo.home_dir().to_string_lossy().to_string()), - ( - "XDG_RUNTIME_DIR", - format!("/run/user/{}", userinfo.uid().to_string()), - ), - // ("DISPLAY", self.display.clone()), - // ("XAUTHORITY", self.xauth.clone()), - // (ENV_DESKTOP_PROTOCOL, XProtocol::X11.to_string()), - ]); - self.child_exit.store(false, Ordering::SeqCst); - let is_child_running = self.is_child_running.clone(); - - let (tx_res, rx_res) = sync_channel(1); - let password = password.to_string(); - let username = username.to_string(); - // start x11 - std::thread::spawn(move || { - match Self::start_x_session_thread( - tx_res.clone(), - is_child_running, - uid, - gid, - display_num, - username, - password, - envs, - ) { - Ok(_) => {} - Err(e) => { - log::error!("Failed to start x session thread"); - allow_err!(tx_res.send(format!("Failed to start x session thread, {}", e))); - } - } - }); - - // wait x11 - match rx_res.recv_timeout(Duration::from_millis(10_000)) { - Ok(res) => { - if res == "" { - Ok(()) - } else { - bail!(res) - } - } - Err(e) => { - bail!("Failed to recv x11 result {}", e) - } - } - } - - #[inline] - fn display_from_num(num: u32) -> String { - format!(":{num}") - } - - fn start_x_session_thread( - tx_res: SyncSender, - is_child_running: Arc, - uid: u32, - gid: u32, - display_num: u32, - username: String, - password: String, - envs: HashMap<&str, String>, - ) -> ResultType<()> { - let mut client = pam::Client::with_password(&pam_get_service_name())?; - client - .conversation_mut() - .set_credentials(&username, &password); - client.authenticate()?; - - client.set_item(pam::PamItemType::TTY, &Self::display_from_num(display_num))?; - client.open_session()?; - - // fixme: FreeBSD kernel needs to login here. - // see: https://github.com/neutrinolabs/xrdp/blob/a64573b596b5fb07ca3a51590c5308d621f7214e/sesman/session.c#L556 - - let (child_xorg, child_wm) = Self::start_x11(uid, gid, username, display_num, &envs)?; - is_child_running.store(true, Ordering::SeqCst); - - // capture the logind session scope (from a live child) for teardown and crash - // recovery, see reap_session_scope and recover_orphaned_session. - let scope_dir = Self::session_scope_dir(child_xorg.id()); - Self::save_orphaned_marker(&scope_dir, display_num); - - log::info!("Start xorg and wm done, notify and wait xtop x11"); - allow_err!(tx_res.send("".to_owned())); - - Self::wait_stop_x11(child_xorg, child_wm, scope_dir, display_num); - log::info!("Wait x11 stop done"); - Ok(()) - } - - fn wait_xorg_exit(child_xorg: &mut Child) -> ResultType { - if let Ok(_) = child_xorg.kill() { - for _ in 0..3 { - match child_xorg.try_wait() { - Ok(Some(status)) => return Ok(format!("Xorg exit with {}", status)), - Ok(None) => {} - Err(e) => { - // fatal error - log::error!("Failed to wait xorg process, {}", e); - bail!("Failed to wait xorg process, {}", e) - } - } - std::thread::sleep(std::time::Duration::from_millis(1_000)); - } - log::error!("Failed to wait xorg process, not exit"); - bail!("Failed to wait xorg process, not exit") - } else { - Ok("Xorg is already exited".to_owned()) - } - } - - fn add_xauth_cookie( - file: &str, - display: &str, - uid: u32, - gid: u32, - envs: &HashMap<&str, String>, - ) -> ResultType<()> { - let randstr = (0..16) - .map(|_| format!("{:02x}", random::())) - .collect::(); - let output = Command::new("xauth") - .uid(uid) - .gid(gid) - .envs(envs) - .args(vec!["-q", "-f", file, "add", display, ".", &randstr]) - .output()?; - // xauth run success, even the following error occurs. - // Ok(Output { status: ExitStatus(unix_wait_status(0)), stdout: "", stderr: "xauth: file .Xauthority does not exist\n" }) - let errmsg = String::from_utf8_lossy(&output.stderr).to_string(); - if !errmsg.is_empty() { - if !errmsg.contains("does not exist") { - bail!("Failed to launch xauth, {}", errmsg) - } - } - Ok(()) - } - - fn wait_x_server_running(pid: u32, display_num: u32, max_wait_secs: u64) -> ResultType<()> { - let wait_begin = Instant::now(); - loop { - if run_cmds(&format!("ls /proc/{}", pid))?.is_empty() { - bail!("X server exit"); - } - - if Self::is_x_server_running(display_num) { - return Ok(()); - } - if wait_begin.elapsed().as_secs() > max_wait_secs { - bail!("Failed to wait xserver after {} seconds", max_wait_secs); - } - std::thread::sleep(Duration::from_millis(300)); - } - } - - fn start_x11( - uid: u32, - gid: u32, - username: String, - display_num: u32, - envs: &HashMap<&str, String>, - ) -> ResultType<(Child, Child)> { - log::debug!("envs of user {}: {:?}", &username, &envs); - - let xauth = Self::get_xauth(); - let display = Self::display_from_num(display_num); - - Self::add_xauth_cookie(&xauth, &display, uid, gid, &envs)?; - - // Start Xorg - let mut child_xorg = Self::start_x_server(&xauth, &display, uid, gid, &envs)?; - - log::info!("xorg started, wait 10 secs to ensuer x server is running"); - - let max_wait_secs = 10; - // wait x server running - if let Err(e) = Self::wait_x_server_running(child_xorg.id(), display_num, max_wait_secs) { - match Self::wait_xorg_exit(&mut child_xorg) { - Ok(msg) => log::info!("{}", msg), - Err(e) => { - log::error!("{}", e); - Self::fatal_exit(); - } - } - bail!(e) - } - - log::info!( - "xorg is running, start x window manager with DISPLAY: {}, XAUTHORITY: {}", - &display, - &xauth - ); - - std::env::set_var("DISPLAY", &display); - std::env::set_var("XAUTHORITY", &xauth); - // start window manager (startwm.sh) - let child_wm = match Self::start_x_window_manager(uid, gid, &envs) { - Ok(c) => c, - Err(e) => { - match Self::wait_xorg_exit(&mut child_xorg) { - Ok(msg) => log::info!("{}", msg), - Err(e) => { - log::error!("{}", e); - Self::fatal_exit(); - } - } - bail!(e) - } - }; - log::info!("x window manager is started"); - - Ok((child_xorg, child_wm)) - } - - fn try_wait_x11_child_exit(child_xorg: &mut Child, child_wm: &mut Child) -> bool { - match child_xorg.try_wait() { - Ok(Some(status)) => { - log::info!("Xorg exit with {}", status); - return true; - } - Ok(None) => {} - Err(e) => log::error!("Failed to wait xorg process, {}", e), - } - - match child_wm.try_wait() { - Ok(Some(status)) => { - // Logout may result "wm exit with signal: 11 (SIGSEGV) (core dumped)" - log::info!("wm exit with {}", status); - return true; - } - Ok(None) => {} - Err(e) => log::error!("Failed to wait xorg process, {}", e), - } - false - } - - fn wait_x11_children_exit(child_xorg: &mut Child, child_wm: &mut Child) { - log::debug!("Try kill child process xorg"); - if let Ok(_) = child_xorg.kill() { - let mut exited = false; - for _ in 0..2 { - match child_xorg.try_wait() { - Ok(Some(status)) => { - log::info!("Xorg exit with {}", status); - exited = true; - break; - } - Ok(None) => {} - Err(e) => { - log::error!("Failed to wait xorg process, {}", e); - Self::fatal_exit(); - } - } - std::thread::sleep(std::time::Duration::from_millis(1_000)); - } - if !exited { - log::error!("Failed to wait child xorg, after kill()"); - // try kill -9? - } - } - log::debug!("Try kill child process wm"); - if let Ok(_) = child_wm.kill() { - let mut exited = false; - for _ in 0..2 { - match child_wm.try_wait() { - Ok(Some(status)) => { - // Logout may result "wm exit with signal: 11 (SIGSEGV) (core dumped)" - log::info!("wm exit with {}", status); - exited = true; - } - Ok(None) => {} - Err(e) => { - log::error!("Failed to wait wm process, {}", e); - Self::fatal_exit(); - } - } - std::thread::sleep(std::time::Duration::from_millis(1_000)); - } - if !exited { - log::error!("Failed to wait child xorg, after kill()"); - // try kill -9? - } - } - } - - // resolve the "session-.scope" directory pam_systemd put the x session in, read - // from a live child pid. cgroup v2 mounts every cgroup under /sys/fs/cgroup, v1/hybrid - // keeps the scope under the systemd controller mount; pick by the controller field and - // confirm the cgroup is real. empty if there is no such scope (e.g. no logind). - fn session_scope_dir(pid: u32) -> String { - let path = format!("/proc/{}/cgroup", pid); - let content = match std::fs::read_to_string(&path) { - Ok(c) => c, - Err(e) => { - log::warn!("Failed to read {} to find session scope: {}", path, e); - return "".to_owned(); - } - }; - for line in content.lines() { - // "::"; v2 unified is "0::", the v1 - // systemd hierarchy is ":name=systemd:". - let mut fields = line.splitn(3, ':'); - let (controllers, cgroup) = match (fields.next(), fields.next(), fields.next()) { - (Some(_), Some(c), Some(p)) => (c, p), - _ => continue, - }; - let scope = match Self::session_scope(cgroup) { - Some(s) => s, - None => continue, - }; - let mount = if controllers.is_empty() { - "/sys/fs/cgroup" - } else if controllers.split(',').any(|c| c == "name=systemd") { - "/sys/fs/cgroup/systemd" - } else { - continue; - }; - let dir = format!("{}{}", mount, scope); - if Path::new(&format!("{}/cgroup.procs", dir)).exists() { - return dir; - } - } - "".to_owned() - } - - // the "/.../session-.scope" prefix of a cgroup path, dropping any nested child - // cgroup below it so a descendant scope does not get mistaken for the session. - fn session_scope(cgroup: &str) -> Option { - let mut scope = String::new(); - for comp in cgroup.split('/').filter(|c| !c.is_empty()) { - scope.push('/'); - scope.push_str(comp); - if comp.starts_with("session-") && comp.ends_with(".scope") { - return Some(scope); - } - } - None - } - - // on teardown reap the whole session scope subtree, not just the xorg + wm pids: - // the per-session pipewire and other desktop children otherwise outlive them and - // hold the logind session in "closing", leaking sockets + displays on reconnect - // (rustdesk/rustdesk#15183). SIGTERM first so pipewire unlinks its sockets, then - // SIGKILL stragglers; skip our own pid (pam put the service in the scope too). - fn reap_session_scope(scope_dir: &str) { - if scope_dir.is_empty() { - return; - } - let me = std::process::id(); - // spare the --server's own children and any descendants of them sharing this scope - // (see pid_is_spared); only the desktop session's leftovers are reaped. - let spared: Vec = crate::server::CHILD_PROCESS - .lock() - .unwrap() - .iter() - .map(|c| c.id()) - .collect(); - for sig in [hbb_common::libc::SIGTERM, hbb_common::libc::SIGKILL] { - let mut pids = Vec::new(); - Self::collect_scope_pids(Path::new(scope_dir), &mut pids); - let mut any = false; - for pid in pids { - if pid == me || Self::pid_is_spared(pid, &spared, me) { - continue; - } - any = true; - log::info!("Reaping leftover session process {} (signal {})", pid, sig); - unsafe { - if hbb_common::libc::kill(pid as hbb_common::libc::pid_t, sig) != 0 { - let err = std::io::Error::last_os_error(); - // ESRCH = it already exited (or did between snapshot and now). - if err.raw_os_error() != Some(hbb_common::libc::ESRCH) { - log::warn!("Failed to signal session process {}: {}", pid, err); - } - } - } - } - if !any { - break; - } - if sig == hbb_common::libc::SIGTERM { - std::thread::sleep(Duration::from_millis(300)); - } - } - } - - // a tracked --server child (the sudo wrapper run_as_user spawns) or any descendant of - // one: with use_pty sudo runs --cm-no-ui under a monitor with its own pid, so walk the - // parent chain (stopping at the --server) to spare the worker, not just the wrapper. - fn pid_is_spared(pid: u32, spared: &[u32], me: u32) -> bool { - let mut cur = pid; - for _ in 0..32 { - if spared.contains(&cur) { - return true; - } - if cur <= 1 || cur == me { - return false; - } - match Self::parent_pid(cur) { - Some(ppid) => cur = ppid, - None => return false, - } - } - false - } - - fn parent_pid(pid: u32) -> Option { - // /proc//stat is "pid (comm) state ppid ..."; comm can contain spaces and ')', - // so read the fields after the last ')'. - let stat = std::fs::read_to_string(format!("/proc/{}/stat", pid)).ok()?; - stat.rsplit_once(')')? - .1 - .split_whitespace() - .nth(1)? - .parse() - .ok() - } - - // collect every pid in the cgroup subtree rooted at dir. "cgroup.procs" lists only - // the procs directly in a cgroup, so recurse into child cgroup directories to catch - // processes the desktop session moved into descendant scopes. - fn collect_scope_pids(dir: &Path, out: &mut Vec) { - let procs = dir.join("cgroup.procs"); - match std::fs::read_to_string(&procs) { - Ok(content) => { - out.extend(content.lines().filter_map(|l| l.trim().parse::().ok())); - } - Err(e) if e.kind() != std::io::ErrorKind::NotFound => { - log::warn!("Failed to read {}: {}", procs.display(), e); - } - Err(_) => {} - } - let entries = match std::fs::read_dir(dir) { - Ok(e) => e, - Err(e) if e.kind() != std::io::ErrorKind::NotFound => { - log::warn!("Failed to list cgroup dir {}: {}", dir.display(), e); - return; - } - Err(_) => return, - }; - for entry in entries { - let entry = match entry { - Ok(entry) => entry, - Err(e) => { - log::warn!("Failed to read entry under {}: {}", dir.display(), e); - continue; - } - }; - match entry.file_type() { - Ok(t) if t.is_dir() => Self::collect_scope_pids(&entry.path(), out), - Ok(_) => {} - Err(e) if e.kind() != std::io::ErrorKind::NotFound => { - log::warn!("Failed to stat {}: {}", entry.path().display(), e); - } - Err(_) => {} - } - } - } - - // a SIGKILL'd Xorg (how wait_x11_children_exit ends it) leaves "/tmp/.X-lock" and - // "/tmp/.X11-unix/X" behind, and get_avail_display() treats either file as "display - // in use", so the number is never reused and climbs until none are free - // (rustdesk/rustdesk#15183). a clean exit would remove them; do the same on teardown, - // but skip it if a live process still holds the lock: another server could have taken - // the number in the gap, and removing its files would break that display. - fn cleanup_x_display_files(display_num: u32) { - let lock = format!("/tmp/.X{}-lock", display_num); - if let Ok(content) = std::fs::read_to_string(&lock) { - if let Ok(pid) = content.trim().parse::() { - if Self::pid_alive(pid) { - log::info!("X display {} still held by pid {}, leaving its files", display_num, pid); - return; - } - } - } - for path in [lock, format!("/tmp/.X11-unix/X{}", display_num)] { - if let Err(e) = std::fs::remove_file(&path) { - if e.kind() != std::io::ErrorKind::NotFound { - log::warn!("Failed to remove stale X file {}: {}", path, e); - } - } - } - } - - // signal-0 probe: the pid exists if kill succeeds or fails with EPERM (alive but not - // ours); only ESRCH means it is gone. - fn pid_alive(pid: i32) -> bool { - unsafe { - if hbb_common::libc::kill(pid as hbb_common::libc::pid_t, 0) == 0 { - return true; - } - } - std::io::Error::last_os_error().raw_os_error() == Some(hbb_common::libc::EPERM) - } - - const ORPHANED_SESSION_KEY: &'static str = "headless-orphaned-session"; - - fn save_orphaned_marker(scope_dir: &str, display_num: u32) { - // tag the marker with this boot's id: a logind session id is only unique within a - // boot (the counter lives in /run and resets), so recovery must not reap a recorded - // scope path after a reboot, when it may name a different live session. - let boot_id = Self::current_boot_id().unwrap_or_default(); - hbb_common::config::LocalConfig::set_option( - Self::ORPHANED_SESSION_KEY.to_owned(), - format!("{};{};{}", scope_dir, display_num, boot_id), - ); - } - - fn current_boot_id() -> Option { - std::fs::read_to_string("/proc/sys/kernel/random/boot_id") - .ok() - .map(|s| s.trim().to_owned()) - } - - fn clear_orphaned_marker() { - hbb_common::config::LocalConfig::set_option( - Self::ORPHANED_SESSION_KEY.to_owned(), - String::new(), - ); - } - - fn parse_orphaned_marker(marker: &str) -> Option<(&str, u32, &str)> { - let (rest, boot_id) = marker.rsplit_once(';')?; - let (scope_dir, display) = rest.rsplit_once(';')?; - Some((scope_dir, display.trim().parse::().ok()?, boot_id)) - } - - // a run that dies before wait_stop_x11 (service or --server crash) leaks the headless - // session scope + X lock files, the same as a missed teardown (rustdesk/rustdesk#15183). - // reap exactly what the dead run recorded - never a scan, so unrelated sessions are safe. - fn recover_orphaned_session() { - let marker = hbb_common::config::LocalConfig::get_option(Self::ORPHANED_SESSION_KEY); - if marker.is_empty() { - return; - } - if let Some((scope_dir, display_num, boot_id)) = Self::parse_orphaned_marker(&marker) { - // only reap the recorded scope when the marker is from this same boot: a leaked - // cgroup cannot outlive a reboot, so cross-boot there is nothing legitimate to - // reap, and the recorded "session-N.scope" may by then name a different live - // session. the X lock cleanup is pid-guarded, so run it either way. - let same_boot = Self::current_boot_id().map_or(false, |b| b == boot_id); - log::info!( - "Recovering leaked headless session from a previous run: scope {}, display {} (same boot: {})", - scope_dir, - display_num, - same_boot - ); - if same_boot { - Self::reap_session_scope(scope_dir); - } - Self::cleanup_x_display_files(display_num); - } - Self::clear_orphaned_marker(); - } - - fn try_wait_stop_x11( - child_xorg: &mut Child, - child_wm: &mut Child, - scope_dir: &str, - display_num: u32, - ) -> bool { - let mut desktop_manager = DESKTOP_MANAGER.lock().unwrap(); - let mut exited = true; - if let Some(desktop_manager) = &mut (*desktop_manager) { - if desktop_manager.child_exit.load(Ordering::SeqCst) { - exited = true; - } else { - exited = Self::try_wait_x11_child_exit(child_xorg, child_wm); - } - if exited { - log::debug!("Wait x11 children exiting"); - Self::wait_x11_children_exit(child_xorg, child_wm); - Self::reap_session_scope(scope_dir); - Self::cleanup_x_display_files(display_num); - Self::clear_orphaned_marker(); - desktop_manager - .is_child_running - .store(false, Ordering::SeqCst); - desktop_manager.child_exit.store(true, Ordering::SeqCst); - } - } - exited - } - - fn wait_stop_x11( - mut child_xorg: Child, - mut child_wm: Child, - scope_dir: String, - display_num: u32, - ) { - loop { - if Self::try_wait_stop_x11(&mut child_xorg, &mut child_wm, &scope_dir, display_num) { - break; - } - std::thread::sleep(Duration::from_millis(super::SERVICE_INTERVAL)); - } - } - - fn get_xorg() -> &'static str { - // Fedora 26 or later - let xorg = "/usr/libexec/Xorg"; - if Path::new(xorg).is_file() { - return xorg; - } - // Debian 9 or later - let xorg = "/usr/lib/xorg/Xorg"; - if Path::new(xorg).is_file() { - return xorg; - } - // Ubuntu 16.04 or later - let xorg = "/usr/lib/xorg/Xorg"; - if Path::new(xorg).is_file() { - return xorg; - } - // Arch Linux - let xorg = "/usr/lib/xorg-server/Xorg"; - if Path::new(xorg).is_file() { - return xorg; - } - // Arch Linux - let xorg = "/usr/lib/Xorg"; - if Path::new(xorg).is_file() { - return xorg; - } - // CentOS 7 /usr/bin/Xorg or param=Xorg - - log::warn!("Failed to find xorg, use default Xorg.\n Please add \"allowed_users=anybody\" to \"/etc/X11/Xwrapper.config\"."); - "Xorg" - } - - fn start_x_server( - xauth: &str, - display: &str, - uid: u32, - gid: u32, - envs: &HashMap<&str, String>, - ) -> ResultType { - let xorg = Self::get_xorg(); - log::info!("Use xorg: {}", &xorg); - let app_name = crate::get_app_name().to_lowercase(); - let conf = format!("/etc/{app_name}/xorg.conf"); - match Command::new(xorg) - .envs(envs) - .uid(uid) - .gid(gid) - .args(vec![ - "-noreset", - "+extension", - "GLX", - "+extension", - "RANDR", - "+extension", - "RENDER", - "-config", - conf.as_ref(), - "-auth", - xauth, - display, - ]) - .spawn() - { - Ok(c) => Ok(c), - Err(e) => { - bail!("Failed to start Xorg with display {}, {}", display, e); - } - } - } - - fn start_x_window_manager( - uid: u32, - gid: u32, - envs: &HashMap<&str, String>, - ) -> ResultType { - let app_name = crate::get_app_name().to_lowercase(); - match Command::new(&format!("/etc/{app_name}/startwm.sh")) - .envs(envs) - .uid(uid) - .gid(gid) - .spawn() - { - Ok(c) => Ok(c), - Err(e) => { - bail!("Failed to start window manager, {}", e); - } - } - } - - fn stop_children(&mut self) { - self.child_exit.store(true, Ordering::SeqCst); - for _i in 1..10 { - if !self.is_child_running.load(Ordering::SeqCst) { - break; - } - std::thread::sleep(Duration::from_millis(super::SERVICE_INTERVAL)); - } - if self.is_child_running.load(Ordering::SeqCst) { - log::warn!("xdesktop child is still running!"); - } - } -} - -fn pam_get_service_name() -> String { - let app_name = crate::get_app_name().to_lowercase(); - if Path::new(&format!("/etc/pam.d/{app_name}")).is_file() { - app_name - } else { - "gdm".to_owned() - } -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn cached_username_prefers_seat0_and_running_managed_session() { - assert_eq!( - cached_username_from_state(Some("seat0".to_owned()), Some(("managed", true))), - "seat0" - ); - assert_eq!( - cached_username_from_state(None, Some(("managed", true))), - "managed" - ); - assert_eq!( - cached_username_from_state(None, Some(("managed", false))), - "" - ); - assert_eq!(cached_username_from_state(None, None), ""); - } - - #[test] - fn seat0_refresh_schedule_limits_process_wide_rate() { - let started = Instant::now(); - let (next_refresh, should_refresh) = schedule_seat0_refresh(None, started); - assert!(should_refresh); - - let (unchanged, should_refresh) = schedule_seat0_refresh(next_refresh, started); - assert!(!should_refresh); - assert_eq!(unchanged, next_refresh); - - let (_, should_refresh) = - schedule_seat0_refresh(next_refresh, started + SEAT0_REFRESH_INTERVAL); - assert!(should_refresh); - } - - #[test] - fn session_scope_truncates_at_first_scope() { - assert_eq!( - DesktopManager::session_scope("/user.slice/user-1000.slice/session-3.scope").as_deref(), - Some("/user.slice/user-1000.slice/session-3.scope") - ); - // a nested child scope must not be mistaken for the session - assert_eq!( - DesktopManager::session_scope( - "/user.slice/user-1000.slice/session-3.scope/app-foo.scope" - ) - .as_deref(), - Some("/user.slice/user-1000.slice/session-3.scope") - ); - assert_eq!( - DesktopManager::session_scope( - "/user.slice/user-1000.slice/user@1000.service/app.slice/x.service" - ), - None - ); - assert_eq!(DesktopManager::session_scope("/"), None); - } - - #[test] - fn collect_scope_pids_walks_descendant_cgroups() { - // regression for #15183: pids in descendant cgroups must be collected too - let base = std::env::temp_dir().join(format!("rustdesk-cgtest-{}", std::process::id())); - let _ = std::fs::remove_dir_all(&base); - let scope = base.join("session-3.scope"); - let child = scope.join("app-foo.scope"); - let nested = child.join("deeper.scope"); - std::fs::create_dir_all(&nested).unwrap(); - std::fs::create_dir_all(scope.join("empty.scope")).unwrap(); - std::fs::write(scope.join("cgroup.procs"), "100\n101\n").unwrap(); - std::fs::write(scope.join("cgroup.controllers"), "memory pids\n").unwrap(); - std::fs::write(child.join("cgroup.procs"), "200\n").unwrap(); - std::fs::write(nested.join("cgroup.procs"), "300\n").unwrap(); - - let mut pids = Vec::new(); - DesktopManager::collect_scope_pids(&scope, &mut pids); - pids.sort(); - let _ = std::fs::remove_dir_all(&base); - - assert_eq!(pids, vec![100, 101, 200, 300]); - } - - #[test] - fn parses_orphaned_session_marker() { - assert_eq!( - DesktopManager::parse_orphaned_marker( - "/sys/fs/cgroup/user.slice/user-1000.slice/session-3.scope;7;abc-123" - ), - Some(( - "/sys/fs/cgroup/user.slice/user-1000.slice/session-3.scope", - 7, - "abc-123" - )) - ); - // an empty scope still carries the display so its stale X lock can be cleaned - assert_eq!(DesktopManager::parse_orphaned_marker(";5;abc-123"), Some(("", 5, "abc-123"))); - // an empty boot id never matches the live one, so the scope reap is skipped - assert_eq!(DesktopManager::parse_orphaned_marker("/scope;5;"), Some(("/scope", 5, ""))); - assert_eq!(DesktopManager::parse_orphaned_marker(""), None); - assert_eq!(DesktopManager::parse_orphaned_marker("garbage"), None); - // the pre-boot-id two-field format no longer parses, recovery just skips it - assert_eq!(DesktopManager::parse_orphaned_marker("/scope;7"), None); - assert_eq!(DesktopManager::parse_orphaned_marker("/scope;notnum;abc"), None); - } -} diff --git a/src/platform/mod.rs b/src/platform/mod.rs index c1bc38232..d55005b4d 100644 --- a/src/platform/mod.rs +++ b/src/platform/mod.rs @@ -20,9 +20,6 @@ pub mod delegate; #[cfg(target_os = "linux")] pub mod linux; -#[cfg(target_os = "linux")] -pub mod linux_desktop_manager; - #[cfg(target_os = "linux")] pub mod gtk_sudo; diff --git a/src/rendezvous_mediator.rs b/src/rendezvous_mediator.rs index 4f5c8fee8..21a7e23f4 100644 --- a/src/rendezvous_mediator.rs +++ b/src/rendezvous_mediator.rs @@ -143,11 +143,6 @@ impl RendezvousMediator { allow_err!(super::lan::start_listening()); }); } - // It is ok to run xdesktop manager when the headless function is not allowed. - #[cfg(target_os = "linux")] - if crate::is_server() { - crate::platform::linux_desktop_manager::start_xdesktop(); - } scrap::codec::test_av1(); *LAST_NOT_DEPLOYED_REGISTER.lock().await = None; loop { diff --git a/src/server/connection.rs b/src/server/connection.rs index fb7d1a2fe..649f045fc 100644 --- a/src/server/connection.rs +++ b/src/server/connection.rs @@ -12,8 +12,6 @@ use crate::clipboard::{update_clipboard, ClipboardSide}; use crate::clipboard_file::*; #[cfg(target_os = "android")] use crate::keyboard::client::map_key_to_control_key; -#[cfg(target_os = "linux")] -use crate::platform::linux_desktop_manager; #[cfg(any(target_os = "windows", target_os = "linux"))] use crate::platform::WallPaperRemover; #[cfg(windows)] @@ -117,39 +115,6 @@ fn constant_time_eq(a: &[u8], b: &[u8]) -> bool { x == 0 } -#[cfg(target_os = "linux")] -fn should_check_linux_headless_os_auth_before_desktop_start( - is_headless_allowed: bool, - username: &str, -) -> bool { - is_headless_allowed && !username.trim().is_empty() -} - -#[cfg(target_os = "linux")] -fn linux_desktop_start_credentials( - is_headless_allowed: bool, - os_login: Option<&OSLogin>, -) -> Option<(String, String)> { - if !is_headless_allowed { - return None; - } - if let Some(os_login) = os_login.filter(|os_login| !os_login.username.trim().is_empty()) { - return Some((os_login.username.clone(), os_login.password.clone())); - } - Some((String::new(), String::new())) -} - -#[cfg(target_os = "linux")] -fn should_record_linux_headless_os_auth_failure( - is_headless_allowed: bool, - username: &str, - err_msg: &str, -) -> bool { - is_headless_allowed - && !username.trim().is_empty() - && err_msg == crate::client::LOGIN_MSG_PASSWORD_WRONG -} - #[cfg(not(any(target_os = "android", target_os = "ios")))] fn should_use_terminal_os_login_scope(is_terminal: bool, os_login_username: &str) -> bool { cfg!(target_os = "windows") && is_terminal && !os_login_username.trim().is_empty() @@ -208,8 +173,6 @@ struct Session { struct StartCmIpcPara { rx_to_cm: mpsc::UnboundedReceiver, tx_from_cm: mpsc::UnboundedSender, - rx_desktop_ready: mpsc::Receiver<()>, - tx_cm_stream_ready: mpsc::Sender<()>, } #[derive(Debug, Copy, Clone, Eq, PartialEq)] @@ -351,8 +314,6 @@ pub struct Connection { options_in_login: Option, #[cfg(not(any(target_os = "ios")))] pressed_modifiers: HashSet, - #[cfg(target_os = "linux")] - linux_headless_handle: LinuxHeadlessHandle, closed: bool, #[cfg(not(any(target_os = "android", target_os = "ios")))] start_cm_ipc_para: Option, @@ -435,14 +396,10 @@ const SESSION_TIMEOUT: Duration = Duration::from_secs(30); /// Whether the DRM backend can serve a Wayland login screen here. /// -/// The cached probe, not the blocking one: this is a routing gate. Available-only ON PURPOSE, and -/// deliberately NOT symmetric with the seat0 adoption gate: that one only starts Xorg on a -/// definitive Unavailable (never over a maybe-live greeter), while admission only accepts on a -/// definitive Available (never a greeter nothing can yet capture). Both err toward refuse-and-retry -/// during an unsettled probe; admitting there would black-screen a client on a helper-less box. +/// A cold cache probes off-thread; admission still requires a definitive `Available` verdict. #[cfg(all(target_os = "linux", feature = "drm"))] fn drm_can_serve_login_screen() -> bool { - super::drm_capturer::is_available_cached() + super::drm_capturer::availability_cached() == super::drm_capturer::Availability::Available } /// Without the feature nothing can capture a Wayland greeter, so the refusal stands. @@ -484,14 +441,6 @@ impl Connection { let (tx_input, _rx_input) = std_mpsc::channel(); let (tx_from_authed, mut rx_from_authed) = mpsc::unbounded_channel::(); let mut hbbs_rx = crate::hbbs_http::sync::signal_receiver(); - #[cfg(not(any(target_os = "android", target_os = "ios")))] - let (tx_cm_stream_ready, _rx_cm_stream_ready) = mpsc::channel(1); - #[cfg(not(any(target_os = "android", target_os = "ios")))] - let (_tx_desktop_ready, rx_desktop_ready) = mpsc::channel(1); - #[cfg(target_os = "linux")] - let linux_headless_handle = - LinuxHeadlessHandle::new(_rx_cm_stream_ready, _tx_desktop_ready); - let (tx_post_seq, rx_post_seq) = mpsc::unbounded_channel(); tokio::spawn(async move { Self::post_seq_loop(rx_post_seq).await; @@ -568,15 +517,11 @@ impl Connection { options_in_login: None, #[cfg(not(any(target_os = "ios")))] pressed_modifiers: Default::default(), - #[cfg(target_os = "linux")] - linux_headless_handle, closed: false, #[cfg(not(any(target_os = "android", target_os = "ios")))] start_cm_ipc_para: Some(StartCmIpcPara { rx_to_cm, tx_from_cm, - rx_desktop_ready, - tx_cm_stream_ready, }), auto_disconnect_timer: None, authed_conn_id: None, @@ -1854,12 +1799,6 @@ impl Connection { if crate::platform::current_is_wayland() { platform_additions.insert("is_wayland".into(), json!(true)); } - #[cfg(target_os = "linux")] - if crate::platform::is_headless_allowed() { - if linux_desktop_manager::is_headless() { - platform_additions.insert("headless".into(), json!(true)); - } - } } #[cfg(target_os = "windows")] { @@ -2690,14 +2629,7 @@ impl Connection { tokio::spawn(async move { #[cfg(windows)] let tx_from_cm_clone = p.tx_from_cm.clone(); - if let Err(err) = start_ipc( - p.rx_to_cm, - p.tx_from_cm, - p.rx_desktop_ready, - p.tx_cm_stream_ready, - ) - .await - { + if let Err(err) = start_ipc(p.rx_to_cm, p.tx_from_cm).await { log::warn!("ipc to connection manager exit: {}", err); // https://github.com/rustdesk/rustdesk-server-pro/discussions/382#discussioncomment-10525725, cm may start failed #[cfg(windows)] @@ -2831,59 +2763,6 @@ impl Connection { #[cfg(not(any(target_os = "android", target_os = "ios")))] if !should_use_terminal_os_login_scope(self.terminal, &lr.os_login.username) { - #[cfg(not(target_os = "linux"))] - self.try_start_cm_ipc(); - } - - #[cfg(target_os = "linux")] - if should_check_linux_headless_os_auth_before_desktop_start( - self.linux_headless_handle.is_headless_allowed, - &lr.os_login.username, - ) { - let (_failure, res) = self.check_failure(0).await; - if !res { - return true; - } - } - - #[cfg(not(target_os = "linux"))] - let err_msg = "".to_owned(); - #[cfg(target_os = "linux")] - let err_msg = match self - .linux_headless_handle - .try_start_desktop(lr.os_login.as_ref()) - .await - { - LinuxDesktopStartOutcome::Finished(err_msg) => err_msg, - LinuxDesktopStartOutcome::Busy => { - self.send_login_error(crate::client::LOGIN_MSG_DESKTOP_SESSION_NOT_READY) - .await; - return true; - } - }; - - // If err is LOGIN_MSG_DESKTOP_SESSION_NOT_READY, just keep this msg and go on checking password. - if !err_msg.is_empty() && err_msg != crate::client::LOGIN_MSG_DESKTOP_SESSION_NOT_READY - { - #[cfg(target_os = "linux")] - if should_record_linux_headless_os_auth_failure( - self.linux_headless_handle.is_headless_allowed, - &lr.os_login.username, - &err_msg, - ) { - let (failure, res) = self.check_failure(0).await; - if !res { - return true; - } - self.update_failure(failure, false, 0); - } - self.send_login_error(err_msg).await; - return true; - } - - #[cfg(target_os = "linux")] - if !should_use_terminal_os_login_scope(self.terminal, &lr.os_login.username) { - // In headless mode, the desktop check above settles the snapshot used by CM routing. self.try_start_cm_ipc(); } @@ -2930,33 +2809,19 @@ impl Connection { } return true; } else if self.is_recent_session(false) { - if err_msg.is_empty() { - #[cfg(target_os = "linux")] - self.linux_headless_handle.wait_desktop_cm_ready().await; - if !self.send_logon_response_and_keep_alive().await { - return false; - } - self.try_start_cm(lr.my_id.clone(), lr.my_name.clone(), self.authorized); - } else { - self.send_login_error(err_msg).await; + if !self.send_logon_response_and_keep_alive().await { + return false; } + self.try_start_cm(lr.my_id.clone(), lr.my_name.clone(), self.authorized); } else if lr.password.is_empty() { - if err_msg.is_empty() { - #[cfg(not(any(target_os = "android", target_os = "ios")))] - if should_use_terminal_os_login_scope(self.terminal, &lr.os_login.username) { - if let Some(keep_alive) = - self.prepare_terminal_login_for_authorization().await - { - return keep_alive; - } + #[cfg(not(any(target_os = "android", target_os = "ios")))] + if should_use_terminal_os_login_scope(self.terminal, &lr.os_login.username) { + if let Some(keep_alive) = self.prepare_terminal_login_for_authorization().await + { + return keep_alive; } - self.try_start_cm(lr.my_id, lr.my_name, false); - } else { - self.send_login_error( - crate::client::LOGIN_MSG_DESKTOP_SESSION_NOT_READY_PASSWORD_EMPTY, - ) - .await; } + self.try_start_cm(lr.my_id, lr.my_name, false); } else { let (failure, res) = self.check_failure(0).await; if !res { @@ -2965,28 +2830,15 @@ impl Connection { if !self.validate_password(allow_logon_screen_password) { self.update_failure_with_scope(failure, false, 0, FailureScope::Default); self.check_update_temporary_password(false); - if err_msg.is_empty() { - self.send_login_error(crate::client::LOGIN_MSG_PASSWORD_WRONG) - .await; - self.try_start_cm(lr.my_id, lr.my_name, false); - } else { - self.send_login_error( - crate::client::LOGIN_MSG_DESKTOP_SESSION_NOT_READY_PASSWORD_WRONG, - ) + self.send_login_error(crate::client::LOGIN_MSG_PASSWORD_WRONG) .await; - } + self.try_start_cm(lr.my_id, lr.my_name, false); } else { self.update_failure_with_scope(failure, true, 0, FailureScope::Default); - if err_msg.is_empty() { - #[cfg(target_os = "linux")] - self.linux_headless_handle.wait_desktop_cm_ready().await; - if !self.send_logon_response_and_keep_alive().await { - return false; - } - self.try_start_cm(lr.my_id, lr.my_name, self.authorized); - } else { - self.send_login_error(err_msg).await; + if !self.send_logon_response_and_keep_alive().await { + return false; } + self.try_start_cm(lr.my_id, lr.my_name, self.authorized); } } } else if let Some(message::Union::Auth2fa(tfa)) = msg.union { @@ -6139,13 +5991,10 @@ pub fn claim_pending_switch_sides_uuid(id: &str, uuid: &uuid::Uuid) -> bool { #[cfg(not(any(target_os = "android", target_os = "ios")))] // IPC bootstrap summary: -// - Resolve target CM socket (headless/non-headless, optional UID-scoped path on Linux). // - Start CM when missing, then bridge bidirectional messages between this task and CM IPC. async fn start_ipc( mut rx_to_cm: mpsc::UnboundedReceiver, tx_from_cm: mpsc::UnboundedSender, - mut _rx_desktop_ready: mpsc::Receiver<()>, - tx_stream_ready: mpsc::Sender<()>, ) -> ResultType<()> { use hbb_common::anyhow::anyhow; @@ -6155,139 +6004,51 @@ async fn start_ipc( } sleep(1.).await; } - #[cfg(target_os = "linux")] - let headless_cm = crate::is_server() - && crate::platform::is_headless_allowed() - && linux_desktop_manager::is_headless(); - #[cfg(not(target_os = "linux"))] - let headless_cm = false; let mut stream = None; - if !headless_cm { - if let Ok(s) = crate::ipc::connect(1000, "_cm").await { - stream = Some(s); - } + if let Ok(s) = crate::ipc::connect(1000, "_cm").await { + stream = Some(s); } if stream.is_none() { - #[allow(unused_mut)] - #[allow(unused_assignments)] - let mut args = vec!["--cm"]; - #[allow(unused_mut)] - #[cfg(target_os = "linux")] - let mut user = None; - - // Cm run as user, wait until desktop session is ready. - #[cfg(target_os = "linux")] - if headless_cm { - let mut username = linux_desktop_manager::get_cached_username(); - loop { - if !username.is_empty() { - break; + let args = vec!["--cm"]; + let run_done; + if crate::platform::is_root() { + let mut res = Ok(None); + for _ in 0..10 { + #[cfg(not(any(target_os = "linux")))] + { + log::debug!("Start cm"); + res = crate::platform::run_as_user(args.clone()); } - // `_rx_desktop_ready` is used as a wake-up signal from desktop/session state changes - // (for example wait_desktop_cm_ready paths). It is not itself a proof of CM readiness. - let wait_result = timeout(1_000, _rx_desktop_ready.recv()).await; - if matches!(wait_result, Ok(None)) { - return Err(anyhow!( - "Desktop-ready channel closed before a Linux session became available" - )); - } - username = linux_desktop_manager::get_cached_username(); - } - let uid = { - let username_for_cmd = username.clone(); - let mut uid_cmd = hbb_common::tokio::process::Command::new("id"); - // TODO: - // Keep current behavior for now to minimize change risk. - // If usernames starting with '-' are observed in the field, prefer: - // `id -u -- ` to avoid option-parsing ambiguity. - // Already verified that `id -u -- ` works as expected on macOS and Ubuntu 24.04. - uid_cmd.arg("-u").arg(&username_for_cmd).kill_on_drop(true); - let output = timeout(10_000, uid_cmd.output()) - .await - .map_err(|_| anyhow!("Timed out querying uid for {}", username))? - .map_err(|e| anyhow!("Failed to run `id -u {}`: {}", username, e))?; - if !output.status.success() { - bail!("Failed to query uid for {}", username); - } - let output = String::from_utf8_lossy(&output.stdout); - let output = output.trim(); - if output.parse::().is_err() { - bail!("Invalid uid {}", output); - } - output.to_string() - }; - user = Some((uid, username)); - args = vec!["--cm-no-ui"]; - } - #[cfg(target_os = "linux")] - let cm_uid: Option = match &user { - Some((uid, _)) => Some( - uid.parse::() - .map_err(|_| anyhow!("Invalid uid {}", uid))?, - ), - None => None, - }; - #[cfg(target_os = "linux")] - if let Some(uid) = cm_uid { - if let Ok(s) = crate::ipc::connect_for_uid(1000, uid, "_cm").await { - stream = Some(s); - } - } - if stream.is_none() { - let run_done; - if crate::platform::is_root() { - let mut res = Ok(None); - for _ in 0..10 { - #[cfg(not(any(target_os = "linux")))] - { - log::debug!("Start cm"); - res = crate::platform::run_as_user(args.clone()); - } - #[cfg(target_os = "linux")] - { - log::debug!("Start cm"); - res = crate::platform::run_as_user( - args.clone(), - user.clone(), - None::<(&str, &str)>, - ); - } - if res.is_ok() { - break; - } - log::error!("Failed to run cm: {res:?}"); - sleep(1.).await; - } - if let Some(task) = res? { - super::CHILD_PROCESS.lock().unwrap().push(task); - } - run_done = true; - } else { - run_done = false; - } - if !run_done { - log::debug!("Start cm"); - super::CHILD_PROCESS - .lock() - .unwrap() - .push(crate::run_me(args)?); - } - for _ in 0..20 { - sleep(0.3).await; #[cfg(target_os = "linux")] { - if let Some(uid) = cm_uid { - if let Ok(s) = crate::ipc::connect_for_uid(1000, uid, "_cm").await { - stream = Some(s); - break; - } - continue; - } + log::debug!("Start cm"); + res = crate::platform::run_as_user(args.clone(), None, None::<(&str, &str)>); } - if let Ok(s) = crate::ipc::connect(1000, "_cm").await { - stream = Some(s); + if res.is_ok() { break; } + log::error!("Failed to run cm: {res:?}"); + sleep(1.).await; + } + if let Some(task) = res? { + super::CHILD_PROCESS.lock().unwrap().push(task); + } + run_done = true; + } else { + run_done = false; + } + if !run_done { + log::debug!("Start cm"); + super::CHILD_PROCESS + .lock() + .unwrap() + .push(crate::run_me(args)?); + } + for _ in 0..20 { + sleep(0.3).await; + if let Ok(s) = crate::ipc::connect(1000, "_cm").await { + stream = Some(s); + break; } } } @@ -6295,7 +6056,6 @@ async fn start_ipc( bail!("Failed to connect to connection manager"); } - let _res = tx_stream_ready.send(()).await; let mut stream = stream.ok_or(anyhow!("none stream"))?; loop { tokio::select! { @@ -6609,84 +6369,6 @@ impl Drop for Connection { } } -// Login requests are unauthenticated here, so only one may reach loginctl/PAM at a time. -#[cfg(target_os = "linux")] -static LINUX_DESKTOP_START_IN_FLIGHT: std::sync::atomic::AtomicBool = - std::sync::atomic::AtomicBool::new(false); - -#[cfg(target_os = "linux")] -struct LinuxDesktopStartGuard; - -#[cfg(target_os = "linux")] -impl Drop for LinuxDesktopStartGuard { - fn drop(&mut self) { - LINUX_DESKTOP_START_IN_FLIGHT.store(false, Ordering::Release); - } -} - -#[cfg(target_os = "linux")] -enum LinuxDesktopStartOutcome { - Finished(String), - Busy, -} - -#[cfg(target_os = "linux")] -struct LinuxHeadlessHandle { - pub is_headless_allowed: bool, - pub wait_ipc_timeout: u64, - pub rx_cm_stream_ready: mpsc::Receiver<()>, - pub tx_desktop_ready: mpsc::Sender<()>, -} - -#[cfg(target_os = "linux")] -impl LinuxHeadlessHandle { - pub fn new(rx_cm_stream_ready: mpsc::Receiver<()>, tx_desktop_ready: mpsc::Sender<()>) -> Self { - let is_headless_allowed = crate::is_server() && crate::platform::is_headless_allowed(); - Self { - is_headless_allowed, - wait_ipc_timeout: 10_000, - rx_cm_stream_ready, - tx_desktop_ready, - } - } - - pub async fn try_start_desktop( - &mut self, - os_login: Option<&OSLogin>, - ) -> LinuxDesktopStartOutcome { - let Some((username, password)) = - linux_desktop_start_credentials(self.is_headless_allowed, os_login) - else { - return LinuxDesktopStartOutcome::Finished(String::new()); - }; - if LINUX_DESKTOP_START_IN_FLIGHT.swap(true, Ordering::AcqRel) { - return LinuxDesktopStartOutcome::Busy; - } - let guard = LinuxDesktopStartGuard; - let err_msg = match tokio::task::spawn_blocking(move || { - let _guard = guard; - linux_desktop_manager::try_start_desktop(&username, &password) - }) - .await - { - Ok(err_msg) => err_msg, - Err(err) => { - log::error!("Linux desktop start task failed: {err}"); - crate::client::LOGIN_MSG_DESKTOP_XSESSION_FAILED.to_owned() - } - }; - LinuxDesktopStartOutcome::Finished(err_msg) - } - - pub async fn wait_desktop_cm_ready(&mut self) { - // A value captured at construction can lag behind a seat0 transition. - if self.is_headless_allowed && linux_desktop_manager::is_headless() { - self.tx_desktop_ready.send(()).await.ok(); - let _res = timeout(self.wait_ipc_timeout, self.rx_cm_stream_ready.recv()).await; - } - } -} - extern "C" fn connection_shutdown_hook() { // https://stackoverflow.com/questions/35980148/why-does-an-atexit-handler-panic-when-it-accesses-stdout // Please make sure there is no print in the call stack diff --git a/src/server/drm_capturer.rs b/src/server/drm_capturer.rs index 0c6beb493..fb7719b80 100644 --- a/src/server/drm_capturer.rs +++ b/src/server/drm_capturer.rs @@ -821,15 +821,14 @@ impl Drop for UinputRefreshGuard { } } -/// Never probes, never blocks: the form the ROUTING gates must use. Seconds of IPC inside -/// `wayland::clear()`, `is_inited()` or the display enumeration trips "deadline has elapsed". +/// Never probes or blocks. Use in hot paths such as `wayland::clear()`, `is_inited()`, and display +/// enumeration, where seconds of IPC would trip "deadline has elapsed". pub(crate) fn is_available_cached() -> bool { matches!(&*DRM_STATE.lock().unwrap(), ProbeState::Available(..)) } -/// The three honest answers the availability machinery can give. `Unsettled` — another probe in -/// flight, or a failure still below the disable threshold — is not a verdict, and the -/// login-screen headless decision must not read it as one. +/// A tri-state assessment of DRM capture availability. +/// `Unsettled` means a probe is in flight or failures have not reached the disable threshold. #[derive(Clone, Copy, PartialEq, Eq)] pub(crate) enum Availability { Available, @@ -843,9 +842,8 @@ pub(crate) enum Availability { fn availability() -> Availability { let (verdict, stale_no) = { let st = DRM_STATE.lock().unwrap(); - // A settled "no" STAYS the answer while an off-thread re-probe re-verifies it; going - // Unknown at expiry would reopen an Unsettled window every TTL on a helper-less box, and - // the login decision reads Unsettled as a possible greeter. + // Keep a settled "no" while an off-thread probe re-verifies it, avoiding a transient + // Unsettled result whenever the negative cache expires. let stale_no = matches!(&*st, ProbeState::Unavailable(since) if since.elapsed() >= NEGATIVE_TTL); let verdict = match &*st { @@ -878,10 +876,8 @@ fn availability() -> Availability { probe_and_publish() } -/// The non-blocking tri-state, for decisions on the LOGIN REQUEST path that must never wait: an -/// unauthenticated peer reaches that path, so a probe there would let it park a worker for the -/// probe deadline. Unknown kicks the probe off-thread and answers Unsettled, which the login -/// decision treats as a possibly servable greeter (no Xorg) until the state settles. +/// Non-blocking login-path assessment. +/// Unknown starts a probe off-thread; callers require `Available` before admitting a session. pub(crate) fn availability_cached() -> Availability { let (verdict, stale_no) = { let st = DRM_STATE.lock().unwrap(); diff --git a/src/ui/common.tis b/src/ui/common.tis index a1a0b8fac..8b90b4a43 100644 --- a/src/ui/common.tis +++ b/src/ui/common.tis @@ -272,30 +272,6 @@ function msgbox(type, title, content, link="", callback=null, height=180, width= handler.send2fa(res.code, res.trust_this_device || false); msgbox("connecting", "Connecting...", "Logging in..."); }; - } else if (type == "session-login" || type == "session-re-login") { - callback = function (res) { - if (!res) { - view.close(); - return; - } - handler.login(res.osusername, res.ospassword, "", false); - if (!is_port_forward) { - if (is_file_transfer) handler.msgbox("connecting", "Connecting...", "Logging in..."); - else msgbox("connecting", "Connecting...", "Logging in..."); - } - }; - } else if (type.indexOf("session-login") >= 0) { - callback = function (res) { - if (!res) { - view.close(); - return; - } - handler.login(res.osusername, res.ospassword, res.password, res.remember); - if (!is_port_forward) { - if (is_file_transfer) handler.msgbox("connecting", "Connecting...", "Logging in..."); - else msgbox("connecting", "Connecting...", "Logging in..."); - } - }; } else if (type.indexOf("insecure-connection") >= 0) { callback = function (res) { if (!res) { diff --git a/src/ui/msgbox.tis b/src/ui/msgbox.tis index 58547ce58..14b0bae02 100644 --- a/src/ui/msgbox.tis +++ b/src/ui/msgbox.tis @@ -41,7 +41,7 @@ class MsgboxComponent: Reactor.Component { } function getIcon(color) { - if (this.type == "input-password" || this.type == "session-login" || this.type == "session-login-password" || this.type == "input-2fa") { + if (this.type == "input-password" || this.type == "input-2fa") { return ; } if (this.type == "connecting") { @@ -50,7 +50,7 @@ class MsgboxComponent: Reactor.Component { if (this.type == "success") { return ; } - if (this.type.indexOf("error") >= 0 || this.type == "re-input-password" || this.type == "input-2fa" || this.type == "session-re-login" || this.type == "session-login-re-password") { + if (this.type.indexOf("error") >= 0 || this.type == "re-input-password" || this.type == "input-2fa") { return ; } return null; @@ -74,37 +74,11 @@ class MsgboxComponent: Reactor.Component { ; } - function getInputUserPasswordContent() { - return
-
{translate("OS Username")}
-
-
{translate("OS Password")}
- -
-
; - } - - function getXsessionPasswordContent() { - return
-
{translate("OS Username")}
-
-
{translate("OS Password")}
- -
{translate('Please enter your password')}
- -
{translate('Remember password')}
-
; - } - function getContent() { if (this.type == "input-password") { return this.getInputPasswordContent(); } else if (this.type == "input-2fa") { return this.get2faContent(); - } else if (this.type == "session-login") { - return this.getInputUserPasswordContent(); - } else if (this.type == "session-login-password") { - return this.getXsessionPasswordContent(); } else if (this.type == "custom-os-password") { var ts = this.autoLogin ? { checked: true } : {}; return
@@ -116,13 +90,13 @@ class MsgboxComponent: Reactor.Component { } function getColor() { - if (this.type == "input-password" || this.type == "input-2fa" || this.type == "custom-os-password" || this.type == "session-login" || this.type == "session-login-password") { + if (this.type == "input-password" || this.type == "input-2fa" || this.type == "custom-os-password") { return "#AD448E"; } if (this.type == "success") { return "#32bea6"; } - if (this.type.indexOf("error") >= 0 || this.type == "re-input-password" || this.type == "session-re-login" || this.type == "session-login-re-password") { + if (this.type.indexOf("error") >= 0 || this.type == "re-input-password") { return "#e04f5f"; } return "#2C8CFF"; @@ -242,16 +216,6 @@ class MsgboxComponent: Reactor.Component { this.update(); return; } - if (this.type == "session-re-login") { - this.type = "session-login"; - this.update(); - return; - } - if (this.type == "session-login-re-password") { - this.type = "session-login-password"; - this.update(); - return; - } var values = this.getValues(); if (this.callback) { var self = this; @@ -352,21 +316,6 @@ class MsgboxComponent: Reactor.Component { return; } } - if (this.type == "session-login") { - values.osusername = (values.osusername || "").trim(); - values.ospassword = (values.ospassword || "").trim(); - if (!values.osusername || !values.ospassword) { - return; - } - } - if (this.type == "session-login-password") { - values.password = (values.password || "").trim(); - values.osusername = (values.osusername || "").trim(); - values.ospassword = (values.ospassword || "").trim(); - if (!values.osusername || !values.ospassword || !values.password) { - return; - } - } if (this.type == "multiple-sessions-nocancel") { values.sid = (this.$$(select))[0].value; }