okey/cli/commands/
start.rs

1use std::{fs::File, io, os::fd::AsRawFd, process, thread};
2
3use anyhow::{anyhow, Result};
4use nix::unistd::{self, ForkResult};
5
6use crate::{
7    core::{InputProxy, KeyAdapter},
8    fs::{config::read_config, device::find_device_by_name},
9};
10
11pub fn start(config_path: Option<String>) -> Result<()> {
12    let parsed = read_config(config_path)?;
13
14    let handles = parsed.keyboards.into_iter().map(|keyboard| {
15        let defaults = parsed.defaults.clone();
16
17        thread::spawn(move || -> Result<()> {
18            let mut device = find_device_by_name(&keyboard.name)?
19                .ok_or(anyhow!("Device not found: {}", keyboard.name))?;
20
21            let mut proxy = InputProxy::try_from_device(&device)?;
22            let mut adapter = KeyAdapter::new(keyboard, defaults, &mut proxy);
23
24            adapter.hook(&mut device)
25        })
26    });
27
28    simple_logger::init()?;
29
30    for handle in handles {
31        handle.join().unwrap()?
32    }
33
34    Ok(())
35}
36
37pub fn start_daemon(config_path: Option<String>) -> Result<()> {
38    match unsafe { unistd::fork() } {
39        Ok(ForkResult::Parent { child, .. }) => {
40            println!("okey daemon started in the background... (PID: {})", child);
41            process::exit(0);
42        }
43        Ok(ForkResult::Child) => {
44            unistd::setsid()?;
45            unistd::chdir("/")?;
46
47            let dev_null = File::open("/dev/null")?;
48            let dev_null_fd = dev_null.as_raw_fd();
49
50            unistd::dup2(dev_null_fd, io::stdin().as_raw_fd())?;
51            unistd::dup2(dev_null_fd, io::stdout().as_raw_fd())?;
52            unistd::dup2(dev_null_fd, io::stderr().as_raw_fd())?;
53
54            start(config_path)?;
55        }
56        Err(err) => Err(err)?,
57    }
58
59    Ok(())
60}