From 25b4b3ff87829c14017df28376e486b83606e6a9 Mon Sep 17 00:00:00 2001 From: Wez Furlong Date: Wed, 26 Jan 2022 10:44:27 -0700 Subject: [PATCH] ssh: use `env` when assume_shell=Posix This allows us to send over COLORTERM and TERM_PROGRAM_XXX environment that the SSH server would have denied via AcceptEnv rules. --- Cargo.lock | 1 + docs/config/lua/SshDomain.md | 8 ++++---- mux/Cargo.toml | 1 + mux/src/ssh.rs | 40 +++++++++++++++++++++++++++++++----- 4 files changed, 41 insertions(+), 9 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 983a5b5dc..1f97f46db 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2323,6 +2323,7 @@ dependencies = [ "ratelim", "regex", "serde", + "shell-words", "smol", "terminfo", "termwiz", diff --git a/docs/config/lua/SshDomain.md b/docs/config/lua/SshDomain.md index eae638882..fbca5f5cc 100644 --- a/docs/config/lua/SshDomain.md +++ b/docs/config/lua/SshDomain.md @@ -76,9 +76,9 @@ panes and tabs. The following values are recognized for `assume_shell`: * `"Unknown"` - this is the default. We can't make any assumptions about the remote shell. -* `"Posix"` - the remote host uses a Bourne Shell compatible shell that allows - the syntax `cd DIR ; exec CMD` and `cd DIR ; exec $SHELL`. - +* `"Posix"` - the remote host uses a POSIX/Bourne Shell compatible environment + that allows the syntax `env -c DIR ENV1=VAL1 ENV2=VAL2 CMD` and + `env -c DIR ENV1=VAL1 ENV2=VAL2 $SHELL`. ```lua return { @@ -96,7 +96,7 @@ return { default_prog = {"fish"}, -- assume that we can use syntax like: - -- "cd /some/where ; exec $SHELL" + -- "env -C /some/where $SHELL" -- using whatever the default command shell is on this -- remote host, so that shell integration will respect -- the current directory on the remote host. diff --git a/mux/Cargo.toml b/mux/Cargo.toml index e51efa99b..db564e5fc 100644 --- a/mux/Cargo.toml +++ b/mux/Cargo.toml @@ -32,6 +32,7 @@ rangeset = { path = "../rangeset" } ratelim= { path = "../ratelim" } regex = "1" serde = {version="1.0", features = ["rc", "derive"]} +shell-words = "1.0" smol = "1.2" terminfo = "0.7" termwiz = { path = "../termwiz" } diff --git a/mux/src/ssh.rs b/mux/src/ssh.rs index e021517c4..622f852e9 100644 --- a/mux/src/ssh.rs +++ b/mux/src/ssh.rs @@ -213,13 +213,43 @@ impl RemoteSshDomain { .iter_extra_env_as_str() .map(|(k, v)| (k.to_string(), v.to_string())) .collect(); - env.insert("WEZTERM_PANE".to_string(), pane_id.to_string()); + + // FIXME: this isn't useful without a way to talk to the remote mux. + // One option is to forward the mux via unix domain, another is to + // embed the mux protocol in an escape sequence and just use the + // existing terminal connection + env.insert("WEZTERM_REMOTE_PANE".to_string(), pane_id.to_string()); + + fn build_env_command( + dir: Option, + cmd: &CommandBuilder, + env: &HashMap, + ) -> anyhow::Result { + let mut env_cmd = vec!["env".to_string()]; + if let Some(dir) = dir { + env_cmd.push("-C".to_string()); + env_cmd.push(dir.clone()); + } else if let Some(dir) = cmd.get_cwd() { + let dir = dir.to_str().context("converting cwd to string")?; + env_cmd.push("-C".to_string()); + env_cmd.push(dir.to_string()); + } + + for (k, v) in env { + env_cmd.push(format!("{}={}", k, v)); + } + + let cmd = if cmd.is_default_prog() { + "$SHELL".to_string() + } else { + cmd.as_unix_command_line()? + }; + + Ok(shell_words::join(env_cmd) + " " + &cmd) + } let command_line = match (cmd.is_default_prog(), self.dom.assume_shell, command_dir) { - (true, Shell::Posix, Some(dir)) => Some(format!("cd {} ; exec $SHELL", dir)), - (false, Shell::Posix, Some(dir)) => { - Some(format!("cd {} ; exec {}", dir, cmd.as_unix_command_line()?)) - } + (_, Shell::Posix, dir) => Some(build_env_command(dir, &cmd, &env)?), (true, _, _) => None, (false, _, _) => Some(cmd.as_unix_command_line()?), };