//! `memoryd serve --config `. use std::ffi::OsString; use std::path::PathBuf; use std::process::ExitCode; use std::sync::Arc; use bxcore::instance; use memoryd::config::{Config, ConfigError}; use memoryd::honcho::config::RUNBOOK as HONCHO_INVALID; use memoryd::serve; const USAGE: &str = "usage: memoryd serve --config "; const START_FAILED: &str = "see docs/runbook.md#memoryd-start-failed"; fn main() -> ExitCode { let args: Vec = std::env::args_os().skip(1).collect(); let Some(path) = parse(&args) else { eprintln!("{USAGE}"); return ExitCode::from(2); }; let config = match Config::load(&path) { Ok(config) => config, Err(e) => { let pointer = match &e { ConfigError::Read(..) | ConfigError::Parse(..) => START_FAILED, ConfigError::Honcho(..) => HONCHO_INVALID, }; eprintln!("memoryd: {e}\n{pointer}"); return ExitCode::from(1); } }; // One memoryd per home (M5b spec, section 9a). The lock comes before anything under the home // is made or bound, so a second copy never takes the sockets of the one that runs. Held until // the process ends. let lock_path = config.paths.home.join("run/memoryd.lock"); let _instance = match instance::lock(&lock_path) { Ok(held) => held, Err(e) => { eprintln!("{}", e.line("memoryd", &lock_path)); return ExitCode::from(1); } }; let log: serve::Log = Arc::new(|line: &str| eprintln!("{line}")); let running = match serve::start(config, log) { Ok(running) => running, // The ledger's and a key's lines name their own pointers. Err(e @ (serve::StartError::Ledger(_) | serve::StartError::Secret(_))) => { eprintln!("memoryd: {e}"); return ExitCode::from(1); } Err(e) => { eprintln!("memoryd: {e}\n{START_FAILED}"); return ExitCode::from(1); } }; eprintln!("memoryd: serving"); match running.run() { Ok(()) => ExitCode::SUCCESS, Err(e) => { eprintln!("memoryd: stopped serving: {e}\n{START_FAILED}"); ExitCode::from(1) } } } /// The config path of `serve --config `, or `None` for any other list. fn parse(args: &[OsString]) -> Option { match args { [serve, flag, path] if serve == "serve" && flag == "--config" => Some(PathBuf::from(path)), _ => None, } }