From 1af4c0771034aa5d5f0a1f558dabc58c87fa3b19 Mon Sep 17 00:00:00 2001 From: Daniel Mueller Date: Fri, 4 Jan 2019 18:27:45 -0800 Subject: Introduce -v/--verbose option This change introduces a new option, -v/--verbose, that can be used to increase the log level of libnitrokey. The option can be supplied multiple times, with each occurrence increasing the verbosity of the logging. On the implementation side, the option is set as part of connecting the device (piggy-backing on the previously introduced command execution context), although it describes global state that strictly speaking could be set anywhere. It is bad enough that libnitrokey just prints log messages to stderr (and does not accept a file handle) and that it does not track the log level on a per-device basis, but we don't want setting of global state from arbitrary locations inside the program. Instead, let's do that along with what pretty much is the first call into libnitrokey anyway: the connection to the device. --- nitrocli/CHANGELOG.md | 5 +++++ nitrocli/doc/nitrocli.1 | 12 +++++++++++- nitrocli/doc/nitrocli.1.pdf | Bin 13301 -> 13820 bytes nitrocli/src/args.rs | 12 ++++++++++-- nitrocli/src/commands.rs | 24 ++++++++++++++++++++++-- 5 files changed, 48 insertions(+), 5 deletions(-) diff --git a/nitrocli/CHANGELOG.md b/nitrocli/CHANGELOG.md index 26e9e99..e6a4480 100644 --- a/nitrocli/CHANGELOG.md +++ b/nitrocli/CHANGELOG.md @@ -1,3 +1,8 @@ +Unreleased +---------- +- Added the `-v`/`--verbose` option to control libnitrokey log level + + 0.2.1 ----- - Added the `pws` command for accessing the password safe diff --git a/nitrocli/doc/nitrocli.1 b/nitrocli/doc/nitrocli.1 index f16ecc6..7786fc1 100644 --- a/nitrocli/doc/nitrocli.1 +++ b/nitrocli/doc/nitrocli.1 @@ -1,8 +1,9 @@ -.TH NITROCLI 1 2018-12-30 +.TH NITROCLI 1 2019-01-05 .SH NAME nitrocli \- access Nitrokey devices .SH SYNOPSIS .B nitrocli +\fR[\fB\-v\fR|\fB\-\-verbose\fR] \fIcommand\fR [\fIarguments\fR] .SH DESCRIPTION @@ -10,6 +11,15 @@ nitrocli \- access Nitrokey devices It supports the Nitrokey Pro and the Nitrokey Storage. It can be used to access the encrypted volume, the one-time password generator, and the password safe. +.SH OPTIONS +.TP +.B \-v, \-\-verbose +Enable additional logging and control its verbosity. Logging enabled through +this option will appear on the standard error stream. This option can be +supplied multiple times. A single occurrence will show additional warnings. +Commands sent to the device will be shown when supplied three times and full +device communication is available with four occurrences. Supplying this option +five times enables the highest verbosity. .SH COMMANDS .SS General .TP diff --git a/nitrocli/doc/nitrocli.1.pdf b/nitrocli/doc/nitrocli.1.pdf index 0354e93..c5e8898 100644 Binary files a/nitrocli/doc/nitrocli.1.pdf and b/nitrocli/doc/nitrocli.1.pdf differ diff --git a/nitrocli/src/args.rs b/nitrocli/src/args.rs index cb66bb2..869734c 100644 --- a/nitrocli/src/args.rs +++ b/nitrocli/src/args.rs @@ -31,7 +31,9 @@ type Result = result::Result; /// A command execution context that captures additional data pertaining /// the command execution. #[derive(Debug)] -pub struct ExecCtx {} +pub struct ExecCtx { + pub verbosity: u64, +} /// A top-level command for nitrocli. #[derive(Debug)] @@ -950,9 +952,15 @@ fn pws_status(ctx: &ExecCtx, args: Vec) -> Result<()> { /// Parse the command-line arguments and return the selected command and /// the remaining arguments for the command. fn parse_arguments(args: Vec) -> Result<(Command, ExecCtx, Vec)> { + let mut verbosity = 0; let mut command = Command::Status; let mut subargs = vec![]; let mut parser = argparse::ArgumentParser::new(); + let _ = parser.refer(&mut verbosity).add_option( + &["-v", "--verbose"], + argparse::IncrBy::(1), + "Increase the log level (can be supplied multiple times)", + ); parser.set_description("Provides access to a Nitrokey device"); let _ = parser.refer(&mut command).required().add_argument( "command", @@ -970,7 +978,7 @@ fn parse_arguments(args: Vec) -> Result<(Command, ExecCtx, Vec)> subargs.insert(0, format!("nitrocli {}", command)); - let ctx = ExecCtx { }; + let ctx = ExecCtx { verbosity }; Ok((command, ctx, subargs)) } diff --git a/nitrocli/src/commands.rs b/nitrocli/src/commands.rs index aa99bd1..27faf05 100644 --- a/nitrocli/src/commands.rs +++ b/nitrocli/src/commands.rs @@ -38,13 +38,33 @@ fn get_error(msg: &str, err: nitrokey::CommandError) -> Error { Error::Error(format!("{}: {:?}", msg, err)) } +/// Set `libnitrokey`'s log level based on the execution context's verbosity. +fn set_log_level(ctx: &args::ExecCtx) { + let log_lvl = match ctx.verbosity { + // The error log level is what libnitrokey uses by default. As such, + // there is no harm in us setting that as well when the user did not + // ask for higher verbosity. + 0 => nitrokey::LogLevel::Error, + 1 => nitrokey::LogLevel::Warning, + 2 => nitrokey::LogLevel::Info, + 3 => nitrokey::LogLevel::DebugL1, + 4 => nitrokey::LogLevel::Debug, + _ => nitrokey::LogLevel::DebugL2, + }; + nitrokey::set_log_level(log_lvl); +} + /// Connect to any Nitrokey device and return it. -fn get_device(_ctx: &args::ExecCtx) -> Result { +fn get_device(ctx: &args::ExecCtx) -> Result { + set_log_level(ctx); + nitrokey::connect().map_err(|_| Error::Error("Nitrokey device not found".to_string())) } /// Connect to a Nitrokey Storage device and return it. -fn get_storage_device(_ctx: &args::ExecCtx) -> Result { +fn get_storage_device(ctx: &args::ExecCtx) -> Result { + set_log_level(ctx); + nitrokey::Storage::connect().or_else(|_| { Err(Error::Error( "Nitrokey Storage device not found".to_string(), -- cgit v1.2.3