diff options
Diffstat (limited to 'src/exec.zig')
| -rw-r--r-- | src/exec.zig | 22 |
1 files changed, 21 insertions, 1 deletions
diff --git a/src/exec.zig b/src/exec.zig index 0bce67d2..6e437093 100644 --- a/src/exec.zig +++ b/src/exec.zig @@ -341,11 +341,20 @@ pub fn spawnV9fsTty(p: *Pardes, from: usize) void { fn spawnTtyWithMount(p: *Pardes, from: usize, v9fs: bool) ?*Pane { if (p.panes[from] == null) return null; + // A directory that is not there makes no terminal: its shell could not + // 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)) { + 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; }; - const nt = p.newShell(free, p.execDir(from)) catch |err| { + const nt = p.newShell(free, dir) catch |err| { if (err == error.PathTooLong) { p.reportFailure(from, std.fmt.comptimePrint("Tty: its directory is longer than a path may be ({d} bytes)", .{pardes.memory.limits.host_path_cap})); return null; @@ -360,6 +369,17 @@ fn spawnTtyWithMount(p: *Pardes, from: usize, v9fs: bool) ?*Pane { return nt; } +/// Whether `path` is a directory on this host, the turn out while it asks +/// (it may be inside a mount this editor serves). +fn isDirectory(path: []const u8) bool { + var buf: [4096]u8 = undefined; + const z = std.fmt.bufPrintSentinel(&buf, "{s}", .{path}, 0) catch return false; + pardes.turn.yield(); + defer pardes.turn.back(); + const stat = std.Io.Dir.cwd().statFile(std.Io.Threaded.global_single_threaded.io(), z, .{}) catch return false; + return stat.kind == .directory; +} + /// With `BootShell replace`, a doc landing in `col` closes a lone pristine /// shell there, the boot's placeholder, and absorbVWeight hands its space to /// the doc. With `keep`, the default, the shell stays like any other pane. |
