From 8aafc3fa24c7475a07259eb06cd5d217f510df98 Mon Sep 17 00:00:00 2001 From: Gabriel Schneider Date: Wed, 5 Aug 2026 19:32:30 -0300 Subject: add a Shell builtin, default fish, with per-family prompt integration --- src/gui/gui.zig | 25 ++++++++++++++----------- 1 file changed, 14 insertions(+), 11 deletions(-) (limited to 'src/gui/gui.zig') diff --git a/src/gui/gui.zig b/src/gui/gui.zig index a4883fa6..e1d5c86d 100644 --- a/src/gui/gui.zig +++ b/src/gui/gui.zig @@ -28,6 +28,7 @@ const selection_pipe = @import("../selection_pipe.zig"); const is_emscripten = builtin.os.tag == .emscripten; const temp_file = if (is_emscripten) struct {} else @import("../temp_file.zig"); +const shell_bin = if (is_emscripten) struct {} else @import("../shell_bin.zig"); pub const c = @cImport({ @cDefine("SDL_DISABLE_OLD_NAMES", "1"); @@ -44,9 +45,6 @@ extern "c" fn setenv(name: [*:0]const u8, value: [*:0]const u8, overwrite: c_int extern "c" fn emscripten_get_element_css_size(target: [*:0]const u8, width: *f64, height: *f64) c_int; const EMSCRIPTEN_RESULT_SUCCESS: c_int = 0; -// absolute shell path per OS: execv must not search PATH (no allocation -// between fork and exec) -const bash_path: [*:0]const u8 = if (builtin.os.tag == .linux) "/usr/bin/bash" else "/bin/bash"; // TIOCSWINSZ: absent from std.c.T on darwin — _IOW('t', 103, winsize) const TIOCSWINSZ: c_int = @bitCast(@as(u32, if (@hasDecl(posix.T, "IOCSWINSZ")) posix.T.IOCSWINSZ else 0x80087467)); @@ -1272,7 +1270,8 @@ fn runNative(init: std.process.Init, opts_in: pardes.Options) !void { core.native_images = true; // shells emit OSC 133 prompt marks via this rc (prompt hiding, click-move) - writeFile(pardes.bash_rc); + writeFile(shell_bin.bash_rc_path, shell_bin.bash_rc); + writeFile(shell_bin.fish_rc_path, shell_bin.fish_rc); // macos: apple's bash 3.2 prints the zsh-deprecation banner into every // pane unless this is in the env BEFORE bash starts (the rc is too late) if (comptime builtin.os.tag.isDarwin()) _ = setenv("BASH_SILENCE_DEPRECATION_WARNING", "1", 1); @@ -1775,7 +1774,8 @@ fn runGrid(init: std.process.Init, opts_in: pardes.Options) !void { if (opts.load_path == null) core.update(.{ .resize = .{ .cols = grid_cols, .rows = grid_rows } }); - writeFile(pardes.bash_rc); + writeFile(shell_bin.bash_rc_path, shell_bin.bash_rc); + writeFile(shell_bin.fish_rc_path, shell_bin.fish_rc); // macos: apple's bash 3.2 prints the zsh-deprecation banner into every // pane unless this is in the env BEFORE bash starts (the rc is too late) if (comptime builtin.os.tag.isDarwin()) _ = setenv("BASH_SILENCE_DEPRECATION_WARNING", "1", 1); @@ -2599,7 +2599,7 @@ fn drainEffects( cwd_buf[cwd.len] = 0; cwd_z = @ptrCast(&cwd_buf); } - const pt = forkShell(cwd_z, core.screen_h, core.screen_w); + const pt = forkShell(core.shellBin(), cwd_z, core.screen_h, core.screen_w); ptys[sp.pane] = pt; // report the pane's starting directory back to the core (tags) var lbuf: [1024]u8 = undefined; @@ -2678,14 +2678,17 @@ fn drainEffects( }; } -fn forkShell(cwd: ?[*:0]const u8, rows: u16, cols: u16) Pty { +fn forkShell(bin: []const u8, cwd: ?[*:0]const u8, rows: u16, cols: u16) Pty { var master: c_int = undefined; + // resolved BEFORE the fork, into this frame, which the child inherits: + // nothing between fork and exec may allocate, and a PATH search would + var path_buf: [std.fs.max_path_bytes]u8 = undefined; + const spawn = shell_bin.resolve(bin, &path_buf); const ws = posix.winsize{ .row = rows, .col = cols, .xpixel = 0, .ypixel = 0 }; const pid = forkpty(&master, null, null, &ws); if (pid == 0) { if (cwd) |cd| _ = chdir(cd); - const argv: [4:null]?[*:0]const u8 = .{ bash_path, "--rcfile", "/tmp/pardes-osc133.bash", null }; - _ = execv(bash_path, &argv); + _ = execv(spawn.path, &spawn.argv); _exit(127); } return .{ .fd = master, .pid = pid }; @@ -4281,8 +4284,8 @@ fn envU16(env: *std.process.Environ.Map, name: []const u8) ?u16 { return std.fmt.parseInt(u16, raw, 10) catch null; } -fn writeFile(data: []const u8) void { - const fd = libc.open("/tmp/pardes-osc133.bash", .{ .ACCMODE = .WRONLY, .CREAT = true, .TRUNC = true }, @as(libc.mode_t, 0o644)); +fn writeFile(path: [*:0]const u8, data: []const u8) void { + const fd = libc.open(path, .{ .ACCMODE = .WRONLY, .CREAT = true, .TRUNC = true }, @as(libc.mode_t, 0o644)); if (fd < 0) return; defer _ = libc.close(fd); writeFd(fd, data); -- cgit v1.3