motiejus/zig

fork of https://codeberg.org/ziglang/zig
git clone https://git.jakstys.lt/motiejus/zig.git
Log | Tree | Refs | README | LICENSE

commit eac7fd4da5992299a1f2fb59c5aa237c0c6c6761 (tree)
parent 1fc42ed3e7ca0b74b54aaa827276d995d6c7c6cd
Author: Andrew Kelley <andrew@ziglang.org>
Date:   Mon, 22 Jul 2024 11:17:18 -0700

Merge pull request #20556 from McSinyx/setpgid

Allow setting PGID in std.process.Child.spawn
Diffstat:
Mlib/std/c.zig | 1+
Mlib/std/os/linux.zig | 4++++
Mlib/std/posix.zig | 18++++++++++++++++++
Mlib/std/process/Child.zig | 9+++++++++
4 files changed, 32 insertions(+), 0 deletions(-)

diff --git a/lib/std/c.zig b/lib/std/c.zig @@ -9167,6 +9167,7 @@ pub extern "c" fn setreuid(ruid: uid_t, euid: uid_t) c_int; pub extern "c" fn setregid(rgid: gid_t, egid: gid_t) c_int; pub extern "c" fn setresuid(ruid: uid_t, euid: uid_t, suid: uid_t) c_int; pub extern "c" fn setresgid(rgid: gid_t, egid: gid_t, sgid: gid_t) c_int; +pub extern "c" fn setpgid(pid: pid_t, pgid: pid_t) c_int; pub extern "c" fn malloc(usize) ?*anyopaque; pub extern "c" fn realloc(?*anyopaque, usize) ?*anyopaque; diff --git a/lib/std/os/linux.zig b/lib/std/os/linux.zig @@ -1551,6 +1551,10 @@ pub fn setresgid(rgid: gid_t, egid: gid_t, sgid: gid_t) usize { } } +pub fn setpgid(pid: pid_t, pgid: pid_t) usize { + return syscall2(.setpgid, @intCast(pid), @intCast(pgid)); +} + pub fn getgroups(size: usize, list: *gid_t) usize { if (@hasField(SYS, "getgroups32")) { return syscall2(.getgroups32, size, @intFromPtr(list)); diff --git a/lib/std/posix.zig b/lib/std/posix.zig @@ -3415,6 +3415,24 @@ pub fn setregid(rgid: gid_t, egid: gid_t) SetIdError!void { } } +pub const SetPgidError = error{ + ProcessAlreadyExec, + InvalidProcessGroupId, + PermissionDenied, + ProcessNotFound, +} || UnexpectedError; + +pub fn setpgid(pid: pid_t, pgid: pid_t) SetPgidError!void { + switch (errno(system.setpgid(pid, pgid))) { + .SUCCESS => return, + .ACCES => return error.ProcessAlreadyExec, + .INVAL => return error.InvalidProcessGroupId, + .PERM => return error.PermissionDenied, + .SRCH => return error.ProcessNotFound, + else => |err| return unexpectedErrno(err), + } +} + /// Test whether a file descriptor refers to a terminal. pub fn isatty(handle: fd_t) bool { if (native_os == .windows) { diff --git a/lib/std/process/Child.zig b/lib/std/process/Child.zig @@ -63,6 +63,9 @@ uid: if (native_os == .windows or native_os == .wasi) void else ?posix.uid_t, /// Set to change the group id when spawning the child process. gid: if (native_os == .windows or native_os == .wasi) void else ?posix.gid_t, +/// Set to change the process group id when spawning the child process. +pgid: if (native_os == .windows or native_os == .wasi) void else ?posix.pid_t, + /// Set to change the current working directory when spawning the child process. cwd: ?[]const u8, /// Set to change the current working directory when spawning the child process. @@ -168,6 +171,7 @@ pub const SpawnError = error{ } || posix.ExecveError || posix.SetIdError || + posix.SetPgidError || posix.ChangeCurDirError || windows.CreateProcessError || windows.GetProcessMemoryInfoError || @@ -213,6 +217,7 @@ pub fn init(argv: []const []const u8, allocator: mem.Allocator) ChildProcess { .cwd = null, .uid = if (native_os == .windows or native_os == .wasi) {} else null, .gid = if (native_os == .windows or native_os == .wasi) {} else null, + .pgid = if (native_os == .windows or native_os == .wasi) {} else null, .stdin = null, .stdout = null, .stderr = null, @@ -675,6 +680,10 @@ fn spawnPosix(self: *ChildProcess) SpawnError!void { posix.setreuid(uid, uid) catch |err| forkChildErrReport(err_pipe[1], err); } + if (self.pgid) |pid| { + posix.setpgid(0, pid) catch |err| forkChildErrReport(err_pipe[1], err); + } + const err = switch (self.expand_arg0) { .expand => posix.execvpeZ_expandArg0(.expand, argv_buf.ptr[0].?, argv_buf.ptr, envp), .no_expand => posix.execvpeZ_expandArg0(.no_expand, argv_buf.ptr[0].?, argv_buf.ptr, envp),