use std::ffi::OsString;
use std::io::IsTerminal as _;
use anyhow::Result;
use clap::Parser;
use crate::{
config::load,
inter::Inter,
runtime::cli::{Cli, Commands},
};
mod cli;
mod generate;
mod store_value;
pub(crate) async fn run<I, T>(args: Option<I>) -> Result<()>
where
I: IntoIterator<Item = T>,
T: Into<OsString> + Clone,
{
let cli = if let Some(args) = args {
Cli::try_parse_from(args)?
} else {
Cli::try_parse()?
};
let config = load(&cli, cli.config_path())?;
let inter = Inter::builder()
.maybe_name(config.socket_path().map(String::from))
.maybe_agent_name(config.agent_socket_path().map(String::from))
.build();
match cli.command() {
Commands::Shares {
num_shares,
threshold,
} => inter.shares(num_shares, threshold).await?,
Commands::Unlock { set, duration } => inter.unlock(set, duration).await?,
Commands::Lock => inter.lock().await?,
Commands::Store {
key,
value,
max_value_bytes,
force,
} => {
const DEFAULT_MAX: usize = 65_536; let max_bytes = max_value_bytes
.or_else(|| config.store_max_value_bytes())
.unwrap_or(DEFAULT_MAX);
let value = if let Some(v) = value {
v
} else if std::io::stdin().is_terminal() {
eprint!("Value: ");
store_value::read_interactive_value(std::io::stdin().lock(), max_bytes)?
} else {
store_value::read_piped_value(tokio::io::stdin(), max_bytes).await?
};
inter.store(key, value, force).await?;
}
Commands::Read { key } => inter.read(key).await?,
Commands::Delete { key, force } => inter.delete(key, force).await?,
Commands::Find { regex } => inter.find(regex).await?,
Commands::Search { query, limit } => inter.search(query, limit).await?,
Commands::Enroll {
name,
force,
independent_auto,
} => inter.enroll(name, force, independent_auto).await?,
Commands::Forget { name, all, force } => inter.forget(name.as_deref(), all, force).await?,
Commands::EnrollStatus => inter.enroll_status().await?,
Commands::Gen {
length,
caps,
numbers,
special,
passphrase,
kind,
key,
} => {
let secret = generate::generate(length, caps, numbers, special, passphrase, kind)?;
if let Some(key) = key {
inter.store(key, secret.clone(), false).await?;
}
generate::print_secret(&secret);
}
}
Ok(())
}