Commit 9e5eb55
Eric Bower
·
2026-07-26 14:13:24 -0400 EDT
parent 4232d74
refactor: use posix.zig for all posix fns The zig team is planning to completely kill std.posix so we might as well get ahead of it and bring everything we need into zmx.
6 files changed,
+251,
-113
+0,
-1
| ... | ... | @@ -1,6 +1,5 @@ | |
| 1 | 1 | const builtin = @import("builtin"); | |
| 2 | 2 | const std = @import("std"); | |
| 3 | - | const posix = std.posix; | |
| 4 | 3 | ||
| 5 | 4 | pub const c = switch (builtin.os.tag) { | |
| 6 | 5 | .macos => @cImport({ |
+6,
-7
| ... | ... | @@ -1,5 +1,4 @@ | |
| 1 | 1 | const std = @import("std"); | |
| 2 | - | const posix = std.posix; | |
| 3 | 2 | const cross = @import("cross.zig"); | |
| 4 | 3 | const socket = @import("socket.zig"); | |
| 5 | 4 | const lib_posix = @import("posix.zig"); |
| ... | ... | @@ -172,7 +171,7 @@ pub const SocketBuffer = struct { | |
| 172 | 171 | } | |
| 173 | 172 | ||
| 174 | 173 | var tmp: [4096]u8 = undefined; | |
| 175 | - | const n = try posix.read(fd, &tmp); | |
| 174 | + | const n = try lib_posix.read(fd, &tmp); | |
| 176 | 175 | if (n > 0) { | |
| 177 | 176 | try self.buf.appendSlice(self.alloc, tmp[0..n]); | |
| 178 | 177 | } |
| ... | ... | @@ -239,8 +238,8 @@ pub fn probeSession( | |
| 239 | 238 | send(fd, .Info, "") catch return error.Unexpected; | |
| 240 | 239 | send(fd, .LabelGet, "") catch {}; | |
| 241 | 240 | ||
| 242 | - | var poll_fds = [_]posix.pollfd{.{ .fd = fd, .events = posix.POLL.IN, .revents = 0 }}; | |
| 243 | - | const poll_result = posix.poll(&poll_fds, timeout_ms) catch return error.Unexpected; | |
| 241 | + | var poll_fds = [_]lib_posix.pollfd{.{ .fd = fd, .events = lib_posix.POLL.IN, .revents = 0 }}; | |
| 242 | + | const poll_result = lib_posix.poll(&poll_fds, timeout_ms) catch return error.Unexpected; | |
| 244 | 243 | if (poll_result == 0) { | |
| 245 | 244 | return error.Timeout; | |
| 246 | 245 | } |
| ... | ... | @@ -270,7 +269,7 @@ pub fn probeSession( | |
| 270 | 269 | } | |
| 271 | 270 | ||
| 272 | 271 | // No complete message available, wait for more data | |
| 273 | - | const more = posix.poll(&poll_fds, 50) catch break; | |
| 272 | + | const more = lib_posix.poll(&poll_fds, 50) catch break; | |
| 274 | 273 | if (more == 0) break; | |
| 275 | 274 | const n_read = sb.read(fd) catch break; | |
| 276 | 275 | if (n_read == 0) break; |
| ... | ... | @@ -325,8 +324,8 @@ pub fn roundTripForTag( | |
| 325 | 324 | ||
| 326 | 325 | send(fd, request_tag, payload) catch return error.Unexpected; | |
| 327 | 326 | ||
| 328 | - | var poll_fds = [_]posix.pollfd{.{ .fd = fd, .events = posix.POLL.IN, .revents = 0 }}; | |
| 329 | - | const poll_result = posix.poll(&poll_fds, timeout_ms) catch return error.Unexpected; | |
| 327 | + | var poll_fds = [_]lib_posix.pollfd{.{ .fd = fd, .events = lib_posix.POLL.IN, .revents = 0 }}; | |
| 328 | + | const poll_result = lib_posix.poll(&poll_fds, timeout_ms) catch return error.Unexpected; | |
| 330 | 329 | if (poll_result == 0) return error.Timeout; | |
| 331 | 330 | ||
| 332 | 331 | var sb = SocketBuffer.init(alloc) catch return error.Unexpected; |
+89,
-90
| ... | ... | @@ -1,5 +1,4 @@ | |
| 1 | 1 | const std = @import("std"); | |
| 2 | - | const posix = std.posix; | |
| 3 | 2 | const build_options = @import("build_options"); | |
| 4 | 3 | const ghostty_vt = @import("ghostty-vt"); | |
| 5 | 4 | const ipc = @import("ipc.zig"); |
| ... | ... | @@ -33,10 +32,10 @@ fn zmxLogFn( | |
| 33 | 32 | /// Self-pipe woken by signal handlers. std.posix.poll loops on .INTR internally | |
| 34 | 33 | /// (PollError has no Interrupted member), so a signal that lands during poll() | |
| 35 | 34 | /// never surfaces; the handler writes a byte here and poll() wakes on POLLIN. | |
| 36 | - | var sig_pipe: [2]posix.fd_t = .{ -1, -1 }; | |
| 35 | + | var sig_pipe: [2]lib_posix.fd_t = .{ -1, -1 }; | |
| 37 | 36 | ||
| 38 | 37 | // https://github.com/ziglang/zig/blob/738d2be9d6b6ef3ff3559130c05159ef53336224/lib/std/posix.zig#L3505 | |
| 39 | - | const O_NONBLOCK: usize = 1 << @bitOffsetOf(posix.O, "NONBLOCK"); | |
| 38 | + | const O_NONBLOCK: usize = 1 << @bitOffsetOf(lib_posix.O, "NONBLOCK"); | |
| 40 | 39 | ||
| 41 | 40 | const SessionMatch = struct { | |
| 42 | 41 | name: []const u8, |
| ... | ... | @@ -83,7 +82,7 @@ fn openSignalPipe() !void { | |
| 83 | 82 | fn drainSignalPipe() void { | |
| 84 | 83 | var b: [16]u8 = undefined; | |
| 85 | 84 | while (true) { | |
| 86 | - | const n = posix.read(sig_pipe[0], &b) catch return; | |
| 85 | + | const n = lib_posix.read(sig_pipe[0], &b) catch return; | |
| 87 | 86 | if (n == 0) return; | |
| 88 | 87 | } | |
| 89 | 88 | } |
| ... | ... | @@ -805,12 +804,12 @@ const Daemon = struct { | |
| 805 | 804 | // main() set SIGPIPE to SIG_IGN, which (unlike handlers) survives | |
| 806 | 805 | // exec. Restore the default so the shell and its children behave | |
| 807 | 806 | // normally (e.g. `yes | head` should exit 141 via SIGPIPE). | |
| 808 | - | const dfl: posix.Sigaction = .{ | |
| 809 | - | .handler = .{ .handler = posix.SIG.DFL }, | |
| 810 | - | .mask = posix.sigemptyset(), | |
| 807 | + | const dfl: lib_posix.Sigaction = .{ | |
| 808 | + | .handler = .{ .handler = lib_posix.SIG.DFL }, | |
| 809 | + | .mask = lib_posix.sigemptyset(), | |
| 811 | 810 | .flags = 0, | |
| 812 | 811 | }; | |
| 813 | - | posix.sigaction(posix.SIG.PIPE, &dfl, null); | |
| 812 | + | lib_posix.sigaction(lib_posix.SIG.PIPE, &dfl, null); | |
| 814 | 813 | ||
| 815 | 814 | const session_env = try std.fmt.allocPrintSentinel( | |
| 816 | 815 | alloc, |
| ... | ... | @@ -848,7 +847,7 @@ const Daemon = struct { | |
| 848 | 847 | ||
| 849 | 848 | /// spawnPty runs forkpty() and executes the shell or shell command the user provides. | |
| 850 | 849 | fn spawnPty(self: *Daemon) !c_int { | |
| 851 | - | const size = ipc.getTerminalSize(posix.STDOUT_FILENO); | |
| 850 | + | const size = ipc.getTerminalSize(lib_posix.STDOUT_FILENO); | |
| 852 | 851 | var ws: cross.c.struct_winsize = .{ | |
| 853 | 852 | .ws_row = size.rows, | |
| 854 | 853 | .ws_col = size.cols, |
| ... | ... | @@ -878,8 +877,8 @@ const Daemon = struct { | |
| 878 | 877 | std.log.info("pty spawned session={s} pid={d}", .{ self.session_name, pid }); | |
| 879 | 878 | ||
| 880 | 879 | // make pty non-blocking | |
| 881 | - | const flags = try lib_posix.fcntl(master_fd, posix.F.GETFL, 0); | |
| 882 | - | _ = try lib_posix.fcntl(master_fd, posix.F.SETFL, flags | O_NONBLOCK); | |
| 880 | + | const flags = try lib_posix.fcntl(master_fd, lib_posix.F.GETFL, 0); | |
| 881 | + | _ = try lib_posix.fcntl(master_fd, lib_posix.F.SETFL, flags | O_NONBLOCK); | |
| 883 | 882 | return master_fd; | |
| 884 | 883 | } | |
| 885 | 884 |
| ... | ... | @@ -946,7 +945,7 @@ const Daemon = struct { | |
| 946 | 945 | std.log.warn("failed to open /dev/null: {s}", .{@errorName(err)}); | |
| 947 | 946 | return err; | |
| 948 | 947 | }; | |
| 949 | - | inline for (.{ posix.STDIN_FILENO, posix.STDOUT_FILENO, posix.STDERR_FILENO }) |fd| { | |
| 948 | + | inline for (.{ lib_posix.STDIN_FILENO, lib_posix.STDOUT_FILENO, lib_posix.STDERR_FILENO }) |fd| { | |
| 950 | 949 | _ = lib_posix.dup2(devnull, fd) catch |err| { | |
| 951 | 950 | std.log.warn("dup2 /dev/null -> {d}: {s}", .{ fd, @errorName(err) }); | |
| 952 | 951 | return err; |
| ... | ... | @@ -1221,11 +1220,11 @@ const Daemon = struct { | |
| 1221 | 1220 | // https://www.gnu.org/software/bash/manual/html_node/Signals.html | |
| 1222 | 1221 | // negative pid means kill process and children | |
| 1223 | 1222 | std.log.info("sending SIGHUP session={s} pid={d}", .{ self.session_name, self.pid }); | |
| 1224 | - | posix.kill(-self.pid, posix.SIG.HUP) catch |err| { | |
| 1223 | + | lib_posix.kill(-self.pid, lib_posix.SIG.HUP) catch |err| { | |
| 1225 | 1224 | std.log.warn("failed to send SIGHUP to pty child err={s}", .{@errorName(err)}); | |
| 1226 | 1225 | }; | |
| 1227 | 1226 | std.Io.sleep(self.io, std.Io.Duration.fromMilliseconds(500), .real) catch unreachable; | |
| 1228 | - | posix.kill(-self.pid, posix.SIG.KILL) catch |err| { | |
| 1227 | + | lib_posix.kill(-self.pid, lib_posix.SIG.KILL) catch |err| { | |
| 1229 | 1228 | std.log.warn("failed to send SIGKILL to pty child err={s}", .{@errorName(err)}); | |
| 1230 | 1229 | }; | |
| 1231 | 1230 | } |
| ... | ... | @@ -1339,7 +1338,7 @@ const Daemon = struct { | |
| 1339 | 1338 | client.has_pending_output = true; | |
| 1340 | 1339 | } | |
| 1341 | 1340 | if (self.clients.items.len > 0) { | |
| 1342 | - | posix.kill(self.pid, posix.SIG.WINCH) catch |err| { | |
| 1341 | + | lib_posix.kill(self.pid, lib_posix.SIG.WINCH) catch |err| { | |
| 1343 | 1342 | std.log.warn("failed to send SIGWINCH err={s}", .{@errorName(err)}); | |
| 1344 | 1343 | }; | |
| 1345 | 1344 | } |
| ... | ... | @@ -1580,7 +1579,7 @@ fn help(io: std.Io) !void { | |
| 1580 | 1579 | } | |
| 1581 | 1580 | ||
| 1582 | 1581 | fn tail(alloc: std.mem.Allocator, client_socket_fds: std.ArrayList(i32), detached: bool, is_run_cmd: bool) !u8 { | |
| 1583 | - | var poll_fds = try std.ArrayList(posix.pollfd).initCapacity(alloc, 4); | |
| 1582 | + | var poll_fds = try std.ArrayList(lib_posix.pollfd).initCapacity(alloc, 4); | |
| 1584 | 1583 | defer poll_fds.deinit(alloc); | |
| 1585 | 1584 | ||
| 1586 | 1585 | var read_buf = try ipc.SocketBuffer.init(alloc); |
| ... | ... | @@ -1599,7 +1598,7 @@ fn tail(alloc: std.mem.Allocator, client_socket_fds: std.ArrayList(i32), detache | |
| 1599 | 1598 | for (client_socket_fds.items) |client_sock_fd| { | |
| 1600 | 1599 | try poll_fds.append(alloc, .{ | |
| 1601 | 1600 | .fd = client_sock_fd, | |
| 1602 | - | .events = posix.POLL.IN, | |
| 1601 | + | .events = lib_posix.POLL.IN, | |
| 1603 | 1602 | .revents = 0, | |
| 1604 | 1603 | }); | |
| 1605 | 1604 | } |
| ... | ... | @@ -1607,20 +1606,20 @@ fn tail(alloc: std.mem.Allocator, client_socket_fds: std.ArrayList(i32), detache | |
| 1607 | 1606 | // Poll for write if we have pending data | |
| 1608 | 1607 | if (stdout_buf.items.len > 0) { | |
| 1609 | 1608 | try poll_fds.append(alloc, .{ | |
| 1610 | - | .fd = posix.STDOUT_FILENO, | |
| 1611 | - | .events = posix.POLL.OUT, | |
| 1609 | + | .fd = lib_posix.STDOUT_FILENO, | |
| 1610 | + | .events = lib_posix.POLL.OUT, | |
| 1612 | 1611 | .revents = 0, | |
| 1613 | 1612 | }); | |
| 1614 | 1613 | } | |
| 1615 | 1614 | ||
| 1616 | - | _ = posix.poll(poll_fds.items, -1) catch |err| { | |
| 1615 | + | _ = lib_posix.poll(poll_fds.items, -1) catch |err| { | |
| 1617 | 1616 | if (err == error.Interrupted) continue; // EINTR from signal, loop again | |
| 1618 | 1617 | return err; | |
| 1619 | 1618 | }; | |
| 1620 | 1619 | ||
| 1621 | 1620 | // Handle socket read (incoming Output messages from daemon) | |
| 1622 | 1621 | for (poll_fds.items) |*poll_fd| { | |
| 1623 | - | if (poll_fd.revents & posix.POLL.IN != 0) { | |
| 1622 | + | if (poll_fd.revents & lib_posix.POLL.IN != 0) { | |
| 1624 | 1623 | const n = read_buf.read(poll_fd.fd) catch |err| { | |
| 1625 | 1624 | if (err == error.WouldBlock) continue; | |
| 1626 | 1625 | if (err == error.ConnectionResetByPeer or err == error.BrokenPipe) { |
| ... | ... | @@ -1642,7 +1641,7 @@ fn tail(alloc: std.mem.Allocator, client_socket_fds: std.ArrayList(i32), detache | |
| 1642 | 1641 | switch (msg.header.tag) { | |
| 1643 | 1642 | .Ack => { | |
| 1644 | 1643 | if (detached) { | |
| 1645 | - | _ = lib_posix.write(posix.STDOUT_FILENO, "command sent!\n") catch |err| blk: { | |
| 1644 | + | _ = lib_posix.write(lib_posix.STDOUT_FILENO, "command sent!\n") catch |err| blk: { | |
| 1646 | 1645 | if (err == error.WouldBlock) break :blk 0; | |
| 1647 | 1646 | return err; | |
| 1648 | 1647 | }; |
| ... | ... | @@ -1704,7 +1703,7 @@ fn tail(alloc: std.mem.Allocator, client_socket_fds: std.ArrayList(i32), detache | |
| 1704 | 1703 | if (task_complete_code) |exit_code| { | |
| 1705 | 1704 | // Flush any remaining output before returning | |
| 1706 | 1705 | flush_loop: while (stdout_buf.items.len > 0) { | |
| 1707 | - | const n = lib_posix.write(posix.STDOUT_FILENO, stdout_buf.items) catch |err| { | |
| 1706 | + | const n = lib_posix.write(lib_posix.STDOUT_FILENO, stdout_buf.items) catch |err| { | |
| 1708 | 1707 | if (err == error.WouldBlock) break :flush_loop; | |
| 1709 | 1708 | return err; | |
| 1710 | 1709 | }; |
| ... | ... | @@ -1714,7 +1713,7 @@ fn tail(alloc: std.mem.Allocator, client_socket_fds: std.ArrayList(i32), detache | |
| 1714 | 1713 | } | |
| 1715 | 1714 | ||
| 1716 | 1715 | if (stdout_buf.items.len > 0) { | |
| 1717 | - | const n = lib_posix.write(posix.STDOUT_FILENO, stdout_buf.items) catch |err| blk: { | |
| 1716 | + | const n = lib_posix.write(lib_posix.STDOUT_FILENO, stdout_buf.items) catch |err| blk: { | |
| 1718 | 1717 | if (err == error.WouldBlock) break :blk 0; | |
| 1719 | 1718 | return err; | |
| 1720 | 1719 | }; |
| ... | ... | @@ -1725,7 +1724,7 @@ fn tail(alloc: std.mem.Allocator, client_socket_fds: std.ArrayList(i32), detache | |
| 1725 | 1724 | ||
| 1726 | 1725 | // Check for HUP/ERR on any socket | |
| 1727 | 1726 | for (poll_fds.items) |poll_fd| { | |
| 1728 | - | if (poll_fd.revents & (posix.POLL.HUP | posix.POLL.ERR | posix.POLL.NVAL) != 0) { | |
| 1727 | + | if (poll_fd.revents & (lib_posix.POLL.HUP | lib_posix.POLL.ERR | lib_posix.POLL.NVAL) != 0) { | |
| 1729 | 1728 | return 0; | |
| 1730 | 1729 | } | |
| 1731 | 1730 | } |
| ... | ... | @@ -2022,7 +2021,7 @@ fn kill(alloc: std.mem.Allocator, io: std.Io, cfg: *Cfg, session_name: []const u | |
| 2022 | 2021 | // accept backlog. | |
| 2023 | 2022 | var drain: [256]u8 = undefined; | |
| 2024 | 2023 | while (true) { | |
| 2025 | - | const n = posix.read(fd, &drain) catch break; | |
| 2024 | + | const n = lib_posix.read(fd, &drain) catch break; | |
| 2026 | 2025 | if (n == 0) break; | |
| 2027 | 2026 | } | |
| 2028 | 2027 |
| ... | ... | @@ -2179,8 +2178,8 @@ fn fetchHistory( | |
| 2179 | 2178 | errdefer result.deinit(alloc); | |
| 2180 | 2179 | ||
| 2181 | 2180 | while (true) { | |
| 2182 | - | var poll_fds = [_]posix.pollfd{.{ .fd = fd, .events = posix.POLL.IN, .revents = 0 }}; | |
| 2183 | - | const poll_result = posix.poll(&poll_fds, 5000) catch return error.Timeout; | |
| 2181 | + | var poll_fds = [_]lib_posix.pollfd{.{ .fd = fd, .events = lib_posix.POLL.IN, .revents = 0 }}; | |
| 2182 | + | const poll_result = lib_posix.poll(&poll_fds, 5000) catch return error.Timeout; | |
| 2184 | 2183 | if (poll_result == 0) { | |
| 2185 | 2184 | return error.Timeout; | |
| 2186 | 2185 | } |
| ... | ... | @@ -2236,8 +2235,8 @@ fn history(alloc: std.mem.Allocator, io: std.Io, cfg: *Cfg, session_name: []cons | |
| 2236 | 2235 | defer sb.deinit(); | |
| 2237 | 2236 | ||
| 2238 | 2237 | while (true) { | |
| 2239 | - | var poll_fds = [_]posix.pollfd{.{ .fd = fd, .events = posix.POLL.IN, .revents = 0 }}; | |
| 2240 | - | const poll_result = posix.poll(&poll_fds, 5000) catch return; | |
| 2238 | + | var poll_fds = [_]lib_posix.pollfd{.{ .fd = fd, .events = lib_posix.POLL.IN, .revents = 0 }}; | |
| 2239 | + | const poll_result = lib_posix.poll(&poll_fds, 5000) catch return; | |
| 2241 | 2240 | if (poll_result == 0) { | |
| 2242 | 2241 | std.log.err("timeout waiting for history response", .{}); | |
| 2243 | 2242 | return; |
| ... | ... | @@ -2248,7 +2247,7 @@ fn history(alloc: std.mem.Allocator, io: std.Io, cfg: *Cfg, session_name: []cons | |
| 2248 | 2247 | ||
| 2249 | 2248 | while (sb.next()) |msg| { | |
| 2250 | 2249 | if (msg.header.tag == .History) { | |
| 2251 | - | _ = lib_posix.write(posix.STDOUT_FILENO, msg.payload) catch return; | |
| 2250 | + | _ = lib_posix.write(lib_posix.STDOUT_FILENO, msg.payload) catch return; | |
| 2252 | 2251 | return; | |
| 2253 | 2252 | } | |
| 2254 | 2253 | } |
| ... | ... | @@ -2314,15 +2313,15 @@ fn attach(daemon: *Daemon) !void { | |
| 2314 | 2313 | // skip terminal setup entirely rather than applying undefined stack bytes | |
| 2315 | 2314 | // via tcsetattr. | |
| 2316 | 2315 | var orig_termios: cross.c.termios = undefined; | |
| 2317 | - | const stdin_is_tty = cross.c.tcgetattr(posix.STDIN_FILENO, &orig_termios) == 0; | |
| 2316 | + | const stdin_is_tty = cross.c.tcgetattr(lib_posix.STDIN_FILENO, &orig_termios) == 0; | |
| 2318 | 2317 | ||
| 2319 | 2318 | defer { | |
| 2320 | 2319 | if (stdin_is_tty) { | |
| 2321 | - | _ = cross.c.tcsetattr(posix.STDIN_FILENO, cross.c.TCSAFLUSH, &orig_termios); | |
| 2320 | + | _ = cross.c.tcsetattr(lib_posix.STDIN_FILENO, cross.c.TCSAFLUSH, &orig_termios); | |
| 2322 | 2321 | } | |
| 2323 | 2322 | // Reset terminal modes on detach | |
| 2324 | 2323 | const restore_seq = "\x1bc"; | |
| 2325 | - | _ = lib_posix.write(posix.STDOUT_FILENO, restore_seq) catch {}; | |
| 2324 | + | _ = lib_posix.write(lib_posix.STDOUT_FILENO, restore_seq) catch {}; | |
| 2326 | 2325 | } | |
| 2327 | 2326 | ||
| 2328 | 2327 | if (stdin_is_tty) { |
| ... | ... | @@ -2340,13 +2339,13 @@ fn attach(daemon: *Daemon) !void { | |
| 2340 | 2339 | raw_termios.c_cc[cross.c.VMIN] = 1; // Minimum chars to read: return after 1 byte | |
| 2341 | 2340 | raw_termios.c_cc[cross.c.VTIME] = 0; // Read timeout: no timeout, return immediately | |
| 2342 | 2341 | ||
| 2343 | - | _ = cross.c.tcsetattr(posix.STDIN_FILENO, cross.c.TCSANOW, &raw_termios); | |
| 2342 | + | _ = cross.c.tcsetattr(lib_posix.STDIN_FILENO, cross.c.TCSANOW, &raw_termios); | |
| 2344 | 2343 | } | |
| 2345 | 2344 | ||
| 2346 | 2345 | // Clear screen before attaching. This provides a clean slate before | |
| 2347 | 2346 | // the session restore. | |
| 2348 | 2347 | const clear_seq = "\x1b[2J\x1b[H"; | |
| 2349 | - | _ = try lib_posix.write(posix.STDOUT_FILENO, clear_seq); | |
| 2348 | + | _ = try lib_posix.write(lib_posix.STDOUT_FILENO, clear_seq); | |
| 2350 | 2349 | ||
| 2351 | 2350 | const looper = try clientLoop(client_sock); | |
| 2352 | 2351 | switch (looper.kind) { |
| ... | ... | @@ -2399,13 +2398,13 @@ fn writeFile(daemon: *Daemon, file_path: []const u8) !void { | |
| 2399 | 2398 | try w.interface.print("session \"{s}\" created\n", .{daemon.session_name}); | |
| 2400 | 2399 | try w.interface.flush(); | |
| 2401 | 2400 | } | |
| 2402 | - | const stdin_fd = posix.STDIN_FILENO; | |
| 2401 | + | const stdin_fd = lib_posix.STDIN_FILENO; | |
| 2403 | 2402 | var stdin_buf = try std.ArrayList(u8).initCapacity(daemon.alloc, 4096); | |
| 2404 | 2403 | defer stdin_buf.deinit(daemon.alloc); | |
| 2405 | 2404 | ||
| 2406 | 2405 | while (true) { | |
| 2407 | 2406 | var tmp: [4096]u8 = undefined; | |
| 2408 | - | const n = posix.read(stdin_fd, &tmp) catch |err| { | |
| 2407 | + | const n = lib_posix.read(stdin_fd, &tmp) catch |err| { | |
| 2409 | 2408 | if (err == error.WouldBlock) break; | |
| 2410 | 2409 | return err; | |
| 2411 | 2410 | }; |
| ... | ... | @@ -2680,22 +2679,22 @@ fn clientLoop(client_sock_fd: i32) !ClientResult { | |
| 2680 | 2679 | defer lib_posix.close(client_sock_fd); | |
| 2681 | 2680 | ||
| 2682 | 2681 | try openSignalPipe(); | |
| 2683 | - | installWakeHandler(@intFromEnum(posix.SIG.WINCH)); | |
| 2682 | + | installWakeHandler(@intFromEnum(lib_posix.SIG.WINCH)); | |
| 2684 | 2683 | ||
| 2685 | 2684 | // Make socket non-blocking to avoid blocking on writes | |
| 2686 | - | var sock_flags = try lib_posix.fcntl(client_sock_fd, posix.F.GETFL, 0); | |
| 2685 | + | var sock_flags = try lib_posix.fcntl(client_sock_fd, lib_posix.F.GETFL, 0); | |
| 2687 | 2686 | sock_flags |= O_NONBLOCK; | |
| 2688 | - | _ = try lib_posix.fcntl(client_sock_fd, posix.F.SETFL, sock_flags); | |
| 2687 | + | _ = try lib_posix.fcntl(client_sock_fd, lib_posix.F.SETFL, sock_flags); | |
| 2689 | 2688 | ||
| 2690 | 2689 | // Buffer for outgoing socket writes | |
| 2691 | 2690 | var sock_write_buf = try std.ArrayList(u8).initCapacity(alloc, 4096); | |
| 2692 | 2691 | defer sock_write_buf.deinit(alloc); | |
| 2693 | 2692 | ||
| 2694 | 2693 | // Send init message with terminal size (buffered) | |
| 2695 | - | const size = ipc.getTerminalSize(posix.STDOUT_FILENO); | |
| 2694 | + | const size = ipc.getTerminalSize(lib_posix.STDOUT_FILENO); | |
| 2696 | 2695 | try ipc.appendMessage(alloc, &sock_write_buf, .Init, std.mem.asBytes(&size)); | |
| 2697 | 2696 | ||
| 2698 | - | var poll_fds = try std.ArrayList(posix.pollfd).initCapacity(alloc, 4); | |
| 2697 | + | var poll_fds = try std.ArrayList(lib_posix.pollfd).initCapacity(alloc, 4); | |
| 2699 | 2698 | defer poll_fds.deinit(alloc); | |
| 2700 | 2699 | ||
| 2701 | 2700 | var read_buf = try ipc.SocketBuffer.init(alloc); |
| ... | ... | @@ -2704,28 +2703,28 @@ fn clientLoop(client_sock_fd: i32) !ClientResult { | |
| 2704 | 2703 | var stdout_buf = try std.ArrayList(u8).initCapacity(alloc, 4096); | |
| 2705 | 2704 | defer stdout_buf.deinit(alloc); | |
| 2706 | 2705 | ||
| 2707 | - | const stdin_fd = posix.STDIN_FILENO; | |
| 2706 | + | const stdin_fd = lib_posix.STDIN_FILENO; | |
| 2708 | 2707 | ||
| 2709 | 2708 | // Make stdin non-blocking. O_NONBLOCK is set on the open file description, | |
| 2710 | 2709 | // which is shared with the parent shell; restore on exit to avoid | |
| 2711 | 2710 | // corrupting the parent's stdin. | |
| 2712 | - | const stdin_orig_flags = try lib_posix.fcntl(stdin_fd, posix.F.GETFL, 0); | |
| 2713 | - | _ = try lib_posix.fcntl(stdin_fd, posix.F.SETFL, stdin_orig_flags | O_NONBLOCK); | |
| 2714 | - | defer _ = lib_posix.fcntl(stdin_fd, posix.F.SETFL, stdin_orig_flags) catch {}; | |
| 2711 | + | const stdin_orig_flags = try lib_posix.fcntl(stdin_fd, lib_posix.F.GETFL, 0); | |
| 2712 | + | _ = try lib_posix.fcntl(stdin_fd, lib_posix.F.SETFL, stdin_orig_flags | O_NONBLOCK); | |
| 2713 | + | defer _ = lib_posix.fcntl(stdin_fd, lib_posix.F.SETFL, stdin_orig_flags) catch {}; | |
| 2715 | 2714 | ||
| 2716 | 2715 | while (true) { | |
| 2717 | 2716 | poll_fds.clearRetainingCapacity(); | |
| 2718 | 2717 | ||
| 2719 | 2718 | try poll_fds.append(alloc, .{ | |
| 2720 | 2719 | .fd = stdin_fd, | |
| 2721 | - | .events = posix.POLL.IN, | |
| 2720 | + | .events = lib_posix.POLL.IN, | |
| 2722 | 2721 | .revents = 0, | |
| 2723 | 2722 | }); | |
| 2724 | 2723 | ||
| 2725 | 2724 | // Poll socket for read, and also for write if we have pending data | |
| 2726 | - | var sock_events: i16 = posix.POLL.IN; | |
| 2725 | + | var sock_events: i16 = lib_posix.POLL.IN; | |
| 2727 | 2726 | if (sock_write_buf.items.len > 0) { | |
| 2728 | - | sock_events |= posix.POLL.OUT; | |
| 2727 | + | sock_events |= lib_posix.POLL.OUT; | |
| 2729 | 2728 | } | |
| 2730 | 2729 | try poll_fds.append(alloc, .{ | |
| 2731 | 2730 | .fd = client_sock_fd, |
| ... | ... | @@ -2733,29 +2732,29 @@ fn clientLoop(client_sock_fd: i32) !ClientResult { | |
| 2733 | 2732 | .revents = 0, | |
| 2734 | 2733 | }); | |
| 2735 | 2734 | ||
| 2736 | - | try poll_fds.append(alloc, .{ .fd = sig_pipe[0], .events = posix.POLL.IN, .revents = 0 }); | |
| 2735 | + | try poll_fds.append(alloc, .{ .fd = sig_pipe[0], .events = lib_posix.POLL.IN, .revents = 0 }); | |
| 2737 | 2736 | ||
| 2738 | 2737 | if (stdout_buf.items.len > 0) { | |
| 2739 | 2738 | try poll_fds.append(alloc, .{ | |
| 2740 | - | .fd = posix.STDOUT_FILENO, | |
| 2741 | - | .events = posix.POLL.OUT, | |
| 2739 | + | .fd = lib_posix.STDOUT_FILENO, | |
| 2740 | + | .events = lib_posix.POLL.OUT, | |
| 2742 | 2741 | .revents = 0, | |
| 2743 | 2742 | }); | |
| 2744 | 2743 | } | |
| 2745 | 2744 | ||
| 2746 | - | _ = try posix.poll(poll_fds.items, -1); | |
| 2745 | + | _ = try lib_posix.poll(poll_fds.items, -1); | |
| 2747 | 2746 | ||
| 2748 | - | if (poll_fds.items[2].revents & posix.POLL.IN != 0) { | |
| 2747 | + | if (poll_fds.items[2].revents & lib_posix.POLL.IN != 0) { | |
| 2749 | 2748 | drainSignalPipe(); | |
| 2750 | - | const next_size = ipc.getTerminalSize(posix.STDOUT_FILENO); | |
| 2749 | + | const next_size = ipc.getTerminalSize(lib_posix.STDOUT_FILENO); | |
| 2751 | 2750 | try ipc.appendMessage(alloc, &sock_write_buf, .Resize, std.mem.asBytes(&next_size)); | |
| 2752 | 2751 | } | |
| 2753 | 2752 | ||
| 2754 | 2753 | // Handle stdin -> socket (Input) | |
| 2755 | - | const inp_flags = (posix.POLL.IN | posix.POLL.HUP | posix.POLL.ERR | posix.POLL.NVAL); | |
| 2754 | + | const inp_flags = (lib_posix.POLL.IN | lib_posix.POLL.HUP | lib_posix.POLL.ERR | lib_posix.POLL.NVAL); | |
| 2756 | 2755 | if (poll_fds.items[0].revents & inp_flags != 0) { | |
| 2757 | 2756 | var buf: [4096]u8 = undefined; | |
| 2758 | - | const n_opt: ?usize = posix.read(stdin_fd, &buf) catch |err| blk: { | |
| 2757 | + | const n_opt: ?usize = lib_posix.read(stdin_fd, &buf) catch |err| blk: { | |
| 2759 | 2758 | if (err == error.WouldBlock) break :blk null; | |
| 2760 | 2759 | return err; | |
| 2761 | 2760 | }; |
| ... | ... | @@ -2778,7 +2777,7 @@ fn clientLoop(client_sock_fd: i32) !ClientResult { | |
| 2778 | 2777 | } | |
| 2779 | 2778 | ||
| 2780 | 2779 | // Handle socket read (incoming Output messages from daemon) | |
| 2781 | - | if (poll_fds.items[1].revents & posix.POLL.IN != 0) { | |
| 2780 | + | if (poll_fds.items[1].revents & lib_posix.POLL.IN != 0) { | |
| 2782 | 2781 | const n = read_buf.read(client_sock_fd) catch |err| { | |
| 2783 | 2782 | if (err == error.WouldBlock) continue; | |
| 2784 | 2783 | if (err == error.ConnectionResetByPeer or err == error.BrokenPipe) { |
| ... | ... | @@ -2803,7 +2802,7 @@ fn clientLoop(client_sock_fd: i32) !ClientResult { | |
| 2803 | 2802 | .Resize => { | |
| 2804 | 2803 | // daemon is asking for the client's window size usually in response | |
| 2805 | 2804 | // to this client being set as leader. | |
| 2806 | - | const next_size = ipc.getTerminalSize(posix.STDOUT_FILENO); | |
| 2805 | + | const next_size = ipc.getTerminalSize(lib_posix.STDOUT_FILENO); | |
| 2807 | 2806 | try ipc.appendMessage( | |
| 2808 | 2807 | alloc, | |
| 2809 | 2808 | &sock_write_buf, |
| ... | ... | @@ -2821,7 +2820,7 @@ fn clientLoop(client_sock_fd: i32) !ClientResult { | |
| 2821 | 2820 | } | |
| 2822 | 2821 | ||
| 2823 | 2822 | // Handle socket write (flush buffered messages to daemon) | |
| 2824 | - | if (poll_fds.items[1].revents & posix.POLL.OUT != 0) { | |
| 2823 | + | if (poll_fds.items[1].revents & lib_posix.POLL.OUT != 0) { | |
| 2825 | 2824 | if (sock_write_buf.items.len > 0) { | |
| 2826 | 2825 | const n = lib_posix.write(client_sock_fd, sock_write_buf.items) catch |err| blk: { | |
| 2827 | 2826 | if (err == error.WouldBlock) break :blk 0; |
| ... | ... | @@ -2838,7 +2837,7 @@ fn clientLoop(client_sock_fd: i32) !ClientResult { | |
| 2838 | 2837 | } | |
| 2839 | 2838 | ||
| 2840 | 2839 | if (stdout_buf.items.len > 0) { | |
| 2841 | - | const n = lib_posix.write(posix.STDOUT_FILENO, stdout_buf.items) catch |err| blk: { | |
| 2840 | + | const n = lib_posix.write(lib_posix.STDOUT_FILENO, stdout_buf.items) catch |err| blk: { | |
| 2842 | 2841 | if (err == error.WouldBlock) break :blk 0; | |
| 2843 | 2842 | return err; | |
| 2844 | 2843 | }; |
| ... | ... | @@ -2847,7 +2846,7 @@ fn clientLoop(client_sock_fd: i32) !ClientResult { | |
| 2847 | 2846 | } | |
| 2848 | 2847 | } | |
| 2849 | 2848 | ||
| 2850 | - | if (poll_fds.items[1].revents & (posix.POLL.HUP | posix.POLL.ERR | posix.POLL.NVAL) != 0) { | |
| 2849 | + | if (poll_fds.items[1].revents & (lib_posix.POLL.HUP | lib_posix.POLL.ERR | lib_posix.POLL.NVAL) != 0) { | |
| 2851 | 2850 | std.log.info("poll hup|err|nval", .{}); | |
| 2852 | 2851 | return ClientResult{ .kind = .detach, .session_name = null }; | |
| 2853 | 2852 | } |
| ... | ... | @@ -2861,7 +2860,7 @@ fn daemonLoop(daemon: *Daemon, server_sock_fd: i32, pty_fd: i32) !void { | |
| 2861 | 2860 | daemon.pty_fd = pty_fd; | |
| 2862 | 2861 | try openSignalPipe(); | |
| 2863 | 2862 | installWakeHandler(@intFromEnum(lib_posix.SIG.TERM)); | |
| 2864 | - | var poll_fds = try std.ArrayList(posix.pollfd).initCapacity(daemon.alloc, 8); | |
| 2863 | + | var poll_fds = try std.ArrayList(lib_posix.pollfd).initCapacity(daemon.alloc, 8); | |
| 2865 | 2864 | defer poll_fds.deinit(daemon.alloc); | |
| 2866 | 2865 | ||
| 2867 | 2866 | const init_size = ipc.getTerminalSize(pty_fd); |
| ... | ... | @@ -2885,13 +2884,13 @@ fn daemonLoop(daemon: *Daemon, server_sock_fd: i32, pty_fd: i32) !void { | |
| 2885 | 2884 | ||
| 2886 | 2885 | try poll_fds.append(daemon.alloc, .{ | |
| 2887 | 2886 | .fd = server_sock_fd, | |
| 2888 | - | .events = posix.POLL.IN, | |
| 2887 | + | .events = lib_posix.POLL.IN, | |
| 2889 | 2888 | .revents = 0, | |
| 2890 | 2889 | }); | |
| 2891 | 2890 | ||
| 2892 | - | var pty_events: i16 = posix.POLL.IN; | |
| 2891 | + | var pty_events: i16 = lib_posix.POLL.IN; | |
| 2893 | 2892 | if (daemon.pty_write_buf.items.len > 0) { | |
| 2894 | - | pty_events |= posix.POLL.OUT; | |
| 2893 | + | pty_events |= lib_posix.POLL.OUT; | |
| 2895 | 2894 | } | |
| 2896 | 2895 | try poll_fds.append(daemon.alloc, .{ | |
| 2897 | 2896 | .fd = pty_fd, |
| ... | ... | @@ -2899,12 +2898,12 @@ fn daemonLoop(daemon: *Daemon, server_sock_fd: i32, pty_fd: i32) !void { | |
| 2899 | 2898 | .revents = 0, | |
| 2900 | 2899 | }); | |
| 2901 | 2900 | ||
| 2902 | - | try poll_fds.append(daemon.alloc, .{ .fd = sig_pipe[0], .events = posix.POLL.IN, .revents = 0 }); | |
| 2901 | + | try poll_fds.append(daemon.alloc, .{ .fd = sig_pipe[0], .events = lib_posix.POLL.IN, .revents = 0 }); | |
| 2903 | 2902 | ||
| 2904 | 2903 | for (daemon.clients.items) |client| { | |
| 2905 | - | var events: i16 = posix.POLL.IN; | |
| 2904 | + | var events: i16 = lib_posix.POLL.IN; | |
| 2906 | 2905 | if (client.has_pending_output) { | |
| 2907 | - | events |= posix.POLL.OUT; | |
| 2906 | + | events |= lib_posix.POLL.OUT; | |
| 2908 | 2907 | } | |
| 2909 | 2908 | try poll_fds.append(daemon.alloc, .{ | |
| 2910 | 2909 | .fd = client.socket_fd, |
| ... | ... | @@ -2913,9 +2912,9 @@ fn daemonLoop(daemon: *Daemon, server_sock_fd: i32, pty_fd: i32) !void { | |
| 2913 | 2912 | }); | |
| 2914 | 2913 | } | |
| 2915 | 2914 | ||
| 2916 | - | _ = try posix.poll(poll_fds.items, -1); | |
| 2915 | + | _ = try lib_posix.poll(poll_fds.items, -1); | |
| 2917 | 2916 | ||
| 2918 | - | if (poll_fds.items[2].revents & posix.POLL.IN != 0) { | |
| 2917 | + | if (poll_fds.items[2].revents & lib_posix.POLL.IN != 0) { | |
| 2919 | 2918 | drainSignalPipe(); | |
| 2920 | 2919 | std.log.info( | |
| 2921 | 2920 | "SIGTERM received, shutting down gracefully session={s}", |
| ... | ... | @@ -2924,15 +2923,15 @@ fn daemonLoop(daemon: *Daemon, server_sock_fd: i32, pty_fd: i32) !void { | |
| 2924 | 2923 | break :daemon_loop; | |
| 2925 | 2924 | } | |
| 2926 | 2925 | ||
| 2927 | - | if (poll_fds.items[0].revents & (posix.POLL.ERR | posix.POLL.HUP | posix.POLL.NVAL) != 0) { | |
| 2926 | + | if (poll_fds.items[0].revents & (lib_posix.POLL.ERR | lib_posix.POLL.HUP | lib_posix.POLL.NVAL) != 0) { | |
| 2928 | 2927 | std.log.err("server socket error revents={d}", .{poll_fds.items[0].revents}); | |
| 2929 | 2928 | break :daemon_loop; | |
| 2930 | - | } else if (poll_fds.items[0].revents & posix.POLL.IN != 0) { | |
| 2929 | + | } else if (poll_fds.items[0].revents & lib_posix.POLL.IN != 0) { | |
| 2931 | 2930 | const client_fd = try lib_posix.accept( | |
| 2932 | 2931 | server_sock_fd, | |
| 2933 | 2932 | null, | |
| 2934 | 2933 | null, | |
| 2935 | - | posix.SOCK.NONBLOCK | posix.SOCK.CLOEXEC, | |
| 2934 | + | lib_posix.SOCK.NONBLOCK | lib_posix.SOCK.CLOEXEC, | |
| 2936 | 2935 | ); | |
| 2937 | 2936 | const client = try daemon.alloc.create(Client); | |
| 2938 | 2937 | client.* = Client{ |
| ... | ... | @@ -2953,14 +2952,14 @@ fn daemonLoop(daemon: *Daemon, server_sock_fd: i32, pty_fd: i32) !void { | |
| 2953 | 2952 | ); | |
| 2954 | 2953 | } | |
| 2955 | 2954 | ||
| 2956 | - | const inp_flags = posix.POLL.IN | posix.POLL.HUP | posix.POLL.ERR | posix.POLL.NVAL; | |
| 2955 | + | const inp_flags = lib_posix.POLL.IN | lib_posix.POLL.HUP | lib_posix.POLL.ERR | lib_posix.POLL.NVAL; | |
| 2957 | 2956 | if (poll_fds.items[1].revents & inp_flags != 0) { | |
| 2958 | 2957 | // Read from PTY. Buffer is sized to N_TTY_BUF_SIZE (4096): the hard | |
| 2959 | 2958 | // kernel limit for the N_TTY line discipline. A larger buffer doesn't | |
| 2960 | 2959 | // help: each read() from a PTY master returns at most 4096 bytes | |
| 2961 | 2960 | // regardless of the userspace buffer size. | |
| 2962 | 2961 | var buf: [4096]u8 = undefined; | |
| 2963 | - | const n_opt: ?usize = posix.read(pty_fd, &buf) catch |err| blk: { | |
| 2962 | + | const n_opt: ?usize = lib_posix.read(pty_fd, &buf) catch |err| blk: { | |
| 2964 | 2963 | if (err == error.WouldBlock) break :blk null; | |
| 2965 | 2964 | break :blk 0; | |
| 2966 | 2965 | }; |
| ... | ... | @@ -3039,7 +3038,7 @@ fn daemonLoop(daemon: *Daemon, server_sock_fd: i32, pty_fd: i32) !void { | |
| 3039 | 3038 | } | |
| 3040 | 3039 | } | |
| 3041 | 3040 | ||
| 3042 | - | if (poll_fds.items[1].revents & posix.POLL.OUT != 0) { | |
| 3041 | + | if (poll_fds.items[1].revents & lib_posix.POLL.OUT != 0) { | |
| 3043 | 3042 | while (daemon.pty_write_buf.items.len > 0) { | |
| 3044 | 3043 | const n = lib_posix.write(pty_fd, daemon.pty_write_buf.items) catch |err| { | |
| 3045 | 3044 | if (err != error.WouldBlock) { |
| ... | ... | @@ -3069,7 +3068,7 @@ fn daemonLoop(daemon: *Daemon, server_sock_fd: i32, pty_fd: i32) !void { | |
| 3069 | 3068 | const client = daemon.clients.items[i]; | |
| 3070 | 3069 | const revents = poll_fds.items[i + 3].revents; | |
| 3071 | 3070 | ||
| 3072 | - | if (revents & posix.POLL.IN != 0) { | |
| 3071 | + | if (revents & lib_posix.POLL.IN != 0) { | |
| 3073 | 3072 | const n = client.read_buf.read(client.socket_fd) catch |err| { | |
| 3074 | 3073 | if (err == error.WouldBlock) continue; | |
| 3075 | 3074 | std.log.debug( |
| ... | ... | @@ -3123,7 +3122,7 @@ fn daemonLoop(daemon: *Daemon, server_sock_fd: i32, pty_fd: i32) !void { | |
| 3123 | 3122 | } | |
| 3124 | 3123 | } | |
| 3125 | 3124 | ||
| 3126 | - | if (revents & posix.POLL.OUT != 0) { | |
| 3125 | + | if (revents & lib_posix.POLL.OUT != 0) { | |
| 3127 | 3126 | // Flush pending output buffers | |
| 3128 | 3127 | const n = lib_posix.write(client.socket_fd, client.write_buf.items) catch |err| blk: { | |
| 3129 | 3128 | if (err == error.WouldBlock) break :blk 0; |
| ... | ... | @@ -3142,7 +3141,7 @@ fn daemonLoop(daemon: *Daemon, server_sock_fd: i32, pty_fd: i32) !void { | |
| 3142 | 3141 | } | |
| 3143 | 3142 | } | |
| 3144 | 3143 | ||
| 3145 | - | if (revents & (posix.POLL.HUP | posix.POLL.ERR | posix.POLL.NVAL) != 0) { | |
| 3144 | + | if (revents & (lib_posix.POLL.HUP | lib_posix.POLL.ERR | lib_posix.POLL.NVAL) != 0) { | |
| 3146 | 3145 | const last = daemon.closeClient(client, i, false); | |
| 3147 | 3146 | if (last) break :daemon_loop; | |
| 3148 | 3147 | } |
| ... | ... | @@ -3150,7 +3149,7 @@ fn daemonLoop(daemon: *Daemon, server_sock_fd: i32, pty_fd: i32) !void { | |
| 3150 | 3149 | } | |
| 3151 | 3150 | } | |
| 3152 | 3151 | ||
| 3153 | - | fn wakeSignalPipe(_: std.os.linux.SIG, _: *const posix.siginfo_t, _: ?*anyopaque) callconv(.c) void { | |
| 3152 | + | fn wakeSignalPipe(_: std.os.linux.SIG, _: *const lib_posix.siginfo_t, _: ?*anyopaque) callconv(.c) void { | |
| 3154 | 3153 | const saved = std.c._errno().*; | |
| 3155 | 3154 | _ = std.c.write(sig_pipe[1], "x", 1); | |
| 3156 | 3155 | std.c._errno().* = saved; |
| ... | ... | @@ -3160,19 +3159,19 @@ fn wakeSignalPipe(_: std.os.linux.SIG, _: *const posix.siginfo_t, _: ?*anyopaque | |
| 3160 | 3159 | // setting wakes the loop. The handler writes to sig_pipe instead; poll() | |
| 3161 | 3160 | // wakes on its read end. | |
| 3162 | 3161 | fn installWakeHandler(sig: u6) void { | |
| 3163 | - | const act: posix.Sigaction = .{ | |
| 3162 | + | const act: lib_posix.Sigaction = .{ | |
| 3164 | 3163 | .handler = .{ .sigaction = wakeSignalPipe }, | |
| 3165 | - | .mask = posix.sigemptyset(), | |
| 3166 | - | .flags = posix.SA.SIGINFO, | |
| 3164 | + | .mask = lib_posix.sigemptyset(), | |
| 3165 | + | .flags = lib_posix.SA.SIGINFO, | |
| 3167 | 3166 | }; | |
| 3168 | - | posix.sigaction(@as(posix.SIG, @enumFromInt(sig)), &act, null); | |
| 3167 | + | lib_posix.sigaction(@as(lib_posix.SIG, @enumFromInt(sig)), &act, null); | |
| 3169 | 3168 | } | |
| 3170 | 3169 | ||
| 3171 | 3170 | fn ignoreSigpipe() void { | |
| 3172 | - | const act: posix.Sigaction = .{ | |
| 3173 | - | .handler = .{ .handler = posix.SIG.IGN }, | |
| 3174 | - | .mask = posix.sigemptyset(), | |
| 3171 | + | const act: lib_posix.Sigaction = .{ | |
| 3172 | + | .handler = .{ .handler = lib_posix.SIG.IGN }, | |
| 3173 | + | .mask = lib_posix.sigemptyset(), | |
| 3175 | 3174 | .flags = 0, | |
| 3176 | 3175 | }; | |
| 3177 | - | posix.sigaction(posix.SIG.PIPE, &act, null); | |
| 3176 | + | lib_posix.sigaction(lib_posix.SIG.PIPE, &act, null); | |
| 3178 | 3177 | } |
+151,
-8
| ... | ... | @@ -6,6 +6,7 @@ const mem = std.mem; | |
| 6 | 6 | const native_os = builtin.os.tag; | |
| 7 | 7 | const use_libc = builtin.link_libc; | |
| 8 | 8 | const linux = std.os.linux; | |
| 9 | + | const cast = std.math.cast; | |
| 9 | 10 | ||
| 10 | 11 | /// A libc-compatible API layer. | |
| 11 | 12 | const system = if (use_libc) |
| ... | ... | @@ -23,28 +24,62 @@ else switch (native_os) { | |
| 23 | 24 | }, | |
| 24 | 25 | }; | |
| 25 | 26 | ||
| 26 | - | pub const SIG = system.SIG; | |
| 27 | 27 | const E = system.E; | |
| 28 | 28 | const PATH_MAX = system.PATH_MAX; | |
| 29 | 29 | const pid_t = system.pid_t; | |
| 30 | - | const AT = system.AT; | |
| 31 | 30 | const lfs64_abi = native_os == .linux and builtin.link_libc and (builtin.abi.isGnu() or builtin.abi.isAndroid()); | |
| 32 | 31 | const uid_t = system.uid_t; | |
| 33 | - | const fd_t = system.fd_t; | |
| 34 | 32 | const mode_t = system.mode_t; | |
| 35 | 33 | const socket_t = fd_t; | |
| 36 | - | const SOCK = system.SOCK; | |
| 37 | - | const F = system.F; | |
| 38 | - | const O = system.O; | |
| 39 | - | const AF = system.AF; | |
| 40 | 34 | const FD_CLOEXEC = system.FD_CLOEXEC; | |
| 41 | - | const sockaddr = system.sockaddr; | |
| 35 | + | pub const SA = system.SA; | |
| 36 | + | pub const fd_t = system.fd_t; | |
| 37 | + | pub const O = system.O; | |
| 38 | + | pub const F = system.F; | |
| 39 | + | pub const sigset_t = system.sigset_t; | |
| 40 | + | pub const nfds_t = system.nfds_t; | |
| 41 | + | pub const SOCK = system.SOCK; | |
| 42 | + | pub const AT = system.AT; | |
| 43 | + | pub const AF = system.AF; | |
| 44 | + | pub const sockaddr = system.sockaddr; | |
| 42 | 45 | pub const socklen_t = system.socklen_t; | |
| 46 | + | pub const pollfd = system.pollfd; | |
| 47 | + | pub const POLL = system.POLL; | |
| 48 | + | pub const STDERR_FILENO = system.STDERR_FILENO; | |
| 49 | + | pub const STDIN_FILENO = system.STDIN_FILENO; | |
| 50 | + | pub const STDOUT_FILENO = system.STDOUT_FILENO; | |
| 51 | + | pub const Sigaction = system.Sigaction; | |
| 52 | + | pub const SIG = system.SIG; | |
| 53 | + | pub const siginfo_t = system.siginfo_t; | |
| 43 | 54 | ||
| 44 | 55 | pub fn getuid() uid_t { | |
| 45 | 56 | return system.getuid(); | |
| 46 | 57 | } | |
| 47 | 58 | ||
| 59 | + | /// Return an empty sigset_t. | |
| 60 | + | pub fn sigemptyset() sigset_t { | |
| 61 | + | if (builtin.link_libc) { | |
| 62 | + | var set: sigset_t = undefined; | |
| 63 | + | switch (errno(system.sigemptyset(&set))) { | |
| 64 | + | .SUCCESS => return set, | |
| 65 | + | else => unreachable, | |
| 66 | + | } | |
| 67 | + | } | |
| 68 | + | return system.sigemptyset(); | |
| 69 | + | } | |
| 70 | + | ||
| 71 | + | /// Examine and change a signal action. | |
| 72 | + | pub fn sigaction(sig: SIG, noalias act: ?*const Sigaction, noalias oact: ?*Sigaction) void { | |
| 73 | + | switch (errno(system.sigaction(sig, act, oact))) { | |
| 74 | + | .SUCCESS => return, | |
| 75 | + | // EINVAL means the signal is either invalid or some signal that cannot have its action | |
| 76 | + | // changed. For POSIX, this means SIGKILL/SIGSTOP. For e.g. Solaris, this also includes the | |
| 77 | + | // non-standard SIGWAITING, SIGCANCEL, and SIGLWP. Either way, programmer error. | |
| 78 | + | .INVAL => unreachable, | |
| 79 | + | else => unreachable, | |
| 80 | + | } | |
| 81 | + | } | |
| 82 | + | ||
| 48 | 83 | /// Get an environment variable. | |
| 49 | 84 | /// See also `getenvZ`. | |
| 50 | 85 | pub fn getenv(key: []const u8) ?[:0]const u8 { |
| ... | ... | @@ -555,6 +590,78 @@ pub fn setsid() SetSidError!pid_t { | |
| 555 | 590 | } | |
| 556 | 591 | } | |
| 557 | 592 | ||
| 593 | + | pub const ReadError = error{ | |
| 594 | + | InputOutput, | |
| 595 | + | SystemResources, | |
| 596 | + | IsDir, | |
| 597 | + | OperationAborted, | |
| 598 | + | BrokenPipe, | |
| 599 | + | ConnectionResetByPeer, | |
| 600 | + | ConnectionTimedOut, | |
| 601 | + | NotOpenForReading, | |
| 602 | + | SocketNotConnected, | |
| 603 | + | ||
| 604 | + | /// This error occurs when no global event loop is configured, | |
| 605 | + | /// and reading from the file descriptor would block. | |
| 606 | + | WouldBlock, | |
| 607 | + | ||
| 608 | + | /// reading a timerfd with CANCEL_ON_SET will lead to this error | |
| 609 | + | /// when the clock goes through a discontinuous change | |
| 610 | + | Canceled, | |
| 611 | + | ||
| 612 | + | /// In WASI, this error occurs when the file descriptor does | |
| 613 | + | /// not hold the required rights to read from it. | |
| 614 | + | AccessDenied, | |
| 615 | + | ||
| 616 | + | /// This error occurs in Linux if the process to be read from | |
| 617 | + | /// no longer exists. | |
| 618 | + | ProcessNotFound, | |
| 619 | + | ||
| 620 | + | /// Unable to read file due to lock. | |
| 621 | + | LockViolation, | |
| 622 | + | } || UnexpectedError; | |
| 623 | + | ||
| 624 | + | /// Returns the number of bytes that were read, which can be less than | |
| 625 | + | /// buf.len. If 0 bytes were read, that means EOF. | |
| 626 | + | /// If `fd` is opened in non blocking mode, the function will return error.WouldBlock | |
| 627 | + | /// when EAGAIN is received. | |
| 628 | + | /// | |
| 629 | + | /// Linux has a limit on how many bytes may be transferred in one `read` call, which is `0x7ffff000` | |
| 630 | + | /// on both 64-bit and 32-bit systems. This is due to using a signed C int as the return value, as | |
| 631 | + | /// well as stuffing the errno codes into the last `4096` values. This is noted on the `read` man page. | |
| 632 | + | /// The limit on Darwin is `0x7fffffff`, trying to read more than that returns EINVAL. | |
| 633 | + | /// The corresponding POSIX limit is `maxInt(isize)`. | |
| 634 | + | pub fn read(fd: fd_t, buf: []u8) ReadError!usize { | |
| 635 | + | if (buf.len == 0) return 0; | |
| 636 | + | // Prevents EINVAL. | |
| 637 | + | const max_count = switch (native_os) { | |
| 638 | + | .linux => 0x7ffff000, | |
| 639 | + | .macos, .ios, .watchos, .tvos, .visionos => maxInt(i32), | |
| 640 | + | else => maxInt(isize), | |
| 641 | + | }; | |
| 642 | + | while (true) { | |
| 643 | + | const rc = system.read(fd, buf.ptr, @min(buf.len, max_count)); | |
| 644 | + | switch (errno(rc)) { | |
| 645 | + | .SUCCESS => return @intCast(rc), | |
| 646 | + | .INTR => continue, | |
| 647 | + | .INVAL => unreachable, | |
| 648 | + | .FAULT => unreachable, | |
| 649 | + | .SRCH => return error.ProcessNotFound, | |
| 650 | + | .AGAIN => return error.WouldBlock, | |
| 651 | + | .CANCELED => return error.Canceled, | |
| 652 | + | .BADF => return error.NotOpenForReading, // Can be a race condition. | |
| 653 | + | .IO => return error.InputOutput, | |
| 654 | + | .ISDIR => return error.IsDir, | |
| 655 | + | .NOBUFS => return error.SystemResources, | |
| 656 | + | .NOMEM => return error.SystemResources, | |
| 657 | + | .NOTCONN => return error.SocketNotConnected, | |
| 658 | + | .CONNRESET => return error.ConnectionResetByPeer, | |
| 659 | + | .TIMEDOUT => return error.ConnectionTimedOut, | |
| 660 | + | else => |err| return unexpectedErrno(err), | |
| 661 | + | } | |
| 662 | + | } | |
| 663 | + | } | |
| 664 | + | ||
| 558 | 665 | /// Open and possibly create a file. Keeps trying if it gets interrupted. | |
| 559 | 666 | /// On Windows, `file_path` should be encoded as [WTF-8](https://simonsapin.github.io/wtf-8/). | |
| 560 | 667 | /// On WASI, `file_path` should be encoded as valid UTF-8. |
| ... | ... | @@ -1106,6 +1213,30 @@ pub fn waitpid(pid: pid_t, flags: u32) WaitPidResult { | |
| 1106 | 1213 | } | |
| 1107 | 1214 | } | |
| 1108 | 1215 | ||
| 1216 | + | pub const PollError = error{ | |
| 1217 | + | /// The network subsystem has failed. | |
| 1218 | + | NetworkSubsystemFailed, | |
| 1219 | + | ||
| 1220 | + | /// The kernel had no space to allocate file descriptor tables. | |
| 1221 | + | SystemResources, | |
| 1222 | + | } || UnexpectedError; | |
| 1223 | + | ||
| 1224 | + | pub fn poll(fds: []pollfd, timeout: i32) PollError!usize { | |
| 1225 | + | while (true) { | |
| 1226 | + | const fds_count = cast(nfds_t, fds.len) orelse return error.SystemResources; | |
| 1227 | + | const rc = system.poll(fds.ptr, fds_count, timeout); | |
| 1228 | + | switch (errno(rc)) { | |
| 1229 | + | .SUCCESS => return @intCast(rc), | |
| 1230 | + | .FAULT => unreachable, | |
| 1231 | + | .INTR => continue, | |
| 1232 | + | .INVAL => unreachable, | |
| 1233 | + | .NOMEM => return error.SystemResources, | |
| 1234 | + | else => |err| return unexpectedErrno(err), | |
| 1235 | + | } | |
| 1236 | + | } | |
| 1237 | + | unreachable; | |
| 1238 | + | } | |
| 1239 | + | ||
| 1109 | 1240 | /// Call this when you made a syscall or something that sets errno | |
| 1110 | 1241 | /// and you get an unexpected error. | |
| 1111 | 1242 | fn unexpectedErrno(err: E) UnexpectedError { |
| ... | ... | @@ -1168,3 +1299,15 @@ pub fn initUnix(path: []const u8) !Address { | |
| 1168 | 1299 | ||
| 1169 | 1300 | return Address{ .un = sock_addr }; | |
| 1170 | 1301 | } | |
| 1302 | + | ||
| 1303 | + | const KillError = error{ ProcessNotFound, PermissionDenied } || UnexpectedError; | |
| 1304 | + | ||
| 1305 | + | pub fn kill(pid: pid_t, sig: SIG) KillError!void { | |
| 1306 | + | switch (errno(system.kill(pid, sig))) { | |
| 1307 | + | .SUCCESS => return, | |
| 1308 | + | .INVAL => unreachable, // invalid signal | |
| 1309 | + | .PERM => return error.PermissionDenied, | |
| 1310 | + | .SRCH => return error.ProcessNotFound, | |
| 1311 | + | else => |err| return unexpectedErrno(err), | |
| 1312 | + | } | |
| 1313 | + | } |
+5,
-6
| ... | ... | @@ -1,5 +1,4 @@ | |
| 1 | 1 | const std = @import("std"); | |
| 2 | - | const posix = std.posix; | |
| 3 | 2 | const lib_posix = @import("posix.zig"); | |
| 4 | 3 | ||
| 5 | 4 | pub fn getSeshPrefix() []const u8 { |
| ... | ... | @@ -31,7 +30,7 @@ pub fn getSeshName(alloc: std.mem.Allocator, sesh: []const u8) ![]const u8 { | |
| 31 | 30 | ||
| 32 | 31 | pub fn sessionConnect(sesh: []const u8) !i32 { | |
| 33 | 32 | var unix_addr = try lib_posix.initUnix(sesh); | |
| 34 | - | const socket_fd = try lib_posix.socket(posix.AF.UNIX, posix.SOCK.STREAM | posix.SOCK.CLOEXEC, 0); | |
| 33 | + | const socket_fd = try lib_posix.socket(lib_posix.AF.UNIX, lib_posix.SOCK.STREAM | lib_posix.SOCK.CLOEXEC, 0); | |
| 35 | 34 | errdefer lib_posix.close(socket_fd); | |
| 36 | 35 | try lib_posix.connect(socket_fd, &unix_addr.any, unix_addr.getOsSockLen()); | |
| 37 | 36 | return socket_fd; |
| ... | ... | @@ -62,8 +61,8 @@ pub fn createSocket(sesh: []const u8) !i32 { | |
| 62 | 61 | // SOCK.STREAM: Reliable, bidirectional communication | |
| 63 | 62 | // SOCK.NONBLOCK: Set socket to non-blocking | |
| 64 | 63 | const fd = try lib_posix.socket( | |
| 65 | - | posix.AF.UNIX, | |
| 66 | - | posix.SOCK.STREAM | posix.SOCK.NONBLOCK | posix.SOCK.CLOEXEC, | |
| 64 | + | lib_posix.AF.UNIX, | |
| 65 | + | lib_posix.SOCK.STREAM | lib_posix.SOCK.NONBLOCK | lib_posix.SOCK.CLOEXEC, | |
| 67 | 66 | 0, | |
| 68 | 67 | ); | |
| 69 | 68 | errdefer lib_posix.close(fd); |
| ... | ... | @@ -78,7 +77,7 @@ pub fn createSocket(sesh: []const u8) !i32 { | |
| 78 | 77 | /// Derived from the platform's sockaddr_un.path field, minus 1 for the | |
| 79 | 78 | /// required null terminator. | |
| 80 | 79 | pub const max_socket_path_len: usize = @typeInfo( | |
| 81 | - | @TypeOf(@as(posix.sockaddr.un, undefined).path), | |
| 80 | + | @TypeOf(@as(lib_posix.sockaddr.un, undefined).path), | |
| 82 | 81 | ).array.len - 1; | |
| 83 | 82 | ||
| 84 | 83 | pub fn getSocketPath( |
| ... | ... | @@ -124,7 +123,7 @@ pub fn maxSessionNameLen(socket_dir: []const u8) ?usize { | |
| 124 | 123 | ||
| 125 | 124 | test "max_socket_path_len matches platform sockaddr_un" { | |
| 126 | 125 | const path_field_len = @typeInfo( | |
| 127 | - | @TypeOf(@as(posix.sockaddr.un, undefined).path), | |
| 126 | + | @TypeOf(@as(lib_posix.sockaddr.un, undefined).path), | |
| 128 | 127 | ).array.len; | |
| 129 | 128 | try std.testing.expectEqual(path_field_len - 1, max_socket_path_len); | |
| 130 | 129 | try std.testing.expect(max_socket_path_len > 0); |
+0,
-1