Merge pull request #5935 from fufesou/fix/xwayland_server_envs
Fix/xwayland server envs
This commit is contained in:
		
						commit
						c7bc2ca82d
					
				| @ -14,6 +14,7 @@ use hbb_common::{ | |||||||
| }; | }; | ||||||
| use std::{ | use std::{ | ||||||
|     cell::RefCell, |     cell::RefCell, | ||||||
|  |     ffi::OsStr, | ||||||
|     io::Write, |     io::Write, | ||||||
|     path::{Path, PathBuf}, |     path::{Path, PathBuf}, | ||||||
|     process::{Child, Command}, |     process::{Child, Command}, | ||||||
| @ -195,17 +196,29 @@ fn start_uinput_service() { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| #[inline] | #[inline] | ||||||
| fn try_start_server_(user: Option<(String, String)>) -> ResultType<Option<Child>> { | fn try_start_server_(desktop: Option<&Desktop>) -> ResultType<Option<Child>> { | ||||||
|     if user.is_some() { |     match desktop { | ||||||
|         run_as_user(vec!["--server"], user) |         Some(desktop) => { | ||||||
|     } else { |             let mut envs = vec![]; | ||||||
|         Ok(Some(crate::run_me(vec!["--server"])?)) |             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] | #[inline] | ||||||
| fn start_server(user: Option<(String, String)>, server: &mut Option<Child>) { | fn start_server(desktop: Option<&Desktop>, server: &mut Option<Child>) { | ||||||
|     match try_start_server_(user) { |     match try_start_server_(desktop) { | ||||||
|         Ok(ps) => *server = ps, |         Ok(ps) => *server = ps, | ||||||
|         Err(err) => { |         Err(err) => { | ||||||
|             log::error!("Failed to start server: {}", err); |             log::error!("Failed to start server: {}", err); | ||||||
| @ -257,6 +270,7 @@ fn stop_subprocess() { | |||||||
| 
 | 
 | ||||||
| fn should_start_server( | fn should_start_server( | ||||||
|     try_x11: bool, |     try_x11: bool, | ||||||
|  |     is_display_changed: bool, | ||||||
|     uid: &mut String, |     uid: &mut String, | ||||||
|     desktop: &Desktop, |     desktop: &Desktop, | ||||||
|     cm0: &mut bool, |     cm0: &mut bool, | ||||||
| @ -273,7 +287,7 @@ fn should_start_server( | |||||||
|             *uid = "".to_owned(); |             *uid = "".to_owned(); | ||||||
|             should_kill = true; |             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(); |         *uid = desktop.uid.clone(); | ||||||
|         if try_x11 { |         if try_x11 { | ||||||
|             set_x11_env(&desktop); |             set_x11_env(&desktop); | ||||||
| @ -335,6 +349,7 @@ pub fn start_os_service() { | |||||||
| 
 | 
 | ||||||
|     let running = Arc::new(AtomicBool::new(true)); |     let running = Arc::new(AtomicBool::new(true)); | ||||||
|     let r = running.clone(); |     let r = running.clone(); | ||||||
|  |     let (mut display, mut xauth): (String, String) = ("".to_owned(), "".to_owned()); | ||||||
|     let mut desktop = Desktop::default(); |     let mut desktop = Desktop::default(); | ||||||
|     let mut sid = "".to_owned(); |     let mut sid = "".to_owned(); | ||||||
|     let mut uid = "".to_owned(); |     let mut uid = "".to_owned(); | ||||||
| @ -357,8 +372,10 @@ pub fn start_os_service() { | |||||||
|             // try kill subprocess "--server"
 |             // try kill subprocess "--server"
 | ||||||
|             stop_server(&mut user_server); |             stop_server(&mut user_server); | ||||||
|             // try start subprocess "--server"
 |             // try start subprocess "--server"
 | ||||||
|  |             // No need to check is_display_changed here.
 | ||||||
|             if should_start_server( |             if should_start_server( | ||||||
|                 true, |                 true, | ||||||
|  |                 false, | ||||||
|                 &mut uid, |                 &mut uid, | ||||||
|                 &desktop, |                 &desktop, | ||||||
|                 &mut cm0, |                 &mut cm0, | ||||||
| @ -373,9 +390,14 @@ pub fn start_os_service() { | |||||||
|             // try kill subprocess "--server"
 |             // try kill subprocess "--server"
 | ||||||
|             stop_server(&mut 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"
 |             // try start subprocess "--server"
 | ||||||
|             if should_start_server( |             if should_start_server( | ||||||
|                 false, |                 false, | ||||||
|  |                 is_display_changed, | ||||||
|                 &mut uid, |                 &mut uid, | ||||||
|                 &desktop, |                 &desktop, | ||||||
|                 &mut cm0, |                 &mut cm0, | ||||||
| @ -384,10 +406,7 @@ pub fn start_os_service() { | |||||||
|             ) { |             ) { | ||||||
|                 stop_subprocess(); |                 stop_subprocess(); | ||||||
|                 force_stop_server(); |                 force_stop_server(); | ||||||
|                 start_server( |                 start_server(Some(&desktop), &mut user_server); | ||||||
|                     Some((desktop.uid.clone(), desktop.username.clone())), |  | ||||||
|                     &mut user_server, |  | ||||||
|                 ); |  | ||||||
|             } |             } | ||||||
|         } else { |         } else { | ||||||
|             force_stop_server(); |             force_stop_server(); | ||||||
| @ -541,7 +560,16 @@ fn is_opensuse() -> bool { | |||||||
|     false |     false | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| pub fn run_as_user(arg: Vec<&str>, user: Option<(String, String)>) -> ResultType<Option<Child>> { | pub fn run_as_user<I, K, V>( | ||||||
|  |     arg: Vec<&str>, | ||||||
|  |     user: Option<(String, String)>, | ||||||
|  |     envs: I, | ||||||
|  | ) -> ResultType<Option<Child>> | ||||||
|  | where | ||||||
|  |     I: IntoIterator<Item = (K, V)>, | ||||||
|  |     K: AsRef<OsStr>, | ||||||
|  |     V: AsRef<OsStr>, | ||||||
|  | { | ||||||
|     let (uid, username) = match user { |     let (uid, username) = match user { | ||||||
|         Some(id_name) => id_name, |         Some(id_name) => id_name, | ||||||
|         None => get_active_user_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"); |         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)) |     Ok(Some(task)) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| @ -639,20 +667,9 @@ pub fn is_installed() -> bool { | |||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| pub(super) fn get_env_tries(name: &str, uid: &str, process: &str, n: usize) -> String { |  | ||||||
|     for _ in 0..n { |  | ||||||
|         let x = get_env(name, uid, process); |  | ||||||
|         if !x.is_empty() { |  | ||||||
|             return x; |  | ||||||
|         } |  | ||||||
|         sleep_millis(300); |  | ||||||
|     } |  | ||||||
|     "".to_owned() |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| #[inline] | #[inline] | ||||||
| fn get_env(name: &str, uid: &str, process: &str) -> String { | 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) { |     if let Ok(x) = run_cmds(&cmd) { | ||||||
|         x.trim_end().to_string() |         x.trim_end().to_string() | ||||||
|     } else { |     } else { | ||||||
| @ -883,13 +900,25 @@ pub fn change_resolution_directly(name: &str, width: usize, height: usize) -> Re | |||||||
|     Ok(()) |     Ok(()) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | #[inline] | ||||||
|  | pub fn is_xwayland_running() -> bool { | ||||||
|  |     if let Ok(output) = run_cmds("pgrep -a Xwayland") { | ||||||
|  |         return output.contains("Xwayland"); | ||||||
|  |     } | ||||||
|  |     false | ||||||
|  | } | ||||||
|  | 
 | ||||||
| mod desktop { | mod desktop { | ||||||
|     use super::*; |     use super::*; | ||||||
| 
 | 
 | ||||||
|     pub const XFCE4_PANEL: &str = "xfce4-panel"; |     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 SDDM_GREETER: &str = "sddm-greeter"; | ||||||
|     pub const PLASMA_X11: &str = "startplasma-x11"; | 
 | ||||||
|  |     const XWAYLAND: &str = "Xwayland"; | ||||||
|  |     const IBUS_DAEMON: &str = "ibus-daemon"; | ||||||
|  |     const PLASMA_KDED5: &str = "kded5"; | ||||||
|  |     const GNOME_GOA_DAEMON: &str = "goa-daemon"; | ||||||
|  |     const RUSTDESK_TRAY: &str = "rustdesk +--tray"; | ||||||
| 
 | 
 | ||||||
|     #[derive(Debug, Clone, Default)] |     #[derive(Debug, Clone, Default)] | ||||||
|     pub struct Desktop { |     pub struct Desktop { | ||||||
| @ -918,14 +947,44 @@ mod desktop { | |||||||
|             self.sid.is_empty() || self.is_rustdesk_subprocess |             self.sid.is_empty() || self.is_rustdesk_subprocess | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         fn get_display(&mut self) { |         fn get_display_xauth_xwayland(&mut self) { | ||||||
|             let display_envs = vec![GNOME_SESSION_BINARY, XFCE4_PANEL, SDDM_GREETER, PLASMA_X11]; |             for _ in 0..5 { | ||||||
|             for diplay_env in display_envs { |                 let display_proc = vec![ | ||||||
|                 self.display = get_env_tries("DISPLAY", &self.uid, diplay_env, 10); |                     XWAYLAND, | ||||||
|  |                     IBUS_DAEMON, | ||||||
|  |                     GNOME_GOA_DAEMON, | ||||||
|  |                     PLASMA_KDED5, | ||||||
|  |                     RUSTDESK_TRAY, | ||||||
|  |                 ]; | ||||||
|  |                 for proc in display_proc { | ||||||
|  |                     self.display = get_env("DISPLAY", &self.uid, proc); | ||||||
|  |                     self.xauth = get_env("XAUTHORITY", &self.uid, proc); | ||||||
|  |                     if !self.display.is_empty() && !self.xauth.is_empty() { | ||||||
|  |                         break; | ||||||
|  |                     } | ||||||
|  |                 } | ||||||
|  |                 sleep_millis(300); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         fn get_display_x11(&mut self) { | ||||||
|  |             for _ in 0..10 { | ||||||
|  |                 let display_proc = vec![ | ||||||
|  |                     XWAYLAND, | ||||||
|  |                     IBUS_DAEMON, | ||||||
|  |                     GNOME_GOA_DAEMON, | ||||||
|  |                     PLASMA_KDED5, | ||||||
|  |                     XFCE4_PANEL, | ||||||
|  |                     SDDM_GREETER, | ||||||
|  |                 ]; | ||||||
|  |                 for proc in display_proc { | ||||||
|  |                     self.display = get_env("DISPLAY", &self.uid, proc); | ||||||
|                     if !self.display.is_empty() { |                     if !self.display.is_empty() { | ||||||
|                         break; |                         break; | ||||||
|                     } |                     } | ||||||
|                 } |                 } | ||||||
|  |                 sleep_millis(300); | ||||||
|  |             } | ||||||
| 
 | 
 | ||||||
|             if self.display.is_empty() { |             if self.display.is_empty() { | ||||||
|                 self.display = Self::get_display_by_user(&self.username); |                 self.display = Self::get_display_by_user(&self.username); | ||||||
| @ -980,15 +1039,25 @@ mod desktop { | |||||||
|             } |             } | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         fn get_xauth(&mut self) { |         fn get_xauth_x11(&mut self) { | ||||||
|             // try by direct access to window manager process by name
 |             // try by direct access to window manager process by name
 | ||||||
|             let display_envs = vec![GNOME_SESSION_BINARY, XFCE4_PANEL, SDDM_GREETER, PLASMA_X11]; |             for _ in 0..10 { | ||||||
|             for diplay_env in display_envs { |                 let display_proc = vec![ | ||||||
|                 self.xauth = get_env_tries("XAUTHORITY", &self.uid, diplay_env, 10); |                     XWAYLAND, | ||||||
|  |                     IBUS_DAEMON, | ||||||
|  |                     GNOME_GOA_DAEMON, | ||||||
|  |                     PLASMA_KDED5, | ||||||
|  |                     XFCE4_PANEL, | ||||||
|  |                     SDDM_GREETER, | ||||||
|  |                 ]; | ||||||
|  |                 for proc in display_proc { | ||||||
|  |                     self.xauth = get_env("XAUTHORITY", &self.uid, proc); | ||||||
|                     if !self.xauth.is_empty() { |                     if !self.xauth.is_empty() { | ||||||
|                         break; |                         break; | ||||||
|                     } |                     } | ||||||
|                 } |                 } | ||||||
|  |                 sleep_millis(300); | ||||||
|  |             } | ||||||
| 
 | 
 | ||||||
|             // get from Xorg process, parameter and environment
 |             // get from Xorg process, parameter and environment
 | ||||||
|             if self.xauth.is_empty() { |             if self.xauth.is_empty() { | ||||||
| @ -1074,6 +1143,11 @@ mod desktop { | |||||||
| 
 | 
 | ||||||
|         pub fn refresh(&mut self) { |         pub fn refresh(&mut self) { | ||||||
|             if !self.sid.is_empty() && is_active_and_seat0(&self.sid) { |             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; | ||||||
|  |                 } | ||||||
|                 return; |                 return; | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
| @ -1088,19 +1162,29 @@ mod desktop { | |||||||
|             self.uid = seat0_values[1].clone(); |             self.uid = seat0_values[1].clone(); | ||||||
|             self.username = seat0_values[2].clone(); |             self.username = seat0_values[2].clone(); | ||||||
|             self.protocal = get_display_server_of_session(&self.sid).into(); |             self.protocal = get_display_server_of_session(&self.sid).into(); | ||||||
|             if self.is_wayland() { |             if self.is_login_wayland() { | ||||||
|                 self.display = "".to_owned(); |                 self.display = "".to_owned(); | ||||||
|                 self.xauth = "".to_owned(); |                 self.xauth = "".to_owned(); | ||||||
|                 self.is_rustdesk_subprocess = false; |                 self.is_rustdesk_subprocess = false; | ||||||
|                 return; |                 return; | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|             self.get_display(); |             if self.is_wayland() { | ||||||
|             self.get_xauth(); |                 if is_xwayland_running() { | ||||||
|  |                     self.get_display_xauth_xwayland(); | ||||||
|  |                 } else { | ||||||
|  |                     self.display = "".to_owned(); | ||||||
|  |                     self.xauth = "".to_owned(); | ||||||
|  |                 } | ||||||
|  |                 self.is_rustdesk_subprocess = false; | ||||||
|  |             } else { | ||||||
|  |                 self.get_display_x11(); | ||||||
|  |                 self.get_xauth_x11(); | ||||||
|                 self.set_is_subprocess(); |                 self.set_is_subprocess(); | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  | } | ||||||
| 
 | 
 | ||||||
| pub struct WakeLock(Option<keepawake::AwakeHandle>); | pub struct WakeLock(Option<keepawake::AwakeHandle>); | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -2522,7 +2522,11 @@ async fn start_ipc( | |||||||
|                 #[cfg(target_os = "linux")] |                 #[cfg(target_os = "linux")] | ||||||
|                 { |                 { | ||||||
|                     log::debug!("Start cm"); |                     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() { |                 if res.is_ok() { | ||||||
|                     break; |                     break; | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user