about summary refs log tree commit diff
path: root/stdio
diff options
context:
space:
mode:
authorPatryk Niedźwiedziński <pniedzwiedzinski19@gmail.com>2021-04-17 10:28:11 +0200
committerPatryk Niedźwiedziński <pniedzwiedzinski19@gmail.com>2021-04-17 10:28:11 +0200
commitb1ddaa81f28b8bbc62d6d50526e0935b173099eb (patch)
treee606c194f8eecdedf3f710ed097cadfe97d60122 /stdio
downloadcat-cosmopolitan-b1ddaa81f28b8bbc62d6d50526e0935b173099eb.tar.gz
cat-cosmopolitan-b1ddaa81f28b8bbc62d6d50526e0935b173099eb.zip
Diffstat (limited to 'stdio')
-rw-r--r--stdio/clearerr.c23
-rw-r--r--stdio/dirstream.c321
-rw-r--r--stdio/dtoa.c25
-rw-r--r--stdio/fbufsize.c27
-rw-r--r--stdio/fclose.c59
-rw-r--r--stdio/fclose_s.c33
-rw-r--r--stdio/fdopen.c50
-rw-r--r--stdio/feof.c26
-rw-r--r--stdio/ferror.c29
-rw-r--r--stdio/fflush.c91
-rw-r--r--stdio/fflush.internal.h21
-rw-r--r--stdio/fgetc.c33
-rw-r--r--stdio/fgetpos.c29
-rw-r--r--stdio/fgets.c46
-rw-r--r--stdio/fgetwc.c51
-rw-r--r--stdio/fgetws.c41
-rw-r--r--stdio/fileno.c31
-rw-r--r--stdio/flbf.c27
-rw-r--r--stdio/flockfile.c38
-rw-r--r--stdio/flushers.c21
-rw-r--r--stdio/flushlbf.c33
-rw-r--r--stdio/fmemopen.c64
-rw-r--r--stdio/fopen.c74
-rw-r--r--stdio/fopenflags.c47
-rw-r--r--stdio/fpending.c26
-rw-r--r--stdio/fprintf.c28
-rw-r--r--stdio/fpurge.c26
-rw-r--r--stdio/fputc.c38
-rw-r--r--stdio/fputs.c39
-rw-r--r--stdio/fputwc.c40
-rw-r--r--stdio/fputws.c44
-rw-r--r--stdio/fread.c99
-rw-r--r--stdio/freadable.c28
-rw-r--r--stdio/freading.c27
-rw-r--r--stdio/freopen.c60
-rw-r--r--stdio/fscanf.c44
-rw-r--r--stdio/fseek.c36
-rw-r--r--stdio/fseeko.c83
-rw-r--r--stdio/fsetlocking.c26
-rw-r--r--stdio/fsetpos.c24
-rw-r--r--stdio/ftell.c29
-rw-r--r--stdio/ftello.c54
-rw-r--r--stdio/fwritable.c28
-rw-r--r--stdio/fwrite.c89
-rw-r--r--stdio/fwriting.c27
-rw-r--r--stdio/get_current_dir_name.c38
-rw-r--r--stdio/getc.c27
-rw-r--r--stdio/getchar.c27
-rw-r--r--stdio/getdelim.c79
-rw-r--r--stdio/getline.c37
-rw-r--r--stdio/gets.c24
-rw-r--r--stdio/getwc.c27
-rw-r--r--stdio/getwchar.c27
-rw-r--r--stdio/internal.h19
-rw-r--r--stdio/mkostemp.c23
-rw-r--r--stdio/mkostemps.c26
-rw-r--r--stdio/mkostempsm.c81
-rw-r--r--stdio/mkstemp.c23
-rw-r--r--stdio/mkstemps.c23
-rw-r--r--stdio/mktemp.c39
-rw-r--r--stdio/pclose.c43
-rw-r--r--stdio/popen.c57
-rw-r--r--stdio/printf.c71
-rw-r--r--stdio/putc.c29
-rw-r--r--stdio/putchar.c26
-rw-r--r--stdio/puts.c38
-rw-r--r--stdio/putwc.c28
-rw-r--r--stdio/putwchar.c27
-rw-r--r--stdio/rewind.c31
-rw-r--r--stdio/scanf.c33
-rw-r--r--stdio/setbuf.c27
-rw-r--r--stdio/setbuffer.c33
-rw-r--r--stdio/setlinebuf.c27
-rw-r--r--stdio/setvbuf.c42
-rw-r--r--stdio/spawn.c115
-rw-r--r--stdio/spawn.h50
-rw-r--r--stdio/spawna.c107
-rw-r--r--stdio/spawna.internal.h19
-rw-r--r--stdio/spawnf.c85
-rw-r--r--stdio/spawnp.c37
-rw-r--r--stdio/stdbuf.c22
-rw-r--r--stdio/stderr-init.S38
-rw-r--r--stdio/stderr.c36
-rw-r--r--stdio/stdin-init.S34
-rw-r--r--stdio/stdin.c36
-rw-r--r--stdio/stdio.h129
-rw-r--r--stdio/stdio.mk66
-rw-r--r--stdio/stdio_ext.h25
-rw-r--r--stdio/stdout-init.S36
-rw-r--r--stdio/stdout.c45
-rw-r--r--stdio/system.c76
-rw-r--r--stdio/systemexec.c38
-rw-r--r--stdio/temp.h20
-rw-r--r--stdio/tmpfile.c44
-rw-r--r--stdio/ungetc.c36
-rw-r--r--stdio/ungetwc.c47
-rw-r--r--stdio/unlocked.h36
-rw-r--r--stdio/unlocked/clearerr_unlocked.S29
-rw-r--r--stdio/unlocked/feof_unlocked.S29
-rw-r--r--stdio/unlocked/ferror_unlocked.S29
-rw-r--r--stdio/unlocked/fflush_unlocked.S29
-rw-r--r--stdio/unlocked/fgetc_unlocked.S29
-rw-r--r--stdio/unlocked/fgets_unlocked.S29
-rw-r--r--stdio/unlocked/fgetwc_unlocked.S29
-rw-r--r--stdio/unlocked/fgetws_unlocked.S29
-rw-r--r--stdio/unlocked/fileno_unlocked.S29
-rw-r--r--stdio/unlocked/fputc_unlocked.S29
-rw-r--r--stdio/unlocked/fputs_unlocked.S29
-rw-r--r--stdio/unlocked/fputwc_unlocked.S29
-rw-r--r--stdio/unlocked/fputws_unlocked.S29
-rw-r--r--stdio/unlocked/fread_unlocked.S29
-rw-r--r--stdio/unlocked/fwrite_unlocked.S29
-rw-r--r--stdio/unlocked/getc_unlocked.S29
-rw-r--r--stdio/unlocked/getchar_unlocked.S29
-rw-r--r--stdio/unlocked/getwc_unlocked.S29
-rw-r--r--stdio/unlocked/getwchar_unlocked.S29
-rw-r--r--stdio/unlocked/putc_unlocked.S29
-rw-r--r--stdio/unlocked/putchar_unlocked.S29
-rw-r--r--stdio/unlocked/putwc_unlocked.S29
-rw-r--r--stdio/unlocked/putwchar_unlocked.S30
-rw-r--r--stdio/vfprintf.c41
-rw-r--r--stdio/vfscanf.c28
-rw-r--r--stdio/vprintf.c23
-rw-r--r--stdio/vscanf.c28
124 files changed, 5132 insertions, 0 deletions
diff --git a/stdio/clearerr.c b/stdio/clearerr.c
new file mode 100644
index 0000000..db30cda
--- /dev/null
+++ b/stdio/clearerr.c
@@ -0,0 +1,23 @@
+/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
+│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8                                :vi│
+╞══════════════════════════════════════════════════════════════════════════════╡
+│ Copyright 2020 Justine Alexandra Roberts Tunney                              │
+│                                                                              │
+│ Permission to use, copy, modify, and/or distribute this software for         │
+│ any purpose with or without fee is hereby granted, provided that the         │
+│ above copyright notice and this permission notice appear in all copies.      │
+│                                                                              │
+│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL                │
+│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │
+│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │
+│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │
+│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │
+│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │
+│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │
+│ PERFORMANCE OF THIS SOFTWARE.                                                │
+╚─────────────────────────────────────────────────────────────────────────────*/
+#include "libc/stdio/stdio.h"
+
+void clearerr(FILE *f) {
+  f->state = 0;
+}
diff --git a/stdio/dirstream.c b/stdio/dirstream.c
new file mode 100644
index 0000000..77940a0
--- /dev/null
+++ b/stdio/dirstream.c
@@ -0,0 +1,321 @@
+/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
+│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8                                :vi│
+╞══════════════════════════════════════════════════════════════════════════════╡
+│ Copyright 2020 Justine Alexandra Roberts Tunney                              │
+│                                                                              │
+│ Permission to use, copy, modify, and/or distribute this software for         │
+│ any purpose with or without fee is hereby granted, provided that the         │
+│ above copyright notice and this permission notice appear in all copies.      │
+│                                                                              │
+│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL                │
+│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │
+│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │
+│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │
+│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │
+│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │
+│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │
+│ PERFORMANCE OF THIS SOFTWARE.                                                │
+╚─────────────────────────────────────────────────────────────────────────────*/
+#include "libc/bits/bits.h"
+#include "libc/calls/internal.h"
+#include "libc/calls/struct/dirent.h"
+#include "libc/dce.h"
+#include "libc/macros.internal.h"
+#include "libc/mem/mem.h"
+#include "libc/nt/enum/fileflagandattributes.h"
+#include "libc/nt/enum/filetype.h"
+#include "libc/nt/files.h"
+#include "libc/nt/runtime.h"
+#include "libc/nt/struct/win32finddata.h"
+#include "libc/str/str.h"
+#include "libc/sysv/consts/dt.h"
+#include "libc/sysv/consts/o.h"
+#include "libc/sysv/errfuns.h"
+
+/**
+ * @fileoverview Directory Streams for Linux+Mac+Windows+FreeBSD+OpenBSD.
+ *
+ * System interfaces for listing the contents of file system directories
+ * are famously incompatible across platforms. Most native projects that
+ * have been around a long time implement wrappers for this. Normally it
+ * will only be for DOS or Windows support. So this is the first time it
+ * has been done for five platforms, having a remarkably tiny footprint.
+ */
+
+/**
+ * Directory stream object.
+ */
+struct dirstream {
+  int64_t fd;
+  int64_t tell;
+  struct dirent ent;
+  union {
+    struct {
+      unsigned buf_pos;
+      unsigned buf_end;
+      char buf[BUFSIZ];
+    };
+    struct {
+      bool isdone;
+      struct NtWin32FindData windata;
+    };
+  };
+};
+
+/**
+ * FreeBSD getdents() and XNU getdirentries() ABI.
+ */
+struct dirent_bsd {
+  uint32_t d_fileno;
+  uint16_t d_reclen;
+  uint8_t d_type;
+  uint8_t d_namlen;
+  char d_name[256];
+};
+
+/**
+ * OpenBSD getdents() ABI.
+ */
+struct dirent_openbsd {
+  uint64_t d_fileno;
+  int64_t d_off;
+  uint16_t d_reclen;
+  uint8_t d_type;
+  uint8_t d_namlen;
+  uint8_t __zomg[4];
+  char d_name[256];
+};
+
+/**
+ * NetBSD getdents().
+ */
+struct dirent_netbsd {
+  uint64_t d_fileno;
+  uint16_t d_reclen;
+  uint16_t d_namlen;
+  uint8_t d_type;
+  char d_name[512];
+};
+
+static textwindows DIR *opendir_nt_impl(char16_t name[PATH_MAX], size_t len) {
+  DIR *res;
+  if (len + 2 + 1 <= PATH_MAX) {
+    if (name[len - 1] != u'\\') name[len++] = u'\\';
+    name[len++] = u'*';
+    name[len] = u'\0';
+    if ((res = calloc(1, sizeof(DIR)))) {
+      if ((res->fd = FindFirstFile(name, &res->windata)) != -1) {
+        return res;
+      } else {
+        __winerr();
+      }
+      free(res);
+    }
+  } else {
+    enametoolong();
+  }
+  return NULL;
+}
+
+static textwindows noinline DIR *opendir_nt(const char *path) {
+  int len;
+  char16_t name[PATH_MAX];
+  if ((len = __mkntpath(path, name)) == -1) return NULL;
+  return opendir_nt_impl(name, len);
+}
+
+static textwindows noinline DIR *fdopendir_nt(int fd) {
+  DIR *res;
+  char16_t name[PATH_MAX];
+  if (__isfdkind(fd, kFdFile)) {
+    if ((res = opendir_nt_impl(
+             name, GetFinalPathNameByHandle(
+                       g_fds.p[fd].handle, name, ARRAYLEN(name),
+                       kNtFileNameNormalized | kNtVolumeNameDos)))) {
+      close(fd);
+      return res;
+    }
+  } else {
+    ebadf();
+  }
+  return NULL;
+}
+
+static textwindows noinline struct dirent *readdir_nt(DIR *dir) {
+  if (!dir->isdone) {
+    memset(&dir->ent, 0, sizeof(dir->ent));
+    dir->ent.d_ino = 0;
+    dir->ent.d_off = dir->tell++;
+    dir->ent.d_reclen = sizeof(dir->ent) +
+                        tprecode16to8(dir->ent.d_name, sizeof(dir->ent.d_name),
+                                      dir->windata.cFileName)
+                            .ax +
+                        1;
+    switch (dir->windata.dwFileType) {
+      case kNtFileTypeDisk:
+        dir->ent.d_type = DT_BLK;
+        break;
+      case kNtFileTypeChar:
+        dir->ent.d_type = DT_CHR;
+        break;
+      case kNtFileTypePipe:
+        dir->ent.d_type = DT_FIFO;
+        break;
+      default:
+        if (dir->windata.dwFileAttributes & kNtFileAttributeDirectory) {
+          dir->ent.d_type = DT_DIR;
+        } else {
+          dir->ent.d_type = DT_REG;
+        }
+        break;
+    }
+    dir->isdone = !FindNextFile(dir->fd, &dir->windata);
+    return &dir->ent;
+  } else {
+    return NULL;
+  }
+}
+
+/**
+ * Opens directory, e.g.
+ *
+ *     DIR *d;
+ *     struct dirent *e;
+ *     CHECK((d = opendir(path)));
+ *     while ((e = readdir(d))) {
+ *       printf("%s/%s\n", path, e->d_name);
+ *     }
+ *     LOGIFNEG1(closedir(d));
+ *
+ * @returns newly allocated DIR object, or NULL w/ errno
+ * @errors ENOENT, ENOTDIR, EACCES, EMFILE, ENFILE, ENOMEM
+ * @see glob()
+ */
+DIR *opendir(const char *name) {
+  int fd;
+  DIR *res;
+  if (!IsWindows()) {
+    res = NULL;
+    if ((fd = open(name, O_RDONLY | O_DIRECTORY | O_CLOEXEC)) != -1) {
+      if (!(res = fdopendir(fd))) close(fd);
+    }
+    return res;
+  } else {
+    return opendir_nt(name);
+  }
+}
+
+/**
+ * Creates directory object for file descriptor.
+ *
+ * @param fd gets owned by this function, if it succeeds
+ * @return new directory object, which must be freed by closedir(),
+ *     or NULL w/ errno
+ * @errors ENOMEM and fd is closed
+ */
+DIR *fdopendir(int fd) {
+  DIR *dir;
+  if (!IsWindows()) {
+    if (!(dir = calloc(1, sizeof(*dir)))) return NULL;
+    dir->fd = fd;
+    return dir;
+  } else {
+    return fdopendir_nt(fd);
+  }
+}
+
+/**
+ * Reads next entry from directory stream.
+ *
+ * This API doesn't define any particular ordering.
+ *
+ * @param dir is the object opendir() or fdopendir() returned
+ * @return next entry or NULL on end or error, which can be
+ *     differentiated by setting errno to 0 beforehand
+ */
+struct dirent *readdir(DIR *dir) {
+  int rc;
+  long basep;
+  struct dirent *ent;
+  struct dirent_bsd *bsd;
+  struct dirent_netbsd *nbsd;
+  struct dirent_openbsd *obsd;
+  if (!IsWindows()) {
+    if (dir->buf_pos >= dir->buf_end) {
+      basep = dir->tell; /* TODO(jart): what does xnu do */
+      rc = getdents(dir->fd, dir->buf, sizeof(dir->buf) - 256, &basep);
+      if (!rc || rc == -1) return NULL;
+      dir->buf_pos = 0;
+      dir->buf_end = rc;
+    }
+    if (IsLinux()) {
+      ent = (struct dirent *)(dir->buf + dir->buf_pos);
+      dir->buf_pos += ent->d_reclen;
+      dir->tell = ent->d_off;
+    } else if (IsOpenbsd()) {
+      obsd = (struct dirent_openbsd *)(dir->buf + dir->buf_pos);
+      dir->buf_pos += obsd->d_reclen;
+      ent = &dir->ent;
+      ent->d_ino = obsd->d_fileno;
+      ent->d_off = obsd->d_off;
+      ent->d_reclen = obsd->d_reclen;
+      ent->d_type = obsd->d_type;
+      memcpy(ent->d_name, obsd->d_name, obsd->d_namlen + 1);
+    } else if (IsNetbsd()) {
+      nbsd = (struct dirent_netbsd *)(dir->buf + dir->buf_pos);
+      dir->buf_pos += nbsd->d_reclen;
+      ent = &dir->ent;
+      ent->d_ino = nbsd->d_fileno;
+      ent->d_off = dir->tell++;
+      ent->d_reclen = nbsd->d_reclen;
+      ent->d_type = nbsd->d_type;
+      memcpy(ent->d_name, nbsd->d_name, MAX(256, nbsd->d_namlen + 1));
+    } else {
+      bsd = (struct dirent_bsd *)(dir->buf + dir->buf_pos);
+      dir->buf_pos += bsd->d_reclen;
+      ent = &dir->ent;
+      ent->d_ino = bsd->d_fileno;
+      ent->d_off = IsXnu() ? (dir->tell = basep) : dir->tell++;
+      ent->d_reclen = bsd->d_reclen;
+      ent->d_type = bsd->d_type;
+      memcpy(ent->d_name, bsd->d_name, bsd->d_namlen + 1);
+    }
+    return ent;
+  } else {
+    return readdir_nt(dir);
+  }
+}
+
+/**
+ * Closes directory object returned by opendir().
+ * @return 0 on success or -1 w/ errno
+ */
+int closedir(DIR *dir) {
+  int rc;
+  if (dir) {
+    if (!IsWindows()) {
+      rc = close(dir->fd);
+    } else {
+      rc = FindClose(dir->fd) ? 0 : __winerr();
+    }
+    free(dir);
+  } else {
+    rc = 0;
+  }
+  return rc;
+}
+
+/**
+ * Returns offset into directory data.
+ */
+long telldir(DIR *dir) {
+  return dir->tell;
+}
+
+/**
+ * Returns file descriptor associated with DIR object.
+ */
+int dirfd(DIR *dir) {
+  if (IsWindows()) return eopnotsupp();
+  return dir->fd;
+}
diff --git a/stdio/dtoa.c b/stdio/dtoa.c
new file mode 100644
index 0000000..f58202d
--- /dev/null
+++ b/stdio/dtoa.c
@@ -0,0 +1,25 @@
+/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
+│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8                                :vi│
+╞══════════════════════════════════════════════════════════════════════════════╡
+│ Copyright 2021 Justine Alexandra Roberts Tunney                              │
+│                                                                              │
+│ Permission to use, copy, modify, and/or distribute this software for         │
+│ any purpose with or without fee is hereby granted, provided that the         │
+│ above copyright notice and this permission notice appear in all copies.      │
+│                                                                              │
+│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL                │
+│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │
+│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │
+│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │
+│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │
+│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │
+│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │
+│ PERFORMANCE OF THIS SOFTWARE.                                                │
+╚─────────────────────────────────────────────────────────────────────────────*/
+#include "libc/fmt/fmts.h"
+#include "third_party/gdtoa/gdtoa.h"
+
+char *__fmt_dtoa(double d0, int mode, int ndigits, int *decpt, int *sign,
+                 char **rve) {
+  return dtoa(d0, mode, ndigits, decpt, sign, rve);
+}
diff --git a/stdio/fbufsize.c b/stdio/fbufsize.c
new file mode 100644
index 0000000..254276b
--- /dev/null
+++ b/stdio/fbufsize.c
@@ -0,0 +1,27 @@
+/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
+│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8                                :vi│
+╞══════════════════════════════════════════════════════════════════════════════╡
+│ Copyright 2021 Justine Alexandra Roberts Tunney                              │
+│                                                                              │
+│ Permission to use, copy, modify, and/or distribute this software for         │
+│ any purpose with or without fee is hereby granted, provided that the         │
+│ above copyright notice and this permission notice appear in all copies.      │
+│                                                                              │
+│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL                │
+│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │
+│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │
+│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │
+│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │
+│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │
+│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │
+│ PERFORMANCE OF THIS SOFTWARE.                                                │
+╚─────────────────────────────────────────────────────────────────────────────*/
+#include "libc/assert.h"
+#include "libc/stdio/stdio_ext.h"
+
+/**
+ * Returns capacity of stdio stream buffer.
+ */
+size_t __fbufsize(FILE *f) {
+  return f->size;
+}
diff --git a/stdio/fclose.c b/stdio/fclose.c
new file mode 100644
index 0000000..cd75a50
--- /dev/null
+++ b/stdio/fclose.c
@@ -0,0 +1,59 @@
+/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
+│vi: set net ft=c ts=8 sts=2 sw=2 fenc=utf-8                                :vi│
+╞══════════════════════════════════════════════════════════════════════════════╡
+│ Copyright 2020 Justine Alexandra Roberts Tunney                              │
+│                                                                              │
+│ Permission to use, copy, modify, and/or distribute this software for         │
+│ any purpose with or without fee is hereby granted, provided that the         │
+│ above copyright notice and this permission notice appear in all copies.      │
+│                                                                              │
+│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL                │
+│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │
+│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │
+│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │
+│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │
+│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │
+│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │
+│ PERFORMANCE OF THIS SOFTWARE.                                                │
+╚─────────────────────────────────────────────────────────────────────────────*/
+#include "libc/assert.h"
+#include "libc/calls/calls.h"
+#include "libc/errno.h"
+#include "libc/mem/mem.h"
+#include "libc/runtime/runtime.h"
+#include "libc/stdio/internal.h"
+#include "libc/stdio/stdio.h"
+
+/**
+ * Closes standard i/o stream and its underlying thing.
+ *
+ * @param f is the file object, which is always free if it's heap,
+ *     otherwise its resources are released and fields updated
+ * @return 0 on success or -1 on error, which can be a trick for
+ *     differentiating between EOF and real errors during previous
+ *     i/o calls, without needing to call ferror()
+ * @see fclose_s()
+ */
+int fclose(FILE *f) {
+  int rc;
+  if (!f) return 0;
+  __fflush_unregister(f);
+  fflush(f);
+  if (!f->nofree) {
+    free_s(&f->buf);
+  }
+  f->state = EOF;
+  if (f->noclose) {
+    f->fd = -1;
+  } else if (close_s(&f->fd) == -1) {
+    f->state = errno;
+  }
+  if (f->state == EOF) {
+    rc = 0;
+  } else {
+    errno = f->state;
+    rc = EOF;
+  }
+  free_s(&f);
+  return rc;
+}
diff --git a/stdio/fclose_s.c b/stdio/fclose_s.c
new file mode 100644
index 0000000..7fa0b41
--- /dev/null
+++ b/stdio/fclose_s.c
@@ -0,0 +1,33 @@
+/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
+│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8                                :vi│
+╞══════════════════════════════════════════════════════════════════════════════╡
+│ Copyright 2020 Justine Alexandra Roberts Tunney                              │
+│                                                                              │
+│ Permission to use, copy, modify, and/or distribute this software for         │
+│ any purpose with or without fee is hereby granted, provided that the         │
+│ above copyright notice and this permission notice appear in all copies.      │
+│                                                                              │
+│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL                │
+│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │
+│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │
+│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │
+│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │
+│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │
+│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │
+│ PERFORMANCE OF THIS SOFTWARE.                                                │
+╚─────────────────────────────────────────────────────────────────────────────*/
+#include "libc/bits/bits.h"
+#include "libc/stdio/stdio.h"
+
+/**
+ * Closes standard i/o stream and its underlying thing.
+ *
+ * @param f is the heap file object pointer, to close+free+clear
+ * @return 0 on success or -1 on error, which can be a trick for
+ *     differentiating between EOF and real errors during previous
+ *     i/o calls, without needing to call ferror()
+ */
+int fclose_s(FILE **fp) {
+  FILE *f = NULL;
+  return fclose(lockxchg(fp, &f));
+}
diff --git a/stdio/fdopen.c b/stdio/fdopen.c
new file mode 100644
index 0000000..0f786fa
--- /dev/null
+++ b/stdio/fdopen.c
@@ -0,0 +1,50 @@
+/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
+│vi: set net ft=c ts=8 sts=2 sw=2 fenc=utf-8                                :vi│
+╞══════════════════════════════════════════════════════════════════════════════╡
+│ Copyright 2020 Justine Alexandra Roberts Tunney                              │
+│                                                                              │
+│ Permission to use, copy, modify, and/or distribute this software for         │
+│ any purpose with or without fee is hereby granted, provided that the         │
+│ above copyright notice and this permission notice appear in all copies.      │
+│                                                                              │
+│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL                │
+│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │
+│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │
+│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │
+│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │
+│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │
+│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │
+│ PERFORMANCE OF THIS SOFTWARE.                                                │
+╚─────────────────────────────────────────────────────────────────────────────*/
+#include "libc/calls/calls.h"
+#include "libc/mem/mem.h"
+#include "libc/stdio/internal.h"
+#include "libc/stdio/stdio.h"
+#include "libc/sysv/consts/o.h"
+#include "libc/sysv/errfuns.h"
+
+/**
+ * Allocates stream object for already-opened file descriptor.
+ *
+ * @param fd existing file descriptor or -1 for plain old buffer
+ * @param mode is passed to fopenflags()
+ * @return new stream or NULL w/ errno
+ * @error ENOMEM
+ */
+FILE *fdopen(int fd, const char *mode) {
+  FILE *f;
+  if ((f = calloc(1, sizeof(FILE)))) {
+    f->fd = fd;
+    f->bufmode = ischardev(fd) ? _IOLBF : _IOFBF;
+    f->iomode = fopenflags(mode);
+    f->size = BUFSIZ;
+    if ((f->buf = malloc(f->size))) {
+      if ((f->iomode & O_ACCMODE) != O_RDONLY) {
+        __fflush_register(f);
+      }
+      return f;
+    }
+    free(f);
+  }
+  return NULL;
+}
diff --git a/stdio/feof.c b/stdio/feof.c
new file mode 100644
index 0000000..6016fc8
--- /dev/null
+++ b/stdio/feof.c
@@ -0,0 +1,26 @@
+/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
+│vi: set net ft=c ts=8 sts=2 sw=2 fenc=utf-8                                :vi│
+╞══════════════════════════════════════════════════════════════════════════════╡
+│ Copyright 2020 Justine Alexandra Roberts Tunney                              │
+│                                                                              │
+│ Permission to use, copy, modify, and/or distribute this software for         │
+│ any purpose with or without fee is hereby granted, provided that the         │
+│ above copyright notice and this permission notice appear in all copies.      │
+│                                                                              │
+│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL                │
+│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │
+│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │
+│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │
+│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │
+│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │
+│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │
+│ PERFORMANCE OF THIS SOFTWARE.                                                │
+╚─────────────────────────────────────────────────────────────────────────────*/
+#include "libc/stdio/stdio.h"
+
+/**
+ * Returns true if stream is in end-of-file state.
+ */
+int feof(FILE *f) {
+  return f->state == -1;
+}
diff --git a/stdio/ferror.c b/stdio/ferror.c
new file mode 100644
index 0000000..241cb25
--- /dev/null
+++ b/stdio/ferror.c
@@ -0,0 +1,29 @@
+/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
+│vi: set net ft=c ts=8 sts=2 sw=2 fenc=utf-8                                :vi│
+╞══════════════════════════════════════════════════════════════════════════════╡
+│ Copyright 2020 Justine Alexandra Roberts Tunney                              │
+│                                                                              │
+│ Permission to use, copy, modify, and/or distribute this software for         │
+│ any purpose with or without fee is hereby granted, provided that the         │
+│ above copyright notice and this permission notice appear in all copies.      │
+│                                                                              │
+│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL                │
+│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │
+│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │
+│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │
+│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │
+│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │
+│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │
+│ PERFORMANCE OF THIS SOFTWARE.                                                │
+╚─────────────────────────────────────────────────────────────────────────────*/
+#include "libc/stdio/stdio.h"
+
+/**
+ * Returns nonzero if stream is in error state.
+ *
+ * @note EOF doesn't count
+ * @see feof()
+ */
+errno_t ferror(FILE *f) {
+  return f->state > 0 ? f->state : 0;
+}
diff --git a/stdio/fflush.c b/stdio/fflush.c
new file mode 100644
index 0000000..99a758d
--- /dev/null
+++ b/stdio/fflush.c
@@ -0,0 +1,91 @@
+/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
+│vi: set net ft=c ts=8 sts=2 sw=2 fenc=utf-8                                :vi│
+╞══════════════════════════════════════════════════════════════════════════════╡
+│ Copyright 2020 Justine Alexandra Roberts Tunney                              │
+│                                                                              │
+│ Permission to use, copy, modify, and/or distribute this software for         │
+│ any purpose with or without fee is hereby granted, provided that the         │
+│ above copyright notice and this permission notice appear in all copies.      │
+│                                                                              │
+│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL                │
+│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │
+│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │
+│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │
+│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │
+│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │
+│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │
+│ PERFORMANCE OF THIS SOFTWARE.                                                │
+╚─────────────────────────────────────────────────────────────────────────────*/
+#include "libc/alg/arraylist.internal.h"
+#include "libc/bits/bits.h"
+#include "libc/bits/pushpop.h"
+#include "libc/calls/calls.h"
+#include "libc/errno.h"
+#include "libc/macros.internal.h"
+#include "libc/mem/mem.h"
+#include "libc/runtime/runtime.h"
+#include "libc/stdio/fflush.internal.h"
+#include "libc/stdio/internal.h"
+#include "libc/stdio/stdio.h"
+#include "libc/sysv/consts/o.h"
+
+/**
+ * Blocks until data from stream buffer is written out.
+ *
+ * @param f is the stream handle
+ * @return is 0 on success or -1 on error
+ */
+int fflush(FILE *f) {
+  size_t i;
+  ssize_t rc;
+  if (!f) {
+    for (i = __fflush.handles.i; i; --i) {
+      if ((f = __fflush.handles.p[i - 1])) {
+        if (fflush(f) == -1) return -1;
+      }
+    }
+  } else if (f->fd != -1) {
+    while (f->beg && !f->end && (f->iomode & O_ACCMODE) != O_RDONLY) {
+      if ((rc = write(f->fd, f->buf, f->beg)) == -1) {
+        f->state = errno;
+        return -1;
+      }
+      if (rc != f->beg) abort();
+      f->beg = 0;
+    }
+  } else if (f->beg && f->beg < f->size) {
+    f->buf[f->beg] = 0;
+  }
+  return 0;
+}
+
+textstartup int __fflush_register(FILE *f) {
+  size_t i;
+  struct StdioFlush *sf;
+  sf = &__fflush;
+  if (!sf->handles.p) {
+    sf->handles.p = &sf->handles_initmem[0];
+    pushmov(&sf->handles.n, ARRAYLEN(sf->handles_initmem));
+    __cxa_atexit(fflush, NULL, NULL);
+  }
+  for (i = sf->handles.i; i; --i) {
+    if (!sf->handles.p[i - 1]) {
+      sf->handles.p[i - 1] = f;
+      return 0;
+    }
+  }
+  return append(&sf->handles, &f);
+}
+
+void __fflush_unregister(FILE *f) {
+  size_t i;
+  struct StdioFlush *sf;
+  sf = &__fflush;
+  sf = pushpop(sf);
+  for (i = sf->handles.i; i; --i) {
+    if (sf->handles.p[i - 1] == f) {
+      pushmov(&sf->handles.p[i - 1], NULL);
+      return;
+    }
+  }
+}
diff --git a/stdio/fflush.internal.h b/stdio/fflush.internal.h
new file mode 100644
index 0000000..d49156d
--- /dev/null
+++ b/stdio/fflush.internal.h
@@ -0,0 +1,21 @@
+#ifndef COSMOPOLITAN_LIBC_STDIO_FFLUSH_H_
+#define COSMOPOLITAN_LIBC_STDIO_FFLUSH_H_
+#include "libc/stdio/stdio.h"
+#if !(__ASSEMBLER__ + __LINKER__ + 0)
+COSMOPOLITAN_C_START_
+
+struct StdioFlushHandles {
+  size_t i, n;
+  FILE **p;
+};
+
+struct StdioFlush {
+  struct StdioFlushHandles handles;
+  FILE *handles_initmem[8];
+};
+
+extern struct StdioFlush __fflush hidden;
+
+COSMOPOLITAN_C_END_
+#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
+#endif /* COSMOPOLITAN_LIBC_STDIO_FFLUSH_H_ */
diff --git a/stdio/fgetc.c b/stdio/fgetc.c
new file mode 100644
index 0000000..034b967
--- /dev/null
+++ b/stdio/fgetc.c
@@ -0,0 +1,33 @@
+/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
+│vi: set net ft=c ts=8 sts=2 sw=2 fenc=utf-8                                :vi│
+╞══════════════════════════════════════════════════════════════════════════════╡
+│ Copyright 2020 Justine Alexandra Roberts Tunney                              │
+│                                                                              │
+│ Permission to use, copy, modify, and/or distribute this software for         │
+│ any purpose with or without fee is hereby granted, provided that the         │
+│ above copyright notice and this permission notice appear in all copies.      │
+│                                                                              │
+│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL                │
+│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │
+│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │
+│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │
+│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │
+│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │
+│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │
+│ PERFORMANCE OF THIS SOFTWARE.                                                │
+╚─────────────────────────────────────────────────────────────────────────────*/
+#include "libc/stdio/stdio.h"
+
+/**
+ * Reads byte from stream.
+ * @return byte in range 0..255, or -1 w/ errno
+ */
+int fgetc(FILE *f) {
+  unsigned char b;
+  if (f->beg < f->end) {
+    return f->buf[f->beg++] & 0xff;
+  } else {
+    if (!fread(&b, 1, 1, f)) return -1;
+    return b;
+  }
+}
diff --git a/stdio/fgetpos.c b/stdio/fgetpos.c
new file mode 100644
index 0000000..cd7d4a3
--- /dev/null
+++ b/stdio/fgetpos.c
@@ -0,0 +1,29 @@
+/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
+│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8                                :vi│
+╞══════════════════════════════════════════════════════════════════════════════╡
+│ Copyright 2020 Justine Alexandra Roberts Tunney                              │
+│                                                                              │
+│ Permission to use, copy, modify, and/or distribute this software for         │
+│ any purpose with or without fee is hereby granted, provided that the         │
+│ above copyright notice and this permission notice appear in all copies.      │
+│                                                                              │
+│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL                │
+│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │
+│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │
+│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │
+│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │
+│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │
+│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │
+│ PERFORMANCE OF THIS SOFTWARE.                                                │
+╚─────────────────────────────────────────────────────────────────────────────*/
+#include "libc/stdio/stdio.h"
+
+int fgetpos(FILE *stream, fpos_t *pos) {
+  long res;
+  if ((res = ftell(stream)) != -1) {
+    *pos = res;
+    return 0;
+  } else {
+    return -1;
+  }
+}
diff --git a/stdio/fgets.c b/stdio/fgets.c
new file mode 100644
index 0000000..195880e
--- /dev/null
+++ b/stdio/fgets.c
@@ -0,0 +1,46 @@
+/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
+│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8                                :vi│
+╞══════════════════════════════════════════════════════════════════════════════╡
+│ Copyright 2020 Justine Alexandra Roberts Tunney                              │
+│                                                                              │
+│ Permission to use, copy, modify, and/or distribute this software for         │
+│ any purpose with or without fee is hereby granted, provided that the         │
+│ above copyright notice and this permission notice appear in all copies.      │
+│                                                                              │
+│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL                │
+│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │
+│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │
+│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │
+│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │
+│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │
+│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │
+│ PERFORMANCE OF THIS SOFTWARE.                                                │
+╚─────────────────────────────────────────────────────────────────────────────*/
+#include "libc/assert.h"
+#include "libc/errno.h"
+#include "libc/stdio/stdio.h"
+
+/**
+ * Reads content from stream.
+ *
+ * This function is similar to getline() except it'll truncate lines
+ * exceeding size. The line ending marker is included and may be removed
+ * using chomp().
+ */
+char *fgets(char *s, int size, FILE *f) {
+  int c;
+  char *p;
+  p = s;
+  if (size > 0) {
+    while (--size > 0) {
+      if ((c = getc(f)) == -1) {
+        if (ferror(f) == EINTR) continue;
+        break;
+      }
+      *p++ = c & 0xff;
+      if (c == '\n') break;
+    }
+    *p = '\0';
+  }
+  return p > s ? s : NULL;
+}
diff --git a/stdio/fgetwc.c b/stdio/fgetwc.c
new file mode 100644
index 0000000..6411236
--- /dev/null
+++ b/stdio/fgetwc.c
@@ -0,0 +1,51 @@
+/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
+│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8                                :vi│
+╞══════════════════════════════════════════════════════════════════════════════╡
+│ Copyright 2020 Justine Alexandra Roberts Tunney                              │
+│                                                                              │
+│ Permission to use, copy, modify, and/or distribute this software for         │
+│ any purpose with or without fee is hereby granted, provided that the         │
+│ above copyright notice and this permission notice appear in all copies.      │
+│                                                                              │
+│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL                │
+│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │
+│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │
+│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │
+│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │
+│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │
+│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │
+│ PERFORMANCE OF THIS SOFTWARE.                                                │
+╚─────────────────────────────────────────────────────────────────────────────*/
+#include "libc/stdio/stdio.h"
+#include "libc/str/thompike.h"
+#include "libc/str/tpdecodecb.internal.h"
+
+/**
+ * Reads UTF-8 character from stream.
+ * @return wide character or -1 on EOF or error
+ */
+wint_t fgetwc(FILE *f) {
+  int c, n;
+  wint_t b, x, y;
+  if (f->beg < f->end) {
+    b = f->buf[f->beg++] & 0xff;
+  } else if ((c = fgetc(f)) != -1) {
+    b = c;
+  } else {
+    return -1;
+  }
+  if (b < 0300) return b;
+  n = ThomPikeLen(b);
+  x = ThomPikeByte(b);
+  while (--n) {
+    if ((c = fgetc(f)) == -1) return -1;
+    y = c;
+    if (ThomPikeCont(y)) {
+      x = ThomPikeMerge(x, y);
+    } else {
+      ungetc(y, f);
+      return b;
+    }
+  }
+  return x;
+}
diff --git a/stdio/fgetws.c b/stdio/fgetws.c
new file mode 100644
index 0000000..3fdd3b3
--- /dev/null
+++ b/stdio/fgetws.c
@@ -0,0 +1,41 @@
+/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
+│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8                                :vi│
+╞══════════════════════════════════════════════════════════════════════════════╡
+│ Copyright 2020 Justine Alexandra Roberts Tunney                              │
+│                                                                              │
+│ Permission to use, copy, modify, and/or distribute this software for         │
+│ any purpose with or without fee is hereby granted, provided that the         │
+│ above copyright notice and this permission notice appear in all copies.      │
+│                                                                              │
+│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL                │
+│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │
+│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │
+│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │
+│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │
+│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │
+│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │
+│ PERFORMANCE OF THIS SOFTWARE.                                                │
+╚─────────────────────────────────────────────────────────────────────────────*/
+#include "libc/assert.h"
+#include "libc/errno.h"
+#include "libc/stdio/stdio.h"
+
+/**
+ * Reads UTF-8 content from stream into UTF-32 buffer.
+ */
+wchar_t *fgetws(wchar_t *s, int size, FILE *f) {
+  wint_t c;
+  wchar_t *p = s;
+  if (size > 0) {
+    while (--size > 0) {
+      if ((c = fgetwc(f)) == -1) {
+        if (ferror(f) == EINTR) continue;
+        break;
+      }
+      *p++ = c;
+      if (c == '\n') break;
+    }
+    *p = '\0';
+  }
+  return (intptr_t)p > (intptr_t)s ? s : NULL;
+}
diff --git a/stdio/fileno.c b/stdio/fileno.c
new file mode 100644
index 0000000..a16d858
--- /dev/null
+++ b/stdio/fileno.c
@@ -0,0 +1,31 @@
+/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
+│vi: set net ft=c ts=8 sts=2 sw=2 fenc=utf-8                                :vi│
+╞══════════════════════════════════════════════════════════════════════════════╡
+│ Copyright 2020 Justine Alexandra Roberts Tunney                              │
+│                                                                              │
+│ Permission to use, copy, modify, and/or distribute this software for         │
+│ any purpose with or without fee is hereby granted, provided that the         │
+│ above copyright notice and this permission notice appear in all copies.      │
+│                                                                              │
+│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL                │
+│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │
+│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │
+│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │
+│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │
+│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │
+│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │
+│ PERFORMANCE OF THIS SOFTWARE.                                                │
+╚─────────────────────────────────────────────────────────────────────────────*/
+#include "libc/stdio/stdio.h"
+#include "libc/sysv/errfuns.h"
+
+/**
+ * Returns file descriptor associated with stream.
+ */
+int fileno(FILE *f) {
+  if (f->fd != -1) {
+    return f->fd;
+  } else {
+    return ebadf();
+  }
+}
diff --git a/stdio/flbf.c b/stdio/flbf.c
new file mode 100644
index 0000000..661e09a
--- /dev/null
+++ b/stdio/flbf.c
@@ -0,0 +1,27 @@
+/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
+│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8                                :vi│
+╞══════════════════════════════════════════════════════════════════════════════╡
+│ Copyright 2021 Justine Alexandra Roberts Tunney                              │
+│                                                                              │
+│ Permission to use, copy, modify, and/or distribute this software for         │
+│ any purpose with or without fee is hereby granted, provided that the         │
+│ above copyright notice and this permission notice appear in all copies.      │
+│                                                                              │
+│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL                │
+│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │
+│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │
+│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │
+│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │
+│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │
+│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │
+│ PERFORMANCE OF THIS SOFTWARE.                                                │
+╚─────────────────────────────────────────────────────────────────────────────*/
+#include "libc/calls/calls.h"
+#include "libc/stdio/stdio_ext.h"
+
+/**
+ * Returns nonzero if stream is line buffered.
+ */
+int __flbf(FILE *f) {
+  return f->bufmode == _IOLBF;
+}
diff --git a/stdio/flockfile.c b/stdio/flockfile.c
new file mode 100644
index 0000000..fd6e8e6
--- /dev/null
+++ b/stdio/flockfile.c
@@ -0,0 +1,38 @@
+/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
+│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8                                :vi│
+╞══════════════════════════════════════════════════════════════════════════════╡
+│ Copyright 2021 Justine Alexandra Roberts Tunney                              │
+│                                                                              │
+│ Permission to use, copy, modify, and/or distribute this software for         │
+│ any purpose with or without fee is hereby granted, provided that the         │
+│ above copyright notice and this permission notice appear in all copies.      │
+│                                                                              │
+│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL                │
+│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │
+│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │
+│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │
+│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │
+│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │
+│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │
+│ PERFORMANCE OF THIS SOFTWARE.                                                │
+╚─────────────────────────────────────────────────────────────────────────────*/
+#include "libc/stdio/stdio.h"
+
+/**
+ * Does nothing since Cosmopolitan currently doesn't support threads.
+ */
+void flockfile(FILE *f) {
+}
+
+/**
+ * Does nothing since Cosmopolitan currently doesn't support threads.
+ */
+void funlockfile(FILE *f) {
+}
+
+/**
+ * Does nothing since Cosmopolitan currently doesn't support threads.
+ */
+int ftrylockfile(FILE *f) {
+  return 0;
+}
diff --git a/stdio/flushers.c b/stdio/flushers.c
new file mode 100644
index 0000000..3b7c976
--- /dev/null
+++ b/stdio/flushers.c
@@ -0,0 +1,21 @@
+/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
+│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8                                :vi│
+╞══════════════════════════════════════════════════════════════════════════════╡
+│ Copyright 2021 Justine Alexandra Roberts Tunney                              │
+│                                                                              │
+│ Permission to use, copy, modify, and/or distribute this software for         │
+│ any purpose with or without fee is hereby granted, provided that the         │
+│ above copyright notice and this permission notice appear in all copies.      │
+│                                                                              │
+│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL                │
+│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │
+│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │
+│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │
+│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │
+│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │
+│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │
+│ PERFORMANCE OF THIS SOFTWARE.                                                │
+╚─────────────────────────────────────────────────────────────────────────────*/
+#include "libc/stdio/fflush.internal.h"
+
+struct StdioFlush __fflush;
diff --git a/stdio/flushlbf.c b/stdio/flushlbf.c
new file mode 100644
index 0000000..a714b25
--- /dev/null
+++ b/stdio/flushlbf.c
@@ -0,0 +1,33 @@
+/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
+│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8                                :vi│
+╞══════════════════════════════════════════════════════════════════════════════╡
+│ Copyright 2021 Justine Alexandra Roberts Tunney                              │
+│                                                                              │
+│ Permission to use, copy, modify, and/or distribute this software for         │
+│ any purpose with or without fee is hereby granted, provided that the         │
+│ above copyright notice and this permission notice appear in all copies.      │
+│                                                                              │
+│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL                │
+│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │
+│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │
+│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │
+│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │
+│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │
+│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │
+│ PERFORMANCE OF THIS SOFTWARE.                                                │
+╚─────────────────────────────────────────────────────────────────────────────*/
+#include "libc/calls/calls.h"
+#include "libc/stdio/fflush.internal.h"
+#include "libc/stdio/stdio_ext.h"
+
+/**
+ * Flushes all line-buffered streams.
+ */
+void _flushlbf(void) {
+  int i;
+  for (i = 0; i < __fflush.handles.i; ++i) {
+    if (__fflush.handles.p[i]->bufmode == _IOLBF) {
+      fflush(__fflush.handles.p[i]);
+    }
+  }
+}
diff --git a/stdio/fmemopen.c b/stdio/fmemopen.c
new file mode 100644
index 0000000..6aac757
--- /dev/null
+++ b/stdio/fmemopen.c
@@ -0,0 +1,64 @@
+/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
+│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8                                :vi│
+╞══════════════════════════════════════════════════════════════════════════════╡
+│ Copyright 2020 Justine Alexandra Roberts Tunney                              │
+│                                                                              │
+│ Permission to use, copy, modify, and/or distribute this software for         │
+│ any purpose with or without fee is hereby granted, provided that the         │
+│ above copyright notice and this permission notice appear in all copies.      │
+│                                                                              │
+│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL                │
+│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │
+│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │
+│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │
+│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │
+│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │
+│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │
+│ PERFORMANCE OF THIS SOFTWARE.                                                │
+╚─────────────────────────────────────────────────────────────────────────────*/
+#include "libc/mem/mem.h"
+#include "libc/stdio/stdio.h"
+#include "libc/str/str.h"
+#include "libc/sysv/consts/o.h"
+#include "libc/sysv/errfuns.h"
+
+/**
+ * Opens buffer as stream.
+ *
+ * @param buf becomes owned by this function, and is allocated if NULL
+ * @return new stream or NULL w/ errno
+ */
+FILE *fmemopen(void *buf, size_t size, const char *mode) {
+  FILE *f;
+  char *p;
+  unsigned flags;
+  if (size && size > 0x7ffff000) {
+    einval();
+    return NULL;
+  }
+  if (!(f = calloc(1, sizeof(FILE)))) {
+    return NULL;
+  }
+  if (buf) {
+    f->nofree = true;
+  } else {
+    if (!size) size = BUFSIZ;
+    if (!(buf = calloc(1, size))) {
+      free(f);
+      return NULL;
+    }
+  }
+  f->fd = -1;
+  f->buf = buf;
+  f->end = size;
+  f->size = size;
+  f->iomode = fopenflags(mode);
+  if (f->iomode & O_APPEND) {
+    if ((p = memchr(buf, '\0', size))) {
+      f->beg = p - (char *)buf;
+    } else {
+      f->beg = f->end;
+    }
+  }
+  return f;
+}
diff --git a/stdio/fopen.c b/stdio/fopen.c
new file mode 100644
index 0000000..a5e0b05
--- /dev/null
+++ b/stdio/fopen.c
@@ -0,0 +1,74 @@
+/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
+│vi: set net ft=c ts=8 sts=2 sw=2 fenc=utf-8                                :vi│
+╞══════════════════════════════════════════════════════════════════════════════╡
+│ Copyright 2020 Justine Alexandra Roberts Tunney                              │
+│                                                                              │
+│ Permission to use, copy, modify, and/or distribute this software for         │
+│ any purpose with or without fee is hereby granted, provided that the         │
+│ above copyright notice and this permission notice appear in all copies.      │
+│                                                                              │
+│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL                │
+│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │
+│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │
+│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │
+│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │
+│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │
+│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │
+│ PERFORMANCE OF THIS SOFTWARE.                                                │
+╚─────────────────────────────────────────────────────────────────────────────*/
+#include "libc/calls/calls.h"
+#include "libc/mem/mem.h"
+#include "libc/stdio/stdio.h"
+#include "libc/str/str.h"
+#include "libc/sysv/consts/o.h"
+
+static const char *fixpathname(const char *pathname, int flags) {
+  if ((flags & O_ACCMODE) == O_RDONLY && strcmp(pathname, "-") == 0) {
+    return "/dev/stdin";
+  } else if ((flags & O_ACCMODE) == O_WRONLY && strcmp(pathname, "-") == 0) {
+    return "/dev/stdout";
+  } else {
+    return pathname;
+  }
+}
+
+static int openpathname(const char *pathname, int flags, bool *out_noclose) {
+  if ((flags & O_ACCMODE) == O_RDONLY && strcmp(pathname, "/dev/stdin") == 0) {
+    *out_noclose = true;
+    return fileno(stdin);
+  } else if ((flags & O_ACCMODE) == O_WRONLY &&
+             strcmp(pathname, "/dev/stdout") == 0) {
+    *out_noclose = true;
+    return fileno(stdout);
+  } else {
+    *out_noclose = false;
+    return open(pathname, flags, 0666);
+  }
+}
+
+/**
+ * Opens file as stream object.
+ *
+ * @param pathname is a utf-8 ideally relative filename
+ * @param mode is the string mode/flag DSL see fopenflags()
+ * @return new object to be free'd by fclose() or NULL w/ errno
+ * @note microsoft unilaterally deprecated this function lool
+ */
+FILE *fopen(const char *pathname, const char *mode) {
+  FILE *f;
+  bool noclose;
+  int fd, flags;
+  flags = fopenflags(mode);
+  pathname = fixpathname(pathname, flags);
+  if ((fd = openpathname(pathname, flags, &noclose)) != -1) {
+    if ((f = fdopen(fd, mode)) != NULL) {
+      f->noclose = noclose;
+      return f;
+    } else {
+      if (!noclose) close(fd);
+      return NULL;
+    }
+  } else {
+    return NULL;
+  }
+}
diff --git a/stdio/fopenflags.c b/stdio/fopenflags.c
new file mode 100644
index 0000000..268ea61
--- /dev/null
+++ b/stdio/fopenflags.c
@@ -0,0 +1,47 @@
+/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
+│vi: set net ft=c ts=8 sts=2 sw=2 fenc=utf-8                                :vi│
+╞══════════════════════════════════════════════════════════════════════════════╡
+│ Copyright 2020 Justine Alexandra Roberts Tunney                              │
+│                                                                              │
+│ Permission to use, copy, modify, and/or distribute this software for         │
+│ any purpose with or without fee is hereby granted, provided that the         │
+│ above copyright notice and this permission notice appear in all copies.      │
+│                                                                              │
+│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL                │
+│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │
+│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │
+│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │
+│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │
+│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │
+│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │
+│ PERFORMANCE OF THIS SOFTWARE.                                                │
+╚─────────────────────────────────────────────────────────────────────────────*/
+#include "libc/calls/calls.h"
+#include "libc/stdio/stdio.h"
+#include "libc/sysv/consts/o.h"
+
+/**
+ * Turns stdio flags description string into bitmask.
+ */
+int fopenflags(const char *mode) {
+  unsigned omode, flags;
+  omode = flags = 0;
+  do {
+    if (*mode == 'r') {
+      omode = O_RDONLY;
+    } else if (*mode == 'w') {
+      omode = O_WRONLY;
+      flags |= O_CREAT | O_TRUNC;
+    } else if (*mode == 'a') {
+      omode = O_WRONLY;
+      flags |= O_CREAT | O_APPEND;
+    } else if (*mode == '+') {
+      omode = O_RDWR;
+    } else if (*mode == 'x') {
+      flags |= O_EXCL;
+    } else if (*mode == 'e') {
+      flags |= O_CLOEXEC;
+    }
+  } while (*mode++);
+  return omode | flags;
+}
diff --git a/stdio/fpending.c b/stdio/fpending.c
new file mode 100644
index 0000000..1d54071
--- /dev/null
+++ b/stdio/fpending.c
@@ -0,0 +1,26 @@
+/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
+│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8                                :vi│
+╞══════════════════════════════════════════════════════════════════════════════╡
+│ Copyright 2021 Justine Alexandra Roberts Tunney                              │
+│                                                                              │
+│ Permission to use, copy, modify, and/or distribute this software for         │
+│ any purpose with or without fee is hereby granted, provided that the         │
+│ above copyright notice and this permission notice appear in all copies.      │
+│                                                                              │
+│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL                │
+│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │
+│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │
+│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │
+│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │
+│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │
+│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │
+│ PERFORMANCE OF THIS SOFTWARE.                                                │
+╚─────────────────────────────────────────────────────────────────────────────*/
+#include "libc/stdio/stdio_ext.h"
+
+/**
+ * Returns number of pending output bytes.
+ */
+size_t __fpending(FILE *f) {
+  return f->end - f->beg;
+}
diff --git a/stdio/fprintf.c b/stdio/fprintf.c
new file mode 100644
index 0000000..10223fb
--- /dev/null
+++ b/stdio/fprintf.c
@@ -0,0 +1,28 @@
+/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
+│vi: set net ft=c ts=8 sts=2 sw=2 fenc=utf-8                                :vi│
+╞══════════════════════════════════════════════════════════════════════════════╡
+│ Copyright 2020 Justine Alexandra Roberts Tunney                              │
+│                                                                              │
+│ Permission to use, copy, modify, and/or distribute this software for         │
+│ any purpose with or without fee is hereby granted, provided that the         │
+│ above copyright notice and this permission notice appear in all copies.      │
+│                                                                              │
+│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL                │
+│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │
+│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │
+│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │
+│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │
+│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │
+│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │
+│ PERFORMANCE OF THIS SOFTWARE.                                                │
+╚─────────────────────────────────────────────────────────────────────────────*/
+#include "libc/stdio/stdio.h"
+
+int(fprintf)(FILE *f, const char *fmt, ...) {
+  int rc;
+  va_list va;
+  va_start(va, fmt);
+  rc = (vfprintf)(f, fmt, va);
+  va_end(va);
+  return rc;
+}
diff --git a/stdio/fpurge.c b/stdio/fpurge.c
new file mode 100644
index 0000000..ae87dd1
--- /dev/null
+++ b/stdio/fpurge.c
@@ -0,0 +1,26 @@
+/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
+│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8                                :vi│
+╞══════════════════════════════════════════════════════════════════════════════╡
+│ Copyright 2021 Justine Alexandra Roberts Tunney                              │
+│                                                                              │
+│ Permission to use, copy, modify, and/or distribute this software for         │
+│ any purpose with or without fee is hereby granted, provided that the         │
+│ above copyright notice and this permission notice appear in all copies.      │
+│                                                                              │
+│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL                │
+│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │
+│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │
+│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │
+│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │
+│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │
+│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │
+│ PERFORMANCE OF THIS SOFTWARE.                                                │
+╚─────────────────────────────────────────────────────────────────────────────*/
+#include "libc/stdio/stdio_ext.h"
+
+/**
+ * Discards contents of stream buffer.
+ */
+void __fpurge(FILE *f) {
+  f->beg = f->end = 0;
+}
diff --git a/stdio/fputc.c b/stdio/fputc.c
new file mode 100644
index 0000000..635294f
--- /dev/null
+++ b/stdio/fputc.c
@@ -0,0 +1,38 @@
+/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
+│vi: set net ft=c ts=8 sts=2 sw=2 fenc=utf-8                                :vi│
+╞══════════════════════════════════════════════════════════════════════════════╡
+│ Copyright 2020 Justine Alexandra Roberts Tunney                              │
+│                                                                              │
+│ Permission to use, copy, modify, and/or distribute this software for         │
+│ any purpose with or without fee is hereby granted, provided that the         │
+│ above copyright notice and this permission notice appear in all copies.      │
+│                                                                              │
+│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL                │
+│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │
+│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │
+│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │
+│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │
+│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │
+│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │
+│ PERFORMANCE OF THIS SOFTWARE.                                                │
+╚─────────────────────────────────────────────────────────────────────────────*/
+#include "libc/calls/calls.h"
+#include "libc/stdio/stdio.h"
+
+/**
+ * Writes byte to stream.
+ *
+ * @param c is byte to buffer or write, which is masked
+ * @return c as unsigned char if written or -1 w/ errno
+ */
+int fputc(int c, FILE *f) {
+  unsigned char b;
+  if (c != '\n' && f->beg < f->size && f->bufmode != _IONBF) {
+    f->buf[f->beg++] = c;
+    return c & 0xff;
+  } else {
+    b = c;
+    if (!fwrite(&b, 1, 1, f)) return -1;
+    return b;
+  }
+}
diff --git a/stdio/fputs.c b/stdio/fputs.c
new file mode 100644
index 0000000..149b03c
--- /dev/null
+++ b/stdio/fputs.c
@@ -0,0 +1,39 @@
+/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
+│vi: set net ft=c ts=8 sts=2 sw=2 fenc=utf-8                                :vi│
+╞══════════════════════════════════════════════════════════════════════════════╡
+│ Copyright 2020 Justine Alexandra Roberts Tunney                              │
+│                                                                              │
+│ Permission to use, copy, modify, and/or distribute this software for         │
+│ any purpose with or without fee is hereby granted, provided that the         │
+│ above copyright notice and this permission notice appear in all copies.      │
+│                                                                              │
+│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL                │
+│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │
+│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │
+│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │
+│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │
+│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │
+│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │
+│ PERFORMANCE OF THIS SOFTWARE.                                                │
+╚─────────────────────────────────────────────────────────────────────────────*/
+#include "libc/stdio/stdio.h"
+#include "libc/str/str.h"
+
+/**
+ * Writes string to stream.
+ *
+ * Writing stops at the NUL-terminator, which isn't included in output.
+ * This function blocks until the full string is written, unless an
+ * unrecoverable error happens.
+ *
+ * @param s is a NUL-terminated string that's non-NULL
+ * @param f is an open stream
+ * @return bytes written, or -1 w/ errno
+ */
+int fputs(const char *s, FILE *f) {
+  size_t n, r;
+  n = strlen(s);
+  r = fwrite(s, 1, n, f);
+  if (!r && n) return -1;
+  return r;
+}
diff --git a/stdio/fputwc.c b/stdio/fputwc.c
new file mode 100644
index 0000000..3bb23e7
--- /dev/null
+++ b/stdio/fputwc.c
@@ -0,0 +1,40 @@
+/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
+│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8                                :vi│
+╞══════════════════════════════════════════════════════════════════════════════╡
+│ Copyright 2020 Justine Alexandra Roberts Tunney                              │
+│                                                                              │
+│ Permission to use, copy, modify, and/or distribute this software for         │
+│ any purpose with or without fee is hereby granted, provided that the         │
+│ above copyright notice and this permission notice appear in all copies.      │
+│                                                                              │
+│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL                │
+│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │
+│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │
+│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │
+│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │
+│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │
+│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │
+│ PERFORMANCE OF THIS SOFTWARE.                                                │
+╚─────────────────────────────────────────────────────────────────────────────*/
+#include "libc/stdio/stdio.h"
+#include "libc/str/tpenc.h"
+
+/**
+ * Writes wide character to stream.
+ *
+ * @return wc if written or -1 w/ errno
+ */
+wint_t fputwc(wchar_t wc, FILE *f) {
+  uint64_t w;
+  if (wc != -1) {
+    w = tpenc(wc);
+    do {
+      if (fputc(w, f) == -1) {
+        return -1;
+      }
+    } while ((w >>= 8));
+    return wc;
+  } else {
+    return -1;
+  }
+}
diff --git a/stdio/fputws.c b/stdio/fputws.c
new file mode 100644
index 0000000..b31fb17
--- /dev/null
+++ b/stdio/fputws.c
@@ -0,0 +1,44 @@
+/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
+│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8                                :vi│
+╞══════════════════════════════════════════════════════════════════════════════╡
+│ Copyright 2020 Justine Alexandra Roberts Tunney                              │
+│                                                                              │
+│ Permission to use, copy, modify, and/or distribute this software for         │
+│ any purpose with or without fee is hereby granted, provided that the         │
+│ above copyright notice and this permission notice appear in all copies.      │
+│                                                                              │
+│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL                │
+│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │
+│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │
+│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │
+│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │
+│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │
+│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │
+│ PERFORMANCE OF THIS SOFTWARE.                                                │
+╚─────────────────────────────────────────────────────────────────────────────*/
+#include "libc/errno.h"
+#include "libc/stdio/stdio.h"
+
+/**
+ * Writes wide character string to stream.
+ *
+ * Writing stops at the NUL-terminator, which isn't included in output.
+ * This function blocks until the full string is written, unless an
+ * unrecoverable error happens.
+ *
+ * @param s is a NUL-terminated string that's non-NULL
+ * @param f is an open stream
+ * @return strlen(s) or -1 w/ errno on error
+ */
+int fputws(const wchar_t *s, FILE *f) {
+  int res = 0;
+  while (*s) {
+    if (fputwc(*s++, f) == -1) {
+      if (ferror(f) == EINTR) continue;
+      if (feof(f)) errno = f->state = EPIPE;
+      return -1;
+    }
+    ++res;
+  }
+  return ++res;
+}
diff --git a/stdio/fread.c b/stdio/fread.c
new file mode 100644
index 0000000..52fea4d
--- /dev/null
+++ b/stdio/fread.c
@@ -0,0 +1,99 @@
+/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
+│vi: set net ft=c ts=8 sts=2 sw=2 fenc=utf-8                                :vi│
+╞══════════════════════════════════════════════════════════════════════════════╡
+│ Copyright 2020 Justine Alexandra Roberts Tunney                              │
+│                                                                              │
+│ Permission to use, copy, modify, and/or distribute this software for         │
+│ any purpose with or without fee is hereby granted, provided that the         │
+│ above copyright notice and this permission notice appear in all copies.      │
+│                                                                              │
+│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL                │
+│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │
+│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │
+│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │
+│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │
+│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │
+│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │
+│ PERFORMANCE OF THIS SOFTWARE.                                                │
+╚─────────────────────────────────────────────────────────────────────────────*/
+#include "libc/calls/calls.h"
+#include "libc/calls/struct/iovec.h"
+#include "libc/errno.h"
+#include "libc/fmt/conv.h"
+#include "libc/macros.internal.h"
+#include "libc/runtime/runtime.h"
+#include "libc/sock/sock.h"
+#include "libc/stdio/internal.h"
+#include "libc/stdio/stdio.h"
+#include "libc/str/internal.h"
+#include "libc/str/str.h"
+#include "libc/sysv/consts/o.h"
+#include "libc/sysv/errfuns.h"
+
+/**
+ * Reads data from stream.
+ *
+ * @param stride specifies the size of individual items
+ * @param count is the number of strides to fetch
+ * @return count on success, [0,count) on eof, or 0 on error or count==0
+ */
+size_t fread(void *buf, size_t stride, size_t count, FILE *f) {
+  char *p;
+  ssize_t rc;
+  size_t n, m;
+  struct iovec iov[2];
+  if ((f->iomode & O_ACCMODE) == O_WRONLY) {
+    f->state = errno = EBADF;
+    return 0;
+  }
+  if (f->beg > f->end) {
+    f->state = errno = EINVAL;
+    return 0;
+  }
+  p = buf;
+  n = stride * count;
+  m = f->end - f->beg;
+  memcpy(p, f->buf + f->beg, MIN(n, m));
+  if (n < m) {
+    f->beg += n;
+    return count;
+  }
+  if (n == m) {
+    f->beg = f->end = 0;
+    return count;
+  }
+  if (f->fd == -1) {
+    f->beg = 0;
+    f->end = 0;
+    f->state = -1;
+    return m / stride;
+  }
+  iov[0].iov_base = p + m;
+  iov[0].iov_len = n - m;
+  if (f->bufmode != _IONBF && n < f->size) {
+    iov[1].iov_base = f->buf;
+    if (f->size > PUSHBACK) {
+      iov[1].iov_len = f->size - PUSHBACK;
+    } else {
+      iov[1].iov_len = f->size;
+    }
+  } else {
+    iov[1].iov_base = NULL;
+    iov[1].iov_len = 0;
+  }
+  if ((rc = readv(f->fd, iov, 2)) == -1) {
+    f->state = errno;
+    return 0;
+  }
+  n = rc;
+  f->beg = 0;
+  f->end = 0;
+  if (n > iov[0].iov_len) {
+    f->end += n - iov[0].iov_len;
+    return count;
+  } else {
+    n = (m + n) / stride;
+    if (n < count) f->state = -1;
+    return n;
+  }
+}
diff --git a/stdio/freadable.c b/stdio/freadable.c
new file mode 100644
index 0000000..23281cb
--- /dev/null
+++ b/stdio/freadable.c
@@ -0,0 +1,28 @@
+/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
+│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8                                :vi│
+╞══════════════════════════════════════════════════════════════════════════════╡
+│ Copyright 2021 Justine Alexandra Roberts Tunney                              │
+│                                                                              │
+│ Permission to use, copy, modify, and/or distribute this software for         │
+│ any purpose with or without fee is hereby granted, provided that the         │
+│ above copyright notice and this permission notice appear in all copies.      │
+│                                                                              │
+│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL                │
+│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │
+│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │
+│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │
+│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │
+│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │
+│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │
+│ PERFORMANCE OF THIS SOFTWARE.                                                │
+╚─────────────────────────────────────────────────────────────────────────────*/
+#include "libc/stdio/stdio_ext.h"
+#include "libc/sysv/consts/o.h"
+
+/**
+ * Returns nonzero if stream allows reading.
+ */
+int __freadable(FILE *f) {
+  return (f->iomode & O_ACCMODE) == O_RDONLY ||
+         (f->iomode & O_ACCMODE) == O_RDWR;
+}
diff --git a/stdio/freading.c b/stdio/freading.c
new file mode 100644
index 0000000..07f2f22
--- /dev/null
+++ b/stdio/freading.c
@@ -0,0 +1,27 @@
+/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
+│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8                                :vi│
+╞══════════════════════════════════════════════════════════════════════════════╡
+│ Copyright 2021 Justine Alexandra Roberts Tunney                              │
+│                                                                              │
+│ Permission to use, copy, modify, and/or distribute this software for         │
+│ any purpose with or without fee is hereby granted, provided that the         │
+│ above copyright notice and this permission notice appear in all copies.      │
+│                                                                              │
+│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL                │
+│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │
+│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │
+│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │
+│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │
+│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │
+│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │
+│ PERFORMANCE OF THIS SOFTWARE.                                                │
+╚─────────────────────────────────────────────────────────────────────────────*/
+#include "libc/stdio/stdio_ext.h"
+#include "libc/sysv/consts/o.h"
+
+/**
+ * Returns nonzero if stream is read only.
+ */
+int __freading(FILE *f) {
+  return (f->iomode & O_ACCMODE) == O_RDONLY;
+}
diff --git a/stdio/freopen.c b/stdio/freopen.c
new file mode 100644
index 0000000..2f83742
--- /dev/null
+++ b/stdio/freopen.c
@@ -0,0 +1,60 @@
+/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
+│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8                                :vi│
+╞══════════════════════════════════════════════════════════════════════════════╡
+│ Copyright 2020 Justine Alexandra Roberts Tunney                              │
+│                                                                              │
+│ Permission to use, copy, modify, and/or distribute this software for         │
+│ any purpose with or without fee is hereby granted, provided that the         │
+│ above copyright notice and this permission notice appear in all copies.      │
+│                                                                              │
+│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL                │
+│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │
+│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │
+│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │
+│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │
+│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │
+│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │
+│ PERFORMANCE OF THIS SOFTWARE.                                                │
+╚─────────────────────────────────────────────────────────────────────────────*/
+#include "libc/calls/calls.h"
+#include "libc/stdio/stdio.h"
+#include "libc/sysv/consts/f.h"
+#include "libc/sysv/consts/fd.h"
+#include "libc/sysv/consts/o.h"
+
+/**
+ * Overwrites existing stream.
+ *
+ * This function can be used in two ways. The first is sort of a
+ * mutating assignment. The second behavior, if pathname is NULL, is
+ * just changing the mode of an already open file descriptor.
+ *
+ * @param pathname is the file to open or NULL
+ * @param mode is the mode string flags, see fopenflags()
+ * @param stream is the existing allocated stream memory, which is
+ *     flushed and closed if already open
+ * @return stream object if successful, or NULL w/ errno
+ */
+FILE *freopen(const char *pathname, const char *mode, FILE *stream) {
+  int fd;
+  unsigned flags;
+  flags = fopenflags(mode);
+  fflush(stream);
+  if (pathname) {
+    /* open new stream, overwriting existing alloc */
+    if ((fd = open(pathname, flags, 0666)) != -1) {
+      dup3(fd, stream->fd, flags & O_CLOEXEC);
+      close(fd);
+      stream->iomode = flags;
+      stream->beg = 0;
+      stream->end = 0;
+      return stream;
+    } else {
+      return NULL;
+    }
+  } else {
+    fcntl(stream->fd, F_SETFD, !!(flags & O_CLOEXEC));
+    fcntl(stream->fd, F_SETFL, flags & ~O_CLOEXEC);
+    return stream;
+  }
+}
diff --git a/stdio/fscanf.c b/stdio/fscanf.c
new file mode 100644
index 0000000..a713b7b
--- /dev/null
+++ b/stdio/fscanf.c
@@ -0,0 +1,44 @@
+/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
+│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8                                :vi│
+╞══════════════════════════════════════════════════════════════════════════════╡
+│ Copyright 2020 Justine Alexandra Roberts Tunney                              │
+│                                                                              │
+│ Permission to use, copy, modify, and/or distribute this software for         │
+│ any purpose with or without fee is hereby granted, provided that the         │
+│ above copyright notice and this permission notice appear in all copies.      │
+│                                                                              │
+│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL                │
+│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │
+│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │
+│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │
+│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │
+│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │
+│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │
+│ PERFORMANCE OF THIS SOFTWARE.                                                │
+╚─────────────────────────────────────────────────────────────────────────────*/
+#include "libc/fmt/fmt.h"
+#include "libc/stdio/stdio.h"
+
+/**
+ * Decodes data from stream.
+ *
+ * To read a line of data from a well-formed trustworthy file:
+ *
+ *     int x, y;
+ *     char text[256];
+ *     fscanf(f, "%d %d %s\n", &x, &y, text);
+ *
+ * Please note that this function is brittle by default, which makes it
+ * a good fit for yolo coding. With some toil it can be used in a way
+ * that makes it reasonably hardened although getline() may be better.
+ *
+ * @see libc/fmt/vcscanf.c
+ */
+int(fscanf)(FILE *stream, const char *fmt, ...) {
+  int rc;
+  va_list va;
+  va_start(va, fmt);
+  rc = (vcscanf)((int (*)(void *))fgetc, (void *)ungetc, stream, fmt, va);
+  va_end(va);
+  return rc;
+}
diff --git a/stdio/fseek.c b/stdio/fseek.c
new file mode 100644
index 0000000..f9c92c7
--- /dev/null
+++ b/stdio/fseek.c
@@ -0,0 +1,36 @@
+/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
+│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8                                :vi│
+╞══════════════════════════════════════════════════════════════════════════════╡
+│ Copyright 2020 Justine Alexandra Roberts Tunney                              │
+│                                                                              │
+│ Permission to use, copy, modify, and/or distribute this software for         │
+│ any purpose with or without fee is hereby granted, provided that the         │
+│ above copyright notice and this permission notice appear in all copies.      │
+│                                                                              │
+│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL                │
+│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │
+│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │
+│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │
+│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │
+│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │
+│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │
+│ PERFORMANCE OF THIS SOFTWARE.                                                │
+╚─────────────────────────────────────────────────────────────────────────────*/
+#include "libc/stdio/stdio.h"
+
+/**
+ * Repositions open file stream.
+ *
+ * This function flushes the buffer (unless it's currently in the EOF
+ * state) and then calls lseek() on the underlying file. If the stream
+ * is in the EOF state, this function can be used to restore it without
+ * needing to reopen the file.
+ *
+ * @param f is a non-null stream handle
+ * @param offset is the byte delta
+ * @param whence can be SEET_SET, SEEK_CUR, or SEEK_END
+ * @returns 0 on success or -1 on error
+ */
+int fseek(FILE *f, long offset, int whence) {
+  return fseeko(f, offset, whence);
+}
diff --git a/stdio/fseeko.c b/stdio/fseeko.c
new file mode 100644
index 0000000..67dd330
--- /dev/null
+++ b/stdio/fseeko.c
@@ -0,0 +1,83 @@
+/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
+│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8                                :vi│
+╞══════════════════════════════════════════════════════════════════════════════╡
+│ Copyright 2021 Justine Alexandra Roberts Tunney                              │
+│                                                                              │
+│ Permission to use, copy, modify, and/or distribute this software for         │
+│ any purpose with or without fee is hereby granted, provided that the         │
+│ above copyright notice and this permission notice appear in all copies.      │
+│                                                                              │
+│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL                │
+│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │
+│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │
+│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │
+│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │
+│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │
+│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │
+│ PERFORMANCE OF THIS SOFTWARE.                                                │
+╚─────────────────────────────────────────────────────────────────────────────*/
+#include "libc/calls/calls.h"
+#include "libc/errno.h"
+#include "libc/stdio/stdio.h"
+#include "libc/sysv/consts/o.h"
+
+/**
+ * Repositions open file stream.
+ *
+ * This function flushes the buffer (unless it's currently in the EOF
+ * state) and then calls lseek() on the underlying file. If the stream
+ * is in the EOF state, this function can be used to restore it without
+ * needing to reopen the file.
+ *
+ * @param f is a non-null stream handle
+ * @param offset is the byte delta
+ * @param whence can be SEET_SET, SEEK_CUR, or SEEK_END
+ * @returns 0 on success or -1 on error
+ */
+int fseeko(FILE *f, int64_t offset, int whence) {
+  ssize_t rc;
+  int64_t pos;
+  if (f->fd != -1) {
+    if (f->beg && !f->end && (f->iomode & O_ACCMODE) != O_RDONLY) {
+      if ((rc = write(f->fd, f->buf, f->beg)) == -1) {
+        f->state = errno;
+        return -1;
+      }
+      if (rc != f->beg) abort();
+      f->beg = 0;
+    }
+    if (whence == SEEK_CUR && f->beg < f->end) {
+      offset -= f->end - f->beg;
+    }
+    if (lseek(f->fd, offset, whence) != -1) {
+      f->beg = 0;
+      f->end = 0;
+      return 0;
+    } else {
+      f->state = errno == ESPIPE ? EBADF : errno;
+      return -1;
+    }
+  } else {
+    switch (whence) {
+      case SEEK_SET:
+        pos = offset;
+        break;
+      case SEEK_CUR:
+        pos = f->beg + offset;
+        break;
+      case SEEK_END:
+        pos = f->end + offset;
+        break;
+      default:
+        pos = -1;
+        break;
+    }
+    if (0 <= pos && pos <= f->end) {
+      f->beg = pos;
+      return 0;
+    } else {
+      f->state = errno = EINVAL;
+      return -1;
+    }
+  }
+}
diff --git a/stdio/fsetlocking.c b/stdio/fsetlocking.c
new file mode 100644
index 0000000..2dd880e
--- /dev/null
+++ b/stdio/fsetlocking.c
@@ -0,0 +1,26 @@
+/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
+│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8                                :vi│
+╞══════════════════════════════════════════════════════════════════════════════╡
+│ Copyright 2021 Justine Alexandra Roberts Tunney                              │
+│                                                                              │
+│ Permission to use, copy, modify, and/or distribute this software for         │
+│ any purpose with or without fee is hereby granted, provided that the         │
+│ above copyright notice and this permission notice appear in all copies.      │
+│                                                                              │
+│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL                │
+│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │
+│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │
+│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │
+│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │
+│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │
+│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │
+│ PERFORMANCE OF THIS SOFTWARE.                                                │
+╚─────────────────────────────────────────────────────────────────────────────*/
+#include "libc/stdio/stdio_ext.h"
+
+/**
+ * Does nothing and returns `FSETLOCKING_BYCALLER`.
+ */
+int __fsetlocking(FILE *f, int type) {
+  return FSETLOCKING_BYCALLER;
+}
diff --git a/stdio/fsetpos.c b/stdio/fsetpos.c
new file mode 100644
index 0000000..899ab69
--- /dev/null
+++ b/stdio/fsetpos.c
@@ -0,0 +1,24 @@
+/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
+│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8                                :vi│
+╞══════════════════════════════════════════════════════════════════════════════╡
+│ Copyright 2020 Justine Alexandra Roberts Tunney                              │
+│                                                                              │
+│ Permission to use, copy, modify, and/or distribute this software for         │
+│ any purpose with or without fee is hereby granted, provided that the         │
+│ above copyright notice and this permission notice appear in all copies.      │
+│                                                                              │
+│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL                │
+│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │
+│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │
+│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │
+│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │
+│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │
+│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │
+│ PERFORMANCE OF THIS SOFTWARE.                                                │
+╚─────────────────────────────────────────────────────────────────────────────*/
+#include "libc/stdio/stdio.h"
+#include "libc/calls/calls.h"
+
+int fsetpos(FILE *stream, const fpos_t *pos) {
+  return fseek(stream, *pos, SEEK_SET);
+}
diff --git a/stdio/ftell.c b/stdio/ftell.c
new file mode 100644
index 0000000..1f843ea
--- /dev/null
+++ b/stdio/ftell.c
@@ -0,0 +1,29 @@
+/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
+│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8                                :vi│
+╞══════════════════════════════════════════════════════════════════════════════╡
+│ Copyright 2020 Justine Alexandra Roberts Tunney                              │
+│                                                                              │
+│ Permission to use, copy, modify, and/or distribute this software for         │
+│ any purpose with or without fee is hereby granted, provided that the         │
+│ above copyright notice and this permission notice appear in all copies.      │
+│                                                                              │
+│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL                │
+│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │
+│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │
+│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │
+│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │
+│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │
+│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │
+│ PERFORMANCE OF THIS SOFTWARE.                                                │
+╚─────────────────────────────────────────────────────────────────────────────*/
+#include "libc/stdio/stdio.h"
+
+/**
+ * Returns current position of stream.
+ *
+ * @param stream is a non-null stream handle
+ * @returns current byte offset from beginning, or -1 w/ errno
+ */
+long ftell(FILE *f) {
+  return ftello(f);
+}
diff --git a/stdio/ftello.c b/stdio/ftello.c
new file mode 100644
index 0000000..7c6148a
--- /dev/null
+++ b/stdio/ftello.c
@@ -0,0 +1,54 @@
+/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
+│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8                                :vi│
+╞══════════════════════════════════════════════════════════════════════════════╡
+│ Copyright 2020 Justine Alexandra Roberts Tunney                              │
+│                                                                              │
+│ Permission to use, copy, modify, and/or distribute this software for         │
+│ any purpose with or without fee is hereby granted, provided that the         │
+│ above copyright notice and this permission notice appear in all copies.      │
+│                                                                              │
+│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL                │
+│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │
+│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │
+│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │
+│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │
+│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │
+│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │
+│ PERFORMANCE OF THIS SOFTWARE.                                                │
+╚─────────────────────────────────────────────────────────────────────────────*/
+#include "libc/calls/calls.h"
+#include "libc/errno.h"
+#include "libc/runtime/runtime.h"
+#include "libc/stdio/stdio.h"
+#include "libc/sysv/consts/o.h"
+
+/**
+ * Returns current position of stream.
+ *
+ * @param stream is a non-null stream handle
+ * @returns current byte offset from beginning, or -1 w/ errno
+ */
+int64_t ftello(FILE *f) {
+  ssize_t rc;
+  int64_t pos;
+  uint32_t skew;
+  if (f->fd != -1) {
+    if (f->beg && !f->end && (f->iomode & O_ACCMODE) != O_RDONLY) {
+      if ((rc = write(f->fd, f->buf, f->beg)) == -1) {
+        f->state = errno;
+        return -1;
+      }
+      if (rc != f->beg) abort();
+      f->beg = 0;
+    }
+    if ((pos = lseek(f->fd, 0, SEEK_CUR)) != -1) {
+      if (f->beg < f->end) pos -= f->end - f->beg;
+      return pos;
+    } else {
+      f->state = errno == ESPIPE ? EBADF : errno;
+      return -1;
+    }
+  } else {
+    return f->beg;
+  }
+}
diff --git a/stdio/fwritable.c b/stdio/fwritable.c
new file mode 100644
index 0000000..04562f4
--- /dev/null
+++ b/stdio/fwritable.c
@@ -0,0 +1,28 @@
+/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
+│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8                                :vi│
+╞══════════════════════════════════════════════════════════════════════════════╡
+│ Copyright 2021 Justine Alexandra Roberts Tunney                              │
+│                                                                              │
+│ Permission to use, copy, modify, and/or distribute this software for         │
+│ any purpose with or without fee is hereby granted, provided that the         │
+│ above copyright notice and this permission notice appear in all copies.      │
+│                                                                              │
+│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL                │
+│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │
+│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │
+│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │
+│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │
+│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │
+│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │
+│ PERFORMANCE OF THIS SOFTWARE.                                                │
+╚─────────────────────────────────────────────────────────────────────────────*/
+#include "libc/stdio/stdio_ext.h"
+#include "libc/sysv/consts/o.h"
+
+/**
+ * Returns nonzero if stream allows reading.
+ */
+int __fwritable(FILE *f) {
+  return (f->iomode & O_ACCMODE) == O_WRONLY ||
+         (f->iomode & O_ACCMODE) == O_RDWR;
+}
diff --git a/stdio/fwrite.c b/stdio/fwrite.c
new file mode 100644
index 0000000..30f1000
--- /dev/null
+++ b/stdio/fwrite.c
@@ -0,0 +1,89 @@
+/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
+│vi: set net ft=c ts=8 sts=2 sw=2 fenc=utf-8                                :vi│
+╞══════════════════════════════════════════════════════════════════════════════╡
+│ Copyright 2020 Justine Alexandra Roberts Tunney                              │
+│                                                                              │
+│ Permission to use, copy, modify, and/or distribute this software for         │
+│ any purpose with or without fee is hereby granted, provided that the         │
+│ above copyright notice and this permission notice appear in all copies.      │
+│                                                                              │
+│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL                │
+│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │
+│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │
+│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │
+│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │
+│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │
+│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │
+│ PERFORMANCE OF THIS SOFTWARE.                                                │
+╚─────────────────────────────────────────────────────────────────────────────*/
+#include "libc/calls/calls.h"
+#include "libc/calls/struct/iovec.h"
+#include "libc/errno.h"
+#include "libc/fmt/conv.h"
+#include "libc/macros.internal.h"
+#include "libc/runtime/runtime.h"
+#include "libc/sock/sock.h"
+#include "libc/stdio/internal.h"
+#include "libc/stdio/stdio.h"
+#include "libc/str/str.h"
+#include "libc/sysv/consts/o.h"
+
+/**
+ * Writes data to stream.
+ *
+ * @param stride specifies the size of individual items
+ * @param count is the number of strides to write
+ * @return count on success, [0,count) on EOF, 0 on error or count==0
+ */
+size_t fwrite(const void *data, size_t stride, size_t count, FILE *f) {
+  ldiv_t d;
+  ssize_t rc;
+  size_t n, m;
+  const char *p;
+  struct iovec iov[2];
+  if ((f->iomode & O_ACCMODE) == O_RDONLY) {
+    f->state = errno = EBADF;
+    return 0;
+  }
+  n = stride * count;
+  m = f->size - f->beg;
+  if (n <= m && f->bufmode != _IONBF) {
+    memcpy(f->buf + f->beg, data, n);
+    f->beg += n;
+    if (f->fd != -1 && f->bufmode == _IOLBF &&
+        (p = memrchr(f->buf, '\n', f->beg))) {
+      n = p + 1 - f->buf;
+      if ((rc = write(f->fd, f->buf, n)) == -1) {
+        if (errno == EINTR || errno == EAGAIN) return count;
+        f->state = errno;
+        return 0;
+      }
+      n = rc;
+      memmove(f->buf, f->buf + n, f->beg - n);
+      f->beg -= n;
+    }
+    return count;
+  }
+  if (f->fd == -1) {
+    n = MIN(n, m);
+    d = ldiv(n, stride);
+    n -= d.rem;
+    memcpy(f->buf + f->beg, data, n);
+    f->beg += n;
+    f->state = -1;
+    return d.quot;
+  }
+  iov[0].iov_base = f->buf;
+  iov[0].iov_len = f->beg;
+  iov[1].iov_base = data;
+  iov[1].iov_len = n;
+  n += f->beg;
+  if ((rc = writev(f->fd, iov, 2)) == -1) {
+    f->state = errno;
+    return 0;
+  }
+  m = rc;
+  if (n != m) abort();
+  f->beg = 0;
+  return count;
+}
diff --git a/stdio/fwriting.c b/stdio/fwriting.c
new file mode 100644
index 0000000..1820949
--- /dev/null
+++ b/stdio/fwriting.c
@@ -0,0 +1,27 @@
+/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
+│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8                                :vi│
+╞══════════════════════════════════════════════════════════════════════════════╡
+│ Copyright 2021 Justine Alexandra Roberts Tunney                              │
+│                                                                              │
+│ Permission to use, copy, modify, and/or distribute this software for         │
+│ any purpose with or without fee is hereby granted, provided that the         │
+│ above copyright notice and this permission notice appear in all copies.      │
+│                                                                              │
+│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL                │
+│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │
+│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │
+│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │
+│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │
+│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │
+│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │
+│ PERFORMANCE OF THIS SOFTWARE.                                                │
+╚─────────────────────────────────────────────────────────────────────────────*/
+#include "libc/stdio/stdio_ext.h"
+#include "libc/sysv/consts/o.h"
+
+/**
+ * Returns nonzero if stream is write only.
+ */
+int __fwriting(FILE *f) {
+  return (f->iomode & O_ACCMODE) == O_WRONLY;
+}
diff --git a/stdio/get_current_dir_name.c b/stdio/get_current_dir_name.c
new file mode 100644
index 0000000..f9fdd0b
--- /dev/null
+++ b/stdio/get_current_dir_name.c
@@ -0,0 +1,38 @@
+/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
+│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8                                :vi│
+╞══════════════════════════════════════════════════════════════════════════════╡
+│ Copyright 2020 Justine Alexandra Roberts Tunney                              │
+│                                                                              │
+│ Permission to use, copy, modify, and/or distribute this software for         │
+│ any purpose with or without fee is hereby granted, provided that the         │
+│ above copyright notice and this permission notice appear in all copies.      │
+│                                                                              │
+│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL                │
+│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │
+│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │
+│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │
+│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │
+│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │
+│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │
+│ PERFORMANCE OF THIS SOFTWARE.                                                │
+╚─────────────────────────────────────────────────────────────────────────────*/
+#include "libc/bits/safemacros.internal.h"
+#include "libc/calls/calls.h"
+#include "libc/mem/mem.h"
+#include "libc/runtime/runtime.h"
+#include "libc/sysv/errfuns.h"
+
+/**
+ * Returns current working directory.
+ *
+ * If the PWD environment variable is set, that'll be returned (since
+ * it's faster than issuing a system call).
+ *
+ * @return pointer that must be free()'d, or NULL w/ errno
+ */
+nodiscard char *get_current_dir_name(void) {
+  char *buf, *res;
+  if (!(buf = malloc(PATH_MAX))) return NULL;
+  if (!(res = (getcwd)(buf, PATH_MAX))) free(buf);
+  return res;
+}
diff --git a/stdio/getc.c b/stdio/getc.c
new file mode 100644
index 0000000..71082bc
--- /dev/null
+++ b/stdio/getc.c
@@ -0,0 +1,27 @@
+/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
+│vi: set net ft=c ts=8 sts=2 sw=2 fenc=utf-8                                :vi│
+╞══════════════════════════════════════════════════════════════════════════════╡
+│ Copyright 2020 Justine Alexandra Roberts Tunney                              │
+│                                                                              │
+│ Permission to use, copy, modify, and/or distribute this software for         │
+│ any purpose with or without fee is hereby granted, provided that the         │
+│ above copyright notice and this permission notice appear in all copies.      │
+│                                                                              │
+│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL                │
+│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │
+│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │
+│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │
+│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │
+│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │
+│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │
+│ PERFORMANCE OF THIS SOFTWARE.                                                │
+╚─────────────────────────────────────────────────────────────────────────────*/
+#include "libc/stdio/stdio.h"
+
+/**
+ * Reads byte from stream.
+ * @return byte in range 0..255, or -1 w/ errno
+ */
+int(getc)(FILE *f) {
+  return fgetc(f);
+}
diff --git a/stdio/getchar.c b/stdio/getchar.c
new file mode 100644
index 0000000..db56d6b
--- /dev/null
+++ b/stdio/getchar.c
@@ -0,0 +1,27 @@
+/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
+│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8                                :vi│
+╞══════════════════════════════════════════════════════════════════════════════╡
+│ Copyright 2021 Justine Alexandra Roberts Tunney                              │
+│                                                                              │
+│ Permission to use, copy, modify, and/or distribute this software for         │
+│ any purpose with or without fee is hereby granted, provided that the         │
+│ above copyright notice and this permission notice appear in all copies.      │
+│                                                                              │
+│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL                │
+│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │
+│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │
+│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │
+│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │
+│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │
+│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │
+│ PERFORMANCE OF THIS SOFTWARE.                                                │
+╚─────────────────────────────────────────────────────────────────────────────*/
+#include "libc/stdio/stdio.h"
+
+/**
+ * Reads byte from stream.
+ * @return byte in range 0..255, or -1 w/ errno
+ */
+int getchar(void) {
+  return fgetc(stdin);
+}
diff --git a/stdio/getdelim.c b/stdio/getdelim.c
new file mode 100644
index 0000000..dfdadf2
--- /dev/null
+++ b/stdio/getdelim.c
@@ -0,0 +1,79 @@
+/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
+│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8                                :vi│
+╞══════════════════════════════════════════════════════════════════════════════╡
+│ Copyright 2020 Justine Alexandra Roberts Tunney                              │
+│                                                                              │
+│ Permission to use, copy, modify, and/or distribute this software for         │
+│ any purpose with or without fee is hereby granted, provided that the         │
+│ above copyright notice and this permission notice appear in all copies.      │
+│                                                                              │
+│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL                │
+│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │
+│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │
+│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │
+│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │
+│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │
+│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │
+│ PERFORMANCE OF THIS SOFTWARE.                                                │
+╚─────────────────────────────────────────────────────────────────────────────*/
+#include "libc/assert.h"
+#include "libc/calls/calls.h"
+#include "libc/errno.h"
+#include "libc/macros.internal.h"
+#include "libc/mem/mem.h"
+#include "libc/runtime/runtime.h"
+#include "libc/stdio/stdio.h"
+#include "libc/str/str.h"
+#include "libc/sysv/consts/o.h"
+
+/**
+ * Reads string from stream.
+ *
+ * @param s is the caller's buffer (in/out) which is extended or
+ *     allocated automatically, also NUL-terminated is guaranteed
+ * @param n is the capacity of s (in/out)
+ * @param delim is the stop char (and NUL is implicitly too)
+ * @return number of bytes read, including delim, excluding NUL, or -1
+ *     w/ errno on EOF or error; see ferror() and feof()
+ * @note this function can't punt EINTR to caller
+ * @see getline(), gettok_r()
+ */
+ssize_t getdelim(char **s, size_t *n, int delim, FILE *f) {
+  char *p;
+  ssize_t rc;
+  size_t i, m;
+  if ((f->iomode & O_ACCMODE) == O_WRONLY) {
+    f->state = errno = EBADF;
+    return -1;
+  }
+  if (f->beg > f->end || f->bufmode == _IONBF) {
+    f->state = errno = EINVAL;
+    return -1;
+  }
+  if (!*s) *n = 0;
+  for (i = 0;; i += m) {
+    m = f->end - f->beg;
+    if ((p = memchr(f->buf + f->beg, delim, m))) m = p + 1 - (f->buf + f->beg);
+    if (i + m + 1 > *n && !(*s = realloc(*s, (*n = i + m + 1)))) abort();
+    memcpy(*s + i, f->buf + f->beg, m);
+    (*s)[i + m] = '\0';
+    if ((f->beg += m) == f->end) f->beg = f->end = 0;
+    if (p) {
+      return i + m;
+    } else if (f->fd == -1) {
+      break;
+    } else if ((rc = read(f->fd, f->buf, f->size)) != -1) {
+      if (!rc) break;
+      f->end = rc;
+    } else if (errno != EINTR) {
+      f->state = errno;
+      return -1;
+    }
+  }
+  f->state = -1;
+  if (i + m) {
+    return i + m;
+  } else {
+    return -1;
+  }
+}
diff --git a/stdio/getline.c b/stdio/getline.c
new file mode 100644
index 0000000..4a5c259
--- /dev/null
+++ b/stdio/getline.c
@@ -0,0 +1,37 @@
+/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
+│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8                                :vi│
+╞══════════════════════════════════════════════════════════════════════════════╡
+│ Copyright 2020 Justine Alexandra Roberts Tunney                              │
+│                                                                              │
+│ Permission to use, copy, modify, and/or distribute this software for         │
+│ any purpose with or without fee is hereby granted, provided that the         │
+│ above copyright notice and this permission notice appear in all copies.      │
+│                                                                              │
+│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL                │
+│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │
+│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │
+│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │
+│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │
+│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │
+│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │
+│ PERFORMANCE OF THIS SOFTWARE.                                                │
+╚─────────────────────────────────────────────────────────────────────────────*/
+#include "libc/stdio/stdio.h"
+
+/**
+ * Reads line from stream.
+ *
+ * This function delegates to getdelim(), which provides further
+ * documentation. Concerning lines, please note the \n or \r\n are
+ * included in results, and can be removed with chomp().
+ *
+ * @param line is the caller's buffer (in/out) which is extended
+ *     automatically. *line may be NULL but only if *n is 0;
+ *     NUL-termination is guaranteed FTMP
+ * @return number of bytes read, including delim, excluding NUL, or -1
+ *     w/ errno on EOF or error; see ferror() and feof()
+ * @see xgetline(), getdelim(), gettok_r()
+ */
+ssize_t getline(char **line, size_t *n, FILE *f) {
+  return getdelim(line, n, '\n', f);
+}
diff --git a/stdio/gets.c b/stdio/gets.c
new file mode 100644
index 0000000..d62e623
--- /dev/null
+++ b/stdio/gets.c
@@ -0,0 +1,24 @@
+/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
+│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8                                :vi│
+╞══════════════════════════════════════════════════════════════════════════════╡
+│ Copyright 2020 Justine Alexandra Roberts Tunney                              │
+│                                                                              │
+│ Permission to use, copy, modify, and/or distribute this software for         │
+│ any purpose with or without fee is hereby granted, provided that the         │
+│ above copyright notice and this permission notice appear in all copies.      │
+│                                                                              │
+│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL                │
+│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │
+│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │
+│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │
+│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │
+│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │
+│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │
+│ PERFORMANCE OF THIS SOFTWARE.                                                │
+╚─────────────────────────────────────────────────────────────────────────────*/
+#include "libc/limits.h"
+#include "libc/stdio/stdio.h"
+
+compatfn char *gets(char *s) {
+  return fgets(s, INT_MAX, stdin);
+}
diff --git a/stdio/getwc.c b/stdio/getwc.c
new file mode 100644
index 0000000..2ec4cc1
--- /dev/null
+++ b/stdio/getwc.c
@@ -0,0 +1,27 @@
+/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
+│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8                                :vi│
+╞══════════════════════════════════════════════════════════════════════════════╡
+│ Copyright 2020 Justine Alexandra Roberts Tunney                              │
+│                                                                              │
+│ Permission to use, copy, modify, and/or distribute this software for         │
+│ any purpose with or without fee is hereby granted, provided that the         │
+│ above copyright notice and this permission notice appear in all copies.      │
+│                                                                              │
+│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL                │
+│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │
+│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │
+│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │
+│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │
+│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │
+│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │
+│ PERFORMANCE OF THIS SOFTWARE.                                                │
+╚─────────────────────────────────────────────────────────────────────────────*/
+#include "libc/stdio/stdio.h"
+
+/**
+ * Reads UTF-8 character from stream.
+ * @return wide character or -1 on EOF or error
+ */
+wint_t(getwc)(FILE *f) {
+  return fgetwc(f);
+}
diff --git a/stdio/getwchar.c b/stdio/getwchar.c
new file mode 100644
index 0000000..a455dbc
--- /dev/null
+++ b/stdio/getwchar.c
@@ -0,0 +1,27 @@
+/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
+│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8                                :vi│
+╞══════════════════════════════════════════════════════════════════════════════╡
+│ Copyright 2020 Justine Alexandra Roberts Tunney                              │
+│                                                                              │
+│ Permission to use, copy, modify, and/or distribute this software for         │
+│ any purpose with or without fee is hereby granted, provided that the         │
+│ above copyright notice and this permission notice appear in all copies.      │
+│                                                                              │
+│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL                │
+│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │
+│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │
+│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │
+│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │
+│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │
+│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │
+│ PERFORMANCE OF THIS SOFTWARE.                                                │
+╚─────────────────────────────────────────────────────────────────────────────*/
+#include "libc/stdio/stdio.h"
+
+/**
+ * Reads UTF-8 character from stream.
+ * @return wide character or -1 on EOF or error
+ */
+wint_t getwchar(void) {
+  return fgetwc(stdin);
+}
diff --git a/stdio/internal.h b/stdio/internal.h
new file mode 100644
index 0000000..ba8de1e
--- /dev/null
+++ b/stdio/internal.h
@@ -0,0 +1,19 @@
+#ifndef COSMOPOLITAN_LIBC_STDIO_INTERNAL_H_
+#define COSMOPOLITAN_LIBC_STDIO_INTERNAL_H_
+#include "libc/stdio/stdio.h"
+
+#define PUSHBACK 12
+
+#if !(__ASSEMBLER__ + __LINKER__ + 0)
+COSMOPOLITAN_C_START_
+
+extern char g_stdinbuf[BUFSIZ];
+extern char g_stdoutbuf[BUFSIZ];
+extern char g_stderrbuf[BUFSIZ];
+
+int __fflush_register(FILE *) hidden;
+void __fflush_unregister(FILE *) hidden;
+
+COSMOPOLITAN_C_END_
+#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
+#endif /* COSMOPOLITAN_LIBC_STDIO_INTERNAL_H_ */
diff --git a/stdio/mkostemp.c b/stdio/mkostemp.c
new file mode 100644
index 0000000..7d4bd03
--- /dev/null
+++ b/stdio/mkostemp.c
@@ -0,0 +1,23 @@
+/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
+│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8                                :vi│
+╞══════════════════════════════════════════════════════════════════════════════╡
+│ Copyright 2020 Justine Alexandra Roberts Tunney                              │
+│                                                                              │
+│ Permission to use, copy, modify, and/or distribute this software for         │
+│ any purpose with or without fee is hereby granted, provided that the         │
+│ above copyright notice and this permission notice appear in all copies.      │
+│                                                                              │
+│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL                │
+│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │
+│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │
+│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │
+│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │
+│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │
+│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │
+│ PERFORMANCE OF THIS SOFTWARE.                                                │
+╚─────────────────────────────────────────────────────────────────────────────*/
+#include "libc/stdio/temp.h"
+
+int mkostemp(char *template, unsigned flags) {
+  return mkostempsm(template, 0, flags, 0600);
+}
diff --git a/stdio/mkostemps.c b/stdio/mkostemps.c
new file mode 100644
index 0000000..2159770
--- /dev/null
+++ b/stdio/mkostemps.c
@@ -0,0 +1,26 @@
+/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
+│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8                                :vi│
+╞══════════════════════════════════════════════════════════════════════════════╡
+│ Copyright 2020 Justine Alexandra Roberts Tunney                              │
+│                                                                              │
+│ Permission to use, copy, modify, and/or distribute this software for         │
+│ any purpose with or without fee is hereby granted, provided that the         │
+│ above copyright notice and this permission notice appear in all copies.      │
+│                                                                              │
+│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL                │
+│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │
+│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │
+│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │
+│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │
+│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │
+│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │
+│ PERFORMANCE OF THIS SOFTWARE.                                                │
+╚─────────────────────────────────────────────────────────────────────────────*/
+#include "libc/stdio/temp.h"
+
+/**
+ * Delegates to mkotempsm() w/ owner-only non-execute access.
+ */
+nodiscard int mkostemps(char *template, int suffixlen, unsigned flags) {
+  return mkostempsm(template, suffixlen, flags, 0600);
+}
diff --git a/stdio/mkostempsm.c b/stdio/mkostempsm.c
new file mode 100644
index 0000000..f42e46f
--- /dev/null
+++ b/stdio/mkostempsm.c
@@ -0,0 +1,81 @@
+/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
+│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8                                :vi│
+╞══════════════════════════════════════════════════════════════════════════════╡
+│ Copyright 2020 Justine Alexandra Roberts Tunney                              │
+│                                                                              │
+│ Permission to use, copy, modify, and/or distribute this software for         │
+│ any purpose with or without fee is hereby granted, provided that the         │
+│ above copyright notice and this permission notice appear in all copies.      │
+│                                                                              │
+│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL                │
+│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │
+│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │
+│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │
+│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │
+│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │
+│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │
+│ PERFORMANCE OF THIS SOFTWARE.                                                │
+╚─────────────────────────────────────────────────────────────────────────────*/
+#include "libc/assert.h"
+#include "libc/calls/calls.h"
+#include "libc/errno.h"
+#include "libc/rand/lcg.internal.h"
+#include "libc/rand/rand.h"
+#include "libc/stdio/temp.h"
+#include "libc/str/str.h"
+#include "libc/sysv/consts/o.h"
+#include "libc/sysv/errfuns.h"
+
+#define RESEED   1024
+#define ATTEMPTS 10
+#define WILDCARD "XXXXXX"
+
+int mkostempsmi(char *tpl, int slen, unsigned flags, uint64_t *rando, int mode,
+                int openit(const char *file, int flags, ...)) {
+  size_t len = strlen(tpl);
+  size_t wildlen = strlen(WILDCARD);
+  if (len < wildlen || slen > len - wildlen) {
+    return einval();
+  }
+  char *ss = tpl + len - wildlen - slen;
+  assert(memcmp(ss, WILDCARD, wildlen) == 0);
+  flags = (flags & ~(flags & O_ACCMODE)) | O_RDWR | O_CREAT | O_EXCL;
+  unsigned attempts = ATTEMPTS;
+  do {
+    char *p = ss;
+    uint32_t num = KnuthLinearCongruentialGenerator(rando) >> 32;
+    for (unsigned i = 0; i < wildlen; ++i) {
+      p[i] = "0123456789abcdefghijklmnopqrstuvwxyz"[num & 31];
+      num >>= 5;
+    }
+    int fd;
+    if ((fd = openit(tpl, flags, 0600)) != -1) return fd;
+  } while (--attempts && errno == EEXIST);
+  memcpy(ss, WILDCARD, wildlen);
+  return -1;
+}
+
+static uint64_t g_mkostemps_rand;
+static uint64_t g_mkostemps_reseed;
+
+/**
+ * Opens unique temporary file.
+ *
+ * The substring XXXXXX is replaced with a pseudorandom number that's
+ * seeded automatically and grants 30 bits of randomness to each value.
+ * Retries are made in the unlikely event of collisions.
+ *
+ * @param template is a pathname relative to current directory by default,
+ *     that needs to have "XXXXXX" at the end of the string
+ * @param suffixlen may be nonzero to permit characters after the XXXXXX
+ * @param flags can have O_APPEND, O_CLOEXEC, etc.
+ * @param mode is conventionally 0600, for owner-only non-exec access
+ * @return exclusive open file descriptor for generated pathname,
+ *     or -1 w/ errno
+ * @see kTmpPath
+ */
+nodiscard int mkostempsm(char *template, int suffixlen, unsigned flags,
+                         int mode) {
+  if (g_mkostemps_reseed++ % RESEED == 0) g_mkostemps_rand = rand64();
+  return mkostempsmi(template, suffixlen, flags, &g_mkostemps_rand, mode, open);
+}
diff --git a/stdio/mkstemp.c b/stdio/mkstemp.c
new file mode 100644
index 0000000..881c3b4
--- /dev/null
+++ b/stdio/mkstemp.c
@@ -0,0 +1,23 @@
+/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
+│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8                                :vi│
+╞══════════════════════════════════════════════════════════════════════════════╡
+│ Copyright 2020 Justine Alexandra Roberts Tunney                              │
+│                                                                              │
+│ Permission to use, copy, modify, and/or distribute this software for         │
+│ any purpose with or without fee is hereby granted, provided that the         │
+│ above copyright notice and this permission notice appear in all copies.      │
+│                                                                              │
+│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL                │
+│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │
+│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │
+│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │
+│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │
+│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │
+│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │
+│ PERFORMANCE OF THIS SOFTWARE.                                                │
+╚─────────────────────────────────────────────────────────────────────────────*/
+#include "libc/stdio/temp.h"
+
+int mkstemp(char *template) {
+  return mkostempsm(template, 0, 0, 0600);
+}
diff --git a/stdio/mkstemps.c b/stdio/mkstemps.c
new file mode 100644
index 0000000..d785d93
--- /dev/null
+++ b/stdio/mkstemps.c
@@ -0,0 +1,23 @@
+/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
+│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8                                :vi│
+╞══════════════════════════════════════════════════════════════════════════════╡
+│ Copyright 2020 Justine Alexandra Roberts Tunney                              │
+│                                                                              │
+│ Permission to use, copy, modify, and/or distribute this software for         │
+│ any purpose with or without fee is hereby granted, provided that the         │
+│ above copyright notice and this permission notice appear in all copies.      │
+│                                                                              │
+│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL                │
+│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │
+│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │
+│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │
+│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │
+│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │
+│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │
+│ PERFORMANCE OF THIS SOFTWARE.                                                │
+╚─────────────────────────────────────────────────────────────────────────────*/
+#include "libc/stdio/temp.h"
+
+int mkstemps(char *template, int suffixlen) {
+  return mkostempsm(template, suffixlen, 0, 0600);
+}
diff --git a/stdio/mktemp.c b/stdio/mktemp.c
new file mode 100644
index 0000000..fb72216
--- /dev/null
+++ b/stdio/mktemp.c
@@ -0,0 +1,39 @@
+/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
+│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8                                :vi│
+╞══════════════════════════════════════════════════════════════════════════════╡
+│ Copyright 2020 Justine Alexandra Roberts Tunney                              │
+│                                                                              │
+│ Permission to use, copy, modify, and/or distribute this software for         │
+│ any purpose with or without fee is hereby granted, provided that the         │
+│ above copyright notice and this permission notice appear in all copies.      │
+│                                                                              │
+│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL                │
+│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │
+│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │
+│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │
+│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │
+│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │
+│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │
+│ PERFORMANCE OF THIS SOFTWARE.                                                │
+╚─────────────────────────────────────────────────────────────────────────────*/
+#include "libc/calls/calls.h"
+#include "libc/stdio/temp.h"
+#include "libc/sysv/errfuns.h"
+
+/**
+ * Generates unique filename.
+ *
+ * This function is usually frowned upon, since it's been known to
+ * create nasty opportunities for race conditions. Our implementation
+ * reflects that; consider using mkostemps().
+ */
+char *mktemp(char *template) {
+  int fd;
+  if ((fd = mkostemps(template, 0, 0)) != -1) {
+    close(fd);
+    unlink(template);
+  } else {
+    template[0] = '\0';
+  }
+  return template;
+}
diff --git a/stdio/pclose.c b/stdio/pclose.c
new file mode 100644
index 0000000..911855a
--- /dev/null
+++ b/stdio/pclose.c
@@ -0,0 +1,43 @@
+/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
+│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8                                :vi│
+╞══════════════════════════════════════════════════════════════════════════════╡
+│ Copyright 2021 Justine Alexandra Roberts Tunney                              │
+│                                                                              │
+│ Permission to use, copy, modify, and/or distribute this software for         │
+│ any purpose with or without fee is hereby granted, provided that the         │
+│ above copyright notice and this permission notice appear in all copies.      │
+│                                                                              │
+│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL                │
+│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │
+│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │
+│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │
+│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │
+│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │
+│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │
+│ PERFORMANCE OF THIS SOFTWARE.                                                │
+╚─────────────────────────────────────────────────────────────────────────────*/
+#include "libc/assert.h"
+#include "libc/calls/calls.h"
+#include "libc/errno.h"
+#include "libc/stdio/stdio.h"
+#include "libc/sysv/errfuns.h"
+
+/**
+ * Closes stream created by popen().
+ * @return termination status of subprocess, or -1 w/ ECHILD
+ */
+int pclose(FILE *f) {
+  int ws, pid;
+  pid = f->pid;
+  fclose(f);
+  assert(pid);
+  if (!pid) return 0;
+TryAgain:
+  if (wait4(pid, &ws, 0, 0) != -1) {
+    return ws;
+  } else if (errno == EINTR) {
+    goto TryAgain;
+  } else {
+    return echild();
+  }
+}
diff --git a/stdio/popen.c b/stdio/popen.c
new file mode 100644
index 0000000..50abc39
--- /dev/null
+++ b/stdio/popen.c
@@ -0,0 +1,57 @@
+/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
+│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8                                :vi│
+╞══════════════════════════════════════════════════════════════════════════════╡
+│ Copyright 2021 Justine Alexandra Roberts Tunney                              │
+│                                                                              │
+│ Permission to use, copy, modify, and/or distribute this software for         │
+│ any purpose with or without fee is hereby granted, provided that the         │
+│ above copyright notice and this permission notice appear in all copies.      │
+│                                                                              │
+│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL                │
+│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │
+│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │
+│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │
+│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │
+│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │
+│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │
+│ PERFORMANCE OF THIS SOFTWARE.                                                │
+╚─────────────────────────────────────────────────────────────────────────────*/
+#include "libc/calls/calls.h"
+#include "libc/errno.h"
+#include "libc/paths.h"
+#include "libc/runtime/runtime.h"
+#include "libc/stdio/internal.h"
+#include "libc/stdio/stdio.h"
+#include "libc/sysv/consts/f.h"
+#include "libc/sysv/consts/fd.h"
+#include "libc/sysv/consts/o.h"
+#include "libc/sysv/errfuns.h"
+
+/**
+ * Spawns subprocess and returns pipe stream.
+ * @see pclose()
+ */
+FILE *popen(const char *cmdline, const char *mode) {
+  FILE *f;
+  int dir, flags, pipefds[2];
+  flags = fopenflags(mode);
+  if ((flags & O_ACCMODE) == O_RDONLY) {
+    dir = 0;
+  } else if ((flags & O_ACCMODE) == O_WRONLY) {
+    dir = 1;
+  } else {
+    errno = EINVAL;
+    return NULL;
+  }
+  if (pipe(pipefds) == -1) return NULL;
+  fcntl(pipefds[dir], F_SETFD, FD_CLOEXEC);
+  if (!(f = fdopen(pipefds[dir], mode))) abort();
+  if ((f->pid = vfork()) == -1) abort();
+  if (!f->pid) {
+    dup2(pipefds[!dir], !dir);
+    systemexec(cmdline);
+    _exit(127);
+  }
+  close(pipefds[!dir]);
+  return f;
+}
diff --git a/stdio/printf.c b/stdio/printf.c
new file mode 100644
index 0000000..8c64c6d
--- /dev/null
+++ b/stdio/printf.c
@@ -0,0 +1,71 @@
+/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
+│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8                                :vi│
+╞══════════════════════════════════════════════════════════════════════════════╡
+│ Copyright 2020 Justine Alexandra Roberts Tunney                              │
+│                                                                              │
+│ Permission to use, copy, modify, and/or distribute this software for         │
+│ any purpose with or without fee is hereby granted, provided that the         │
+│ above copyright notice and this permission notice appear in all copies.      │
+│                                                                              │
+│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL                │
+│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │
+│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │
+│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │
+│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │
+│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │
+│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │
+│ PERFORMANCE OF THIS SOFTWARE.                                                │
+╚─────────────────────────────────────────────────────────────────────────────*/
+#include "libc/stdio/stdio.h"
+
+/**
+ * Formats and writes string to stdout.
+ *
+ * Cosmopolitan supports most of the standard formatting behaviors
+ * described by `man 3 printf`, in addition to the following:
+ *
+ * - `%jd`, `%jx`, etc. are {,u}intmax_t which in Cosmopolitan is 128-bit.
+ *
+ * - `%'d` or `%,d` may be used to insert thousands separators. The prior is
+ *   consistent with C; the latter is consistent with Python.
+ *
+ * - `%m` inserts strerror(errno) into the formatted output. This is
+ *   consistent with glibc, musl, and uclibc.
+ *
+ * - `%n` inserts "\n" on non-Windows and "\r\n" on Windows. This is the
+ *   same behavior as Java. It's incompatible with glibc's behavior,
+ *   since that's problematic according to Android's security team.
+ *
+ * - `%hs` converts UTF-16/UCS-2 → UTF-8, which can be helpful on Windows.
+ *   Formatting (e.g. %-10hs) will use monospace display width rather
+ *   than string length or codepoint count.
+ *
+ * - `%ls` (or `%Ls`) converts UTF-32 → UTF-8. Formatting (e.g. %-10ls)
+ *   will use monospace display width rather than string length.
+ *
+ * - The `%#s` and `%#c` alternate forms display values using the
+ *   standard IBM standard 256-letter alphabet. Using `%#.*s` to specify
+ *   length will allow true binary (i.e. with NULs) to be formatted.
+ *
+ * - The `%'s` and `%'c` alternate forms are Cosmopolitan extensions for
+ *   escaping string literals for C/C++ and Python. The outer quotation
+ *   marks can be added automatically using ``%`s``. If constexpr format
+ *   strings are used, we can avoid linking cescapec() too.
+ *
+ * - The backtick modifier (``%`s`` and ``%`c``) and repr() directive
+ *   (`%r`) both ask the formatting machine to represent values as real
+ *   code rather than using arbitrary traditions for displaying values.
+ *   This means it implies the quoting modifier, wraps the value with
+ *   {,u,L}['"] quotes, displays NULL as "NULL" rather than "(null)".
+ *
+ * @see __fmt() for intuitive reference documentation
+ * @see {,v}{,s{,n},{,{,x}as},f,d}printf
+ */
+int(printf)(const char* fmt, ...) {
+  int rc;
+  va_list va;
+  va_start(va, fmt);
+  rc = (vfprintf)(stdout, fmt, va);
+  va_end(va);
+  return rc;
+}
diff --git a/stdio/putc.c b/stdio/putc.c
new file mode 100644
index 0000000..559519a
--- /dev/null
+++ b/stdio/putc.c
@@ -0,0 +1,29 @@
+/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
+│vi: set net ft=c ts=8 sts=2 sw=2 fenc=utf-8                                :vi│
+╞══════════════════════════════════════════════════════════════════════════════╡
+│ Copyright 2020 Justine Alexandra Roberts Tunney                              │
+│                                                                              │
+│ Permission to use, copy, modify, and/or distribute this software for         │
+│ any purpose with or without fee is hereby granted, provided that the         │
+│ above copyright notice and this permission notice appear in all copies.      │
+│                                                                              │
+│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL                │
+│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │
+│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │
+│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │
+│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │
+│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │
+│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │
+│ PERFORMANCE OF THIS SOFTWARE.                                                │
+╚─────────────────────────────────────────────────────────────────────────────*/
+#include "libc/stdio/stdio.h"
+
+/**
+ * Writes byte to stream.
+ *
+ * @param c is byte to buffer or write, which is masked
+ * @return c as unsigned char if written or -1 w/ errno
+ */
+int(putc)(int c, FILE *f) {
+  return fputc(c, f);
+}
diff --git a/stdio/putchar.c b/stdio/putchar.c
new file mode 100644
index 0000000..55b7c3c
--- /dev/null
+++ b/stdio/putchar.c
@@ -0,0 +1,26 @@
+/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
+│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8                                :vi│
+╞══════════════════════════════════════════════════════════════════════════════╡
+│ Copyright 2020 Justine Alexandra Roberts Tunney                              │
+│                                                                              │
+│ Permission to use, copy, modify, and/or distribute this software for         │
+│ any purpose with or without fee is hereby granted, provided that the         │
+│ above copyright notice and this permission notice appear in all copies.      │
+│                                                                              │
+│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL                │
+│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │
+│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │
+│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │
+│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │
+│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │
+│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │
+│ PERFORMANCE OF THIS SOFTWARE.                                                │
+╚─────────────────────────────────────────────────────────────────────────────*/
+#include "libc/stdio/stdio.h"
+
+/**
+ * Writes byte to stdout.
+ *
+ * @return c (as unsigned char) if written or -1 w/ errno
+ */
+int putchar(int c) { return fputc(c, stdout); }
diff --git a/stdio/puts.c b/stdio/puts.c
new file mode 100644
index 0000000..044420e
--- /dev/null
+++ b/stdio/puts.c
@@ -0,0 +1,38 @@
+/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
+│vi: set net ft=c ts=8 sts=2 sw=2 fenc=utf-8                                :vi│
+╞══════════════════════════════════════════════════════════════════════════════╡
+│ Copyright 2020 Justine Alexandra Roberts Tunney                              │
+│                                                                              │
+│ Permission to use, copy, modify, and/or distribute this software for         │
+│ any purpose with or without fee is hereby granted, provided that the         │
+│ above copyright notice and this permission notice appear in all copies.      │
+│                                                                              │
+│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL                │
+│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │
+│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │
+│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │
+│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │
+│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │
+│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │
+│ PERFORMANCE OF THIS SOFTWARE.                                                │
+╚─────────────────────────────────────────────────────────────────────────────*/
+#include "libc/stdio/stdio.h"
+
+/**
+ * Writes string w/ trailing newline to stdout.
+ */
+int puts(const char *s) {
+  FILE *f;
+  size_t n, r;
+  f = stdout;
+  if ((n = strlen(s))) {
+    r = fwrite(s, 1, n, f);
+    if (!r) return -1;
+    if (r < n) return r;
+  }
+  if (fputc('\n', f) == -1) {
+    if (feof(f)) return n;
+    return -1;
+  }
+  return n + 1;
+}
diff --git a/stdio/putwc.c b/stdio/putwc.c
new file mode 100644
index 0000000..fad85ca
--- /dev/null
+++ b/stdio/putwc.c
@@ -0,0 +1,28 @@
+/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
+│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8                                :vi│
+╞══════════════════════════════════════════════════════════════════════════════╡
+│ Copyright 2020 Justine Alexandra Roberts Tunney                              │
+│                                                                              │
+│ Permission to use, copy, modify, and/or distribute this software for         │
+│ any purpose with or without fee is hereby granted, provided that the         │
+│ above copyright notice and this permission notice appear in all copies.      │
+│                                                                              │
+│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL                │
+│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │
+│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │
+│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │
+│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │
+│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │
+│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │
+│ PERFORMANCE OF THIS SOFTWARE.                                                │
+╚─────────────────────────────────────────────────────────────────────────────*/
+#include "libc/stdio/stdio.h"
+
+/**
+ * Writes wide character to stream.
+ *
+ * @return wc if written or -1 w/ errno
+ */
+wint_t(putwc)(wchar_t wc, FILE *f) {
+  return fputwc(wc, f);
+}
diff --git a/stdio/putwchar.c b/stdio/putwchar.c
new file mode 100644
index 0000000..8fe5cf0
--- /dev/null
+++ b/stdio/putwchar.c
@@ -0,0 +1,27 @@
+/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
+│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8                                :vi│
+╞══════════════════════════════════════════════════════════════════════════════╡
+│ Copyright 2020 Justine Alexandra Roberts Tunney                              │
+│                                                                              │
+│ Permission to use, copy, modify, and/or distribute this software for         │
+│ any purpose with or without fee is hereby granted, provided that the         │
+│ above copyright notice and this permission notice appear in all copies.      │
+│                                                                              │
+│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL                │
+│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │
+│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │
+│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │
+│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │
+│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │
+│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │
+│ PERFORMANCE OF THIS SOFTWARE.                                                │
+╚─────────────────────────────────────────────────────────────────────────────*/
+#include "libc/stdio/stdio.h"
+
+/**
+ * Writes wide character to stdout.
+ * @return wc if written or -1 w/ errno
+ */
+wint_t putwchar(wchar_t wc) {
+  return fputwc(wc, stdout);
+}
diff --git a/stdio/rewind.c b/stdio/rewind.c
new file mode 100644
index 0000000..03aa3f5
--- /dev/null
+++ b/stdio/rewind.c
@@ -0,0 +1,31 @@
+/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
+│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8                                :vi│
+╞══════════════════════════════════════════════════════════════════════════════╡
+│ Copyright 2020 Justine Alexandra Roberts Tunney                              │
+│                                                                              │
+│ Permission to use, copy, modify, and/or distribute this software for         │
+│ any purpose with or without fee is hereby granted, provided that the         │
+│ above copyright notice and this permission notice appear in all copies.      │
+│                                                                              │
+│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL                │
+│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │
+│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │
+│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │
+│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │
+│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │
+│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │
+│ PERFORMANCE OF THIS SOFTWARE.                                                │
+╚─────────────────────────────────────────────────────────────────────────────*/
+#include "libc/calls/calls.h"
+#include "libc/stdio/stdio.h"
+
+/**
+ * Moves standard i/o stream to beginning of file.
+ *
+ * Like fseek(), this function can be used to restore a stream from the
+ * EOF state, without reopening it.
+ */
+void rewind(FILE *f) {
+  fseek(f, 0, SEEK_SET);
+  f->state = 0;
+}
diff --git a/stdio/scanf.c b/stdio/scanf.c
new file mode 100644
index 0000000..e2b19b2
--- /dev/null
+++ b/stdio/scanf.c
@@ -0,0 +1,33 @@
+/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
+│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8                                :vi│
+╞══════════════════════════════════════════════════════════════════════════════╡
+│ Copyright 2020 Justine Alexandra Roberts Tunney                              │
+│                                                                              │
+│ Permission to use, copy, modify, and/or distribute this software for         │
+│ any purpose with or without fee is hereby granted, provided that the         │
+│ above copyright notice and this permission notice appear in all copies.      │
+│                                                                              │
+│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL                │
+│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │
+│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │
+│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │
+│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │
+│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │
+│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │
+│ PERFORMANCE OF THIS SOFTWARE.                                                │
+╚─────────────────────────────────────────────────────────────────────────────*/
+#include "libc/fmt/fmt.h"
+#include "libc/stdio/stdio.h"
+
+/**
+ * Standard input decoder.
+ * @see libc/fmt/vcscanf.h
+ */
+int(scanf)(const char *fmt, ...) {
+  int rc;
+  va_list va;
+  va_start(va, fmt);
+  rc = (vcscanf)((int (*)(void *))fgetc, NULL, stdin, fmt, va);
+  va_end(va);
+  return rc;
+}
diff --git a/stdio/setbuf.c b/stdio/setbuf.c
new file mode 100644
index 0000000..4396f15
--- /dev/null
+++ b/stdio/setbuf.c
@@ -0,0 +1,27 @@
+/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
+│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8                                :vi│
+╞══════════════════════════════════════════════════════════════════════════════╡
+│ Copyright 2020 Justine Alexandra Roberts Tunney                              │
+│                                                                              │
+│ Permission to use, copy, modify, and/or distribute this software for         │
+│ any purpose with or without fee is hereby granted, provided that the         │
+│ above copyright notice and this permission notice appear in all copies.      │
+│                                                                              │
+│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL                │
+│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │
+│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │
+│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │
+│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │
+│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │
+│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │
+│ PERFORMANCE OF THIS SOFTWARE.                                                │
+╚─────────────────────────────────────────────────────────────────────────────*/
+#include "libc/calls/calls.h"
+#include "libc/stdio/stdio.h"
+
+/**
+ * Sets buffer on stdio stream.
+ */
+void setbuf(FILE *f, char *buf) {
+  setvbuf(f, buf, buf ? _IOFBF : _IONBF, BUFSIZ);
+}
diff --git a/stdio/setbuffer.c b/stdio/setbuffer.c
new file mode 100644
index 0000000..94220dc
--- /dev/null
+++ b/stdio/setbuffer.c
@@ -0,0 +1,33 @@
+/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
+│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8                                :vi│
+╞══════════════════════════════════════════════════════════════════════════════╡
+│ Copyright 2020 Justine Alexandra Roberts Tunney                              │
+│                                                                              │
+│ Permission to use, copy, modify, and/or distribute this software for         │
+│ any purpose with or without fee is hereby granted, provided that the         │
+│ above copyright notice and this permission notice appear in all copies.      │
+│                                                                              │
+│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL                │
+│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │
+│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │
+│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │
+│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │
+│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │
+│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │
+│ PERFORMANCE OF THIS SOFTWARE.                                                │
+╚─────────────────────────────────────────────────────────────────────────────*/
+#include "libc/calls/calls.h"
+#include "libc/runtime/runtime.h"
+#include "libc/stdio/stdio.h"
+#include "libc/sysv/errfuns.h"
+
+/**
+ * Sets buffer on stdio stream.
+ *
+ * @param buf may optionally be non-NULL to set the stream's underlying
+ *     buffer, which the stream will own, but won't free
+ * @param size is ignored if buf is NULL
+ */
+void setbuffer(FILE *f, char *buf, size_t size) {
+  setvbuf(f, buf, buf ? _IOFBF : _IONBF, size);
+}
diff --git a/stdio/setlinebuf.c b/stdio/setlinebuf.c
new file mode 100644
index 0000000..fa6bc64
--- /dev/null
+++ b/stdio/setlinebuf.c
@@ -0,0 +1,27 @@
+/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
+│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8                                :vi│
+╞══════════════════════════════════════════════════════════════════════════════╡
+│ Copyright 2021 Justine Alexandra Roberts Tunney                              │
+│                                                                              │
+│ Permission to use, copy, modify, and/or distribute this software for         │
+│ any purpose with or without fee is hereby granted, provided that the         │
+│ above copyright notice and this permission notice appear in all copies.      │
+│                                                                              │
+│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL                │
+│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │
+│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │
+│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │
+│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │
+│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │
+│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │
+│ PERFORMANCE OF THIS SOFTWARE.                                                │
+╚─────────────────────────────────────────────────────────────────────────────*/
+#include "libc/calls/calls.h"
+#include "libc/stdio/stdio.h"
+
+/**
+ * Puts stream in line-buffering mode.
+ */
+void setlinebuf(FILE *f) {
+  setvbuf(f, NULL, _IOLBF, 0);
+}
diff --git a/stdio/setvbuf.c b/stdio/setvbuf.c
new file mode 100644
index 0000000..4149bdd
--- /dev/null
+++ b/stdio/setvbuf.c
@@ -0,0 +1,42 @@
+/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
+│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8                                :vi│
+╞══════════════════════════════════════════════════════════════════════════════╡
+│ Copyright 2020 Justine Alexandra Roberts Tunney                              │
+│                                                                              │
+│ Permission to use, copy, modify, and/or distribute this software for         │
+│ any purpose with or without fee is hereby granted, provided that the         │
+│ above copyright notice and this permission notice appear in all copies.      │
+│                                                                              │
+│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL                │
+│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │
+│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │
+│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │
+│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │
+│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │
+│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │
+│ PERFORMANCE OF THIS SOFTWARE.                                                │
+╚─────────────────────────────────────────────────────────────────────────────*/
+#include "libc/stdio/stdio.h"
+#include "libc/sysv/errfuns.h"
+
+/**
+ * Tunes buffering settings for an stdio stream.
+ *
+ * @param mode may be _IOFBF, _IOLBF, or _IONBF
+ * @param buf may optionally be non-NULL to set the stream's underlying
+ *     buffer, which the stream will own, but won't free, otherwise the
+ *     existing buffer is used
+ * @param size is ignored if buf is NULL
+ * @return 0 on success or -1 on error
+ */
+int setvbuf(FILE *f, char *buf, int mode, size_t size) {
+  if (buf) {
+    if (!size) size = BUFSIZ;
+    if (!f->nofree && f->buf != buf) free_s(&f->buf);
+    f->buf = buf;
+    f->size = size;
+    f->nofree = true;
+  }
+  f->bufmode = mode;
+  return 0;
+}
diff --git a/stdio/spawn.c b/stdio/spawn.c
new file mode 100644
index 0000000..5dc3980
--- /dev/null
+++ b/stdio/spawn.c
@@ -0,0 +1,115 @@
+/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
+│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8                                :vi│
+╞══════════════════════════════════════════════════════════════════════════════╡
+│ Copyright 2021 Justine Alexandra Roberts Tunney                              │
+│                                                                              │
+│ Permission to use, copy, modify, and/or distribute this software for         │
+│ any purpose with or without fee is hereby granted, provided that the         │
+│ above copyright notice and this permission notice appear in all copies.      │
+│                                                                              │
+│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL                │
+│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │
+│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │
+│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │
+│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │
+│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │
+│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │
+│ PERFORMANCE OF THIS SOFTWARE.                                                │
+╚─────────────────────────────────────────────────────────────────────────────*/
+#include "libc/calls/calls.h"
+#include "libc/calls/scheduler.h"
+#include "libc/calls/sigbits.h"
+#include "libc/calls/struct/sigaction.h"
+#include "libc/errno.h"
+#include "libc/fmt/fmt.h"
+#include "libc/stdio/spawn.h"
+#include "libc/stdio/spawna.internal.h"
+#include "libc/str/str.h"
+
+/**
+ * Spawns process the POSIX way.
+ *
+ * @param pid is non-NULL and will be set to child pid in parent
+ * @param path of executable that is not PATH searched
+ * @return 0 on success or error number on failure
+ */
+int posix_spawn(int *pid, const char *path,
+                const posix_spawn_file_actions_t *file_actions,
+                const posix_spawnattr_t *attrp, char *const argv[],
+                char *const envp[]) {
+  unsigned mode;
+  sigset_t allsigs;
+  struct sigaction dfl;
+  char *p, *q, opath[PATH_MAX];
+  int s, fd, newfd, oflag, tempfd;
+  if (!(*pid = vfork())) {
+    if (attrp) {
+      if (attrp->posix_attr_flags & POSIX_SPAWN_SETPGROUP) {
+        if (setpgid(0, attrp->posix_attr_pgroup)) _exit(127);
+      }
+      if (attrp->posix_attr_flags & POSIX_SPAWN_SETSIGMASK) {
+        sigprocmask(SIG_SETMASK, &attrp->posix_attr_sigmask, NULL);
+      }
+      if (attrp->posix_attr_flags & POSIX_SPAWN_RESETIDS) {
+        setuid(getuid());
+        setgid(getgid());
+      }
+      if (attrp->posix_attr_flags & POSIX_SPAWN_SETSIGDEF) {
+        dfl.sa_handler = SIG_DFL;
+        dfl.sa_flags = 0;
+        sigfillset(&allsigs);
+        for (s = 0; sigismember(&allsigs, s); s++) {
+          if (sigismember(&attrp->posix_attr_sigdefault, s)) {
+            if (sigaction(s, &dfl, NULL) == -1) _exit(127);
+          }
+        }
+      }
+    }
+    if (file_actions) {
+      for (p = *file_actions; *p; p = strchr(p, ')') + 1) {
+        if (!strncmp(p, "close(", 6)) {
+          if (sscanf(p + 6, "%d)", &fd) != 1) _exit(127);
+          if (close(fd) == -1) _exit(127);
+        } else if (!strncmp(p, "dup2(", 5)) {
+          if (sscanf(p + 5, "%d,%d)", &fd, &newfd) != 2) _exit(127);
+          if (dup2(fd, newfd) == -1) _exit(127);
+        } else if (!strncmp(p, "open(", 5)) {
+          if (sscanf(p + 5, "%d,", &fd) != 1) _exit(127);
+          p = strchr(p, ',') + 1;
+          q = strchr(p, '*');
+          if (!q || q - p + 1 > PATH_MAX) _exit(127);
+          strncpy(opath, p, q - p);
+          opath[q - p] = '\0';
+          if (sscanf(q + 1, "%o,%o)", &oflag, &mode) != 2) _exit(127);
+          if (close(fd) == -1 && errno != EBADF) _exit(127);
+          tempfd = open(opath, oflag, mode);
+          if (tempfd == -1) _exit(127);
+          if (tempfd != fd) {
+            if (dup2(tempfd, fd) == -1) _exit(127);
+            if (close(tempfd) == -1) _exit(127);
+          }
+        } else {
+          _exit(127);
+        }
+      }
+    }
+    if (attrp) {
+      if (attrp->posix_attr_flags & POSIX_SPAWN_SETSCHEDULER) {
+        if (sched_setscheduler(0, attrp->posix_attr_schedpolicy,
+                               &attrp->posix_attr_schedparam) == -1) {
+          _exit(127);
+        }
+      }
+      if (attrp->posix_attr_flags & POSIX_SPAWN_SETSCHEDPARAM) {
+        if (sched_setparam(0, &attrp->posix_attr_schedparam) == -1) {
+          _exit(127);
+        }
+      }
+    }
+    execve(path, argv, envp);
+    _exit(127);
+  } else {
+    if (*pid == -1) return errno;
+    return 0;
+  }
+}
diff --git a/stdio/spawn.h b/stdio/spawn.h
new file mode 100644
index 0000000..7fe335c
--- /dev/null
+++ b/stdio/spawn.h
@@ -0,0 +1,50 @@
+#ifndef COSMOPOLITAN_LIBC_STDIO_SPAWN_H_
+#define COSMOPOLITAN_LIBC_STDIO_SPAWN_H_
+#include "libc/calls/struct/sched_param.h"
+#include "libc/calls/struct/sigset.h"
+
+#define POSIX_SPAWN_RESETIDS      0x01
+#define POSIX_SPAWN_SETPGROUP     0x02
+#define POSIX_SPAWN_SETSIGDEF     0x04
+#define POSIX_SPAWN_SETSIGMASK    0x08
+#define POSIX_SPAWN_SETSCHEDPARAM 0x10
+#define POSIX_SPAWN_SETSCHEDULER  0x20
+
+#if !(__ASSEMBLER__ + __LINKER__ + 0)
+COSMOPOLITAN_C_START_
+
+typedef char *posix_spawn_file_actions_t;
+typedef struct _posix_spawnattr posix_spawnattr_t;
+
+int posix_spawn(int *, const char *, const posix_spawn_file_actions_t *,
+                const posix_spawnattr_t *, char *const[], char *const[]);
+int posix_spawnp(int *, const char *, const posix_spawn_file_actions_t *,
+                 const posix_spawnattr_t *, char *const[], char *const[]);
+
+int posix_spawn_file_actions_init(posix_spawn_file_actions_t *);
+int posix_spawn_file_actions_destroy(posix_spawn_file_actions_t *);
+int posix_spawn_file_actions_addclose(posix_spawn_file_actions_t *, int);
+int posix_spawn_file_actions_adddup2(posix_spawn_file_actions_t *, int, int);
+int posix_spawn_file_actions_addopen(posix_spawn_file_actions_t *, int,
+                                     const char *, int, unsigned);
+
+int posix_spawnattr_init(posix_spawnattr_t *);
+int posix_spawnattr_destroy(posix_spawnattr_t *);
+int posix_spawnattr_getflags(const posix_spawnattr_t *, short *);
+int posix_spawnattr_setflags(posix_spawnattr_t *, short);
+int posix_spawnattr_getpgroup(const posix_spawnattr_t *, int *);
+int posix_spawnattr_setpgroup(posix_spawnattr_t *, int);
+int posix_spawnattr_getschedpolicy(const posix_spawnattr_t *, int *);
+int posix_spawnattr_setschedpolicy(posix_spawnattr_t *, int);
+int posix_spawnattr_getschedparam(const posix_spawnattr_t *,
+                                  struct sched_param *);
+int posix_spawnattr_setschedparam(posix_spawnattr_t *,
+                                  const struct sched_param *);
+int posix_spawnattr_getsigmask(const posix_spawnattr_t *, sigset_t *);
+int posix_spawnattr_setsigmask(posix_spawnattr_t *, const sigset_t *);
+int posix_spawnattr_getdefault(const posix_spawnattr_t *, sigset_t *);
+int posix_spawnattr_setsigdefault(posix_spawnattr_t *, const sigset_t *);
+
+COSMOPOLITAN_C_END_
+#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
+#endif /* COSMOPOLITAN_LIBC_STDIO_SPAWN_H_ */
diff --git a/stdio/spawna.c b/stdio/spawna.c
new file mode 100644
index 0000000..125738e
--- /dev/null
+++ b/stdio/spawna.c
@@ -0,0 +1,107 @@
+/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
+│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8                                :vi│
+╞══════════════════════════════════════════════════════════════════════════════╡
+│ Copyright 2021 Justine Alexandra Roberts Tunney                              │
+│                                                                              │
+│ Permission to use, copy, modify, and/or distribute this software for         │
+│ any purpose with or without fee is hereby granted, provided that the         │
+│ above copyright notice and this permission notice appear in all copies.      │
+│                                                                              │
+│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL                │
+│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │
+│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │
+│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │
+│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │
+│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │
+│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │
+│ PERFORMANCE OF THIS SOFTWARE.                                                │
+╚─────────────────────────────────────────────────────────────────────────────*/
+#include "libc/calls/calls.h"
+#include "libc/calls/scheduler.h"
+#include "libc/calls/sigbits.h"
+#include "libc/stdio/spawn.h"
+#include "libc/stdio/spawna.internal.h"
+
+/**
+ * Initialize object with default values.
+ */
+int posix_spawnattr_init(posix_spawnattr_t *attr) {
+  attr->posix_attr_flags = 0;
+  attr->posix_attr_pgroup = 0;
+  sigprocmask(0, NULL, &attr->posix_attr_sigmask);
+  sigemptyset(&attr->posix_attr_sigdefault);
+  attr->posix_attr_schedpolicy = sched_getscheduler(0);
+  sched_getparam(0, &attr->posix_attr_schedparam);
+  return 0;
+}
+
+int posix_spawnattr_destroy(posix_spawnattr_t *attr) {
+  return 0;
+}
+
+int posix_spawnattr_getflags(const posix_spawnattr_t *attr, short *flags) {
+  *flags = attr->posix_attr_flags;
+  return 0;
+}
+
+int posix_spawnattr_setflags(posix_spawnattr_t *attr, short flags) {
+  attr->posix_attr_flags = flags;
+  return 0;
+}
+
+int posix_spawnattr_getpgroup(const posix_spawnattr_t *attr, int *pgroup) {
+  *pgroup = attr->posix_attr_pgroup;
+  return 0;
+}
+
+int posix_spawnattr_setpgroup(posix_spawnattr_t *attr, int pgroup) {
+  attr->posix_attr_pgroup = pgroup;
+  return 0;
+}
+
+int posix_spawnattr_getschedpolicy(const posix_spawnattr_t *attr,
+                                   int *schedpolicy) {
+  *schedpolicy = attr->posix_attr_schedpolicy;
+  return 0;
+}
+
+int posix_spawnattr_setschedpolicy(posix_spawnattr_t *attr, int schedpolicy) {
+  attr->posix_attr_schedpolicy = schedpolicy;
+  return 0;
+}
+
+int posix_spawnattr_getschedparam(const posix_spawnattr_t *attr,
+                                  struct sched_param *schedparam) {
+  *schedparam = attr->posix_attr_schedparam;
+  return 0;
+}
+
+int posix_spawnattr_setschedparam(posix_spawnattr_t *attr,
+                                  const struct sched_param *schedparam) {
+  attr->posix_attr_schedparam = *schedparam;
+  return 0;
+}
+
+int posix_spawnattr_getsigmask(const posix_spawnattr_t *attr,
+                               sigset_t *sigmask) {
+  *sigmask = attr->posix_attr_sigmask;
+  return 0;
+}
+
+int posix_spawnattr_setsigmask(posix_spawnattr_t *attr,
+                               const sigset_t *sigmask) {
+  attr->posix_attr_sigmask = *sigmask;
+  return 0;
+}
+
+int posix_spawnattr_getsigdefault(const posix_spawnattr_t *attr,
+                                  sigset_t *sigdefault) {
+  *sigdefault = attr->posix_attr_sigdefault;
+  return 0;
+}
+
+int posix_spawnattr_setsigdefault(posix_spawnattr_t *attr,
+                                  const sigset_t *sigdefault) {
+  attr->posix_attr_sigdefault = *sigdefault;
+  return 0;
+}
diff --git a/stdio/spawna.internal.h b/stdio/spawna.internal.h
new file mode 100644
index 0000000..2635aca
--- /dev/null
+++ b/stdio/spawna.internal.h
@@ -0,0 +1,19 @@
+#ifndef COSMOPOLITAN_LIBC_STDIO_SPAWNA_INTERNAL_H_
+#define COSMOPOLITAN_LIBC_STDIO_SPAWNA_INTERNAL_H_
+#include "libc/calls/struct/sched_param.h"
+#include "libc/calls/struct/sigset.h"
+#if !(__ASSEMBLER__ + __LINKER__ + 0)
+COSMOPOLITAN_C_START_
+
+struct _posix_spawnattr {
+  int16_t posix_attr_flags;
+  int32_t posix_attr_pgroup;
+  sigset_t posix_attr_sigmask;
+  sigset_t posix_attr_sigdefault;
+  int32_t posix_attr_schedpolicy;
+  struct sched_param posix_attr_schedparam;
+};
+
+COSMOPOLITAN_C_END_
+#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
+#endif /* COSMOPOLITAN_LIBC_STDIO_SPAWNA_INTERNAL_H_ */
diff --git a/stdio/spawnf.c b/stdio/spawnf.c
new file mode 100644
index 0000000..3e893b1
--- /dev/null
+++ b/stdio/spawnf.c
@@ -0,0 +1,85 @@
+/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
+│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8                                :vi│
+╞══════════════════════════════════════════════════════════════════════════════╡
+│ Copyright 2021 Justine Alexandra Roberts Tunney                              │
+│                                                                              │
+│ Permission to use, copy, modify, and/or distribute this software for         │
+│ any purpose with or without fee is hereby granted, provided that the         │
+│ above copyright notice and this permission notice appear in all copies.      │
+│                                                                              │
+│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL                │
+│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │
+│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │
+│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │
+│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │
+│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │
+│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │
+│ PERFORMANCE OF THIS SOFTWARE.                                                │
+╚─────────────────────────────────────────────────────────────────────────────*/
+#include "libc/errno.h"
+#include "libc/fmt/fmt.h"
+#include "libc/mem/mem.h"
+#include "libc/stdio/spawn.h"
+#include "libc/str/str.h"
+
+/**
+ * Creates object with no actions.
+ */
+int posix_spawn_file_actions_init(posix_spawn_file_actions_t *file_actions) {
+  *file_actions = malloc(sizeof(char));
+  if (!*file_actions) return ENOMEM;
+  strcpy(*file_actions, "");
+  return 0;
+}
+
+/**
+ * Frees object storage and make invalid.
+ */
+int posix_spawn_file_actions_destroy(posix_spawn_file_actions_t *file_actions) {
+  free(*file_actions);
+  *file_actions = NULL;
+  return 0;
+}
+
+/**
+ * Adds new action string to object.
+ */
+static int add_to_file_actions(posix_spawn_file_actions_t *file_actions,
+                               char *new_action) {
+  *file_actions =
+      realloc(*file_actions, strlen(*file_actions) + strlen(new_action) + 1);
+  if (!*file_actions) return ENOMEM;
+  strcat(*file_actions, new_action);
+  return 0;
+}
+
+/**
+ * Add a close action to object.
+ */
+int posix_spawn_file_actions_addclose(posix_spawn_file_actions_t *file_actions,
+                                      int fildes) {
+  char temp[100];
+  sprintf(temp, "close(%d)", fildes);
+  return add_to_file_actions(file_actions, temp);
+}
+
+/**
+ * Add a dup2 action to object.
+ */
+int posix_spawn_file_actions_adddup2(posix_spawn_file_actions_t *file_actions,
+                                     int fildes, int newfildes) {
+  char temp[100];
+  sprintf(temp, "dup2(%d,%d)", fildes, newfildes);
+  return add_to_file_actions(file_actions, temp);
+}
+
+/**
+ * Add an open action to object.
+ */
+int posix_spawn_file_actions_addopen(posix_spawn_file_actions_t *file_actions,
+                                     int fildes, const char *path, int oflag,
+                                     unsigned mode) {
+  char temp[100];
+  sprintf(temp, "open(%d,%s*%o,%o)", fildes, path, oflag, mode);
+  return add_to_file_actions(file_actions, temp);
+}
diff --git a/stdio/spawnp.c b/stdio/spawnp.c
new file mode 100644
index 0000000..2191b3c
--- /dev/null
+++ b/stdio/spawnp.c
@@ -0,0 +1,37 @@
+/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
+│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8                                :vi│
+╞══════════════════════════════════════════════════════════════════════════════╡
+│ Copyright 2021 Justine Alexandra Roberts Tunney                              │
+│                                                                              │
+│ Permission to use, copy, modify, and/or distribute this software for         │
+│ any purpose with or without fee is hereby granted, provided that the         │
+│ above copyright notice and this permission notice appear in all copies.      │
+│                                                                              │
+│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL                │
+│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │
+│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │
+│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │
+│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │
+│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │
+│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │
+│ PERFORMANCE OF THIS SOFTWARE.                                                │
+╚─────────────────────────────────────────────────────────────────────────────*/
+#include "libc/calls/calls.h"
+#include "libc/errno.h"
+#include "libc/stdio/spawn.h"
+
+/**
+ * Spawns process the POSIX way w/ PATH search.
+ *
+ * @param pid is non-NULL and will be set to child pid in parent
+ * @param path of executable is PATH searched unless it contains a slash
+ * @return 0 on success or error number on failure
+ */
+int posix_spawnp(int *pid, const char *path,
+                 const posix_spawn_file_actions_t *file_actions,
+                 const posix_spawnattr_t *attrp, char *const argv[],
+                 char *const envp[]) {
+  char pathbuf[PATH_MAX];
+  if (!(path = commandv(path, pathbuf))) return errno;
+  return posix_spawn(pid, path, file_actions, attrp, argv, envp);
+}
diff --git a/stdio/stdbuf.c b/stdio/stdbuf.c
new file mode 100644
index 0000000..67d68cf
--- /dev/null
+++ b/stdio/stdbuf.c
@@ -0,0 +1,22 @@
+/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
+│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8                                :vi│
+╞══════════════════════════════════════════════════════════════════════════════╡
+│ Copyright 2020 Justine Alexandra Roberts Tunney                              │
+│                                                                              │
+│ Permission to use, copy, modify, and/or distribute this software for         │
+│ any purpose with or without fee is hereby granted, provided that the         │
+│ above copyright notice and this permission notice appear in all copies.      │
+│                                                                              │
+│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL                │
+│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │
+│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │
+│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │
+│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │
+│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │
+│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │
+│ PERFORMANCE OF THIS SOFTWARE.                                                │
+╚─────────────────────────────────────────────────────────────────────────────*/
+#include "libc/stdio/internal.h"
+
+char g_stdoutbuf[BUFSIZ] hidden;
+char g_stderrbuf[BUFSIZ] hidden;
diff --git a/stdio/stderr-init.S b/stdio/stderr-init.S
new file mode 100644
index 0000000..30acd05
--- /dev/null
+++ b/stdio/stderr-init.S
@@ -0,0 +1,38 @@
+/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8     -*-│
+│vi: set et ft=asm ts=8 tw=8 fenc=utf-8                                     :vi│
+╞══════════════════════════════════════════════════════════════════════════════╡
+│ Copyright 2020 Justine Alexandra Roberts Tunney                              │
+│                                                                              │
+│ Permission to use, copy, modify, and/or distribute this software for         │
+│ any purpose with or without fee is hereby granted, provided that the         │
+│ above copyright notice and this permission notice appear in all copies.      │
+│                                                                              │
+│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL                │
+│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │
+│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │
+│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │
+│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │
+│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │
+│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │
+│ PERFORMANCE OF THIS SOFTWARE.                                                │
+╚─────────────────────────────────────────────────────────────────────────────*/
+#include "libc/sysv/consts/o.h"
+#include "libc/dce.h"
+#include "libc/calls/calls.h"
+#include "libc/sysv/consts/fileno.h"
+#include "libc/macros.internal.h"
+.source	__FILE__
+
+	.init.start 400,_init_stderr
+	ezlea	__stderr,ax
+	push	$_IOLBF
+	pop	(%rax)				#→ f.fd
+	push	STDERR_FILENO
+	pop	12(%rax)
+	mov	O_WRONLY,%edx
+	mov	%edx,4(%rax)			#→ f.iomode
+	ezlea	__stderr_buf,cx
+	mov	%rcx,24(%rax)			#→ f.buf
+	movl	$BUFSIZ,32(%rax)		#→ f.size
+	mov	%rax,stderr(%rip)
+	.init.end 400,_init_stderr,globl,hidden
diff --git a/stdio/stderr.c b/stdio/stderr.c
new file mode 100644
index 0000000..9529789
--- /dev/null
+++ b/stdio/stderr.c
@@ -0,0 +1,36 @@
+/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
+│vi: set net ft=c ts=8 sts=2 sw=2 fenc=utf-8                                :vi│
+╞══════════════════════════════════════════════════════════════════════════════╡
+│ Copyright 2020 Justine Alexandra Roberts Tunney                              │
+│                                                                              │
+│ Permission to use, copy, modify, and/or distribute this software for         │
+│ any purpose with or without fee is hereby granted, provided that the         │
+│ above copyright notice and this permission notice appear in all copies.      │
+│                                                                              │
+│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL                │
+│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │
+│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │
+│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │
+│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │
+│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │
+│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │
+│ PERFORMANCE OF THIS SOFTWARE.                                                │
+╚─────────────────────────────────────────────────────────────────────────────*/
+#include "libc/stdio/internal.h"
+#include "libc/stdio/stdio.h"
+
+STATIC_YOINK("_init_stderr");
+
+/**
+ * Pointer to standard error stream.
+ */
+FILE *stderr;
+
+hidden FILE __stderr;
+hidden unsigned char __stderr_buf[BUFSIZ];
+
+static textstartup void __stderr_init() {
+  __fflush_register(stderr);
+}
+
+const void *const __stderr_ctor[] initarray = {__stderr_init};
diff --git a/stdio/stdin-init.S b/stdio/stdin-init.S
new file mode 100644
index 0000000..4609537
--- /dev/null
+++ b/stdio/stdin-init.S
@@ -0,0 +1,34 @@
+/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8     -*-│
+│vi: set et ft=asm ts=8 tw=8 fenc=utf-8                                     :vi│
+╞══════════════════════════════════════════════════════════════════════════════╡
+│ Copyright 2020 Justine Alexandra Roberts Tunney                              │
+│                                                                              │
+│ Permission to use, copy, modify, and/or distribute this software for         │
+│ any purpose with or without fee is hereby granted, provided that the         │
+│ above copyright notice and this permission notice appear in all copies.      │
+│                                                                              │
+│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL                │
+│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │
+│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │
+│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │
+│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │
+│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │
+│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │
+│ PERFORMANCE OF THIS SOFTWARE.                                                │
+╚─────────────────────────────────────────────────────────────────────────────*/
+#include "libc/sysv/consts/o.h"
+#include "libc/dce.h"
+#include "libc/calls/calls.h"
+#include "libc/sysv/consts/fileno.h"
+#include "libc/macros.internal.h"
+.source	__FILE__
+
+	.init.start 400,_init_stdin
+	ezlea	__stdin,ax
+	mov	O_RDONLY,%edx
+	mov	%edx,4(%rax)			#→ f.iomode
+	ezlea	__stdin_buf,cx
+	mov	%rcx,24(%rax)			#→ f.buf
+	movl	$BUFSIZ,32(%rax)		#→ f.size
+	mov	%rax,stdin(%rip)
+	.init.end 400,_init_stdin,globl,hidden
diff --git a/stdio/stdin.c b/stdio/stdin.c
new file mode 100644
index 0000000..716a0b6
--- /dev/null
+++ b/stdio/stdin.c
@@ -0,0 +1,36 @@
+/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
+│vi: set net ft=c ts=8 sts=2 sw=2 fenc=utf-8                                :vi│
+╞══════════════════════════════════════════════════════════════════════════════╡
+│ Copyright 2020 Justine Alexandra Roberts Tunney                              │
+│                                                                              │
+│ Permission to use, copy, modify, and/or distribute this software for         │
+│ any purpose with or without fee is hereby granted, provided that the         │
+│ above copyright notice and this permission notice appear in all copies.      │
+│                                                                              │
+│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL                │
+│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │
+│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │
+│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │
+│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │
+│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │
+│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │
+│ PERFORMANCE OF THIS SOFTWARE.                                                │
+╚─────────────────────────────────────────────────────────────────────────────*/
+#include "libc/stdio/internal.h"
+#include "libc/stdio/stdio.h"
+
+STATIC_YOINK("_init_stdin");
+
+/**
+ * Pointer to standard input stream.
+ */
+FILE *stdin;
+
+hidden FILE __stdin;
+hidden unsigned char __stdin_buf[BUFSIZ];
+
+static textstartup void __stdin_init() {
+  __fflush_register(stdin);
+}
+
+const void *const __stdin_ctor[] initarray = {__stdin_init};
diff --git a/stdio/stdio.h b/stdio/stdio.h
new file mode 100644
index 0000000..268913b
--- /dev/null
+++ b/stdio/stdio.h
@@ -0,0 +1,129 @@
+#ifndef COSMOPOLITAN_LIBC_STDIO_STDIO_H_
+#define COSMOPOLITAN_LIBC_STDIO_STDIO_H_
+#include "libc/fmt/pflink.h"
+#include "libc/runtime/symbolic.h"
+
+#define FILENAME_MAX PATH_MAX
+
+#if !(__ASSEMBLER__ + __LINKER__ + 0)
+COSMOPOLITAN_C_START_
+
+/*───────────────────────────────────────────────────────────────────────────│─╗
+│ cosmopolitan § standard i/o                                              ─╬─│┼
+╚────────────────────────────────────────────────────────────────────────────│*/
+
+typedef struct FILE {
+  uint8_t bufmode; /* 0x00 _IOFBF, etc. (ignored if fd=-1) */
+  bool noclose;    /* 0x01 for fake dup() */
+  uint32_t iomode; /* 0x04 O_RDONLY, etc. (ignored if fd=-1) */
+  int32_t state;   /* 0x08 0=OK, -1=EOF, >0=errno */
+  int fd;          /* 0x0c ≥0=fd, -1=closed|buffer */
+  uint32_t beg;    /* 0x10 */
+  uint32_t end;    /* 0x14 */
+  char *buf;       /* 0x18 */
+  uint32_t size;   /* 0x20 */
+  uint32_t nofree; /* 0x24 */
+  int pid;         /* 0x28 */
+} FILE;
+
+extern FILE *stdin;
+extern FILE *stdout;
+extern FILE *stderr;
+
+errno_t ferror(FILE *) paramsnonnull();
+void clearerr(FILE *) paramsnonnull();
+int feof(FILE *) paramsnonnull();
+int getc(FILE *) paramsnonnull();
+int putc(int, FILE *) paramsnonnull();
+int fflush(FILE *);
+int fgetc(FILE *) paramsnonnull();
+int ungetc(int, FILE *) paramsnonnull();
+int fileno(FILE *) paramsnonnull() nosideeffect;
+int fputc(int, FILE *) paramsnonnull();
+int fputs(const char *, FILE *) paramsnonnull();
+int fputws(const wchar_t *, FILE *) paramsnonnull();
+char *fgets(char *, int, FILE *) paramsnonnull();
+wchar_t *fgetws(wchar_t *, int, FILE *) paramsnonnull();
+wint_t putwc(wchar_t, FILE *) paramsnonnull();
+wint_t fputwc(wchar_t, FILE *) paramsnonnull();
+wint_t putwchar(wchar_t);
+wint_t getwchar(void);
+wint_t getwc(FILE *) paramsnonnull();
+wint_t fgetwc(FILE *) paramsnonnull();
+wint_t ungetwc(wint_t, FILE *) paramsnonnull();
+int getchar(void);
+int putchar(int);
+int puts(const char *) paramsnonnull();
+ssize_t getline(char **, size_t *, FILE *) paramsnonnull();
+ssize_t getdelim(char **, size_t *, int, FILE *) paramsnonnull();
+FILE *fopen(const char *, const char *) paramsnonnull() nodiscard;
+FILE *fdopen(int, const char *) paramsnonnull() nodiscard;
+FILE *fmemopen(void *, size_t, const char *) paramsnonnull((3)) nodiscard;
+FILE *freopen(const char *, const char *, FILE *) paramsnonnull((2, 3));
+size_t fread(void *, size_t, size_t, FILE *) paramsnonnull((4));
+size_t fwrite(const void *, size_t, size_t, FILE *) paramsnonnull((4));
+int fclose(FILE *);
+int fclose_s(FILE **) paramsnonnull();
+int fseek(FILE *, long, int) paramsnonnull();
+long ftell(FILE *) paramsnonnull();
+int fseeko(FILE *, int64_t, int) paramsnonnull();
+int64_t ftello(FILE *) paramsnonnull();
+void rewind(FILE *) paramsnonnull();
+int fopenflags(const char *) paramsnonnull();
+void setbuf(FILE *, char *);
+void setbuffer(FILE *, char *, size_t);
+int setvbuf(FILE *, char *, int, size_t);
+FILE *popen(const char *, const char *);
+int pclose(FILE *);
+
+typedef uint64_t fpos_t;
+compatfn char *gets(char *) paramsnonnull();
+compatfn int fgetpos(FILE *, fpos_t *) paramsnonnull();
+compatfn int fsetpos(FILE *, const fpos_t *) paramsnonnull();
+
+int system(const char *);
+int systemexec(const char *);
+
+/*───────────────────────────────────────────────────────────────────────────│─╗
+│ cosmopolitan § standard i/o » formatting                                 ─╬─│┼
+╚────────────────────────────────────────────────────────────────────────────│*/
+
+int printf(const char *, ...) printfesque(1)
+    paramsnonnull((1)) nothrow nocallback;
+int vprintf(const char *, va_list) paramsnonnull() nothrow nocallback;
+int fprintf(FILE *, const char *, ...) printfesque(2)
+    paramsnonnull((1, 2)) nothrow nocallback;
+int vfprintf(FILE *, const char *, va_list) paramsnonnull() nothrow nocallback;
+int scanf(const char *, ...) scanfesque(1);
+int vscanf(const char *, va_list);
+int fscanf(FILE *, const char *, ...) scanfesque(2);
+int vfscanf(FILE *, const char *, va_list);
+
+/*───────────────────────────────────────────────────────────────────────────│─╗
+│ cosmopolitan § standard i/o » optimizations                              ─╬─│┼
+╚────────────────────────────────────────────────────────────────────────────│*/
+
+#define getc(f)     fgetc(f)
+#define getwc(f)    fgetwc(f)
+#define putc(c, f)  fputc(c, f)
+#define putwc(c, f) fputwc(c, f)
+
+#if defined(__GNUC__) && !defined(__STRICT_ANSI__)
+#define printf(FMT, ...)     (printf)(PFLINK(FMT), ##__VA_ARGS__)
+#define vprintf(FMT, VA)     (vprintf)(PFLINK(FMT), VA)
+#define fprintf(F, FMT, ...) (fprintf)(F, PFLINK(FMT), ##__VA_ARGS__)
+#define vfprintf(F, FMT, VA) (vfprintf)(F, PFLINK(FMT), VA)
+#define vscanf(FMT, VA)      (vscanf)(SFLINK(FMT), VA)
+#define scanf(FMT, ...)      (scanf)(SFLINK(FMT), ##__VA_ARGS__)
+#define fscanf(F, FMT, ...)  (fscanf)(F, SFLINK(FMT), ##__VA_ARGS__)
+#define vfscanf(F, FMT, VA)  (vfscanf)(F, SFLINK(FMT), VA)
+#endif
+
+COSMOPOLITAN_C_END_
+#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
+
+#define stdin  SYMBOLIC(stdin)
+#define stdout SYMBOLIC(stdout)
+#define stderr SYMBOLIC(stderr)
+
+#endif /* COSMOPOLITAN_LIBC_STDIO_STDIO_H_ */
diff --git a/stdio/stdio.mk b/stdio/stdio.mk
new file mode 100644
index 0000000..a54636e
--- /dev/null
+++ b/stdio/stdio.mk
@@ -0,0 +1,66 @@
+#-*-mode:makefile-gmake;indent-tabs-mode:t;tab-width:8;coding:utf-8-*-┐
+#───vi: set et ft=make ts=8 tw=8 fenc=utf-8 :vi───────────────────────┘
+
+PKGS += LIBC_STDIO
+
+LIBC_STDIO_ARTIFACTS += LIBC_STDIO_A
+LIBC_STDIO = $(LIBC_STDIO_A_DEPS) $(LIBC_STDIO_A)
+LIBC_STDIO_A = o/$(MODE)/libc/stdio/stdio.a
+LIBC_STDIO_A_FILES := $(wildcard libc/stdio/*) $(wildcard libc/stdio/unlocked/*)
+LIBC_STDIO_A_HDRS = $(filter %.h,$(LIBC_STDIO_A_FILES))
+LIBC_STDIO_A_SRCS_S = $(filter %.S,$(LIBC_STDIO_A_FILES))
+LIBC_STDIO_A_SRCS_C = $(filter %.c,$(LIBC_STDIO_A_FILES))
+
+LIBC_STDIO_A_SRCS =					\
+	$(LIBC_STDIO_A_SRCS_S)				\
+	$(LIBC_STDIO_A_SRCS_C)
+
+LIBC_STDIO_A_OBJS =					\
+	$(LIBC_STDIO_A_SRCS_S:%.S=o/$(MODE)/%.o)	\
+	$(LIBC_STDIO_A_SRCS_C:%.c=o/$(MODE)/%.o)
+
+LIBC_STDIO_A_CHECKS =					\
+	$(LIBC_STDIO_A).pkg				\
+	$(LIBC_STDIO_A_HDRS:%=o/$(MODE)/%.ok)
+
+LIBC_STDIO_A_DIRECTDEPS =				\
+	LIBC_ALG					\
+	LIBC_BITS					\
+	LIBC_CALLS					\
+	LIBC_FMT					\
+	LIBC_INTRIN					\
+	LIBC_MEM					\
+	LIBC_NEXGEN32E					\
+	LIBC_NT_KERNEL32				\
+	LIBC_RAND					\
+	LIBC_RUNTIME					\
+	LIBC_STR					\
+	LIBC_STUBS					\
+	LIBC_SYSV					\
+	LIBC_SYSV_CALLS					\
+	THIRD_PARTY_GDTOA
+
+LIBC_STDIO_A_DEPS :=					\
+	$(call uniq,$(foreach x,$(LIBC_STDIO_A_DIRECTDEPS),$($(x))))
+
+$(LIBC_STDIO_A):libc/stdio/				\
+		$(LIBC_STDIO_A).pkg			\
+		$(LIBC_STDIO_A_OBJS)
+
+$(LIBC_STDIO_A).pkg:					\
+		$(LIBC_STDIO_A_OBJS)			\
+		$(foreach x,$(LIBC_STDIO_A_DIRECTDEPS),$($(x)_A).pkg)
+
+o/$(MODE)/libc/stdio/fputc.o:				\
+		OVERRIDE_CFLAGS +=			\
+			-O3
+
+LIBC_STDIO_LIBS = $(foreach x,$(LIBC_STDIO_ARTIFACTS),$($(x)))
+LIBC_STDIO_SRCS = $(foreach x,$(LIBC_STDIO_ARTIFACTS),$($(x)_SRCS))
+LIBC_STDIO_HDRS = $(foreach x,$(LIBC_STDIO_ARTIFACTS),$($(x)_HDRS))
+LIBC_STDIO_CHECKS = $(foreach x,$(LIBC_STDIO_ARTIFACTS),$($(x)_CHECKS))
+LIBC_STDIO_OBJS = $(foreach x,$(LIBC_STDIO_ARTIFACTS),$($(x)_OBJS))
+$(LIBC_STDIO_OBJS): $(BUILD_FILES) libc/stdio/stdio.mk
+
+.PHONY: o/$(MODE)/libc/stdio
+o/$(MODE)/libc/stdio: $(LIBC_STDIO_CHECKS)
diff --git a/stdio/stdio_ext.h b/stdio/stdio_ext.h
new file mode 100644
index 0000000..ea8b671
--- /dev/null
+++ b/stdio/stdio_ext.h
@@ -0,0 +1,25 @@
+#ifndef COSMOPOLITAN_LIBC_STDIO_STDIO_EXT_H_
+#define COSMOPOLITAN_LIBC_STDIO_STDIO_EXT_H_
+#include "libc/stdio/stdio.h"
+
+#define FSETLOCKING_QUERY    0
+#define FSETLOCKING_INTERNAL 1
+#define FSETLOCKING_BYCALLER 2
+
+#if !(__ASSEMBLER__ + __LINKER__ + 0)
+COSMOPOLITAN_C_START_
+
+size_t __fbufsize(FILE *);
+size_t __fpending(FILE *);
+int __flbf(FILE *);
+int __freadable(FILE *);
+int __fwritable(FILE *);
+int __freading(FILE *);
+int __fwriting(FILE *);
+int __fsetlocking(FILE *, int);
+void _flushlbf(void);
+void __fpurge(FILE *);
+
+COSMOPOLITAN_C_END_
+#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
+#endif /* COSMOPOLITAN_LIBC_STDIO_STDIO_EXT_H_ */
diff --git a/stdio/stdout-init.S b/stdio/stdout-init.S
new file mode 100644
index 0000000..da9efdb
--- /dev/null
+++ b/stdio/stdout-init.S
@@ -0,0 +1,36 @@
+/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8     -*-│
+│vi: set et ft=asm ts=8 tw=8 fenc=utf-8                                     :vi│
+╞══════════════════════════════════════════════════════════════════════════════╡
+│ Copyright 2020 Justine Alexandra Roberts Tunney                              │
+│                                                                              │
+│ Permission to use, copy, modify, and/or distribute this software for         │
+│ any purpose with or without fee is hereby granted, provided that the         │
+│ above copyright notice and this permission notice appear in all copies.      │
+│                                                                              │
+│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL                │
+│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │
+│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │
+│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │
+│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │
+│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │
+│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │
+│ PERFORMANCE OF THIS SOFTWARE.                                                │
+╚─────────────────────────────────────────────────────────────────────────────*/
+#include "libc/sysv/consts/o.h"
+#include "libc/dce.h"
+#include "libc/calls/calls.h"
+#include "libc/sysv/consts/fileno.h"
+#include "libc/macros.internal.h"
+.source	__FILE__
+
+	.init.start 400,_init_stdout
+	ezlea	__stdout,ax
+	push	STDOUT_FILENO
+	pop	12(%rax)			#→ f.fd
+	mov	O_WRONLY,%edx
+	mov	%edx,4(%rax)			#→ f.iomode
+	ezlea	__stdout_buf,cx
+	mov	%rcx,24(%rax)			#→ f.buf
+	movl	$BUFSIZ,32(%rax)		#→ f.size
+	mov	%rax,stdout(%rip)
+	.init.end 400,_init_stdout,globl,hidden
diff --git a/stdio/stdout.c b/stdio/stdout.c
new file mode 100644
index 0000000..41227ad
--- /dev/null
+++ b/stdio/stdout.c
@@ -0,0 +1,45 @@
+/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
+│vi: set net ft=c ts=8 sts=2 sw=2 fenc=utf-8                                :vi│
+╞══════════════════════════════════════════════════════════════════════════════╡
+│ Copyright 2020 Justine Alexandra Roberts Tunney                              │
+│                                                                              │
+│ Permission to use, copy, modify, and/or distribute this software for         │
+│ any purpose with or without fee is hereby granted, provided that the         │
+│ above copyright notice and this permission notice appear in all copies.      │
+│                                                                              │
+│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL                │
+│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │
+│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │
+│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │
+│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │
+│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │
+│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │
+│ PERFORMANCE OF THIS SOFTWARE.                                                │
+╚─────────────────────────────────────────────────────────────────────────────*/
+#include "libc/bits/pushpop.h"
+#include "libc/calls/calls.h"
+#include "libc/dce.h"
+#include "libc/stdio/internal.h"
+#include "libc/stdio/stdio.h"
+
+STATIC_YOINK("_init_stdout");
+
+/**
+ * Pointer to standard output stream.
+ */
+FILE *stdout;
+
+hidden FILE __stdout;
+hidden unsigned char __stdout_buf[BUFSIZ];
+
+static textstartup void __stdout_init() {
+  struct FILE *sf;
+  sf = stdout;
+  asm("" : "+r"(sf));
+  if (IsWindows() || ischardev(pushpop(sf->fd))) {
+    sf->bufmode = _IOLBF;
+  }
+  __fflush_register(sf);
+}
+
+const void *const __stdout_ctor[] initarray = {__stdout_init};
diff --git a/stdio/system.c b/stdio/system.c
new file mode 100644
index 0000000..ef58b0f
--- /dev/null
+++ b/stdio/system.c
@@ -0,0 +1,76 @@
+/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
+│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8                                :vi│
+╞══════════════════════════════════════════════════════════════════════════════╡
+│ Copyright 2020 Justine Alexandra Roberts Tunney                              │
+│                                                                              │
+│ Permission to use, copy, modify, and/or distribute this software for         │
+│ any purpose with or without fee is hereby granted, provided that the         │
+│ above copyright notice and this permission notice appear in all copies.      │
+│                                                                              │
+│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL                │
+│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │
+│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │
+│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │
+│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │
+│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │
+│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │
+│ PERFORMANCE OF THIS SOFTWARE.                                                │
+╚─────────────────────────────────────────────────────────────────────────────*/
+#include "libc/bits/weaken.h"
+#include "libc/calls/calls.h"
+#include "libc/calls/sigbits.h"
+#include "libc/calls/struct/sigaction.h"
+#include "libc/dce.h"
+#include "libc/errno.h"
+#include "libc/paths.h"
+#include "libc/runtime/runtime.h"
+#include "libc/stdio/stdio.h"
+#include "libc/str/str.h"
+#include "libc/sysv/consts/ok.h"
+#include "libc/sysv/consts/sig.h"
+
+/**
+ * Launches program with system command interpreter.
+ *
+ * @param cmdline is an interpreted Turing-complete command
+ * @return -1 if child process couldn't be created, otherwise a wait
+ *     status that can be accessed using macros like WEXITSTATUS(s)
+ */
+int system(const char *cmdline) {
+  int pid, wstatus;
+  sigset_t chldmask, savemask;
+  struct sigaction ignore, saveint, savequit;
+  if (!cmdline) {
+    if (IsWindows()) return 1;
+    if (access(_PATH_BSHELL, X_OK) == 0) return 1;
+    return 0;
+  }
+  ignore.sa_flags = 0;
+  ignore.sa_handler = SIG_IGN;
+  sigemptyset(&ignore.sa_mask);
+  sigaction(SIGINT, &ignore, &saveint);
+  sigaction(SIGQUIT, &ignore, &savequit);
+  sigemptyset(&chldmask);
+  sigaddset(&chldmask, SIGCHLD);
+  sigprocmask(SIG_BLOCK, &chldmask, &savemask);
+  if (!(pid = fork())) {
+    sigaction(SIGINT, &saveint, NULL);
+    sigaction(SIGQUIT, &savequit, NULL);
+    sigprocmask(SIG_SETMASK, &savemask, NULL);
+    systemexec(cmdline);
+    _exit(127);
+  } else if (pid != -1) {
+    while (wait4(pid, &wstatus, 0, NULL) == -1) {
+      if (errno != EINTR) {
+        wstatus = -1;
+        break;
+      }
+    }
+  } else {
+    wstatus = -1;
+  }
+  sigaction(SIGINT, &saveint, NULL);
+  sigaction(SIGQUIT, &savequit, NULL);
+  sigprocmask(SIG_SETMASK, &savemask, NULL);
+  return wstatus;
+}
diff --git a/stdio/systemexec.c b/stdio/systemexec.c
new file mode 100644
index 0000000..cb9b3fd
--- /dev/null
+++ b/stdio/systemexec.c
@@ -0,0 +1,38 @@
+/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
+│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8                                :vi│
+╞══════════════════════════════════════════════════════════════════════════════╡
+│ Copyright 2021 Justine Alexandra Roberts Tunney                              │
+│                                                                              │
+│ Permission to use, copy, modify, and/or distribute this software for         │
+│ any purpose with or without fee is hereby granted, provided that the         │
+│ above copyright notice and this permission notice appear in all copies.      │
+│                                                                              │
+│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL                │
+│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │
+│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │
+│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │
+│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │
+│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │
+│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │
+│ PERFORMANCE OF THIS SOFTWARE.                                                │
+╚─────────────────────────────────────────────────────────────────────────────*/
+#include "libc/calls/calls.h"
+#include "libc/dce.h"
+#include "libc/paths.h"
+#include "libc/runtime/runtime.h"
+#include "libc/stdio/stdio.h"
+#include "libc/str/str.h"
+
+/**
+ * Executes system command replacing current process.
+ * @vforksafe
+ */
+int systemexec(const char *cmdline) {
+  char comspec[128];
+  const char *prog, *arg;
+  strcpy(comspec, kNtSystemDirectory);
+  strcat(comspec, "cmd.exe");
+  prog = !IsWindows() ? _PATH_BSHELL : comspec;
+  arg = !IsWindows() ? "-c" : "/C";
+  return execv(prog, (char *const[]){prog, arg, cmdline, NULL});
+}
diff --git a/stdio/temp.h b/stdio/temp.h
new file mode 100644
index 0000000..9b6113f
--- /dev/null
+++ b/stdio/temp.h
@@ -0,0 +1,20 @@
+#ifndef COSMOPOLITAN_LIBC_STDIO_TEMP_H_
+#define COSMOPOLITAN_LIBC_STDIO_TEMP_H_
+#include "libc/stdio/stdio.h"
+#if !(__ASSEMBLER__ + __LINKER__ + 0)
+COSMOPOLITAN_C_START_
+
+nodiscard FILE *tmpfile(void);
+nodiscard int mkstemp(char *);
+nodiscard int mkostemp(char *, unsigned);
+nodiscard int mkstemps(char *, int);
+nodiscard int mkostemps(char *, int, unsigned);
+nodiscard int mkostempsm(char *, int, unsigned, int);
+compatfn char *mktemp(char *);
+
+int mkostempsmi(char *, int, unsigned, uint64_t *, int,
+                int (*)(const char *, int, ...)) hidden nodiscard;
+
+COSMOPOLITAN_C_END_
+#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
+#endif /* COSMOPOLITAN_LIBC_STDIO_TEMP_H_ */
diff --git a/stdio/tmpfile.c b/stdio/tmpfile.c
new file mode 100644
index 0000000..b2197e4
--- /dev/null
+++ b/stdio/tmpfile.c
@@ -0,0 +1,44 @@
+/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
+│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8                                :vi│
+╞══════════════════════════════════════════════════════════════════════════════╡
+│ Copyright 2020 Justine Alexandra Roberts Tunney                              │
+│                                                                              │
+│ Permission to use, copy, modify, and/or distribute this software for         │
+│ any purpose with or without fee is hereby granted, provided that the         │
+│ above copyright notice and this permission notice appear in all copies.      │
+│                                                                              │
+│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL                │
+│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │
+│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │
+│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │
+│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │
+│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │
+│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │
+│ PERFORMANCE OF THIS SOFTWARE.                                                │
+╚─────────────────────────────────────────────────────────────────────────────*/
+#include "libc/bits/safemacros.internal.h"
+#include "libc/calls/calls.h"
+#include "libc/fmt/fmt.h"
+#include "libc/macros.internal.h"
+#include "libc/runtime/runtime.h"
+#include "libc/stdio/stdio.h"
+#include "libc/stdio/temp.h"
+#include "libc/str/str.h"
+
+/**
+ * Creates a temporary file.
+ *
+ * @see mkostempsm(), kTmpPath
+ */
+FILE *tmpfile(void) {
+  int fd;
+  char *tmp, *sep, tpl[PATH_MAX];
+  tmp = firstnonnull(getenv("TMPDIR"), kTmpPath);
+  sep = !isempty(tmp) && !endswith(tmp, "/") ? "/" : "";
+  if (snprintf(tpl, PATH_MAX, "%s%stmp.XXXXXX", tmp, sep) < PATH_MAX) {
+    if ((fd = mkostemps(tpl, 0, 0)) != -1) {
+      return fdopen(fd, "w+");
+    }
+  }
+  return NULL;
+}
diff --git a/stdio/ungetc.c b/stdio/ungetc.c
new file mode 100644
index 0000000..91a28e2
--- /dev/null
+++ b/stdio/ungetc.c
@@ -0,0 +1,36 @@
+/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
+│vi: set net ft=c ts=8 sts=2 sw=2 fenc=utf-8                                :vi│
+╞══════════════════════════════════════════════════════════════════════════════╡
+│ Copyright 2020 Justine Alexandra Roberts Tunney                              │
+│                                                                              │
+│ Permission to use, copy, modify, and/or distribute this software for         │
+│ any purpose with or without fee is hereby granted, provided that the         │
+│ above copyright notice and this permission notice appear in all copies.      │
+│                                                                              │
+│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL                │
+│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │
+│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │
+│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │
+│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │
+│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │
+│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │
+│ PERFORMANCE OF THIS SOFTWARE.                                                │
+╚─────────────────────────────────────────────────────────────────────────────*/
+#include "libc/stdio/stdio.h"
+#include "libc/str/str.h"
+
+/**
+ * Pushes byte back to stream.
+ */
+int ungetc(int c, FILE *f) {
+  if (c == -1) return -1;
+  if (f->beg) {
+    f->buf[--f->beg] = c;
+  } else if (f->end < f->size) {
+    memmove(f->buf + 1, f->buf, f->end++);
+    f->buf[0] = c;
+  } else {
+    return -1;
+  }
+  return c & 0xff;
+}
diff --git a/stdio/ungetwc.c b/stdio/ungetwc.c
new file mode 100644
index 0000000..be1fce4
--- /dev/null
+++ b/stdio/ungetwc.c
@@ -0,0 +1,47 @@
+/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
+│vi: set net ft=c ts=8 sts=2 sw=2 fenc=utf-8                                :vi│
+╞══════════════════════════════════════════════════════════════════════════════╡
+│ Copyright 2020 Justine Alexandra Roberts Tunney                              │
+│                                                                              │
+│ Permission to use, copy, modify, and/or distribute this software for         │
+│ any purpose with or without fee is hereby granted, provided that the         │
+│ above copyright notice and this permission notice appear in all copies.      │
+│                                                                              │
+│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL                │
+│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │
+│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │
+│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │
+│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │
+│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │
+│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │
+│ PERFORMANCE OF THIS SOFTWARE.                                                │
+╚─────────────────────────────────────────────────────────────────────────────*/
+#include "libc/stdio/stdio.h"
+#include "libc/str/str.h"
+#include "libc/str/tpenc.h"
+
+/**
+ * Pushes wide character back to stream.
+ */
+wint_t ungetwc(wint_t c, FILE *f) {
+  char b[6];
+  unsigned n;
+  uint64_t w;
+  if (c == -1) return -1;
+  n = 0;
+  w = tpenc(c);
+  do {
+    b[n++] = w;
+  } while ((w >>= 8));
+  if (f->beg >= n) {
+    f->beg -= n;
+    memcpy(f->buf + f->beg, b, n);
+  } else if (f->beg + f->end + n <= f->size) {
+    memmove(f->buf + f->beg + n, f->buf + f->beg, f->end - f->beg);
+    memcpy(f->buf + f->beg, b, n);
+    f->end += n;
+  } else {
+    return -1;
+  }
+  return c;
+}
diff --git a/stdio/unlocked.h b/stdio/unlocked.h
new file mode 100644
index 0000000..8686466
--- /dev/null
+++ b/stdio/unlocked.h
@@ -0,0 +1,36 @@
+#ifndef COSMOPOLITAN_LIBC_STDIO_UNLOCKED_H_
+#define COSMOPOLITAN_LIBC_STDIO_UNLOCKED_H_
+#include "libc/stdio/stdio.h"
+#if !(__ASSEMBLER__ + __LINKER__ + 0)
+COSMOPOLITAN_C_START_
+
+void flockfile(FILE *);
+void funlockfile(FILE *);
+int ftrylockfile(FILE *);
+int getc_unlocked(FILE *) paramsnonnull();
+int getchar_unlocked(void);
+int putc_unlocked(int, FILE *) paramsnonnull();
+int putchar_unlocked(int);
+void clearerr_unlocked(FILE *);
+int feof_unlocked(FILE *);
+int ferror_unlocked(FILE *);
+int fileno_unlocked(FILE *);
+int fflush_unlocked(FILE *);
+int fgetc_unlocked(FILE *);
+int fputc_unlocked(int, FILE *);
+size_t fread_unlocked(void *, size_t, size_t, FILE *);
+size_t fwrite_unlocked(const void *, size_t, size_t, FILE *);
+char *fgets_unlocked(char *, int, FILE *);
+int fputs_unlocked(const char *, FILE *);
+wint_t getwc_unlocked(FILE *);
+wint_t getwchar_unlocked(void);
+wint_t fgetwc_unlocked(FILE *);
+wint_t fputwc_unlocked(wchar_t, FILE *);
+wint_t putwc_unlocked(wchar_t, FILE *);
+wint_t putwchar_unlocked(wchar_t);
+wchar_t *fgetws_unlocked(wchar_t *, int, FILE *);
+int fputws_unlocked(const wchar_t *, FILE *);
+
+COSMOPOLITAN_C_END_
+#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
+#endif /* COSMOPOLITAN_LIBC_STDIO_UNLOCKED_H_ */
diff --git a/stdio/unlocked/clearerr_unlocked.S b/stdio/unlocked/clearerr_unlocked.S
new file mode 100644
index 0000000..a1da354
--- /dev/null
+++ b/stdio/unlocked/clearerr_unlocked.S
@@ -0,0 +1,29 @@
+/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8     -*-│
+│vi: set et ft=asm ts=8 tw=8 fenc=utf-8                                     :vi│
+╞══════════════════════════════════════════════════════════════════════════════╡
+│ Copyright 2020 Justine Alexandra Roberts Tunney                              │
+│                                                                              │
+│ Permission to use, copy, modify, and/or distribute this software for         │
+│ any purpose with or without fee is hereby granted, provided that the         │
+│ above copyright notice and this permission notice appear in all copies.      │
+│                                                                              │
+│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL                │
+│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │
+│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │
+│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │
+│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │
+│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │
+│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │
+│ PERFORMANCE OF THIS SOFTWARE.                                                │
+╚─────────────────────────────────────────────────────────────────────────────*/
+#include "libc/macros.internal.h"
+.source	__FILE__
+
+clearerr_unlocked:
+	push	%rbp
+	mov	%rsp,%rbp
+	.profilable		# note: no consensus for threads exists in abis
+	call	clearerr
+	pop	%rbp
+	ret
+	.endfn	clearerr_unlocked,globl
diff --git a/stdio/unlocked/feof_unlocked.S b/stdio/unlocked/feof_unlocked.S
new file mode 100644
index 0000000..a3a80c1
--- /dev/null
+++ b/stdio/unlocked/feof_unlocked.S
@@ -0,0 +1,29 @@
+/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8     -*-│
+│vi: set et ft=asm ts=8 tw=8 fenc=utf-8                                     :vi│
+╞══════════════════════════════════════════════════════════════════════════════╡
+│ Copyright 2020 Justine Alexandra Roberts Tunney                              │
+│                                                                              │
+│ Permission to use, copy, modify, and/or distribute this software for         │
+│ any purpose with or without fee is hereby granted, provided that the         │
+│ above copyright notice and this permission notice appear in all copies.      │
+│                                                                              │
+│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL                │
+│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │
+│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │
+│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │
+│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │
+│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │
+│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │
+│ PERFORMANCE OF THIS SOFTWARE.                                                │
+╚─────────────────────────────────────────────────────────────────────────────*/
+#include "libc/macros.internal.h"
+.source	__FILE__
+
+feof_unlocked:
+	push	%rbp
+	mov	%rsp,%rbp
+	.profilable		# note: no consensus for threads exists in abis
+	call	feof
+	pop	%rbp
+	ret
+	.endfn	feof_unlocked,globl
diff --git a/stdio/unlocked/ferror_unlocked.S b/stdio/unlocked/ferror_unlocked.S
new file mode 100644
index 0000000..e6598fb
--- /dev/null
+++ b/stdio/unlocked/ferror_unlocked.S
@@ -0,0 +1,29 @@
+/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8     -*-│
+│vi: set et ft=asm ts=8 tw=8 fenc=utf-8                                     :vi│
+╞══════════════════════════════════════════════════════════════════════════════╡
+│ Copyright 2020 Justine Alexandra Roberts Tunney                              │
+│                                                                              │
+│ Permission to use, copy, modify, and/or distribute this software for         │
+│ any purpose with or without fee is hereby granted, provided that the         │
+│ above copyright notice and this permission notice appear in all copies.      │
+│                                                                              │
+│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL                │
+│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │
+│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │
+│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │
+│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │
+│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │
+│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │
+│ PERFORMANCE OF THIS SOFTWARE.                                                │
+╚─────────────────────────────────────────────────────────────────────────────*/
+#include "libc/macros.internal.h"
+.source	__FILE__
+
+ferror_unlocked:
+	push	%rbp
+	mov	%rsp,%rbp
+	.profilable		# note: no consensus for threads exists in abis
+	call	ferror
+	pop	%rbp
+	ret
+	.endfn	ferror_unlocked,globl
diff --git a/stdio/unlocked/fflush_unlocked.S b/stdio/unlocked/fflush_unlocked.S
new file mode 100644
index 0000000..280d080
--- /dev/null
+++ b/stdio/unlocked/fflush_unlocked.S
@@ -0,0 +1,29 @@
+/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8     -*-│
+│vi: set et ft=asm ts=8 tw=8 fenc=utf-8                                     :vi│
+╞══════════════════════════════════════════════════════════════════════════════╡
+│ Copyright 2020 Justine Alexandra Roberts Tunney                              │
+│                                                                              │
+│ Permission to use, copy, modify, and/or distribute this software for         │
+│ any purpose with or without fee is hereby granted, provided that the         │
+│ above copyright notice and this permission notice appear in all copies.      │
+│                                                                              │
+│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL                │
+│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │
+│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │
+│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │
+│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │
+│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │
+│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │
+│ PERFORMANCE OF THIS SOFTWARE.                                                │
+╚─────────────────────────────────────────────────────────────────────────────*/
+#include "libc/macros.internal.h"
+.source	__FILE__
+
+fflush_unlocked:
+	push	%rbp
+	mov	%rsp,%rbp
+	.profilable		# note: no consensus for threads exists in abis
+	call	fflush
+	pop	%rbp
+	ret
+	.endfn	fflush_unlocked,globl
diff --git a/stdio/unlocked/fgetc_unlocked.S b/stdio/unlocked/fgetc_unlocked.S
new file mode 100644
index 0000000..f4c77bc
--- /dev/null
+++ b/stdio/unlocked/fgetc_unlocked.S
@@ -0,0 +1,29 @@
+/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8     -*-│
+│vi: set et ft=asm ts=8 tw=8 fenc=utf-8                                     :vi│
+╞══════════════════════════════════════════════════════════════════════════════╡
+│ Copyright 2020 Justine Alexandra Roberts Tunney                              │
+│                                                                              │
+│ Permission to use, copy, modify, and/or distribute this software for         │
+│ any purpose with or without fee is hereby granted, provided that the         │
+│ above copyright notice and this permission notice appear in all copies.      │
+│                                                                              │
+│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL                │
+│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │
+│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │
+│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │
+│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │
+│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │
+│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │
+│ PERFORMANCE OF THIS SOFTWARE.                                                │
+╚─────────────────────────────────────────────────────────────────────────────*/
+#include "libc/macros.internal.h"
+.source	__FILE__
+
+fgetc_unlocked:
+	push	%rbp
+	mov	%rsp,%rbp
+	.profilable		# note: no consensus for threads exists in abis
+	call	fgetc
+	pop	%rbp
+	ret
+	.endfn	fgetc_unlocked,globl
diff --git a/stdio/unlocked/fgets_unlocked.S b/stdio/unlocked/fgets_unlocked.S
new file mode 100644
index 0000000..7521d8c
--- /dev/null
+++ b/stdio/unlocked/fgets_unlocked.S
@@ -0,0 +1,29 @@
+/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8     -*-│
+│vi: set et ft=asm ts=8 tw=8 fenc=utf-8                                     :vi│
+╞══════════════════════════════════════════════════════════════════════════════╡
+│ Copyright 2020 Justine Alexandra Roberts Tunney                              │
+│                                                                              │
+│ Permission to use, copy, modify, and/or distribute this software for         │
+│ any purpose with or without fee is hereby granted, provided that the         │
+│ above copyright notice and this permission notice appear in all copies.      │
+│                                                                              │
+│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL                │
+│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │
+│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │
+│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │
+│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │
+│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │
+│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │
+│ PERFORMANCE OF THIS SOFTWARE.                                                │
+╚─────────────────────────────────────────────────────────────────────────────*/
+#include "libc/macros.internal.h"
+.source	__FILE__
+
+fgets_unlocked:
+	push	%rbp
+	mov	%rsp,%rbp
+	.profilable		# note: no consensus for threads exists in abis
+	call	fgets
+	pop	%rbp
+	ret
+	.endfn	fgets_unlocked,globl
diff --git a/stdio/unlocked/fgetwc_unlocked.S b/stdio/unlocked/fgetwc_unlocked.S
new file mode 100644
index 0000000..52bbb7a
--- /dev/null
+++ b/stdio/unlocked/fgetwc_unlocked.S
@@ -0,0 +1,29 @@
+/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8     -*-│
+│vi: set et ft=asm ts=8 tw=8 fenc=utf-8                                     :vi│
+╞══════════════════════════════════════════════════════════════════════════════╡
+│ Copyright 2020 Justine Alexandra Roberts Tunney                              │
+│                                                                              │
+│ Permission to use, copy, modify, and/or distribute this software for         │
+│ any purpose with or without fee is hereby granted, provided that the         │
+│ above copyright notice and this permission notice appear in all copies.      │
+│                                                                              │
+│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL                │
+│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │
+│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │
+│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │
+│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │
+│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │
+│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │
+│ PERFORMANCE OF THIS SOFTWARE.                                                │
+╚─────────────────────────────────────────────────────────────────────────────*/
+#include "libc/macros.internal.h"
+.source	__FILE__
+
+fgetwc_unlocked:
+	push	%rbp
+	mov	%rsp,%rbp
+	.profilable		# note: no consensus for threads exists in abis
+	call	fgetwc
+	pop	%rbp
+	ret
+	.endfn	fgetwc_unlocked,globl
diff --git a/stdio/unlocked/fgetws_unlocked.S b/stdio/unlocked/fgetws_unlocked.S
new file mode 100644
index 0000000..02b1dd7
--- /dev/null
+++ b/stdio/unlocked/fgetws_unlocked.S
@@ -0,0 +1,29 @@
+/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8     -*-│
+│vi: set et ft=asm ts=8 tw=8 fenc=utf-8                                     :vi│
+╞══════════════════════════════════════════════════════════════════════════════╡
+│ Copyright 2020 Justine Alexandra Roberts Tunney                              │
+│                                                                              │
+│ Permission to use, copy, modify, and/or distribute this software for         │
+│ any purpose with or without fee is hereby granted, provided that the         │
+│ above copyright notice and this permission notice appear in all copies.      │
+│                                                                              │
+│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL                │
+│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │
+│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │
+│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │
+│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │
+│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │
+│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │
+│ PERFORMANCE OF THIS SOFTWARE.                                                │
+╚─────────────────────────────────────────────────────────────────────────────*/
+#include "libc/macros.internal.h"
+.source	__FILE__
+
+fgetws_unlocked:
+	push	%rbp
+	mov	%rsp,%rbp
+	.profilable		# note: no consensus for threads exists in abis
+	call	fgetws
+	pop	%rbp
+	ret
+	.endfn	fgetws_unlocked,globl
diff --git a/stdio/unlocked/fileno_unlocked.S b/stdio/unlocked/fileno_unlocked.S
new file mode 100644
index 0000000..f90be61
--- /dev/null
+++ b/stdio/unlocked/fileno_unlocked.S
@@ -0,0 +1,29 @@
+/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8     -*-│
+│vi: set et ft=asm ts=8 tw=8 fenc=utf-8                                     :vi│
+╞══════════════════════════════════════════════════════════════════════════════╡
+│ Copyright 2020 Justine Alexandra Roberts Tunney                              │
+│                                                                              │
+│ Permission to use, copy, modify, and/or distribute this software for         │
+│ any purpose with or without fee is hereby granted, provided that the         │
+│ above copyright notice and this permission notice appear in all copies.      │
+│                                                                              │
+│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL                │
+│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │
+│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │
+│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │
+│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │
+│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │
+│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │
+│ PERFORMANCE OF THIS SOFTWARE.                                                │
+╚─────────────────────────────────────────────────────────────────────────────*/
+#include "libc/macros.internal.h"
+.source	__FILE__
+
+fileno_unlocked:
+	push	%rbp
+	mov	%rsp,%rbp
+	.profilable		# note: no consensus for threads exists in abis
+	call	fileno
+	pop	%rbp
+	ret
+	.endfn	fileno_unlocked,globl
diff --git a/stdio/unlocked/fputc_unlocked.S b/stdio/unlocked/fputc_unlocked.S
new file mode 100644
index 0000000..7c35788
--- /dev/null
+++ b/stdio/unlocked/fputc_unlocked.S
@@ -0,0 +1,29 @@
+/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8     -*-│
+│vi: set et ft=asm ts=8 tw=8 fenc=utf-8                                     :vi│
+╞══════════════════════════════════════════════════════════════════════════════╡
+│ Copyright 2020 Justine Alexandra Roberts Tunney                              │
+│                                                                              │
+│ Permission to use, copy, modify, and/or distribute this software for         │
+│ any purpose with or without fee is hereby granted, provided that the         │
+│ above copyright notice and this permission notice appear in all copies.      │
+│                                                                              │
+│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL                │
+│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │
+│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │
+│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │
+│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │
+│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │
+│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │
+│ PERFORMANCE OF THIS SOFTWARE.                                                │
+╚─────────────────────────────────────────────────────────────────────────────*/
+#include "libc/macros.internal.h"
+.source	__FILE__
+
+fputc_unlocked:
+	push	%rbp
+	mov	%rsp,%rbp
+	.profilable		# note: no consensus for threads exists in abis
+	call	fputc
+	pop	%rbp
+	ret
+	.endfn	fputc_unlocked,globl
diff --git a/stdio/unlocked/fputs_unlocked.S b/stdio/unlocked/fputs_unlocked.S
new file mode 100644
index 0000000..2adf210
--- /dev/null
+++ b/stdio/unlocked/fputs_unlocked.S
@@ -0,0 +1,29 @@
+/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8     -*-│
+│vi: set et ft=asm ts=8 tw=8 fenc=utf-8                                     :vi│
+╞══════════════════════════════════════════════════════════════════════════════╡
+│ Copyright 2020 Justine Alexandra Roberts Tunney                              │
+│                                                                              │
+│ Permission to use, copy, modify, and/or distribute this software for         │
+│ any purpose with or without fee is hereby granted, provided that the         │
+│ above copyright notice and this permission notice appear in all copies.      │
+│                                                                              │
+│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL                │
+│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │
+│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │
+│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │
+│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │
+│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │
+│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │
+│ PERFORMANCE OF THIS SOFTWARE.                                                │
+╚─────────────────────────────────────────────────────────────────────────────*/
+#include "libc/macros.internal.h"
+.source	__FILE__
+
+fputs_unlocked:
+	push	%rbp
+	mov	%rsp,%rbp
+	.profilable		# note: no consensus for threads exists in abis
+	call	fputs
+	pop	%rbp
+	ret
+	.endfn	fputs_unlocked,globl
diff --git a/stdio/unlocked/fputwc_unlocked.S b/stdio/unlocked/fputwc_unlocked.S
new file mode 100644
index 0000000..1b505fa
--- /dev/null
+++ b/stdio/unlocked/fputwc_unlocked.S
@@ -0,0 +1,29 @@
+/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8     -*-│
+│vi: set et ft=asm ts=8 tw=8 fenc=utf-8                                     :vi│
+╞══════════════════════════════════════════════════════════════════════════════╡
+│ Copyright 2020 Justine Alexandra Roberts Tunney                              │
+│                                                                              │
+│ Permission to use, copy, modify, and/or distribute this software for         │
+│ any purpose with or without fee is hereby granted, provided that the         │
+│ above copyright notice and this permission notice appear in all copies.      │
+│                                                                              │
+│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL                │
+│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │
+│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │
+│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │
+│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │
+│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │
+│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │
+│ PERFORMANCE OF THIS SOFTWARE.                                                │
+╚─────────────────────────────────────────────────────────────────────────────*/
+#include "libc/macros.internal.h"
+.source	__FILE__
+
+fputwc_unlocked:
+	push	%rbp
+	mov	%rsp,%rbp
+	.profilable		# note: no consensus for threads exists in abis
+	call	fputwc
+	pop	%rbp
+	ret
+	.endfn	fputwc_unlocked,globl
diff --git a/stdio/unlocked/fputws_unlocked.S b/stdio/unlocked/fputws_unlocked.S
new file mode 100644
index 0000000..611be6a
--- /dev/null
+++ b/stdio/unlocked/fputws_unlocked.S
@@ -0,0 +1,29 @@
+/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8     -*-│
+│vi: set et ft=asm ts=8 tw=8 fenc=utf-8                                     :vi│
+╞══════════════════════════════════════════════════════════════════════════════╡
+│ Copyright 2020 Justine Alexandra Roberts Tunney                              │
+│                                                                              │
+│ Permission to use, copy, modify, and/or distribute this software for         │
+│ any purpose with or without fee is hereby granted, provided that the         │
+│ above copyright notice and this permission notice appear in all copies.      │
+│                                                                              │
+│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL                │
+│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │
+│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │
+│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │
+│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │
+│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │
+│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │
+│ PERFORMANCE OF THIS SOFTWARE.                                                │
+╚─────────────────────────────────────────────────────────────────────────────*/
+#include "libc/macros.internal.h"
+.source	__FILE__
+
+fputws_unlocked:
+	push	%rbp
+	mov	%rsp,%rbp
+	.profilable		# note: no consensus for threads exists in abis
+	call	fputws
+	pop	%rbp
+	ret
+	.endfn	fputws_unlocked,globl
diff --git a/stdio/unlocked/fread_unlocked.S b/stdio/unlocked/fread_unlocked.S
new file mode 100644
index 0000000..3cbb061
--- /dev/null
+++ b/stdio/unlocked/fread_unlocked.S
@@ -0,0 +1,29 @@
+/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8     -*-│
+│vi: set et ft=asm ts=8 tw=8 fenc=utf-8                                     :vi│
+╞══════════════════════════════════════════════════════════════════════════════╡
+│ Copyright 2020 Justine Alexandra Roberts Tunney                              │
+│                                                                              │
+│ Permission to use, copy, modify, and/or distribute this software for         │
+│ any purpose with or without fee is hereby granted, provided that the         │
+│ above copyright notice and this permission notice appear in all copies.      │
+│                                                                              │
+│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL                │
+│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │
+│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │
+│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │
+│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │
+│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │
+│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │
+│ PERFORMANCE OF THIS SOFTWARE.                                                │
+╚─────────────────────────────────────────────────────────────────────────────*/
+#include "libc/macros.internal.h"
+.source	__FILE__
+
+fread_unlocked:
+	push	%rbp
+	mov	%rsp,%rbp
+	.profilable		# note: no consensus for threads exists in abis
+	call	fread
+	pop	%rbp
+	ret
+	.endfn	fread_unlocked,globl
diff --git a/stdio/unlocked/fwrite_unlocked.S b/stdio/unlocked/fwrite_unlocked.S
new file mode 100644
index 0000000..d296e28
--- /dev/null
+++ b/stdio/unlocked/fwrite_unlocked.S
@@ -0,0 +1,29 @@
+/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8     -*-│
+│vi: set et ft=asm ts=8 tw=8 fenc=utf-8                                     :vi│
+╞══════════════════════════════════════════════════════════════════════════════╡
+│ Copyright 2020 Justine Alexandra Roberts Tunney                              │
+│                                                                              │
+│ Permission to use, copy, modify, and/or distribute this software for         │
+│ any purpose with or without fee is hereby granted, provided that the         │
+│ above copyright notice and this permission notice appear in all copies.      │
+│                                                                              │
+│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL                │
+│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │
+│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │
+│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │
+│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │
+│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │
+│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │
+│ PERFORMANCE OF THIS SOFTWARE.                                                │
+╚─────────────────────────────────────────────────────────────────────────────*/
+#include "libc/macros.internal.h"
+.source	__FILE__
+
+fwrite_unlocked:
+	push	%rbp
+	mov	%rsp,%rbp
+	.profilable		# note: no consensus for threads exists in abis
+	call	fwrite
+	pop	%rbp
+	ret
+	.endfn	fwrite_unlocked,globl
diff --git a/stdio/unlocked/getc_unlocked.S b/stdio/unlocked/getc_unlocked.S
new file mode 100644
index 0000000..1d6e9c7
--- /dev/null
+++ b/stdio/unlocked/getc_unlocked.S
@@ -0,0 +1,29 @@
+/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8     -*-│
+│vi: set et ft=asm ts=8 tw=8 fenc=utf-8                                     :vi│
+╞══════════════════════════════════════════════════════════════════════════════╡
+│ Copyright 2020 Justine Alexandra Roberts Tunney                              │
+│                                                                              │
+│ Permission to use, copy, modify, and/or distribute this software for         │
+│ any purpose with or without fee is hereby granted, provided that the         │
+│ above copyright notice and this permission notice appear in all copies.      │
+│                                                                              │
+│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL                │
+│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │
+│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │
+│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │
+│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │
+│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │
+│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │
+│ PERFORMANCE OF THIS SOFTWARE.                                                │
+╚─────────────────────────────────────────────────────────────────────────────*/
+#include "libc/macros.internal.h"
+.source	__FILE__
+
+getc_unlocked:
+	push	%rbp
+	mov	%rsp,%rbp
+	.profilable		# note: no consensus for threads exists in abis
+	call	getc
+	pop	%rbp
+	ret
+	.endfn	getc_unlocked,globl
diff --git a/stdio/unlocked/getchar_unlocked.S b/stdio/unlocked/getchar_unlocked.S
new file mode 100644
index 0000000..ebb6b76
--- /dev/null
+++ b/stdio/unlocked/getchar_unlocked.S
@@ -0,0 +1,29 @@
+/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8     -*-│
+│vi: set et ft=asm ts=8 tw=8 fenc=utf-8                                     :vi│
+╞══════════════════════════════════════════════════════════════════════════════╡
+│ Copyright 2020 Justine Alexandra Roberts Tunney                              │
+│                                                                              │
+│ Permission to use, copy, modify, and/or distribute this software for         │
+│ any purpose with or without fee is hereby granted, provided that the         │
+│ above copyright notice and this permission notice appear in all copies.      │
+│                                                                              │
+│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL                │
+│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │
+│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │
+│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │
+│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │
+│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │
+│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │
+│ PERFORMANCE OF THIS SOFTWARE.                                                │
+╚─────────────────────────────────────────────────────────────────────────────*/
+#include "libc/macros.internal.h"
+.source	__FILE__
+
+getchar_unlocked:
+	push	%rbp
+	mov	%rsp,%rbp
+	.profilable		# note: no consensus for threads exists in abis
+	call	getchar
+	pop	%rbp
+	ret
+	.endfn	getchar_unlocked,globl
diff --git a/stdio/unlocked/getwc_unlocked.S b/stdio/unlocked/getwc_unlocked.S
new file mode 100644
index 0000000..a024387
--- /dev/null
+++ b/stdio/unlocked/getwc_unlocked.S
@@ -0,0 +1,29 @@
+/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8     -*-│
+│vi: set et ft=asm ts=8 tw=8 fenc=utf-8                                     :vi│
+╞══════════════════════════════════════════════════════════════════════════════╡
+│ Copyright 2020 Justine Alexandra Roberts Tunney                              │
+│                                                                              │
+│ Permission to use, copy, modify, and/or distribute this software for         │
+│ any purpose with or without fee is hereby granted, provided that the         │
+│ above copyright notice and this permission notice appear in all copies.      │
+│                                                                              │
+│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL                │
+│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │
+│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │
+│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │
+│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │
+│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │
+│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │
+│ PERFORMANCE OF THIS SOFTWARE.                                                │
+╚─────────────────────────────────────────────────────────────────────────────*/
+#include "libc/macros.internal.h"
+.source	__FILE__
+
+getwc_unlocked:
+	push	%rbp
+	mov	%rsp,%rbp
+	.profilable		# note: no consensus for threads exists in abis
+	call	fgetwc_unlocked
+	pop	%rbp
+	ret
+	.endfn	getwc_unlocked,globl
diff --git a/stdio/unlocked/getwchar_unlocked.S b/stdio/unlocked/getwchar_unlocked.S
new file mode 100644
index 0000000..bb6710a
--- /dev/null
+++ b/stdio/unlocked/getwchar_unlocked.S
@@ -0,0 +1,29 @@
+/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8     -*-│
+│vi: set et ft=asm ts=8 tw=8 fenc=utf-8                                     :vi│
+╞══════════════════════════════════════════════════════════════════════════════╡
+│ Copyright 2020 Justine Alexandra Roberts Tunney                              │
+│                                                                              │
+│ Permission to use, copy, modify, and/or distribute this software for         │
+│ any purpose with or without fee is hereby granted, provided that the         │
+│ above copyright notice and this permission notice appear in all copies.      │
+│                                                                              │
+│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL                │
+│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │
+│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │
+│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │
+│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │
+│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │
+│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │
+│ PERFORMANCE OF THIS SOFTWARE.                                                │
+╚─────────────────────────────────────────────────────────────────────────────*/
+#include "libc/macros.internal.h"
+.source	__FILE__
+
+getwchar_unlocked:
+	push	%rbp
+	mov	%rsp,%rbp
+	.profilable		# note: no consensus for threads exists in abis
+	call	getwchar
+	pop	%rbp
+	ret
+	.endfn	getwchar_unlocked,globl
diff --git a/stdio/unlocked/putc_unlocked.S b/stdio/unlocked/putc_unlocked.S
new file mode 100644
index 0000000..842d740
--- /dev/null
+++ b/stdio/unlocked/putc_unlocked.S
@@ -0,0 +1,29 @@
+/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8     -*-│
+│vi: set et ft=asm ts=8 tw=8 fenc=utf-8                                     :vi│
+╞══════════════════════════════════════════════════════════════════════════════╡
+│ Copyright 2020 Justine Alexandra Roberts Tunney                              │
+│                                                                              │
+│ Permission to use, copy, modify, and/or distribute this software for         │
+│ any purpose with or without fee is hereby granted, provided that the         │
+│ above copyright notice and this permission notice appear in all copies.      │
+│                                                                              │
+│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL                │
+│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │
+│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │
+│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │
+│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │
+│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │
+│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │
+│ PERFORMANCE OF THIS SOFTWARE.                                                │
+╚─────────────────────────────────────────────────────────────────────────────*/
+#include "libc/macros.internal.h"
+.source	__FILE__
+
+putc_unlocked:
+	push	%rbp
+	mov	%rsp,%rbp
+	.profilable		# note: no consensus for threads exists in abis
+	call	putc
+	pop	%rbp
+	ret
+	.endfn	putc_unlocked,globl
diff --git a/stdio/unlocked/putchar_unlocked.S b/stdio/unlocked/putchar_unlocked.S
new file mode 100644
index 0000000..df0b807
--- /dev/null
+++ b/stdio/unlocked/putchar_unlocked.S
@@ -0,0 +1,29 @@
+/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8     -*-│
+│vi: set et ft=asm ts=8 tw=8 fenc=utf-8                                     :vi│
+╞══════════════════════════════════════════════════════════════════════════════╡
+│ Copyright 2020 Justine Alexandra Roberts Tunney                              │
+│                                                                              │
+│ Permission to use, copy, modify, and/or distribute this software for         │
+│ any purpose with or without fee is hereby granted, provided that the         │
+│ above copyright notice and this permission notice appear in all copies.      │
+│                                                                              │
+│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL                │
+│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │
+│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │
+│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │
+│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │
+│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │
+│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │
+│ PERFORMANCE OF THIS SOFTWARE.                                                │
+╚─────────────────────────────────────────────────────────────────────────────*/
+#include "libc/macros.internal.h"
+.source	__FILE__
+
+putchar_unlocked:
+	push	%rbp
+	mov	%rsp,%rbp
+	.profilable		# note: no consensus for threads exists in abis
+	call	putchar
+	pop	%rbp
+	ret
+	.endfn	putchar_unlocked,globl
diff --git a/stdio/unlocked/putwc_unlocked.S b/stdio/unlocked/putwc_unlocked.S
new file mode 100644
index 0000000..3890a2d
--- /dev/null
+++ b/stdio/unlocked/putwc_unlocked.S
@@ -0,0 +1,29 @@
+/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8     -*-│
+│vi: set et ft=asm ts=8 tw=8 fenc=utf-8                                     :vi│
+╞══════════════════════════════════════════════════════════════════════════════╡
+│ Copyright 2020 Justine Alexandra Roberts Tunney                              │
+│                                                                              │
+│ Permission to use, copy, modify, and/or distribute this software for         │
+│ any purpose with or without fee is hereby granted, provided that the         │
+│ above copyright notice and this permission notice appear in all copies.      │
+│                                                                              │
+│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL                │
+│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │
+│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │
+│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │
+│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │
+│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │
+│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │
+│ PERFORMANCE OF THIS SOFTWARE.                                                │
+╚─────────────────────────────────────────────────────────────────────────────*/
+#include "libc/macros.internal.h"
+.source	__FILE__
+
+putwc_unlocked:
+	push	%rbp
+	mov	%rsp,%rbp
+	.profilable		# note: no consensus for threads exists in abis
+	call	fputwc_unlocked
+	pop	%rbp
+	ret
+	.endfn	putwc_unlocked,globl
diff --git a/stdio/unlocked/putwchar_unlocked.S b/stdio/unlocked/putwchar_unlocked.S
new file mode 100644
index 0000000..5e7f38e
--- /dev/null
+++ b/stdio/unlocked/putwchar_unlocked.S
@@ -0,0 +1,30 @@
+
+/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8     -*-│
+│vi: set et ft=asm ts=8 tw=8 fenc=utf-8                                     :vi│
+╞══════════════════════════════════════════════════════════════════════════════╡
+│ Copyright 2020 Justine Alexandra Roberts Tunney                              │
+│                                                                              │
+│ Permission to use, copy, modify, and/or distribute this software for         │
+│ any purpose with or without fee is hereby granted, provided that the         │
+│ above copyright notice and this permission notice appear in all copies.      │
+│                                                                              │
+│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL                │
+│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │
+│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │
+│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │
+│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │
+│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │
+│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │
+│ PERFORMANCE OF THIS SOFTWARE.                                                │
+╚─────────────────────────────────────────────────────────────────────────────*/
+#include "libc/macros.internal.h"
+.source	__FILE__
+
+putwchar_unlocked:
+	push	%rbp
+	mov	%rsp,%rbp
+	.profilable		# note: no consensus for threads exists in abis
+	call	putwchar
+	pop	%rbp
+	ret
+	.endfn	putwchar_unlocked,globl
diff --git a/stdio/vfprintf.c b/stdio/vfprintf.c
new file mode 100644
index 0000000..cd2c0a2
--- /dev/null
+++ b/stdio/vfprintf.c
@@ -0,0 +1,41 @@
+/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
+│vi: set net ft=c ts=8 sts=2 sw=2 fenc=utf-8                                :vi│
+╞══════════════════════════════════════════════════════════════════════════════╡
+│ Copyright 2020 Justine Alexandra Roberts Tunney                              │
+│                                                                              │
+│ Permission to use, copy, modify, and/or distribute this software for         │
+│ any purpose with or without fee is hereby granted, provided that the         │
+│ above copyright notice and this permission notice appear in all copies.      │
+│                                                                              │
+│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL                │
+│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │
+│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │
+│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │
+│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │
+│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │
+│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │
+│ PERFORMANCE OF THIS SOFTWARE.                                                │
+╚─────────────────────────────────────────────────────────────────────────────*/
+#include "libc/fmt/fmt.h"
+#include "libc/limits.h"
+#include "libc/stdio/stdio.h"
+#include "libc/sysv/errfuns.h"
+
+struct state {
+  FILE *f;
+  int n;
+};
+
+static noinstrument int vfprintfputchar(int c, struct state *st) {
+  st->n++;
+  return fputc(c, st->f);
+}
+
+int(vfprintf)(FILE *f, const char *fmt, va_list va) {
+  struct state st[1] = {{f, 0}};
+  if (__fmt(vfprintfputchar, st, fmt, va) != -1) {
+    return st->n;
+  } else {
+    return -1;
+  }
+}
diff --git a/stdio/vfscanf.c b/stdio/vfscanf.c
new file mode 100644
index 0000000..536c554
--- /dev/null
+++ b/stdio/vfscanf.c
@@ -0,0 +1,28 @@
+/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
+│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8                                :vi│
+╞══════════════════════════════════════════════════════════════════════════════╡
+│ Copyright 2020 Justine Alexandra Roberts Tunney                              │
+│                                                                              │
+│ Permission to use, copy, modify, and/or distribute this software for         │
+│ any purpose with or without fee is hereby granted, provided that the         │
+│ above copyright notice and this permission notice appear in all copies.      │
+│                                                                              │
+│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL                │
+│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │
+│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │
+│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │
+│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │
+│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │
+│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │
+│ PERFORMANCE OF THIS SOFTWARE.                                                │
+╚─────────────────────────────────────────────────────────────────────────────*/
+#include "libc/fmt/fmt.h"
+#include "libc/stdio/stdio.h"
+
+/**
+ * Stream decoder.
+ * @see libc/fmt/vcscanf.h
+ */
+int(vfscanf)(FILE *stream, const char *fmt, va_list ap) {
+  return (vcscanf)((void *)fgetc, (void *)ungetc, stream, fmt, ap);
+}
diff --git a/stdio/vprintf.c b/stdio/vprintf.c
new file mode 100644
index 0000000..0599232
--- /dev/null
+++ b/stdio/vprintf.c
@@ -0,0 +1,23 @@
+/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
+│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8                                :vi│
+╞══════════════════════════════════════════════════════════════════════════════╡
+│ Copyright 2020 Justine Alexandra Roberts Tunney                              │
+│                                                                              │
+│ Permission to use, copy, modify, and/or distribute this software for         │
+│ any purpose with or without fee is hereby granted, provided that the         │
+│ above copyright notice and this permission notice appear in all copies.      │
+│                                                                              │
+│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL                │
+│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │
+│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │
+│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │
+│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │
+│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │
+│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │
+│ PERFORMANCE OF THIS SOFTWARE.                                                │
+╚─────────────────────────────────────────────────────────────────────────────*/
+#include "libc/stdio/stdio.h"
+
+int(vprintf)(const char* fmt, va_list va) {
+  return (vfprintf)(stdout, fmt, va);
+}
diff --git a/stdio/vscanf.c b/stdio/vscanf.c
new file mode 100644
index 0000000..acb01a2
--- /dev/null
+++ b/stdio/vscanf.c
@@ -0,0 +1,28 @@
+/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
+│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8                                :vi│
+╞══════════════════════════════════════════════════════════════════════════════╡
+│ Copyright 2020 Justine Alexandra Roberts Tunney                              │
+│                                                                              │
+│ Permission to use, copy, modify, and/or distribute this software for         │
+│ any purpose with or without fee is hereby granted, provided that the         │
+│ above copyright notice and this permission notice appear in all copies.      │
+│                                                                              │
+│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL                │
+│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │
+│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │
+│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │
+│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │
+│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │
+│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │
+│ PERFORMANCE OF THIS SOFTWARE.                                                │
+╚─────────────────────────────────────────────────────────────────────────────*/
+#include "libc/fmt/fmt.h"
+#include "libc/stdio/stdio.h"
+
+/**
+ * String decoder.
+ * @see libc/fmt/vcscanf.h
+ */
+int(vscanf)(const char *fmt, va_list ap) {
+  return (vcscanf)((int (*)(void *))fgetc, (void *)ungetc, stdin, fmt, ap);
+}