diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/builtins.zig | 9 | ||||
| -rw-r--r-- | src/ninep/ctl.zig | 22 |
2 files changed, 22 insertions, 9 deletions
diff --git a/src/builtins.zig b/src/builtins.zig index 5a2037cf..ba67766d 100644 --- a/src/builtins.zig +++ b/src/builtins.zig @@ -609,11 +609,13 @@ pub const Kill = struct { const names = std.mem.trim(u8, c.arg orelse "", " \t\r\n"); var stopped = false; var jobless = false; + var running = false; for (c.p.panes, 0..) |slot, id| { const pane = slot orelse continue; // A command pane's child is the command: the whole of its // process group goes, as acme's Kill ends the process. if (pane.command) |line| if (!pane.command_done) { + running = true; const said = std.mem.trim(u8, line, " \t"); const first = said[0 .. std.mem.indexOfAny(u8, said, " \t") orelse said.len]; if (names.len > 0) { @@ -627,6 +629,7 @@ pub const Kill = struct { continue; }; if (!panes.terminal.commandRunning(pane)) continue; + running = true; const sent = pane.sent_command.?; if (names.len > 0) { var words = std.mem.tokenizeAny(u8, names, " \t"); @@ -640,9 +643,11 @@ pub const Kill = struct { } if (stopped) return; if (jobless) return c.p.reportFailure(c.id, "Kill: no job to signal (its shell runs it without job control)"); - if (names.len > 0) + // Said, but no failure: a script's Kill, named or not, has nothing + // left to do. Only commands running, none of them the one named, is. + if (names.len > 0 and running) c.p.reportFailure(c.id, "Kill: no running command has that first word") - else // said, but no failure: a script's Kill has nothing left to do + else c.p.setMessage(c.id, "Kill: nothing running"); } }; diff --git a/src/ninep/ctl.zig b/src/ninep/ctl.zig index 4312653c..9a95a10f 100644 --- a/src/ninep/ctl.zig +++ b/src/ninep/ctl.zig @@ -1952,12 +1952,12 @@ test "a builtin that fails a ctl write logs only its err, so the same failure ag p.update(.tick); // the pane's `new` is logged first while (p.nextEffect()) |_| {} const ctl_node = @intFromEnum(tree.TopFile.ctl); - for (0..3) |_| try testing.expectEqual(Status.err, wr(p, ctl_node, "Kill zzz\n").reply.status); + for (0..3) |_| try testing.expectEqual(Status.err, wr(p, ctl_node, "Unmount zzz\n").reply.status); const log = @intFromEnum(tree.TopFile.log); const h = call(p, .{ .tag = 1, .op = .open, .node = log }).reply.handle; const text = call(p, .{ .tag = 2, .op = .read, .node = log, .handle = h, .size = 1 << 16 }).bytes; - try testing.expect(std.mem.endsWith(u8, text, "err - ctl: Kill: no running command has that first word (x3)\n")); - try testing.expect(std.mem.indexOf(u8, text, "msg - Kill") == null); + try testing.expect(std.mem.endsWith(u8, text, "err - ctl: Unmount: no such mount zzz (x3)\n")); + try testing.expect(std.mem.indexOf(u8, text, "msg - Unmount") == null); _ = call(p, .{ .tag = 3, .op = .release, .node = log, .handle = h }); } @@ -2517,6 +2517,14 @@ test "a look at file:3:0 is refused as addr 3:0 is, a column counting from 1" { try testing.expectEqual(Status.ok, wr(p, Node.of(serial, .look), "/test.txt:3:1\n").reply.status); } +test "Kill with a name and nothing running says so and does not fail, as bare Kill does" { + const p = try withFile(testing.allocator, "x\n"); + defer p.deinit(); + const r = wr(p, @intFromEnum(tree.TopFile.ctl), "Kill zzz\n"); + try testing.expectEqual(Status.ok, r.reply.status); + try testing.expect(th.logHas(p, "Kill: nothing running")); +} + test "a line starting with # runs as nothing at an exec or a ctl, silently" { const p = try withFile(testing.allocator, "x\n"); defer p.deinit(); @@ -3315,9 +3323,9 @@ test "a builtin that fails through exec, tagexec or a column's exec fails the wr while (p.nextEffect()) |_| {} const serial = serialOf(p); for ([_]u64{ root_exec, Node.of(serial, .exec), @intFromEnum(tree.TopFile.tagexec), Node.ofCol(pardes.layout.columnSerial(p, 0), .exec) }) |node| { - const failed = wr(p, node, "Kill zzz\n"); + const failed = wr(p, node, "Unmount zzz\n"); try testing.expectEqual(Status.err, failed.reply.status); - try testing.expect(std.mem.indexOf(u8, failed.reply.ename, "Kill: no running command has that first word") != null); + try testing.expect(std.mem.indexOf(u8, failed.reply.ename, "Unmount: no such mount zzz") != null); } const log = @intFromEnum(tree.TopFile.log); const h = call(p, .{ .tag = 1, .op = .open, .node = log }).reply.handle; @@ -3325,8 +3333,8 @@ test "a builtin that fails through exec, tagexec or a column's exec fails the wr try testing.expect(std.mem.indexOf(u8, text, "msg ") == null); // The root's exec ran at the pane, so its err and the pane's exec's are // the same record, counted. - try testing.expectEqual(@as(usize, 3), std.mem.count(u8, text, "Kill: no running command has that first word")); - try testing.expect(std.mem.indexOf(u8, text, "first word (x2)") != null); + try testing.expectEqual(@as(usize, 3), std.mem.count(u8, text, "Unmount: no such mount zzz")); + try testing.expect(std.mem.indexOf(u8, text, "mount zzz (x2)") != null); _ = call(p, .{ .tag = 3, .op = .release, .node = log, .handle = h }); // A control character is refused with its reason. try testing.expectEqualStrings(e_control, wr(p, root_exec, "Msg a\x01b\n").reply.ename); |
