summaryrefslogtreecommitdiff
path: root/src/ninep
diff options
context:
space:
mode:
Diffstat (limited to 'src/ninep')
-rw-r--r--src/ninep/ctl.zig27
1 files changed, 20 insertions, 7 deletions
diff --git a/src/ninep/ctl.zig b/src/ninep/ctl.zig
index 06eb8cdd..697ef594 100644
--- a/src/ninep/ctl.zig
+++ b/src/ninep/ctl.zig
@@ -300,7 +300,7 @@ pub fn failureErrno(failure: []const u8) u16 {
if (std.mem.indexOf(u8, failure, "no such") != null or std.mem.indexOf(u8, failure, "not found") != null) return E.NOENT;
// A pattern refused (Edit's too) is malformed input, as 9ns reads it;
// so is a word this build has not (`invalid: acme's Put ...`).
- if (std.mem.indexOf(u8, failure, "bad regular expression") != null or std.mem.startsWith(u8, failure, "invalid") or
+ if (std.mem.indexOf(u8, failure, "bad regular expression") != null or std.mem.indexOf(u8, failure, "invalid") != null or
std.mem.startsWith(u8, failure, "address out of range")) return E.INVAL;
// A word's arguments wrong, or a dial that is no address: what 9ns
// reads as EINVAL from the same words (`control message`, `bad `).
@@ -997,7 +997,8 @@ pub fn writePane(p: *Pardes, req: Req, pane: *Pane) Reply {
// else leaves it standing, and says what it takes.
if (!std.mem.eql(u8, choice, "-") and (choice.len != 1 or std.mem.indexOfScalar(u8, choices, choice[0]) == null)) {
var why: [96]u8 = undefined;
- return refuse(p, req, std.fmt.bufPrint(&why, "answer takes {s} or -", .{choices}) catch "answer takes a choice or -", line);
+ // The choice refused is what is quoted: `answer takes a b or - "z"`.
+ return refuseQuoting(p, req, std.fmt.bufPrint(&why, "answer takes {s} or -", .{choices}) catch "answer takes a choice or -", choice);
}
if (apply) _ = p.answerQuestion(id, if (choice[0] == '-') null else choice[0]);
} else if (!apply) {
@@ -1032,6 +1033,9 @@ fn acmeCtl(p: *Pardes, req: Req, serial: u32, line: []const u8, apply: bool) Acm
// name's first byte: a line's words are split at blanks.
if (std.mem.eql(u8, word, "name") and rest.len > 0 and line[word.len + 1] == ' ')
return .{ .refused = tree.failText(req.tag, E.INVAL, "bad character in file name: a blank at its start") };
+ // `name` with nothing after it names nothing: said so, not an unknown word.
+ if (std.mem.eql(u8, word, "name") and rest.len == 0)
+ return .{ .refused = tree.failText(req.tag, E.INVAL, "invalid file name: name takes the name, and there is none") };
const into: ?Into = if (std.mem.eql(u8, word, "name") and rest.len > 0)
.{ .file = .name, .data = line[word.len + 1 ..] }
else if (std.mem.eql(u8, line, "clean"))
@@ -2356,7 +2360,7 @@ test "a setting this frontend cannot show says GUI-only, and DumpDir reads back
if (comptime !pardes.font_picker) {
try testing.expectEqualStrings("Fonts is GUI-only, invalid here \"Fonts\"", wr(p, root_ctl, "Fonts\n").reply.ename);
const ran = wr(p, root_exec, "Fonts\n");
- try testing.expectEqual(E.IO, ran.errno());
+ try testing.expectEqual(E.INVAL, ran.errno());
try testing.expectEqualStrings("Fonts is GUI-only, invalid here", ran.reply.ename);
}
}
@@ -3697,13 +3701,22 @@ test "size is monotonic: growing is never refused, and a size once taken is take
try testing.expectStringStartsWith(bad.reply.ename, "invalid size");
}
-test "Repl with no such language names a few whole, and where the rest are" {
+test "Repl with no such language is invalid, EINVAL, and names a few whole and how many more" {
const p = try th.withTerm(testing.allocator);
defer p.deinit();
const refused = wr(p, Node.of(serialOf(p), .ctl), "Repl zzlang\n");
- try testing.expectEqual(Status.err, refused.reply.status);
- try testing.expect(std.mem.indexOf(u8, refused.reply.ename, "Repl: no language \"zzlang\"; - or one like zig ada bash c c_sharp clojure (") != null);
- try testing.expect(std.mem.indexOf(u8, refused.reply.ename, " more: docs/typ/reference.typ, REPLs)") != null);
+ try testing.expectEqual(E.INVAL, refused.errno());
+ try testing.expect(std.mem.indexOf(u8, refused.reply.ename, "Repl: invalid language \"zzlang\"; - or one like zig ada bash c c_sharp clojure (") != null);
+ try testing.expect(std.mem.endsWith(u8, refused.reply.ename, " more)"));
+}
+
+test "answer quotes the choice it refuses, and a bare name says it names nothing" {
+ const p = try withFile(testing.allocator, "x\n");
+ defer p.deinit();
+ const node = Node.of(serialOf(p), .ctl);
+ const empty = wr(p, node, "name \n");
+ try testing.expectEqual(E.INVAL, empty.errno());
+ try testing.expectEqualStrings("invalid file name: name takes the name, and there is none", empty.reply.ename);
}
test "a 10k-line Edit text block is taken in linear time and memory" {