diff options
| author | Gabriel Schneider <[email protected]> | 2026-09-29 09:05:05 -0300 |
|---|---|---|
| committer | Gabriel Schneider <[email protected]> | 2026-10-01 00:12:16 -0300 |
| commit | 7b727114350030fa34281803cc12a1dbb7e6f7fc (patch) | |
| tree | 032114e21cad83d2f5bf2a01e0e69470a568237b /src/exec.zig | |
| parent | 78d6f64e72be2a22c40feaf012636bc8f04d46de (diff) | |
| download | pardes-7b727114350030fa34281803cc12a1dbb7e6f7fc.tar.gz pardes-7b727114350030fa34281803cc12a1dbb7e6f7fc.zip | |
A command from a missing directory fails ENOENT with no pane; one whose shell never started ends exit 127
Exec made a command pane in a directory that was not there, whose shell
never started: it said running for ever, a follower waited for an exit
that never came, and Kill found it. The line now fails up front, as Tty
does, `exec: <dir>: no such directory`; and a command pane whose shell
the host could not start ends `exit 127` at once. A shell that could not
start in its directory says `directory missing`, not `file not found`.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Diffstat (limited to 'src/exec.zig')
| -rw-r--r-- | src/exec.zig | 20 |
1 files changed, 18 insertions, 2 deletions
diff --git a/src/exec.zig b/src/exec.zig index ebe90b98..79717963 100644 --- a/src/exec.zig +++ b/src/exec.zig @@ -351,11 +351,11 @@ fn spawnTtyWithMount(p: *Pardes, from: usize, v9fs: bool) ?*Pane { // start in it, and a dead pane would answer no run. Asked only of a host // that starts shells (none, as in the core's tests, starts none). const dir = p.execDir(from); - if (comptime hosted) if (p.host.vtable.spawn != null) if (@import("fs.zig").localPath(dir)) |local| if (!isDirectory(local)) { + if (missingDir(p, dir)) { var said: [pardes.memory.limits.host_path_cap + 48]u8 = undefined; p.reportFailure(from, std.fmt.bufPrint(&said, "Tty: {s}: no such directory", .{dir}) catch "Tty: no such directory"); return null; - }; + } const free = p.freeSlot() orelse { p.reportError(from, "Tty", error.NoPaneSlots); return null; @@ -375,6 +375,15 @@ fn spawnTtyWithMount(p: *Pardes, from: usize, v9fs: bool) ?*Pane { return nt; } +/// Whether a shell would be started in `dir` and `dir` is not there: asked +/// only of a host that starts shells, and only of a local path. +pub fn missingDir(p: *Pardes, dir: []const u8) bool { + if (comptime !hosted) return false; + if (p.host.vtable.spawn == null) return false; + const local = @import("fs.zig").localPath(dir) orelse return false; + return !isDirectory(local); +} + /// Whether `path` is a directory on this host, the turn out while it asks /// (it may be inside a mount this editor serves). pub fn isDirectory(path: []const u8) bool { @@ -662,6 +671,13 @@ fn runCommand(p: *Pardes, from: usize, line: []const u8) ?usize { } const src = p.panes[from] orelse return null; const dir = p.execDir(from); + // A directory that is not there runs nothing, as Tty makes nothing + // there: no pane, and the write fails ENOENT. + if (missingDir(p, dir)) { + var said: [pardes.memory.limits.host_path_cap + 48]u8 = undefined; + p.reportFailure(from, std.fmt.bufPrint(&said, "exec: {s}: no such directory", .{dir}) catch "exec: no such directory"); + return null; + } // Not one whose pty a job it left behind still prints to: reusing it // would hang that job up. // From a column's tag, only a finished pane in that column is reused, |
