summary refs log tree commit diff stats
path: root/lib/posix/posix.nim
diff options
context:
space:
mode:
Diffstat (limited to 'lib/posix/posix.nim')
-rw-r--r--lib/posix/posix.nim329
1 files changed, 209 insertions, 120 deletions
diff --git a/lib/posix/posix.nim b/lib/posix/posix.nim
index 70ba53a2e..fbe945df3 100644
--- a/lib/posix/posix.nim
+++ b/lib/posix/posix.nim
@@ -27,17 +27,19 @@
 ## the \`identifier\` notation is used.
 ##
 ## This library relies on the header files of your C compiler. The
-## resulting C code will just ``#include <XYZ.h>`` and *not* define the
+## resulting C code will just `#include <XYZ.h>` and *not* define the
 ## symbols declared here.
 
 # Dead code elimination ensures that we don't accidentally generate #includes
 # for files that might not exist on a specific platform! The user will get an
 # error only if they actually try to use the missing declaration
-{.deadCodeElim: on.}  # dce option deprecated
 
 when defined(nimHasStyleChecks):
   {.push styleChecks: off.}
 
+when defined(nimPreviewSlimSystem):
+  import std/syncio
+
 # TODO these constants don't seem to be fetched from a header file for unknown
 #      platforms - where do they come from and why are they here?
 when false:
@@ -89,10 +91,10 @@ const
 type Sighandler = proc (a: cint) {.noconv.}
 
 const StatHasNanoseconds* = defined(linux) or defined(freebsd) or
-    defined(osx) or defined(openbsd) or defined(dragonfly) ## \
+    defined(osx) or defined(openbsd) or defined(dragonfly) or defined(haiku) ## \
   ## Boolean flag that indicates if the system supports nanosecond time
-  ## resolution in the fields of ``Stat``. Note that the nanosecond based fields
-  ## (``Stat.st_atim``, ``Stat.st_mtim`` and ``Stat.st_ctim``) can be accessed
+  ## resolution in the fields of `Stat`. Note that the nanosecond based fields
+  ## (`Stat.st_atim`, `Stat.st_mtim` and `Stat.st_ctim`) can be accessed
   ## without checking this flag, because this module defines fallback procs
   ## when they are not available.
 
@@ -106,6 +108,8 @@ elif (defined(macos) or defined(macosx) or defined(bsd)) and defined(cpu64):
   include posix_macos_amd64
 elif defined(nintendoswitch):
   include posix_nintendoswitch
+elif defined(haiku):
+  include posix_haiku
 else:
   include posix_other
 
@@ -150,11 +154,13 @@ proc htons*(a1: uint16): uint16 {.importc, header: "<arpa/inet.h>".}
 proc ntohl*(a1: uint32): uint32 {.importc, header: "<arpa/inet.h>".}
 proc ntohs*(a1: uint16): uint16 {.importc, header: "<arpa/inet.h>".}
 
