aboutsummaryrefslogtreecommitdiff
path: root/src/DarwinPosixSpawn.zig
diff options
context:
space:
mode:
authorAndrew Kelley <andrew@ziglang.org>2024-03-18 22:39:59 -0700
committerAndrew Kelley <andrew@ziglang.org>2024-03-19 11:45:09 -0700
commitcd62005f19ff966d2c42de4daeb9a1e4b644bf76 (patch)
tree4bb316708afaf79c971808df792d8fe86274789b /src/DarwinPosixSpawn.zig
parent7057bffc14602add697eb566b83934b7ad3fd81c (diff)
downloadzig-cd62005f19ff966d2c42de4daeb9a1e4b644bf76.tar.gz
zig-cd62005f19ff966d2c42de4daeb9a1e4b644bf76.zip
extract std.posix from std.os
closes #5019
Diffstat (limited to 'src/DarwinPosixSpawn.zig')
-rw-r--r--src/DarwinPosixSpawn.zig224
1 files changed, 224 insertions, 0 deletions
diff --git a/src/DarwinPosixSpawn.zig b/src/DarwinPosixSpawn.zig
new file mode 100644
index 0000000000..336848353e
--- /dev/null
+++ b/src/DarwinPosixSpawn.zig
@@ -0,0 +1,224 @@
+const errno = std.posix.errno;
+const unexpectedErrno = std.posix.unexpectedErrno;
+
+pub const Error = error{
+ SystemResources,
+ InvalidFileDescriptor,
+ NameTooLong,
+ TooBig,
+ PermissionDenied,
+ InputOutput,
+ FileSystem,
+ FileNotFound,
+ InvalidExe,
+ NotDir,
+ FileBusy,
+ /// Returned when the child fails to execute either in the pre-exec() initialization step, or
+ /// when exec(3) is invoked.
+ ChildExecFailed,
+} || std.posix.UnexpectedError;
+
+pub const Attr = struct {
+ attr: std.c.posix_spawnattr_t,
+
+ pub fn init() Error!Attr {
+ var attr: std.c.posix_spawnattr_t = undefined;
+ switch (errno(std.c.posix_spawnattr_init(&attr))) {
+ .SUCCESS => return Attr{ .attr = attr },
+ .NOMEM => return error.SystemResources,
+ .INVAL => unreachable,
+ else => |err| return unexpectedErrno(err),
+ }
+ }
+
+ pub fn deinit(self: *Attr) void {
+ defer self.* = undefined;
+ switch (errno(std.c.posix_spawnattr_destroy(&self.attr))) {
+ .SUCCESS => return,
+ .INVAL => unreachable, // Invalid parameters.
+ else => unreachable,
+ }
+ }
+
+ pub fn get(self: Attr) Error!u16 {
+ var flags: c_short = undefined;
+ switch (errno(std.c.posix_spawnattr_getflags(&self.attr, &flags))) {
+ .SUCCESS => return @as(u16, @bitCast(flags)),
+ .INVAL => unreachable,
+ else => |err| return unexpectedErrno(err),
+ }
+ }
+
+ pub fn set(self: *Attr, flags: u16) Error!void {
+ switch (errno(std.c.posix_spawnattr_setflags(&self.attr, @as(c_short, @bitCast(flags))))) {
+ .SUCCESS => return,
+ .INVAL => unreachable,
+ else => |err| return unexpectedErrno(err),
+ }
+ }
+};
+
+pub const Actions = struct {
+ actions: std.c.posix_spawn_file_actions_t,
+
+ pub fn init() Error!Actions {
+ var actions: std.c.posix_spawn_file_actions_t = undefined;
+ switch (errno(std.c.posix_spawn_file_actions_init(&actions))) {
+ .SUCCESS => return Actions{ .actions = actions },
+ .NOMEM => return error.SystemResources,
+ .INVAL => unreachable,
+ else => |err| return unexpectedErrno(err),
+ }
+ }
+
+ pub fn deinit(self: *Actions) void {
+ defer self.* = undefined;
+ switch (errno(std.c.posix_spawn_file_actions_destroy(&self.actions))) {
+ .SUCCESS => return,
+ .INVAL => unreachable, // Invalid parameters.
+ else => unreachable,
+ }
+ }
+
+ pub fn open(self: *Actions, fd: std.c.fd_t, path: []const u8, flags: u32, mode: std.c.mode_t) Error!void {
+ const posix_path = try std.os.toPosixPath(path);
+ return self.openZ(fd, &posix_path, flags, mode);
+ }
+
+ pub fn openZ(self: *Actions, fd: std.c.fd_t, path: [*:0]const u8, flags: u32, mode: std.c.mode_t) Error!void {
+ switch (errno(std.c.posix_spawn_file_actions_addopen(&self.actions, fd, path, @as(c_int, @bitCast(flags)), mode))) {
+ .SUCCESS => return,
+ .BADF => return error.InvalidFileDescriptor,
+ .NOMEM => return error.SystemResources,
+ .NAMETOOLONG => return error.NameTooLong,
+ .INVAL => unreachable, // the value of file actions is invalid
+ else => |err| return unexpectedErrno(err),
+ }
+ }
+
+ pub fn close(self: *Actions, fd: std.c.fd_t) Error!void {
+ switch (errno(std.c.posix_spawn_file_actions_addclose(&self.actions, fd))) {
+ .SUCCESS => return,
+ .BADF => return error.InvalidFileDescriptor,
+ .NOMEM => return error.SystemResources,
+ .INVAL => unreachable, // the value of file actions is invalid
+ .NAMETOOLONG => unreachable,
+ else => |err| return unexpectedErrno(err),
+ }
+ }
+
+ pub fn dup2(self: *Actions, fd: std.c.fd_t, newfd: std.c.fd_t) Error!void {
+ switch (errno(std.c.posix_spawn_file_actions_adddup2(&self.actions, fd, newfd))) {
+ .SUCCESS => return,
+ .BADF => return error.InvalidFileDescriptor,
+ .NOMEM => return error.SystemResources,
+ .INVAL => unreachable, // the value of file actions is invalid
+ .NAMETOOLONG => unreachable,
+ else => |err| return unexpectedErrno(err),
+ }
+ }
+
+ pub fn inherit(self: *Actions, fd: std.c.fd_t) Error!void {
+ switch (errno(std.c.posix_spawn_file_actions_addinherit_np(&self.actions, fd))) {
+ .SUCCESS => return,
+ .BADF => return error.InvalidFileDescriptor,
+ .NOMEM => return error.SystemResources,
+ .INVAL => unreachable, // the value of file actions is invalid
+ .NAMETOOLONG => unreachable,
+ else => |err| return unexpectedErrno(err),
+ }
+ }
+
+ pub fn chdir(self: *Actions, path: []const u8) Error!void {
+ const posix_path = try std.os.toPosixPath(path);
+ return self.chdirZ(&posix_path);
+ }
+
+ pub fn chdirZ(self: *Actions, path: [*:0]const u8) Error!void {
+ switch (errno(std.c.posix_spawn_file_actions_addchdir_np(&self.actions, path))) {
+ .SUCCESS => return,
+ .NOMEM => return error.SystemResources,
+ .NAMETOOLONG => return error.NameTooLong,
+ .BADF => unreachable,
+ .INVAL => unreachable, // the value of file actions is invalid
+ else => |err| return unexpectedErrno(err),
+ }
+ }
+
+ pub fn fchdir(self: *Actions, fd: std.c.fd_t) Error!void {
+ switch (errno(std.c.posix_spawn_file_actions_addfchdir_np(&self.actions, fd))) {
+ .SUCCESS => return,
+ .BADF => return error.InvalidFileDescriptor,
+ .NOMEM => return error.SystemResources,
+ .INVAL => unreachable, // the value of file actions is invalid
+ .NAMETOOLONG => unreachable,
+ else => |err| return unexpectedErrno(err),
+ }
+ }
+};
+
+pub fn spawn(
+ path: []const u8,
+ actions: ?Actions,
+ attr: ?Attr,
+ argv: [*:null]?[*:0]const u8,
+ envp: [*:null]?[*:0]const u8,
+) Error!std.c.pid_t {
+ const posix_path = try std.os.toPosixPath(path);
+ return spawnZ(&posix_path, actions, attr, argv, envp);
+}
+
+pub fn spawnZ(
+ path: [*:0]const u8,
+ actions: ?Actions,
+ attr: ?Attr,
+ argv: [*:null]?[*:0]const u8,
+ envp: [*:null]?[*:0]const u8,
+) Error!std.c.pid_t {
+ var pid: std.c.pid_t = undefined;
+ switch (errno(std.c.posix_spawn(
+ &pid,
+ path,
+ if (actions) |a| &a.actions else null,
+ if (attr) |a| &a.attr else null,
+ argv,
+ envp,
+ ))) {
+ .SUCCESS => return pid,
+ .@"2BIG" => return error.TooBig,
+ .NOMEM => return error.SystemResources,
+ .BADF => return error.InvalidFileDescriptor,
+ .ACCES => return error.PermissionDenied,
+ .IO => return error.InputOutput,
+ .LOOP => return error.FileSystem,
+ .NAMETOOLONG => return error.NameTooLong,
+ .NOENT => return error.FileNotFound,
+ .NOEXEC => return error.InvalidExe,
+ .NOTDIR => return error.NotDir,
+ .TXTBSY => return error.FileBusy,
+ .BADARCH => return error.InvalidExe,
+ .BADEXEC => return error.InvalidExe,
+ .FAULT => unreachable,
+ .INVAL => unreachable,
+ else => |err| return unexpectedErrno(err),
+ }
+}
+
+pub fn waitpid(pid: std.c.pid_t, flags: u32) Error!std.os.WaitPidResult {
+ var status: c_int = undefined;
+ while (true) {
+ const rc = waitpid(pid, &status, @as(c_int, @intCast(flags)));
+ switch (errno(rc)) {
+ .SUCCESS => return std.os.WaitPidResult{
+ .pid = @as(std.c.pid_t, @intCast(rc)),
+ .status = @as(u32, @bitCast(status)),
+ },
+ .INTR => continue,
+ .CHILD => return error.ChildExecFailed,
+ .INVAL => unreachable, // Invalid flags.
+ else => unreachable,
+ }
+ }
+}
+
+const std = @import("std");