From a0ce70651aed0ba47b92a7657c8d2e7d111c1af5 Mon Sep 17 00:00:00 2001 From: Jon Parise Date: Sat, 14 Dec 2024 17:17:52 -0500 Subject: [PATCH] bash: re-enable automatic bash shell detection Bash shell detection was originally disabled in #1823 due to problems with /bin/bash on macOS. Apple distributes their own patched version of Bash 3.2 on macOS that disables the POSIX-style $ENV-based startup path: https://github.com/apple-oss-distributions/bash/blob/e5397a7e74633a4e84194a6c6b609e04077da6f8/bash-3.2/shell.c#L1112-L1114 This means we're unable to perform our automatic shell integration sequence in this specific environment. Standard Bash 3.2 works fine. Knowing this, we can re-enable bash shell detection by default unless we're running "/bin/bash" on Darwin. We can safely assume that's the unsupported Bash executable because /bin is non-writable on modern macOS installations due to System Integrity Protection. macOS users can either manually source our shell integration script (which otherwise works fine with Apple's Bash) or install a standard version of Bash from Homebrew or elsewhere. --- README.md | 8 ++++++-- src/shell-integration/README.md | 10 +++++++--- src/termio/shell_integration.zig | 21 ++++++++++++++++----- 3 files changed, 29 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index 5052ac214..b859bb580 100644 --- a/README.md +++ b/README.md @@ -231,8 +231,12 @@ function fine within Ghostty with the above mentioned shell integration features inoperative. **If you want to disable automatic shell integration,** set `shell-integration = none` in your configuration file. -Automatic `bash` shell integration requires Bash version 4 or later and must be -explicitly enabled by setting `shell-integration = bash`. +> [!NOTE] +> +> The version of Bash distributed with macOS (`/bin/bash`) does not support +> automatic shell integration. You'll need to manually source the shell +> integration script (as shown below). You can also install a standard +> version of Bash from Homebrew or elsewhere and set it as your shell. **For the automatic shell integration to work,** Ghostty must either be run from the macOS app bundle or be installed in a location where the contents of diff --git a/src/shell-integration/README.md b/src/shell-integration/README.md index d5294046f..78f5687df 100644 --- a/src/shell-integration/README.md +++ b/src/shell-integration/README.md @@ -18,9 +18,6 @@ our integration script (`bash/ghostty.bash`). This prevents Bash from loading its normal startup files, which becomes our script's responsibility (along with disabling POSIX mode). -Because automatic Bash shell integration requires Bash version 4 or later, it -must be explicitly enabled (`shell-integration = bash`). - Bash shell integration can also be sourced manually from `bash/ghostty.bash`. This also works for older versions of Bash. @@ -31,6 +28,13 @@ if [ -n "${GHOSTTY_RESOURCES_DIR}" ]; then fi ``` +> [!NOTE] +> +> The version of Bash distributed with macOS (`/bin/bash`) does not support +> automatic shell integration. You'll need to manually source the shell +> integration script (as shown above). You can also install a standard +> version of Bash from Homebrew or elsewhere and set it as your shell. + ### Elvish For [Elvish](https://elv.sh), `$GHOSTTY_RESOURCES_DIR/src/shell-integration` diff --git a/src/termio/shell_integration.zig b/src/termio/shell_integration.zig index 06f2abc67..3d7b769cf 100644 --- a/src/termio/shell_integration.zig +++ b/src/termio/shell_integration.zig @@ -1,4 +1,5 @@ const std = @import("std"); +const builtin = @import("builtin"); const Allocator = std.mem.Allocator; const ArenaAllocator = std.heap.ArenaAllocator; const EnvMap = std.process.EnvMap; @@ -57,11 +58,21 @@ pub fn setup( }; const result: ShellIntegration = shell: { - // For now, bash integration must be explicitly enabled via force_shell. - // Our automatic shell integration requires bash version 4 or later, - // and systems like macOS continue to ship bash version 3 by default. - // This approach avoids the cost of performing a runtime version check. - if (std.mem.eql(u8, "bash", exe) and force_shell == .bash) { + if (std.mem.eql(u8, "bash", exe)) { + // Apple distributes their own patched version of Bash 3.2 + // on macOS that disables the ENV-based POSIX startup path. + // This means we're unable to perform our automatic shell + // integration sequence in this specific environment. + // + // If we're running "/bin/bash" on Darwin, we can assume + // we're using Apple's Bash because /bin is non-writable + // on modern macOS due to System Integrity Protection. + if (comptime builtin.target.isDarwin()) { + if (std.mem.eql(u8, "/bin/bash", command)) { + return null; + } + } + const new_command = try setupBash( alloc_arena, command,