-proc inet_addr*(a1: cstring): InAddrT {.importc, header: "<arpa/inet.h>".}
-proc inet_ntoa*(a1: InAddr): cstring {.importc, header: "<arpa/inet.h>".}
-proc inet_ntop*(a1: cint, a2: pointer, a3: cstring, a4: int32): cstring {.
+when not defined(zephyr):
+  proc inet_addr*(a1: cstring): InAddrT {.importc, header: "<arpa/inet.h>".}
+  proc inet_ntoa*(a1: InAddr): cstring {.importc, header: "<arpa/inet.h>".}
+
+proc inet_ntop*(a1: cint, a2: pointer | ptr InAddr | ptr In6Addr, a3: cstring, a4: int32): cstring {.
   importc:"(char *)$1", header: "<arpa/inet.h>".}
-proc inet_pton*(a1: cint, a2: cstring, a3: pointer): cint {.
+proc inet_pton*(a1: cint, a2: cstring, a3: pointer | ptr InAddr | ptr In6Addr): cint {.
   importc, header: "<arpa/inet.h>".}
 
 var
@@ -166,29 +172,54 @@ proc IN6ADDR_LOOPBACK_INIT* (): In6Addr {.importc, header: "<netinet/in.h>".}
 
 # dirent.h
 proc closedir*(a1: ptr DIR): cint  {.importc, header: "<dirent.h>".}
-proc opendir*(a1: cstring): ptr DIR {.importc, header: "<dirent.h>".}
-proc readdir*(a1: ptr DIR): ptr Dirent  {.importc, header: "<dirent.h>".}
+proc opendir*(a1: cstring): ptr DIR {.importc, header: "<dirent.h>", sideEffect.}
+proc readdir*(a1: ptr DIR): ptr Dirent  {.importc, header: "<dirent.h>", sideEffect.}
 proc readdir_r*(a1: ptr DIR, a2: ptr Dirent, a3: ptr ptr Dirent): cint  {.
-                importc, header: "<dirent.h>".}
+                importc, header: "<dirent.h>", sideEffect.}
 proc rewinddir*(a1: ptr DIR)  {.importc, header: "<dirent.h>".}
 proc seekdir*(a1: ptr DIR, a2: int)  {.importc, header: "<dirent.h>".}
 proc telldir*(a1: ptr DIR): int {.importc, header: "<dirent.h>".}
 
 # dlfcn.h
-proc dlclose*(a1: pointer): cint {.importc, header: "<dlfcn.h>".}
-proc dlerror*(): cstring {.importc, header: "<dlfcn.h>".}
-proc dlopen*(a1: cstring, a2: cint): pointer {.importc, header: "<dlfcn.h>".}
-proc dlsym*(a1: pointer, a2: cstring): pointer {.importc, header: "<dlfcn.h>".}
-
-proc creat*(a1: cstring, a2: Mode): cint {.importc, header: "<fcntl.h>".}
-proc fcntl*(a1: cint | SocketHandle, a2: cint): cint {.varargs, importc, header: "<fcntl.h>".}
-proc open*(a1: cstring, a2: cint): cint {.varargs, importc, header: "<fcntl.h>".}
+proc dlclose*(a1: pointer): cint {.importc, header: "<dlfcn.h>", sideEffect.}
+proc dlerror*(): cstring {.importc, header: "<dlfcn.h>", sideEffect.}
+proc dlopen*(a1: cstring, a2: cint): pointer {.importc, header: "<dlfcn.h>", sideEffect.}
+proc dlsym*(a1: pointer, a2: cstring): pointer {.importc, header: "<dlfcn.h>", sideEffect.}
+
+proc creat*(a1: cstring, a2: Mode): cint {.importc, header: "<fcntl.h>", sideEffect.}
+proc fcntl*(a1: cint | SocketHandle, a2: cint): cint {.varargs, importc, header: "<fcntl.h>", sideEffect.}
+proc openImpl(a1: cstring, a2: cint): cint {.varargs, importc: "open", header: "<fcntl.h>", sideEffect.}
+proc open*(a1: cstring, a2: cint, mode: Mode | cint = 0.Mode): cint {.inline.} =
+  # prevents bug #17888
+  openImpl(a1, a2, mode)
+
 proc posix_fadvise*(a1: cint, a2, a3: Off, a4: cint): cint {.
   importc, header: "<fcntl.h>".}
-proc posix_fallocate*(a1: cint, a2, a3: Off): cint {.
-  importc, header: "<fcntl.h>".}
 
-when not defined(haiku) and not defined(OpenBSD):
+proc ftruncate*(a1: cint, a2: Off): cint {.importc, header: "<unistd.h>".}
+when defined(osx):              # 2001 POSIX evidently does not concern Apple
+  type FStore {.importc: "fstore_t", header: "<fcntl.h>", bycopy.} = object
+    fst_flags: uint32           ## IN: flags word
+    fst_posmode: cint           ## IN: indicates offset field
+    fst_offset,                 ## IN: start of the region
+      fst_length,               ## IN: size of the region
+      fst_bytesalloc: Off       ## OUT: number of bytes allocated
+  var F_PEOFPOSMODE {.importc, header: "<fcntl.h>".}: cint
+  var F_ALLOCATEALL {.importc, header: "<fcntl.h>".}: uint32
+  var F_PREALLOCATE {.importc, header: "<fcntl.h>".}: cint
+  proc posix_fallocate*(a1: cint, a2, a3: Off): cint =
+    var fst = FStore(fst_flags: F_ALLOCATEALL, fst_posmode: F_PEOFPOSMODE,
+                     fst_offset: a2, fst_length: a3)
+    # Must also call ftruncate to match what POSIX does. Unlike posix_fallocate,
+    # this can shrink files.  Could guard w/getFileSize, but caller likely knows
+    # present size & has no good reason to call this unless it is growing.
+    if fcntl(a1, F_PREALLOCATE, fst.addr) != cint(-1): ftruncate(a1, a2 + a3)
+    else: cint(-1)
+else:
+  proc posix_fallocate*(a1: cint, a2, a3: Off): cint {.
+    importc, header: "<fcntl.h>".}
+
+when not defined(haiku) and not defined(openbsd):
   proc fmtmsg*(a1: int, a2: cstring, a3: cint,
               a4, a5, a6: cstring): cint {.importc, header: "<fmtmsg.h>".}
 
@@ -205,7 +236,7 @@ when not (defined(linux) and defined(amd64)) and not defined(nintendoswitch):
 
 proc glob*(a1: cstring, a2: cint,
           a3: proc (x1: cstring, x2: cint): cint {.noconv.},
-          a4: ptr Glob): cint {.importc, header: "<glob.h>".}
+          a4: ptr Glob): cint {.importc, header: "<glob.h>", sideEffect.}
   ## Filename globbing. Use `os.walkPattern() <os.html#glob_1>`_ and similar.
 
 proc globfree*(a1: ptr Glob) {.importc, header: "<glob.h>".}
@@ -234,31 +265,57 @@ proc dirname*(a1: cstring): cstring {.importc, header: "<libgen.h>".}
 
 proc localeconv*(): ptr Lconv {.importc, header: "<locale.h>".}
 proc setlocale*(a1: cint, a2: cstring): cstring {.
-                importc, header: "<locale.h>".}
+                importc, header: "<locale.h>", sideEffect.}
 
 proc strfmon*(a1: cstring, a2: int, a3: cstring): int {.varargs,
    importc, header: "<monetary.h>".}
 
