summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/9p_io.zig46
1 files changed, 46 insertions, 0 deletions
diff --git a/src/9p_io.zig b/src/9p_io.zig
index cb345b00..0b3db274 100644
--- a/src/9p_io.zig
+++ b/src/9p_io.zig
@@ -1925,10 +1925,56 @@ pub fn exportPaneEnv(listener: ?*const Listener, serial: u32, adopts: bool) void
var buf: [16]u8 = undefined;
const id = std.fmt.bufPrintSentinel(&buf, "{d}", .{serial}, 0) catch break :exporting;
if (setenv("PARDES_9P", path, 1) != 0) break :exporting;
+ exportMount(l.path());
if (setenv("PARDES_PANE", id, 1) == 0) return;
}
_ = unsetenv("PARDES_9P");
_ = unsetenv("PARDES_PANE");
+ _ = unsetenv("PARDES_MOUNT");
+}
+
+/// $PARDES_MOUNT, the session's own directory, when the environment says
+/// where it is -- never by looking at the mount, which this editor serves
+/// (the self-mount deadlock). Under `9ns --mntgen` (NINE_MNTGEN=1) it is
+/// `$NINE_MOUNT/pardes/<name>`, the name the registry gives the socket.
+/// Any other $NINE_MOUNT is a mount of another server, made before this
+/// session had a socket: unknown, so unset, and a script falls back to
+/// `9p -a "unix!$PARDES_9P"`. A Tty9p shell sets its own (linux/v9fs.zig).
+fn exportMount(sock_path: []const u8) void {
+ const mntgen = if (libc.getenv("NINE_MNTGEN")) |v| std.mem.eql(u8, std.mem.span(v), "1") else false;
+ const root = if (libc.getenv("NINE_MOUNT")) |v| std.mem.span(v) else "";
+ const base = std.fs.path.basename(sock_path);
+ const sock_prefix = "pardes-9p-";
+ const suffix = ".sock";
+ if (mntgen and root.len > 0 and std.mem.startsWith(u8, base, sock_prefix) and std.mem.endsWith(u8, base, suffix) and base.len > sock_prefix.len + suffix.len) {
+ var buf: [4096]u8 = undefined;
+ if (std.fmt.bufPrintSentinel(&buf, "{s}/pardes/{s}", .{ std.mem.trimEnd(u8, root, "/"), base[sock_prefix.len .. base.len - suffix.len] }, 0)) |mount| {
+ if (setenv("PARDES_MOUNT", mount, 1) == 0) return;
+ } else |_| {}
+ }
+ _ = unsetenv("PARDES_MOUNT");
+}
+
+test "a pane's PARDES_MOUNT is the session's directory under 9ns --mntgen, and unset when not known" {
+ const names = [_][*:0]const u8{ "NINE_MNTGEN", "NINE_MOUNT", "PARDES_MOUNT" };
+ var saved: [names.len]?[:0]u8 = @splat(null);
+ for (names, &saved) |name, *value| {
+ if (libc.getenv(name)) |old| value.* = try testing.allocator.dupeZ(u8, std.mem.span(old));
+ }
+ defer for (names, saved) |name, value| {
+ if (value) |old| {
+ _ = setenv(name, old, 1);
+ testing.allocator.free(old);
+ } else _ = unsetenv(name);
+ };
+ _ = setenv("NINE_MOUNT", "/mnt/9p", 1);
+ _ = setenv("NINE_MNTGEN", "1", 1);
+ exportMount("/run/user/1000/pardes-9p-work.sock");
+ try testing.expectEqualStrings("/mnt/9p/pardes/work", std.mem.span(libc.getenv("PARDES_MOUNT").?));
+ // A mount of another server (9ns --unix): not this session's.
+ _ = unsetenv("NINE_MNTGEN");
+ exportMount("/run/user/1000/pardes-9p-work.sock");
+ try testing.expect(libc.getenv("PARDES_MOUNT") == null);
}
test "9P shell environment states being inside pardes apart from how to reach it" {