//! `gatewayd serve --config `: the Mattermost channel. It loads its configuration and its //! token, prepares its directory, then serves until it must stop (exit 1). use std::os::unix::fs::DirBuilderExt; use std::path::Path; use std::process::ExitCode; use std::sync::Arc; use std::sync::atomic::AtomicBool; use gatewayd::config::{Config, MATTERMOST_TOKEN}; use gatewayd::secrets; use gatewayd::serve::{START_FAILED, Tuning, run}; fn main() -> ExitCode { // `args_os`: the config path need not be UTF-8, and `args` would panic on one that is not. let args: Vec = std::env::args_os().skip(1).collect(); let words: Vec> = args.iter().map(|a| a.to_str()).collect(); match (words.as_slice(), args.get(2)) { ([Some("serve"), Some("--config"), _], Some(path)) => serve(Path::new(path)), _ => { eprintln!("usage: gatewayd serve --config "); ExitCode::from(2) } } } fn serve(path: &Path) -> ExitCode { // Each failure prints its message with `eprintln!` and returns `ExitCode::from(1)`. // 1. `let config = match Config::load(path) { ... }`: an Err(e) prints // "gatewayd: {e}\n{START_FAILED}". // 2. `let source = match config.token_source() { ... }`: an Err(why) prints // "gatewayd: {}: {why}\n{START_FAILED}" with `path.display()`. // 3. `let loaded = match secrets::load(MATTERMOST_TOKEN, &source, &|k| std::env::var_os(k))`: // an Err(e) prints "gatewayd: {e}" (the error carries its own pointer). // Then `if let Some(warning) = &loaded.warning { eprintln!("{warning}"); }`. // 4. The state file's directory: // `let dir = config.state_path().parent().map(Path::to_path_buf).unwrap_or_default();` // `std::fs::DirBuilder::new().recursive(true).mode(0o700).create(&dir)`: an Err(e) prints // "gatewayd: cannot prepare {}: {e}\n{START_FAILED}" with `dir.display()`. // 5. `let log: gatewayd::serve::Log = Arc::new(|line: &str| eprintln!("{line}"));` // `let stop = run(config, loaded.secret, Tuning::default(), log, &AtomicBool::new(false));` // `eprintln!("{stop}");` and `ExitCode::from(1)`. todo!() }