diff --git a/crates/owlry-core/Cargo.toml b/crates/owlry-core/Cargo.toml index a6e5b40..0dc162d 100644 --- a/crates/owlry-core/Cargo.toml +++ b/crates/owlry-core/Cargo.toml @@ -11,6 +11,10 @@ description = "Core daemon for the Owlry application launcher" name = "owlry_core" path = "src/lib.rs" +[[bin]] +name = "owlry-core" +path = "src/main.rs" + [dependencies] owlry-plugin-api = { path = "../owlry-plugin-api" } @@ -32,6 +36,9 @@ dirs = "5" # Error handling thiserror = "2" +# Signal handling +ctrlc = { version = "3", features = ["termination"] } + # Logging & notifications log = "0.4" env_logger = "0.11" diff --git a/crates/owlry-core/src/main.rs b/crates/owlry-core/src/main.rs new file mode 100644 index 0000000..121dcae --- /dev/null +++ b/crates/owlry-core/src/main.rs @@ -0,0 +1,38 @@ +use log::info; + +use owlry_core::paths; +use owlry_core::server::Server; + +fn main() { + env_logger::Builder::from_env(env_logger::Env::default().default_filter_or("warn")).init(); + + let sock = paths::socket_path(); + info!("Starting owlry-core daemon..."); + + // Ensure the socket parent directory exists + if let Err(e) = paths::ensure_parent_dir(&sock) { + eprintln!("Failed to create socket directory: {e}"); + std::process::exit(1); + } + + let server = match Server::bind(&sock) { + Ok(s) => s, + Err(e) => { + eprintln!("Failed to start owlry-core: {e}"); + std::process::exit(1); + } + }; + + // Graceful shutdown on SIGTERM/SIGINT + let sock_cleanup = sock.clone(); + ctrlc::set_handler(move || { + let _ = std::fs::remove_file(&sock_cleanup); + std::process::exit(0); + }) + .ok(); + + if let Err(e) = server.run() { + eprintln!("Server error: {e}"); + std::process::exit(1); + } +} diff --git a/crates/owlry-core/src/paths.rs b/crates/owlry-core/src/paths.rs index a846063..2505f37 100644 --- a/crates/owlry-core/src/paths.rs +++ b/crates/owlry-core/src/paths.rs @@ -154,6 +154,20 @@ pub fn system_data_dirs() -> Vec { dirs } +// ============================================================================= +// Runtime files +// ============================================================================= + +/// IPC socket path: `$XDG_RUNTIME_DIR/owlry/owlry.sock` +/// +/// Falls back to `/tmp` if `$XDG_RUNTIME_DIR` is not set. +pub fn socket_path() -> PathBuf { + let runtime_dir = std::env::var("XDG_RUNTIME_DIR") + .map(PathBuf::from) + .unwrap_or_else(|_| PathBuf::from("/tmp")); + runtime_dir.join(APP_NAME).join("owlry.sock") +} + // ============================================================================= // Helper functions // =============================================================================