aboutsummaryrefslogtreecommitdiff
path: root/src/commands.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/commands.rs')
-rw-r--r--src/commands.rs42
1 files changed, 41 insertions, 1 deletions
diff --git a/src/commands.rs b/src/commands.rs
index 549ebec..7612b76 100644
--- a/src/commands.rs
+++ b/src/commands.rs
@@ -8,6 +8,7 @@ use std::convert::TryFrom as _;
use std::env;
use std::ffi;
use std::fmt;
+use std::fs;
use std::io;
use std::mem;
use std::ops;
@@ -33,6 +34,8 @@ use crate::output;
use crate::pinentry;
use crate::Context;
+const NITROCLI_EXT_PREFIX: &str = "nitrocli-";
+
/// Set `libnitrokey`'s log level based on the execution context's verbosity.
fn set_log_level(ctx: &mut Context<'_>) {
let log_lvl = match ctx.config.verbosity {
@@ -1087,15 +1090,52 @@ pub fn pws_status(ctx: &mut Context<'_>, all: bool) -> anyhow::Result<()> {
})
}
+/// Find and list all available extensions.
+///
+/// The logic used in this function should use the same criteria as
+/// `resolve_extension`.
+pub(crate) fn discover_extensions(path_var: &ffi::OsStr) -> anyhow::Result<Vec<String>> {
+ let dirs = env::split_paths(path_var);
+ let mut commands = Vec::new();
+
+ for dir in dirs {
+ match fs::read_dir(&dir) {
+ Ok(entries) => {
+ for entry in entries {
+ let entry = entry?;
+ let path = entry.path();
+ if path.is_file() {
+ let name = entry.file_name();
+ let file = name.to_string_lossy();
+ if file.starts_with(NITROCLI_EXT_PREFIX) {
+ let mut file = file.into_owned();
+ file.replace_range(..NITROCLI_EXT_PREFIX.len(), "");
+ commands.push(file);
+ }
+ }
+ }
+ }
+ Err(ref err) if err.kind() == io::ErrorKind::NotFound => (),
+ x => x
+ .map(|_| ())
+ .with_context(|| format!("Failed to iterate entries of directory {}", dir.display()))?,
+ }
+ }
+ Ok(commands)
+}
+
/// Resolve an extension provided by name to an actual path.
///
/// Extensions are (executable) files that have the "nitrocli-" prefix
/// and are discoverable via the `PATH` environment variable.
+///
+/// The logic used in this function should use the same criteria as
+/// `discover_extensions`.
pub(crate) fn resolve_extension(
path_var: &ffi::OsStr,
ext_name: &ffi::OsStr,
) -> anyhow::Result<path::PathBuf> {
- let mut bin_name = ffi::OsString::from("nitrocli-");
+ let mut bin_name = ffi::OsString::from(NITROCLI_EXT_PREFIX);
bin_name.push(ext_name);
for dir in env::split_paths(path_var) {