aboutsummaryrefslogtreecommitdiff
path: root/nitrocli/src/main.rs
diff options
context:
space:
mode:
authorDaniel Mueller <deso@posteo.net>2017-03-26 17:31:28 -0700
committerDaniel Mueller <deso@posteo.net>2017-03-26 17:31:28 -0700
commitde5ae8656387267bb4614bbab6b62784323f23c0 (patch)
tree7be8d72b26b0ae355d5e157c2f36ccb30d6fa347 /nitrocli/src/main.rs
parentcd6e41862cea59ec306e7c9c578270575eb2a73b (diff)
downloadnitrocli-de5ae8656387267bb4614bbab6b62784323f23c0.tar.gz
nitrocli-de5ae8656387267bb4614bbab6b62784323f23c0.tar.bz2
Discover and open nictrokey using libhidapi
This change uses the 'hid' crate to discover and open the Nitrokey Storage device. 'hid' is a wrapper around libhidapi (its libusb back-end in particular). Being a command line application some sort of parameter handling needs to happen. The approach we take is very simple for now to minimize the number of dependencies: we just compare the first argument against the expected ones and raise an error if no match was found. Because we only have positional arguments right now this is all we need.
Diffstat (limited to 'nitrocli/src/main.rs')
-rw-r--r--nitrocli/src/main.rs85
1 files changed, 84 insertions, 1 deletions
diff --git a/nitrocli/src/main.rs b/nitrocli/src/main.rs
index 57e6a7a..bdbfe37 100644
--- a/nitrocli/src/main.rs
+++ b/nitrocli/src/main.rs
@@ -18,7 +18,90 @@
// *************************************************************************
+#![deny(missing_docs)]
+
+//! Nitrocli is a program providing a command line interface to certain
+//! commands of the Nitrokey Storage device.
+
+extern crate hid as libhid;
+
+
+mod error;
+mod nitrokey;
+
+use error::Error;
+use std::process;
+use std::result;
+
+type Result<T> = result::Result<T, Error>;
+type NitroFunc = Fn(&mut libhid::Handle) -> Result<()>;
+
+
+/// Find and open the nitrokey device and execute a function on it.
+fn nitrokey_do(function: &NitroFunc) -> Result<()> {
+ let hid = libhid::init()?;
+ // The Manager::find method is plain stupid as it still returns an
+ // iterable. Using it does not help in more concise error handling.
+ for device in hid.devices() {
+ if device.vendor_id() == nitrokey::VID && device.product_id() == nitrokey::PID {
+ return function(&mut device.open()?);
+ }
+ }
+ return Err(Error::Error("Nitrokey device not found".to_string()));
+}
+
+
+/// Open the encrypted volume on the nitrokey.
+fn open() -> Result<()> {
+ return nitrokey_do(&|handle| {
+ println!("Found nitrokey. Opening encrypted volume...");
+ return Ok(());
+ });
+}
+
+
+/// Close the previously opened encrypted volume.
+fn close() -> Result<()> {
+ return nitrokey_do(&|handle| {
+ println!("Found nitrokey. Closing encrypted volume...");
+ return Ok(());
+ });
+}
+
+
+// A macro for generating a match of the different supported commands.
+// Each supplied command is converted into a string and matched against.
+macro_rules! commands {
+ ( $str:expr, [ $( $command:expr), *] ) => {
+ match &*$str.to_string() {
+ $(
+ stringify!($command) => {
+ if let Err(err) = $command() {
+ println!("{}", err);
+ return 1
+ }
+ return 0
+ },
+ )*
+ x => {
+ println!("Invalid command: {}", x);
+ println!("Available commands: {}", stringify!( $($command)* ));
+ return 1
+ },
+ }
+ }
+}
+
+fn run() -> i32 {
+ let argv: Vec<String> = std::env::args().collect();
+ if argv.len() != 2 {
+ println!("Usage: {} <command>", argv[0]);
+ return 1;
+ }
+
+ commands!(&argv[1], [open, close]);
+}
fn main() {
- println!("Hello, world!");
+ process::exit(run());
}