From da7bcf89d400db54bb0a1b158f5a02a4228f4b56 Mon Sep 17 00:00:00 2001 From: fufesou Date: Fri, 6 Oct 2023 21:31:37 +0800 Subject: [PATCH] fix, wayland --server, envs Signed-off-by: fufesou --- src/platform/linux.rs | 110 +++++++++++++++++++++++++++++---------- src/server/connection.rs | 6 ++- 2 files changed, 88 insertions(+), 28 deletions(-) diff --git a/src/platform/linux.rs b/src/platform/linux.rs index de8c9d732..8ab7693b0 100644 --- a/src/platform/linux.rs +++ b/src/platform/linux.rs @@ -14,6 +14,7 @@ use hbb_common::{ }; use std::{ cell::RefCell, + ffi::OsStr, io::Write, path::{Path, PathBuf}, process::{Child, Command}, @@ -195,17 +196,29 @@ fn start_uinput_service() { } #[inline] -fn try_start_server_(user: Option<(String, String)>) -> ResultType> { - if user.is_some() { - run_as_user(vec!["--server"], user) - } else { - Ok(Some(crate::run_me(vec!["--server"])?)) +fn try_start_server_(desktop: Option<&Desktop>) -> ResultType> { + match desktop { + Some(desktop) => { + let mut envs = vec![]; + if !desktop.display.is_empty() { + envs.push(("DISPLAY", desktop.display.clone())); + } + if !desktop.xauth.is_empty() { + envs.push(("XAUTHORITY", desktop.xauth.clone())); + } + run_as_user( + vec!["--server"], + Some((desktop.uid.clone(), desktop.username.clone())), + envs, + ) + } + None => Ok(Some(crate::run_me(vec!["--server"])?)), } } #[inline] -fn start_server(user: Option<(String, String)>, server: &mut Option) { - match try_start_server_(user) { +fn start_server(desktop: Option<&Desktop>, server: &mut Option) { + match try_start_server_(desktop) { Ok(ps) => *server = ps, Err(err) => { log::error!("Failed to start server: {}", err); @@ -257,6 +270,7 @@ fn stop_subprocess() { fn should_start_server( try_x11: bool, + is_display_changed: bool, uid: &mut String, desktop: &Desktop, cm0: &mut bool, @@ -273,7 +287,7 @@ fn should_start_server( *uid = "".to_owned(); should_kill = true; } - } else if desktop.uid != *uid && !desktop.uid.is_empty() { + } else if is_display_changed || desktop.uid != *uid && !desktop.uid.is_empty() { *uid = desktop.uid.clone(); if try_x11 { set_x11_env(&desktop); @@ -335,6 +349,7 @@ pub fn start_os_service() { let running = Arc::new(AtomicBool::new(true)); let r = running.clone(); + let (mut display, mut xauth): (String, String) = ("".to_owned(), "".to_owned()); let mut desktop = Desktop::default(); let mut sid = "".to_owned(); let mut uid = "".to_owned(); @@ -357,8 +372,10 @@ pub fn start_os_service() { // try kill subprocess "--server" stop_server(&mut user_server); // try start subprocess "--server" + // No need to check is_display_changed here. if should_start_server( true, + false, &mut uid, &desktop, &mut cm0, @@ -373,9 +390,14 @@ pub fn start_os_service() { // try kill subprocess "--server" stop_server(&mut server); + let is_display_changed = desktop.display != display || desktop.xauth != xauth; + display = desktop.display.clone(); + xauth = desktop.xauth.clone(); + // try start subprocess "--server" if should_start_server( false, + is_display_changed, &mut uid, &desktop, &mut cm0, @@ -384,10 +406,7 @@ pub fn start_os_service() { ) { stop_subprocess(); force_stop_server(); - start_server( - Some((desktop.uid.clone(), desktop.username.clone())), - &mut user_server, - ); + start_server(Some(&desktop), &mut user_server); } } else { force_stop_server(); @@ -541,7 +560,16 @@ fn is_opensuse() -> bool { false } -pub fn run_as_user(arg: Vec<&str>, user: Option<(String, String)>) -> ResultType> { +pub fn run_as_user( + arg: Vec<&str>, + user: Option<(String, String)>, + envs: I, +) -> ResultType> +where + I: IntoIterator, + K: AsRef, + V: AsRef, +{ let (uid, username) = match user { Some(id_name) => id_name, None => get_active_user_id_name(), @@ -558,7 +586,7 @@ pub fn run_as_user(arg: Vec<&str>, user: Option<(String, String)>) -> ResultType args.insert(0, "-E"); } - let task = Command::new("sudo").args(args).spawn()?; + let task = Command::new("sudo").envs(envs).args(args).spawn()?; Ok(Some(task)) } @@ -652,7 +680,7 @@ pub(super) fn get_env_tries(name: &str, uid: &str, process: &str, n: usize) -> S #[inline] fn get_env(name: &str, uid: &str, process: &str) -> String { - let cmd = format!("ps -u {} -f | grep '{}' | grep -v 'grep' | tail -1 | awk '{{print $2}}' | xargs -I__ cat /proc/__/environ 2>/dev/null | tr '\\0' '\\n' | grep '^{}=' | tail -1 | sed 's/{}=//g'", uid, process, name, name); + let cmd = format!("ps -u {} -f | grep -E '{}' | grep -v 'grep' | tail -1 | awk '{{print $2}}' | xargs -I__ cat /proc/__/environ 2>/dev/null | tr '\\0' '\\n' | grep '^{}=' | tail -1 | sed 's/{}=//g'", uid, process, name, name); if let Ok(x) = run_cmds(&cmd) { x.trim_end().to_string() } else { @@ -887,9 +915,11 @@ mod desktop { use super::*; pub const XFCE4_PANEL: &str = "xfce4-panel"; - pub const GNOME_SESSION_BINARY: &str = "gnome-session-binary"; pub const SDDM_GREETER: &str = "sddm-greeter"; - pub const PLASMA_X11: &str = "startplasma-x11"; + + const PLASMA_KDED5: &str = "kded5"; + const GNOME_GOA_DAEMON: &str = "goa-daemon"; + const RUSTDESK_TRAY: &str = "rustdesk +--tray"; #[derive(Debug, Clone, Default)] pub struct Desktop { @@ -918,10 +948,30 @@ mod desktop { self.sid.is_empty() || self.is_rustdesk_subprocess } - fn get_display(&mut self) { - let display_envs = vec![GNOME_SESSION_BINARY, XFCE4_PANEL, SDDM_GREETER, PLASMA_X11]; - for diplay_env in display_envs { - self.display = get_env_tries("DISPLAY", &self.uid, diplay_env, 10); + fn get_display_wayland(&mut self) { + let display_proc = vec![PLASMA_KDED5, GNOME_GOA_DAEMON, RUSTDESK_TRAY]; + for proc in display_proc { + self.display = get_env("DISPLAY", &self.uid, proc); + if !self.display.is_empty() { + break; + } + } + } + + fn get_xauth_wayland(&mut self) { + let display_proc = vec![PLASMA_KDED5, GNOME_GOA_DAEMON, RUSTDESK_TRAY]; + for proc in display_proc { + self.xauth = get_env("XAUTHORITY", &self.uid, proc); + if !self.xauth.is_empty() { + break; + } + } + } + + fn get_display_x11(&mut self) { + let display_envs = vec![PLASMA_KDED5, GNOME_GOA_DAEMON, XFCE4_PANEL, SDDM_GREETER]; + for display_env in display_envs { + self.display = get_env_tries("DISPLAY", &self.uid, display_env, 10); if !self.display.is_empty() { break; } @@ -980,9 +1030,9 @@ mod desktop { } } - fn get_xauth(&mut self) { + fn get_xauth_x11(&mut self) { // try by direct access to window manager process by name - let display_envs = vec![GNOME_SESSION_BINARY, XFCE4_PANEL, SDDM_GREETER, PLASMA_X11]; + let display_envs = vec![PLASMA_KDED5, GNOME_GOA_DAEMON, XFCE4_PANEL, SDDM_GREETER]; for diplay_env in display_envs { self.xauth = get_env_tries("XAUTHORITY", &self.uid, diplay_env, 10); if !self.xauth.is_empty() { @@ -1088,16 +1138,22 @@ mod desktop { self.uid = seat0_values[1].clone(); self.username = seat0_values[2].clone(); self.protocal = get_display_server_of_session(&self.sid).into(); - if self.is_wayland() { + if self.is_login_wayland() { self.display = "".to_owned(); self.xauth = "".to_owned(); self.is_rustdesk_subprocess = false; return; } - self.get_display(); - self.get_xauth(); - self.set_is_subprocess(); + if self.is_wayland() { + self.get_display_wayland(); + self.get_xauth_wayland(); + self.is_rustdesk_subprocess = false; + } else { + self.get_display_x11(); + self.get_xauth_x11(); + self.set_is_subprocess(); + } } } } diff --git a/src/server/connection.rs b/src/server/connection.rs index 35538a85a..7da5e4086 100644 --- a/src/server/connection.rs +++ b/src/server/connection.rs @@ -2522,7 +2522,11 @@ async fn start_ipc( #[cfg(target_os = "linux")] { log::debug!("Start cm"); - res = crate::platform::run_as_user(args.clone(), user.clone()); + res = crate::platform::run_as_user( + args.clone(), + user.clone(), + None::<(&str, &str)>, + ); } if res.is_ok() { break;