aboutsummaryrefslogtreecommitdiff
path: root/nitrocli/src/args.rs
diff options
context:
space:
mode:
authorRobin Krahl <robin.krahl@ireas.org>2018-12-18 00:39:24 +0100
committerDaniel Mueller <deso@posteo.net>2018-12-23 12:04:57 -0800
commit048c97adcedab552e8c5b33567a06de4cb5c0f81 (patch)
tree8271dde240632509260c074dd3ae9554b3dda442 /nitrocli/src/args.rs
parent32126d545532971302c0a8d512b5a8ec8226ed33 (diff)
downloadnitrocli-048c97adcedab552e8c5b33567a06de4cb5c0f81.tar.gz
nitrocli-048c97adcedab552e8c5b33567a06de4cb5c0f81.tar.bz2
Port argument handling to argparse
This patch replaces the macro for argument parsing with `argparse::ArgumentParser` from the argparse crate. It moves the application logic to the `commands` module and the argument parsing to the `options` module. An enum is used to represent the available commands. The code is based on the `subcommands.rs` example shipped with argparse.
Diffstat (limited to 'nitrocli/src/args.rs')
-rw-r--r--nitrocli/src/args.rs153
1 files changed, 153 insertions, 0 deletions
diff --git a/nitrocli/src/args.rs b/nitrocli/src/args.rs
new file mode 100644
index 0000000..07a3e6a
--- /dev/null
+++ b/nitrocli/src/args.rs
@@ -0,0 +1,153 @@
+// 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 <http://www.gnu.org/licenses/>. *
+// *************************************************************************
+
+use std::fmt;
+use std::io;
+use std::result;
+use std::str;
+
+use crate::commands;
+use crate::error::Error;
+
+type Result<T> = result::Result<T, Error>;
+
+/// 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<String>) -> 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<Self, Self::Err> {
+ 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<String>) -> 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<String>) -> 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<String>) -> 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<String>) -> 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<String>) -> Result<()> {
+ let mut parser = argparse::ArgumentParser::new();
+ parser.set_description("Clears the cached passphrase");
+ 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<String>) -> Result<(Command, Vec<String>)> {
+ 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<String>) -> Result<()> {
+ let (command, args) = parse_arguments(args)?;
+ command.execute(args)
+}