summaryrefslogtreecommitdiff
path: root/src/ninep
diff options
context:
space:
mode:
authorGabriel Schneider <[email protected]>2026-09-30 14:07:54 -0300
committerGabriel Schneider <[email protected]>2026-10-01 00:12:17 -0300
commit3cfc0d921184b5bf25e7855e22003b1ec230c32d (patch)
treedf954636bba9711d1b3429c81500a4c6ce00a59c /src/ninep
parent30bfe8143c5e3840275880d77e9765cf94910ee1 (diff)
downloadpardes-3cfc0d921184b5bf25e7855e22003b1ec230c32d.tar.gz
pardes-3cfc0d921184b5bf25e7855e22003b1ec230c32d.zip
An event record written back without its trailing newline is taken, as every other line file's last line is
`printf 'MX0 10' > event` was refused as a malformed record, while exec, look and every ctl take a last line with no newline. The event file now does too: a write not ending in a newline is read as though it did, and the write still counts the bytes that came. Co-Authored-By: Claude Opus 5.5 <[email protected]>
Diffstat (limited to 'src/ninep')
-rw-r--r--src/ninep/events.zig23
1 files changed, 19 insertions, 4 deletions
diff --git a/src/ninep/events.zig b/src/ninep/events.zig
index c6505f52..63405781 100644
--- a/src/ninep/events.zig
+++ b/src/ninep/events.zig
@@ -688,8 +688,17 @@ fn scanNumber(data: []const u8, i: *usize) ?u32 {
}
/// Writing a Look or Exec record back performs the action it names.
-pub fn writeEvent(p: *Pardes, req: Req, id: usize) Reply {
- const pane0 = p.panes[id] orelse return Reply.fail(req.tag, E.NOENT);
+pub fn writeEvent(p: *Pardes, asked: Req, id: usize) Reply {
+ const pane0 = p.panes[id] orelse return Reply.fail(asked.tag, E.NOENT);
+ // Its last record needs no newline, as every other line file's last
+ // line does not (`printf 'MX0 10' > event`).
+ var req = asked;
+ if (req.data.len > 0 and req.data[req.data.len - 1] != '\n') {
+ const whole = p.scratch.allocator().alloc(u8, req.data.len + 1) catch return Reply.fail(req.tag, E.NOMEM);
+ @memcpy(whole[0..req.data.len], req.data);
+ whole[req.data.len] = '\n';
+ req.data = whole;
+ }
const serial = pane0.serial;
{
const body = pane_files.bodyOf(pane0);
@@ -783,7 +792,7 @@ pub fn writeEvent(p: *Pardes, req: Req, id: usize) Reply {
else => unreachable,
}
}
- return .{ .tag = req.tag, .written = @intCast(req.data.len) };
+ return .{ .tag = req.tag, .written = @intCast(asked.data.len) };
}
// ---- tests ----
@@ -984,11 +993,17 @@ test "writing an event record back performs the action it names" {
try testing.expectEqual(Status.ok, wr(p, event, "FX0 10\nFX0 10\n").reply.status);
try testing.expectEqualStrings("fs-ran", pane.msg[0..pane.msg_len]);
+ // The last record needs no newline, as any line file's last line.
+ pane.msg_len = 0;
+ const bare = wr(p, event, "FX0 10");
+ try testing.expectEqual(Status.ok, bare.reply.status);
+ try testing.expectEqual(@as(u32, 6), bare.reply.written);
+ try testing.expectEqualStrings("fs-ran", pane.msg[0..pane.msg_len]);
+
pane.msg_len = 0;
for ([_][]const u8{
"FX0 10\nFQ0 1\n", // unknown type character
"FX0 999\n", // out of range
- "FX0 10", // no newline
"FX5 1\n", // q0 > q1
"FD0 3\n", // a report, not a request
"F\n",