summaryrefslogtreecommitdiff
path: root/src/host_io.zig
diff options
context:
space:
mode:
authorGabriel Schneider <[email protected]>2026-09-29 12:38:13 -0300
committerGabriel Schneider <[email protected]>2026-10-01 00:12:16 -0300
commite21965c564bf0670c0e95ca493ea69bbc9626577 (patch)
tree08b4bbd851677084236ccb1f64ac3d334f1b9c20 /src/host_io.zig
parent2bd2ae838cd7db2ef5cde9038be50680a59cab97 (diff)
downloadpardes-e21965c564bf0670c0e95ca493ea69bbc9626577.tar.gz
pardes-e21965c564bf0670c0e95ca493ea69bbc9626577.zip
Tty or Shell naming a file that is there but not executable says so
It said no shell "x", not found, as for a name that is nowhere. A file that exists without its execute bit now says not a shell: x is not executable. Co-Authored-By: Claude Opus 5.5 <[email protected]>
Diffstat (limited to 'src/host_io.zig')
-rw-r--r--src/host_io.zig5
1 files changed, 5 insertions, 0 deletions
diff --git a/src/host_io.zig b/src/host_io.zig
index 85ba94f4..072f3100 100644
--- a/src/host_io.zig
+++ b/src/host_io.zig
@@ -872,6 +872,8 @@ pub const Shell = struct {
@memcpy(buf[0..bin.len], bin);
buf[bin.len] = 0;
if (isDirectory(@ptrCast(&buf))) return std.fmt.bufPrint(said, "not a shell: {s} is a directory", .{bin}) catch "not a shell: a directory";
+ // There, but no program: said so, not "not found".
+ if (libc.access(@ptrCast(&buf), 0) == 0) return std.fmt.bufPrint(said, "not a shell: {s} is not executable", .{bin}) catch "not a shell: not executable";
}
// "not found": the words a mount reads as ENOENT.
return std.fmt.bufPrint(said, "no shell \"{s}\", not found (a name on the usual paths, or a path to one)", .{bin}) catch "no such shell";
@@ -912,6 +914,9 @@ pub const Shell = struct {
try std.testing.expectEqualStrings("interpreter /no/such/interp not found", refusal(try std.fmt.bufPrint(&path, "{s}/bad", .{dir}), &said).?);
try std.testing.expect(refusal(try std.fmt.bufPrint(&path, "{s}/good", .{dir}), &said) == null);
try std.testing.expect(std.mem.startsWith(u8, refusal(try std.fmt.bufPrint(&path, "{s}/none", .{dir}), &said).?, "no shell "));
+ try tmp.dir.writeFile(std.testing.io, .{ .sub_path = "plain", .data = "echo\n" });
+ const plain = try std.fmt.bufPrint(&path, "{s}/plain", .{dir});
+ try std.testing.expect(std.mem.endsWith(u8, refusal(plain, &said).?, "plain is not executable"));
}
fn fallback(buf: *[std.fs.max_path_bytes]u8) [*:0]const u8 {