diff options
Diffstat (limited to 'src/macos.zig')
| -rw-r--r-- | src/macos.zig | 57 |
1 files changed, 5 insertions, 52 deletions
diff --git a/src/macos.zig b/src/macos.zig index e54e013c..2b04237e 100644 --- a/src/macos.zig +++ b/src/macos.zig @@ -35,11 +35,8 @@ const file_watch = @import("file_watch.zig"); /// attachments, so nothing here is analysed. const image = if (pardes.pdf_enabled) @import("image.zig") else struct {}; const user_config = @import("user_config.zig"); +const host_io = @import("host_io.zig"); -extern "c" fn forkpty(amaster: *c_int, name: ?[*:0]u8, termp: ?*const anyopaque, winp: ?*const posix.winsize) c_int; -extern "c" fn execv(path: [*:0]const u8, argv: [*:null]const ?[*:0]const u8) c_int; -extern "c" fn chdir(path: [*:0]const u8) c_int; -extern "c" fn _exit(status: c_int) noreturn; extern "c" fn setenv(name: [*:0]const u8, value: [*:0]const u8, overwrite: c_int) c_int; /// Implemented by FileWatcher.swift in the app and e2e host. Zig-only unit @@ -1807,7 +1804,7 @@ fn spawnShell(ctx: ?*anyopaque, pane: u8, cwd: []const u8) void { cwd_buf[cwd.len] = 0; cwd_z = @ptrCast(&cwd_buf); } - const child = forkShell(core, pane, &st.prompt_rcs, core.shellBin(), cwd_z, core.screen_h, core.screen_w); + const child = host_io.forkShell(core, pane, &st.prompt_rcs, core.shellBin(), cwd_z, core.screen_h, core.screen_w, null); st.ptys[pane] = .{ .file = child.file, .pid = child.pid, @@ -1823,7 +1820,7 @@ fn spawnShell(ctx: ?*anyopaque, pane: u8, cwd: []const u8) void { fn ptyWrite(ctx: ?*anyopaque, pane: u8, bytes: []const u8) void { const st = hostState(ctx); - if (st.ptys[pane]) |pt| writeFd(pt.file.handle, bytes); + if (st.ptys[pane]) |pt| host_io.writeFd(pt.file.handle, bytes); } fn ptyResize(ctx: ?*anyopaque, pane: u8, cols: u16, rows: u16) void { @@ -1848,14 +1845,7 @@ fn ttyTaken(ctx: ?*anyopaque, pane: u8) bool { /// resolved which path and which bytes. fn writeFile(ctx: ?*anyopaque, pane: u8, path: []const u8, bytes: []const u8) void { const st = hostState(ctx); - var pathbuf: [4096:0]u8 = undefined; - if (path.len >= pathbuf.len) return; - @memcpy(pathbuf[0..path.len], path); - pathbuf[path.len] = 0; - const fd = libc.open(pathbuf[0..path.len :0], .{ .ACCMODE = .WRONLY, .CREAT = true, .TRUNC = true }, @as(libc.mode_t, 0o644)); - if (fd < 0) return; - writeFd(fd, bytes); - _ = libc.close(fd); + if (!host_io.writeFileBytes(path, bytes)) return; // The directory source will observe our own close. Move its baseline first // so that notification is a hash no-op instead of manufacturing an external // reload and undo boundary. @@ -1870,10 +1860,7 @@ fn writeDump(ctx: ?*anyopaque, bytes: []const u8) void { const st = hostState(ctx); var pbuf: [1024:0]u8 = undefined; const path = pardes.dump.outPath(&pbuf) orelse return; - const fd = libc.open(path, .{ .ACCMODE = .WRONLY, .CREAT = true, .TRUNC = true }, @as(libc.mode_t, 0o644)); - if (fd < 0) return; - writeFd(fd, bytes); - _ = libc.close(fd); + if (!host_io.writeFileBytes(path, bytes)) return; st.core.setLastDump(path); } @@ -1988,40 +1975,6 @@ fn wake(st: *State) void { // ---------------------------------------------------------------- helpers -fn forkShell(core: *pardes.Pardes, pane: usize, prompt_rcs: *const shell_bin.PromptRcs, bin: []const u8, cwd: ?[*:0]const u8, rows: u16, cols: u16) struct { file: std.Io.File, pid: posix.pid_t } { - var master: c_int = undefined; - // Resolved BEFORE the fork, into this frame, which the child inherits: - // nothing between fork and exec may allocate, so a PATH search cannot - // happen there. - var path_buf: [std.fs.max_path_bytes]u8 = undefined; - const spawn = shell_bin.resolve(bin, &path_buf, prompt_rcs); - const ws = posix.winsize{ .row = rows, .col = cols, .xpixel = 0, .ypixel = 0 }; - const pid = forkpty(&master, null, null, &ws); - if (pid == 0) { - if (cwd) |c| _ = chdir(c); - _ = execv(spawn.path, &spawn.argv); - _exit(127); - } - if (pid > 0) core.acknowledgeShell(pane, std.mem.span(spawn.path), spawn.argv[1] != null); - return .{ .file = .{ .handle = master, .flags = .{ .nonblocking = false } }, .pid = pid }; -} - -fn writeFd(fd: c_int, data: []const u8) void { - var off: usize = 0; - while (off < data.len) { - const n = libc.write(fd, data[off..].ptr, data.len - off); - if (n < 0) { - if (libc.errno(n) == .INTR) continue; - return; - } - // A zero-byte write makes no progress; looping on it would spin the - // main thread forever, which here means a beachball rather than the - // tty shell's hung terminal. - if (n == 0) return; - off += @intCast(n); - } -} - /// Rebuild the process environment as a Map, because a library never sees the /// std.process.Init that main() gets one from. Only the config-path lookup /// reads it, and the arena owns the copies for the life of the process. |
