okey-cli 0.1.2

An advanced, easy-to-use key remapper for Linux
Documentation
use std::{fs::File, io, os::fd::AsRawFd, process, thread};

use anyhow::{anyhow, Result};
use nix::unistd::{self, ForkResult};

use crate::{
    core::{InputProxy, KeyAdapter},
    fs::{config::read_config, device::find_device_by_name},
};

pub fn start(config_path: Option<String>) -> Result<()> {
    let parsed = read_config(config_path)?;

    let handles = parsed.keyboards.into_iter().map(|keyboard| {
        let defaults = parsed.defaults.clone();

        thread::spawn(move || -> Result<()> {
            let mut device = find_device_by_name(&keyboard.name)?
                .ok_or(anyhow!("Device not found: {}", keyboard.name))?;

            let mut proxy = InputProxy::try_from_device(&device)?;
            let mut adapter = KeyAdapter::new(keyboard, defaults, &mut proxy);

            adapter.hook(&mut device)
        })
    });

    simple_logger::init()?;

    for handle in handles {
        handle.join().unwrap()?
    }

    Ok(())
}

pub fn start_daemon(config_path: Option<String>) -> Result<()> {
    match unsafe { unistd::fork() } {
        Ok(ForkResult::Parent { child, .. }) => {
            println!("okey daemon started in the background... (PID: {})", child);
            process::exit(0);
        }
        Ok(ForkResult::Child) => {
            unistd::setsid()?;
            unistd::chdir("/")?;

            let dev_null = File::open("/dev/null")?;
            let dev_null_fd = dev_null.as_raw_fd();

            unistd::dup2(dev_null_fd, io::stdin().as_raw_fd())?;
            unistd::dup2(dev_null_fd, io::stdout().as_raw_fd())?;
            unistd::dup2(dev_null_fd, io::stderr().as_raw_fd())?;

            start(config_path)?;
        }
        Err(err) => Err(err)?,
    }

    Ok(())
}