aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--nitrocli/src/args.rs5
-rw-r--r--nitrocli/src/commands.rs61
-rw-r--r--nitrocli/src/main.rs5
-rw-r--r--nitrocli/src/redefine.rs38
4 files changed, 85 insertions, 24 deletions
diff --git a/nitrocli/src/args.rs b/nitrocli/src/args.rs
index f689643..76b9766 100644
--- a/nitrocli/src/args.rs
+++ b/nitrocli/src/args.rs
@@ -815,7 +815,10 @@ pub fn otp_set(ctx: &mut ExecCtx<'_>, args: Vec<String>) -> Result<()> {
));
}
- println!("Warning: The --ascii option is deprecated. Please use --format ascii instead.");
+ println!(
+ ctx,
+ "Warning: The --ascii option is deprecated. Please use --format ascii instead."
+ )?;
secret_format = Some(OtpSecretFormat::Ascii);
}
let secret_format = secret_format.unwrap_or(OtpSecretFormat::Hex);
diff --git a/nitrocli/src/commands.rs b/nitrocli/src/commands.rs
index 6c83c29..c86f20b 100644
--- a/nitrocli/src/commands.rs
+++ b/nitrocli/src/commands.rs
@@ -232,11 +232,16 @@ where
}
/// Query and pretty print the status that is common to all Nitrokey devices.
-fn print_status(model: &'static str, device: &nitrokey::DeviceWrapper) -> Result<()> {
+fn print_status(
+ ctx: &mut args::ExecCtx<'_>,
+ model: &'static str,
+ device: &nitrokey::DeviceWrapper,
+) -> Result<()> {
let serial_number = device
.get_serial_number()
.map_err(|err| get_error("Could not query the serial number", err))?;
println!(
+ ctx,
r#"Status:
model: {model}
serial number: 0x{id}
@@ -249,7 +254,7 @@ fn print_status(model: &'static str, device: &nitrokey::DeviceWrapper) -> Result
fwv1 = device.get_minor_firmware_version(),
urc = device.get_user_retry_count(),
arc = device.get_admin_retry_count(),
- );
+ )?;
Ok(())
}
@@ -260,7 +265,7 @@ pub fn status(ctx: &mut args::ExecCtx<'_>) -> Result<()> {
nitrokey::DeviceWrapper::Pro(_) => "Pro",
nitrokey::DeviceWrapper::Storage(_) => "Storage",
};
- print_status(model, &device)
+ print_status(ctx, model, &device)
}
/// Open the encrypted volume on the nitrokey.
@@ -287,8 +292,12 @@ pub fn storage_close(ctx: &mut args::ExecCtx<'_>) -> Result<()> {
}
/// Pretty print the status of a Nitrokey Storage.
-fn print_storage_status(status: &nitrokey::StorageStatus) {
+fn print_storage_status(
+ ctx: &mut args::ExecCtx<'_>,
+ status: &nitrokey::StorageStatus,
+) -> Result<()> {
println!(
+ ctx,
r#"Status:
SD card ID: {id:#x}
firmware: {fw}
@@ -311,7 +320,8 @@ fn print_storage_status(status: &nitrokey::StorageStatus) {
vu = get_volume_status(&status.unencrypted_volume),
ve = get_volume_status(&status.encrypted_volume),
vh = get_volume_status(&status.hidden_volume),
- );
+ )?;
+ Ok(())
}
/// Connect to and pretty print the status of a Nitrokey Storage.
@@ -321,8 +331,7 @@ pub fn storage_status(ctx: &mut args::ExecCtx<'_>) -> Result<()> {
.get_status()
.map_err(|err| get_error("Getting Storage status failed", err))?;
- print_storage_status(&status);
- Ok(())
+ print_storage_status(ctx, &status)
}
/// Return a String representation of the given Option.
@@ -339,6 +348,7 @@ pub fn config_get(ctx: &mut args::ExecCtx<'_>) -> Result<()> {
.get_config()
.map_err(|err| get_error("Could not get configuration", err))?;
println!(
+ ctx,
r#"Config:
numlock binding: {nl}
capslock binding: {cl}
@@ -348,7 +358,7 @@ pub fn config_get(ctx: &mut args::ExecCtx<'_>) -> Result<()> {
cl = format_option(config.capslock),
sl = format_option(config.scrollock),
otp = config.user_password,
- );
+ )?;
Ok(())
}
@@ -429,7 +439,7 @@ pub fn otp_get(
} else {
get_otp(slot, algorithm, &device)
}?;
- println!("{}", otp);
+ println!(ctx, "{}", otp)?;
Ok(())
}
@@ -504,6 +514,7 @@ pub fn otp_clear(
}
fn print_otp_status(
+ ctx: &mut args::ExecCtx<'_>,
algorithm: args::OtpAlgorithm,
device: &nitrokey::DeviceWrapper,
all: bool,
@@ -534,16 +545,16 @@ fn print_otp_status(
}
Err(err) => return Err(get_error("Could not check OTP slot", err)),
};
- println!("{}\t{}\t{}", algorithm, slot - 1, name);
+ println!(ctx, "{}\t{}\t{}", algorithm, slot - 1, name)?;
}
}
/// Print the status of the OTP slots.
pub fn otp_status(ctx: &mut args::ExecCtx<'_>, all: bool) -> Result<()> {
let device = get_device(ctx)?;
- println!("alg\tslot\tname");
- print_otp_status(args::OtpAlgorithm::Hotp, &device, all)?;
- print_otp_status(args::OtpAlgorithm::Totp, &device, all)?;
+ println!(ctx, "alg\tslot\tname")?;
+ print_otp_status(ctx, args::OtpAlgorithm::Hotp, &device, all)?;
+ print_otp_status(ctx, args::OtpAlgorithm::Totp, &device, all)?;
Ok(())
}
@@ -613,15 +624,16 @@ pub fn pin_unblock(ctx: &mut args::ExecCtx<'_>) -> Result<()> {
}
fn print_pws_data(
+ ctx: &mut args::ExecCtx<'_>,
description: &'static str,
result: result::Result<String, nitrokey::CommandError>,
quiet: bool,
) -> Result<()> {
let value = result.map_err(|err| get_error("Could not access PWS slot", err))?;
if quiet {
- println!("{}", value);
+ println!(ctx, "{}", value)?;
} else {
- println!("{} {}", description, value);
+ println!(ctx, "{} {}", description, value)?;
}
Ok(())
}
@@ -639,13 +651,13 @@ pub fn pws_get(
let pws = get_password_safe(&device)?;
let show_all = !show_name && !show_login && !show_password;
if show_all || show_name {
- print_pws_data("name: ", pws.get_slot_name(slot), quiet)?;
+ print_pws_data(ctx, "name: ", pws.get_slot_name(slot), quiet)?;
}
if show_all || show_login {
- print_pws_data("login: ", pws.get_slot_login(slot), quiet)?;
+ print_pws_data(ctx, "login: ", pws.get_slot_login(slot), quiet)?;
}
if show_all || show_password {
- print_pws_data("password:", pws.get_slot_password(slot), quiet)?;
+ print_pws_data(ctx, "password:", pws.get_slot_password(slot), quiet)?;
}
Ok(())
}
@@ -674,7 +686,12 @@ pub fn pws_clear(ctx: &mut args::ExecCtx<'_>, slot: u8) -> Result<()> {
.map_err(|err| get_error("Could not clear PWS slot", err))
}
-fn print_pws_slot(pws: &nitrokey::PasswordSafe<'_>, slot: usize, programmed: bool) -> Result<()> {
+fn print_pws_slot(
+ ctx: &mut args::ExecCtx<'_>,
+ pws: &nitrokey::PasswordSafe<'_>,
+ slot: usize,
+ programmed: bool,
+) -> Result<()> {
if slot > u8::MAX as usize {
return Err(Error::Error("Invalid PWS slot number".to_string()));
}
@@ -686,7 +703,7 @@ fn print_pws_slot(pws: &nitrokey::PasswordSafe<'_>, slot: usize, programmed: boo
} else {
"[not programmed]".to_string()
};
- println!("{}\t{}", slot, name);
+ println!(ctx, "{}\t{}", slot, name)?;
Ok(())
}
@@ -697,13 +714,13 @@ pub fn pws_status(ctx: &mut args::ExecCtx<'_>, all: bool) -> Result<()> {
let slots = pws
.get_slot_status()
.map_err(|err| get_error("Could not read PWS slot status", err))?;
- println!("slot\tname");
+ println!(ctx, "slot\tname")?;
for (i, &value) in slots
.into_iter()
.enumerate()
.filter(|(_, &value)| all || value)
{
- print_pws_slot(&pws, i, value)?;
+ print_pws_slot(ctx, &pws, i, value)?;
}
Ok(())
}
diff --git a/nitrocli/src/main.rs b/nitrocli/src/main.rs
index ad79c6e..2425562 100644
--- a/nitrocli/src/main.rs
+++ b/nitrocli/src/main.rs
@@ -68,6 +68,9 @@
//! Nitrocli is a program providing a command line interface to certain
//! commands of Nitrokey Pro and Storage devices.
+#[macro_use]
+mod redefine;
+
mod args;
mod commands;
mod error;
@@ -101,7 +104,7 @@ fn run<'ctx, 'io: 'ctx>(ctx: &'ctx mut RunCtx<'io>, args: Vec<String>) -> i32 {
_ => 1,
},
_ => {
- println!("{}", err);
+ let _ = eprintln!(ctx, "{}", err);
1
}
},
diff --git a/nitrocli/src/redefine.rs b/nitrocli/src/redefine.rs
new file mode 100644
index 0000000..a79cb4b
--- /dev/null
+++ b/nitrocli/src/redefine.rs
@@ -0,0 +1,38 @@
+// redefine.rs
+
+// *************************************************************************
+// * Copyright (C) 2019 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/>. *
+// *************************************************************************
+
+// A replacement of the standard println!() macro that requires an
+// execution context as the first argument and prints to its stdout.
+macro_rules! println {
+ ($ctx:expr) => {
+ writeln!($ctx.stdout, "")
+ };
+ ($ctx:expr, $($arg:tt)*) => {
+ writeln!($ctx.stdout, $($arg)*)
+ };
+}
+
+macro_rules! eprintln {
+ ($ctx:expr) => {
+ writeln!($ctx.stderr, "")
+ };
+ ($ctx:expr, $($arg:tt)*) => {
+ writeln!($ctx.stderr, $($arg)*)
+ };
+}