Skip to content

Commit 5e8ebe3

Browse files
[refactor] environment for swhkd (#246)
* refactor: New Env for swhkd * Refactor Functions * Fix Spelling in environ * Fix spelling in daemon * Add Path Validations * Run formatting
1 parent a4d2ffe commit 5e8ebe3

File tree

3 files changed

+158
-58
lines changed

3 files changed

+158
-58
lines changed

swhkd/src/daemon.rs

Lines changed: 9 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ use tokio_stream::{StreamExt, StreamMap};
2626
use tokio_udev::{AsyncMonitorSocket, EventType, MonitorBuilder};
2727

2828
mod config;
29+
mod environ;
2930
mod perms;
3031
mod uinput;
3132

@@ -55,20 +56,12 @@ async fn main() -> Result<(), Box<dyn Error>> {
5556
env_logger::init();
5657
log::trace!("Logger initialized.");
5758

58-
let invoking_uid = match env::var("PKEXEC_UID") {
59-
Ok(uid) => {
60-
let uid = uid.parse::<u32>().unwrap();
61-
log::trace!("Invoking UID: {}", uid);
62-
uid
63-
}
64-
Err(_) => {
65-
log::error!("Failed to launch swhkd!!!");
66-
log::error!("Make sure to launch the binary with pkexec.");
67-
exit(1);
68-
}
69-
};
59+
let env = environ::Env::construct();
60+
log::trace!("Environment Aquired");
61+
62+
let invoking_uid = env.pkexec_id;
7063

71-
setup_swhkd(invoking_uid);
64+
setup_swhkd(invoking_uid, env.xdg_runtime_dir.clone().to_string_lossy().to_string());
7265

7366
let load_config = || {
7467
// Drop privileges to the invoking user.
@@ -77,7 +70,7 @@ async fn main() -> Result<(), Box<dyn Error>> {
7770
let config_file_path: PathBuf = if args.is_present("config") {
7871
Path::new(args.value_of("config").unwrap()).to_path_buf()
7972
} else {
80-
fetch_xdg_config_path()
73+
env.fetch_xdg_config_path()
8174
};
8275

8376
log::debug!("Using config file path: {:#?}", config_file_path);
@@ -231,7 +224,7 @@ async fn main() -> Result<(), Box<dyn Error>> {
231224
tokio::pin!(hotkey_repeat_timer);
232225

233226
// The socket we're sending the commands to.
234-
let socket_file_path = fetch_xdg_runtime_socket_path();
227+
let socket_file_path = env.fetch_xdg_runtime_socket_path();
235228
loop {
236229
select! {
237230
_ = &mut hotkey_repeat_timer, if &last_hotkey.is_some() => {
@@ -501,50 +494,12 @@ pub fn set_command_line_args() -> Command<'static> {
501494
app
502495
}
503496

504-
pub fn fetch_xdg_config_path() -> PathBuf {
505-
let config_file_path: PathBuf = match env::var("XDG_CONFIG_HOME") {
506-
Ok(val) => {
507-
log::debug!("XDG_CONFIG_HOME exists: {:#?}", val);
508-
Path::new(&val).join("swhkd/swhkdrc")
509-
}
510-
Err(_) => {
511-
log::error!("XDG_CONFIG_HOME has not been set.");
512-
Path::new("/etc/swhkd/swhkdrc").to_path_buf()
513-
}
514-
};
515-
config_file_path
516-
}
517-
518-
pub fn fetch_xdg_runtime_socket_path() -> PathBuf {
519-
match env::var("XDG_RUNTIME_DIR") {
520-
Ok(val) => {
521-
log::debug!("XDG_RUNTIME_DIR exists: {:#?}", val);
522-
Path::new(&val).join("swhkd.sock")
523-
}
524-
Err(_) => {
525-
log::error!("XDG_RUNTIME_DIR has not been set.");
526-
Path::new(&format!("/run/user/{}/swhkd.sock", env::var("PKEXEC_UID").unwrap()))
527-
.to_path_buf()
528-
}
529-
}
530-
}
531-
532-
pub fn setup_swhkd(invoking_uid: u32) {
497+
pub fn setup_swhkd(invoking_uid: u32, runtime_path: String) {
533498
// Set a sane process umask.
534499
log::trace!("Setting process umask.");
535500
umask(Mode::S_IWGRP | Mode::S_IWOTH);
536501

537502
// Get the runtime path and create it if needed.
538-
let runtime_path: String = match env::var("XDG_RUNTIME_DIR") {
539-
Ok(runtime_path) => {
540-
log::debug!("XDG_RUNTIME_DIR exists: {:#?}", runtime_path);
541-
Path::new(&runtime_path).join("swhkd").to_str().unwrap().to_owned()
542-
}
543-
Err(_) => {
544-
log::error!("XDG_RUNTIME_DIR has not been set.");
545-
String::from("/run/swhkd/")
546-
}
547-
};
548503
if !Path::new(&runtime_path).exists() {
549504
match fs::create_dir_all(Path::new(&runtime_path)) {
550505
Ok(_) => {

swhkd/src/environ.rs

Lines changed: 141 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,141 @@
1+
use std::{
2+
env::VarError,
3+
path::{Path, PathBuf},
4+
};
5+
6+
pub struct Env {
7+
pub pkexec_id: u32,
8+
pub xdg_config_home: PathBuf,
9+
pub xdg_runtime_socket: PathBuf,
10+
pub xdg_runtime_dir: PathBuf,
11+
}
12+
13+
#[derive(Debug)]
14+
pub enum EnvError {
15+
PkexecNotFound,
16+
XdgConfigNotFound,
17+
XdgRuntimeNotFound,
18+
PathNotFound,
19+
GenericError(String),
20+
}
21+
22+
impl Env {
23+
pub fn construct() -> Self {
24+
let pkexec_id = match Self::get_env("PKEXEC_UID") {
25+
Ok(val) => match val.parse::<u32>() {
26+
Ok(val) => val,
27+
Err(_) => {
28+
log::error!("Failed to launch swhkd!!!");
29+
log::error!("Make sure to launch the binary with pkexec.");
30+
std::process::exit(1);
31+
}
32+
},
33+
Err(_) => {
34+
log::error!("Failed to launch swhkd!!!");
35+
log::error!("Make sure to launch the binary with pkexec.");
36+
std::process::exit(1);
37+
}
38+
};
39+
40+
let xdg_config_home = match Self::get_env("XDG_CONFIG_HOME") {
41+
Ok(val) => match validate_path(&PathBuf::from(val)) {
42+
Ok(val) => val,
43+
Err(e) => match e {
44+
EnvError::PathNotFound => {
45+
log::warn!("XDG_CONFIG_HOME does not exist, using hardcoded /etc");
46+
PathBuf::from("/etc")
47+
}
48+
_ => {
49+
eprintln!("Failed to get XDG_CONFIG_HOME: {:?}", e);
50+
std::process::exit(1);
51+
}
52+
},
53+
},
54+
Err(e) => match e {
55+
EnvError::XdgConfigNotFound => {
56+
log::warn!("XDG_CONFIG_HOME not found, using hardcoded /etc");
57+
PathBuf::from("/etc")
58+
}
59+
_ => {
60+
eprintln!("Failed to get XDG_CONFIG_HOME: {:?}", e);
61+
std::process::exit(1);
62+
}
63+
},
64+
};
65+
66+
let xdg_runtime_socket = match Self::get_env("XDG_RUNTIME_DIR") {
67+
Ok(val) => match validate_path(&PathBuf::from(val).join("swhkd.sock")) {
68+
Ok(val) => val,
69+
Err(e) => match e {
70+
EnvError::PathNotFound => {
71+
log::warn!("XDG_RUNTIME_DIR does not exist, using hardcoded /run/user");
72+
PathBuf::from(format!("/run/user/{}", pkexec_id))
73+
}
74+
_ => {
75+
eprintln!("Failed to get XDG_RUNTIME_DIR: {:?}", e);
76+
std::process::exit(1);
77+
}
78+
},
79+
},
80+
Err(e) => match e {
81+
EnvError::XdgRuntimeNotFound => {
82+
log::warn!("XDG_RUNTIME_DIR not found, using hardcoded /run/user");
83+
PathBuf::from(format!("/run/user/{}", pkexec_id))
84+
}
85+
_ => {
86+
eprintln!("Failed to get XDG_RUNTIME_DIR: {:?}", e);
87+
std::process::exit(1);
88+
}
89+
},
90+
};
91+
92+
let xdg_runtime_dir = match Self::get_env("XDG_RUNTIME_DIR") {
93+
Ok(val) => PathBuf::from(val),
94+
Err(e) => match e {
95+
EnvError::XdgRuntimeNotFound => {
96+
log::warn!("XDG_RUNTIME_DIR not found, using hardcoded /run/swhkd");
97+
PathBuf::from("/run/swhkd")
98+
}
99+
_ => {
100+
eprintln!("Failed to get XDG_RUNTIME_DIR: {:?}", e);
101+
std::process::exit(1);
102+
}
103+
},
104+
};
105+
106+
Self { pkexec_id, xdg_config_home, xdg_runtime_dir, xdg_runtime_socket }
107+
}
108+
109+
fn get_env(name: &str) -> Result<String, EnvError> {
110+
match std::env::var(name) {
111+
Ok(val) => Ok(val),
112+
Err(e) => match e {
113+
VarError::NotPresent => match name {
114+
"PKEXEC_UID" => Err(EnvError::PkexecNotFound),
115+
"XDG_CONFIG_HOME" => Err(EnvError::XdgConfigNotFound),
116+
"XDG_RUNTIME_DIR" => Err(EnvError::XdgRuntimeNotFound),
117+
_ => Err(EnvError::GenericError(e.to_string())),
118+
},
119+
VarError::NotUnicode(_) => {
120+
Err(EnvError::GenericError("Not a valid unicode".to_string()))
121+
}
122+
},
123+
}
124+
}
125+
126+
pub fn fetch_xdg_config_path(&self) -> PathBuf {
127+
PathBuf::from(&self.xdg_config_home).join("swhkd/swhkdrc")
128+
}
129+
130+
pub fn fetch_xdg_runtime_socket_path(&self) -> PathBuf {
131+
PathBuf::from(&self.xdg_runtime_dir).join("swhkd.sock")
132+
}
133+
}
134+
135+
fn validate_path(path: &Path) -> Result<PathBuf, EnvError> {
136+
if path.exists() {
137+
Ok(path.to_path_buf())
138+
} else {
139+
Err(EnvError::PathNotFound)
140+
}
141+
}

swhks/src/environ.rs

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ pub enum EnvError {
2020
DataHomeNotSet,
2121
HomeNotSet,
2222
RuntimeDirNotSet,
23+
PathNotFound,
2324
GenericError(String),
2425
}
2526

@@ -30,15 +31,15 @@ impl Env {
3031
let home = match Self::get_env("HOME") {
3132
Ok(val) => val,
3233
Err(_) => {
33-
eprintln!("HOME Variable is not set, cannot fall back on hardcoded path for XDG_DATA_HOME.");
34+
eprintln!("HOME Variable is not set/found, cannot fall back on hardcoded path for XDG_DATA_HOME.");
3435
std::process::exit(1);
3536
}
3637
};
3738

3839
let data_home = match Self::get_env("XDG_DATA_HOME") {
3940
Ok(val) => val,
4041
Err(e) => match e {
41-
EnvError::DataHomeNotSet => {
42+
EnvError::DataHomeNotSet | EnvError::PathNotFound => {
4243
log::warn!(
4344
"XDG_DATA_HOME Variable is not set, falling back on hardcoded path."
4445
);
@@ -51,7 +52,7 @@ impl Env {
5152
let runtime_dir = match Self::get_env("XDG_RUNTIME_DIR") {
5253
Ok(val) => val,
5354
Err(e) => match e {
54-
EnvError::RuntimeDirNotSet => {
55+
EnvError::RuntimeDirNotSet | EnvError::PathNotFound => {
5556
log::warn!(
5657
"XDG_RUNTIME_DIR Variable is not set, falling back on hardcoded path."
5758
);
@@ -67,7 +68,10 @@ impl Env {
6768
/// Actual interface to get the environment variable.
6869
fn get_env(name: &str) -> Result<PathBuf, EnvError> {
6970
match std::env::var(name) {
70-
Ok(val) => Ok(PathBuf::from(val)),
71+
Ok(val) => match PathBuf::from(&val).exists() {
72+
true => Ok(PathBuf::from(val)),
73+
false => Err(EnvError::PathNotFound),
74+
},
7175
Err(e) => match e {
7276
VarError::NotPresent => match name {
7377
"XDG_DATA_HOME" => Err(EnvError::DataHomeNotSet),

0 commit comments

Comments
 (0)