Merge pull request #1603 from mitchellh/update-zig

Update Zig
This commit is contained in:
Mitchell Hashimoto
2024-03-22 20:25:29 -07:00
committed by GitHub
15 changed files with 103 additions and 92 deletions

View File

@ -5,8 +5,8 @@
.dependencies = .{ .dependencies = .{
// Zig libs // Zig libs
.libxev = .{ .libxev = .{
.url = "https://github.com/mitchellh/libxev/archive/418cac65473668b02cc5a85194042bdaf04acd00.tar.gz", .url = "https://github.com/mitchellh/libxev/archive/0f73adfda1cff9c740160717b5431ebada6b8755.tar.gz",
.hash = "12203116ff408eb48f81c947dfeb06f7feebf6a9efa962a560ac69463098b2c04a96", .hash = "12203dcbe098ee49ea242432cd198b1ca557626988f056bea86630dcfe8660244407",
}, },
.mach_glfw = .{ .mach_glfw = .{
.url = "https://github.com/der-teufel-programming/mach-glfw/archive/250affff8c52d1eaa0fab2ef1118f691bf1225ec.tar.gz", .url = "https://github.com/der-teufel-programming/mach-glfw/archive/250affff8c52d1eaa0fab2ef1118f691bf1225ec.tar.gz",
@ -14,8 +14,8 @@
.lazy = true, .lazy = true,
}, },
.zig_objc = .{ .zig_objc = .{
.url = "https://github.com/mitchellh/zig-objc/archive/83a52ce8e3452b299cb8f2ab91bfb34cf042c664.tar.gz", .url = "https://github.com/mitchellh/zig-objc/archive/0a89cc09da6804ae448241a673ce85a282216074.tar.gz",
.hash = "1220d55dc3e61375ac93cb2449ea7b33e6bea4e53e72d18b0e6bc0ec6d38c05faaed", .hash = "1220acfc53954f699415c6942422571670544a5236866fa7b6e069e2b1b2ba86ae9c",
}, },
.zig_js = .{ .zig_js = .{
.url = "https://github.com/mitchellh/zig-js/archive/d4edb682733aef8dc3933683272bdf7c8b9fe658.tar.gz", .url = "https://github.com/mitchellh/zig-js/archive/d4edb682733aef8dc3933683272bdf7c8b9fe658.tar.gz",

12
flake.lock generated
View File

@ -147,11 +147,11 @@
}, },
"nixpkgs-zig-0-12": { "nixpkgs-zig-0-12": {
"locked": { "locked": {
"lastModified": 1710350178, "lastModified": 1711143939,
"narHash": "sha256-vZERN9g+/dfZvSRL9gNBYGVDv/8v7pmXr6LhWYxBgcU=", "narHash": "sha256-oT6a81U4NHjJH1hjaMVXKsdTZJwl2dT+MhMESKoevvA=",
"owner": "vancluever", "owner": "vancluever",
"repo": "nixpkgs", "repo": "nixpkgs",
"rev": "25322cf4d6b4ffb6f318ab45eab985d1b40e6056", "rev": "c4749393c06e52da4adf42877fdf9bac7141f0de",
"type": "github" "type": "github"
}, },
"original": { "original": {
@ -194,11 +194,11 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1710331756, "lastModified": 1711109355,
"narHash": "sha256-ZYFHWEHupxj/e9jOcjUOJLVTuvMR4fYMV53F0zu8Rfs=", "narHash": "sha256-VZPO5mq2di5yjHkkY9ZGEIZaX7EtdusSkxICBAtHAec=",
"owner": "mitchellh", "owner": "mitchellh",
"repo": "zig-overlay", "repo": "zig-overlay",
"rev": "510a1f01f1ddc06df0f2b888f12ad1aa9a65cc31", "rev": "5fe52bdf2c213e47712d93c9ce12dfed4c4cef86",
"type": "github" "type": "github"
}, },
"original": { "original": {

View File

@ -1,3 +1,3 @@
# This file is auto-generated! check build-support/check-zig-cache-hash.sh for # This file is auto-generated! check build-support/check-zig-cache-hash.sh for
# more details. # more details.
"sha256-Rf0xVSlgIciiZP/ZeAkdHnEAQTWApewNFSY8xSDAMIk=" "sha256-nr8utAh2oMwnN6nyWzJo8VubFO5cCrHK+QNYuT2WBi0="

View File

@ -22,7 +22,8 @@ const internal_os = @import("os/main.zig");
const windows = internal_os.windows; const windows = internal_os.windows;
const TempDir = internal_os.TempDir; const TempDir = internal_os.TempDir;
const mem = std.mem; const mem = std.mem;
const os = std.os; const linux = std.os.linux;
const posix = std.posix;
const debug = std.debug; const debug = std.debug;
const testing = std.testing; const testing = std.testing;
const Allocator = std.mem.Allocator; const Allocator = std.mem.Allocator;
@ -70,7 +71,7 @@ pseudo_console: if (builtin.os.tag == .windows) ?windows.exp.HPCON else void =
data: ?*anyopaque = null, data: ?*anyopaque = null,
/// Process ID is set after start is called. /// Process ID is set after start is called.
pid: ?os.pid_t = null, pid: ?posix.pid_t = null,
/// The various methods a process may exit. /// The various methods a process may exit.
pub const Exit = if (builtin.os.tag == .windows) union(enum) { pub const Exit = if (builtin.os.tag == .windows) union(enum) {
@ -89,12 +90,12 @@ pub const Exit = if (builtin.os.tag == .windows) union(enum) {
Unknown: u32, Unknown: u32,
pub fn init(status: u32) Exit { pub fn init(status: u32) Exit {
return if (os.W.IFEXITED(status)) return if (posix.W.IFEXITED(status))
Exit{ .Exited = os.W.EXITSTATUS(status) } Exit{ .Exited = posix.W.EXITSTATUS(status) }
else if (os.W.IFSIGNALED(status)) else if (posix.W.IFSIGNALED(status))
Exit{ .Signal = os.W.TERMSIG(status) } Exit{ .Signal = posix.W.TERMSIG(status) }
else if (os.W.IFSTOPPED(status)) else if (posix.W.IFSTOPPED(status))
Exit{ .Stopped = os.W.STOPSIG(status) } Exit{ .Stopped = posix.W.STOPSIG(status) }
else else
Exit{ .Unknown = status }; Exit{ .Unknown = status };
} }
@ -133,7 +134,7 @@ fn startPosix(self: *Command, arena: Allocator) !void {
@compileError("missing env vars"); @compileError("missing env vars");
// Fork // Fork
const pid = try std.os.fork(); const pid = try posix.fork();
if (pid != 0) { if (pid != 0) {
// Parent, return immediately. // Parent, return immediately.
self.pid = @intCast(pid); self.pid = @intCast(pid);
@ -143,18 +144,18 @@ fn startPosix(self: *Command, arena: Allocator) !void {
// We are the child. // We are the child.
// Setup our file descriptors for std streams. // Setup our file descriptors for std streams.
if (self.stdin) |f| try setupFd(f.handle, os.STDIN_FILENO); if (self.stdin) |f| try setupFd(f.handle, posix.STDIN_FILENO);
if (self.stdout) |f| try setupFd(f.handle, os.STDOUT_FILENO); if (self.stdout) |f| try setupFd(f.handle, posix.STDOUT_FILENO);
if (self.stderr) |f| try setupFd(f.handle, os.STDERR_FILENO); if (self.stderr) |f| try setupFd(f.handle, posix.STDERR_FILENO);
// Setup our working directory // Setup our working directory
if (self.cwd) |cwd| try os.chdir(cwd); if (self.cwd) |cwd| try posix.chdir(cwd);
// If the user requested a pre exec callback, call it now. // If the user requested a pre exec callback, call it now.
if (self.pre_exec) |f| f(self); if (self.pre_exec) |f| f(self);
// Finally, replace our process. // Finally, replace our process.
_ = std.os.execveZ(pathZ, argsZ, envp) catch null; _ = posix.execveZ(pathZ, argsZ, envp) catch null;
// If we are executing this code, the exec failed. In that scenario, // If we are executing this code, the exec failed. In that scenario,
// we return a very specific error that can be detected to determine // we return a very specific error that can be detected to determine
@ -180,7 +181,7 @@ fn startWindows(self: *Command, arena: Allocator) !void {
.creation = windows.OPEN_EXISTING, .creation = windows.OPEN_EXISTING,
}, },
) else null; ) else null;
defer if (null_fd) |fd| std.os.close(fd); defer if (null_fd) |fd| posix.close(fd);
// TODO: In the case of having FDs instead of pty, need to set up // TODO: In the case of having FDs instead of pty, need to set up
// attributes such that the child process only inherits these handles, // attributes such that the child process only inherits these handles,
@ -272,8 +273,8 @@ fn setupFd(src: File.Handle, target: i32) !void {
// file descriptor to be closed on exec since we're exactly exec-ing after // file descriptor to be closed on exec since we're exactly exec-ing after
// this. // this.
while (true) { while (true) {
const rc = os.linux.dup3(src, target, 0); const rc = linux.dup3(src, target, 0);
switch (os.errno(rc)) { switch (posix.errno(rc)) {
.SUCCESS => break, .SUCCESS => break,
.INTR => continue, .INTR => continue,
.AGAIN, .ACCES => return error.Locked, .AGAIN, .ACCES => return error.Locked,
@ -285,19 +286,19 @@ fn setupFd(src: File.Handle, target: i32) !void {
.NOTDIR => unreachable, // invalid parameter .NOTDIR => unreachable, // invalid parameter
.DEADLK => return error.DeadLock, .DEADLK => return error.DeadLock,
.NOLCK => return error.LockedRegionLimitExceeded, .NOLCK => return error.LockedRegionLimitExceeded,
else => |err| return os.unexpectedErrno(err), else => |err| return posix.unexpectedErrno(err),
} }
} }
}, },
.ios, .macos => { .ios, .macos => {
// Mac doesn't support dup3 so we use dup2. We purposely clear // Mac doesn't support dup3 so we use dup2. We purposely clear
// CLO_ON_EXEC for this fd. // CLO_ON_EXEC for this fd.
const flags = try os.fcntl(src, os.F.GETFD, 0); const flags = try posix.fcntl(src, posix.F.GETFD, 0);
if (flags & os.FD_CLOEXEC != 0) { if (flags & posix.FD_CLOEXEC != 0) {
_ = try os.fcntl(src, os.F.SETFD, flags & ~@as(u32, os.FD_CLOEXEC)); _ = try posix.fcntl(src, posix.F.SETFD, flags & ~@as(u32, posix.FD_CLOEXEC));
} }
try os.dup2(src, target); try posix.dup2(src, target);
}, },
else => @compileError("unsupported platform"), else => @compileError("unsupported platform"),
} }
@ -322,7 +323,7 @@ pub fn wait(self: Command, block: bool) !Exit {
return .{ .Exited = exit_code }; return .{ .Exited = exit_code };
} }
const res = if (block) std.os.waitpid(self.pid.?, 0) else res: { const res = if (block) posix.waitpid(self.pid.?, 0) else res: {
// We specify NOHANG because its not our fault if the process we launch // We specify NOHANG because its not our fault if the process we launch
// for the tty doesn't properly waitpid its children. We don't want // for the tty doesn't properly waitpid its children. We don't want
// to hang the terminal over it. // to hang the terminal over it.
@ -331,7 +332,7 @@ pub fn wait(self: Command, block: bool) !Exit {
// wait call has not been performed, so we need to keep trying until we get // wait call has not been performed, so we need to keep trying until we get
// a non-zero pid back, otherwise we end up with zombie processes. // a non-zero pid back, otherwise we end up with zombie processes.
while (true) { while (true) {
const res = std.os.waitpid(self.pid.?, std.c.W.NOHANG); const res = posix.waitpid(self.pid.?, std.c.W.NOHANG);
if (res.pid != 0) break :res res; if (res.pid != 0) break :res res;
} }
}; };
@ -361,11 +362,11 @@ pub fn expandPath(alloc: Allocator, cmd: []const u8) !?[]u8 {
const PATH = switch (builtin.os.tag) { const PATH = switch (builtin.os.tag) {
.windows => blk: { .windows => blk: {
const win_path = os.getenvW(std.unicode.utf8ToUtf16LeStringLiteral("PATH")) orelse return null; const win_path = std.process.getenvW(std.unicode.utf8ToUtf16LeStringLiteral("PATH")) orelse return null;
const path = try std.unicode.utf16leToUtf8Alloc(alloc, win_path); const path = try std.unicode.utf16leToUtf8Alloc(alloc, win_path);
break :blk path; break :blk path;
}, },
else => os.getenvZ("PATH") orelse return null, else => std.posix.getenvZ("PATH") orelse return null,
}; };
defer if (builtin.os.tag == .windows) alloc.free(PATH); defer if (builtin.os.tag == .windows) alloc.free(PATH);
@ -568,7 +569,7 @@ test "Command: pre exec" {
fn do(_: *Command) void { fn do(_: *Command) void {
// This runs in the child, so we can exit and it won't // This runs in the child, so we can exit and it won't
// kill the test runner. // kill the test runner.
os.exit(42); posix.exit(42);
} }
}).do, }).do,
}; };

View File

@ -9,6 +9,7 @@
const std = @import("std"); const std = @import("std");
const assert = std.debug.assert; const assert = std.debug.assert;
const posix = std.posix;
const builtin = @import("builtin"); const builtin = @import("builtin");
const build_config = @import("build_config.zig"); const build_config = @import("build_config.zig");
const main = @import("main.zig"); const main = @import("main.zig");
@ -65,7 +66,7 @@ export fn ghostty_cli_main(argc: usize, argv: [*][*:0]u8) noreturn {
std.os.argv = argv[0..argc]; std.os.argv = argv[0..argc];
main.main() catch |err| { main.main() catch |err| {
std.log.err("failed to run ghostty error={}", .{err}); std.log.err("failed to run ghostty error={}", .{err});
std.os.exit(1); posix.exit(1);
}; };
} }

View File

@ -4,6 +4,7 @@
const std = @import("std"); const std = @import("std");
const builtin = @import("builtin"); const builtin = @import("builtin");
const Allocator = std.mem.Allocator; const Allocator = std.mem.Allocator;
const posix = std.posix;
const build_config = @import("build_config.zig"); const build_config = @import("build_config.zig");
const options = @import("build_options"); const options = @import("build_options");
const glfw = @import("glfw"); const glfw = @import("glfw");
@ -42,7 +43,7 @@ pub fn main() !MainReturn {
// no other Zig code should EVER access the global state. // no other Zig code should EVER access the global state.
state.init() catch |err| { state.init() catch |err| {
const stderr = std.io.getStdErr().writer(); const stderr = std.io.getStdErr().writer();
defer std.os.exit(1); defer posix.exit(1);
const ErrSet = @TypeOf(err) || error{Unknown}; const ErrSet = @TypeOf(err) || error{Unknown};
switch (@as(ErrSet, @errorCast(err))) { switch (@as(ErrSet, @errorCast(err))) {
error.MultipleActions => try stderr.print( error.MultipleActions => try stderr.print(
@ -72,7 +73,7 @@ pub fn main() !MainReturn {
// Execute our action if we have one // Execute our action if we have one
if (state.action) |action| { if (state.action) |action| {
std.log.info("executing CLI action={}", .{action}); std.log.info("executing CLI action={}", .{action});
std.os.exit(action.run(alloc) catch |err| err: { posix.exit(action.run(alloc) catch |err| err: {
std.log.err("CLI action failed error={}", .{err}); std.log.err("CLI action failed error={}", .{err});
break :err 1; break :err 1;
}); });
@ -94,7 +95,7 @@ pub fn main() !MainReturn {
.{}, .{},
); );
std.os.exit(0); posix.exit(0);
} }
// Create our app state // Create our app state

View File

@ -1,6 +1,7 @@
const std = @import("std"); const std = @import("std");
const builtin = @import("builtin"); const builtin = @import("builtin");
const build_config = @import("../build_config.zig"); const build_config = @import("../build_config.zig");
const posix = std.posix;
const c = @cImport({ const c = @cImport({
@cInclude("unistd.h"); @cInclude("unistd.h");
@ -24,7 +25,7 @@ pub fn launchedFromDesktop() bool {
// app bundle (i.e. via open) then we still treat it as if it // app bundle (i.e. via open) then we still treat it as if it
// was launched from the desktop. // was launched from the desktop.
if (build_config.artifact == .lib and if (build_config.artifact == .lib and
std.os.getenv("GHOSTTY_MAC_APP") != null) break :macos true; posix.getenv("GHOSTTY_MAC_APP") != null) break :macos true;
break :macos c.getppid() == 1; break :macos c.getppid() == 1;
}, },
@ -36,7 +37,7 @@ pub fn launchedFromDesktop() bool {
// another terminal was launched from a desktop file and then launches // another terminal was launched from a desktop file and then launches
// Ghostty and Ghostty inherits the env. // Ghostty and Ghostty inherits the env.
.linux => linux: { .linux => linux: {
const gio_pid_str = std.os.getenv("GIO_LAUNCHED_DESKTOP_FILE_PID") orelse const gio_pid_str = posix.getenv("GIO_LAUNCHED_DESKTOP_FILE_PID") orelse
break :linux false; break :linux false;
const pid = c.getpid(); const pid = c.getpid();

View File

@ -1,6 +1,7 @@
const std = @import("std"); const std = @import("std");
const builtin = @import("builtin"); const builtin = @import("builtin");
const Allocator = std.mem.Allocator; const Allocator = std.mem.Allocator;
const posix = std.posix;
/// The separator used in environment variables such as PATH. /// The separator used in environment variables such as PATH.
pub const PATH_SEP = switch (builtin.os.tag) { pub const PATH_SEP = switch (builtin.os.tag) {
@ -46,7 +47,7 @@ pub const GetEnvResult = struct {
pub fn getenv(alloc: Allocator, key: []const u8) !?GetEnvResult { pub fn getenv(alloc: Allocator, key: []const u8) !?GetEnvResult {
return switch (builtin.os.tag) { return switch (builtin.os.tag) {
// Non-Windows doesn't need to allocate // Non-Windows doesn't need to allocate
else => if (std.os.getenv(key)) |v| .{ .value = v } else null, else => if (posix.getenv(key)) |v| .{ .value = v } else null,
// Windows needs to allocate // Windows needs to allocate
.windows => if (std.process.getEnvVarOwned(alloc, key)) |v| .{ .windows => if (std.process.getEnvVarOwned(alloc, key)) |v| .{

View File

@ -1,5 +1,6 @@
const std = @import("std"); const std = @import("std");
const builtin = @import("builtin"); const builtin = @import("builtin");
const posix = std.posix;
const log = std.log.scoped(.os); const log = std.log.scoped(.os);
@ -7,8 +8,7 @@ const log = std.log.scoped(.os);
/// need to do this because each window consumes at least a handful of fds. /// need to do this because each window consumes at least a handful of fds.
/// This is extracted from the Zig compiler source code. /// This is extracted from the Zig compiler source code.
pub fn fixMaxFiles() void { pub fn fixMaxFiles() void {
if (!@hasDecl(std.os.system, "rlimit")) return; if (!@hasDecl(posix.system, "rlimit")) return;
const posix = std.os;
var lim = posix.getrlimit(.NOFILE) catch { var lim = posix.getrlimit(.NOFILE) catch {
log.warn("failed to query file handle limit, may limit max windows", .{}); log.warn("failed to query file handle limit, may limit max windows", .{});
@ -49,14 +49,14 @@ pub fn fixMaxFiles() void {
pub fn allocTmpDir(allocator: std.mem.Allocator) ?[]const u8 { pub fn allocTmpDir(allocator: std.mem.Allocator) ?[]const u8 {
if (builtin.os.tag == .windows) { if (builtin.os.tag == .windows) {
// TODO: what is a good fallback path on windows? // TODO: what is a good fallback path on windows?
const v = std.os.getenvW(std.unicode.utf8ToUtf16LeStringLiteral("TMP")) orelse return null; const v = std.process.getenvW(std.unicode.utf8ToUtf16LeStringLiteral("TMP")) orelse return null;
return std.unicode.utf16leToUtf8Alloc(allocator, v) catch |e| { return std.unicode.utf16leToUtf8Alloc(allocator, v) catch |e| {
log.warn("failed to convert temp dir path from windows string: {}", .{e}); log.warn("failed to convert temp dir path from windows string: {}", .{e});
return null; return null;
}; };
} }
if (std.os.getenv("TMPDIR")) |v| return v; if (posix.getenv("TMPDIR")) |v| return v;
if (std.os.getenv("TMP")) |v| return v; if (posix.getenv("TMP")) |v| return v;
return "/tmp"; return "/tmp";
} }

View File

@ -2,6 +2,7 @@ const std = @import("std");
const builtin = @import("builtin"); const builtin = @import("builtin");
const assert = std.debug.assert; const assert = std.debug.assert;
const passwd = @import("passwd.zig"); const passwd = @import("passwd.zig");
const posix = std.posix;
const Error = error{ const Error = error{
/// The buffer used for output is not large enough to store the value. /// The buffer used for output is not large enough to store the value.
@ -24,7 +25,7 @@ pub inline fn home(buf: []u8) !?[]u8 {
fn homeUnix(buf: []u8) !?[]u8 { fn homeUnix(buf: []u8) !?[]u8 {
// First: if we have a HOME env var, then we use that. // First: if we have a HOME env var, then we use that.
if (std.os.getenv("HOME")) |result| { if (posix.getenv("HOME")) |result| {
if (buf.len < result.len) return Error.BufferTooSmall; if (buf.len < result.len) return Error.BufferTooSmall;
@memcpy(buf[0..result.len], result); @memcpy(buf[0..result.len], result);
return buf[0..result.len]; return buf[0..result.len];

View File

@ -1,11 +1,12 @@
const std = @import("std"); const std = @import("std");
const builtin = @import("builtin"); const builtin = @import("builtin");
const windows = @import("windows.zig"); const windows = @import("windows.zig");
const posix = std.posix;
/// pipe() that works on Windows and POSIX. /// pipe() that works on Windows and POSIX.
pub fn pipe() ![2]std.os.fd_t { pub fn pipe() ![2]posix.fd_t {
switch (builtin.os.tag) { switch (builtin.os.tag) {
else => return try std.os.pipe(), else => return try posix.pipe(),
.windows => { .windows => {
var read: windows.HANDLE = undefined; var read: windows.HANDLE = undefined;
var write: windows.HANDLE = undefined; var write: windows.HANDLE = undefined;

View File

@ -5,6 +5,7 @@ const std = @import("std");
const builtin = @import("builtin"); const builtin = @import("builtin");
const assert = std.debug.assert; const assert = std.debug.assert;
const Allocator = std.mem.Allocator; const Allocator = std.mem.Allocator;
const posix = std.posix;
const homedir = @import("homedir.zig"); const homedir = @import("homedir.zig");
pub const Options = struct { pub const Options = struct {
@ -24,7 +25,7 @@ pub fn config(alloc: Allocator, opts: Options) ![]u8 {
// both whether we have the env var and whether we own it. // both whether we have the env var and whether we own it.
// on Windows we treat `LOCALAPPDATA` as a fallback for `XDG_CONFIG_HOME` // on Windows we treat `LOCALAPPDATA` as a fallback for `XDG_CONFIG_HOME`
const env_, const owned = switch (builtin.os.tag) { const env_, const owned = switch (builtin.os.tag) {
else => .{ std.os.getenv("XDG_CONFIG_HOME"), false }, else => .{ posix.getenv("XDG_CONFIG_HOME"), false },
.windows => windows: { .windows => windows: {
if (std.process.getEnvVarOwned(alloc, "XDG_CONFIG_HOME")) |env| { if (std.process.getEnvVarOwned(alloc, "XDG_CONFIG_HOME")) |env| {
break :windows .{ env, true }; break :windows .{ env, true };

View File

@ -1,6 +1,7 @@
const std = @import("std"); const std = @import("std");
const builtin = @import("builtin"); const builtin = @import("builtin");
const windows = @import("os/main.zig").windows; const windows = @import("os/main.zig").windows;
const posix = std.posix;
const log = std.log.scoped(.pty); const log = std.log.scoped(.pty);
@ -26,7 +27,7 @@ pub const Pty = switch (builtin.os.tag) {
// a termio that doesn't use a pty. This isn't used in any user-facing // a termio that doesn't use a pty. This isn't used in any user-facing
// artifacts, this is just a stopgap to get compilation to work on iOS. // artifacts, this is just a stopgap to get compilation to work on iOS.
const NullPty = struct { const NullPty = struct {
pub const Fd = std.os.fd_t; pub const Fd = posix.fd_t;
master: Fd, master: Fd,
slave: Fd, slave: Fd,
@ -54,7 +55,7 @@ const NullPty = struct {
/// of Linux syscalls. The caller is responsible for detail-oriented handling /// of Linux syscalls. The caller is responsible for detail-oriented handling
/// of the returned file handles. /// of the returned file handles.
const PosixPty = struct { const PosixPty = struct {
pub const Fd = std.os.fd_t; pub const Fd = posix.fd_t;
// https://github.com/ziglang/zig/issues/13277 // https://github.com/ziglang/zig/issues/13277
// Once above is fixed, use `c.TIOCSCTTY` // Once above is fixed, use `c.TIOCSCTTY`
@ -95,8 +96,8 @@ const PosixPty = struct {
) < 0) ) < 0)
return error.OpenptyFailed; return error.OpenptyFailed;
errdefer { errdefer {
_ = std.os.system.close(master_fd); _ = posix.system.close(master_fd);
_ = std.os.system.close(slave_fd); _ = posix.system.close(slave_fd);
} }
// Enable UTF-8 mode. I think this is on by default on Linux but it // Enable UTF-8 mode. I think this is on by default on Linux but it
@ -115,8 +116,8 @@ const PosixPty = struct {
} }
pub fn deinit(self: *Pty) void { pub fn deinit(self: *Pty) void {
_ = std.os.system.close(self.master); _ = posix.system.close(self.master);
_ = std.os.system.close(self.slave); _ = posix.system.close(self.slave);
self.* = undefined; self.* = undefined;
} }
@ -142,7 +143,7 @@ const PosixPty = struct {
if (setsid() < 0) return error.ProcessGroupFailed; if (setsid() < 0) return error.ProcessGroupFailed;
// Set controlling terminal // Set controlling terminal
switch (std.os.system.getErrno(c.ioctl(self.slave, TIOCSCTTY, @as(c_ulong, 0)))) { switch (posix.errno(c.ioctl(self.slave, TIOCSCTTY, @as(c_ulong, 0)))) {
.SUCCESS => {}, .SUCCESS => {},
else => |err| { else => |err| {
log.err("error setting controlling terminal errno={}", .{err}); log.err("error setting controlling terminal errno={}", .{err});
@ -151,8 +152,8 @@ const PosixPty = struct {
} }
// Can close master/slave pair now // Can close master/slave pair now
std.os.close(self.slave); posix.close(self.slave);
std.os.close(self.master); posix.close(self.master);
// TODO: reset signals // TODO: reset signals
} }

View File

@ -3,6 +3,7 @@ const builtin = @import("builtin");
const assert = std.debug.assert; const assert = std.debug.assert;
const Allocator = std.mem.Allocator; const Allocator = std.mem.Allocator;
const ArenaAllocator = std.heap.ArenaAllocator; const ArenaAllocator = std.heap.ArenaAllocator;
const posix = std.posix;
const command = @import("graphics_command.zig"); const command = @import("graphics_command.zig");
const point = @import("../point.zig"); const point = @import("../point.zig");
@ -78,7 +79,7 @@ pub const LoadingImage = struct {
if (comptime builtin.os.tag != .windows) { if (comptime builtin.os.tag != .windows) {
if (std.mem.indexOfScalar(u8, buf[0..size], 0) != null) { if (std.mem.indexOfScalar(u8, buf[0..size], 0) != null) {
// std.os.realpath *asserts* that the path does not have // posix.realpath *asserts* that the path does not have
// internal nulls instead of erroring. // internal nulls instead of erroring.
log.warn("failed to get absolute path: BadPathName", .{}); log.warn("failed to get absolute path: BadPathName", .{});
return error.InvalidData; return error.InvalidData;
@ -86,7 +87,7 @@ pub const LoadingImage = struct {
} }
var abs_buf: [std.fs.MAX_PATH_BYTES]u8 = undefined; var abs_buf: [std.fs.MAX_PATH_BYTES]u8 = undefined;
const path = std.os.realpath(buf[0..size], &abs_buf) catch |err| { const path = posix.realpath(buf[0..size], &abs_buf) catch |err| {
log.warn("failed to get absolute path: {}", .{err}); log.warn("failed to get absolute path: {}", .{err});
return error.InvalidData; return error.InvalidData;
}; };
@ -151,7 +152,7 @@ pub const LoadingImage = struct {
if (!isPathInTempDir(path)) return error.TemporaryFileNotInTempDir; if (!isPathInTempDir(path)) return error.TemporaryFileNotInTempDir;
} }
defer if (medium == .temporary_file) { defer if (medium == .temporary_file) {
std.os.unlink(path) catch |err| { posix.unlink(path) catch |err| {
log.warn("failed to delete temporary file: {}", .{err}); log.warn("failed to delete temporary file: {}", .{err});
}; };
}; };
@ -209,7 +210,7 @@ pub const LoadingImage = struct {
// The temporary dir is sometimes a symlink. On macOS for // The temporary dir is sometimes a symlink. On macOS for
// example /tmp is /private/var/... // example /tmp is /private/var/...
var buf: [std.fs.MAX_PATH_BYTES]u8 = undefined; var buf: [std.fs.MAX_PATH_BYTES]u8 = undefined;
if (std.os.realpath(dir, &buf)) |real_dir| { if (posix.realpath(dir, &buf)) |real_dir| {
if (std.mem.startsWith(u8, path, real_dir)) return true; if (std.mem.startsWith(u8, path, real_dir)) return true;
} else |_| {} } else |_| {}
} }

View File

@ -8,6 +8,7 @@ const assert = std.debug.assert;
const Allocator = std.mem.Allocator; const Allocator = std.mem.Allocator;
const ArenaAllocator = std.heap.ArenaAllocator; const ArenaAllocator = std.heap.ArenaAllocator;
const EnvMap = std.process.EnvMap; const EnvMap = std.process.EnvMap;
const posix = std.posix;
const termio = @import("../termio.zig"); const termio = @import("../termio.zig");
const Command = @import("../Command.zig"); const Command = @import("../Command.zig");
const Pty = @import("../pty.zig").Pty; const Pty = @import("../pty.zig").Pty;
@ -206,7 +207,7 @@ pub fn threadEnter(self: *Exec, thread: *termio.Thread) !ThreadData {
// (Linux) which are usually guaranteed to exist. Still, we // (Linux) which are usually guaranteed to exist. Still, we
// want to handle this scenario. // want to handle this scenario.
self.execFailedInChild() catch {}; self.execFailedInChild() catch {};
std.os.exit(1); posix.exit(1);
}; };
errdefer self.subprocess.stop(); errdefer self.subprocess.stop();
const pid = pid: { const pid = pid: {
@ -221,8 +222,8 @@ pub fn threadEnter(self: *Exec, thread: *termio.Thread) !ThreadData {
// Create our pipe that we'll use to kill our read thread. // Create our pipe that we'll use to kill our read thread.
// pipe[0] is the read end, pipe[1] is the write end. // pipe[0] is the read end, pipe[1] is the write end.
const pipe = try internal_os.pipe(); const pipe = try internal_os.pipe();
errdefer std.os.close(pipe[0]); errdefer posix.close(pipe[0]);
errdefer std.os.close(pipe[1]); errdefer posix.close(pipe[1]);
// Setup our data that is used for callbacks // Setup our data that is used for callbacks
var ev_data_ptr = try alloc.create(EventData); var ev_data_ptr = try alloc.create(EventData);
@ -335,7 +336,7 @@ pub fn threadExit(self: *Exec, data: ThreadData) void {
// Quit our read thread after exiting the subprocess so that // Quit our read thread after exiting the subprocess so that
// we don't get stuck waiting for data to stop flowing if it is // we don't get stuck waiting for data to stop flowing if it is
// a particularly noisy process. // a particularly noisy process.
_ = std.os.write(data.read_thread_pipe, "x") catch |err| _ = posix.write(data.read_thread_pipe, "x") catch |err|
log.warn("error writing to read thread quit pipe err={}", .{err}); log.warn("error writing to read thread quit pipe err={}", .{err});
if (comptime builtin.os.tag == .windows) { if (comptime builtin.os.tag == .windows) {
@ -658,11 +659,11 @@ const ThreadData = struct {
/// Our read thread /// Our read thread
read_thread: std.Thread, read_thread: std.Thread,
read_thread_pipe: std.os.fd_t, read_thread_pipe: posix.fd_t,
read_thread_fd: if (builtin.os.tag == .windows) std.os.fd_t else void, read_thread_fd: if (builtin.os.tag == .windows) posix.fd_t else void,
pub fn deinit(self: *ThreadData) void { pub fn deinit(self: *ThreadData) void {
std.os.close(self.read_thread_pipe); posix.close(self.read_thread_pipe);
self.ev.deinit(self.alloc); self.ev.deinit(self.alloc);
self.alloc.destroy(self.ev); self.alloc.destroy(self.ev);
self.* = undefined; self.* = undefined;
@ -1251,7 +1252,7 @@ const Subprocess = struct {
// Once started, we can close the pty child side. We do this after // Once started, we can close the pty child side. We do this after
// wait right now but that is fine too. This lets us read the // wait right now but that is fine too. This lets us read the
// parent and detect EOF. // parent and detect EOF.
_ = std.os.close(pty.slave); _ = posix.close(pty.slave);
return .{ return .{
.read = pty.master, .read = pty.master,
@ -1393,7 +1394,7 @@ const Subprocess = struct {
// The gist is that it lets us detect when children // The gist is that it lets us detect when children
// are still alive without blocking so that we can // are still alive without blocking so that we can
// kill them again. // kill them again.
const res = std.os.waitpid(pid, std.c.W.NOHANG); const res = posix.waitpid(pid, std.c.W.NOHANG);
if (res.pid != 0) break; if (res.pid != 0) break;
std.time.sleep(10 * std.time.ns_per_ms); std.time.sleep(10 * std.time.ns_per_ms);
} }
@ -1462,18 +1463,18 @@ const Subprocess = struct {
/// fds and this is still much faster and lower overhead than any async /// fds and this is still much faster and lower overhead than any async
/// mechanism. /// mechanism.
const ReadThread = struct { const ReadThread = struct {
fn threadMainPosix(fd: std.os.fd_t, ev: *EventData, quit: std.os.fd_t) void { fn threadMainPosix(fd: posix.fd_t, ev: *EventData, quit: posix.fd_t) void {
// Always close our end of the pipe when we exit. // Always close our end of the pipe when we exit.
defer std.os.close(quit); defer posix.close(quit);
// First thing, we want to set the fd to non-blocking. We do this // First thing, we want to set the fd to non-blocking. We do this
// so that we can try to read from the fd in a tight loop and only // so that we can try to read from the fd in a tight loop and only
// check the quit fd occasionally. // check the quit fd occasionally.
if (std.os.fcntl(fd, std.os.F.GETFL, 0)) |flags| { if (posix.fcntl(fd, posix.F.GETFL, 0)) |flags| {
_ = std.os.fcntl( _ = posix.fcntl(
fd, fd,
std.os.F.SETFL, posix.F.SETFL,
flags | @as(u32, @bitCast(std.os.O{ .NONBLOCK = true })), flags | @as(u32, @bitCast(posix.O{ .NONBLOCK = true })),
) catch |err| { ) catch |err| {
log.warn("read thread failed to set flags err={}", .{err}); log.warn("read thread failed to set flags err={}", .{err});
log.warn("this isn't a fatal error, but may cause performance issues", .{}); log.warn("this isn't a fatal error, but may cause performance issues", .{});
@ -1485,9 +1486,9 @@ const ReadThread = struct {
// Build up the list of fds we're going to poll. We are looking // Build up the list of fds we're going to poll. We are looking
// for data on the pty and our quit notification. // for data on the pty and our quit notification.
var pollfds: [2]std.os.pollfd = .{ var pollfds: [2]posix.pollfd = .{
.{ .fd = fd, .events = std.os.POLL.IN, .revents = undefined }, .{ .fd = fd, .events = posix.POLL.IN, .revents = undefined },
.{ .fd = quit, .events = std.os.POLL.IN, .revents = undefined }, .{ .fd = quit, .events = posix.POLL.IN, .revents = undefined },
}; };
var buf: [1024]u8 = undefined; var buf: [1024]u8 = undefined;
@ -1498,7 +1499,7 @@ const ReadThread = struct {
// the data will eventually stop while we're trying to quit. This // the data will eventually stop while we're trying to quit. This
// is always true because we kill the process. // is always true because we kill the process.
while (true) { while (true) {
const n = std.os.read(fd, &buf) catch |err| { const n = posix.read(fd, &buf) catch |err| {
switch (err) { switch (err) {
// This means our pty is closed. We're probably // This means our pty is closed. We're probably
// gracefully shutting down. // gracefully shutting down.
@ -1530,22 +1531,22 @@ const ReadThread = struct {
} }
// Wait for data. // Wait for data.
_ = std.os.poll(&pollfds, -1) catch |err| { _ = posix.poll(&pollfds, -1) catch |err| {
log.warn("poll failed on read thread, exiting early err={}", .{err}); log.warn("poll failed on read thread, exiting early err={}", .{err});
return; return;
}; };
// If our quit fd is set, we're done. // If our quit fd is set, we're done.
if (pollfds[1].revents & std.os.POLL.IN != 0) { if (pollfds[1].revents & posix.POLL.IN != 0) {
log.info("read thread got quit signal", .{}); log.info("read thread got quit signal", .{});
return; return;
} }
} }
} }
fn threadMainWindows(fd: std.os.fd_t, ev: *EventData, quit: std.os.fd_t) void { fn threadMainWindows(fd: posix.fd_t, ev: *EventData, quit: posix.fd_t) void {
// Always close our end of the pipe when we exit. // Always close our end of the pipe when we exit.
defer std.os.close(quit); defer posix.close(quit);
var buf: [1024]u8 = undefined; var buf: [1024]u8 = undefined;
while (true) { while (true) {
@ -2641,8 +2642,8 @@ const StreamHandler = struct {
} }
// Otherwise, it must match our hostname. // Otherwise, it must match our hostname.
var buf: [std.os.HOST_NAME_MAX]u8 = undefined; var buf: [posix.HOST_NAME_MAX]u8 = undefined;
const hostname = std.os.gethostname(&buf) catch |err| { const hostname = posix.gethostname(&buf) catch |err| {
log.warn("failed to get hostname for OSC 7 validation: {}", .{err}); log.warn("failed to get hostname for OSC 7 validation: {}", .{err});
break :host_valid false; break :host_valid false;
}; };