commit 2365ddceeb4688826c6bdef3986c22d23112fdb7
parent 686f94ddf02f46d2629b06471c4a9d8325ebe613
Author: Lorenz (xha) <me@xha.li>
Date: Sat, 25 Nov 2023 15:18:06 +0100
OpenBSD: add rt
Co-authored-by: Lennart Jablonka <humm@ljabl.com>
Signed-off-by: Lorenz (xha) <me@xha.li>
Diffstat:
13 files changed, 2848 insertions(+), 0 deletions(-)
diff --git a/rt/+openbsd/env.ha b/rt/+openbsd/env.ha
@@ -0,0 +1,6 @@
+// SPDX-License-Identifier: MPL-2.0
+// (c) Hare authors <https://harelang.org>
+
+export let argc: size = 0;
+export let argv: *[*]*u8 = null: *[*]*u8;
+export let envp: *[*]nullable *u8 = null: *[*]nullable *u8;
diff --git a/rt/+openbsd/errno.ha b/rt/+openbsd/errno.ha
@@ -0,0 +1,501 @@
+// SPDX-License-Identifier: MPL-2.0
+// (c) Hare authors <https://harelang.org>
+
+// $OpenBSD: errno.h,v 1.25 2017/09/05 03:06:26 jsg Exp $
+
+// Represents an error returned from the OpenBSD kernel.
+export type errno = !int;
+
+// Obtains a human-friendly reading of an [[errno]] (e.g. "Operation not
+// permitted").
+export fn strerror(err: errno) str = {
+ switch (err) {
+ case EPERM =>
+ return "Operation not permitted";
+ case ENOENT =>
+ return "No such file or directory";
+ case ESRCH =>
+ return "No such process";
+ case EINTR =>
+ return "Interrupted system call";
+ case EIO =>
+ return "Input/output error";
+ case ENXIO =>
+ return "Device not configured";
+ case E2BIG =>
+ return "Argument list too long";
+ case ENOEXEC =>
+ return "Exec format error";
+ case EBADF =>
+ return "Bad file descriptor";
+ case ECHILD =>
+ return "No child processes";
+ case EDEADLK =>
+ return "Resource deadlock avoided";
+ case ENOMEM =>
+ return "Cannot allocate memory";
+ case EACCES =>
+ return "Permission denied";
+ case EFAULT =>
+ return "Bad address";
+ case ENOTBLK =>
+ return "Block device required";
+ case EBUSY =>
+ return "Device busy";
+ case EEXIST =>
+ return "File exists";
+ case EXDEV =>
+ return "Cross-device link";
+ case ENODEV =>
+ return "Operation not supported by device";
+ case ENOTDIR =>
+ return "Not a directory";
+ case EISDIR =>
+ return "Is a directory";
+ case EINVAL =>
+ return "Invalid argument";
+ case ENFILE =>
+ return "Too many open files in system";
+ case EMFILE =>
+ return "Too many open files";
+ case ENOTTY =>
+ return "Inappropriate ioctl for device";
+ case ETXTBSY =>
+ return "Text file busy";
+ case EFBIG =>
+ return "File too large";
+ case ENOSPC =>
+ return "No space left on device";
+ case ESPIPE =>
+ return "Illegal seek";
+ case EROFS =>
+ return "Read-only file system";
+ case EMLINK =>
+ return "Too many links";
+ case EPIPE =>
+ return "Broken pipe";
+ case EDOM =>
+ return "Numerical argument out of domain";
+ case ERANGE =>
+ return "Result too large";
+ case EAGAIN =>
+ return "Resource temporarily unavailable";
+ case EINPROGRESS =>
+ return "Operation now in progress";
+ case EALREADY =>
+ return "Operation already in progress";
+ case ENOTSOCK =>
+ return "Socket operation on non-socket";
+ case EDESTADDRREQ =>
+ return "Destination address required";
+ case EMSGSIZE =>
+ return "Message too long";
+ case EPROTOTYPE =>
+ return "Protocol wrong type for socket";
+ case ENOPROTOOPT =>
+ return "Protocol not available";
+ case EPROTONOSUPPORT =>
+ return "Protocol not supported";
+ case ESOCKTNOSUPPORT =>
+ return "Socket type not supported";
+ case EOPNOTSUPP =>
+ return "Operation not supported";
+ case EPFNOSUPPORT =>
+ return "Protocol family not supported";
+ case EAFNOSUPPORT =>
+ return "Address family not supported by protocol family";
+ case EADDRINUSE =>
+ return "Address already in use";
+ case EADDRNOTAVAIL =>
+ return "Can't assign requested address";
+ case ENETDOWN =>
+ return "Network is down";
+ case ENETUNREACH =>
+ return "Network is unreachable";
+ case ENETRESET =>
+ return "Network dropped connection on reset";
+ case ECONNABORTED =>
+ return "Software caused connection abort";
+ case ECONNRESET =>
+ return "Connection reset by peer";
+ case ENOBUFS =>
+ return "No buffer space available";
+ case EISCONN =>
+ return "Socket is already connected";
+ case ENOTCONN =>
+ return "Socket is not connected";
+ case ESHUTDOWN =>
+ return "Can't send after socket shutdown";
+ case ETOOMANYREFS =>
+ return "Too many references: can't splice";
+ case ETIMEDOUT =>
+ return "Operation timed out";
+ case ECONNREFUSED =>
+ return "Connection refused";
+ case ELOOP =>
+ return "Too many levels of symbolic links";
+ case ENAMETOOLONG =>
+ return "File name too long";
+ case EHOSTDOWN =>
+ return "Host is down";
+ case EHOSTUNREACH =>
+ return "No route to host";
+ case ENOTEMPTY =>
+ return "Directory not empty";
+ case EPROCLIM =>
+ return "Too many processes";
+ case EUSERS =>
+ return "Too many users";
+ case EDQUOT =>
+ return "Disk quota exceeded";
+ case ESTALE =>
+ return "Stale NFS file handle";
+ case EREMOTE =>
+ return "Too many levels of remote in path";
+ case EBADRPC =>
+ return "RPC struct is bad";
+ case ERPCMISMATCH =>
+ return "RPC version wrong";
+ case EPROGUNAVAIL =>
+ return "RPC program not available";
+ case EPROGMISMATCH =>
+ return "Program version wrong";
+ case EPROCUNAVAIL =>
+ return "Bad procedure for program";
+ case ENOLCK =>
+ return "No locks available";
+ case ENOSYS =>
+ return "Function not implemented";
+ case EFTYPE =>
+ return "Inappropriate file type or format";
+ case EAUTH =>
+ return "Authentication error";
+ case ENEEDAUTH =>
+ return "Need authenticator";
+ case EIPSEC =>
+ return "IPsec processing failure";
+ case ENOATTR =>
+ return "Attribute not found";
+ case EILSEQ =>
+ return "Illegal byte sequence";
+ case ENOMEDIUM =>
+ return "No medium found";
+ case EMEDIUMTYPE =>
+ return "Wrong medium type";
+ case EOVERFLOW =>
+ return "Value too large to be stored in data type";
+ case ECANCELED =>
+ return "Operation canceled";
+ case EIDRM =>
+ return "Identifier removed";
+ case ENOMSG =>
+ return "No message of desired type";
+ case ENOTSUP =>
+ return "Not supported";
+ case EBADMSG =>
+ return "Bad message";
+ case ENOTRECOVERABLE =>
+ return "State not recoverable";
+ case EOWNERDEAD =>
+ return "Previous owner died";
+ case EPROTO =>
+ return "Protocol error";
+ case =>
+ return unknown_errno(err);
+ };
+};
+
+// Gets the programmer-friendly name for an [[errno]] (e.g. EPERM).
+export fn errname(err: errno) str = {
+ switch (err) {
+ case EPERM =>
+ return "EPERM";
+ case ENOENT =>
+ return "ENOENT";
+ case ESRCH =>
+ return "ESRCH";
+ case EINTR =>
+ return "EINTR";
+ case EIO =>
+ return "EIO";
+ case ENXIO =>
+ return "ENXIO";
+ case E2BIG =>
+ return "E2BIG";
+ case ENOEXEC =>
+ return "ENOEXEC";
+ case EBADF =>
+ return "EBADF";
+ case ECHILD =>
+ return "ECHILD";
+ case EDEADLK =>
+ return "EDEADLK";
+ case ENOMEM =>
+ return "ENOMEM";
+ case EACCES =>
+ return "EACCES";
+ case EFAULT =>
+ return "EFAULT";
+ case ENOTBLK =>
+ return "ENOTBLK";
+ case EBUSY =>
+ return "EBUSY";
+ case EEXIST =>
+ return "EEXIST";
+ case EXDEV =>
+ return "EXDEV";
+ case ENODEV =>
+ return "ENODEV";
+ case ENOTDIR =>
+ return "ENOTDIR";
+ case EISDIR =>
+ return "EISDIR";
+ case EINVAL =>
+ return "EINVAL";
+ case ENFILE =>
+ return "ENFILE";
+ case EMFILE =>
+ return "EMFILE";
+ case ENOTTY =>
+ return "ENOTTY";
+ case ETXTBSY =>
+ return "ETXTBSY";
+ case EFBIG =>
+ return "EFBIG";
+ case ENOSPC =>
+ return "ENOSPC";
+ case ESPIPE =>
+ return "ESPIPE";
+ case EROFS =>
+ return "EROFS";
+ case EMLINK =>
+ return "EMLINK";
+ case EPIPE =>
+ return "EPIPE";
+ case EDOM =>
+ return "EDOM";
+ case ERANGE =>
+ return "ERANGE";
+ case EAGAIN =>
+ return "EAGAIN";
+ case EINPROGRESS =>
+ return "EINPROGRESS";
+ case EALREADY =>
+ return "EALREADY";
+ case ENOTSOCK =>
+ return "ENOTSOCK";
+ case EDESTADDRREQ =>
+ return "EDESTADDRREQ";
+ case EMSGSIZE =>
+ return "EMSGSIZE";
+ case EPROTOTYPE =>
+ return "EPROTOTYPE";
+ case ENOPROTOOPT =>
+ return "ENOPROTOOPT";
+ case EPROTONOSUPPORT =>
+ return "EPROTONOSUPPORT";
+ case ESOCKTNOSUPPORT =>
+ return "ESOCKTNOSUPPORT";
+ case EOPNOTSUPP =>
+ return "EOPNOTSUPP";
+ case EPFNOSUPPORT =>
+ return "EPFNOSUPPORT";
+ case EAFNOSUPPORT =>
+ return "EAFNOSUPPORT";
+ case EADDRINUSE =>
+ return "EADDRINUSE";
+ case EADDRNOTAVAIL =>
+ return "EADDRNOTAVAIL";
+ case ENETDOWN =>
+ return "ENETDOWN";
+ case ENETUNREACH =>
+ return "ENETUNREACH";
+ case ENETRESET =>
+ return "ENETRESET";
+ case ECONNABORTED =>
+ return "ECONNABORTED";
+ case ECONNRESET =>
+ return "ECONNRESET";
+ case ENOBUFS =>
+ return "ENOBUFS";
+ case EISCONN =>
+ return "EISCONN";
+ case ENOTCONN =>
+ return "ENOTCONN";
+ case ESHUTDOWN =>
+ return "ESHUTDOWN";
+ case ETOOMANYREFS =>
+ return "ETOOMANYREFS";
+ case ETIMEDOUT =>
+ return "ETIMEDOUT";
+ case ECONNREFUSED =>
+ return "ECONNREFUSED";
+ case ELOOP =>
+ return "ELOOP";
+ case ENAMETOOLONG =>
+ return "ENAMETOOLONG";
+ case EHOSTDOWN =>
+ return "EHOSTDOWN";
+ case EHOSTUNREACH =>
+ return "EHOSTUNREACH";
+ case ENOTEMPTY =>
+ return "ENOTEMPTY";
+ case EPROCLIM =>
+ return "EPROCLIM";
+ case EUSERS =>
+ return "EUSERS";
+ case EDQUOT =>
+ return "EDQUOT";
+ case ESTALE =>
+ return "ESTALE";
+ case EREMOTE =>
+ return "EREMOTE";
+ case EBADRPC =>
+ return "EBADRPC";
+ case ERPCMISMATCH =>
+ return "ERPCMISMATCH";
+ case EPROGUNAVAIL =>
+ return "EPROGUNAVAIL";
+ case EPROGMISMATCH =>
+ return "EPROGMISMATCH";
+ case EPROCUNAVAIL =>
+ return "EPROCUNAVAIL";
+ case ENOLCK =>
+ return "ENOLCK";
+ case ENOSYS =>
+ return "ENOSYS";
+ case EFTYPE =>
+ return "EFTYPE";
+ case EAUTH =>
+ return "EAUTH";
+ case ENEEDAUTH =>
+ return "ENEEDAUTH";
+ case EIPSEC =>
+ return "EIPSEC";
+ case ENOATTR =>
+ return "ENOATTR";
+ case EILSEQ =>
+ return "EILSEQ";
+ case ENOMEDIUM =>
+ return "ENOMEDIUM";
+ case EMEDIUMTYPE =>
+ return "EMEDIUMTYPE";
+ case EOVERFLOW =>
+ return "EOVERFLOW";
+ case ECANCELED =>
+ return "ECANCELED";
+ case EIDRM =>
+ return "EIDRM";
+ case ENOMSG =>
+ return "ENOMSG";
+ case ENOTSUP =>
+ return "ENOTSUP";
+ case EBADMSG =>
+ return "EBADMSG";
+ case ENOTRECOVERABLE =>
+ return "ENOTRECOVERABLE";
+ case EOWNERDEAD =>
+ return "EOWNERDEAD";
+ case EPROTO =>
+ return "EPROTO";
+ case =>
+ return unknown_errno(err);
+ };
+};
+
+export def EPERM: errno = 1;
+export def ENOENT: errno = 2;
+export def ESRCH: errno = 3;
+export def EINTR: errno = 4;
+export def EIO: errno = 5;
+export def ENXIO: errno = 6;
+export def E2BIG: errno = 7;
+export def ENOEXEC: errno = 8;
+export def EBADF: errno = 9;
+export def ECHILD: errno = 10;
+export def EDEADLK: errno = 11;
+export def ENOMEM: errno = 12;
+export def EACCES: errno = 13;
+export def EFAULT: errno = 14;
+export def ENOTBLK: errno = 15;
+export def EBUSY: errno = 16;
+export def EEXIST: errno = 17;
+export def EXDEV: errno = 18;
+export def ENODEV: errno = 19;
+export def ENOTDIR: errno = 20;
+export def EISDIR: errno = 21;
+export def EINVAL: errno = 22;
+export def ENFILE: errno = 23;
+export def EMFILE: errno = 24;
+export def ENOTTY: errno = 25;
+export def ETXTBSY: errno = 26;
+export def EFBIG: errno = 27;
+export def ENOSPC: errno = 28;
+export def ESPIPE: errno = 29;
+export def EROFS: errno = 30;
+export def EMLINK: errno = 31;
+export def EPIPE: errno = 32;
+export def EDOM: errno = 33;
+export def ERANGE: errno = 34;
+export def EAGAIN: errno = 35;
+export def EWOULDBLOCK: errno = EAGAIN;
+export def EINPROGRESS: errno = 36;
+export def EALREADY: errno = 37;
+export def ENOTSOCK: errno = 38;
+export def EDESTADDRREQ: errno = 39;
+export def EMSGSIZE: errno = 40;
+export def EPROTOTYPE: errno = 41;
+export def ENOPROTOOPT: errno = 42;
+export def EPROTONOSUPPORT: errno = 43;
+export def ESOCKTNOSUPPORT: errno = 44;
+export def EOPNOTSUPP: errno = 45;
+export def EPFNOSUPPORT: errno = 46;
+export def EAFNOSUPPORT: errno = 47;
+export def EADDRINUSE: errno = 48;
+export def EADDRNOTAVAIL: errno = 49;
+export def ENETDOWN: errno = 50;
+export def ENETUNREACH: errno = 51;
+export def ENETRESET: errno = 52;
+export def ECONNABORTED: errno = 53;
+export def ECONNRESET: errno = 54;
+export def ENOBUFS: errno = 55;
+export def EISCONN: errno = 56;
+export def ENOTCONN: errno = 57;
+export def ESHUTDOWN: errno = 58;
+export def ETOOMANYREFS: errno = 59;
+export def ETIMEDOUT: errno = 60;
+export def ECONNREFUSED: errno = 61;
+export def ELOOP: errno = 62;
+export def ENAMETOOLONG: errno = 63;
+export def EHOSTDOWN: errno = 64;
+export def EHOSTUNREACH: errno = 65;
+export def ENOTEMPTY: errno = 66;
+export def EPROCLIM: errno = 67;
+export def EUSERS: errno = 68;
+export def EDQUOT: errno = 69;
+export def ESTALE: errno = 70;
+export def EREMOTE: errno = 71;
+export def EBADRPC: errno = 72;
+export def ERPCMISMATCH: errno = 73;
+export def EPROGUNAVAIL: errno = 74;
+export def EPROGMISMATCH: errno = 75;
+export def EPROCUNAVAIL: errno = 76;
+export def ENOLCK: errno = 77;
+export def ENOSYS: errno = 78;
+export def EFTYPE: errno = 79;
+export def EAUTH: errno = 80;
+export def ENEEDAUTH: errno = 81;
+export def EIPSEC: errno = 82;
+export def ENOATTR: errno = 83;
+export def EILSEQ: errno = 84;
+export def ENOMEDIUM: errno = 85;
+export def EMEDIUMTYPE: errno = 86;
+export def EOVERFLOW: errno = 87;
+export def ECANCELED: errno = 88;
+export def EIDRM: errno = 89;
+export def ENOMSG: errno = 90;
+export def ENOTSUP: errno = 91;
+export def EBADMSG: errno = 92;
+export def ENOTRECOVERABLE: errno = 93;
+export def EOWNERDEAD: errno = 94;
+export def EPROTO: errno = 95;
diff --git a/rt/+openbsd/hare+test.sc b/rt/+openbsd/hare+test.sc
@@ -0,0 +1,7 @@
+SECTIONS {
+ .test_array : {
+ PROVIDE(__test_array_start = .);
+ KEEP(*(.test_array*))
+ PROVIDE(__test_array_end = .);
+ }
+} INSERT AFTER .bss; /* .bss was choosen arbitrarily. */
diff --git a/rt/+openbsd/hare.sc b/rt/+openbsd/hare.sc
@@ -0,0 +1 @@
+/* empty linker script; not needed for OpenBSD */
+\ No newline at end of file
diff --git a/rt/+openbsd/libc.ha b/rt/+openbsd/libc.ha
@@ -0,0 +1,20 @@
+// SPDX-License-Identifier: MPL-2.0
+// (c) Hare authors <https://harelang.org>
+
+// Miscellaneous libc functions
+
+export @symbol("arc4random_buf") fn arc4random_buf(
+ buf: *opaque,
+ nbytes: size
+) void;
+
+@symbol("ptsname") fn libc_ptsname(flides: int) *u8;
+
+export fn ptsname(flides: int) (*u8 | errno) = {
+ let res = libc_ptsname(flides);
+
+ if (res == null) {
+ return *__errno(): errno;
+ };
+ return res;
+};
diff --git a/rt/+openbsd/platform_abort.ha b/rt/+openbsd/platform_abort.ha
@@ -0,0 +1,23 @@
+// SPDX-License-Identifier: MPL-2.0
+// (c) Hare authors <https://harelang.org>
+
+fn platform_abort(path: *str, line: u64, col: u64, msg: str) void = {
+ const prefix = "Abort: ";
+ const sep = ":";
+ const sepspace = ": ";
+ const linefeed = "\n";
+ write(STDERR_FILENO, *(&prefix: **opaque): *const u8, len(prefix)): void;
+ write(STDERR_FILENO, *(path: **opaque): *const u8, len(path)): void;
+ write(STDERR_FILENO, *(&sep: **opaque): *const u8, len(sep)): void;
+ let (line, z) = u64tos(line);
+ write(STDERR_FILENO, line, z): void;
+ write(STDERR_FILENO, *(&sep: **opaque): *const u8, len(sep)): void;
+ let (col, z) = u64tos(col);
+ write(STDERR_FILENO, col, z): void;
+ write(STDERR_FILENO, *(&sepspace: **opaque): *const u8,
+ len(sepspace)): void;
+ write(STDERR_FILENO, *(&msg: **opaque): *const u8, len(msg)): void;
+ write(STDERR_FILENO, *(&linefeed: **opaque): *const u8, 1): void;
+ kill(getpid(), SIGABRT): void;
+ for (true) void;
+};
diff --git a/rt/+openbsd/signal.ha b/rt/+openbsd/signal.ha
@@ -0,0 +1,73 @@
+// SPDX-License-Identifier: MPL-2.0
+// (c) Hare authors <https://harelang.org>
+
+export fn sigemptyset(set: *sigset) void = {
+ *set = 0;
+};
+
+export fn sigaddset(set: *sigset, signum: int) (void | errno) = {
+ if (signum < 1 || signum > NSIG) {
+ return *__errno(): errno;
+ };
+ *set |= 1u << (signum: uint - 1);
+};
+
+export fn sigdelset(set: *sigset, signum: int) (void | errno) = {
+ if (signum < 1 || signum > NSIG) {
+ return *__errno(): errno;
+ };
+ *set &= ~(1u << (signum: uint - 1));
+};
+
+export fn sigismember(set: *sigset, signum: int) (bool | errno) = {
+ if (signum < 1 || signum > NSIG) {
+ return *__errno(): errno;
+ };
+ return (*set & (1u << (signum: uint - 1))) != 0;
+};
+
+export fn sigfillset(set: *sigset) (void | errno) = {
+ *set = ~0u;
+};
+
+// Test sigset operations do not fail for valid signal numbers.
+@test fn sigset_valid_signum() void = {
+ let set: sigset = 0;
+ sigemptyset(&set);
+
+ assert(!(sigismember(&set, 1) is errno), "Unexpected error");
+ assert(!(sigismember(&set, 15) is errno), "Unexpected error");
+ assert(!(sigismember(&set, NSIG) is errno), "Unexpected error");
+
+ assert(!(sigaddset(&set, 1) is errno), "Unexpected error");
+ assert(!(sigaddset(&set, 15) is errno), "Unexpected error");
+ assert(!(sigaddset(&set, NSIG) is errno), "Unexpected error");
+
+ // It's ok to add a signal that is already present in the set.
+ assert(!(sigaddset(&set, 1) is errno), "Unexpected error");
+
+ assert(!(sigdelset(&set, 1) is errno), "Unexpected error");
+ assert(!(sigdelset(&set, 15) is errno), "Unexpected error");
+ assert(!(sigdelset(&set, NSIG) is errno), "Unexpected error");
+
+ // It's ok to delete a signal that is not present in the set.
+ assert(!(sigdelset(&set, 10) is errno), "Unexpected error");
+};
+
+// Test sigset operations fail for invalid signal numbers.
+@test fn sigset_invalid_signum() void = {
+ let set: sigset = 0;
+ sigemptyset(&set);
+
+ assert(sigismember(&set, -1) is errno, "Expected error");
+ assert(sigismember(&set, 0) is errno, "Expected error");
+ assert(sigismember(&set, NSIG + 1) is errno, "Expected error");
+
+ assert(sigaddset(&set, -1) is errno, "Expected error");
+ assert(sigaddset(&set, 0) is errno, "Expected error");
+ assert(sigaddset(&set, NSIG + 1) is errno, "Expected error");
+
+ assert(sigdelset(&set, -1) is errno, "Expected error");
+ assert(sigdelset(&set, 0) is errno, "Expected error");
+ assert(sigdelset(&set, NSIG + 1) is errno, "Expected error");
+};
diff --git a/rt/+openbsd/socket.ha b/rt/+openbsd/socket.ha
@@ -0,0 +1,150 @@
+// SPDX-License-Identifier: MPL-2.0
+// (c) Hare authors <https://harelang.org>
+
+export type socklen_t = u32;
+export type sa_family_t = u8;
+
+export type in_addr = struct {
+ s_addr: u32
+};
+
+export type sockaddr_in = struct {
+ sin_len: u8,
+ sin_family: sa_family_t,
+ sin_port: u16,
+ sin_addr: in_addr,
+ __pad: [8]u8,
+};
+
+export type in6_addr = struct {
+ union {
+ s6_addr: [16]u8,
+ s6_addr16: [8]u16,
+ s6_addr32: [4]u32,
+ }
+};
+
+export type sockaddr_in6 = struct {
+ sin6_len: u8,
+ sin6_family: sa_family_t,
+ sin6_port: u16,
+ sin6_flowinfo: u32,
+ sin6_addr: in6_addr,
+ sin6_scope_id: u32,
+};
+
+export def UNIX_PATH_MAX: size = 104;
+
+export type sockaddr_un = struct {
+ sun_len: u8,
+ sun_family: sa_family_t,
+ sun_path: [UNIX_PATH_MAX]u8,
+};
+
+export type sockaddr = struct {
+ union {
+ in: sockaddr_in,
+ in6: sockaddr_in6,
+ un: sockaddr_un,
+ },
+};
+
+export def SCM_RIGHTS: int = 0x01;
+export def SCM_TIMESTAMP: int = 0x04;
+
+export type msghdr = struct {
+ msg_name: nullable *opaque,
+ msg_namelen: socklen_t,
+ msg_iov: nullable *[*]iovec,
+ msg_iovlen: uint,
+ msg_control: nullable *opaque,
+ msg_controllen: socklen_t,
+ msg_flags: int
+};
+
+export type cmsghdr = struct {
+ cmsg_len: socklen_t,
+ cmsg_level: int,
+ cmsg_type: int,
+};
+
+export type cmsg = struct {
+ hdr: cmsghdr,
+ cmsg_data: [*]u8,
+};
+
+export def SOCK_STREAM: int = 1;
+export def SOCK_DGRAM: int = 2;
+export def SOCK_RAW: int = 3;
+export def SOCK_RDM: int = 4;
+export def SOCK_SEQPACKET: int = 5;
+
+export def SOCK_CLOEXEC: int = 0x8000;
+export def SOCK_NONBLOCK: int = 0x4000;
+
+export def SOL_SOCKET: int = 0xffff;
+
+export def AF_UNSPEC: sa_family_t = 0;
+export def AF_UNIX: sa_family_t = 1;
+export def AF_LOCAL: sa_family_t = AF_UNIX;
+export def AF_INET: sa_family_t = 2;
+export def AF_IMPLINK: sa_family_t = 3;
+export def AF_PUP: sa_family_t = 4;
+export def AF_CHAOS: sa_family_t = 5;
+export def AF_NS: sa_family_t = 6;
+export def AF_ISO: sa_family_t = 7;
+export def AF_OSI: sa_family_t = AF_ISO;
+export def AF_ECMA: sa_family_t = 8;
+export def AF_DATAKIT: sa_family_t = 9;
+export def AF_CCITT: sa_family_t = 10;
+export def AF_SNA: sa_family_t = 11;
+export def AF_DECnet: sa_family_t = 12;
+export def AF_DLI: sa_family_t = 13;
+export def AF_LAT: sa_family_t = 14;
+export def AF_HYLINK: sa_family_t = 15;
+export def AF_APPLETALK: sa_family_t = 16;
+export def AF_ROUTE: sa_family_t = 17;
+export def AF_LINK: sa_family_t = 18;
+export def pseudo_AF_XTP: sa_family_t = 19;
+export def AF_COIP: sa_family_t = 20;
+export def AF_CNT: sa_family_t = 21;
+export def pseudo_AF_RTIP: sa_family_t = 22;
+export def AF_IPX: sa_family_t = 23;
+export def AF_INET6: sa_family_t = 24;
+export def pseudo_AF_PIP: sa_family_t = 25;
+export def AF_ISDN: sa_family_t = 26;
+export def AF_E164: sa_family_t = AF_ISDN;
+export def AF_NATM: sa_family_t = 27;
+export def AF_ENCAP: sa_family_t = 28;
+export def AF_SIP: sa_family_t = 29;
+export def AF_KEY: sa_family_t = 30;
+export def pseudo_AF_HDRCMPLT: sa_family_t = 31;
+
+export def SO_DEBUG: int = 0x0001;
+export def SO_ACCEPTCONN: int = 0x0002;
+export def SO_REUSEADDR: int = 0x0004;
+export def SO_KEEPALIVE: int = 0x0008;
+export def SO_DONTROUTE: int = 0x0010;
+export def SO_BROADCAST: int = 0x0020;
+export def SO_USELOOPBACK: int = 0x0040;
+export def SO_LINGER: int = 0x0080;
+export def SO_OOBINLINE: int = 0x0100;
+export def SO_REUSEPORT: int = 0x0200;
+export def SO_TIMESTAMP: int = 0x0800;
+export def SO_BINDANY: int = 0x1000;
+export def SO_ZEROIZE: int = 0x2000;
+
+export def SO_SNDBUF: int = 0x1001;
+export def SO_RCVBUF: int = 0x1002;
+export def SO_SNDLOWAT: int = 0x1003;
+export def SO_RCVLOWAT: int = 0x1004;
+export def SO_SNDTIMEO: int = 0x1005;
+export def SO_RCVTIMEO: int = 0x1006;
+export def SO_ERROR: int = 0x1007;
+export def SO_TYPE: int = 0x1008;
+export def SO_NETPROC: int = 0x1020;
+export def SO_RTABLE: int = 0x1021;
+export def SO_PEERCRED: int = 0x1022;
+export def SO_SPLICE: int = 0x1023;
+export def SO_DOMAIN: int = 0x1024;
+export def SO_PROTOCOL: int = 0x1025;
diff --git a/rt/+openbsd/start+test.ha b/rt/+openbsd/start+test.ha
@@ -0,0 +1,28 @@
+// SPDX-License-Identifier: MPL-2.0
+// (c) Hare authors <https://harelang.org>
+
+// The real main function.
+@symbol(".main") fn main() void;
+
+@symbol("__test_main") fn test_main() size;
+
+// The setup of envp and args is done here. This is called by crt0 before
+// normal init functions are called.
+export @symbol("preinit_hare") fn preinit_hare(
+ c_argc: int,
+ c_argv: *[*]*u8,
+ c_envp: *[*]nullable *u8
+) void = {
+ argc = c_argc: size;
+ argv = c_argv;
+ envp = c_envp;
+};
+
+// The purpose of this "fake" main function is to make sure we exit with the
+// correct exit code in the case that rt::exit() is not called from within the
+// program. The intilization and finilization functions are not run from here,
+// they are ran by crt0.
+export @symbol("main") fn _main() void = {
+ const ret = if (test_main() > 0) 1 else 0;
+ exit(ret);
+};
diff --git a/rt/+openbsd/start.ha b/rt/+openbsd/start.ha
@@ -0,0 +1,26 @@
+// SPDX-License-Identifier: MPL-2.0
+// (c) Hare authors <https://harelang.org>
+
+// The real main function.
+@symbol(".main") fn main() void;
+
+// The setup of envp and args is done here. This is called by crt0 before
+// normal init functions are called.
+export @symbol("preinit_hare") fn preinit_hare(
+ c_argc: int,
+ c_argv: *[*]*u8,
+ c_envp: *[*]nullable *u8
+) void = {
+ argc = c_argc: size;
+ argv = c_argv;
+ envp = c_envp;
+};
+
+// The purpose of this "fake" main function is to make sure we exit with the
+// correct exit code in the case that rt::exit() is not called from within the
+// program. The intilization and finilization functions are not run from here,
+// they are ran by crt0.
+export @symbol("main") fn _main() void = {
+ main();
+ exit(0);
+};
diff --git a/rt/+openbsd/start.s b/rt/+openbsd/start.s
@@ -0,0 +1,4 @@
+.section ".preinit_array"
+.balign 8
+.init.initfunc.0:
+ .quad preinit_hare+0
diff --git a/rt/+openbsd/syscalls.ha b/rt/+openbsd/syscalls.ha
@@ -0,0 +1,1271 @@
+// SPDX-License-Identifier: MPL-2.0
+// (c) Hare authors <https://harelang.org>
+
+let pathbuf: [PATH_MAX]u8 = [0...];
+export type path = (str | []u8 | *const u8);
+
+fn copy_cpath(path: path, buf: []u8) (*const u8 | errno) = {
+ let path = match (path) {
+ case let c: *const u8 =>
+ return c;
+ case let s: str =>
+ let ptr = &s: *struct {
+ buf: *[*]u8,
+ length: size,
+ capacity: size,
+ };
+ yield ptr.buf[..ptr.length];
+ case let b: []u8 =>
+ yield b;
+ };
+ if (len(path) + 1 >= len(buf)) {
+ return ENAMETOOLONG;
+ };
+ memcpy(buf: *[*]u8, path: *[*]u8, len(path));
+ buf[len(path)] = 0;
+ return buf: *[*]u8: *const u8;
+};
+
+// NUL terminates a string and stores it in a static buffer of PATH_MAX bytes in
+// length.
+fn cpath(path: path) (*const u8 | errno) = {
+ return copy_cpath(path, pathbuf);
+};
+
+// /usr/include/errno.h: #define errno (*__errno())
+@symbol("__errno") fn __errno() *int;
+
+// exit
+export @symbol("exit") fn exit(status: int) never;
+
+// fork
+
+@symbol("fork") fn libc_fork() int;
+
+export fn fork() (int | void | errno) = {
+ let res = libc_fork();
+ if (res == -1) {
+ return *__errno(): errno;
+ };
+ if (res == 0) {
+ return;
+ };
+ return res;
+};
+
+// read
+
+@symbol("read") fn libc_read(d: int, buf: *opaque, nbytes: size) size;
+
+export fn read(fd: int, buf: *opaque, count: size) (size | errno) = {
+ let res: u64 = libc_read(fd, buf, count);
+ if (res == -1) {
+ return *__errno(): errno;
+ };
+ return res;
+};
+
+// write
+
+@symbol("write") fn libc_write(d: int, buf: *const opaque, nbytes: size) size;
+
+export fn write(fd: int, buf: *const opaque, count: size) (size | errno) = {
+ let res: u64 = libc_write(fd, buf, count);
+ if (res == -1) {
+ return *__errno(): errno;
+ };
+ return res;
+};
+
+// open
+
+@symbol("open") fn libc_open(path: *opaque, flags: int, mode: int) int;
+
+export fn open(path: path, flags: int, mode: int) (int | errno) = {
+ let res = libc_open(cpath(path)?, flags, mode);
+ if (res == -1) {
+ return *__errno(): errno;
+ };
+ return res;
+};
+
+// posix_openpt (libc function not a syscall)
+
+@symbol("posix_openpt") fn libc_openpt(oflag: int) int;
+
+export fn posix_openpt(flags: int) (int | errno) = {
+ let res = libc_openpt(flags);
+ if (res == -1) {
+ return *__errno(): errno;
+ };
+ return res;
+};
+
+// close
+
+@symbol("close") fn libc_close(d: int) int;
+
+export fn close(fd: int) (void | errno) = {
+ let res = libc_close(fd);
+ if (res == -1) {
+ return *__errno(): errno;
+ };
+};
+
+// getentropy
+// __tfork
+// link
+// unlink
+// wait4
+
+@symbol("wait4") fn libc_wait4(
+ wpid: int,
+ status: nullable *int,
+ options: int,
+ rusage: nullable *rusage
+) int;
+
+export fn wait4(
+ pid: int,
+ wstatus: nullable *int,
+ options: int,
+ rusage: nullable *rusage,
+) (int | errno) = {
+ let res = libc_wait4(pid, wstatus, options, rusage);
+ if (res == -1) {
+ return *__errno(): errno;
+ };
+ return res;
+};
+
+// chdir
+
+@symbol("chdir") fn libc_chdir(path: *const u8) int;
+
+export fn chdir(path: path) (void | errno) = {
+ let res = libc_chdir(cpath(path)?);
+
+ if (res == -1) {
+ return *__errno(): errno;
+ };
+};
+
+// fchdir
+
+@symbol("fchdir") fn libc_fchdir(fd: int) int;
+
+export fn fchdir(fd: int) (void | errno) = {
+ let res = libc_fchdir(fd);
+
+ if (res == -1) {
+ return *__errno(): errno;
+ };
+};
+
+// mknod
+// chmod
+// chown
+// obreak
+// getdtablecount
+// getrusage
+// getpid
+
+export @symbol("getpid") fn getpid() int;
+
+// mount
+// unmount
+// setuid
+
+@symbol("setuid") fn libc_setuid(uid: uid_t) int;
+
+export fn setuid(uid: uid_t) (void | errno) = {
+ let res = libc_setuid(uid);
+ if (res == -1) {
+ return *__errno(): errno;
+ };
+};
+
+// getuid
+
+export @symbol("getuid") fn getuid() uid_t;
+
+// geteuid
+
+export @symbol("geteuid") fn geteuid() uid_t;
+
+// ptrace
+// recvmsg
+
+@symbol("recvmsg") fn libc_recvmsg(s: int, msg: *const msghdr, flags: int) i64;
+
+export fn recvmsg(fd: int, msg: *const msghdr, flags: int) (int | errno) = {
+ let res = libc_recvmsg(fd, msg, flags);
+ if (res == -1) {
+ return *__errno(): errno;
+ };
+ // TODO: could overflow
+ return res: int;
+};
+
+// sendmsg
+
+@symbol("sendmsg") fn libc_sendmsg(s: int, msg: *const msghdr, flags: int) i64;
+
+export fn sendmsg(fd: int, msg: *const msghdr, flags: int) (int | errno) = {
+ let res = libc_sendmsg(fd, msg, flags);
+ if (res == -1) {
+ return *__errno(): errno;
+ };
+ // TODO: could overflow
+ return res: int;
+};
+
+// recvfrom
+
+@symbol("recvfrom") fn libc_recvfrom(
+ s: int,
+ buf: *opaque,
+ length: size,
+ flags: int,
+ from: nullable *sockaddr,
+ fromlen: nullable *u32,
+) i64;
+
+export fn recvfrom(
+ sockfd: int,
+ buf: *opaque,
+ length: size,
+ flags: int,
+ from: nullable *sockaddr,
+ fromlen: nullable *u32
+) (size | errno) = {
+ let res = libc_recvfrom(sockfd, buf, length, flags, from, fromlen);
+ if (res == -1) {
+ return *__errno(): errno;
+ };
+ return res: size;
+};
+
+// accept
+// getpeername
+
+@symbol("getpeername") fn libc_getpeername(
+ s: int,
+ name: *sockaddr,
+ namelen: *u32
+) int;
+
+export fn getpeername(
+ sockfd: int,
+ addr: *sockaddr,
+ addrlen: *u32
+) (void | errno) = {
+ let res = libc_getpeername(sockfd, addr, addrlen);
+ if (res == -1) {
+ return *__errno(): errno;
+ };
+};
+
+// getsockname
+
+@symbol("getsockname") fn libc_getsockname(
+ sockfd: int,
+ addr: nullable *sockaddr,
+ addrlen: nullable *u32
+) int;
+
+export fn getsockname(
+ sockfd: int,
+ addr: nullable *sockaddr,
+ addrlen: nullable *u32
+) (void | errno) = {
+ let res = libc_getsockname(sockfd, addr, addrlen);
+ if (res == -1) {
+ return *__errno(): errno;
+ };
+
+};
+// access
+
+@symbol("access") fn libc_access(path: *const u8, amode: int) int;
+
+export fn access(path: path, amode: int) (bool | errno) = {
+ let res = libc_access(cpath(path)?, amode);
+ if (res == -1) {
+ let err = *__errno(): errno;
+
+ switch (res) {
+ case EACCES =>
+ return false;
+ case =>
+ return err;
+ };
+ };
+
+ return true;
+};
+
+
+// chflags
+// fchflags
+// sync
+// msyscall
+// stat
+// getppid
+// lstat
+// dup
+// fstatat
+
+@symbol("fstatat") fn libc_fstatat(fd: int, path: *const u8, sb: *stat, flag: int) int;
+
+export fn fstatat(
+ dirfd: int,
+ path: path,
+ stat: *stat,
+ flag: int
+) (void | errno) = {
+ let res = libc_fstatat(dirfd, cpath(path)?, stat, flag);
+ if (res == -1) {
+ return *__errno(): errno;
+ };
+};
+
+
+// getegid
+
+export @symbol("getegid") fn getegid() gid_t;
+
+// profil
+// ktrace
+// sigaction
+
+export @symbol("sigaction") fn libc_sigaction(
+ sig: int,
+ act: *const sigact,
+ oact: nullable *sigact
+) int;
+
+export fn sigaction(
+ signum: int,
+ act: *const sigact,
+ old: nullable *sigact,
+) (void | errno) = {
+ let res = libc_sigaction(signum, act, old);
+ if (res == -1) {
+ return *__errno(): errno;
+ };
+};
+// getgid
+
+export @symbol("getgid") fn getgid() gid_t;
+
+// sigprocmask
+
+@symbol("sigprocmask") fn libc_sigprocmask(
+ how: int,
+ set: nullable *const sigset,
+ old: nullable *sigset
+) int;
+
+export fn sigprocmask(
+ how: int,
+ set: nullable *const sigset,
+ old: nullable *sigset
+) (void | errno) = {
+ let res = libc_sigprocmask(how, set, old);
+ if (res == -1) {
+ return *__errno(): errno;
+ };
+};
+
+// mmap
+
+@symbol("mmap") fn libc_mmap(
+ addr: nullable *opaque,
+ len_: size,
+ prot: int,
+ flags: int,
+ fd: int,
+ pos: i64
+) nullable *opaque;
+
+export fn mmap(
+ addr: nullable *opaque,
+ len_: size,
+ prot: int,
+ flags: int,
+ fd: int,
+ pos: i64
+) (*opaque | errno) = {
+ let res = libc_mmap(addr, len_, prot, flags, fd, pos);
+
+ if (res == null) {
+ return *__errno(): errno;
+ };
+ return res: *opaque;
+};
+
+// setlogin
+// acct
+// sigpending
+// fstat
+// ioctl
+
+@symbol("ioctl") fn libc_ioctl(fd: int, req: u64, arg: u64) int;
+
+export type ioctl_arg = (nullable *opaque | u64);
+
+export fn ioctl(fd: int, req: u64, arg: ioctl_arg) (int | errno) = {
+ let res = match (arg) {
+ case let u: u64 =>
+ yield libc_ioctl(fd, req, u);
+ case let ptr: nullable *opaque =>
+ yield libc_ioctl(fd, req, ptr: uintptr: u64);
+ };
+ if (res == -1) {
+ return *__errno(): errno;
+ };
+ return res;
+};
+
+// reboot
+// revoke
+// symlink
+// readlink
+// execve
+
+@symbol("execve") fn libc_execve(path: *const u8, argv: *[*]nullable *const u8,
+ envp: *[*]nullable *const u8) int;
+
+export fn execve(path: path, argv: *[*]nullable *const u8,
+ envp: *[*]nullable *const u8) errno = {
+ let res = libc_execve(cpath(path)?, argv, envp);
+ return *__errno(): errno;
+};
+
+// umask
+
+@symbol("umask") fn libc_umask(numask: mode_t) mode_t;
+
+export fn umask(mode: mode_t) (mode_t | errno) = {
+ // Always successful on OpenBSD.
+ return libc_umask(mode);
+};
+
+// chroot
+
+@symbol("chroot") fn libc_chroot(dirname: *const u8) int;
+
+export fn chroot(path: path) (void | errno) = {
+ let res = libc_chroot(cpath(path)?);
+ if (res == -1) {
+ return *__errno(): errno;
+ };
+};
+
+// getfsstat
+// statfs
+// fstatfs
+// fhstatfs
+// vfork
+// gettimeofday
+// settimeofday
+// setitimer
+// getitimer
+// select
+// kevent
+// munmap
+
+@symbol("munmap") fn libc_munmap(addr: *opaque, len_: size) int;
+
+export fn munmap(addr: *opaque, len_: size) (void | errno) = {
+ let res = munmap(addr, len_);
+ if (res == -1) {
+ return *__errno(): errno;
+ };
+};
+
+// mprotect
+// madvise
+// utimes
+// futimes
+// mquery
+// getgroups
+
+@symbol("getgroups") fn libc_getgroups(gidsetlen: int, gidset: *[*]u32) int;
+
+export fn getgroups(gids: []uint) (uint | errno) = {
+ let res = libc_getgroups(len(gids): int, gids: *[*]u32);
+ if (res == -1) {
+ return *__errno(): errno;
+ };
+ return res: uint;
+};
+
+// setgroups
+
+@symbol("setgroups") fn libc_setgroups(
+ ngroups: int,
+ gidset: *[*]u32
+) int;
+
+export fn setgroups(gids: []uint) (void | errno) = {
+ let res = libc_setgroups(len(gids): int, gids: *[*]u32);
+ if (res == -1) {
+ return *__errno(): errno;
+ };
+};
+
+// getpgrp
+// setpgid
+// futex
+// utimensat
+// futimens
+// kbind
+// clock_gettime
+
+@symbol("clock_gettime") fn libc_clock_gettime(clock: int, now: *timespec) int;
+
+export fn clock_gettime(clock: int, now: *timespec) (void | errno) = {
+ let res = libc_clock_gettime(clock, now);
+ if (res == -1) {
+ return *__errno(): errno;
+ };
+};
+
+// clock_settime
+// clock_getres
+// dup2
+
+@symbol("dup2") fn libc_dup2(oldd: int, newd: int) int;
+
+export fn dup2(oldfd: int, newfd: int) (int | errno) = {
+ let res = libc_dup2(oldfd, newfd);
+ if (res == -1) {
+ return *__errno(): errno;
+ };
+ return res;
+};
+
+// nanosleep
+
+@symbol("nanosleep") fn libc_nanosleep(
+ timeout: *const timespec,
+ remainder: *timespec
+) int;
+
+export fn nanosleep(
+ timeout: *const timespec,
+ remainder: *timespec
+) (void | errno) = {
+ let res = libc_nanosleep(timeout, remainder);
+ if (res == -1) {
+ return *__errno(): errno;
+ };
+};
+
+// fcntl
+
+@symbol("fcntl") fn libc_fcntl(fd: int, cmd: int, arg: u64) int;
+
+export type fcntl_arg = (void | int | *st_flock | *u64);
+
+export fn fcntl(fd: int, cmd: int, arg: fcntl_arg) (int | errno) = {
+ let res = match (arg) {
+ case void =>
+ yield libc_fcntl(fd, cmd, 0);
+ case let i: int =>
+ yield libc_fcntl(fd, cmd, i: u64);
+ case let l: *st_flock =>
+ yield libc_fcntl(fd, cmd, l: uintptr: u64);
+ case let u: *u64 =>
+ yield libc_fcntl(fd, cmd, u: uintptr: u64);
+ };
+ if (res == -1) {
+ return *__errno(): errno;
+ };
+ return res;
+};
+
+// accept4
+
+@symbol("accept4") fn libc_accept4(
+ s: int,
+ addr: nullable *sockaddr,
+ adddrlen: nullable *u32,
+ flags: int
+) int;
+
+export fn accept4(
+ sockfd: int,
+ addr: nullable *sockaddr,
+ addrlen: nullable *u32,
+ flags: int
+) (int | errno) = {
+ let res = libc_accept4(sockfd, addr, addrlen, flags);
+ if (res == -1) {
+ return *__errno(): errno;
+ };
+ return res;
+};
+
+// __thrsleep
+// fsync
+// setpriority
+
+@symbol("setpriority") fn libc_setpriority(
+ which: int,
+ who: id_t,
+ prio: int
+) int;
+
+export fn setpriority(which: int, who: id_t, prio: int) (void | errno) = {
+ let res = libc_setpriority(which, who, prio);
+ if (res == -1) {
+ return *__errno(): errno;
+ };
+};
+
+// socket
+
+@symbol("socket") fn libc_socket(domain: int, t: int, protocol: int) int;
+
+export fn socket(domain: int, t: int, protocol: int) (int | errno) = {
+ let res = libc_socket(domain, t, protocol);
+ if (res == -1) {
+ return *__errno(): errno;
+ };
+ return res;
+};
+
+// connect
+
+@symbol("connect") fn libc_connect(
+ sockfd: int,
+ addr: *const sockaddr,
+ addrlen: u32
+) int;
+
+export fn connect(
+ sockfd: int,
+ addr: *const sockaddr,
+ addrlen: u32
+) (void | errno) = {
+ let res = libc_connect(sockfd, addr, addrlen);
+ if (res == -1) {
+ return *__errno(): errno;
+ };
+};
+
+// getdents
+
+@symbol("getdents") fn libc_getdents(fd: int, buf: *opaque, nbytes: size) int;
+
+export fn getdents(dirfd: int, buf: *opaque, nbytes: size) (int | errno) = {
+ let res = libc_getdents(dirfd, buf, nbytes);
+ if (res == -1) {
+ return *__errno(): errno;
+ };
+ return res;
+};
+
+// getpriority
+
+@symbol("getpriority") fn libc_getpriority(which: int, who: id_t) int;
+
+export fn getpriority(which: int, who: id_t) (int | errno) = {
+ let res = libc_getpriority(which, who);
+ if (res == -1) {
+ return *__errno(): errno;
+ };
+ return res;
+};
+
+// pipe2
+
+@symbol("pipe2") fn libc_pipe2(pipefd: *[2]int, flags: int) int;
+
+export fn pipe2(pipefd: *[2]int, flags: int) (void | errno) = {
+ let res = libc_pipe2(pipefd, flags);
+ if (res == -1) {
+ return *__errno(): errno;
+ };
+};
+
+// dup3
+// sigreturn
+// bind
+
+@symbol("bind") fn libc_bind(
+ sockfd: int,
+ addr: *const sockaddr,
+ addrlen: u32
+) int;
+
+export fn bind(
+ sockfd: int,
+ addr: *const sockaddr,
+ addrlen: u32
+) (void | errno) = {
+ let res = libc_bind(sockfd, addr, addrlen);
+ if (res == -1) {
+ return *__errno(): errno;
+ };
+};
+
+// setsockopt
+
+@symbol("setsockopt") fn libc_setsockopt(
+ s: int,
+ level: int,
+ optname: int,
+ optval: *opaque,
+ optlen: u32
+) int;
+
+export fn setsockopt(
+ sockfd: int,
+ level: int,
+ optname: int,
+ optval: *opaque,
+ optlen: u32
+) (void | errno) = {
+ let res = libc_setsockopt(sockfd, level, optname, optval, optlen);
+ if (res == -1) {
+ return *__errno(): errno;
+ };
+};
+
+// listen
+
+@symbol("listen") fn libc_listen(s: int, backlog: int) int;
+
+// TODO: backlog should be int.
+export fn listen(sockfd: int, backlog: u32) (void | errno) = {
+ let res = libc_listen(sockfd, backlog: int);
+ if (res == -1) {
+ return *__errno(): errno;
+ };
+};
+
+// chflagsat
+// pledge
+// ppoll
+
+@symbol("ppoll") fn libc_ppoll(
+ fds: *[*]pollfd,
+ nfds: nfds_t,
+ timeout: const nullable *timespec,
+ mask: const nullable *sigset,
+) int;
+
+export fn ppoll(
+ fds: *[*]pollfd,
+ nfds: nfds_t,
+ timeout: const nullable *timespec,
+ sigmask: const nullable *sigset,
+) (int | errno) = {
+ let ret = libc_ppoll(fds, nfds, timeout, sigmask);
+
+ if (ret == -1) {
+ return *__errno(): errno;
+ };
+ return ret;
+};
+
+// pselect
+// sigsuspend
+// sendsyslog
+// unveil
+// __realpath
+// recvmmsg
+// sendmmsg
+// getsockopt
+
+@symbol("getsockopt") fn libc_getsockopt(
+ s: int,
+ level: int,
+ optname: int,
+ optval: nullable *opaque,
+ optlen: nullable *u32
+) int;
+
+export fn getsockopt(
+ sockfd: int,
+ level: int,
+ optname: int,
+ optval: nullable *opaque,
+ optlen: nullable *u32
+) (void | errno) = {
+ let res = libc_getsockopt(sockfd, level, optname, optval, optlen);
+ if (res == -1) {
+ return *__errno(): errno;
+ };
+};
+
+// thrkill
+// readv
+
+@symbol("readv") fn libc_readv(d: int, iov: const *[*]iovec, iovcnt: int) size;
+
+export fn readv(fd: int, iov: const *[*]iovec, iovcnt: int) (size | errno) = {
+ let res: u64 = libc_readv(fd, iov, iovcnt);
+
+ if (res == -1) {
+ return *__errno(): errno;
+ };
+ return res;
+};
+
+// writev
+
+@symbol("readv") fn libc_writev(d: int, iov: const *[*]iovec, iovcnt: int) size;
+
+export fn writev(fd: int, iov: const *[*]iovec, iovcnt: int) (size | errno) = {
+ let res: u64 = libc_writev(fd, iov, iovcnt);
+
+ if (res == -1) {
+ return *__errno(): errno;
+ };
+ return res;
+};
+
+// kill
+
+@symbol("kill") fn libc_kill(pid: int, signal: int) int;
+
+export fn kill(pid: int, signal: int) (void | errno) = {
+ let res = libc_kill(pid, signal);
+ if (res == -1) {
+ return *__errno(): errno;
+ };
+};
+
+// fchown
+// fchmod
+// setreuid
+// setregid
+// rename
+// flock
+
+@symbol("flock") fn libc_flock(fd: int, operation: int) int;
+
+export fn flock(fd: int, op: int) (void | errno) = {
+ let res = libc_flock(fd, op);
+ if (res == -1) {
+ return *__errno(): errno;
+ };
+};
+
+// mkfifo
+// sendto
+
+@symbol("sendto") fn libc_sendto(
+ s: int,
+ msg: *opaque,
+ length: size,
+ flags: int,
+ to: nullable *sockaddr,
+ tolen: socklen_t
+) i64;
+
+export fn sendto(
+ sockfd: int,
+ buf: *opaque,
+ length: size,
+ flags: int,
+ dest_addr: nullable *sockaddr,
+ addrlen: u32
+) (size | errno) = {
+ let res = libc_sendto(sockfd, buf, length, flags, dest_addr, addrlen);
+ if (res == -1) {
+ return *__errno(): errno;
+ };
+ return res: size;
+};
+
+// shutdown
+
+@symbol("shutdown") fn libc_shutdown(s: int, how: int) int;
+
+export fn shutdown(s: int, how: int) (void | errno) = {
+ let res = libc_shutdown(s, how);
+ if (res == -1) {
+ return *__errno(): errno;
+ };
+};
+
+// socketpair
+
+@symbol("socketpair") fn libc_socketpair(
+ domain: int,
+ type_: int,
+ protocol: int,
+ sv: *[*]int
+) int;
+
+export fn socketpair(
+ domain: int,
+ type_: int,
+ protocol: int,
+ sv: *[*]int
+) (void | errno) = {
+ let res = libc_socketpair(domain, type_, protocol, sv);
+ if (res == -1) {
+ return *__errno(): errno;
+ };
+
+};
+// mkdir
+// rmdir
+// adjtime
+// getlogin_r
+// getthrname
+// setthrname
+// pinsyscall
+// setsid
+// quotactl
+// ypconnect
+// nfssvc
+// mimmutable
+// waitid
+// getfh
+// __tmpfd
+// sysarch
+// lseek
+
+@symbol("lseek") fn libc_lseek(fildes: int, pos: i64, whence: int) i64;
+
+export fn lseek(fd: int, off: i64, whence: int) (i64 | errno) = {
+ let res = libc_lseek(fd, off, whence);
+ if (res == -1) {
+ return *__errno(): errno;
+ };
+ return res;
+};
+
+// truncate
+// ftruncate
+
+@symbol("ftruncate") fn libc_ftruncate(fd: int, length: i64) int;
+
+export fn ftruncate(fd: int, length: i64) (void | errno) = {
+ let res = libc_ftruncate(fd, length);
+ if (res == -1) {
+ return *__errno(): errno;
+ };
+};
+
+// pread
+// pwrite
+// preadv
+// pwritev
+// setgid
+
+@symbol("setgid") fn libc_setgid(gid: gid_t) int;
+
+export fn setgid(gid: gid_t) (void | errno) = {
+ let res = libc_setgid(gid);
+ if (res == -1) {
+ return *__errno(): errno;
+ };
+};
+
+// setegid
+
+@symbol("setegid") fn libc_setegid(gid: gid_t) int;
+
+export fn setegid(gid: gid_t) (void | errno) = {
+ let res = libc_setegid(gid);
+ if (res == -1) {
+ return *__errno(): errno;
+ };
+};
+
+// seteuid
+
+@symbol("seteuid") fn libc_seteuid(uid: uid_t) int;
+
+export fn seteuid(uid: uid_t) (void | errno) = {
+ let res = libc_seteuid(uid);
+ if (res == -1) {
+ return *__errno(): errno;
+ };
+};
+
+// pathconf
+// fpathconf
+// swapctl
+// getrlimit
+// setrlimit
+// sysctl
+
+@symbol("sysctl") fn libc_sysctl(
+ name: *[*]int,
+ namelen: uint,
+ oldp: nullable *opaque,
+ oldlenp: nullable *size,
+ newp: nullable *opaque,
+ newlen: size
+) int;
+
+export fn sysctl(
+ name: []int,
+ namelen: uint,
+ oldp: nullable *opaque,
+ oldlenp: nullable *size,
+ newp: nullable *opaque,
+ newlen: size
+) (void | errno) = {
+ let res = libc_sysctl(name: *[*]int, namelen, oldp, oldlenp, newp, newlen);
+ if (res == -1) {
+ return *__errno(): errno;
+ };
+};
+
+// mlock
+// munlock
+// getpgid
+// utrace
+// semget
+// msgget
+// msgsnd
+// msgrcv
+// shmat
+// shmdt
+// minherit
+// poll
+// issetugid
+// lchown
+// getsid
+// msync
+// pipe
+// fhopen
+// kqueue
+// kqueue1
+// mlockall
+// munlockall
+// getresuid
+// setresuid
+// getresgid
+// setresgid
+// closefrom
+// sigaltstack
+// shmget
+// semop
+// fhstat
+// __semctl
+// shmctl
+// msgctl
+// sched_yield
+// getthrid
+// __thrwakeup
+// __threxit
+// __thrsigdivert
+// getcwd
+
+@symbol("getcwd") fn libc_getcwd(buf: *u8, bufsz: size) *u8;
+
+export fn getcwd() (*const u8 | errno) = {
+ static let pathbuf: [PATH_MAX]u8 = [0...];
+
+ let res = libc_getcwd(&pathbuf: *u8, len(pathbuf));
+ if (res == null) {
+ return *__errno(): errno;
+ };
+
+ return res;
+};
+
+// adjfreq
+// setrtable
+// getrtable
+// faccessat
+// fchmodat
+
+@symbol("fchmodat") fn libc_fchmodat(
+ fd: int,
+ path: *const u8,
+ mode: mode_t,
+ flag: int
+) int;
+
+export fn fchmodat(
+ dirfd: int,
+ path: path,
+ mode: mode_t,
+ flag: int
+) (void | errno) = {
+ let res = libc_fchmodat(dirfd, cpath(path)?, mode, flag);
+ if (res == -1) {
+ return *__errno(): errno;
+ };
+};
+
+// fchownat
+
+@symbol("fchownat") fn libc_fchownat(
+ fd: int,
+ path: *const u8,
+ owner: uid_t,
+ group: gid_t,
+ flag: int
+) int;
+
+export fn fchownat(
+ dirfd: int,
+ path: path,
+ uid: uid_t,
+ gid: gid_t,
+ flag: int
+) (void | errno) = {
+ let res = libc_fchownat(dirfd, cpath(path)?, uid, gid, flag);
+ if (res == -1) {
+ return *__errno(): errno;
+ };
+};
+
+// linkat
+
+@symbol("linkat") fn libc_linkat(
+ fd1: int,
+ name1: *const u8,
+ fd2: int,
+ name2: *const u8,
+ flag: int
+) int;
+
+export fn linkat(
+ olddirfd: int,
+ oldpath: path,
+ newdirfd: int,
+ newpath: path,
+ flags: int,
+) (void | errno) = {
+ let oldpath = cpath(oldpath)?;
+ static let newpathbuf: [PATH_MAX]u8 = [0...];
+ let newpath = copy_cpath(newpath, newpathbuf)?;
+
+ let res = libc_linkat(olddirfd, oldpath, newdirfd, newpath, flags);
+ if (res == -1) {
+ return *__errno(): errno;
+ };
+};
+
+// mkdirat
+
+@symbol("mkdirat") fn libc_mkdirat(fd: int, path: *const u8, mode: mode_t) int;
+
+export fn mkdirat(dirfd: int, path: path, mode: mode_t) (void | errno) = {
+ let res = libc_mkdirat(dirfd, cpath(path)?, mode);
+ if (res == -1) {
+ return *__errno(): errno;
+ };
+};
+
+// mkfifoat
+// mknodat
+// openat
+
+@symbol("openat") fn libc_openat(
+ fd: int,
+ path: *const u8,
+ flags: int,
+ mode: uint,
+) int;
+
+export fn openat(
+ dirfd: int,
+ path: path,
+ flags: int,
+ mode: uint,
+) (int | errno) = {
+ let res = libc_openat(dirfd, cpath(path)?, flags, mode);
+ if (res == -1) {
+ return *__errno(): errno;
+ };
+ return res;
+};
+
+// readlinkat
+
+@symbol("readlinkat") fn libc_readlinkat(
+ fd: int,
+ path: *const u8,
+ buf: *u8,
+ bufsiz: size
+) i64;
+
+export fn readlinkat(
+ dirfd: int,
+ path: path,
+ buf: []u8,
+) (size | errno) = {
+ let res = libc_readlinkat(dirfd, cpath(path)?, &buf: *u8, len(buf));
+ if (res == -1) {
+ return *__errno(): errno;
+ };
+ return res: size;
+};
+
+// renameat
+
+@symbol("renameat") fn libc_renameat(
+ fromfd: int,
+ from: *const u8,
+ tofd: int,
+ to: *const u8
+) int;
+
+export fn renameat(
+ olddirfd: int,
+ oldpath: str,
+ newdirfd: int,
+ newpath: str,
+) (void | errno) = {
+ static let newpathbuf: [PATH_MAX]u8 = [0...];
+ let newpath = copy_cpath(newpath, newpathbuf)?;
+
+ let res = libc_renameat(olddirfd, cpath(oldpath)?, newdirfd,
+ &newpathbuf: *u8);
+ if (res == -1) {
+ return *__errno(): errno;
+ };
+};
+
+// symlinkat
+
+@symbol("symlinkat") fn libc_symlinkat(
+ name1: *const u8,
+ fd: int,
+ name2: *const u8
+) int;
+
+export fn symlinkat(
+ target: path,
+ newdirfd: int,
+ linkpath: path,
+) (void | errno) = {
+ let target = cpath(target)?;
+ static let linkpathbuf: [PATH_MAX]u8 = [0...];
+ let linkpath = copy_cpath(linkpath, linkpathbuf)?;
+
+ let res = libc_symlinkat(target, newdirfd, linkpath);
+ if (res == -1) {
+ return *__errno(): errno;
+ };
+};
+
+// unlinkat
+
+@symbol("unlinkat") fn libc_unlinkat(fd: int, path: *const u8, flag: int) int;
+
+export fn unlinkat(dirfd: int, path: path, flags: int) (void | errno) = {
+ let res = libc_unlinkat(dirfd, cpath(path)?, flags);
+ if (res == -1) {
+ return *__errno(): errno;
+ };
+};
+
+// __set_tcb
+// __get_tcb
diff --git a/rt/+openbsd/types.ha b/rt/+openbsd/types.ha
@@ -0,0 +1,737 @@
+// SPDX-License-Identifier: MPL-2.0
+// (c) Hare authors <https://harelang.org>
+
+export type time_t = i64;
+export type clock_t = i64;
+export type clockid_t = i32;
+export type suseconds_t = i64;
+export type dev_t = i32;
+export type ino_t = u64;
+export type nlink_t = u32;
+export type id_t = u32;
+export type pid_t = i32;
+export type uid_t = u32;
+export type gid_t = u32;
+export type off_t = i64;
+export type blkcnt_t = i64;
+export type blksize_t = i32;
+export type nfds_t = uint;
+export type mode_t = u32;
+export type sigset = uint;
+
+// Maximum length of a file path including the NUL terminator.
+export def PATH_MAX: size = 1024;
+
+export def PATH_PTMDEV: str = "/dev/ptm";
+export def PTMGET: u64 = 0x40287401;
+
+export type ptmget = struct {
+ cfd: int,
+ sfd: int,
+ cn: [16]u8,
+ sn: [16]u8
+};
+
+export def S_ISUID: mode_t = 0o4000;
+export def S_ISGID: mode_t = 0o2000;
+export def S_ISTXT: mode_t = 0o1000;
+export def S_IRWXU: mode_t = 0o700;
+export def S_IRUSR: mode_t = 0o400;
+export def S_IWUSR: mode_t = 0o200;
+export def S_IXUSR: mode_t = 0o100;
+export def S_IRWXG: mode_t = 0o070;
+export def S_IRGRP: mode_t = 0o040;
+export def S_IWGRP: mode_t = 0o020;
+export def S_IXGRP: mode_t = 0o010;
+export def S_IRWXO: mode_t = 0o007;
+export def S_IROTH: mode_t = 0o004;
+export def S_IWOTH: mode_t = 0o002;
+export def S_IXOTH: mode_t = 0o001;
+export def S_IFMT: mode_t = 0o170000;
+export def S_IFIFO: mode_t = 0o010000;
+export def S_IFCHR: mode_t = 0o020000;
+export def S_IFDIR: mode_t = 0o040000;
+export def S_IFBLK: mode_t = 0o060000;
+export def S_IFREG: mode_t = 0o100000;
+export def S_IFLNK: mode_t = 0o120000;
+export def S_IFSOCK: mode_t = 0o140000;
+export def S_ISVTX: mode_t = 0o001000;
+
+export def O_RDONLY: int = 0x0000;
+export def O_WRONLY: int = 0x0001;
+export def O_RDWR: int = 0x0002;
+export def O_ACCMODE: int = 0x0003;
+export def O_NONBLOCK: int = 0x0004;
+export def O_APPEND: int = 0x0008;
+export def O_SHLOCK: int = 0x0010;
+export def O_EXLOCK: int = 0x0020;
+export def O_ASYNC: int = 0x0040;
+export def O_FSYNC: int = 0x0080;
+export def O_SYNC: int = 0x0080;
+export def O_NOFOLLOW: int = 0x0100;
+export def O_CREAT: int = 0x0200;
+export def O_TRUNC: int = 0x0400;
+export def O_EXCL: int = 0x0800;
+export def O_DSYNC: int = O_SYNC;
+export def O_RSYNC: int = O_SYNC;
+export def O_NOCTTY: int = 0x8000;
+export def O_CLOEXEC: int = 0x10000;
+export def O_DIRECTORY: int = 0x20000;
+
+export def WAIT_ANY: pid_t = -1;
+export def WAIT_MYPGRP: pid_t = 0;
+
+export def WNOHANG: int = 0x01;
+export def WUNTRACED: int = 0x02;
+export def WSTOPPED: int = WUNTRACED;
+export def WEXITED: int = 0x04;
+export def WCONTINUED: int = 0x08;
+export def WNOWAIT: int = 0x10;
+export def WTRAPPED: int = 0x20;
+
+export fn wtermsig(status: int) int = status & 0o177;
+
+export fn wifexited(status: int) bool = wtermsig(status) == 0;
+export fn wexitstatus(status: int) int = (status >> 8) & 0xff;
+
+export fn wifsignaled(status: int) bool =
+ wtermsig(status) != 0o177 && wtermsig(status) != 0;
+
+export type rusage = struct {
+ ru_utime: timeval,
+ ru_stime: timeval,
+ ru_maxrss: i64,
+ ru_ixrss: i64,
+ ru_idrss: i64,
+ ru_isrss: i64,
+ ru_minflt: i64,
+ ru_majflt: i64,
+ ru_nswap: i64,
+ ru_inblock: i64,
+ ru_oublock: i64,
+ ru_msgsnd: i64,
+ ru_msgrcv: i64,
+ ru_nsignals: i64,
+ ru_nvcsw: i64,
+ ru_nivcsw: i64,
+};
+
+export def RUSAGE_SELF: int = 0;
+export def RUSAGE_CHILDREN: int = -1;
+export def RUSAGE_THREAD: int = 1;
+
+export def F_OK: int = 0;
+export def X_OK: int = 0x01;
+export def W_OK: int = 0x02;
+export def R_OK: int = 0x04;
+
+export def AT_FDCWD: int = -100;
+export def AT_EACCESS: int = 0x01;
+export def AT_SYMLINK_NOFOLLOW: int = 0x02;
+export def AT_SYMLINK_FOLLOW: int = 0x04;
+export def AT_REMOVEDIR: int = 0x08;
+
+export def PROT_NONE: int = 0x00;
+export def PROT_READ: int = 0x01;
+export def PROT_WRITE: int = 0x02;
+export def PROT_EXEC: int = 0x04;
+
+export def MAP_SHARED: int = 0x0001;
+export def MAP_PRIVATE: int = 0x0002;
+export def MAP_FIXED: int = 0x0010;
+export def __MAP_NOREPLACE: int = 0x0800;
+export def MAP_ANON: int = 0x1000;
+export def __MAP_NOFAULT: int = 0x2000;
+export def MAP_STACK: int = 0x4000;
+export def MAP_CONCEAL: int = 0x8000;
+
+export def MAP_FLAGMASK: int = 0xfff7;
+
+export def RB_AUTOBOOT: int = 0x00000;
+export def RB_ASKNAME: int = 0x00001;
+export def RB_SINGLE: int = 0x00002;
+export def RB_NOSYNC: int = 0x00004;
+export def RB_HALT: int = 0x00008;
+export def RB_INITNAME: int = 0x00010;
+export def RB_DFLTROOT: int = 0x00020;
+export def RB_KDB: int = 0x00040;
+export def RB_RDONLY: int = 0x00080;
+export def RB_DUMP: int = 0x00100;
+export def RB_MINIROOT: int = 0x00200;
+export def RB_CONFIG: int = 0x00400;
+export def RB_TIMEBAD: int = 0x00800;
+export def RB_POWERDOWN: int = 0x01000;
+export def RB_SERCONS: int = 0x02000;
+export def RB_USERREQ: int = 0x04000;
+export def RB_RESET: int = 0x08000;
+export def RB_GOODRANDOM: int = 0x10000;
+export def RB_UNHIBERNATE: int = 0x20000;
+
+export def NGROUPS_MAX: size = 16;
+
+export type timespec = struct {
+ tv_sec: time_t,
+ tv_nsec: i64,
+};
+
+export def CLOCK_REALTIME: clockid_t = 0;
+export def CLOCK_PROCESS_CPUTIME_ID: clockid_t = 2;
+export def CLOCK_MONOTONIC: clockid_t = 3;
+export def CLOCK_THREAD_CPUTIME_ID: clockid_t = 4;
+export def CLOCK_UPTIME: clockid_t = 5;
+export def CLOCK_BOOTTIME: clockid_t = 6;
+
+export def F_DUPFD: int = 0;
+export def F_GETFD: int = 1;
+export def F_SETFD: int = 2;
+export def F_GETFL: int = 3;
+export def F_SETFL: int = 4;
+export def F_GETOWN: int = 5;
+export def F_SETOWN: int = 6;
+export def F_GETLK: int = 7;
+export def F_SETLK: int = 8;
+export def F_SETLKW: int = 9;
+export def F_DUPFD_CLOEXEC: int = 10;
+export def F_ISATTY: int = 11;
+
+export def FD_CLOEXEC: int = 1;
+
+export def F_RDLCK: i16 = 1;
+export def F_UNLCK: i16 = 2;
+export def F_WRLCK: i16 = 3;
+
+export type st_flock = struct {
+ l_start: off_t,
+ l_len: off_t,
+ l_pid: pid_t,
+ l_type: i16,
+ l_whence: i16,
+};
+
+export type dirent = struct {
+ d_fileno: ino_t,
+ d_off: off_t,
+ d_reclen: u16,
+ d_type: u8,
+ d_namlen: u8,
+ __d_padding: [4]u8,
+ d_name: [*]u8,
+};
+
+export def MAXNAMLEN: size = 255;
+
+export def DT_UNKNOWN: u8 = 0;
+export def DT_FIFO: u8 = 1;
+export def DT_CHR: u8 = 2;
+export def DT_DIR: u8 = 4;
+export def DT_BLK: u8 = 6;
+export def DT_REG: u8 = 8;
+export def DT_LNK: u8 = 10;
+export def DT_SOCK: u8 = 12;
+
+export type pollfd = struct {
+ fd: int,
+ events: i16,
+ revents: i16,
+};
+
+export def POLLIN: i16 = 0x0001;
+export def POLLPRI: i16 = 0x0002;
+export def POLLOUT: i16 = 0x0004;
+export def POLLERR: i16 = 0x0008;
+export def POLLHUP: i16 = 0x0010;
+export def POLLNVAL: i16 = 0x0020;
+export def POLLRDNORM: i16 = 0x0040;
+export def POLLNORM: i16 = POLLRDNORM;
+export def POLLWRNORM: i16 = POLLOUT;
+export def POLLRDBAND: i16 = 0x0080;
+export def POLLWRBAND: i16 = 0x0100;
+
+export type iovec = struct {
+ iov_base: *opaque,
+ iov_len: size,
+};
+
+export def NSIG: int = 32;
+
+export type sigact = struct {
+ union {
+ sa_handler: *fn (int) void,
+ sa_sigaction: *fn (int, *siginfo, *opaque) void,
+ },
+ sa_mask: sigset,
+ sa_flags: int,
+};
+
+export type siginfo = struct {
+ si_signo: int,
+ si_code: int,
+ si_errno: int,
+ _data: union {
+ _pad: [128/4 - 3]int,
+ _proc: struct {
+ _pid: pid_t,
+ _uid: uid_t,
+ _pdata: union {
+ _kill: struct {
+ _value: sigval,
+ },
+ _cid: struct {
+ _utime: clock_t,
+ _stime: clock_t,
+ _status: int
+ },
+ },
+ },
+ _fault: struct {
+ _addr: nullable *opaque,
+ _trapno: int,
+ },
+ },
+};
+
+export type sigval = union {
+ sival_int: int,
+ sival_ptr: *opaque,
+};
+
+export type timeval = struct {
+ tv_sec: time_t,
+ tv_usec: suseconds_t,
+};
+
+export type stat = struct {
+ st_mode: mode_t,
+ st_dev: dev_t,
+ st_ino: ino_t,
+ st_nlink: nlink_t,
+ st_uid: uid_t,
+ st_gid: gid_t,
+ st_rdev: dev_t,
+ st_atim: timespec,
+ st_mtim: timespec,
+ st_ctim: timespec,
+ st_size: off_t,
+ st_blocks: blkcnt_t,
+ st_blksize: blksize_t,
+ st_flags: u32,
+ st_gen: u32,
+ st_birthtim: timespec,
+};
+
+export type winsize = struct {
+ ws_row: u16,
+ ws_col: u16,
+ ws_xpixel: u16,
+ ws_ypixel: u16,
+};
+
+export type termios = struct {
+ c_iflag: tcflag,
+ c_oflag: tcflag,
+ c_cflag: tcflag,
+ c_lflag: tcflag,
+ c_cc: [NCCS]cc,
+};
+
+export def NCCS: size = 20;
+
+export type tcflag = enum uint {
+ // c_iflag bits
+ IGNBRK = 0x00000001,
+ BRKINT = 0x00000002,
+ IGNPAR = 0x00000004,
+ PARMRK = 0x00000008,
+ INPCK = 0x00000010,
+ ISTRIP = 0x00000020,
+ INLCR = 0x00000040,
+ IGNCR = 0x00000080,
+ ICRNL = 0x00000100,
+ IXON = 0x00000200,
+ IXOFF = 0x00000400,
+ IXANY = 0x00000800,
+ IMAXBEL = 0x00002000,
+
+ // c_oflag bits
+ OPOST = 0x00000001,
+ ONLCR = 0x00000002,
+ TABDLY = 0x00000004,
+ TAB0 = 0x00000000,
+ TAB3 = 0x00000004,
+ ONOEOT = 0x00000008,
+ OCRNL = 0x00000010,
+ ONOCR = 0x00000020,
+ ONLRET = 0x00000040,
+
+ // c_cflag bits
+ CIGNORE = 0x00000001,
+ CSIZE = 0x00000300,
+ CS5 = 0x00000000,
+ CS6 = 0x00000100,
+ CS7 = 0x00000200,
+ CS8 = 0x00000300,
+ CSTOPB = 0x00000400,
+ CREAD = 0x00000800,
+ PARENB = 0x00001000,
+ PARODD = 0x00002000,
+ HUPCL = 0x00004000,
+ CLOCAL = 0x00008000,
+ CCTS_OFLOW = 0x00010000,
+ CRTS_IFLOW = 0x00020000,
+ CRTSCTS = (CCTS_OFLOW | CRTS_IFLOW),
+ CDTR_IFLOW = 0x00040000,
+ CDSR_OFLOW = 0x00080000,
+ CCAR_OFLOW = 0x00100000,
+ CNO_RTSDTR = 0x00200000,
+
+ // c_lflag bits
+ ECHOKE = 0x00000001,
+ ECHOE = 0x00000002,
+ ECHOK = 0x00000004,
+ ECHO = 0x00000008,
+ ECHONL = 0x00000010,
+ ECHOPRT = 0x00000020,
+ ECHOCTL = 0x00000040,
+ ISIG = 0x00000080,
+ ICANON = 0x00000100,
+ ALTWERASE = 0x00000200,
+ IEXTEN = 0x00000400,
+ EXTPROC = 0x00000800,
+ TOSTOP = 0x00400000,
+ FLUSHO = 0x00800000,
+ NOKERNINFO = 0x02000000,
+ PENDIN = 0x20000000,
+ NOFLSH = 0x80000000,
+};
+
+export type cc = enum u8 {
+ VEOF = 0,
+ VEOL = 1,
+ VEOL2 = 2,
+ VERASE = 3,
+ VWERASE = 4,
+ VKILL = 5,
+ VREPRINT = 6,
+ VERASE2 = 7,
+ VINTR = 8,
+ VQUIT = 9,
+ VSUSP = 10,
+ VDSUSP = 11,
+ VSTART = 12,
+ VSTOP = 13,
+ VLNEXT = 14,
+ VDISCARD = 15,
+ VMIN = 16,
+ VTIME = 17,
+ VSTATUS = 18,
+};
+
+export def TIOCGWINSZ: u64 = 0x40087468;
+export def TIOCSWINSZ: u64 = 0x80087467;
+export def TIOCGETA: u64 = 0x402c7413;
+export def TIOCSETA: u64 = 0x802c7414;
+
+export def SIG_DFL: uintptr = 0;
+export def SIG_IGN: uintptr = 1;
+
+export def SIG_BLOCK: int = 1;
+export def SIG_UNBLOCK: int = 2;
+export def SIG_SETMASK: int = 3;
+
+export def SA_ONSTACK: int = 0x0001;
+export def SA_RESTART: int = 0x0002;
+export def SA_RESETHAND: int = 0x0004;
+export def SA_NOCLDSTOP: int = 0x0008;
+export def SA_NODEFER: int = 0x0010;
+export def SA_NOCLDWAIT: int = 0x0020;
+export def SA_SIGINFO: u64 = 0x0040;
+
+export def SIGHUP: int = 1;
+export def SIGINT: int = 2;
+export def SIGQUIT: int = 3;
+export def SIGILL: int = 4;
+export def SIGTRAP: int = 5;
+export def SIGABRT: int = 6;
+export def SIGEMT: int = 7;
+export def SIGFPE: int = 8;
+export def SIGKILL: int = 9;
+export def SIGBUS: int = 10;
+export def SIGSEGV: int = 11;
+export def SIGSYS: int = 12;
+export def SIGPIPE: int = 13;
+export def SIGALRM: int = 14;
+export def SIGTERM: int = 15;
+export def SIGURG: int = 16;
+export def SIGSTOP: int = 17;
+export def SIGTSTP: int = 18;
+export def SIGCONT: int = 19;
+export def SIGCHLD: int = 20;
+export def SIGTTIN: int = 21;
+export def SIGTTOU: int = 22;
+export def SIGIO: int = 23;
+export def SIGXCPU: int = 24;
+export def SIGXFSZ: int = 25;
+export def SIGVTALRM: int = 26;
+export def SIGPROF: int = 27;
+export def SIGWINCH: int = 28;
+export def SIGINFO: int = 29;
+export def SIGUSR1: int = 30;
+export def SIGUSR2: int = 31;
+export def SIGTHR: int = 32;
+
+export def PRIO_PROCESS: int = 0;
+export def PRIO_PGRP: int = 1;
+export def PRIO_USER: int = 2;
+
+export def STDIN_FILENO: int = 0;
+export def STDOUT_FILENO: int = 1;
+export def STDERR_FILENO: int = 2;
+
+export def SEEK_SET: int = 0;
+export def SEEK_CUR: int = 1;
+export def SEEK_END: int = 2;
+
+export def LOCK_SH: int = 1;
+export def LOCK_EX: int = 2;
+export def LOCK_NB: int = 4;
+export def LOCK_UN: int = 8;
+
+// sysctl
+export def CTL_KERN: int = 1;
+export def CTL_VM: int = 2;
+export def CTL_FS: int = 3;
+export def CTL_NET: int = 4;
+export def CTL_DEBUG: int = 5;
+export def CTL_HW: int = 6;
+export def CTL_MACHDEP: int = 7;
+export def CTL_DDB: int = 9;
+export def CTL_VFS: int = 10;
+
+export def KERN_OSTYPE: int = 1;
+export def KERN_OSRELEASE: int = 2;
+export def KERN_OSREV: int = 3;
+export def KERN_VERSION: int = 4;
+export def KERN_MAXVNODES: int = 5;
+export def KERN_MAXPROC: int = 6;
+export def KERN_MAXFILES: int = 7;
+export def KERN_ARGMAX: int = 8;
+export def KERN_SECURELVL: int = 9;
+export def KERN_HOSTNAME: int = 10;
+export def KERN_HOSTID: int = 11;
+export def KERN_CLOCKRATE: int = 12;
+export def KERN_PROF: int = 16;
+export def KERN_POSIX1: int = 17;
+export def KERN_NGROUPS: int = 18;
+export def KERN_JOB_CONTROL: int = 19;
+export def KERN_SAVED_IDS: int = 20;
+export def KERN_BOOTTIME: int = 21;
+export def KERN_DOMAINNAME: int = 22;
+export def KERN_MAXPARTITIONS: int = 23;
+export def KERN_RAWPARTITION: int = 24;
+export def KERN_MAXTHREAD: int = 25;
+export def KERN_NTHREADS: int = 26;
+export def KERN_OSVERSION: int = 27;
+export def KERN_SOMAXCONN: int = 28;
+export def KERN_SOMINCONN: int = 29;
+export def KERN_NOSUIDCOREDUMP: int = 32;
+export def KERN_FSYNC: int = 33;
+export def KERN_SYSVMSG: int = 34;
+export def KERN_SYSVSEM: int = 35;
+export def KERN_SYSVSHM: int = 36;
+export def KERN_MSGBUFSIZE: int = 38;
+export def KERN_MALLOCSTATS: int = 39;
+export def KERN_CPTIME: int = 40;
+export def KERN_NCHSTATS: int = 41;
+export def KERN_FORKSTAT: int = 42;
+export def KERN_TTY: int = 44;
+export def KERN_CCPU: int = 45;
+export def KERN_FSCALE: int = 46;
+export def KERN_NPROCS: int = 47;
+export def KERN_MSGBUF: int = 48;
+export def KERN_POOL: int = 49;
+export def KERN_STACKGAPRANDOM: int = 50;
+export def KERN_SYSVIPC_INFO: int = 51;
+export def KERN_ALLOWKMEM: int = 52;
+export def KERN_WITNESSWATCH: int = 53;
+export def KERN_SPLASSERT: int = 54;
+export def KERN_PROC_ARGS: int = 55;
+export def KERN_NFILES: int = 56;
+export def KERN_TTYCOUNT: int = 57;
+export def KERN_NUMVNODES: int = 58;
+export def KERN_MBSTAT: int = 59;
+export def KERN_WITNESS: int = 60;
+export def KERN_SEMINFO: int = 61;
+export def KERN_SHMINFO: int = 62;
+export def KERN_INTRCNT: int = 63;
+export def KERN_WATCHDOG: int = 64;
+export def KERN_ALLOWDT: int = 65;
+export def KERN_PROC: int = 66;
+export def KERN_MAXCLUSTERS: int = 67;
+export def KERN_EVCOUNT: int = 68;
+export def KERN_TIMECOUNTER: int = 69;
+export def KERN_MAXLOCKSPERUID: int = 70;
+export def KERN_CPTIME2: int = 71;
+export def KERN_CACHEPCT: int = 72;
+export def KERN_FILE: int = 73;
+export def KERN_WXABORT: int = 74;
+export def KERN_CONSDEV: int = 75;
+export def KERN_NETLIVELOCKS: int = 76;
+export def KERN_POOL_DEBUG: int = 77;
+export def KERN_PROC_CWD: int = 78;
+export def KERN_PROC_NOBROADCASTKILL: int = 79;
+export def KERN_PROC_VMMAP: int = 80;
+export def KERN_GLOBAL_PTRACE: int = 81;
+export def KERN_CONSBUFSIZE: int = 82;
+export def KERN_CONSBUF: int = 83;
+export def KERN_AUDIO: int = 84;
+export def KERN_CPUSTATS: int = 85;
+export def KERN_PFSTATUS: int = 86;
+export def KERN_TIMEOUT_STATS: int = 87;
+export def KERN_UTC_OFFSET: int = 88;
+export def KERN_VIDEO: int = 89;
+export def KERN_CLOCKINTR: int = 90;
+export def KERN_AUTOCONF_SERIAL: int = 91;
+export def KERN_MAXID: int = 92;
+
+export def KERN_PROC_ALL: int = 0;
+export def KERN_PROC_PID: int = 1;
+export def KERN_PROC_PGRP: int = 2;
+export def KERN_PROC_SESSION: int = 3;
+export def KERN_PROC_TTY: int = 4;
+export def KERN_PROC_UID: int = 5;
+export def KERN_PROC_RUID: int = 6;
+export def KERN_PROC_KTHREAD: int = 7;
+export def KERN_PROC_SHOW_THREADS: int = 0x40000000;
+
+export def KERN_SYSVIPC_MSG_INFO: int = 1;
+export def KERN_SYSVIPC_SEM_INFO: int = 2;
+export def KERN_SYSVIPC_SHM_INFO: int = 3;
+
+export def KERN_PROC_ARGV: int = 1;
+export def KERN_PROC_NARGV: int = 2;
+export def KERN_PROC_ENV: int = 3;
+export def KERN_PROC_NENV: int = 4;
+
+export def KERN_AUDIO_RECORD: int = 1;
+export def KERN_AUDIO_MAXID: int = 2;
+
+export def KERN_VIDEO_RECORD: int = 1;
+export def KERN_VIDEO_MAXID: int = 2;
+
+export def KERN_FILE_BYFILE: int = 1;
+export def KERN_FILE_BYPID: int = 2;
+export def KERN_FILE_BYUID: int = 3;
+export def KERN_FILESLOP: int = 10;
+
+export def KERN_FILE_TEXT: int = -1;
+export def KERN_FILE_CDIR: int = -2;
+export def KERN_FILE_RDIR: int = -3;
+export def KERN_FILE_TRACE: int = -4;
+
+export def KI_MNAMELEN: int = 96;
+export def KI_UNPPATHLEN: int = 104;
+
+export def KERN_INTRCNT_NUM: int = 1;
+export def KERN_INTRCNT_CNT: int = 2;
+export def KERN_INTRCNT_NAME: int = 3;
+export def KERN_INTRCNT_VECTOR: int = 4;
+export def KERN_INTRCNT_MAXID: int = 5;
+
+export def KERN_WATCHDOG_PERIOD: int = 1;
+export def KERN_WATCHDOG_AUTO: int = 2;
+export def KERN_WATCHDOG_MAXID: int = 3;
+
+export def KERN_TIMECOUNTER_TICK: int = 1;
+export def KERN_TIMECOUNTER_TIMESTEPWARNINGS: int = 2;
+export def KERN_TIMECOUNTER_HARDWARE: int = 3;
+export def KERN_TIMECOUNTER_CHOICE: int = 4;
+export def KERN_TIMECOUNTER_MAXID: int = 5;
+
+export def KERN_CLOCKINTR_STATS: int = 1;
+export def KERN_CLOCKINTR_MAXID: int = 2;
+
+export def FS_POSIX: int = 1;
+export def FS_MAXID: int = 2;
+
+export def FS_POSIX_SETUID: int = 1;
+export def FS_POSIX_MAXID: int = 2;
+
+export def HW_MACHINE: int = 1;
+export def HW_MODEL: int = 2;
+export def HW_NCPU: int = 3;
+export def HW_BYTEORDER: int = 4;
+export def HW_PHYSMEM: int = 5;
+export def HW_USERMEM: int = 6;
+export def HW_PAGESIZE: int = 7;
+export def HW_DISKNAMES: int = 8;
+export def HW_DISKSTATS: int = 9;
+export def HW_DISKCOUNT: int = 10;
+export def HW_SENSORS: int = 11;
+export def HW_CPUSPEED: int = 12;
+export def HW_SETPERF: int = 13;
+export def HW_VENDOR: int = 14;
+export def HW_PRODUCT: int = 15;
+export def HW_VERSION: int = 16;
+export def HW_SERIALNO: int = 17;
+export def HW_UUID: int = 18;
+export def HW_PHYSMEM64: int = 19;
+export def HW_USERMEM64: int = 20;
+export def HW_NCPUFOUND: int = 21;
+export def HW_ALLOWPOWERDOWN: int = 22;
+export def HW_PERFPOLICY: int = 23;
+export def HW_SMT: int = 24;
+export def HW_NCPUONLINE: int = 25;
+export def HW_POWER: int = 26;
+export def HW_BATTERY: int = 27;
+export def HW_UCOMNAMES: int = 28;
+export def HW_MAXID: int = 30;
+
+export def HW_BATTERY_CHARGEMODE: int = 1;
+export def HW_BATTERY_CHARGESTART: int = 2;
+export def HW_BATTERY_CHARGESTOP: int = 3;
+export def HW_BATTERY_MAXID: int = 4;
+
+export def CTL_DEBUG_NAME: int = 0;
+export def CTL_DEBUG_VALUE: int = 1;
+export def CTL_DEBUG_MAXID: int = 20;
+
+export def SI_NOINFO: int = 32767;
+export def SI_USER: int = 0;
+export def SI_LWP: int = -1;
+export def SI_QUEUE: int = -2;
+export def SI_TIMER: int = -3;
+
+export def ILL_ILLOPC: int = 1;
+export def ILL_ILLOPN: int = 2;
+export def ILL_ILLADR: int = 3;
+export def ILL_ILLTRP: int = 4;
+export def ILL_PRVOPC: int = 5;
+export def ILL_PRVREG: int = 6;
+export def ILL_COPROC: int = 7;
+export def ILL_BADSTK: int = 8;
+
+export def FPE_INTDIV: int = 1;
+export def FPE_INTOVF: int = 2;
+export def FPE_FLTDIV: int = 3;
+export def FPE_FLTOVF: int = 4;
+export def FPE_FLTUND: int = 5;
+export def FPE_FLTRES: int = 6;
+export def FPE_FLTINV: int = 7;
+export def FPE_FLTSUB: int = 8;
+
+export def SEGV_MAPERR: int = 1;
+export def SEGV_ACCERR: int = 2;
+
+export def BUS_ADRALN: int = 1;
+export def BUS_ADRERR: int = 2;
+export def BUS_OBJERR: int = 3;
+
+export def TRAP_BRKPT: int = 1;
+export def TRAP_TRACE: int = 2;
+
+export def CLD_EXITED: int = 1;
+export def CLD_KILLED: int = 2;
+export def CLD_DUMPED: int = 3;
+export def CLD_TRAPPED: int = 4;
+export def CLD_STOPPED: int = 5;
+export def CLD_CONTINUED: int = 6;