From 30e7205ebf0bd51c2e61c59183961b6a8478da57 Mon Sep 17 00:00:00 2001 From: chayleaf Date: Wed, 14 Aug 2024 11:28:19 +0700 Subject: [PATCH] convert commands into strings --- src/main.rs | 151 +++++++++++++++++++++++++++++----------------------- 1 file changed, 85 insertions(+), 66 deletions(-) diff --git a/src/main.rs b/src/main.rs index f9a8c1d..d5198c2 100644 --- a/src/main.rs +++ b/src/main.rs @@ -4,15 +4,23 @@ non_upper_case_globals, clippy::missing_safety_doc )] -use std::{borrow::Cow, env, ffi::CStr, mem, mem::MaybeUninit, os::raw::c_void, process, ptr}; +use std::{ + borrow::Cow, + env, + ffi::{CStr, CString}, + mem, + mem::MaybeUninit, + os::raw::c_void, + process, ptr, +}; use ext_idle_notify_v1_protocol::{ ext_idle_notification_v1_interface, ext_idle_notifier_v1_interface, }; use libc::{ __errno_location, abort, access, calloc, close, execvp, exit, fclose, fopen, fork, free, - getenv, getline, getopt, getpid, memset, printf, sigemptyset, signal, sigprocmask, sigset_t, - size_t, sprintf, strcmp, strdup, strlen, strncmp, strstr, strtoul, waitpid, + getenv, getline, getopt, getpid, printf, sigemptyset, signal, sigprocmask, sigset_t, size_t, + sprintf, strcmp, strdup, strlen, strncmp, strstr, strtoul, waitpid, }; use libsystemd_sys::bus::{ sd_bus, sd_bus_call_method, sd_bus_default_system, sd_bus_error, sd_bus_error_free, @@ -134,11 +142,11 @@ struct swayidle_state { event_loop: *mut wl_event_loop, timeout_cmds: wl_list, seats: wl_list, - seat_name: *mut libc::c_char, - before_sleep_cmd: *mut libc::c_char, - after_resume_cmd: *mut libc::c_char, - logind_lock_cmd: *mut libc::c_char, - logind_unlock_cmd: *mut libc::c_char, + seat_name: Option, + before_sleep_cmd: Option, + after_resume_cmd: Option, + logind_lock_cmd: Option, + logind_unlock_cmd: Option, logind_idlehint: bool, timeouts_enabled: bool, wait: bool, @@ -149,8 +157,8 @@ struct swayidle_timeout_cmd { timeout: libc::c_int, registered_timeout: libc::c_int, idle_notification: *mut ext_idle_notification_v1, - idle_cmd: *mut libc::c_char, - resume_cmd: *mut libc::c_char, + idle_cmd: Option, + resume_cmd: Option, idlehint: bool, resume_pending: bool, } @@ -265,11 +273,11 @@ static mut state: swayidle_state = swayidle_state { prev: ptr::null_mut(), next: ptr::null_mut(), }, - seat_name: ptr::null_mut(), - before_sleep_cmd: ptr::null_mut(), - after_resume_cmd: ptr::null_mut(), - logind_lock_cmd: ptr::null_mut(), - logind_unlock_cmd: ptr::null_mut(), + seat_name: None, + before_sleep_cmd: None, + after_resume_cmd: None, + logind_lock_cmd: None, + logind_unlock_cmd: None, logind_idlehint: false, timeouts_enabled: false, wait: false, @@ -290,7 +298,6 @@ unsafe extern "C" fn swayidle_log_init(verbosity: log_importance) { } impl swayidle_state { unsafe fn init(&mut self) { - memset(ptr::addr_of_mut!(*self).cast(), 0, mem::size_of::()); wl_list_init(&mut self.timeout_cmds); wl_list_init(&mut self.seats); } @@ -299,22 +306,18 @@ impl swayidle_state { let mut tmp: *mut swayidle_timeout_cmd = (*cmd).link.next.cast(); while ptr::addr_of_mut!((*cmd).link) != ptr::addr_of_mut!(self.timeout_cmds) { wl_list_remove(&mut (*cmd).link); - free((*cmd).idle_cmd.cast()); - free((*cmd).resume_cmd.cast()); - free(cmd.cast()); + drop(Box::from_raw(cmd)); cmd = tmp; tmp = (*cmd).link.next.cast(); } - free(self.after_resume_cmd.cast()); - free(self.before_sleep_cmd.cast()); } unsafe fn sway_terminate(&self, exit_code: libc::c_int) -> ! { wl_display_disconnect(self.display); wl_event_loop_destroy(self.event_loop); exit(exit_code); } - unsafe fn cmd_exec(&self, param: *mut libc::c_char) { - log::debug!("Cmd exec {}", read_str(param)); + unsafe fn cmd_exec(&self, param: &str) { + log::debug!("Cmd exec {param}"); let mut pid = fork(); match pid { 0 => { @@ -330,10 +333,11 @@ impl swayidle_state { signal(2, 0); signal(15, 0); signal(10, 0); + let param = CString::new(param).unwrap(); let cmd: [*const libc::c_char; 4] = [ b"sh\0".as_ptr().cast(), b"-c\0".as_ptr().cast(), - param, + param.as_ptr(), ptr::null(), ]; execvp(cmd[0], cmd.as_ptr()); @@ -352,7 +356,7 @@ impl swayidle_state { log::error!("fork failed: {}", strerror(*__errno_location()),); } _ => { - log::debug!("Spawned process {}", read_str(param)); + log::debug!("Spawned process {param}"); if self.wait { log::debug!("Blocking until process exits"); } @@ -460,7 +464,7 @@ impl swayidle_state { self.wait = 1 != 0; } 83 => { - self.seat_name = strdup(optarg); + self.seat_name = read_str2(optarg); } 104 | 63 => { printf(b"Usage: %s [OPTIONS]\n\0".as_ptr().cast(), *argv); @@ -518,16 +522,16 @@ impl swayidle_state { b"delay\0".as_ptr().cast(), ptr::addr_of_mut!(sleep_lock_fd), ); - if !self.after_resume_cmd.is_null() { - self.cmd_exec(self.after_resume_cmd); + if let Some(after_resume_cmd) = &self.after_resume_cmd { + self.cmd_exec(after_resume_cmd); } if self.logind_idlehint { set_idle_hint(false); } return 0; } - if !self.before_sleep_cmd.is_null() { - self.cmd_exec(self.before_sleep_cmd); + if let Some(before_sleep_cmd) = &self.before_sleep_cmd { + self.cmd_exec(before_sleep_cmd); } log::debug!("Prepare for sleep done"); release_inhibitor_lock(sleep_lock_fd); @@ -535,8 +539,8 @@ impl swayidle_state { } unsafe fn handle_lock(&self) -> libc::c_int { log::debug!("Lock signal received"); - if !self.logind_lock_cmd.is_null() { - self.cmd_exec(self.logind_lock_cmd); + if let Some(logind_lock_cmd) = &self.logind_lock_cmd { + self.cmd_exec(logind_lock_cmd); } log::debug!("Lock command done"); 0 @@ -546,8 +550,8 @@ impl swayidle_state { if self.logind_idlehint { set_idle_hint(false); } - if !self.logind_unlock_cmd.is_null() { - self.cmd_exec(self.logind_unlock_cmd); + if let Some(logind_unlock_cmd) = &self.logind_unlock_cmd { + self.cmd_exec(logind_unlock_cmd); } log::debug!("Unlock command done"); 0 @@ -635,8 +639,8 @@ impl swayidle_state { exit(-1); } self.before_sleep_cmd = parse_command(argc - 1, &mut *argv.offset(1)); - if !self.before_sleep_cmd.is_null() { - log::debug!("Setup sleep lock: {}", read_str(self.before_sleep_cmd)); + if let Some(before_sleep_cmd) = &self.before_sleep_cmd { + log::debug!("Setup sleep lock: {before_sleep_cmd}"); } 2 } @@ -648,8 +652,8 @@ impl swayidle_state { exit(-1); } self.after_resume_cmd = parse_command(argc - 1, &mut *argv.offset(1)); - if !self.after_resume_cmd.is_null() { - log::debug!("Setup resume hook: {}", read_str(self.after_resume_cmd)); + if let Some(after_resume_cmd) = &self.after_resume_cmd { + log::debug!("Setup resume hook: {after_resume_cmd}"); } 2 } @@ -659,8 +663,8 @@ impl swayidle_state { exit(-1); } self.logind_lock_cmd = parse_command(argc - 1, &mut *argv.offset(1)); - if !self.logind_lock_cmd.is_null() { - log::debug!("Setup lock hook: {}", read_str(self.logind_lock_cmd)); + if let Some(logind_lock_cmd) = &self.logind_lock_cmd { + log::debug!("Setup lock hook: {logind_lock_cmd}"); } 2 } @@ -670,8 +674,8 @@ impl swayidle_state { exit(-1); } self.logind_unlock_cmd = parse_command(argc - 1, &mut *argv.offset(1)); - if !self.logind_unlock_cmd.is_null() { - log::debug!("Setup unlock hook: {}", read_str(self.logind_unlock_cmd)); + if let Some(logind_unlock_cmd) = &self.logind_unlock_cmd { + log::debug!("Setup unlock hook: {logind_unlock_cmd}"); } 2 } @@ -752,6 +756,13 @@ impl Drop for swayidle_state { unsafe { self.finish() } } } +unsafe fn read_str2(ptr: *const libc::c_char) -> Option { + if ptr.is_null() { + None + } else { + Some(CStr::from_ptr(ptr).to_string_lossy().into()) + } +} unsafe fn read_str(ptr: *const libc::c_char) -> Cow<'static, str> { if ptr.is_null() { "".into() @@ -1227,8 +1238,8 @@ unsafe extern "C" fn handle_idled(data: *mut libc::c_void, _notif: *mut ext_idle log::debug!("idle state"); if (*cmd).idlehint { set_idle_hint(true); - } else if !(*cmd).idle_cmd.is_null() { - state.cmd_exec((*cmd).idle_cmd); + } else if let Some(idle_cmd) = &(*cmd).idle_cmd { + state.cmd_exec(idle_cmd); } } unsafe extern "C" fn handle_resumed( @@ -1243,8 +1254,8 @@ unsafe extern "C" fn handle_resumed( } if (*cmd).idlehint { set_idle_hint(false); - } else if !(*cmd).resume_cmd.is_null() { - state.cmd_exec((*cmd).resume_cmd); + } else if let Some(resume_cmd) = &(*cmd).resume_cmd { + state.cmd_exec(resume_cmd); } } static mut idle_notification_listener: ext_idle_notification_v1_listener = @@ -1252,13 +1263,17 @@ static mut idle_notification_listener: ext_idle_notification_v1_listener = idled: Some(handle_idled), resumed: Some(handle_resumed), }; -unsafe extern "C" fn parse_command(argc: usize, argv: *mut *mut libc::c_char) -> *mut libc::c_char { +unsafe fn parse_command(argc: usize, argv: *mut *mut libc::c_char) -> Option { if argc < 1 { log::error!("Missing command"); - return ptr::null_mut(); + return None; } - log::debug!("Command: {}", read_str(*argv)); - strdup(*argv) + let Some(ret) = read_str2(*argv) else { + log::error!("Missing command"); + return None; + }; + log::debug!("Command: {ret}"); + Some(ret) } unsafe extern "C" fn build_timeout_cmd(argv: *mut *mut libc::c_char) -> *mut swayidle_timeout_cmd { *__errno_location() = 0; @@ -1272,15 +1287,19 @@ unsafe extern "C" fn build_timeout_cmd(argv: *mut *mut libc::c_char) -> *mut swa ); exit(-1); } - let cmd: *mut swayidle_timeout_cmd = calloc(1, mem::size_of::()).cast(); - (*cmd).idlehint = false; - (*cmd).resume_pending = false; - if seconds > 0 { - (*cmd).timeout = seconds * 1000; - } else { - (*cmd).timeout = -1; - } - cmd + Box::into_raw(Box::new(swayidle_timeout_cmd { + idlehint: false, + resume_pending: false, + timeout: if seconds > 0 { seconds * 1000 } else { -1 }, + idle_cmd: None, + idle_notification: ptr::null_mut(), + link: wl_list { + prev: ptr::null_mut(), + next: ptr::null_mut(), + }, + registered_timeout: 0, + resume_cmd: None, + })) } unsafe extern "C" fn handle_signal(sig: libc::c_int, _data: *mut libc::c_void) -> libc::c_int { state.handle_signal(sig) @@ -1375,7 +1394,7 @@ unsafe fn main_0(argc: usize, argv: *mut *mut libc::c_char) -> libc::c_int { let mut seat_i: *mut seat; seat_i = state.seats.next.cast(); while ptr::addr_of_mut!((*seat_i).link) != ptr::addr_of_mut!(state.seats) { - if (state.seat_name).is_null() || strcmp((*seat_i).name, state.seat_name) == 0 { + if !matches!(&state.seat_name, Some(seat_name) if read_str((*seat_i).name) != *seat_name) { seat = (*seat_i).proxy; } seat_i = (*seat_i).link.next.cast(); @@ -1385,25 +1404,25 @@ unsafe fn main_0(argc: usize, argv: *mut *mut libc::c_char) -> libc::c_int { return -4; } if seat.is_null() { - if state.seat_name.is_null() { - log::error!("No seat found"); + if let Some(seat_name) = &state.seat_name { + log::error!("Seat {seat_name} not found"); } else { - log::error!("Seat {} not found", read_str(state.seat_name)); + log::error!("No seat found"); } return -5; } let mut should_run = wl_list_empty(&state.timeout_cmds) == 0; state.connect_to_bus(); setup_property_changed_listener(); - if !state.before_sleep_cmd.is_null() || !state.after_resume_cmd.is_null() { + if state.before_sleep_cmd.is_some() || state.after_resume_cmd.is_some() { should_run = true; setup_sleep_listener(); } - if !state.logind_lock_cmd.is_null() { + if state.logind_lock_cmd.is_some() { should_run = true; setup_lock_listener(); } - if !state.logind_unlock_cmd.is_null() { + if state.logind_unlock_cmd.is_some() { should_run = true; setup_unlock_listener(); }