-when not defined(nintendoswitch):
-  proc mq_close*(a1: Mqd): cint {.importc, header: "<mqueue.h>".}
-  proc mq_getattr*(a1: Mqd, a2: ptr MqAttr): cint {.
-    importc, header: "<mqueue.h>".}
-  proc mq_notify*(a1: Mqd, a2: ptr SigEvent): cint {.
+when not (defined(nintendoswitch) or defined(macos) or defined(macosx)):
+  proc mq_notify*(mqdes: Mqd, event: ptr SigEvent): cint {.
     importc, header: "<mqueue.h>".}
-  proc mq_open*(a1: cstring, a2: cint): Mqd {.
+
+  proc mq_open*(name: cstring, flags: cint): Mqd {.
     varargs, importc, header: "<mqueue.h>".}
-  proc mq_receive*(a1: Mqd, a2: cstring, a3: int, a4: var int): int {.
-    importc, header: "<mqueue.h>".}
-  proc mq_send*(a1: Mqd, a2: cstring, a3: int, a4: int): cint {.
+
+  proc mq_close*(mqdes: Mqd): cint {.importc, header: "<mqueue.h>".}
+
+  proc mq_receive*(
+    mqdes: Mqd,
+    buffer: cstring,
+    length: csize_t,
+    priority: var cuint
+  ): int {.importc, header: "<mqueue.h>".}
+
+  proc mq_timedreceive*(
+    mqdes: Mqd,
+    buffer: cstring,
+    length: csize_t,
+    priority: cuint,
+    timeout: ptr Timespec
+  ): int {.importc, header: "<mqueue.h>".}
+
+  proc mq_send*(
+    mqdes: Mqd,
+    buffer: cstring,
+    length: csize_t,
+    priority: cuint
+  ): cint {.importc, header: "<mqueue.h>".}
+
+  proc mq_timedsend*(
+    mqdes: Mqd,
+    buffer: cstring,
+    length: csize_t,
+    priority: cuint,
+    timeout: ptr Timespec
+  ): cint {.importc, header: "<mqueue.h>".}
+
+  proc mq_getattr*(mqdes: Mqd, attribute: ptr MqAttr): cint {.
     importc, header: "<mqueue.h>".}
-  proc mq_setattr*(a1: Mqd, a2, a3: ptr MqAttr): cint {.
+
+  proc mq_setattr*(mqdes: Mqd, newAttribute, oldAttribute: ptr MqAttr): cint {.
     importc, header: "<mqueue.h>".}
 
-  proc mq_timedreceive*(a1: Mqd, a2: cstring, a3: int, a4: int,
-                        a5: ptr Timespec): int {.importc, header: "<mqueue.h>".}
-  proc mq_timedsend*(a1: Mqd, a2: cstring, a3: int, a4: int,
-                     a5: ptr Timespec): cint {.importc, header: "<mqueue.h>".}
-  proc mq_unlink*(a1: cstring): cint {.importc, header: "<mqueue.h>".}
+  proc mq_unlink*(mqdes: cstring): cint {.importc, header: "<mqueue.h>".}
 
 
 proc getpwnam*(a1: cstring): ptr Passwd {.importc, header: "<pwd.h>".}
@@ -446,7 +503,7 @@ proc pthread_spin_unlock*(a1: ptr Pthread_spinlock): cint {.
 proc pthread_testcancel*() {.importc, header: "<pthread.h>".}
 
 
-proc exitnow*(code: int): void {.importc: "_exit", header: "<unistd.h>".}
+proc exitnow*(code: int) {.importc: "_exit", header: "<unistd.h>".}
 proc access*(a1: cstring, a2: cint): cint {.importc, header: "<unistd.h>".}
 proc alarm*(a1: cint): cint {.importc, header: "<unistd.h>".}
 proc chdir*(a1: cstring): cint {.importc, header: "<unistd.h>".}
@@ -459,54 +516,53 @@ proc dup*(a1: cint): cint {.importc, header: "<unistd.h>".}
 proc dup2*(a1, a2: cint): cint {.importc, header: "<unistd.h>".}
 proc encrypt*(a1: array[0..63, char], a2: cint) {.importc, header: "<unistd.h>".}
 
-proc execl*(a1, a2: cstring): cint {.varargs, importc, header: "<unistd.h>".}
-proc execle*(a1, a2: cstring): cint {.varargs, importc, header: "<unistd.h>".}
-proc execlp*(a1, a2: cstring): cint {.varargs, importc, header: "<unistd.h>".}
-proc execv*(a1: cstring, a2: cstringArray): cint {.importc, header: "<unistd.h>".}
+proc execl*(a1, a2: cstring): cint {.varargs, importc, header: "<unistd.h>", sideEffect.}
+proc execle*(a1, a2: cstring): cint {.varargs, importc, header: "<unistd.h>", sideEffect.}
+proc execlp*(a1, a2: cstring): cint {.varargs, importc, header: "<unistd.h>", sideEffect.}
+proc execv*(a1: cstring, a2: cstringArray): cint {.importc, header: "<unistd.h>", sideEffect.}
 proc execve*(a1: cstring, a2, a3: cstringArray): cint {.
-  importc, header: "<unistd.h>".}
-proc execvp*(a1: cstring, a2: cstringArray): cint {.importc, header: "<unistd.h>".}
-proc execvpe*(a1: cstring, a2: cstringArray, a3: cstringArray): cint {.importc, header: "<unistd.h>".}
-proc fchown*(a1: cint, a2: Uid, a3: Gid): cint {.importc, header: "<unistd.h>".}
-proc fchdir*(a1: cint): cint {.importc, header: "<unistd.h>".}
+  importc, header: "<unistd.h>", sideEffect.}
+proc execvp*(a1: cstring, a2: cstringArray): cint {.importc, header: "<unistd.h>", sideEffect.}
+proc execvpe*(a1: cstring, a2: cstringArray, a3: cstringArray): cint {.importc, header: "<unistd.h>", sideEffect.}
+proc fchown*(a1: cint, a2: Uid, a3: Gid): cint {.importc, header: "<unistd.h>", sideEffect.}
+proc fchdir*(a1: cint): cint {.importc, header: "<unistd.h>", sideEffect.}
 proc fdatasync*(a1: cint): cint {.importc, header: "<unistd.h>".}
-proc fork*(): Pid {.importc, header: "<unistd.h>".}
+proc fork*(): Pid {.importc, header: "<unistd.h>", sideEffect.}
 proc fpathconf*(a1, a2: cint): int {.importc, header: "<unistd.h>".}
 proc fsync*(a1: cint): cint {.importc, header: "<unistd.h>".}
  ## synchronize a file's buffer cache to the storage device
 
-proc ftruncate*(a1: cint, a2: Off): cint {.importc, header: "<unistd.h>".}
-proc getcwd*(a1: cstring, a2: int): cstring {.importc, header: "<unistd.h>".}
-proc getuid*(): Uid {.importc, header: "<unistd.h>".}
+proc getcwd*(a1: cstring, a2: int): cstring {.importc, header: "<unistd.h>", sideEffect.}
+proc getuid*(): Uid {.importc, header: "<unistd.h>", sideEffect.}
  ## returns the real user ID of the calling process
 
-proc geteuid*(): Uid {.importc, header: "<unistd.h>".}
+proc geteuid*(): Uid {.importc, header: "<unistd.h>", sideEffect.}
  ## returns the effective user ID of the calling process
 
-proc getgid*(): Gid {.importc, header: "<unistd.h>".}
+proc getgid*(): Gid {.importc, header: "<unistd.h>", sideEffect.}
  ## returns the real group ID of the calling process
 
-proc getegid*(): Gid {.importc, header: "<unistd.h>".}
+proc getegid*(): Gid {.importc, header: "<unistd.h>", sideEffect.}
  ## returns the effective group ID of the calling process
 
 proc getgroups*(a1: cint, a2: ptr array[0..255, Gid]): cint {.
   importc, header: "<unistd.h>".}
-proc gethostid*(): int {.importc, header: "<unistd.h>".}
-proc gethostname*(a1: cstring, a2: int): cint {.importc, header: "<unistd.h>".}
-proc getlogin*(): cstring {.importc, header: "<unistd.h>".}
-proc getlogin_r*(a1: cstring, a2: int): cint {.importc, header: "<unistd.h>".}
+proc gethostid*(): int {.importc, header: "<unistd.h>", sideEffect.}
+proc gethostname*(a1: cstring, a2: int): cint {.importc, header: "<unistd.h>", sideEffect.}
+proc getlogin*(): cstring {.importc, header: "<unistd.h>", sideEffect.}
+proc getlogin_r*(a1: cstring, a2: int): cint {.importc, header: "<unistd.h>", sideEffect.}
 
 proc getopt*(a1: cint, a2: cstringArray, a3: cstring): cint {.
   importc, header: "<unistd.h>".}
 proc getpgid*(a1: Pid): Pid {.importc, header: "<unistd.h>".}
 proc getpgrp*(): Pid {.importc, header: "<unistd.h>".}
-proc getpid*(): Pid {.importc, header: "<unistd.h>".}
+proc getpid*(): Pid {.importc, header: "<unistd.h>", sideEffect.}
  ## returns  the process ID (PID) of the calling process
 
-proc getppid*(): Pid {.importc, header: "<unistd.h>".}
+proc getppid*(): Pid {.importc, header: "<unistd.h>", sideEffect.}
  ## returns the process ID of the parent of the calling process
 
-proc getsid*(a1: Pid): Pid {.importc, header: "<unistd.h>".}
+proc getsid*(a1: Pid): Pid {.importc, header: "<unistd.h>", sideEffect.}
  ## returns the session ID of the calling process
 
 proc getwd*(a1: cstring): cstring {.importc, header: "<unistd.h>".}
@@ -528,7 +584,8 @@ proc pread*(a1: cint, a2: pointer, a3: int, a4: Off): int {.
 proc pwrite*(a1: cint, a2: pointer, a3: int, a4: Off): int {.
   importc, header: "<unistd.h>".}
 proc read*(a1: cint, a2: pointer, a3: int): int {.importc, header: "<unistd.h>".}
-proc readlink*(a1, a2: cstring, a3: int): int {.importc, header: "<unistd.h>".}
+when not defined(nintendoswitch):
+  proc readlink*(a1, a2: cstring, a3: int): int {.importc, header: "<unistd.h>".}
 proc ioctl*(f: FileHandle, device: uint): int {.importc: "ioctl",
       header: "<sys/ioctl.h>", varargs, tags: [WriteIOEffect].}
   ## A system call for device-specific input/output operations and other
@@ -547,7 +604,10 @@ proc setsid*(): Pid {.importc, header: "<unistd.h>".}
 proc setuid*(a1: Uid): cint {.importc, header: "<unistd.h>".}
 proc sleep*(a1: cint): cint {.importc, header: "<unistd.h>".}
 proc swab*(a1, a2: pointer, a3: int) {.importc, header: "<unistd.h>".}
-proc symlink*(a1, a2: cstring): cint {.importc, header: "<unistd.h>".}
+when not defined(nintendoswitch):
+  proc symlink*(a1, a2: cstring): cint {.importc, header: "<unistd.h>".}
+else:
+  proc symlink*(a1, a2: cstring): cint = -1
 proc sync*() {.importc, header: "<unistd.h>".}
 proc sysconf*(a1: cint): int {.importc, header: "<unistd.h>".}
 proc tcgetpgrp*(a1: cint): Pid {.importc, header: "<unistd.h>".}
@@ -584,11 +644,13 @@ proc statvfs*(a1: cstring, a2: var Statvfs): cint {.
 proc fstatvfs*(a1: cint, a2: var Statvfs): cint {.
   importc, header: "<sys/statvfs.h>".}
 
-proc chmod*(a1: cstring, a2: Mode): cint {.importc, header: "<sys/stat.h>".}
-proc fchmod*(a1: cint, a2: Mode): cint {.importc, header: "<sys/stat.h>".}
-proc fstat*(a1: cint, a2: var Stat): cint {.importc, header: "<sys/stat.h>".}
-proc lstat*(a1: cstring, a2: var Stat): cint {.importc, header: "<sys/stat.h>".}
-proc mkdir*(a1: cstring, a2: Mode): cint {.importc, header: "<sys/stat.h>".}
+proc chmod*(a1: cstring, a2: Mode): cint {.importc, header: "<sys/stat.h>", sideEffect.}
+when defined(osx) or defined(freebsd):
+  proc lchmod*(a1: cstring, a2: Mode): cint {.importc, header: "<sys/stat.h>", sideEffect.}
+proc fchmod*(a1: cint, a2: Mode): cint {.importc, header: "<sys/stat.h>", sideEffect.}
+proc fstat*(a1: cint, a2: var Stat): cint {.importc, header: "<sys/stat.h>", sideEffect.}
+proc lstat*(a1: cstring, a2: var Stat): cint {.importc, header: "<sys/stat.h>", sideEffect.}
+proc mkdir*(a1: cstring, a2: Mode): cint {.importc, header: "<sys/stat.h>", sideEffect.}
   ## Use `os.createDir() <os.html#createDir,string>`_ and similar.
 
 proc mkfifo*(a1: cstring, a2: Mode): cint {.importc, header: "<sys/stat.h>".}
@@ -637,7 +699,8 @@ proc posix_madvise*(a1: pointer, a2: int, a3: cint): cint {.
   importc, header: "<sys/mman.h>".}
 proc posix_mem_offset*(a1: pointer, a2: int, a3: var Off,
            a4: var int, a5: var cint): cint {.importc, header: "<sys/mman.h>".}
-when not (defined(linux) and defined(amd64)) and not defined(nintendoswitch):
+when not (defined(linux) and defined(amd64)) and not defined(nintendoswitch) and
+     not defined(haiku):
   proc posix_typed_mem_get_info*(a1: cint,
     a2: var Posix_typed_mem_info): cint {.importc, header: "<sys/mman.h>".}
 proc posix_typed_mem_open*(a1: cstring, a2, a3: cint): cint {.
@@ -649,17 +712,17 @@ proc shm_unlink*(a1: cstring): cint {.importc, header: "<sys/mman.h>".}
 proc asctime*(a1: var Tm): cstring{.importc, header: "<time.h>".}
 
 proc asctime_r*(a1: var Tm, a2: cstring): cstring {.importc, header: "<time.h>".}
-proc clock*(): Clock {.importc, header: "<time.h>".}
+proc clock*(): Clock {.importc, header: "<time.h>", sideEffect.}
 proc clock_getcpuclockid*(a1: Pid, a2: var ClockId): cint {.
-  importc, header: "<time.h>".}
+  importc, header: "<time.h>", sideEffect.}
 proc clock_getres*(a1: ClockId, a2: var Timespec): cint {.
-  importc, header: "<time.h>".}
+  importc, header: "<time.h>", sideEffect.}
 proc clock_gettime*(a1: ClockId, a2: var Timespec): cint {.
-  importc, header: "<time.h>".}
+  importc, header: "<time.h>", sideEffect.}
 proc clock_nanosleep*(a1: ClockId, a2: cint, a3: var Timespec,
-               a4: var Timespec): cint {.importc, header: "<time.h>".}
+               a4: var Timespec): cint {.importc, header: "<time.h>", sideEffect.}
 proc clock_settime*(a1: ClockId, a2: var Timespec): cint {.
-  importc, header: "<time.h>".}
+  importc, header: "<time.h>", sideEffect.}
 
 proc `==`*(a, b: Time): bool {.borrow.}
 proc `-`*(a, b: Time): Time {.borrow.}
@@ -673,11 +736,11 @@ proc localtime*(a1: var Time): ptr Tm {.importc, header: "<time.h>".}
 proc localtime_r*(a1: var Time, a2: var Tm): ptr Tm {.importc, header: "<time.h>".}
 proc mktime*(a1: var Tm): Time  {.importc, header: "<time.h>".}
 proc timegm*(a1: var Tm): Time  {.importc, header: "<time.h>".}
-proc nanosleep*(a1, a2: var Timespec): cint {.importc, header: "<time.h>".}
+proc nanosleep*(a1, a2: var Timespec): cint {.importc, header: "<time.h>", sideEffect.}
 proc strftime*(a1: cstring, a2: int, a3: cstring,
            a4: var Tm): int {.importc, header: "<time.h>".}
 proc strptime*(a1, a2: cstring, a3: var Tm): cstring {.importc, header: "<time.h>".}
-proc time*(a1: var Time): Time {.importc, header: "<time.h>".}
+proc time*(a1: var Time): Time {.importc, header: "<time.h>", sideEffect.}
 proc timer_create*(a1: ClockId, a2: var SigEvent,
                a3: var Timer): cint {.importc, header: "<time.h>".}
 proc timer_delete*(a1: Timer): cint {.importc, header: "<time.h>".}
@@ -689,11 +752,11 @@ proc timer_settime*(a1: Timer, a2: cint, a3: var Itimerspec,
 proc tzset*() {.importc, header: "<time.h>".}
 
 
-proc wait*(a1: ptr cint): Pid {.importc, discardable, header: "<sys/wait.h>".}
+proc wait*(a1: ptr cint): Pid {.importc, discardable, header: "<sys/wait.h>", sideEffect.}
 proc waitid*(a1: cint, a2: Id, a3: var SigInfo, a4: cint): cint {.
-  importc, header: "<sys/wait.h>".}
+  importc, header: "<sys/wait.h>", sideEffect.}
 proc waitpid*(a1: Pid, a2: var cint, a3: cint): Pid {.
-  importc, header: "<sys/wait.h>".}
+  importc, header: "<sys/wait.h>", sideEffect.}
 
 type Rusage* {.importc: "struct rusage", header: "<sys/resource.h>",
                bycopy.} = object
@@ -704,7 +767,7 @@ type Rusage* {.importc: "struct rusage", header: "<sys/resource.h>",
     ru_nsignals*, ru_nvcsw*, ru_nivcsw*: clong        # switching activity
 
 proc wait4*(pid: Pid, status: ptr cint, options: cint, rusage: ptr Rusage): Pid
-  {.importc, header: "<sys/wait.h>".}
+  {.importc, header: "<sys/wait.h>", sideEffect.}
 
 const
   RUSAGE_SELF* = cint(0)
@@ -717,8 +780,8 @@ proc getrusage*(who: cint, rusage: ptr Rusage): cint
 
 proc bsd_signal*(a1: cint, a2: proc (x: pointer) {.noconv.}) {.
   importc, header: "<signal.h>".}
-proc kill*(a1: Pid, a2: cint): cint {.importc, header: "<signal.h>".}
-proc killpg*(a1: Pid, a2: cint): cint {.importc, header: "<signal.h>".}
+proc kill*(a1: Pid, a2: cint): cint {.importc, header: "<signal.h>", sideEffect.}
+proc killpg*(a1: Pid, a2: cint): cint {.importc, header: "<signal.h>", sideEffect.}
 proc pthread_kill*(a1: Pthread, a2: cint): cint {.importc, header: "<signal.h>".}
 proc pthread_sigmask*(a1: cint, a2, a3: var Sigset): cint {.
   importc, header: "<signal.h>".}
@@ -762,6 +825,13 @@ else:
   proc sigtimedwait*(a1: var Sigset, a2: var SigInfo,
                      a3: var Timespec): cint {.importc, header: "<signal.h>".}
 
+when defined(sunos) or defined(solaris):
+  # The following compile time flag is needed on Illumos/Solaris to use the POSIX
+  # `sigwait` implementation. See the documentation here:
+  # https://docs.oracle.com/cd/E19455-01/806-5257/6je9h033k/index.html
+  # https://www.illumos.org/man/2/sigwait
+  {.passc: "-D_POSIX_PTHREAD_SEMANTICS".}
+
 proc sigwait*(a1: var Sigset, a2: var cint): cint {.
   importc, header: "<signal.h>".}
 proc sigwaitinfo*(a1: var Sigset, a2: var SigInfo): cint {.
@@ -874,15 +944,9 @@ proc CMSG_NXTHDR*(mhdr: ptr Tmsghdr, cmsg: ptr Tcmsghdr): ptr Tcmsghdr {.
 proc CMSG_FIRSTHDR*(mhdr: ptr Tmsghdr): ptr Tcmsghdr {.
   importc, header: "<sys/socket.h>".}
 
-proc CMSG_SPACE*(len: csize): csize {.
-  importc, header: "<sys/socket.h>", deprecated: "argument `len` should be of type `csize_t`".}
-
 proc CMSG_SPACE*(len: csize_t): csize_t {.
   importc, header: "<sys/socket.h>".}
 
-proc CMSG_LEN*(len: csize): csize {.
-  importc, header: "<sys/socket.h>", deprecated: "argument `len` should be of type `csize_t`".}
-
 proc CMSG_LEN*(len: csize_t): csize_t {.
   importc, header: "<sys/socket.h>".}
 
@@ -892,11 +956,15 @@ const
 proc `==`*(x, y: SocketHandle): bool {.borrow.}
 
 proc accept*(a1: SocketHandle, a2: ptr SockAddr, a3: ptr SockLen): SocketHandle {.
-  importc, header: "<sys/socket.h>".}
+  importc, header: "<sys/socket.h>", sideEffect.}
+
+when defined(linux) or defined(bsd) or defined(nuttx):
+  proc accept4*(a1: SocketHandle, a2: ptr SockAddr, a3: ptr SockLen,
+                flags: cint): SocketHandle {.importc, header: "<sys/socket.h>".}
 
 proc bindSocket*(a1: SocketHandle, a2: ptr SockAddr, a3: SockLen): cint {.
   importc: "bind", header: "<sys/socket.h>".}
-  ## is Posix's ``bind``, because ``bind`` is a reserved word
+  ## is Posix's `bind`, because `bind` is a reserved word
 
 proc connect*(a1: SocketHandle, a2: ptr SockAddr, a3: SockLen): cint {.
   importc, header: "<sys/socket.h>".}
@@ -909,21 +977,21 @@ proc getsockopt*(a1: SocketHandle, a2, a3: cint, a4: pointer, a5: ptr SockLen):
   importc, header: "<sys/socket.h>".}
 
 proc listen*(a1: SocketHandle, a2: cint): cint {.
-  importc, header: "<sys/socket.h>".}
+  importc, header: "<sys/socket.h>", sideEffect.}
 proc recv*(a1: SocketHandle, a2: pointer, a3: int, a4: cint): int {.
-  importc, header: "<sys/socket.h>".}
+  importc, header: "<sys/socket.h>", sideEffect.}
 proc recvfrom*(a1: SocketHandle, a2: pointer, a3: int, a4: cint,
         a5: ptr SockAddr, a6: ptr SockLen): int {.
-  importc, header: "<sys/socket.h>".}
+  importc, header: "<sys/socket.h>", sideEffect.}
 proc recvmsg*(a1: SocketHandle, a2: ptr Tmsghdr, a3: cint): int {.
-  importc, header: "<sys/socket.h>".}
+  importc, header: "<sys/socket.h>", sideEffect.}
 proc send*(a1: SocketHandle, a2: pointer, a3: int, a4: cint): int {.
-  importc, header: "<sys/socket.h>".}
+  importc, header: "<sys/socket.h>", sideEffect.}
 proc sendmsg*(a1: SocketHandle, a2: ptr Tmsghdr, a3: cint): int {.
-  importc, header: "<sys/socket.h>".}
+  importc, header: "<sys/socket.h>", sideEffect.}
 proc sendto*(a1: SocketHandle, a2: pointer, a3: int, a4: cint, a5: ptr SockAddr,
              a6: SockLen): int {.
-  importc, header: "<sys/socket.h>".}
+  importc, header: "<sys/socket.h>", sideEffect.}
 proc setsockopt*(a1: SocketHandle, a2, a3: cint, a4: pointer, a5: SockLen): cint {.
   importc, header: "<sys/socket.h>".}
 proc shutdown*(a1: SocketHandle, a2: cint): cint {.
@@ -956,9 +1024,15 @@ proc IN6_IS_ADDR_LINKLOCAL* (a1: ptr In6Addr): cint {.
 proc IN6_IS_ADDR_SITELOCAL* (a1: ptr In6Addr): cint {.
   importc, header: "<netinet/in.h>".}
   ## Unicast site-local address.
-proc IN6_IS_ADDR_V4MAPPED* (a1: ptr In6Addr): cint {.
-  importc, header: "<netinet/in.h>".}
-  ## IPv4 mapped address.
+when defined(lwip):
+  proc IN6_IS_ADDR_V4MAPPED*(ipv6_address: ptr In6Addr): cint =
+    var bits32: ptr array[4, uint32] = cast[ptr array[4, uint32]](ipv6_address)
+    return (bits32[1] == 0'u32 and bits32[2] == htonl(0x0000FFFF)).cint
+else:
+  proc IN6_IS_ADDR_V4MAPPED* (a1: ptr In6Addr): cint {.
+    importc, header: "<netinet/in.h>".}
+    ## IPv4 mapped address.
+
 proc IN6_IS_ADDR_V4COMPAT* (a1: ptr In6Addr): cint {.
   importc, header: "<netinet/in.h>".}
   ## IPv4-compatible address.
@@ -982,7 +1056,7 @@ proc endhostent*() {.importc, header: "<netdb.h>".}
 proc endnetent*() {.importc, header: "<netdb.h>".}
 proc endprotoent*() {.importc, header: "<netdb.h>".}
 proc endservent*() {.importc, header: "<netdb.h>".}
-proc freeaddrinfo*(a1: ptr AddrInfo) {.importc, header: "<netdb.h>".}
+proc freeAddrInfo*(a1: ptr AddrInfo) {.importc: "freeaddrinfo", header: "<netdb.h>".}
 
 proc gai_strerror*(a1: cint): cstring {.importc:"(char *)$1", header: "<netdb.h>".}
 
@@ -1020,22 +1094,37 @@ proc setnetent*(a1: cint) {.importc, header: "<netdb.h>".}
 proc setprotoent*(a1: cint) {.importc, header: "<netdb.h>".}
 proc setservent*(a1: cint) {.importc, header: "<netdb.h>".}
 
-proc poll*(a1: ptr TPollfd, a2: Tnfds, a3: int): cint {.
-  importc, header: "<poll.h>".}
+when not defined(lwip):
+  proc poll*(a1: ptr TPollfd, a2: Tnfds, a3: int): cint {.
+    importc, header: "<poll.h>", sideEffect.}
 
 proc realpath*(name, resolved: cstring): cstring {.
   importc: "realpath", header: "<stdlib.h>".}
 
-proc mkstemp*(tmpl: cstring): cint {.importc, header: "<stdlib.h>".}
+proc mkstemp*(tmpl: cstring): cint {.importc, header: "<stdlib.h>", sideEffect.}
   ## Creates a unique temporary file.
   ##
-  ## **Warning**: The `tmpl` argument is written to by `mkstemp` and thus
-  ## can't be a string literal. If in doubt copy the string before passing it.
+  ## .. warning:: The `tmpl` argument is written to by `mkstemp` and thus
+  ##   can't be a string literal. If in doubt make a copy of the cstring before
+  ##   passing it in.
 
-proc mkdtemp*(tmpl: cstring): pointer {.importc, header: "<stdlib.h>".}
+proc mkstemps*(tmpl: cstring, suffixlen: int): cint {.importc, header: "<stdlib.h>", sideEffect.}
+  ## Creates a unique temporary file.
+  ##
+  ## .. warning:: The `tmpl` argument is written to by `mkstemps` and thus
+  ##   can't be a string literal. If in doubt make a copy of the cstring before
+  ##   passing it in.
+
+proc mkdtemp*(tmpl: cstring): pointer {.importc, header: "<stdlib.h>", sideEffect.}
+
+when defined(linux) or defined(bsd) or defined(osx):
+  proc mkostemp*(tmpl: cstring, oflags: cint): cint {.importc, header: "<stdlib.h>", sideEffect.}
+  proc mkostemps*(tmpl: cstring, suffixlen: cint, oflags: cint): cint {.importc, header: "<stdlib.h>", sideEffect.}
+
+  proc posix_memalign*(memptr: pointer, alignment: csize_t, size: csize_t): cint {.importc, header: "<stdlib.h>".}
 
 proc utimes*(path: cstring, times: ptr array[2, Timeval]): int {.
-  importc: "utimes", header: "<sys/time.h>".}
+  importc: "utimes", header: "<sys/time.h>", sideEffect.}
   ## Sets file access and modification times.
   ##
   ## Pass the filename and an array of times to set the access and modification
@@ -1050,15 +1139,15 @@ proc handle_signal(sig: cint, handler: proc (a: cint) {.noconv.}) {.importc: "si
 
 template onSignal*(signals: varargs[cint], body: untyped) =
   ## Setup code to be executed when Unix signals are received. The
-  ## currently handled signal is injected as ``sig`` into the calling
+  ## currently handled signal is injected as `sig` into the calling
   ## scope.
   ##
   ## Example:
-  ##
-  ## .. code-block::
-  ##   from posix import SIGINT, SIGTERM, onSignal
+  ##   ```Nim
+  ##   from std/posix import SIGINT, SIGTERM, onSignal
   ##   onSignal(SIGINT, SIGTERM):
   ##     echo "bye from signal ", sig
+  ##   ```
 
   for s in signals:
     handle_signal(s,
@@ -1075,12 +1164,12 @@ type
   ## The getrlimit() and setrlimit() system calls get and set resource limits respectively.
   ## Each resource has an associated soft and hard limit, as defined by the RLimit structure
 
-proc setrlimit*(resource: cint, rlp: var RLimit): cint
-      {.importc: "setrlimit",header: "<sys/resource.h>".}
+proc setrlimit*(resource: cint, rlp: var RLimit): cint {.
+  importc: "setrlimit", header: "<sys/resource.h>".}
   ## The setrlimit() system calls sets resource limits.
 
-proc getrlimit*(resource: cint, rlp: var RLimit): cint
-      {.importc: "getrlimit",header: "<sys/resource.h>".}
+proc getrlimit*(resource: cint, rlp: var RLimit): cint {.
+  importc: "getrlimit", header: "<sys/resource.h>".}
   ## The getrlimit() system call gets resource limits.
 
 when defined(nimHasStyleChecks):