diff options
| author | Gabriel Schneider <[email protected]> | 2026-09-30 11:55:25 -0300 |
|---|---|---|
| committer | Gabriel Schneider <[email protected]> | 2026-10-01 00:12:17 -0300 |
| commit | 8c86eb1bccf5846d5f5b627845f640e3b6b12134 (patch) | |
| tree | aba9d20470ce7504d6f75a5e2226f2f4702abe65 /src | |
| parent | ff161c1200e57f10bfc5d5b7dc6fc573967b9303 (diff) | |
| download | pardes-8c86eb1bccf5846d5f5b627845f640e3b6b12134.tar.gz pardes-8c86eb1bccf5846d5f5b627845f640e3b6b12134.zip | |
A builtin that takes no argument, written with one to an exec, is refused wrong #args as at a ctl
At a ctl, `Config extra` and `DumpConfig extra` were refused with
`wrong #args`. Written to an exec, the builtin match missed, since the word
takes no argument, and the line ran as a shell command named Config, which
did nothing and said nothing. An exec now refuses it with the ctl's words.
A setting word keeps its value (`Verbose off`).
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Diffstat (limited to 'src')
| -rw-r--r-- | src/ninep/ctl.zig | 19 |
1 files changed, 19 insertions, 0 deletions
diff --git a/src/ninep/ctl.zig b/src/ninep/ctl.zig index 98980f2c..e44368ea 100644 --- a/src/ninep/ctl.zig +++ b/src/ninep/ctl.zig @@ -239,6 +239,14 @@ pub fn captured(p: *Pardes, req: Req, id: usize, exec: bool, text: []const u8, i p.fs.results_len = 0; return refuse(p, req, "wrong #args in control message", cmd); }; + // ...and one that takes none, written with one (`Config extra`): + // refused as a ctl's is, not run as a shell command of that name. + if (std.mem.indexOfAny(u8, cmd, " \t")) |sp| if (std.meta.stringToEnum(Builtin, cmd[0..sp])) |b| { + if (!builtins.registry.takesArg(b) and config.Runtime.find(cmd[0..sp]) == null) { + p.fs.results_len = 0; + return refuse(p, req, "wrong #args in control message", cmd); + } + }; } p.fs.capturing = true; p.fs.failure_len = 0; @@ -2435,6 +2443,17 @@ test "a look that misses file:/re/ names the file, and is logged as its pane's" try testing.expect(th.logHas(p, try std.fmt.bufPrint(&want, "err {d} look: {s}/f.txt: no match for regexp", .{ f_serial, dir }))); } +test "a builtin that takes no argument, written with one to an exec, is refused wrong #args, as at a ctl" { + const p = try withFile(testing.allocator, "x\n"); + defer p.deinit(); + const serial = serialOf(p); + for ([_]u64{ @intFromEnum(tree.TopFile.exec), Node.of(serial, .exec) }) |node| for ([_][]const u8{ "Config extra\n", "DumpConfig extra\n" }) |line| { + const r = wr(p, node, line); + try testing.expectEqual(E.INVAL, r.errno()); + try testing.expectStringStartsWith(r.reply.ename, "wrong #args in control message"); + }; +} + test "acme's words run as pardes's (Put is Save, Delete a Del that does not ask) or are refused, never run as commands" { const p = try withFile(testing.allocator, "x\n"); defer p.deinit(); |
