diff options
-rw-r--r-- | nitrocli/src/args.rs | 5 | ||||
-rw-r--r-- | nitrocli/src/commands.rs | 61 | ||||
-rw-r--r-- | nitrocli/src/main.rs | 5 | ||||
-rw-r--r-- | nitrocli/src/redefine.rs | 38 |
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)*) + }; +} |