diff --git a/Cargo.lock b/Cargo.lock index 0a46a4b..f817b60 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -345,6 +345,15 @@ dependencies = [ "typenum", ] +[[package]] +name = "daemonize" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab8bfdaacb3c887a54d41bdf48d3af8873b3f5566469f8ba21b92057509f116e" +dependencies = [ + "libc", +] + [[package]] name = "derivative" version = "2.2.0" @@ -612,9 +621,9 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.147" +version = "0.2.146" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3" +checksum = "f92be4933c13fd498862a9e02a3055f8a8d9c039ce33db97306fd5a6caa7f29b" [[package]] name = "linux-raw-sys" @@ -1123,12 +1132,11 @@ version = "0.1.0" dependencies = [ "anyhow", "clap", + "daemonize", "humantime", - "libc", "notify-rust", "serde", "serde_cbor", - "signal-hook", "thiserror", ] diff --git a/Cargo.toml b/Cargo.toml index 1209e08..6626413 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,10 +8,9 @@ edition = "2021" [dependencies] anyhow = "1.0.71" clap = { version = "4.3.4", features = ["derive"] } +daemonize = "0.5.0" humantime = "2.1.0" -libc = "0.2.147" notify-rust = "4.8.0" serde = { version = "1.0.164", features = ["derive"] } serde_cbor = "0.11.2" -signal-hook = "0.3.17" thiserror = "1.0.44" diff --git a/src/cli.rs b/src/cli.rs index 3926105..51fe842 100644 --- a/src/cli.rs +++ b/src/cli.rs @@ -1,5 +1,4 @@ use crate::daemon::{Answer, AnswerErr, Command as OtherCommand}; -use crate::run_path; use anyhow::{Context, Result}; use clap::{Parser, Subcommand}; use std::net::Shutdown; @@ -13,7 +12,7 @@ pub struct Cli { #[command(subcommand)] pub command: Command, #[arg(short, long)] - #[clap(default_value_t = format!("{}/timers.socket", run_path()))] + #[clap(default_value = "/tmp/timers.socket")] pub socket: String, } @@ -25,9 +24,6 @@ pub enum Command { /// do not send notifications #[arg(short, long)] no_notify: bool, - #[arg(short, long)] - #[clap(default_value_t = format!("{}/timers.pid", run_path()))] - pid_file: String, }, /// Add a timer #[clap(visible_alias = "a")] diff --git a/src/daemon.rs b/src/daemon.rs index e9cecbb..7b15c35 100644 --- a/src/daemon.rs +++ b/src/daemon.rs @@ -4,10 +4,6 @@ pub use crate::timer::Timer; use anyhow::Context; use serde::{Deserialize, Serialize}; use std::fmt::{Display, Formatter}; -use std::fs::File; -use std::path::Path; -use std::sync::Arc; -use std::sync::atomic::{AtomicBool, Ordering}; use std::{ io::Write, os::unix::net::{UnixListener, UnixStream}, @@ -67,41 +63,22 @@ pub enum AnswerErr { } pub struct Daemon { - socket_path: Box, - pid_file_path: Box, listener: UnixListener, timers: Vec, pomodoro: Option, notify: bool, } -#[derive(Debug, thiserror::Error)] -pub enum DaemonErr { - #[error("Daemon already running!")] - AlreadyRunning, -} - impl Daemon { - pub fn new(socket: String, pid_file: String, no_notify: bool) -> anyhow::Result { - let pid_file_path = std::path::Path::new(&pid_file); - if pid_file_path.exists() { - return Err(DaemonErr::AlreadyRunning)?; - }; - let mut pid_file = File::create(pid_file_path) - .with_context(|| format!("Could not create pid file at {}!", pid_file))?; - write!(pid_file, "{}", std::process::id()).context("Could not write pid to file!")?; - - let socket_path = std::path::Path::new(&socket); - if socket_path.exists() { - std::fs::remove_file(socket_path) - .with_context(|| format!("Could not remove previous socket {}!", socket))?; + pub fn new(socket_path: String, no_notify: bool) -> anyhow::Result { + let path = std::path::Path::new(&socket_path); + if path.exists() { + std::fs::remove_file(path) + .with_context(|| format!("Could not remove previous socket {}!", socket_path))?; } - let listener = - UnixListener::bind(&socket).context(format!("Cannot bind to socket {}!", socket))?; - + let listener = UnixListener::bind(&socket_path) + .context(format!("Cannot bind to socket {}!", socket_path))?; Ok(Self { - socket_path: socket_path.into(), - pid_file_path: pid_file_path.into(), listener, timers: Vec::new(), pomodoro: None, @@ -191,12 +168,7 @@ impl Daemon { self.listener .set_nonblocking(true) .context("Could not set listener to non blocking!")?; - - let term = Arc::new(AtomicBool::new(false)); - for sig in signal_hook::consts::TERM_SIGNALS { - signal_hook::flag::register(*sig, Arc::clone(&term))?; - } - while !term.load(Ordering::Relaxed) { + loop { while let Ok((stream, _)) = self.listener.accept() { if let Err(e) = self.handle_stream(&stream) { println!("Error while handling stream: {}", e) @@ -204,20 +176,6 @@ impl Daemon { } self.check_timers(); sleep(Duration::from_millis(100)); - }; - Ok(()) - } -} - -impl Drop for Daemon { - fn drop(&mut self) { - println!("Stopping..."); - if let Err(err) = std::fs::remove_file(self.socket_path.as_ref()) { - eprintln!("Error removing socket: {}", err) - }; - if let Err(err) = std::fs::remove_file(self.pid_file_path.as_ref()) { - eprintln!("Error removing pid file: {}", err) - }; - println!("Stopped successfully!"); + } } } diff --git a/src/helper.rs b/src/helper.rs deleted file mode 100644 index 164b5e9..0000000 --- a/src/helper.rs +++ /dev/null @@ -1,7 +0,0 @@ -pub fn getuid() -> u32 { - unsafe { libc::getuid() } -} - -pub fn run_path() -> String { - format!("/run/user/{}", getuid()) -} diff --git a/src/main.rs b/src/main.rs index 5b118eb..3143354 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,21 +1,20 @@ mod cli; mod daemon; -mod helper; mod notification; mod pomodoro; mod timer; use crate::cli::{send_command, Cli, Command as CliCommand}; use crate::daemon::{Command as DaemonCommand, Daemon}; -use crate::helper::run_path; use clap::Parser; use cli::PomodoroCommand; fn main() -> Result<(), anyhow::Error> { let args = Cli::parse(); let daemon_command = match args.command { - CliCommand::Daemon { no_notify, pid_file } => { - return Daemon::new(args.socket, pid_file, no_notify)?.run(); + CliCommand::Daemon { no_notify } => { + daemonize::Daemonize::new().start()?; + return Daemon::new(args.socket, no_notify)?.run(); } CliCommand::Add { name, duration } => { DaemonCommand::Add(name.into_boxed_str(), duration.into())