diff options
| author | Gabriel Schneider <[email protected]> | 2026-09-29 11:23:19 -0300 |
|---|---|---|
| committer | Gabriel Schneider <[email protected]> | 2026-10-01 00:12:16 -0300 |
| commit | 1ac8fbeedaf7cba881a7423b92ead1f739b8ac21 (patch) | |
| tree | c3916f9918fb98252987331195cd1b70712c890d /src/pardes.zig | |
| parent | 2c98513a23d060093d690dbd7743dda5ad86c117 (diff) | |
| download | pardes-1ac8fbeedaf7cba881a7423b92ead1f739b8ac21.tar.gz pardes-1ac8fbeedaf7cba881a7423b92ead1f739b8ac21.zip | |
A script whose interpreter is not there is told apart from a missing shell, and Tty refuses it up front
Tty's up-front check found the script and let it through, so the pane was made, its exec failed ENOENT, and the log read new, msg shell: shell not found, del, then the err. The check now reads a script's #! line and refuses it, interpreter /no/such/interp not found, and an exec that fails ENOENT on a file that is there says the same.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Diffstat (limited to 'src/pardes.zig')
| -rw-r--r-- | src/pardes.zig | 34 |
1 files changed, 24 insertions, 10 deletions
diff --git a/src/pardes.zig b/src/pardes.zig index d9c69921..d2fd795b 100644 --- a/src/pardes.zig +++ b/src/pardes.zig @@ -5338,16 +5338,7 @@ pub const Pardes = struct { const pane = p.panes[id] orelse return; pane.shell_failed = true; ctlfs.pty.shellGone(p, pane, false); - if (err == error.FileNotFound or err == error.NotDir) - p.reportFailure(id, "shell: directory missing (no such directory)") - else - p.reportError(id, "shell", err); - // A 9P write that asked for the shell (pty/ctl's exec), waiting on - // it, fails with what was said, as a failed Save's does. - const said = pane.msg[0..pane.msg_len]; - const kept = @import("Messages.zig").clip(said, p.fs.late_failure.len); - @memcpy(p.fs.late_failure[0..kept.len], kept); - p.fs.late_failure_len = @intCast(kept.len); + p.sayShellFailure(id, err); // A command that never started ended: `exit 127`, as a shell says of // a command it could not run, so a follower waiting on its exit // hears one, its tag stops saying it runs, and Kill finds nothing. @@ -5362,6 +5353,29 @@ pub const Pardes = struct { } } + fn sayShellFailure(p: *Pardes, id: u8, err: anyerror) void { + const pane = p.panes[id] orelse return; + if (err == error.FileNotFound or err == error.NotDir) { + p.reportFailure(id, "shell: directory missing (no such directory)"); + } else if (err == error.InterpreterNotFound) { + // The script is there; the program its `#!` names is not. + var said: [320]u8 = undefined; + var interp: [256]u8 = undefined; + var buf: [std.fs.max_path_bytes]u8 = undefined; + const Shell = if (comptime hosted) @import("host_io.zig").Shell else void; + const name: ?[]const u8 = if (comptime hosted) (if (Shell.find(pane.shell orelse p.shellBin(), &buf)) |f| Shell.missingInterpreter(f, &interp) else null) else null; + p.reportFailure(id, if (name) |n| std.fmt.bufPrint(&said, "shell: interpreter {s} not found", .{n}) catch "shell: interpreter not found" else "shell: interpreter not found"); + } else { + p.reportError(id, "shell", err); + } + // A 9P write that asked for the shell (pty/ctl's exec), waiting on + // it, fails with what was said, as a failed Save's does. + const said = pane.msg[0..pane.msg_len]; + const kept = @import("Messages.zig").clip(said, p.fs.late_failure.len); + @memcpy(p.fs.late_failure[0..kept.len], kept); + p.fs.late_failure_len = @intCast(kept.len); + } + pub fn saveFailed(p: *Pardes, id: u8, path: []const u8, err: anyerror) void { if (p.panes[id]) |pane| if (pane.file) |*f| { // The `-%` spelling fs.zig already uses for "make this dirty". |
