summaryrefslogtreecommitdiff
path: root/src/builtins.zig
diff options
context:
space:
mode:
authorGabriel Schneider <[email protected]>2026-09-30 21:25:52 -0300
committerGabriel Schneider <[email protected]>2026-10-01 00:12:17 -0300
commit237071bd4865f0220c35c8c37895c8dba48aed84 (patch)
treef9bc231af7e51f2d8b06225a63c095f5b9b6f0cf /src/builtins.zig
parent137dc2ea4be0fc5baf4cab1d8a757ce426e5cbb2 (diff)
downloadpardes-237071bd4865f0220c35c8c37895c8dba48aed84.tar.gz
pardes-237071bd4865f0220c35c8c37895c8dba48aed84.zip
Attach in a detached session is refused with words: bare is wrong #args, a name no session has is "no such session"
A detached session's core has no frontend loop to take an Attach, so the word was asked and never answered: a ctl write of it succeeded and nothing happened. The core now knows it is a detached session's, and Attach there says why: bare names no session but itself, a name with no session behind it is said so, and one that is a session is told to be attached from a frontend. Co-Authored-By: Claude Opus 5.5 <[email protected]>
Diffstat (limited to 'src/builtins.zig')
-rw-r--r--src/builtins.zig22
1 files changed, 21 insertions, 1 deletions
diff --git a/src/builtins.zig b/src/builtins.zig
index cb588ba3..bc9bb075 100644
--- a/src/builtins.zig
+++ b/src/builtins.zig
@@ -742,9 +742,29 @@ pub const Attach = struct {
if (comptime enabled) ask(c) else unreachable;
}
fn ask(c: Ctx) void {
- const name = c.arg orelse "";
+ const name = std.mem.trim(u8, c.arg orelse "", " \t\r\n");
if (name.len > pardes.attach_name_max)
return c.p.reportError(c.id, comptime word(@This()), error.NameTooLong);
+ // A detached session has no terminal to move: bare, there is no
+ // "the one session there" but itself; a name is said for what it is.
+ if (c.p.opts.detached_session) {
+ if (name.len == 0) return c.p.reportFailure(c.id, "wrong #args in control message \"Attach\": a detached session names the session");
+ // A session is its socket, `pardes-detached-<name>.sock` beside
+ // the 9P ones (detached/server.zig socketPath); not imported, as
+ // the core links no frontend's code.
+ const ninep_io = @import("9p_io.zig");
+ var dir_buf: [ninep_io.sun_path_len:0]u8 = undefined;
+ var path_buf: [ninep_io.sun_path_len + 64:0]u8 = undefined;
+ const exists = if (ninep_io.socketDir(&dir_buf)) |dir|
+ (if (std.fmt.bufPrintSentinel(&path_buf, "{s}/pardes-detached-{s}.sock", .{ dir, name }, 0)) |path| ninep_io.statNoFollow(path) != null else |_| false)
+ else
+ false;
+ var said: [pardes.attach_name_max + 96]u8 = undefined;
+ return c.p.reportFailure(c.id, if (exists)
+ std.fmt.bufPrint(&said, "Attach: {s}: a detached session has no terminal to attach; Attach from a frontend", .{name}) catch "Attach: a detached session has no terminal to attach"
+ else
+ std.fmt.bufPrint(&said, "Attach: {s}: no such session", .{name}) catch "Attach: no such session");
+ }
c.p.emit(.{ .attach = .{ .pane = @intCast(c.id), .name = .from(name) } });
}
};