From 74e1122fc29c42653917ad7ecb1d1e2f7e482ddb Mon Sep 17 00:00:00 2001 From: coastalwhite Date: Sat, 6 Apr 2024 16:50:42 +0200 Subject: [PATCH] Add deentry for desktop entry sessions --- Cargo.lock | 7 +++ Cargo.toml | 2 + extra/config.toml | 6 +++ src/config.rs | 2 + src/post_login/mod.rs | 107 ++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 124 insertions(+) diff --git a/Cargo.lock b/Cargo.lock index da921a8..3f75284 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -60,6 +60,12 @@ dependencies = [ "winapi", ] +[[package]] +name = "deentry" +version = "0.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "866170d551fbf7e49a7fe5160092933f210fe1853cf0cbf5d81957b941bdb690" + [[package]] name = "env_logger" version = "0.9.3" @@ -92,6 +98,7 @@ name = "lemurs" version = "0.3.2" dependencies = [ "crossterm", + "deentry", "env_logger", "libc", "log", diff --git a/Cargo.toml b/Cargo.toml index 55a4b06..c5dabae 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -34,6 +34,8 @@ unicode-width = "0.1" mio = { version = "0.8.8", features = [ "os-poll", "os-ext" ] } +deentry = "0.0.1" + # Interacting with the kernel interfaces rand = "0.8.4" nix = "0.23.1" diff --git a/extra/config.toml b/extra/config.toml index 92f0cd5..4b651bf 100644 --- a/extra/config.toml +++ b/extra/config.toml @@ -340,7 +340,13 @@ scripts_path = "/etc/lemurs/wms" # window manager. xsetup_path = "/etc/lemurs/xsetup.sh" +# The directory to use for desktop entries X11 sessions. +xsessions_path = "/usr/share/xsessions" + [wayland] # Path to the directory where the startup scripts for the Wayland sessions are # found scripts_path = "/etc/lemurs/wayland" + +# The directory to use for desktop entries wayland sessions. +wayland_sessions_path = "/usr/share/wayland-sessions" diff --git a/src/config.rs b/src/config.rs index 27a11eb..7988e2a 100644 --- a/src/config.rs +++ b/src/config.rs @@ -374,10 +374,12 @@ toml_config_struct! { X11Config, PartialX11Config, RoughX11Config, scripts_path => String, xsetup_path => String, + xsessions_path => String, } toml_config_struct! { WaylandConfig, PartialWaylandConfig, RoughWaylandConfig, scripts_path => String, + wayland_sessions_path => String, } #[derive(Debug, Clone, Deserialize)] diff --git a/src/post_login/mod.rs b/src/post_login/mod.rs index cc60f00..a1421c9 100644 --- a/src/post_login/mod.rs +++ b/src/post_login/mod.rs @@ -234,10 +234,111 @@ impl PostLoginEnvironment { } } +fn parse_desktop_entry(path: &Path, _: &Config) -> Result<(String, String), String> { + let content = match fs::read_to_string(path) { + Ok(content) => content, + Err(err) => { + return Err(format!("file cannot be read. Reason: {err}")); + } + }; + + let desktop_entry = match deentry::DesktopEntry::try_from(&content[..]) { + Ok(v) => v, + Err(err) => { + return Err(format!("file cannot be parsed. Reason: {err}")); + } + }; + + let Some(desktop_entry) = desktop_entry + .groups() + .iter() + .find(|g| g.name() == "Desktop Entry") + else { + return Err(format!("file does not contain 'Desktop Entry' group")); + }; + + let Some(exec) = desktop_entry.get("Exec") else { + return Err(format!("'Exec' key cannot be found")); + }; + + let exec = match exec.value().as_string() { + Ok(v) => v, + Err(err) => { + return Err(format!( + "'Exec' key does not contain a string. Reason: {err}" + )); + } + }; + + let name = match desktop_entry.get("Name") { + Some(name) => match name.value().as_string() { + Ok(v) => v, + Err(err) => { + warn!( + "Cannot use 'Name' in '{}' because it does not contain a string. Reason: {err}", + path.display() + ); + + exec + } + }, + None => exec, + }; + + Ok((name.to_string(), exec.to_string())) +} + pub fn get_envs(config: &Config) -> Vec<(String, PostLoginEnvironment)> { // NOTE: Maybe we can do something smart with `with_capacity` here. let mut envs = Vec::new(); + match fs::read_dir(&config.x11.xsessions_path) { + Ok(paths) => { + for path in paths { + let Ok(path) = path else { + continue; + }; + + let path = path.path(); + + match parse_desktop_entry(&path, config) { + Ok((name, exec)) => { + info!("Added environment '{name}' from xsessions"); + envs.push((name, PostLoginEnvironment::X { xinitrc_path: exec })); + } + Err(err) => warn!("Skipping '{}', because {err}", path.display()), + } + } + } + Err(err) => { + warn!("Failed to read from the xsessions folder '{err}'",); + } + } + + match fs::read_dir(&config.wayland.wayland_sessions_path + ) { + Ok(paths) => { + for path in paths { + let Ok(path) = path else { + continue; + }; + + let path = path.path(); + + match parse_desktop_entry(&path, config) { + Ok((name, exec)) => { + info!("Added environment '{name}' from wayland sessions"); + envs.push((name, PostLoginEnvironment::Wayland { script_path: exec })) + } + Err(err) => warn!("Skipping '{}', because {err}", path.display()), + } + } + } + Err(err) => { + warn!("Failed to read from the wayland sessions folder '{err}'",); + } + } + match fs::read_dir(&config.x11.scripts_path) { Ok(paths) => { for path in paths { @@ -255,6 +356,7 @@ pub fn get_envs(config: &Config) -> Vec<(String, PostLoginEnvironment)> { } } + info!("Added environment '{file_name}' from lemurs x11 scripts"); envs.push(( file_name, PostLoginEnvironment::X { @@ -303,6 +405,7 @@ pub fn get_envs(config: &Config) -> Vec<(String, PostLoginEnvironment)> { } } + info!("Added environment '{file_name}' from lemurs wayland scripts"); envs.push(( file_name, PostLoginEnvironment::Wayland { @@ -334,6 +437,10 @@ pub fn get_envs(config: &Config) -> Vec<(String, PostLoginEnvironment)> { } if envs.is_empty() || config.environment_switcher.include_tty_shell { + if envs.is_empty() { + info!("Added TTY SHELL because no other environments were found"); + } + envs.push(("TTYSHELL".to_string(), PostLoginEnvironment::Shell)); }