summaryrefslogtreecommitdiff
path: root/src/ninep
diff options
context:
space:
mode:
Diffstat (limited to 'src/ninep')
-rw-r--r--src/ninep/ctl.zig16
-rw-r--r--src/ninep/pty.zig8
2 files changed, 23 insertions, 1 deletions
diff --git a/src/ninep/ctl.zig b/src/ninep/ctl.zig
index 31382279..92342525 100644
--- a/src/ninep/ctl.zig
+++ b/src/ninep/ctl.zig
@@ -1996,7 +1996,7 @@ test "pty/ctl exec in a directory that is gone fails ENOENT; a shell that cannot
try testing.expectEqualStrings("shell: access denied", p.fs.late_failure[0..p.fs.late_failure_len]);
}
-test "a script whose interpreter is not there: Tty refuses it up front, only an err logged" {
+test "a script whose interpreter is not there: Tty refuses it up front, only an err logged, and pty/ctl exec keeps the running shell" {
const p = try th.withTerm(testing.allocator);
defer p.deinit();
const Starting = struct {
@@ -2023,6 +2023,20 @@ test "a script whose interpreter is not there: Tty refuses it up front, only an
try testing.expect(th.logHas(p, "Tty: interpreter /no/such/interp not found\n"));
try testing.expect(!th.logHas(p, "\nmsg "));
try testing.expect(!th.logHas(p, "\ndel "));
+ // The shell to start again is that script: refused before the running
+ // one goes.
+ const id = p.paneBySerial(serial).?;
+ p.panes[id].?.shell = try p.gpa.dupe(u8, try std.fmt.bufPrint(&line, "{s}/bad", .{dir}));
+ p.setCwd(id, dir);
+ const exec_refused = wr(p, Node.of(serial, .pty_ctl), "exec\n");
+ try testing.expectEqual(E.NOENT, exec_refused.errno());
+ try testing.expectEqualStrings("exec: interpreter /no/such/interp not found", exec_refused.reply.ename);
+ // One the host found could not start (the script changed after): said
+ // with the interpreter's name, and the running shell is not gone.
+ p.fs.late_failure_len = 0;
+ p.restartFailed(@intCast(id), error.InterpreterNotFound);
+ try testing.expectEqualStrings("shell: interpreter /no/such/interp not found", p.fs.late_failure[0..p.fs.late_failure_len]);
+ try testing.expect(!p.panes[id].?.shell_failed);
}
test "every EINVAL a write gets says why, in its err record too; DEL is a control character in a line" {
diff --git a/src/ninep/pty.zig b/src/ninep/pty.zig
index aa0f499a..bf5f432c 100644
--- a/src/ninep/pty.zig
+++ b/src/ninep/pty.zig
@@ -67,6 +67,14 @@ pub fn writeCtl(p: *Pardes, req: Req, id: usize) Reply {
const dir = pane.cwdSlice();
return tree.failText(req.tag, E.NOENT, std.fmt.bufPrint(&p.fs.ename, "exec: {s}: no such directory", .{dir[0..@min(dir.len, 256)]}) catch "exec: no such directory");
};
+ // Nor is a shell that is not there, or a script whose
+ // interpreter is not: refused, and the running shell kept.
+ if (comptime pardes.hosted) if (!apply and std.mem.eql(u8, line, "exec")) if (p.panes[id]) |pane| {
+ const bin = pane.shell orelse p.shellBin();
+ var why: [320]u8 = undefined;
+ if (@import("../host_io.zig").Shell.refusal(bin[0..@min(bin.len, 200)], &why)) |refused|
+ return tree.failText(req.tag, E.NOENT, std.fmt.bufPrint(&p.fs.ename, "exec: {s}", .{refused}) catch "exec: no such shell");
+ };
if (!verb(p, id, line, apply)) return tree.failText(req.tag, E.INVAL, if (outOfRange(line)) e_winsize_range else e_bad_pty_ctl);
}
}