use std::process::Command; extern crate libc; use libc::{c_int, c_char}; #[macro_use] extern crate redhook; static mut BUTTON_STATE: [bool; 5] = [false; 5]; hook! { unsafe fn read(fd: c_int, buf: *const c_char, count: c_int) -> c_int => read_hook { let res = real!(read)(fd, buf, count); if fd != 6 { return res; } // The data being read is an evdev input_event. // The data we care about is the `code` which is used as the key identifier (102 for Middle button, 105 for Left button, 106 for Right button, 116 for power). // offset 10 -> key identifier // offset 12 -> state change -> 0=release/1=press let code = *buf.offset(10); let state = *buf.offset(12); let button_index = match code { 102 => 0, 105 => 1, 106 => 2, 116 => 3, _ => 4, // any unknown buttons just write their state to an extra slot. this is to avoid an extra branch in the code / early return. }; match state { 0 => BUTTON_STATE[button_index] = false, 1 => BUTTON_STATE[button_index] = true, _ => {}, } if BUTTON_STATE[1] && BUTTON_STATE[2] { println!("I want to exit now..."); Command::new("systemctl") .arg("stop") .arg("xochitl") .output() .expect("failed to call systemctl"); } res } }