summaryrefslogtreecommitdiff
path: root/src/macos.zig
diff options
context:
space:
mode:
Diffstat (limited to 'src/macos.zig')
-rw-r--r--src/macos.zig57
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.