// args.rs
// *************************************************************************
// * Copyright (C) 2018 Daniel Mueller (deso@posteo.net) *
// * *
// * This program is free software: you can redistribute it and/or modify *
// * it under the terms of the GNU General Public License as published by *
// * the Free Software Foundation, either version 3 of the License, or *
// * (at your option) any later version. *
// * *
// * This program is distributed in the hope that it will be useful, *
// * but WITHOUT ANY WARRANTY; without even the implied warranty of *
// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
// * GNU General Public License for more details. *
// * *
// * You should have received a copy of the GNU General Public License *
// * along with this program. If not, see . *
// *************************************************************************
use std::fmt;
use std::io;
use std::result;
use std::str;
use crate::commands;
use crate::error::Error;
type Result = result::Result;
/// A top-level command for nitrocli.
#[derive(Debug)]
pub enum Command {
Clear,
Close,
Open,
Status,
}
impl Command {
/// Execute this command with the given arguments.
pub fn execute(&self, args: Vec) -> Result<()> {
match *self {
Command::Clear => clear(args),
Command::Close => close(args),
Command::Open => open(args),
Command::Status => status(args),
}
}
}
impl fmt::Display for Command {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(
f,
"{}",
match *self {
Command::Clear => "clear",
Command::Close => "close",
Command::Open => "open",
Command::Status => "status",
}
)
}
}
impl str::FromStr for Command {
type Err = ();
fn from_str(s: &str) -> result::Result {
match s {
"clear" => Ok(Command::Clear),
"close" => Ok(Command::Close),
"open" => Ok(Command::Open),
"status" => Ok(Command::Status),
_ => Err(()),
}
}
}
fn parse(parser: &argparse::ArgumentParser<'_>, args: Vec) -> Result<()> {
if let Err(err) = parser.parse(args, &mut io::stdout(), &mut io::stderr()) {
Err(Error::ArgparseError(err))
} else {
Ok(())
}
}
/// Inquire the status of the nitrokey.
fn status(args: Vec) -> Result<()> {
let mut parser = argparse::ArgumentParser::new();
parser.set_description("Print the status of the connected Nitrokey Storage");
parse(&parser, args)?;
commands::status()
}
/// Open the encrypted volume on the nitrokey.
fn open(args: Vec) -> Result<()> {
let mut parser = argparse::ArgumentParser::new();
parser.set_description("Opens the encrypted volume on a Nitrokey Storage");
parse(&parser, args)?;
commands::open()
}
/// Close the previously opened encrypted volume.
fn close(args: Vec) -> Result<()> {
let mut parser = argparse::ArgumentParser::new();
parser.set_description("Closes the encrypted volume on a Nitrokey Storage");
parse(&parser, args)?;
commands::close()
}
/// Clear the PIN stored when opening the nitrokey's encrypted volume.
fn clear(args: Vec) -> Result<()> {
let mut parser = argparse::ArgumentParser::new();
parser.set_description("Clears the cached passphrases");
parse(&parser, args)?;
commands::clear()
}
/// Parse the command-line arguments and return the selected command and
/// the remaining arguments for the command.
fn parse_arguments(args: Vec) -> Result<(Command, Vec)> {
let mut command = Command::Status;
let mut subargs = vec![];
let mut parser = argparse::ArgumentParser::new();
parser.set_description("Provides access to a Nitrokey device");
let _ = parser.refer(&mut command).required().add_argument(
"command",
argparse::Store,
"The command to execute (clear|close|open|status)",
);
let _ = parser.refer(&mut subargs).add_argument(
"arguments",
argparse::List,
"The arguments for the command",
);
parser.stop_on_first_argument(true);
parse(&parser, args)?;
drop(parser);
subargs.insert(0, format!("nitrocli {}", command));
Ok((command, subargs))
}
/// Parse the command-line arguments and execute the selected command.
pub fn handle_arguments(args: Vec) -> Result<()> {
let (command, args) = parse_arguments(args)?;
command.execute(args)
}