mirror of
https://github.com/Ed94/Odin.git
synced 2026-08-06 15:48:51 +00:00
posix: add package
This commit is contained in:
@@ -0,0 +1,380 @@
|
||||
package posix
|
||||
|
||||
import "core:c"
|
||||
|
||||
when ODIN_OS == .Darwin {
|
||||
foreign import lib "system:System.framework"
|
||||
} else {
|
||||
foreign import lib "system:c"
|
||||
}
|
||||
|
||||
// sys/wait.h - declarations for waiting
|
||||
|
||||
foreign lib {
|
||||
/*
|
||||
Obtains status information pertaining to one of the caller's child processes.
|
||||
|
||||
Returns: -1 (setting errno) on failure or signal on calling process, the pid of the process that caused the return otherwise
|
||||
|
||||
[[ More; https://pubs.opengroup.org/onlinepubs/9699919799/functions/wait.html ]]
|
||||
*/
|
||||
wait :: proc(stat_loc: ^c.int) -> pid_t ---
|
||||
|
||||
/*
|
||||
Obtains status information pertaining to the given pid specifier.
|
||||
|
||||
If pid is -1, status is requested for any child process.
|
||||
If pid is greater than 0, it specifies the process ID of a single child process.
|
||||
If pid is 0, it specifies any child process whose process group ID is equal to that of the call.
|
||||
If pid is < -1, status is requested for any child whose process group ID is the absolute value of pid.
|
||||
|
||||
Returns: -1 (setting errno) on failure or signal on calling process, 0 if NOHANG and status is not available, the pid of the process that caused the return otherwise
|
||||
|
||||
Example:
|
||||
// The following example demonstrates the use of waitpid(), fork(), and the macros used to
|
||||
// interpret the status value returned by waitpid() (and wait()). The code segment creates a
|
||||
// child process which does some unspecified work. Meanwhile the parent loops performing calls
|
||||
// to waitpid() to monitor the status of the child. The loop terminates when child termination
|
||||
// is detected.
|
||||
|
||||
child_pid := posix.fork(); switch child_pid {
|
||||
case -1: // `fork` failed.
|
||||
panic("fork failed")
|
||||
|
||||
case 0: // This is the child.
|
||||
|
||||
// Do some work...
|
||||
|
||||
case:
|
||||
for {
|
||||
status: i32
|
||||
wpid := posix.waitpid(child_pid, &status, { .UNTRACED, .CONTINUED })
|
||||
if wpid == -1 {
|
||||
panic("waitpid failure")
|
||||
}
|
||||
|
||||
switch {
|
||||
case posix.WIFEXITED(status):
|
||||
fmt.printfln("child exited, status=%v", posix.WEXITSTATUS(status))
|
||||
case posix.WIFSIGNALED(status):
|
||||
fmt.printfln("child killed (signal %v)", posix.WTERMSIG(status))
|
||||
case posix.WIFSTOPPED(status):
|
||||
fmt.printfln("child stopped (signal %v", posix.WSTOPSIG(status))
|
||||
case posix.WIFCONTINUED(status):
|
||||
fmt.println("child continued")
|
||||
case:
|
||||
// Should never happen.
|
||||
fmt.println("unexpected status (%x)", status)
|
||||
}
|
||||
|
||||
if posix.WIFEXITED(status) || posix.WIFSIGNALED(status) {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[[ More; https://pubs.opengroup.org/onlinepubs/9699919799/functions/wait.html ]]
|
||||
*/
|
||||
waitpid :: proc(pid: pid_t, stat_loc: ^c.int, options: Wait_Flags) -> pid_t ---
|
||||
|
||||
/*
|
||||
Obtains status information pertaining to the given idtype_t and id specifier.
|
||||
|
||||
Returns: 0 if WNOHANG and no status available, 0 if child changed state, -1 (setting errno) on failure
|
||||
|
||||
[[ More; https://pubs.opengroup.org/onlinepubs/9699919799/functions/waitid.html ]]
|
||||
*/
|
||||
waitid :: proc(idtype: idtype_t, id: id_t, infop: ^siginfo_t, options: Wait_Flags) -> c.int ---
|
||||
}
|
||||
|
||||
// If terminated normally.
|
||||
WIFEXITED :: #force_inline proc "contextless" (x: c.int) -> bool {
|
||||
return _WIFEXITED(x)
|
||||
}
|
||||
|
||||
// If WIFEXITED is true, returns the exit status.
|
||||
WEXITSTATUS :: #force_inline proc "contextless" (x: c.int) -> c.int {
|
||||
return _WEXITSTATUS(x)
|
||||
}
|
||||
|
||||
// If terminated due to an uncaught signal.
|
||||
WIFSIGNALED :: #force_inline proc "contextless" (x: c.int) -> bool {
|
||||
return _WIFSIGNALED(x)
|
||||
}
|
||||
|
||||
// If WIFSIGNALED is true, returns the signal.
|
||||
WTERMSIG :: #force_inline proc "contextless" (x: c.int) -> Signal {
|
||||
return _WTERMSIG(x)
|
||||
}
|
||||
|
||||
// If status was returned for a child process that is currently stopped.
|
||||
WIFSTOPPED :: #force_inline proc "contextless" (x: c.int) -> bool {
|
||||
return _WIFSTOPPED(x)
|
||||
}
|
||||
|
||||
// If WIFSTOPPED, the signal that caused the child process to stop.
|
||||
WSTOPSIG :: #force_inline proc "contextless" (x: c.int) -> Signal {
|
||||
return _WSTOPSIG(x)
|
||||
}
|
||||
|
||||
// If status was returned for a child process that has continued from a job control stop.
|
||||
WIFCONTINUED :: #force_inline proc "contextless" (x: c.int) -> bool {
|
||||
return _WIFCONTINUED(x)
|
||||
}
|
||||
|
||||
idtype_t :: enum c.int {
|
||||
// Wait for any children and `id` is ignored.
|
||||
P_ALL,
|
||||
// Wait for any child wiith a process group ID equal to `id`.
|
||||
P_PID,
|
||||
// Wait for any child with a process group ID equal to `id`.
|
||||
P_PGID,
|
||||
}
|
||||
|
||||
Wait_Flag_Bits :: enum c.int {
|
||||
// Report the status of any continued child process specified by pid whose status has not been
|
||||
// reported since it continued from a job control stop.
|
||||
CONTINUED = log2(WCONTINUED),
|
||||
// Don't suspend execution of the calling thread if status is not immediately available for one
|
||||
// of the child processes specified by pid.
|
||||
NOHANG = log2(WNOHANG),
|
||||
// The status of any child process specified by pid that are stopped, and whose status has not
|
||||
// yet been reported since they stopped, shall also be reported to the requesting process.
|
||||
UNTRACED = log2(WUNTRACED),
|
||||
|
||||
// Following are only available on `waitid`, not `waitpid`.
|
||||
|
||||
// Wait for processes that have exited.
|
||||
EXITED = log2(WEXITED),
|
||||
// Keep the process whose status is returned in a waitable state, so it may be waited on again.
|
||||
NOWAIT = log2(WNOWAIT),
|
||||
// Children that have stopped upon receipt of a signal, and whose status either hasn't been reported
|
||||
// or has been reported but that report was called with NOWAIT.
|
||||
STOPPED = log2(WSTOPPED),
|
||||
}
|
||||
Wait_Flags :: bit_set[Wait_Flag_Bits; c.int]
|
||||
|
||||
when ODIN_OS == .Darwin {
|
||||
|
||||
id_t :: distinct c.uint
|
||||
|
||||
WCONTINUED :: 0x00000010
|
||||
WNOHANG :: 0x00000001
|
||||
WUNTRACED :: 0x00000002
|
||||
|
||||
WEXITED :: 0x00000004
|
||||
WNOWAIT :: 0x00000020
|
||||
WSTOPPED :: 0x00000008
|
||||
|
||||
@(private)
|
||||
_WSTATUS :: #force_inline proc "contextless" (x: c.int) -> c.int {
|
||||
return x & 0o177
|
||||
}
|
||||
|
||||
@(private)
|
||||
_WSTOPPED :: 0o177
|
||||
|
||||
@(private)
|
||||
_WIFEXITED :: #force_inline proc "contextless" (x: c.int) -> bool {
|
||||
return _WSTATUS(x) == 0
|
||||
}
|
||||
|
||||
@(private)
|
||||
_WEXITSTATUS :: #force_inline proc "contextless" (x: c.int) -> c.int {
|
||||
return x >> 8
|
||||
}
|
||||
|
||||
@(private)
|
||||
_WIFSIGNALED :: #force_inline proc "contextless" (x: c.int) -> bool {
|
||||
return _WSTATUS(x) != _WSTOPPED && _WSTATUS(x) != 0
|
||||
}
|
||||
|
||||
@(private)
|
||||
_WTERMSIG :: #force_inline proc "contextless" (x: c.int) -> Signal {
|
||||
return Signal(_WSTATUS(x))
|
||||
}
|
||||
|
||||
@(private)
|
||||
_WIFSTOPPED :: #force_inline proc "contextless" (x: c.int) -> bool {
|
||||
return _WSTATUS(x) == _WSTOPPED && WSTOPSIG(x) != .SIGCONT
|
||||
}
|
||||
|
||||
@(private)
|
||||
_WSTOPSIG :: #force_inline proc "contextless" (x: c.int) -> Signal {
|
||||
return Signal(x >> 8)
|
||||
}
|
||||
|
||||
@(private)
|
||||
_WIFCONTINUED :: #force_inline proc "contextless" (x: c.int) -> bool {
|
||||
return _WSTATUS(x) == _WSTOPPED && WSTOPSIG(x) == .SIGCONT
|
||||
}
|
||||
|
||||
} else when ODIN_OS == .FreeBSD {
|
||||
|
||||
id_t :: distinct c.int64_t
|
||||
|
||||
WCONTINUED :: 4
|
||||
WNOHANG :: 1
|
||||
WUNTRACED :: 2
|
||||
|
||||
WEXITED :: 16
|
||||
WNOWAIT :: 8
|
||||
WSTOPPED :: 2
|
||||
|
||||
@(private)
|
||||
_WSTATUS :: #force_inline proc "contextless" (x: c.int) -> c.int {
|
||||
return x & 0o177
|
||||
}
|
||||
|
||||
@(private)
|
||||
_WSTOPPED :: 0o177
|
||||
|
||||
@(private)
|
||||
_WIFEXITED :: #force_inline proc "contextless" (x: c.int) -> bool {
|
||||
return _WSTATUS(x) == 0
|
||||
}
|
||||
|
||||
@(private)
|
||||
_WEXITSTATUS :: #force_inline proc "contextless" (x: c.int) -> c.int {
|
||||
return x >> 8
|
||||
}
|
||||
|
||||
@(private)
|
||||
_WIFSIGNALED :: #force_inline proc "contextless" (x: c.int) -> bool {
|
||||
return _WSTATUS(x) != _WSTOPPED && _WSTATUS(x) != 0 && x != c.int(Signal.SIGCONT)
|
||||
}
|
||||
|
||||
@(private)
|
||||
_WTERMSIG :: #force_inline proc "contextless" (x: c.int) -> Signal {
|
||||
return Signal(_WSTATUS(x))
|
||||
}
|
||||
|
||||
@(private)
|
||||
_WIFSTOPPED :: #force_inline proc "contextless" (x: c.int) -> bool {
|
||||
return _WSTATUS(x) == _WSTOPPED
|
||||
}
|
||||
|
||||
@(private)
|
||||
_WSTOPSIG :: #force_inline proc "contextless" (x: c.int) -> Signal {
|
||||
return Signal(x >> 8)
|
||||
}
|
||||
|
||||
@(private)
|
||||
_WIFCONTINUED :: #force_inline proc "contextless" (x: c.int) -> bool {
|
||||
return x == c.int(Signal.SIGCONT)
|
||||
}
|
||||
} else when ODIN_OS == .NetBSD {
|
||||
|
||||
id_t :: distinct c.uint32_t
|
||||
|
||||
WCONTINUED :: 0x00000010
|
||||
WNOHANG :: 0x00000001
|
||||
WUNTRACED :: 0x00000002
|
||||
|
||||
WEXITED :: 0x00000020
|
||||
WNOWAIT :: 0x00010000
|
||||
WSTOPPED :: 0x00000002
|
||||
|
||||
@(private)
|
||||
_WSTATUS :: #force_inline proc "contextless" (x: c.int) -> c.int {
|
||||
return x & 0o177
|
||||
}
|
||||
|
||||
@(private)
|
||||
_WSTOPPED :: 0o177
|
||||
|
||||
@(private)
|
||||
_WIFEXITED :: #force_inline proc "contextless" (x: c.int) -> bool {
|
||||
return _WSTATUS(x) == 0
|
||||
}
|
||||
|
||||
@(private)
|
||||
_WEXITSTATUS :: #force_inline proc "contextless" (x: c.int) -> c.int {
|
||||
return (x >> 8) & 0x000000ff
|
||||
}
|
||||
|
||||
@(private)
|
||||
_WIFSIGNALED :: #force_inline proc "contextless" (x: c.int) -> bool {
|
||||
return !WIFSTOPPED(x) && !WIFCONTINUED(x) && !WIFEXITED(x)
|
||||
}
|
||||
|
||||
@(private)
|
||||
_WTERMSIG :: #force_inline proc "contextless" (x: c.int) -> Signal {
|
||||
return Signal(_WSTATUS(x))
|
||||
}
|
||||
|
||||
@(private)
|
||||
_WIFSTOPPED :: #force_inline proc "contextless" (x: c.int) -> bool {
|
||||
return _WSTATUS(x) == _WSTOPPED && !WIFCONTINUED(x)
|
||||
}
|
||||
|
||||
@(private)
|
||||
_WSTOPSIG :: #force_inline proc "contextless" (x: c.int) -> Signal {
|
||||
return Signal((x >> 8) & 0xff)
|
||||
}
|
||||
|
||||
@(private)
|
||||
_WIFCONTINUED :: #force_inline proc "contextless" (x: c.int) -> bool {
|
||||
return x == 0xffff
|
||||
}
|
||||
|
||||
} else when ODIN_OS == .OpenBSD {
|
||||
|
||||
id_t :: distinct c.uint32_t
|
||||
|
||||
WCONTINUED :: 0x00000010
|
||||
WNOHANG :: 0x00000001
|
||||
WUNTRACED :: 0x00000002
|
||||
|
||||
WEXITED :: 0x00000020
|
||||
WNOWAIT :: 0x00010000
|
||||
WSTOPPED :: 0x00000002
|
||||
|
||||
@(private)
|
||||
_WSTATUS :: #force_inline proc "contextless" (x: c.int) -> c.int {
|
||||
return x & 0o177
|
||||
}
|
||||
|
||||
@(private)
|
||||
_WSTOPPED :: 0o177
|
||||
@(private)
|
||||
_WCONTINUED :: 0o177777
|
||||
|
||||
@(private)
|
||||
_WIFEXITED :: #force_inline proc "contextless" (x: c.int) -> bool {
|
||||
return _WSTATUS(x) == 0
|
||||
}
|
||||
|
||||
@(private)
|
||||
_WEXITSTATUS :: #force_inline proc "contextless" (x: c.int) -> c.int {
|
||||
return (x >> 8) & 0x000000ff
|
||||
}
|
||||
|
||||
@(private)
|
||||
_WIFSIGNALED :: #force_inline proc "contextless" (x: c.int) -> bool {
|
||||
return _WSTATUS(x) != _WSTOPPED && _WSTATUS(x) != 0
|
||||
}
|
||||
|
||||
@(private)
|
||||
_WTERMSIG :: #force_inline proc "contextless" (x: c.int) -> Signal {
|
||||
return Signal(_WSTATUS(x))
|
||||
}
|
||||
|
||||
@(private)
|
||||
_WIFSTOPPED :: #force_inline proc "contextless" (x: c.int) -> bool {
|
||||
return (x & 0xff) == _WSTOPPED
|
||||
}
|
||||
|
||||
@(private)
|
||||
_WSTOPSIG :: #force_inline proc "contextless" (x: c.int) -> Signal {
|
||||
return Signal((x >> 8) & 0xff)
|
||||
}
|
||||
|
||||
@(private)
|
||||
_WIFCONTINUED :: #force_inline proc "contextless" (x: c.int) -> bool {
|
||||
return (x & _WCONTINUED) == _WCONTINUED
|
||||
}
|
||||
|
||||
} else {
|
||||
#panic("posix is unimplemented for the current target")
|
||||
}
|
||||
Reference in New Issue
Block a user