Skip to content

Commit b26da39

Browse files
authored
Merge pull request #85 from waycrate/daemon-refactor
refactor: improve daemon / server code
2 parents 2664180 + 1db56f9 commit b26da39

File tree

2 files changed

+91
-70
lines changed

2 files changed

+91
-70
lines changed

src/daemon.rs

Lines changed: 61 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ impl KeyboardState {
3737

3838
#[tokio::main]
3939
async fn main() -> Result<(), Box<dyn std::error::Error>> {
40-
let args = set_flags().get_matches();
40+
let args = set_command_line_args().get_matches();
4141
env::set_var("RUST_LOG", "swhkd=warn");
4242

4343
if args.is_present("debug") {
@@ -77,14 +77,17 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
7777
}
7878
}
7979

80-
permission_check();
80+
if let Err(_) = check_user_permissions() {
81+
exit(1);
82+
}
8183

8284
let load_config = || {
8385
let config_file_path: std::path::PathBuf = if args.is_present("config") {
8486
Path::new(args.value_of("config").unwrap()).to_path_buf()
8587
} else {
86-
check_config_xdg()
88+
fetch_xdg_config_path()
8789
};
90+
8891
log::debug!("Using config file path: {:#?}", config_file_path);
8992

9093
if !config_file_path.exists() {
@@ -99,16 +102,18 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
99102
}
100103
Ok(out) => out,
101104
};
105+
102106
for hotkey in &hotkeys {
103107
log::debug!("hotkey: {:#?}", hotkey);
104108
}
109+
105110
hotkeys
106111
};
107112

108113
let mut hotkeys = load_config();
109114

110115
log::trace!("Attempting to find all keyboard file descriptors.");
111-
let keyboard_devices: Vec<Device> = evdev::enumerate().filter(check_keyboard).collect();
116+
let keyboard_devices: Vec<Device> = evdev::enumerate().filter(check_device_is_keyboard).collect();
112117

113118
let mut uinput_device = match uinput::create_uinput_device() {
114119
Ok(dev) => dev,
@@ -143,20 +148,12 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
143148
250
144149
};
145150

146-
fn send_command(hotkey: config::Hotkey) {
147-
log::info!("Hotkey pressed: {:#?}", hotkey);
148-
if let Err(e) = sock_send(&hotkey.command) {
149-
log::error!("Failed to send command over IPC.");
150-
log::error!("Is swhks running?");
151-
log::error!("{:#?}", e)
152-
}
153-
}
154-
155151
let mut signals = Signals::new(&[
156152
SIGUSR1, SIGUSR2, SIGHUP, SIGABRT, SIGBUS, SIGCHLD, SIGCONT, SIGINT, SIGPIPE, SIGQUIT,
157153
SIGSYS, SIGTERM, SIGTRAP, SIGTSTP, SIGVTALRM, SIGXCPU, SIGXFSZ,
158154
])?;
159-
let mut paused = false;
155+
156+
let mut execution_is_paused = false;
160157
let mut last_hotkey: Option<config::Hotkey> = None;
161158
let mut keyboard_states: Vec<KeyboardState> = Vec::new();
162159
let mut keyboard_stream_map = StreamMap::new();
@@ -167,7 +164,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
167164
keyboard_states.push(KeyboardState::new());
168165
}
169166

170-
// the initial sleep duration is never read because last_hotkey is initialized to None
167+
// The initial sleep duration is never read because last_hotkey is initialized to None
171168
let hotkey_repeat_timer = sleep(Duration::from_millis(0));
172169
tokio::pin!(hotkey_repeat_timer);
173170

