use std::path::Path;
use std::process::Command;
pub(crate) fn configure_ssh_command(cmd: &mut Command, alias: &str, config_path: &Path) {
let exe = std::env::current_exe()
.ok()
.map(|p| p.to_string_lossy().into_owned())
.or_else(|| std::env::args().next())
.unwrap_or_else(|| "purple".to_string());
cmd.env("SSH_ASKPASS", &exe)
.env("SSH_ASKPASS_REQUIRE", "force")
.env("PURPLE_ASKPASS_MODE", "1")
.env("PURPLE_HOST_ALIAS", alias)
.env("PURPLE_CONFIG_PATH", config_path.as_os_str());
}
#[cfg(test)]
mod tests {
use super::*;
use std::collections::HashMap;
use std::ffi::OsString;
use std::path::PathBuf;
fn snapshot_envs(cmd: &Command) -> HashMap<OsString, OsString> {
cmd.get_envs()
.filter_map(|(k, v)| v.map(|val| (k.to_os_string(), val.to_os_string())))
.collect()
}
#[test]
fn sets_ssh_askpass_require_to_force() {
let mut cmd = Command::new("ssh");
configure_ssh_command(&mut cmd, "myhost", &PathBuf::from("/tmp/cfg"));
let envs = snapshot_envs(&cmd);
assert_eq!(
envs.get(&OsString::from("SSH_ASKPASS_REQUIRE")),
Some(&OsString::from("force")),
"SSH_ASKPASS_REQUIRE must be 'force' to work in headless ssh sessions"
);
}
#[test]
fn sets_ssh_askpass_to_current_exe() {
let mut cmd = Command::new("ssh");
configure_ssh_command(&mut cmd, "myhost", &PathBuf::from("/tmp/cfg"));
let envs = snapshot_envs(&cmd);
let askpass = envs
.get(&OsString::from("SSH_ASKPASS"))
.expect("SSH_ASKPASS must be set");
assert!(
!askpass.is_empty(),
"SSH_ASKPASS must point at a non-empty path"
);
}
#[test]
fn sets_purple_context_vars() {
let mut cmd = Command::new("ssh");
configure_ssh_command(&mut cmd, "myhost", &PathBuf::from("/tmp/my/ssh_config"));
let envs = snapshot_envs(&cmd);
assert_eq!(
envs.get(&OsString::from("PURPLE_ASKPASS_MODE")),
Some(&OsString::from("1"))
);
assert_eq!(
envs.get(&OsString::from("PURPLE_HOST_ALIAS")),
Some(&OsString::from("myhost"))
);
assert_eq!(
envs.get(&OsString::from("PURPLE_CONFIG_PATH")),
Some(&OsString::from("/tmp/my/ssh_config"))
);
}
#[test]
fn passes_alias_with_spaces_and_slashes_unmodified() {
let mut cmd = Command::new("ssh");
configure_ssh_command(&mut cmd, "my host/with slash", &PathBuf::from("/tmp/cfg"));
let envs = snapshot_envs(&cmd);
assert_eq!(
envs.get(&OsString::from("PURPLE_HOST_ALIAS")),
Some(&OsString::from("my host/with slash"))
);
}
#[test]
fn does_not_set_bw_session() {
let mut cmd = Command::new("ssh");
configure_ssh_command(&mut cmd, "myhost", &PathBuf::from("/tmp/cfg"));
let envs = snapshot_envs(&cmd);
assert!(!envs.contains_key(&OsString::from("BW_SESSION")));
}
}