Kaynağa Gözat

Haiku: more posix

avanspector 8 ay önce
ebeveyn
işleme
5d3a069e7a

+ 1 - 1
core/c/libc/time.odin

@@ -95,7 +95,7 @@ when ODIN_OS == .Linux || ODIN_OS == .FreeBSD || ODIN_OS == .Darwin || ODIN_OS =
 
 	time_t :: distinct i64
 
-	when ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD {
+	when ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD || ODIN_OS == .Haiku {
 		clock_t :: distinct int32_t
 	} else {
 		clock_t :: distinct long

+ 19 - 7
core/sys/haiku/os.odin

@@ -2,7 +2,7 @@
 package sys_haiku
 
 import "base:intrinsics"
-import "core:c"
+import "core:sys/posix"
 
 foreign import libroot "system:c"
 
@@ -74,7 +74,7 @@ foreign libroot {
 	resize_area         :: proc(id: area_id, newSize: uintptr) -> status_t ---
 	set_area_protection :: proc(id: area_id, newProtection: area_protection_flags) -> status_t ---
 	_get_area_info      :: proc(id: area_id, areaInfo: ^area_info, size: uintptr) -> status_t ---
-	_get_next_area_info :: proc(team: team_id, cookie: ^c.ssize_t, areaInfo: ^area_info, size: uintptr) -> status_t ---
+	_get_next_area_info :: proc(team: team_id, cookie: ^int, areaInfo: ^area_info, size: uintptr) -> status_t ---
 }
 
 // Ports
@@ -99,15 +99,15 @@ port_flags :: distinct bit_set[port_flag; u32]
 foreign libroot {
 	create_port          :: proc(capacity: i32, name: cstring) -> port_id ---
 	find_port            :: proc(name: cstring) -> port_id ---
-	read_port            :: proc(port: port_id, code: ^i32, buffer: rawptr, bufferSize: uintptr) -> c.ssize_t ---
-	read_port_etc        :: proc(port: port_id, code: ^i32, buffer: rawptr, bufferSize: uintptr, flags: port_flags, timeout: bigtime_t) -> c.ssize_t ---
+	read_port            :: proc(port: port_id, code: ^i32, buffer: rawptr, bufferSize: uintptr) -> int ---
+	read_port_etc        :: proc(port: port_id, code: ^i32, buffer: rawptr, bufferSize: uintptr, flags: port_flags, timeout: bigtime_t) -> int ---
 	write_port           :: proc(port: port_id, code: i32, buffer: rawptr, bufferSize: uintptr) -> status_t ---
 	write_port_etc       :: proc(port: port_id, code: i32, buffer: rawptr, bufferSize: uintptr, flags: port_flags, timeout: bigtime_t) -> status_t ---
 	close_port           :: proc(port: port_id) -> status_t ---
 	delete_port          :: proc(port: port_id) -> status_t ---
-	port_buffer_size     :: proc(port: port_id) -> c.ssize_t ---
-	port_buffer_size_etc :: proc(port: port_id, flags: port_flags, timeout: bigtime_t) -> c.ssize_t ---
-	port_count           :: proc(port: port_id) -> c.ssize_t ---
+	port_buffer_size     :: proc(port: port_id) -> int ---
+	port_buffer_size_etc :: proc(port: port_id, flags: port_flags, timeout: bigtime_t) -> int ---
+	port_count           :: proc(port: port_id) -> int ---
 	set_port_owner       :: proc(port: port_id, team: team_id) -> status_t ---
 	_get_port_info       :: proc(port: port_id, portInfo: ^port_info, portInfoSize: uintptr) -> status_t ---
 	_get_next_port_info  :: proc(team: team_id, cookie: ^i32, portInfo: ^port_info, portInfoSize: uintptr) -> status_t ---
@@ -484,3 +484,15 @@ foreign libroot {
 	is_computer_on      :: proc() -> i32 ---
 	is_computer_on_fire :: proc() -> f64 ---
 }
+
+// POSIX signals
+
+@(default_calling_convention="c")
+foreign libroot {
+	/*
+	Wait for queued signals.
+
+	[[ More; https://pubs.opengroup.org/onlinepubs/9699919799/functions/sigtimedwait.html ]]
+	*/
+	sigtimedwait :: proc(set: ^posix.sigset_t, info: ^posix.siginfo_t, timeout: ^posix.timespec) -> posix.result ---
+}

+ 3 - 1
core/sys/posix/arpa_inet.odin

@@ -1,10 +1,12 @@
-#+build darwin, linux, freebsd, openbsd, netbsd
+#+build darwin, linux, freebsd, openbsd, netbsd, haiku
 package posix
 
 import "core:c"
 
 when ODIN_OS == .Darwin {
 	foreign import lib "system:System.framework"
+} else when ODIN_OS == .Haiku {
+	foreign import lib "system:network"
 } else {
 	foreign import lib "system:c"
 }

+ 19 - 8
core/sys/posix/dirent.odin

@@ -1,4 +1,4 @@
-#+build darwin, linux, freebsd, openbsd, netbsd
+#+build darwin, linux, freebsd, openbsd, netbsd, haiku
 package posix
 
 import "core:c"
@@ -219,12 +219,23 @@ when ODIN_OS == .Darwin {
 
 } else when ODIN_OS == .Linux {
 
-		dirent :: struct {
-			d_ino:    u64,                     /* [PSX] file number of entry */
-			d_off:    i64,                     /* directory offset of the next entry */
-			d_reclen: u16,                     /* length of this record */
-			d_type:   D_Type,                  /* file type  */
-			d_name:   [256]c.char `fmt:"s,0"`, /* [PSX] entry name */
-		}
+	dirent :: struct {
+		d_ino:    u64,                     /* [PSX] file number of entry */
+		d_off:    i64,                     /* directory offset of the next entry */
+		d_reclen: u16,                     /* length of this record */
+		d_type:   D_Type,                  /* file type  */
+		d_name:   [256]c.char `fmt:"s,0"`, /* [PSX] entry name */
+	}
+
+} else when ODIN_OS == .Haiku {
+
+	dirent :: struct {
+		d_dev:    dev_t,                 /* device */
+		d_pdev:   dev_t,                 /* parent device (only for queries) */
+		d_ino:    ino_t,                 /* inode number */
+		d_pino:   ino_t,                 /* parent inode (only for queries) */
+		d_reclen: c.ushort,              /* length of this record, not the name */
+		d_name:   [0]c.char `fmt:"s,0"`, /* name of the entry (null byte terminated) */
+	}
 
 }

+ 2 - 2
core/sys/posix/fnmatch.odin

@@ -1,4 +1,4 @@
-#+build darwin, linux, openbsd, freebsd, netbsd
+#+build darwin, linux, openbsd, freebsd, netbsd, haiku
 package posix
 
 import "core:c"
@@ -46,7 +46,7 @@ FNM_Flag_Bits :: enum c.int {
 }
 FNM_Flags :: bit_set[FNM_Flag_Bits; c.int]
 
-when ODIN_OS == .Darwin || ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD || ODIN_OS == .OpenBSD {
+when ODIN_OS == .Darwin || ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD || ODIN_OS == .OpenBSD || ODIN_OS == .Haiku {
 
 	FNM_NOMATCH  :: 1
 

+ 3 - 3
core/sys/posix/glob.odin

@@ -1,4 +1,4 @@
-#+build linux, darwin, netbsd, openbsd, freebsd
+#+build linux, darwin, netbsd, openbsd, freebsd, haiku
 package posix
 
 import "core:c"
@@ -109,7 +109,7 @@ when ODIN_OS == .Darwin {
 	GLOB_NOMATCH :: -3
 	GLOB_NOSPACE :: -1
 
-} else when ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD {
+} else when ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD || ODIN_OS == .Haiku {
 
 	glob_t :: struct {
 		gl_pathc:  c.size_t,                      /* [PSX] count of paths matched by pattern */
@@ -134,7 +134,7 @@ when ODIN_OS == .Darwin {
 	GLOB_ERR      :: 0x0004
 	GLOB_MARK     :: 0x0008
 	GLOB_NOCHECK  :: 0x0010
-	GLOB_NOESCAPE :: 0x2000 when ODIN_OS == .FreeBSD else 0x0100
+	GLOB_NOESCAPE :: 0x2000 when ODIN_OS == .FreeBSD || ODIN_OS == .Haiku else 0x0100
 	GLOB_NOSORT   :: 0x0020
 
 	GLOB_ABORTED :: -2

+ 3 - 3
core/sys/posix/langinfo.odin

@@ -1,4 +1,4 @@
-#+build linux, darwin, netbsd, openbsd, freebsd
+#+build linux, darwin, netbsd, openbsd, freebsd, haiku
 package posix
 
 import "core:c"
@@ -143,7 +143,7 @@ nl_item :: enum nl_item_t {
 	CRNCYSTR    = CRNCYSTR,
 }
 
-when ODIN_OS == .Darwin || ODIN_OS == .FreeBSD {
+when ODIN_OS == .Darwin || ODIN_OS == .FreeBSD || ODIN_OS == .Haiku {
 
 	// NOTE: declared with `_t` so we can enumerate the real `nl_info`.
 	nl_item_t :: distinct c.int
@@ -210,7 +210,7 @@ when ODIN_OS == .Darwin || ODIN_OS == .FreeBSD {
 	YESEXPR :: 52
 	NOEXPR  :: 53
 
-	CRNCYSTR :: 56
+	CRNCYSTR :: 54 when ODIN_OS == .Haiku else 56
 
 } else when ODIN_OS == .NetBSD || ODIN_OS == .OpenBSD {
 

+ 1 - 1
core/sys/posix/libgen.odin

@@ -1,4 +1,4 @@
-#+build linux, darwin, netbsd, openbsd, freebsd
+#+build linux, darwin, netbsd, openbsd, freebsd, haiku
 package posix
 
 when ODIN_OS == .Darwin {

+ 1 - 1
core/sys/posix/locale.odin

@@ -1,4 +1,4 @@
-#+build windows, linux, darwin, netbsd, openbsd, freebsd
+#+build windows, linux, darwin, netbsd, openbsd, freebsd, haiku
 package posix
 
 import "core:c/libc"

+ 1 - 1
core/sys/posix/monetary.odin

@@ -1,4 +1,4 @@
-#+build linux, darwin, netbsd, openbsd, freebsd
+#+build linux, darwin, netbsd, openbsd, freebsd, haiku
 package posix
 
 import "core:c"

+ 19 - 2
core/sys/posix/netdb.odin

@@ -1,4 +1,4 @@
-#+build linux, darwin, netbsd, openbsd, freebsd
+#+build linux, darwin, netbsd, openbsd, freebsd, haiku
 package posix
 
 import "core:c"
@@ -319,7 +319,7 @@ Info_Errno :: enum c.int {
 	OVERFLOW = EAI_OVERFLOW,
 }
 
-when ODIN_OS == .Darwin || ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD || ODIN_OS == .OpenBSD || ODIN_OS == .OpenBSD || ODIN_OS == .Linux {
+when ODIN_OS == .Darwin || ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD || ODIN_OS == .OpenBSD || ODIN_OS == .OpenBSD || ODIN_OS == .Linux || ODIN_OS == .Haiku {
 
 	hostent :: struct {
 		h_name:      cstring,                /* [PSX] official name of host */
@@ -431,6 +431,23 @@ when ODIN_OS == .Darwin || ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD || ODIN_OS
 		NI_NUMERICSCOPE :: 0x100
 		NI_DGRAM        :: 16
 
+	} else when ODIN_OS == .Haiku {
+
+		AI_PASSIVE     :: 0x001
+		AI_CANONNAME   :: 0x002
+		AI_NUMERICHOST :: 0x004
+		AI_NUMERICSERV :: 0x008
+		AI_V4MAPPED    :: 0x800
+		AI_ALL         :: 0x100
+		AI_ADDRCONFIG  :: 0x400
+
+		NI_NOFQDN       :: 0x01
+		NI_NUMERICHOST  :: 0x02
+		NI_NAMEREQD     :: 0x04
+		NI_NUMERICSERV  :: 0x08
+		NI_DGRAM        :: 0x10
+		NI_NUMERICSCOPE :: 0x40
+
 	}
 
 	when ODIN_OS == .OpenBSD {

+ 45 - 16
core/sys/posix/netinet_in.odin

@@ -1,4 +1,4 @@
-#+build linux, darwin, netbsd, openbsd, freebsd
+#+build linux, darwin, netbsd, openbsd, freebsd, haiku
 package posix
 
 import "core:c"
@@ -31,20 +31,31 @@ Protocol :: enum c.int {
 	UDP  = IPPROTO_UDP,
 }
 
-when ODIN_OS == .Darwin || ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD || ODIN_OS == .OpenBSD || ODIN_OS == .Linux {
+when ODIN_OS == .Darwin || ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD || ODIN_OS == .OpenBSD || ODIN_OS == .Linux || ODIN_OS == .Haiku {
 
 	in_addr :: struct {
 		s_addr: in_addr_t, /* [PSX] big endian address */
 	}
 
-	in6_addr :: struct {
-		using _: struct #raw_union {
-			s6_addr:     [16]c.uint8_t, /* [PSX] big endian address */
-			__u6_addr16: [8]c.uint16_t,
-			__u6_addr32: [4]c.uint32_t,
-		},
+	when ODIN_OS == .Haiku {
+		in6_addr :: struct #packed {
+			using _: struct #raw_union {
+				s6_addr:     [16]c.uint8_t, /* [PSX] big endian address */
+				__u6_addr16: [8]c.uint16_t,
+				__u6_addr32: [4]c.uint32_t,
+			},
+		}
+	} else {
+		in6_addr :: struct {
+			using _: struct #raw_union {
+				s6_addr:     [16]c.uint8_t, /* [PSX] big endian address */
+				__u6_addr16: [8]c.uint16_t,
+				__u6_addr32: [4]c.uint32_t,
+			},
+		}
 	}
 
+
 	when ODIN_OS == .Linux {
 
 		sockaddr_in :: struct {
@@ -77,12 +88,20 @@ when ODIN_OS == .Darwin || ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD || ODIN_OS
 
 	} else {
 
+		when ODIN_OS == .Haiku {
+			@(private)
+			_SIN_ZEROSIZE :: 24
+		} else {
+			@(private)
+			_SIN_ZEROSIZE :: 8
+		}
+
 		sockaddr_in :: struct {
 			sin_len:    c.uint8_t,
 			sin_family: sa_family_t, /* [PSX] AF_INET (but a smaller size) */
 			sin_port:   in_port_t,   /* [PSX] port number */
 			sin_addr:   in_addr,     /* [PSX] IP address */
-			sin_zero:   [8]c.char,
+			sin_zero:   [_SIN_ZEROSIZE]c.char,
 		}
 
 		sockaddr_in6 :: struct {
@@ -99,13 +118,23 @@ when ODIN_OS == .Darwin || ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD || ODIN_OS
 			ipv6mr_interface: c.uint,   /* [PSX] interface index */
 		}
 
-		IPV6_JOIN_GROUP     :: 12
-		IPV6_LEAVE_GROUP    :: 13
-		IPV6_MULTICAST_HOPS :: 10
-		IPV6_MULTICAST_IF   :: 9
-		IPV6_MULTICAST_LOOP :: 11
-		IPV6_UNICAST_HOPS   :: 4
-		IPV6_V6ONLY         :: 27
+		when ODIN_OS == .Haiku {
+			IPV6_JOIN_GROUP     :: 28
+			IPV6_LEAVE_GROUP    :: 29
+			IPV6_MULTICAST_HOPS :: 25
+			IPV6_MULTICAST_IF   :: 24
+			IPV6_MULTICAST_LOOP :: 26
+			IPV6_UNICAST_HOPS   :: 27
+			IPV6_V6ONLY         :: 30	
+		} else {
+			IPV6_JOIN_GROUP     :: 12
+			IPV6_LEAVE_GROUP    :: 13
+			IPV6_MULTICAST_HOPS :: 10
+			IPV6_MULTICAST_IF   :: 9
+			IPV6_MULTICAST_LOOP :: 11
+			IPV6_UNICAST_HOPS   :: 4
+			IPV6_V6ONLY         :: 27
+		}
 
 	}
 

+ 36 - 13
core/sys/posix/poll.odin

@@ -1,4 +1,4 @@
-#+build linux, darwin, netbsd, openbsd, freebsd
+#+build linux, darwin, netbsd, openbsd, freebsd, haiku
 package posix
 
 import "base:intrinsics"
@@ -25,7 +25,11 @@ foreign lib {
 	poll :: proc(fds: [^]pollfd, nfds: nfds_t, timeout: c.int) -> c.int ---
 }
 
-nfds_t :: c.uint
+when ODIN_OS == .Haiku {
+	nfds_t :: c.ulong
+} else {
+	nfds_t :: c.uint
+}
 
 Poll_Event_Bits :: enum c.short {
 	// Data other than high-priority data may be read without blocking.
@@ -53,7 +57,7 @@ Poll_Event_Bits :: enum c.short {
 }
 Poll_Event :: bit_set[Poll_Event_Bits; c.short]
 
-when ODIN_OS == .Darwin || ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD || ODIN_OS == .OpenBSD {
+when ODIN_OS == .Darwin || ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD || ODIN_OS == .OpenBSD || ODIN_OS == .Haiku {
 
 	pollfd :: struct {
 		fd:      FD,         /* [PSX] the following descriptor being polled */
@@ -61,17 +65,36 @@ when ODIN_OS == .Darwin || ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD || ODIN_OS
 		revents: Poll_Event, /* [PSX] the output event flags */
 	}
 
-	POLLIN     :: 0x0001
-	POLLRDNORM :: 0x0040
-	POLLRDBAND :: 0x0080
-	POLLPRI    :: 0x0002
-	POLLOUT    :: 0x0004
-	POLLWRNORM :: POLLOUT
-	POLLWRBAND :: 0x0100
+	when ODIN_OS == .Haiku {
+
+		POLLIN     :: 0x0001 /* any readable data available */
+		POLLOUT    :: 0x0002 /* file descriptor is writeable */
+		POLLRDNORM :: POLLIN
+		POLLWRNORM :: POLLOUT
+		POLLRDBAND :: 0x0008 /* priority readable data */
+		POLLWRBAND :: 0x0010 /* priority data can be written */
+		POLLPRI    :: 0x0020 /* high priority readable data */
+
+		POLLERR    :: 0x0004 /* errors pending */
+		POLLHUP    :: 0x0080 /* disconnected */
+		POLLNVAL   :: 0x1000 /* invalid file descriptor */
+
+	} else {
+
+		POLLIN     :: 0x0001
+		POLLRDNORM :: 0x0040
+		POLLRDBAND :: 0x0080
+		POLLPRI    :: 0x0002
+		POLLOUT    :: 0x0004
+		POLLWRNORM :: POLLOUT
+		POLLWRBAND :: 0x0100
+
+		POLLERR    :: 0x0008
+		POLLHUP    :: 0x0010
+		POLLNVAL   :: 0x0020
+		
+	}
 
-	POLLERR    :: 0x0008
-	POLLHUP    :: 0x0010
-	POLLNVAL   :: 0x0020
 
 } else when ODIN_OS == .Linux {
 

+ 13 - 1
core/sys/posix/pwd.odin

@@ -1,4 +1,4 @@
-#+build linux, darwin, netbsd, openbsd, freebsd
+#+build linux, darwin, netbsd, openbsd, freebsd, haiku
 package posix
 
 import "core:c"
@@ -176,4 +176,16 @@ when ODIN_OS == .Darwin || ODIN_OS == .NetBSD || ODIN_OS == .OpenBSD {
 		pw_shell:  cstring, /* Shell program.  */
 	}
 
+} else when ODIN_OS == .Haiku {
+
+	passwd :: struct {
+		pw_name:   cstring, /* [PSX] user name */
+		pw_passwd: cstring, /* encrypted password */
+		pw_uid:    uid_t,   /* [PSX] user uid */
+		pw_gid:    gid_t,   /* [PSX] user gid */
+		pw_dir:    cstring, /* Home directory.  */
+		pw_shell:  cstring, /* Shell program.  */
+		pw_gecos:  cstring, /* Real name.  */
+	}
+
 }

+ 0 - 10
core/sys/posix/signal.odin

@@ -185,16 +185,6 @@ foreign lib {
 	*/
 	sigwait :: proc(set: ^sigset_t, sig: ^Signal) -> Errno ---
 
-	when ODIN_OS != .Darwin {
-		/*
-		Wait for queued signals.
-
-		[[ More; https://pubs.opengroup.org/onlinepubs/9699919799/functions/sigtimedwait.html ]]
-		*/
-		sigtimedwait :: proc(set: ^sigset_t, info: ^siginfo_t, timeout: ^timespec) -> result ---
-	}
-
-
 	/* NOTE: unimplemented on darwin.
 
 	void   psiginfo(const siginfo_t *, const char *);

+ 1 - 1
core/sys/posix/stdio_libc.odin

@@ -1,4 +1,4 @@
-#+build linux, windows, linux, darwin, netbsd, openbsd, freebsd
+#+build linux, windows, linux, darwin, netbsd, openbsd, freebsd, haiku
 package posix
 
 import "core:c"

+ 1 - 1
core/sys/posix/stdlib.odin

@@ -1,4 +1,4 @@
-#+build linux, darwin, netbsd, openbsd, freebsd
+#+build linux, darwin, netbsd, openbsd, freebsd, haiku
 package posix
 
 import "base:intrinsics"

+ 1 - 1
core/sys/posix/stdlib_libc.odin

@@ -1,4 +1,4 @@
-#+build linux, windows, darwin, netbsd, openbsd, freebsd
+#+build linux, windows, darwin, netbsd, openbsd, freebsd, haiku
 package posix
 
 import "base:intrinsics"

+ 1 - 1
core/sys/posix/string.odin

@@ -1,4 +1,4 @@
-#+build linux, darwin, netbsd, openbsd, freebsd
+#+build linux, darwin, netbsd, openbsd, freebsd, haiku
 package posix
 
 import "core:c"

+ 1 - 1
core/sys/posix/string_libc.odin

@@ -1,4 +1,4 @@
-#+build linux, windows, darwin, netbsd, openbsd, freebsd
+#+build linux, windows, darwin, netbsd, openbsd, freebsd, haiku
 package posix
 
 when ODIN_OS == .Windows {

+ 24 - 1
core/sys/posix/sys_ipc.odin

@@ -1,4 +1,4 @@
-#+build linux, darwin, netbsd, openbsd, freebsd
+#+build linux, darwin, netbsd, openbsd, freebsd, haiku
 package posix
 
 import "core:c"
@@ -111,4 +111,27 @@ when ODIN_OS == .Darwin {
 	IPC_SET  :: 1
 	IPC_STAT :: 2
 
+} else when ODIN_OS == .Haiku {
+
+	key_t :: distinct c.int32_t
+
+	ipc_perm :: struct {
+		key:  key_t,
+		uid:  uid_t,     /* [PSX] owner's user ID */
+		gid:  gid_t,     /* [PSX] owner's group ID */
+		cuid: uid_t,     /* [PSX] creator's user ID */
+		cgid: gid_t,     /* [PSX] creator's group ID */
+		mode: mode_t,    /* [PSX] read/write perms */
+	}
+
+	IPC_CREAT  :: 0o01000
+	IPC_EXCL   :: 0o02000
+	IPC_NOWAIT :: 0o04000
+
+	IPC_PRIVATE :: key_t(0)
+
+	IPC_RMID :: 0
+	IPC_SET  :: 1
+	IPC_STAT :: 2
+
 }

+ 19 - 1
core/sys/posix/sys_msg.odin

@@ -1,4 +1,4 @@
-#+build linux, darwin, netbsd, openbsd, freebsd
+#+build linux, darwin, netbsd, openbsd, freebsd, haiku
 package posix
 
 import "core:c"
@@ -171,4 +171,22 @@ when ODIN_OS == .Darwin {
 		__unused:    [2]c.ulong,
 	}
 
+} else when ODIN_OS == .Haiku {
+
+	msgqnum_t :: distinct c.uint32_t
+	msglen_t  :: distinct c.uint32_t
+
+	MSG_NOERROR :: 0o10000
+
+	msqid_ds :: struct {
+		msg_perm:   ipc_perm,  /* [PSX] operation permission structure */
+		msg_qnum:   msgqnum_t, /* [PSX] number of messages currently on queue */
+		msg_qbytes: msglen_t,  /* [PSX] maximum number of bytes allowed on queue */
+		msg_lspid:  pid_t,     /* [PSX] process ID of last msgsnd() */
+		msg_lrpid:  pid_t,     /* [PSX] process ID of last msgrcv() */
+		msg_stime:  time_t,    /* [PSX] time of last msgsnd() */
+		msg_rtime:  time_t,    /* [PSX] time of last msgrcv() */
+		msg_ctime:  time_t,    /* [PSX] time of last change */
+	}
+
 }

+ 37 - 16
core/sys/posix/sys_resource.odin

@@ -1,4 +1,4 @@
-#+build linux, darwin, netbsd, openbsd, freebsd
+#+build linux, darwin, netbsd, openbsd, freebsd, haiku
 package posix
 
 import "core:c"
@@ -96,15 +96,26 @@ when ODIN_OS == .NetBSD {
 	@(private) LGETRUSAGE :: "getrusage"
 }
 
-when ODIN_OS == .Darwin || ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD || ODIN_OS == .OpenBSD || ODIN_OS == .Linux {
+when ODIN_OS == .Darwin || ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD || ODIN_OS == .OpenBSD || ODIN_OS == .Linux || ODIN_OS == .Haiku {
 
 	PRIO_PROCESS :: 0
 	PRIO_PGRP    :: 1
 	PRIO_USER    :: 2
 
-	rlim_t :: distinct c.uint64_t
+	when ODIN_OS == .Haiku {
+		rlim_t :: distinct c.ulong
+	} else {
+		rlim_t :: distinct c.uint64_t
+	}
 
-	RLIM_INFINITY  :: ~rlim_t(0) when ODIN_OS == .Linux else (rlim_t(1) << 63) - 1
+	when ODIN_OS == .Haiku {
+		RLIM_INFINITY :: rlim_t(0xFFFFFFFF)
+	} else when ODIN_OS == .Linux {
+		RLIM_INFINITY :: ~rlim_t(0)
+	} else {
+		RLIM_INFINITY :: (rlim_t(1) << 63) - 1
+	}
+	
 	RLIM_SAVED_MAX :: RLIM_INFINITY
 	RLIM_SAVED_CUR :: RLIM_INFINITY
 
@@ -140,19 +151,29 @@ when ODIN_OS == .Darwin || ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD || ODIN_OS
 		ru_nivcsw:   c.long, /* involuntary " */
 	}
 
-	RLIMIT_CORE   :: 4
-	RLIMIT_CPU    :: 0
-	RLIMIT_DATA   :: 2
-	RLIMIT_FSIZE  :: 1
-	RLIMIT_NOFILE :: 7 when ODIN_OS == .Linux else 8
-	RLIMIT_STACK  :: 3
-
-	when ODIN_OS == .Linux {
-		RLIMIT_AS :: 9
-	} else when ODIN_OS == .Darwin || ODIN_OS == .OpenBSD {
-		RLIMIT_AS :: 5
+	when ODIN_OS == .Haiku {
+		RLIMIT_CORE   :: 0
+		RLIMIT_CPU    :: 1
+		RLIMIT_DATA   :: 2
+		RLIMIT_FSIZE  :: 3
+		RLIMIT_NOFILE :: 4
+		RLIMIT_STACK  :: 5
+		RLIMIT_AS     :: 6
 	} else {
-		RLIMIT_AS :: 10
+		RLIMIT_CORE   :: 4
+		RLIMIT_CPU    :: 0
+		RLIMIT_DATA   :: 2
+		RLIMIT_FSIZE  :: 1
+		RLIMIT_NOFILE :: 7 when ODIN_OS == .Linux else 8
+		RLIMIT_STACK  :: 3
+	
+		when ODIN_OS == .Linux {
+			RLIMIT_AS :: 9
+		} else when ODIN_OS == .Darwin || ODIN_OS == .OpenBSD {
+			RLIMIT_AS :: 5
+		} else {
+			RLIMIT_AS :: 10
+		}
 	}
 
 }

+ 11 - 5
core/sys/posix/sys_select.odin

@@ -1,4 +1,4 @@
-#+build linux, darwin, netbsd, openbsd, freebsd
+#+build linux, darwin, netbsd, openbsd, freebsd, haiku
 package posix
 
 import "base:intrinsics"
@@ -56,9 +56,9 @@ when ODIN_OS == .NetBSD {
 	LSELECT  :: "select"
 }
 
-when ODIN_OS == .Darwin || ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD || ODIN_OS == .OpenBSD || ODIN_OS == .Linux {
+when ODIN_OS == .Darwin || ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD || ODIN_OS == .OpenBSD || ODIN_OS == .Linux || ODIN_OS == .Haiku {
 
-	suseconds_t :: distinct (c.int32_t when ODIN_OS == .Darwin || ODIN_OS == .NetBSD else c.long)
+	suseconds_t :: distinct (c.int32_t when ODIN_OS == .Darwin || ODIN_OS == .NetBSD || ODIN_OS == .Haiku else c.long)
 
 	timeval :: struct {
 		tv_sec:  time_t,      /* [PSX] seconds */
@@ -75,8 +75,14 @@ when ODIN_OS == .Darwin || ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD || ODIN_OS
 	@(private)
 	ALIGN ::  align_of(c.long) when ODIN_OS == .FreeBSD || ODIN_OS == .Linux else align_of(c.int32_t)
 
-	fd_set :: struct #align(ALIGN) {
-		fds_bits: [(FD_SETSIZE / __NFDBITS) when (FD_SETSIZE % __NFDBITS) == 0 else (FD_SETSIZE / __NFDBITS) + 1]c.int32_t,
+	when ODIN_OS == .Haiku {
+		fd_set :: struct #align(ALIGN) {
+			fds_bits: [(FD_SETSIZE + (__NFDBITS - 1)) / __NFDBITS]c.int32_t,
+		}
+	} else {
+		fd_set :: struct #align(ALIGN) {
+			fds_bits: [(FD_SETSIZE / __NFDBITS) when (FD_SETSIZE % __NFDBITS) == 0 else (FD_SETSIZE / __NFDBITS) + 1]c.int32_t,
+		}
 	}
 
 	@(private)

+ 27 - 1
core/sys/posix/sys_sem.odin

@@ -1,4 +1,4 @@
-#+build linux, darwin, netbsd, openbsd, freebsd
+#+build linux, darwin, netbsd, openbsd, freebsd, haiku
 package posix
 
 import "core:c"
@@ -154,4 +154,30 @@ when ODIN_OS == .Darwin || ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD || ODIN_OS
 		sem_flg: c.short,  /* [PSX] operation flags */
 	}
 
+} else when ODIN_OS == .Haiku {
+
+	SEM_UNDO :: 10 // undo the operation on exit
+
+	// Commands for `semctl'.
+	GETPID  :: 3
+	GETVAL  :: 4
+	GETALL  :: 5
+	GETNCNT :: 6
+	GETZCNT :: 7
+	SETVAL  :: 8
+	SETALL  :: 9
+
+	semid_ds :: struct {
+		sem_perm:  ipc_perm,  // [PSX] operation permission structure
+		sem_nsems: c.ushort, // [PSX] number of semaphores in set
+		sem_otime: time_t,    // [PSX] last semop()
+		sem_ctime: time_t,    // [PSX] last time changed by semctl()
+	}
+
+	sembuf :: struct {
+		sem_num: c.ushort, /* [PSX] semaphore number */
+		sem_op:  c.short,  /* [PSX] semaphore operation */
+		sem_flg: c.short,  /* [PSX] operation flags */
+	}
+
 }

+ 56 - 10
core/sys/posix/sys_socket.odin

@@ -1,4 +1,4 @@
-#+build linux, darwin, netbsd, openbsd, freebsd
+#+build linux, darwin, netbsd, openbsd, freebsd, haiku
 package posix
 
 import "core:c"
@@ -328,24 +328,32 @@ when ODIN_OS == .NetBSD {
 	@(private) LSOCKET :: "socket"
 }
 
-when ODIN_OS == .Darwin || ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD || ODIN_OS == .OpenBSD || ODIN_OS == .Linux {
+when ODIN_OS == .Darwin || ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD || ODIN_OS == .OpenBSD || ODIN_OS == .Linux || ODIN_OS == .Haiku {
 
 	socklen_t :: distinct c.uint
 
+	when ODIN_OS == .Haiku {
+		@(private)
+		_SA_DATASIZE :: 30
+	} else {
+		@(private)
+		_SA_DATASIZE :: 14
+	}
+
 	when ODIN_OS == .Linux {
 		_sa_family_t :: distinct c.ushort
 
 		sockaddr :: struct {
-			sa_family: sa_family_t, /* [PSX] address family */
-			sa_data:   [14]c.char,  /* [PSX] socket address */
+			sa_family: sa_family_t,           /* [PSX] address family */
+			sa_data:   [_SA_DATASIZE]c.char,  /* [PSX] socket address */
 		}
 	} else {
 		_sa_family_t :: distinct c.uint8_t
 
 		sockaddr :: struct {
-			sa_len:    c.uint8_t,   /* total length */
-			sa_family: sa_family_t, /* [PSX] address family */
-			sa_data:   [14]c.char,  /* [PSX] socket address */
+			sa_len:    c.uint8_t,             /* total length */
+			sa_family: sa_family_t,           /* [PSX] address family */
+			sa_data:   [_SA_DATASIZE]c.char,  /* [PSX] socket address */
 		}
 	}
 
@@ -355,6 +363,11 @@ when ODIN_OS == .Darwin || ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD || ODIN_OS
 		_SS_PAD1SIZE :: 6
 		@(private)
 		_SS_PAD2SIZE :: 240
+	} else when ODIN_OS == .Haiku {
+		@(private)
+		_SS_PAD1SIZE :: 6
+		@(private)
+		_SS_PAD2SIZE :: 112
 	} else when ODIN_OS == .Linux {
 		@(private)
 		_SS_SIZE :: 128
@@ -486,6 +499,26 @@ when ODIN_OS == .Darwin || ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD || ODIN_OS
 
 		SO_RCVTIMEO   :: 66
 		SO_SNDTIMEO   :: 67
+	} else when ODIN_OS == .Haiku {
+		SOL_SOCKET :: -1
+
+		SO_ACCEPTCONN :: 0x00000001
+		SO_BROADCAST  :: 0x00000002
+		SO_DEBUG      :: 0x00000004
+		SO_DONTROUTE  :: 0x00000008
+		SO_ERROR      :: 0x40000007
+		SO_KEEPALIVE  :: 0x00000010
+		SO_OOBINLINE  :: 0x00000020
+		SO_RCVBUF     :: 0x40000004
+		SO_RCVLOWAT   :: 0x40000005
+		SO_REUSEADDR  :: 0x00000040
+		SO_SNDBUF     :: 0x40000001
+		SO_SNDLOWAT   :: 0x40000002
+		SO_TYPE       :: 0x40000008
+
+		SO_LINGER     :: 0x00000200
+		SO_RCVTIMEO   :: 0x40000006
+		SO_SNDTIMEO   :: 0x40000003
 	} else {
 		SOL_SOCKET :: 0xffff
 
@@ -523,7 +556,11 @@ when ODIN_OS == .Darwin || ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD || ODIN_OS
 	}
 
 	// The maximum backlog queue length for listen().
-	SOMAXCONN :: 128
+	when ODIN_OS == .Haiku {
+		SOMAXCONN :: 32
+	} else {
+		SOMAXCONN :: 128
+	}
 
 	when ODIN_OS == .Linux {
 		MSG_CTRUNC    :: 0x008
@@ -549,11 +586,18 @@ when ODIN_OS == .Darwin || ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD || ODIN_OS
 			MSG_NOSIGNAL :: 0x00020000
 		} else when ODIN_OS == .NetBSD || ODIN_OS == .OpenBSD {
 			MSG_NOSIGNAL :: 0x0400
+		} else when ODIN_OS == .Haiku {
+			MSG_NOSIGNAL :: 0x800
 		}
 	}
 
-	AF_INET   :: 2
-	AF_UNIX   :: 1
+	when ODIN_OS == .Haiku {
+		AF_INET :: 1
+		AF_UNIX :: 9
+	} else {
+		AF_INET :: 2
+		AF_UNIX :: 1
+	}
 
 	when ODIN_OS == .Darwin {
 		AF_INET6 :: 30
@@ -563,6 +607,8 @@ when ODIN_OS == .Darwin || ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD || ODIN_OS
 		AF_INET6 :: 24
 	} else when ODIN_OS == .Linux {
 		AF_INET6 :: 10
+	} else when ODIN_OS == .Haiku {
+		AF_INET6 :: 5
 	}
 
 	SHUT_RD   :: 0

+ 12 - 1
core/sys/posix/sys_time.odin

@@ -1,4 +1,4 @@
-#+build linux, darwin, netbsd, openbsd, freebsd
+#+build linux, darwin, netbsd, openbsd, freebsd, haiku
 package posix
 
 import "core:c"
@@ -78,4 +78,15 @@ when ODIN_OS == .Darwin || ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD || ODIN_OS
 	ITIMER_VIRTUAL :: 1
 	ITIMER_PROF    :: 2
 
+} else when ODIN_OS == .Haiku {
+
+	itimerval :: struct {
+		it_interval: timeval, /* [PSX] timer interval */
+		it_value:    timeval, /* [PSX] current value */
+	}
+
+	ITIMER_REAL    :: 1
+	ITIMER_VIRTUAL :: 2
+	ITIMER_PROF    :: 3
+
 }

+ 2 - 2
core/sys/posix/sys_times.odin

@@ -1,4 +1,4 @@
-#+build linux, darwin, netbsd, openbsd, freebsd
+#+build linux, darwin, netbsd, openbsd, freebsd, haiku
 package posix
 
 when ODIN_OS == .Darwin {
@@ -25,7 +25,7 @@ when ODIN_OS == .NetBSD {
 	@(private) LTIMES :: "times"
 }
 
-when ODIN_OS == .Darwin || ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD || ODIN_OS == .OpenBSD || ODIN_OS == .Linux {
+when ODIN_OS == .Darwin || ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD || ODIN_OS == .OpenBSD || ODIN_OS == .Linux || ODIN_OS == .Haiku {
 
 	tms :: struct {
 		tms_utime:  clock_t, /* [PSX] user CPU time */

+ 2 - 2
core/sys/posix/sys_uio.odin

@@ -1,4 +1,4 @@
-#+build linux, darwin, netbsd, openbsd, freebsd
+#+build linux, darwin, netbsd, openbsd, freebsd, haiku
 package posix
 
 import "core:c"
@@ -31,7 +31,7 @@ foreign libc {
 	writev :: proc(fildes: FD, iov: [^]iovec, iovcnt: c.int) -> c.ssize_t ---
 }
 
-when ODIN_OS == .Darwin || ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD || ODIN_OS == .OpenBSD || ODIN_OS == .Linux {
+when ODIN_OS == .Darwin || ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD || ODIN_OS == .OpenBSD || ODIN_OS == .Linux || ODIN_OS == .Haiku {
 
 	iovec :: struct {
 		iov_base: rawptr,   /* [PSX] base address of I/O memory region */

+ 9 - 1
core/sys/posix/sys_un.odin

@@ -1,4 +1,4 @@
-#+build linux, darwin, netbsd, openbsd, freebsd
+#+build linux, darwin, netbsd, openbsd, freebsd, haiku
 package posix
 
 import "core:c"
@@ -20,4 +20,12 @@ when ODIN_OS == .Darwin || ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD || ODIN_OS
 		sun_path:   [108]c.char, /* [PSX] socket pathname */
 	}
 
+} else when ODIN_OS == .Haiku {
+
+	sockaddr_un :: struct {
+		sun_len:    c.uint8_t,
+		sun_family: sa_family_t, /* [PSX] address family */
+		sun_path:   [126]c.char, /* [PSX] socket pathname */
+	}
+
 }

+ 3 - 3
core/sys/posix/sys_utsname.odin

@@ -1,4 +1,4 @@
-#+build linux, darwin, netbsd, openbsd, freebsd
+#+build linux, darwin, netbsd, openbsd, freebsd, haiku
 package posix
 
 import "core:c"
@@ -38,10 +38,10 @@ foreign lib {
 	uname :: proc(uname: ^utsname) -> c.int ---
 }
 
-when ODIN_OS == .Darwin || ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD || ODIN_OS == .OpenBSD {
+when ODIN_OS == .Darwin || ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD || ODIN_OS == .OpenBSD || ODIN_OS == .Haiku {
 
 	@(private)
-	_SYS_NAMELEN :: 256
+	_SYS_NAMELEN :: 32 when ODIN_OS == .Haiku else 256
 
 	utsname :: struct {
 		sysname:  [_SYS_NAMELEN]c.char `fmt:"s,0"`, /* [PSX] name of OS */

+ 53 - 1
core/sys/posix/sys_wait.odin

@@ -1,4 +1,4 @@
-#+build linux, darwin, netbsd, openbsd, freebsd
+#+build linux, darwin, netbsd, openbsd, freebsd, haiku
 package posix
 
 import "core:c"
@@ -442,4 +442,56 @@ when ODIN_OS == .Darwin {
 	_WIFCONTINUED :: #force_inline proc "contextless" (x: c.int) -> bool {
 		return x == 0xffff
 	}
+
+} else when ODIN_OS == .Haiku {
+
+	id_t :: distinct c.int32_t
+
+	WCONTINUED :: 0x04
+	WNOHANG    :: 0x01
+	WUNTRACED  :: 0x02
+
+	WEXITED  :: 0x08
+	WNOWAIT  :: 0x20
+	WSTOPPED :: 0x10
+
+	_P_ALL  :: 0
+	_P_PID  :: 1
+	_P_PGID :: 2
+
+	@(private)
+	_WIFEXITED :: #force_inline proc "contextless" (x: c.int) -> bool {
+		return (x & ~(c.int)(0xff)) == 0
+	}
+
+	@(private)
+	_WEXITSTATUS :: #force_inline proc "contextless" (x: c.int) -> c.int {
+		return x & 0xff
+	}
+
+	@(private)
+	_WIFSIGNALED :: #force_inline proc "contextless" (x: c.int) -> bool {
+		return ((x >> 8) & 0xff) != 0
+	}
+
+	@(private)
+	_WTERMSIG :: #force_inline proc "contextless" (x: c.int) -> Signal {
+		return Signal((x >> 8) & 0xff)
+	}
+
+	@(private)
+	_WIFSTOPPED :: #force_inline proc "contextless" (x: c.int) -> bool {
+		return ((x >> 16) & 0xff) != 0
+	}
+
+	@(private)
+	_WSTOPSIG :: #force_inline proc "contextless" (x: c.int) -> Signal {
+		return Signal((x >> 16) & 0xff)
+	}
+
+	@(private)
+	_WIFCONTINUED :: #force_inline proc "contextless" (x: c.int) -> bool {
+		return (x & 0x20000) != 0
+	}
+
 }

+ 172 - 12
core/sys/posix/termios.odin

@@ -1,4 +1,4 @@
-#+build linux, darwin, netbsd, openbsd, freebsd
+#+build linux, darwin, netbsd, openbsd, freebsd, haiku
 package posix
 
 import "core:c"
@@ -138,17 +138,30 @@ CLocal_Flag_Bits :: enum tcflag_t {
 }
 CLocal_Flags :: bit_set[CLocal_Flag_Bits; tcflag_t]
 
-CControl_Flag_Bits :: enum tcflag_t {
-	// CS5    = log2(CS5), /* 5 bits (pseudo) (default) */
-	CS6    = log2(CS6),    /* 6 bits */
-	CS7    = log2(CS7),    /* 7 bits */
-	CS8    = log2(CS8),    /* 8 bits */
-	CSTOPB = log2(CSTOPB), /* send 2 stop bits */
-	CREAD  = log2(CREAD),  /* enable receiver */
-	PARENB = log2(PARENB), /* parity enable */
-	PARODD = log2(PARODD), /* odd parity, else even */
-	HUPCL  = log2(HUPCL),  /* hang up on last close */
-	CLOCAL = log2(CLOCAL), /* ignore modem status lines */
+when ODIN_OS == .Haiku {
+	CControl_Flag_Bits :: enum tcflag_t {
+		// CS7    = log2(CS7),    /* 7 bits (default) */
+		CS8    = log2(CS8),    /* 8 bits */
+		CSTOPB = log2(CSTOPB), /* send 2 stop bits */
+		CREAD  = log2(CREAD),  /* enable receiver */
+		PARENB = log2(PARENB), /* parity enable */
+		PARODD = log2(PARODD), /* odd parity, else even */
+		HUPCL  = log2(HUPCL),  /* hang up on last close */
+		CLOCAL = log2(CLOCAL), /* ignore modem status lines */
+	}	
+} else {
+	CControl_Flag_Bits :: enum tcflag_t {
+		// CS5    = log2(CS5), /* 5 bits (pseudo) (default) */
+		CS6    = log2(CS6),    /* 6 bits */
+		CS7    = log2(CS7),    /* 7 bits */
+		CS8    = log2(CS8),    /* 8 bits */
+		CSTOPB = log2(CSTOPB), /* send 2 stop bits */
+		CREAD  = log2(CREAD),  /* enable receiver */
+		PARENB = log2(PARENB), /* parity enable */
+		PARODD = log2(PARODD), /* odd parity, else even */
+		HUPCL  = log2(HUPCL),  /* hang up on last close */
+		CLOCAL = log2(CLOCAL), /* ignore modem status lines */
+	}
 }
 CControl_Flags :: bit_set[CControl_Flag_Bits; tcflag_t]
 
@@ -597,4 +610,151 @@ when ODIN_OS == .Darwin {
 	TCOOFF :: 0
 	TCOON  :: 1
 
+} else when ODIN_OS == .Haiku {
+
+	cc_t      :: distinct c.uchar
+	_speed_t  :: distinct c.uint32_t
+	tcflag_t  :: distinct c.uint16_t
+
+	// Same as speed_t, but 16-bit.
+	CSpeed :: enum tcflag_t {
+		B0     = B0,
+		B50    = B50,
+		B75    = B75,
+		B110   = B110,
+		B134   = B134,
+		B150   = B150,
+		B200   = B200,
+		B300   = B300,
+		B600   = B600,
+		B1200  = B1200,
+		B1800  = B1800,
+		B2400  = B2400,
+		B4800  = B4800,
+		B9600  = B9600,
+		B19200 = B19200,
+		B38400 = B38400,
+	}
+
+	termios :: struct {
+		c_iflag:       CInput_Flags,   /* [XBD] input flags */
+		c_ispeed:      CSpeed,         /* input speed */
+		c_oflag:       COutput_Flags,  /* [XBD] output flags */
+		c_ospeed:      CSpeed,         /* output speed */
+		c_cflag:       CControl_Flags, /* [XBD] control flags */
+		c_ispeed_high: tcflag_t,       /* high word of input baudrate */
+		c_lflag:       CLocal_Flags,   /* [XBD] local flag */
+		c_ospeed_high: tcflag_t,       /* high word of output baudrate */
+		c_line:        c.char,
+		_padding:      c.uchar,
+		_padding2:     c.uchar,
+		c_cc:          [NCCS]cc_t,
+	}
+
+	NCCS :: 11
+
+	VINTR  :: 0
+	VQUIT  :: 1
+	VERASE :: 2
+	VKILL  :: 3
+	VEOF   :: 4
+	VEOL   :: 5
+	VMIN   :: 4
+	VTIME  :: 5
+	VEOL2  :: 6
+	VSWTCH :: 7
+	VSTART :: 8
+	VSTOP  :: 9
+	VSUSP  :: 10
+
+	IGNBRK :: 0x01   /* ignore break condition */
+	BRKINT :: 0x02   /* break sends interrupt */
+	IGNPAR :: 0x04   /* ignore characters with parity errors */
+	PARMRK :: 0x08   /* mark parity errors */
+	INPCK  :: 0x10   /* enable input parity checking */
+	ISTRIP :: 0x20   /* strip high bit from characters */
+	INLCR  :: 0x40   /* maps newline to CR on input */
+	IGNCR  :: 0x80   /* ignore carriage returns */
+	ICRNL  :: 0x100  /* map CR to newline on input */
+	IXON   :: 0x400  /* enable input SW flow control */
+	IXANY  :: 0x800  /* any character will restart input */
+	IXOFF  :: 0x1000 /* enable output SW flow control */
+
+	OPOST   :: 0x01  /* enable postprocessing of output */
+	ONLCR   :: 0x04  /* map NL to CR-NL on output */
+	OCRNL   :: 0x08  /* map CR to NL on output */
+	ONOCR   :: 0x10  /* no CR output when at column 0 */
+	ONLRET  :: 0x20  /* newline performs CR function */
+	OFILL   :: 0x40  /* use fill characters for delays */
+	OFDEL   :: 0x80  /* Fills are DEL, otherwise NUL */
+	_NLDLY  :: 0x100 /* Newline delays: */
+	NL0     :: 0x000
+	NL1     :: 0x100
+	_CRDLY  :: 0x600 /* Carriage return delays: */
+	CR0     :: 0x000
+	CR1     :: 0x200
+	CR2     :: 0x400
+	CR3     :: 0x600
+	_TABDLY :: 0x1800 /* Tab delays: */
+	TAB0    :: 0x0000
+	TAB1    :: 0x0800
+	TAB3    :: 0x1800
+	_BSDLY  :: 0x2000 /* Backspace delays: */
+	BS0     :: 0x0000
+	BS1     :: 0x2000
+	_VTDLY  :: 0x4000 /* Vertical tab delays: */
+	VT0     :: 0x0000
+	VT1     :: 0x4000
+	_FFDLY  :: 0x8000 /* Form feed delays: */
+	FF0     :: 0x0000
+	FF1     :: 0x8000
+
+	B0     :: 0x00 /* hang up */
+	B50    :: 0x01 /* 50 baud */
+	B75    :: 0x02
+	B110   :: 0x03
+	B134   :: 0x04
+	B150   :: 0x05
+	B200   :: 0x06
+	B300   :: 0x07
+	B600   :: 0x08
+	B1200  :: 0x09
+	B1800  :: 0x0A
+	B2400  :: 0x0B
+	B4800  :: 0x0C
+	B9600  :: 0x0D
+	B19200 :: 0x0E
+	B38400 :: 0x0F
+
+	_CSIZE  :: 0x20  /* character size */
+	//CS5    :: 0x00  /* only 7 and 8 bits supported */
+	//CS6    :: 0x00  /* Note, it was not very wise to set all of these */
+	//CS7    :: 0x00  /* to zero, but there is not much we can do about it*/
+	CS8    :: 0x20
+	CSTOPB :: 0x40  /* send 2 stop bits, not 1 */
+	CREAD  :: 0x80  /* enable receiver */
+	PARENB :: 0x100 /* parity enable */
+	PARODD :: 0x200 /* odd parity, else even */
+	HUPCL  :: 0x400 /* hangs up on last close */
+	CLOCAL :: 0x800 /* indicates local line */
+
+	ISIG   :: 0x01  /* enable signals */
+	ICANON :: 0x02  /* Canonical input */
+	ECHO   :: 0x08  /* Enable echo */
+	ECHOE  :: 0x10  /* Echo erase as bs-sp-bs */
+	ECHOK  :: 0x20  /* Echo nl after kill */
+	ECHONL :: 0x40  /* Echo nl */
+	NOFLSH :: 0x80  /* Disable flush after int or quit */
+	TOSTOP :: 0x100 /* stop bg processes that write to tty */
+	IEXTEN :: 0x200 /* implementation defined extensions */
+
+	TCIFLUSH  :: 1
+	TCOFLUSH  :: 2
+	TCIOFLUSH :: 3
+
+	TCIOFF :: 0x04
+	TCION  :: 0x08
+	TCOOFF :: 0x01
+	TCOON  :: 0x02
+
 }

+ 172 - 2
core/sys/posix/unistd.odin

@@ -1,4 +1,4 @@
-#+build linux, darwin, netbsd, openbsd, freebsd
+#+build linux, darwin, netbsd, openbsd, freebsd, haiku
 package posix
 
 import "core:c"
@@ -1852,7 +1852,7 @@ when ODIN_OS == .Darwin {
 	_PC_ALLOC_SIZE_MIN     :: 19
 	_PC_SYMLINK_MAX        :: 20
 	_PC_2_SYMLINK          :: 21
-
+	
 	_SC_ARG_MAX               :: 1
 	_SC_CHILD_MAX             :: 2
 	_SC_CLK_TCK               :: 3
@@ -1992,4 +1992,174 @@ when ODIN_OS == .Darwin {
 	// NOTE: Not implemented.
 	_POSIX_VDISABLE :: 0
 
+} else when ODIN_OS == .Haiku {
+
+	_F_OK   :: 0
+	X_OK    :: 1
+	W_OK    :: 2
+	R_OK    :: 4
+
+	F_LOCK  :: 1
+	F_TEST  :: 3
+	F_TLOCK :: 2
+	F_ULOCK :: 0
+
+	_CS_PATH                           :: 1
+	_CS_POSIX_V6_WIDTH_RESTRICTED_ENVS :: 0 // Undefined.
+	_CS_POSIX_V6_ILP32_OFF32_CFLAGS    :: 0 // Undefined.
+	_CS_POSIX_V6_ILP32_OFF32_LDFLAGS   :: 0 // Undefined.
+	_CS_POSIX_V6_ILP32_OFF32_LIBS      :: 0 // Undefined.
+	_CS_POSIX_V6_ILP32_OFFBIG_CFLAGS   :: 0 // Undefined.
+	_CS_POSIX_V6_ILP32_OFFBIG_LDFLAGS  :: 0 // Undefined.
+	_CS_POSIX_V6_ILP32_OFFBIG_LIBS     :: 0 // Undefined.
+	_CS_POSIX_V6_LP64_OFF64_CFLAGS     :: 0 // Undefined.
+	_CS_POSIX_V6_LP64_OFF64_LDFLAGS    :: 0 // Undefined.
+	_CS_POSIX_V6_LP64_OFF64_LIBS       :: 0 // Undefined.
+	_CS_POSIX_V6_LPBIG_OFFBIG_CFLAGS   :: 0 // Undefined.
+	_CS_POSIX_V6_LPBIG_OFFBIG_LDFLAGS  :: 0 // Undefined.
+	_CS_POSIX_V6_LPBIG_OFFBIG_LIBS     :: 0 // Undefined.
+
+	_SC_ASYNCHRONOUS_IO      :: 0 // Undefined.
+	_SC_RAW_SOCKETS          :: 0 // Undefined.
+	_SC_SS_REPL_MAX          :: 0 // Undefined.
+	_SC_TRACE_EVENT_NAME_MAX :: 0 // Undefined.
+	_SC_TRACE_NAME_MAX       :: 0 // Undefined.
+	_SC_TRACE_SYS_MAX        :: 0 // Undefined.
+	_SC_TRACE_USER_EVENT_MAX :: 0 // Undefined.
+
+	_PC_CHOWN_RESTRICTED   :: 1
+	_PC_MAX_CANON          :: 2
+	_PC_MAX_INPUT          :: 3
+	_PC_NAME_MAX           :: 4
+	_PC_NO_TRUNC           :: 5
+	_PC_PATH_MAX           :: 6
+	_PC_PIPE_BUF           :: 7
+	_PC_VDISABLE           :: 8
+	_PC_LINK_MAX           :: 25
+	_PC_SYNC_IO            :: 26
+	_PC_ASYNC_IO           :: 27
+	_PC_PRIO_IO            :: 28
+	_PC_FILESIZEBITS       :: 30
+	_PC_REC_INCR_XFER_SIZE :: 31
+	_PC_REC_MAX_XFER_SIZE  :: 32
+	_PC_REC_MIN_XFER_SIZE  :: 33
+	_PC_REC_XFER_ALIGN     :: 34
+	_PC_ALLOC_SIZE_MIN     :: 35
+	_PC_SYMLINK_MAX        :: 36
+	_PC_2_SYMLINK          :: 37
+
+	_SC_ARG_MAX                    :: 15
+	_SC_CHILD_MAX                  :: 16
+	_SC_CLK_TCK                    :: 17
+	_SC_JOB_CONTROL                :: 18
+	_SC_NGROUPS_MAX                :: 19
+	_SC_OPEN_MAX                   :: 20
+	_SC_SAVED_IDS                  :: 21
+	_SC_STREAM_MAX                 :: 22
+	_SC_TZNAME_MAX                 :: 23
+	_SC_VERSION                    :: 24
+	_SC_GETGR_R_SIZE_MAX           :: 25
+	_SC_GETPW_R_SIZE_MAX           :: 26
+	_SC_PAGE_SIZE                  :: 27
+	_SC_PAGESIZE                   :: _SC_PAGE_SIZE
+	_SC_SEM_NSEMS_MAX              :: 28
+	_SC_SEM_VALUE_MAX              :: 29
+	_SC_SEMAPHORES                 :: 30
+	_SC_THREADS                    :: 31
+	_SC_IOV_MAX                    :: 32
+	_SC_NPROCESSORS_CONF           :: 34
+	_SC_NPROCESSORS_ONLN           :: 35
+	_SC_ATEXIT_MAX                 :: 37
+	_SC_MAPPED_FILES               :: 45
+	_SC_THREAD_PROCESS_SHARED      :: 46
+	_SC_THREAD_STACK_MIN           :: 47
+	_SC_THREAD_ATTR_STACKADDR      :: 48
+	_SC_THREAD_ATTR_STACKSIZE      :: 49
+	_SC_THREAD_PRIORITY_SCHEDULING :: 50
+	_SC_REALTIME_SIGNALS           :: 51
+	_SC_MEMORY_PROTECTION          :: 52
+	_SC_SIGQUEUE_MAX               :: 53
+	_SC_RTSIG_MAX                  :: 54
+	_SC_MONOTONIC_CLOCK            :: 55
+	_SC_DELAYTIMER_MAX             :: 56
+	_SC_TIMER_MAX                  :: 57
+	_SC_TIMERS                     :: 58
+	_SC_CPUTIME                    :: 59
+	_SC_THREAD_CPUTIME             :: 60
+	_SC_HOST_NAME_MAX              :: 61
+	_SC_REGEXP                     :: 62
+	_SC_SYMLOOP_MAX                :: 63
+	_SC_SHELL                      :: 64
+	_SC_TTY_NAME_MAX               :: 65
+	_SC_ADVISORY_INFO              :: 66
+	_SC_BARRIERS                   :: 67
+	_SC_CLOCK_SELECTION            :: 68
+	_SC_FSYNC                      :: 69
+	_SC_IPV6                       :: 70
+	_SC_MEMLOCK                    :: 71
+	_SC_MEMLOCK_RANGE              :: 72
+	_SC_MESSAGE_PASSING            :: 73
+	_SC_PRIORITIZED_IO             :: 74
+	_SC_PRIORITY_SCHEDULING        :: 75
+	_SC_READER_WRITER_LOCKS        :: 76
+	_SC_SHARED_MEMORY_OBJECTS      :: 77
+	_SC_SPAWN                      :: 78
+	_SC_SPIN_LOCKS                 :: 79
+	_SC_SPORADIC_SERVER            :: 80
+	_SC_SYNCHRONIZED_IO            :: 81
+	_SC_THREAD_PRIO_INHERIT        :: 82
+	_SC_THREAD_PRIO_PROTECT        :: 83
+	_SC_THREAD_SAFE_FUNCTIONS      :: 86
+	_SC_THREAD_SPORADIC_SERVER     :: 87
+	_SC_TIMEOUTS                   :: 88
+	_SC_TRACE                      :: 89
+	_SC_TRACE_EVENT_FILTER         :: 90
+	_SC_TRACE_INHERIT              :: 91
+	_SC_TRACE_LOG                  :: 92
+	_SC_TYPED_MEMORY_OBJECTS       :: 93
+	_SC_V6_ILP32_OFF32             :: 94
+	_SC_V6_ILP32_OFFBIG            :: 95
+	_SC_V6_LP64_OFF64              :: 96
+	_SC_V6_LPBIG_OFFBIG            :: 97
+	_SC_2_C_BIND                   :: 102
+	_SC_2_C_DEV                    :: 103
+	_SC_2_CHAR_TERM                :: 104
+	_SC_2_FORT_DEV                 :: 105
+	_SC_2_FORT_RUN                 :: 106
+	_SC_2_LOCALEDEF                :: 107
+	_SC_2_PBS                      :: 108
+	_SC_2_PBS_ACCOUNTING           :: 109
+	_SC_2_PBS_CHECKPOINT           :: 110
+	_SC_2_PBS_LOCATE               :: 111
+	_SC_2_PBS_MESSAGE              :: 112
+	_SC_2_PBS_TRACK                :: 113
+	_SC_2_SW_DEV                   :: 114
+	_SC_2_UPE                      :: 115
+	_SC_2_VERSION                  :: 116
+	_SC_XOPEN_CRYPT                :: 117
+	_SC_XOPEN_ENH_I18N             :: 118
+	_SC_XOPEN_REALTIME             :: 119
+	_SC_XOPEN_REALTIME_THREADS     :: 120
+	_SC_XOPEN_SHM                  :: 121
+	_SC_XOPEN_STREAMS              :: 122
+	_SC_XOPEN_UNIX                   :: 123
+	_SC_XOPEN_VERSION                :: 125
+	_SC_AIO_LISTIO_MAX               :: 126
+	_SC_AIO_MAX                      :: 127
+	_SC_AIO_PRIO_DELTA_MAX           :: 128
+	_SC_BC_BASE_MAX                  :: 129
+	_SC_BC_DIM_MAX                   :: 130
+	_SC_BC_SCALE_MAX                 :: 131
+	_SC_BC_STRING_MAX                :: 132
+	_SC_COLL_WEIGHTS_MAX             :: 133
+	_SC_EXPR_NEST_MAX                :: 134
+	_SC_LINE_MAX                     :: 135
+	_SC_LOGIN_NAME_MAX               :: 136
+	_SC_MQ_OPEN_MAX                  :: 137
+	_SC_MQ_PRIO_MAX                  :: 138
+	_SC_THREAD_DESTRUCTOR_ITERATIONS :: 139
+	_SC_THREAD_KEYS_MAX              :: 140
+	_SC_THREAD_THREADS_MAX           :: 141
+	_SC_RE_DUP_MAX                   :: 142
+
 }

+ 1 - 1
core/sys/posix/unistd_libc.odin

@@ -1,4 +1,4 @@
-#+build linux, windows, darwin, netbsd, openbsd, freebsd
+#+build linux, windows, darwin, netbsd, openbsd, freebsd, haiku
 package posix
 
 import "core:c"

+ 2 - 2
core/sys/posix/utime.odin

@@ -1,4 +1,4 @@
-#+build linux, darwin, netbsd, openbsd, freebsd
+#+build linux, darwin, netbsd, openbsd, freebsd, haiku
 package posix
 
 when ODIN_OS == .Darwin {
@@ -25,7 +25,7 @@ when ODIN_OS == .NetBSD {
 	@(private) LUTIME :: "utime"
 }
 
-when ODIN_OS == .Darwin || ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD || ODIN_OS == .OpenBSD	|| ODIN_OS == .Linux {
+when ODIN_OS == .Darwin || ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD || ODIN_OS == .OpenBSD || ODIN_OS == .Linux || ODIN_OS == .Haiku {
 
 	utimbuf :: struct {
 		actime:  time_t, /* [PSX] access time (seconds since epoch) */