Skip to content

Commit 7bb4df1

Browse files
committed
[Refactor] abstract setup.rs into setup_swhkd and support
xdg_runtime_dir instead of hardcoding /run/swhkd
1 parent 29a0a02 commit 7bb4df1

File tree

1 file changed

+74
-55
lines changed

1 file changed

+74
-55
lines changed

src/daemon.rs

Lines changed: 74 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -67,58 +67,7 @@ async fn main() -> Result<(), Box<dyn Error>> {
6767
}
6868
};
6969

70-
log::trace!("Setting process umask.");
71-
umask(Mode::S_IWGRP | Mode::S_IWOTH);
72-
73-
let runtime_path = "/run/swhkd/";
74-
if !Path::new(runtime_path).exists() {
75-
match fs::create_dir_all(Path::new(runtime_path)) {
76-
Ok(_) => {
77-
log::debug!("Created runtime directory.");
78-
match fs::set_permissions(Path::new(runtime_path), Permissions::from_mode(0o600)) {
79-
Ok(_) => log::debug!("Set runtime directory to readonly."),
80-
Err(e) => log::error!("Failed to set runtime directory to readonly: {}", e),
81-
}
82-
}
83-
Err(e) => log::error!("Failed to create runtime directory: {}", e),
84-
}
85-
}
86-
87-
let pidfile: String = format!("{}swhkd_{}.pid", runtime_path, invoking_uid);
88-
if Path::new(&pidfile).exists() {
89-
log::trace!("Reading {} file and checking for running instances.", pidfile);
90-
let swhkd_pid = match fs::read_to_string(&pidfile) {
91-
Ok(swhkd_pid) => swhkd_pid,
92-
Err(e) => {
93-
log::error!("Unable to read {} to check all running instances", e);
94-
exit(1);
95-
}
96-
};
97-
log::debug!("Previous PID: {}", swhkd_pid);
98-
99-
let mut sys = System::new_all();
100-
sys.refresh_all();
101-
for (pid, process) in sys.processes() {
102-
if pid.to_string() == swhkd_pid && process.exe() == env::current_exe().unwrap() {
103-
log::error!("Swhkd is already running!");
104-
log::error!("pid of existing swhkd process: {}", pid.to_string());
105-
log::error!("To close the existing swhkd process, run `sudo killall swhkd`");
106-
exit(1);
107-
}
108-
}
109-
}
110-
111-
match fs::write(&pidfile, id().to_string()) {
112-
Ok(_) => {}
113-
Err(e) => {
114-
log::error!("Unable to write to {}: {}", pidfile, e);
115-
exit(1);
116-
}
117-
}
118-
119-
if check_user_permissions().is_err() {
120-
exit(1);
121-
}
70+
setup_swhkd(invoking_uid);
12271

12372
let root_resuid = perms::get_resuid();
12473
let root_resgid = perms::get_resgid();
@@ -212,7 +161,7 @@ async fn main() -> Result<(), Box<dyn Error>> {
212161
tokio::pin!(hotkey_repeat_timer);
213162

214163
// The socket that we're sending the commands to.
215-
let socket_file_path = fetch_xdg_runtime_path();
164+
let socket_file_path = fetch_xdg_runtime_socket_path();
216165
loop {
217166
select! {
218167
_ = &mut hotkey_repeat_timer, if &last_hotkey.is_some() => {
@@ -372,7 +321,7 @@ fn send_command(hotkey: config::Hotkey, socket_path: &Path) {
372321
}
373322
}
374323

375-
pub fn check_user_permissions() -> Result<(), Box<dyn std::error::Error>> {
324+
pub fn check_input_group() -> Result<(), Box<dyn std::error::Error>> {
376325
if !Uid::current().is_root() {
377326
let groups = nix::unistd::getgroups();
378327
for (_, groups) in groups.iter().enumerate() {
@@ -440,7 +389,7 @@ pub fn fetch_xdg_config_path() -> PathBuf {
440389
config_file_path
441390
}
442391

443-
pub fn fetch_xdg_runtime_path() -> PathBuf {
392+
pub fn fetch_xdg_runtime_socket_path() -> PathBuf {
444393
match env::var("XDG_RUNTIME_DIR") {
445394
Ok(val) => {
446395
log::debug!("XDG_RUNTIME_DIR exists: {:#?}", val);
@@ -453,3 +402,73 @@ pub fn fetch_xdg_runtime_path() -> PathBuf {
453402
}
454403
}
455404
}
405+
406+
pub fn setup_swhkd(invoking_uid: u32) {
407+
// Set a sane process umask.
408+
log::trace!("Setting process umask.");
409+
umask(Mode::S_IWGRP | Mode::S_IWOTH);
410+
411+
// Get the runtime path and create it if needed.
412+
let runtime_path: String = match env::var("XDG_RUNTIME_DIR") {
413+
Ok(runtime_path) => {
414+
log::debug!("XDG_RUNTIME_DIR exists: {:#?}", runtime_path);
415+
Path::new(&runtime_path).join("swhkd").to_str().unwrap().to_owned()
416+
}
417+
Err(_) => {
418+
log::error!("XDG_RUNTIME_DIR has not been set.");
419+
String::from("/run/swhkd/")
420+
}
421+
};
422+
if !Path::new(&runtime_path).exists() {
423+
match fs::create_dir_all(Path::new(&runtime_path)) {
424+
Ok(_) => {
425+
log::debug!("Created runtime directory.");
426+
match fs::set_permissions(Path::new(&runtime_path), Permissions::from_mode(0o600)) {
427+
Ok(_) => log::debug!("Set runtime directory to readonly."),
428+
Err(e) => log::error!("Failed to set runtime directory to readonly: {}", e),
429+
}
430+
}
431+
Err(e) => log::error!("Failed to create runtime directory: {}", e),
432+
}
433+
}
434+
435+
// Get the PID file path for instance tracking.
436+
let pidfile: String = format!("{}swhkd_{}.pid", runtime_path, invoking_uid);
437+
if Path::new(&pidfile).exists() {
438+
log::trace!("Reading {} file and checking for running instances.", pidfile);
439+
let swhkd_pid = match fs::read_to_string(&pidfile) {
440+
Ok(swhkd_pid) => swhkd_pid,
441+
Err(e) => {
442+
log::error!("Unable to read {} to check all running instances", e);
443+
exit(1);
444+
}
445+
};
446+
log::debug!("Previous PID: {}", swhkd_pid);
447+
448+
// Check if swhkd is already running!
449+
let mut sys = System::new_all();
450+
sys.refresh_all();
451+
for (pid, process) in sys.processes() {
452+
if pid.to_string() == swhkd_pid && process.exe() == env::current_exe().unwrap() {
453+
log::error!("Swhkd is already running!");
454+
log::error!("pid of existing swhkd process: {}", pid.to_string());
455+
log::error!("To close the existing swhkd process, run `sudo killall swhkd`");
456+
exit(1);
457+
}
458+
}
459+
}
460+
461+
// Write to the pid file.
462+
match fs::write(&pidfile, id().to_string()) {
463+
Ok(_) => {}
464+
Err(e) => {
465+
log::error!("Unable to write to {}: {}", pidfile, e);
466+
exit(1);
467+
}
468+
}
469+
470+
// Check if the user is in input group.
471+
if check_input_group().is_err() {
472+
exit(1);
473+
}
474+
}

0 commit comments

Comments
 (0)