@@ -178,47 +175,66 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
178175
send_command(hotkey.clone());
179176
hotkey_repeat_timer.as_mut().reset(Instant::now() + Duration::from_millis(repeat_cooldown_duration));
180177
}
178+
181179
Some(signal) = signals.next() => {
182180
match signal {
183181
SIGUSR1 => {
184-
paused = true;
185-
for mut device in evdev::enumerate().filter(check_keyboard) {
182+
execution_is_paused = true;
183+
for mut device in evdev::enumerate().filter(check_device_is_keyboard) {
186184
let _ = device.ungrab();
187185
}
188186
}
187+
189188
SIGUSR2 => {
190-
paused = false;
191-
for mut device in evdev::enumerate().filter(check_keyboard) {
189+
execution_is_paused = false;
190+
for mut device in evdev::enumerate().filter(check_device_is_keyboard) {
192191
let _ = device.grab();
193192
}
194193
}
194+
195195
SIGHUP => {
196196
hotkeys = load_config();
197197
}
198+
198199
SIGINT => {
199-
for mut device in evdev::enumerate().filter(check_keyboard) {
200+
for mut device in evdev::enumerate().filter(check_device_is_keyboard) {
200201
let _ = device.ungrab();
201202
}
202203
log::warn!("Received SIGINT signal, exiting...");
203204
exit(1);
204205
}
206+
205207
_ => {
208+
for (_, mut device) in evdev::enumerate() {
209+
if check_device_is_keyboard(&device){
210+
let _ = device.ungrab();
211+
};
212+
}
206213
log::warn!("Got signal: {:#?}", signal);
207214
exit(1);
208215
}
209216
}
210217
}
218+
211219
Some((i, Ok(event))) = keyboard_stream_map.next() => {
212-
let keyboard_state = &mut keyboard_states[i];
213-
if let InputEventKind::Key(key) = event.kind() {
220+
let keyboard_state = &mut keyboard_states[i];
221+
222+
let key = match event.kind() {
223+
InputEventKind::Key(keycode) => keycode,
224+
_ => continue
225+
};
226+
214227
match event.value() {
228+
// Key press
215229
1 => {
216230
if let Some(modifier) = modifiers_map.get(&key) {
217231
keyboard_state.state_modifiers.insert(*modifier);
218232
} else {
219233
keyboard_state.state_keysyms.insert(key);
220234
}
221235
}
236+
237+
// Key release
222238
0 => {
223239
if let Some(modifier) = modifiers_map.get(&key) {
224240
if let Some(hotkey) = &last_hotkey {
@@ -236,6 +252,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
236252
keyboard_state.state_keysyms.remove(key);
237253
}
238254
}
255+
239256
_ => {}
240257
}
241258

@@ -257,11 +274,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
257274
uinput_device.emit(&[event]).unwrap();
258275
}
259276

260-
if paused || last_hotkey.is_some() {
261-
continue;
262-
}
263-
264-
if possible_hotkeys.is_empty() {
277+
if execution_is_paused || possible_hotkeys.is_empty() || last_hotkey.is_some() {
265278
continue;
266279
}
267280

@@ -270,7 +283,6 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
270283
log::debug!("hotkey: {:#?}", possible_hotkeys);
271284

272285
for hotkey in possible_hotkeys {
273-
// this should check if state_modifiers and hotkey.modifiers have the same elements
274286
if keyboard_state.state_modifiers.iter().all(|x| hotkey.modifiers.contains(x))
275287
&& keyboard_state.state_modifiers.len() == hotkey.modifiers.len()
276288
&& keyboard_state.state_keysyms.contains(hotkey.keysym)
@@ -283,11 +295,25 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
283295
}
284296
}
285297
}
286-
}
287298
}
288299
}
289300

290-
pub fn permission_check() {
301+
fn sock_send(command: &str) -> std::io::Result<()> {
302+
let mut stream = UnixStream::connect("/tmp/swhkd.sock")?;
303+
stream.write_all(command.as_bytes())?;
304+
Ok(())
305+
}
306+
307+
fn send_command(hotkey: config::Hotkey) {
308+
log::info!("Hotkey pressed: {:#?}", hotkey);
309+
if let Err(e) = sock_send(&hotkey.command) {
310+
log::error!("Failed to send command over IPC.");
311+
log::error!("Is swhks running?");
312+
log::error!("{:#?}", e)
313+
}
314+
}
315+
316+
pub fn check_user_permissions() -> Result<(), ()> {
291317
if !Uid::current().is_root() {
292318
let groups = nix::unistd::getgroups();
293319
for (_, groups) in groups.iter().enumerate() {
@@ -300,13 +326,14 @@ pub fn permission_check() {
300326
}
301327
}
302328
log::error!("Consider using `pkexec swhkd ...`");
303-
exit(1);
329+
Err(())
304330
} else {
305331
log::warn!("Running swhkd as root!");
332+
Ok(())
306333
}
307334
}
308335

309-
pub fn check_keyboard(device: &Device) -> bool {
336+
pub fn check_device_is_keyboard(device: &Device) -> bool {
310337
if device.supported_keys().map_or(false, |keys| keys.contains(Key::KEY_ENTER)) {
311338
if device.name() == Some("swhkd virtual output") {
312339
return false;
@@ -319,7 +346,7 @@ pub fn check_keyboard(device: &Device) -> bool {
319346
}
320347
}
321348

322-
pub fn set_flags() -> Command<'static> {
349+
pub fn set_command_line_args() -> Command<'static> {
323350
let app = Command::new("swhkd")
324351
.version(env!("CARGO_PKG_VERSION"))
325352
.author(env!("CARGO_PKG_AUTHORS"))
@@ -340,7 +367,7 @@ pub fn set_flags() -> Command<'static> {
340367
app
341368
}
342369

343-
pub fn check_config_xdg() -> std::path::PathBuf {
370+
pub fn fetch_xdg_config_path() -> std::path::PathBuf {
344371
let config_file_path: std::path::PathBuf = match env::var("XDG_CONFIG_HOME") {
345372
Ok(val) => {
346373
log::debug!("XDG_CONFIG_HOME exists: {:#?}", val);
@@ -353,9 +380,3 @@ pub fn check_config_xdg() -> std::path::PathBuf {
353380
};
354381
config_file_path
355382
}
356-
357-
fn sock_send(command: &str) -> std::io::Result<()> {
358-
let mut stream = UnixStream::connect("/tmp/swhkd.sock")?;
359-
stream.write_all(command.as_bytes())?;
360-
Ok(())
361-
}

src/server.rs

Lines changed: 30 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,12 @@ fn main() -> std::io::Result<()> {
1111
env::set_var("RUST_LOG", "swhks=trace");
1212
env_logger::init();
1313

14-
let pidfile: String = String::from("/tmp/swhks.pid");
15-
let sockfile: String = String::from("/tmp/swhkd.sock");
14+
let pid_file_path = String::from("/tmp/swhks.pid");
15+
let sock_file_path = String::from("/tmp/swhkd.sock");
1616

17-
if Path::new(&pidfile).exists() {
18-
log::trace!("Reading {} file and checking for running instances.", pidfile);
19-
let swhkd_pid = match fs::read_to_string(&pidfile) {
17+
if Path::new(&pid_file_path).exists() {
18+
log::trace!("Reading {} file and checking for running instances.", pid_file_path);
19+
let swhkd_pid = match fs::read_to_string(&pid_file_path) {
2020
Ok(swhkd_pid) => swhkd_pid,
2121
Err(e) => {
2222
log::error!("Unable to read {} to check all running instances", e);
@@ -35,55 +35,55 @@ fn main() -> std::io::Result<()> {
3535
}
3636
}
3737

38-
if Path::new(&sockfile).exists() {
38+
if Path::new(&sock_file_path).exists() {
3939
log::trace!("Sockfile exists, attempting to remove it.");
40-
match fs::remove_file(&sockfile) {
40+
match fs::remove_file(&sock_file_path) {
4141
Ok(_) => {
4242
log::debug!("Removed old socket file");
4343
}
4444
Err(e) => {
4545
log::error!("Error removing the socket file!: {}", e);
46-
log::error!("You can manually remove the socket file: {}", sockfile);
46+
log::error!("You can manually remove the socket file: {}", sock_file_path);
4747
exit(1);
4848
}
4949
};
5050
}
5151

52-
match fs::write(&pidfile, id().to_string()) {
52+
match fs::write(&pid_file_path, id().to_string()) {
5353
Ok(_) => {}
5454
Err(e) => {
55-
log::error!("Unable to write to {}: {}", pidfile, e);
55+
log::error!("Unable to write to {}: {}", pid_file_path, e);
5656
exit(1);
5757
}
5858
}
5959

60-
fn run_system_command(command: &str) {
61-
match Command::new("sh")
62-
.arg("-c")
63-
.arg(command)
64-
.stdin(Stdio::null())
65-
.stdout(Stdio::null())
66-
.stderr(Stdio::null())
67-
.spawn()
68-
{
69-
Ok(_) => {}
70-
Err(e) => {
71-
log::error!("Failed to execute {}", command);
72-
log::error!("Error, {}", e);
73-
}
74-
}
75-
}
76-
77-
let listener = UnixListener::bind(sockfile)?;
60+
let listener = UnixListener::bind(sock_file_path)?;
7861
loop {
7962
match listener.accept() {
80-
Ok((mut socket, addr)) => {
63+
Ok((mut socket, address)) => {
8164
let mut response = String::new();
8265
socket.read_to_string(&mut response)?;
8366
run_system_command(&response);
84-
log::debug!("Socket: {:?} Address: {:?} Response: {}", socket, addr, response);
67+
log::debug!("Socket: {:?} Address: {:?} Response: {}", socket, address, response);
8568
}
8669
Err(e) => log::error!("accept function failed: {:?}", e),
8770
}
8871
}
8972
}
73+
74+
fn run_system_command(command: &str) {
75+
match Command::new("sh")
76+
.arg("-c")
77+
.arg(command)
78+
.stdin(Stdio::null())
79+
.stdout(Stdio::null())
80+
.stderr(Stdio::null())
81+
.spawn()
82+
{
83+
Ok(_) => {}
84+
Err(e) => {
85+
log::error!("Failed to execute {}", command);
86+
log::error!("Error, {}", e);
87+
}
88+
}
89+
}

0 commit comments

Comments
 (0)