From e29067c0b6d4c3adcf5d751381c40652d41dd493 Mon Sep 17 00:00:00 2001 From: Eric Zhang Date: Wed, 22 Nov 2023 22:51:31 -0500 Subject: [PATCH] Fix default shell when /bin/bash is not present Resolves #56. --- crates/sshx/examples/stdin_client.rs | 2 +- crates/sshx/src/main.rs | 5 ++++- crates/sshx/src/terminal.rs | 16 +++++++++++++--- 3 files changed, 18 insertions(+), 5 deletions(-) diff --git a/crates/sshx/examples/stdin_client.rs b/crates/sshx/examples/stdin_client.rs index ea1c226..79787cd 100644 --- a/crates/sshx/examples/stdin_client.rs +++ b/crates/sshx/examples/stdin_client.rs @@ -13,7 +13,7 @@ use tracing::{error, info, trace}; async fn main() -> Result<()> { tracing_subscriber::fmt::init(); - let shell = get_default_shell(); + let shell = get_default_shell().await; info!(%shell, "using default shell"); let mut terminal = Terminal::new(&shell).await?; diff --git a/crates/sshx/src/main.rs b/crates/sshx/src/main.rs index bdacf7a..5765e37 100644 --- a/crates/sshx/src/main.rs +++ b/crates/sshx/src/main.rs @@ -47,7 +47,10 @@ fn print_greeting(shell: &str, controller: &Controller) { #[tokio::main] async fn start(args: Args) -> Result<()> { - let shell = args.shell.unwrap_or_else(get_default_shell); + let shell = match args.shell { + Some(shell) => shell, + None => get_default_shell().await, + }; let runner = Runner::Shell(shell.clone()); let mut controller = Controller::new(&args.server, runner).await?; diff --git a/crates/sshx/src/terminal.rs b/crates/sshx/src/terminal.rs index 8b9933d..a330bbf 100644 --- a/crates/sshx/src/terminal.rs +++ b/crates/sshx/src/terminal.rs @@ -18,13 +18,23 @@ use nix::sys::signal::{kill, Signal::SIGKILL}; use nix::sys::wait::waitpid; use nix::unistd::{execvp, fork, ForkResult, Pid}; use pin_project::{pin_project, pinned_drop}; -use tokio::fs::File; +use tokio::fs::{self, File}; use tokio::io::{self, AsyncRead, AsyncWrite}; use tracing::{instrument, trace}; /// Returns the default shell on this system. -pub fn get_default_shell() -> String { - env::var("SHELL").unwrap_or_else(|_| String::from("/bin/bash")) +pub async fn get_default_shell() -> String { + if let Ok(shell) = env::var("SHELL") { + if !shell.is_empty() { + return shell; + } + } + for shell in ["/bin/bash", "/bin/sh"] { + if fs::metadata(shell).await.is_ok() { + return shell.to_string(); + } + } + String::from("sh") } /// An object that stores the state for a terminal session.