diff options
Diffstat (limited to 'src/ninep/pty.zig')
| -rw-r--r-- | src/ninep/pty.zig | 33 |
1 files changed, 27 insertions, 6 deletions
diff --git a/src/ninep/pty.zig b/src/ninep/pty.zig index c657d27d..b34bd59d 100644 --- a/src/ninep/pty.zig +++ b/src/ninep/pty.zig @@ -76,6 +76,18 @@ fn verb(p: *Pardes, id: usize, line: []const u8, apply: bool) bool { return true; } +/// ctl reads back its state in the words it takes, as a Plan 9 ctl does. +pub fn readCtl(p: *Pardes, req: Req, pane: *Pane) Reply { + p.fs.stage(p.gpa).print(p.gpa, "winsize {d} {d}\n", .{ pane.cols, pane.rows }) catch + return Reply.fail(req.tag, E.NOMEM); + return tree.stagedReply(p, req); +} + +pub fn ctlLen(pane: *const Pane) u64 { + var buf: [32]u8 = undefined; + return (std.fmt.bufPrint(&buf, "winsize {d} {d}\n", .{ pane.cols, pane.rows }) catch unreachable).len; +} + /// Three right-aligned fields: cols, rows and whether the host holds the tty. pub const status_len: u64 = 36; @@ -183,7 +195,7 @@ test "a terminal pane's pty/ holds exactly ctl, status and data" { const ctl = look_up(p, Node.of(serial, .pty), "ctl"); try testing.expectEqual(Node.of(serial, .pty_ctl), ctl.reply.attr.node); - try testing.expectEqual(@as(u16, 0o222), ctl.reply.attr.mode); + try testing.expectEqual(@as(u16, 0o666), ctl.reply.attr.mode); try testing.expectEqual(@as(u16, 0o444), look_up(p, Node.of(serial, .pty), "status").reply.attr.mode); try testing.expectEqual(E.NOENT, look_up(p, Node.of(serial, .pty), "body").errno()); try testing.expectEqual(E.NOENT, look_up(p, Node.of(serial, .pty), "pty").errno()); @@ -191,7 +203,7 @@ test "a terminal pane's pty/ holds exactly ctl, status and data" { try testing.expectEqual(E.NOTDIR, look_up(p, Node.of(serial, .pty_ctl), "x").errno()); try testing.expectEqual(E.NOTDIR, rdir(p, Node.of(serial, .pty_ctl), 0).errno()); try testing.expectEqual(E.PERM, rd(p, Node.of(serial, .pty), 0, 16).errno()); - try testing.expectEqual(E.PERM, rd(p, Node.of(serial, .pty_ctl), 0, 16).errno()); + try testing.expect(std.mem.startsWith(u8, rd(p, Node.of(serial, .pty_ctl), 0, 64).bytes, "winsize ")); try testing.expectEqual(E.PERM, wr(p, Node.of(serial, .pty_status), "x").errno()); } @@ -204,6 +216,8 @@ test "every pty/ctl verb, and every refusal" { const pane = p.panes[0].?; const cols = pane.cols; const rows = pane.rows; + var said: [32]u8 = undefined; + try testing.expectEqualStrings(try std.fmt.bufPrint(&said, "winsize {d} {d}\n", .{ cols, rows }), rd(p, ctl, 0, 64).bytes); const ws = wr(p, ctl, "winsize 132 44\n"); try testing.expectEqual(@as(u32, "winsize 132 44\n".len), ws.reply.written); try testing.expectEqual(@as(u16, 132), ws.winsize.?.cols); @@ -331,7 +345,12 @@ test "pty/data writes at the shell and reads the raw stream" { try testing.expectEqual(@as(usize, 0), p.fs.panes[0].pty_out.buf.items.len); try testing.expectEqual(Status.again, rd(p, data, 0, 64).reply.status); - _ = call(p, .{ .tag = 5, .op = .open, .node = data }); + // An open that only writes is not a reader: nothing queues for it. + const writer = call(p, .{ .tag = 4, .op = .open, .node = data, .omode = 1 }); + try testing.expectEqual(@as(u16, 0), p.fs.panes[0].pty_readers); + _ = call(p, .{ .tag = 4, .op = .release, .node = data, .handle = writer.reply.handle }); + + const reader = call(p, .{ .tag = 5, .op = .open, .node = data }); try testing.expectEqual(@as(u16, 1), p.fs.panes[0].pty_readers); try testing.expectEqual(@as(u16, 0), p.fs.listeners); try testing.expect(!p.fs.scripted(0)); @@ -351,14 +370,16 @@ test "pty/data writes at the shell and reads the raw stream" { p.update(.{ .output = .{ .pane = 0, .bytes = "orphan" } }); while (p.nextEffect()) |_| {} - _ = call(p, .{ .tag = 6, .op = .release, .node = data }); + _ = call(p, .{ .tag = 6, .op = .release, .node = data, .handle = reader.reply.handle }); try testing.expectEqual(@as(u16, 0), p.fs.panes[0].pty_readers); try testing.expectEqual(@as(usize, 0), p.fs.panes[0].pty_out.buf.capacity); try testing.expectEqual(Status.again, rd(p, data, 0, 64).reply.status); + // A second reader would take half the stream from the first: refused. _ = call(p, .{ .tag = 7, .op = .open, .node = data }); - _ = call(p, .{ .tag = 8, .op = .open, .node = data }); - _ = call(p, .{ .tag = 9, .op = .release, .node = data }); + const second = call(p, .{ .tag = 8, .op = .open, .node = data, .omode = 2 }); + try testing.expectEqual(Status.err, second.reply.status); + try testing.expectEqualStrings(tree.e_in_use, second.reply.ename); try testing.expectEqual(@as(u16, 1), p.fs.panes[0].pty_readers); p.update(.{ .output = .{ .pane = 0, .bytes = "still" } }); while (p.nextEffect()) |_| {} |
