Initial Contribution
diff --git a/libc/stdio/asprintf.c b/libc/stdio/asprintf.c
new file mode 100644
index 0000000..7379140
--- /dev/null
+++ b/libc/stdio/asprintf.c
@@ -0,0 +1,60 @@
+/*	$OpenBSD: asprintf.c,v 1.15 2005/10/10 12:00:52 espie Exp $	*/
+
+/*
+ * Copyright (c) 1997 Todd C. Miller <Todd.Miller@courtesan.com>
+ *
+ * Permission to use, copy, modify, and 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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <stdarg.h>
+#include "local.h"
+
+int
+asprintf(char **str, const char *fmt, ...)
+{
+	int ret;
+	va_list ap;
+	FILE f;
+	unsigned char *_base;
+
+	f._file = -1;
+	f._flags = __SWR | __SSTR | __SALC;
+	f._bf._base = f._p = (unsigned char *)malloc(128);
+	if (f._bf._base == NULL)
+		goto err;
+	f._bf._size = f._w = 127;		/* Leave room for the NUL */
+	va_start(ap, fmt);
+	ret = vfprintf(&f, fmt, ap);
+  va_end(ap);
+	if (ret == -1)
+		goto err;
+	*f._p = '\0';
+	_base = realloc(f._bf._base, ret + 1);
+	if (_base == NULL)
+		goto err;
+	*str = (char *)_base;
+	return (ret);
+
+err:
+	if (f._bf._base) {
+		free(f._bf._base);
+		f._bf._base = NULL;
+	}
+	*str = NULL;
+	errno = ENOMEM;
+	return (-1);
+}
diff --git a/libc/stdio/clrerr.c b/libc/stdio/clrerr.c
new file mode 100644
index 0000000..20f1994
--- /dev/null
+++ b/libc/stdio/clrerr.c
@@ -0,0 +1,43 @@
+/*	$OpenBSD: clrerr.c,v 1.6 2005/08/08 08:05:36 espie Exp $ */
+/*-
+ * Copyright (c) 1990, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <stdio.h>
+#undef	clearerr
+
+void
+clearerr(FILE *fp)
+{
+	flockfile(fp);
+	__sclearerr(fp);
+	funlockfile(fp);
+}
diff --git a/libc/stdio/fclose.c b/libc/stdio/fclose.c
new file mode 100644
index 0000000..bdf6e52
--- /dev/null
+++ b/libc/stdio/fclose.c
@@ -0,0 +1,61 @@
+/*	$OpenBSD: fclose.c,v 1.6 2005/08/08 08:05:36 espie Exp $ */
+/*-
+ * Copyright (c) 1990, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include "local.h"
+
+int
+fclose(FILE *fp)
+{
+	int r;
+
+	if (fp->_flags == 0) {	/* not open! */
+		errno = EBADF;
+		return (EOF);
+	}
+	WCIO_FREE(fp);
+	r = fp->_flags & __SWR ? __sflush(fp) : 0;
+	if (fp->_close != NULL && (*fp->_close)(fp->_cookie) < 0)
+		r = EOF;
+	if (fp->_flags & __SMBF)
+		free((char *)fp->_bf._base);
+	if (HASUB(fp))
+		FREEUB(fp);
+	if (HASLB(fp))
+		FREELB(fp);
+	fp->_flags = 0;		/* Release this FILE for reuse. */
+	fp->_r = fp->_w = 0;	/* Mess up if reaccessed. */
+	return (r);
+}
diff --git a/libc/stdio/fdopen.c b/libc/stdio/fdopen.c
new file mode 100644
index 0000000..1df609c
--- /dev/null
+++ b/libc/stdio/fdopen.c
@@ -0,0 +1,76 @@
+/*	$OpenBSD: fdopen.c,v 1.5 2005/08/08 08:05:36 espie Exp $ */
+/*-
+ * Copyright (c) 1990, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/types.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <errno.h>
+#include "local.h"
+
+FILE *
+fdopen(int fd, const char *mode)
+{
+	FILE *fp;
+	int flags, oflags, fdflags, tmp;
+
+	if ((flags = __sflags(mode, &oflags)) == 0)
+		return (NULL);
+
+	/* Make sure the mode the user wants is a subset of the actual mode. */
+	if ((fdflags = fcntl(fd, F_GETFL, 0)) < 0)
+		return (NULL);
+	tmp = fdflags & O_ACCMODE;
+	if (tmp != O_RDWR && (tmp != (oflags & O_ACCMODE))) {
+		errno = EINVAL;
+		return (NULL);
+	}
+
+	if ((fp = __sfp()) == NULL)
+		return (NULL);
+	fp->_flags = flags;
+	/*
+	 * If opened for appending, but underlying descriptor does not have
+	 * O_APPEND bit set, assert __SAPP so that __swrite() will lseek to
+	 * end before each write.
+	 */
+	if ((oflags & O_APPEND) && !(fdflags & O_APPEND))
+		fp->_flags |= __SAPP;
+	fp->_file = fd;
+	fp->_cookie = fp;
+	fp->_read = __sread;
+	fp->_write = __swrite;
+	fp->_seek = __sseek;
+	fp->_close = __sclose;
+	return (fp);
+}
diff --git a/libc/stdio/feof.c b/libc/stdio/feof.c
new file mode 100644
index 0000000..eb742da
--- /dev/null
+++ b/libc/stdio/feof.c
@@ -0,0 +1,45 @@
+/*	$OpenBSD: feof.c,v 1.5 2005/08/08 08:05:36 espie Exp $ */
+/*-
+ * Copyright (c) 1990, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <stdio.h>
+
+/*
+ * A subroutine version of the macro feof.
+ */
+#undef feof
+
+int
+feof(FILE *fp)
+{
+	return (__sfeof(fp));
+}
diff --git a/libc/stdio/ferror.c b/libc/stdio/ferror.c
new file mode 100644
index 0000000..0d2cf01
--- /dev/null
+++ b/libc/stdio/ferror.c
@@ -0,0 +1,45 @@
+/*	$OpenBSD: ferror.c,v 1.5 2005/08/08 08:05:36 espie Exp $ */
+/*-
+ * Copyright (c) 1990, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <stdio.h>
+
+/*
+ * A subroutine version of the macro ferror.
+ */
+#undef ferror
+
+int
+ferror(FILE *fp)
+{
+	return (__sferror(fp));
+}
diff --git a/libc/stdio/fflush.c b/libc/stdio/fflush.c
new file mode 100644
index 0000000..3f72ad8
--- /dev/null
+++ b/libc/stdio/fflush.c
@@ -0,0 +1,82 @@
+/*	$OpenBSD: fflush.c,v 1.5 2005/08/08 08:05:36 espie Exp $ */
+/*-
+ * Copyright (c) 1990, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <errno.h>
+#include <stdio.h>
+#include "local.h"
+
+/* Flush a single file, or (if fp is NULL) all files.  */
+int
+fflush(FILE *fp)
+{
+
+	if (fp == NULL)
+		return (_fwalk(__sflush));
+	if ((fp->_flags & (__SWR | __SRW)) == 0) {
+		errno = EBADF;
+		return (EOF);
+	}
+	return (__sflush(fp));
+}
+
+int
+__sflush(FILE *fp)
+{
+	unsigned char *p;
+	int n, t;
+
+	t = fp->_flags;
+	if ((t & __SWR) == 0)
+		return (0);
+
+	if ((p = fp->_bf._base) == NULL)
+		return (0);
+
+	n = fp->_p - p;		/* write this much */
+
+	/*
+	 * Set these immediately to avoid problems with longjmp and to allow
+	 * exchange buffering (via setvbuf) in user write function.
+	 */
+	fp->_p = p;
+	fp->_w = t & (__SLBF|__SNBF) ? 0 : fp->_bf._size;
+
+	for (; n > 0; n -= t, p += t) {
+		t = (*fp->_write)(fp->_cookie, (char *)p, n);
+		if (t <= 0) {
+			fp->_flags |= __SERR;
+			return (EOF);
+		}
+	}
+	return (0);
+}
diff --git a/libc/stdio/fgetc.c b/libc/stdio/fgetc.c
new file mode 100644
index 0000000..53e2948
--- /dev/null
+++ b/libc/stdio/fgetc.c
@@ -0,0 +1,40 @@
+/*	$OpenBSD: fgetc.c,v 1.5 2005/08/08 08:05:36 espie Exp $ */
+/*-
+ * Copyright (c) 1990, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <stdio.h>
+
+int
+fgetc(FILE *fp)
+{
+	return (__sgetc(fp));
+}
diff --git a/libc/stdio/fgetln.c b/libc/stdio/fgetln.c
new file mode 100644
index 0000000..946e1b7
--- /dev/null
+++ b/libc/stdio/fgetln.c
@@ -0,0 +1,150 @@
+/*	$OpenBSD: fgetln.c,v 1.7 2005/08/08 08:05:36 espie Exp $ */
+/*-
+ * Copyright (c) 1990, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "local.h"
+
+/*
+ * Expand the line buffer.  Return -1 on error.
+#ifdef notdef
+ * The `new size' does not account for a terminating '\0',
+ * so we add 1 here.
+#endif
+ */
+int
+__slbexpand(FILE *fp, size_t newsize)
+{
+	void *p;
+
+#ifdef notdef
+	++newsize;
+#endif
+	if ((size_t)fp->_lb._size >= newsize)
+		return (0);
+	if ((p = realloc(fp->_lb._base, newsize)) == NULL)
+		return (-1);
+	fp->_lb._base = p;
+	fp->_lb._size = newsize;
+	return (0);
+}
+
+/*
+ * Get an input line.  The returned pointer often (but not always)
+ * points into a stdio buffer.  Fgetline does not alter the text of
+ * the returned line (which is thus not a C string because it will
+ * not necessarily end with '\0'), but does allow callers to modify
+ * it if they wish.  Thus, we set __SMOD in case the caller does.
+ */
+char *
+fgetln(FILE *fp, size_t *lenp)
+{
+	unsigned char *p;
+	size_t len;
+	size_t off;
+
+	/* make sure there is input */
+	if (fp->_r <= 0 && __srefill(fp)) {
+		*lenp = 0;
+		return (NULL);
+	}
+
+	/* look for a newline in the input */
+	if ((p = memchr((void *)fp->_p, '\n', fp->_r)) != NULL) {
+		char *ret;
+
+		/*
+		 * Found one.  Flag buffer as modified to keep fseek from
+		 * `optimising' a backward seek, in case the user stomps on
+		 * the text.
+		 */
+		p++;		/* advance over it */
+		ret = (char *)fp->_p;
+		*lenp = len = p - fp->_p;
+		fp->_flags |= __SMOD;
+		fp->_r -= len;
+		fp->_p = p;
+		return (ret);
+	}
+
+	/*
+	 * We have to copy the current buffered data to the line buffer.
+	 * As a bonus, though, we can leave off the __SMOD.
+	 *
+	 * OPTIMISTIC is length that we (optimistically) expect will
+	 * accommodate the `rest' of the string, on each trip through the
+	 * loop below.
+	 */
+#define OPTIMISTIC 80
+
+	for (len = fp->_r, off = 0;; len += fp->_r) {
+		size_t diff;
+
+		/*
+		 * Make sure there is room for more bytes.  Copy data from
+		 * file buffer to line buffer, refill file and look for
+		 * newline.  The loop stops only when we find a newline.
+		 */
+		if (__slbexpand(fp, len + OPTIMISTIC))
+			goto error;
+		(void)memcpy((void *)(fp->_lb._base + off), (void *)fp->_p,
+		    len - off);
+		off = len;
+		if (__srefill(fp))
+			break;	/* EOF or error: return partial line */
+		if ((p = memchr((void *)fp->_p, '\n', fp->_r)) == NULL)
+			continue;
+
+		/* got it: finish up the line (like code above) */
+		p++;
+		diff = p - fp->_p;
+		len += diff;
+		if (__slbexpand(fp, len))
+			goto error;
+		(void)memcpy((void *)(fp->_lb._base + off), (void *)fp->_p,
+		    diff);
+		fp->_r -= diff;
+		fp->_p = p;
+		break;
+	}
+	*lenp = len;
+#ifdef notdef
+	fp->_lb._base[len] = '\0';
+#endif
+	return ((char *)fp->_lb._base);
+
+error:
+	*lenp = 0;		/* ??? */
+	return (NULL);		/* ??? */
+}
diff --git a/libc/stdio/fgetpos.c b/libc/stdio/fgetpos.c
new file mode 100644
index 0000000..e6188e5
--- /dev/null
+++ b/libc/stdio/fgetpos.c
@@ -0,0 +1,43 @@
+/*	$OpenBSD: fgetpos.c,v 1.6 2005/08/08 08:05:36 espie Exp $ */
+/*-
+ * Copyright (c) 1990, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <stdio.h>
+
+/*
+ * fgetpos: like ftello.
+ */
+int
+fgetpos(FILE *fp, fpos_t *pos)
+{
+	return((*pos = ftello(fp)) == (fpos_t)-1);
+}
diff --git a/libc/stdio/fgets.c b/libc/stdio/fgets.c
new file mode 100644
index 0000000..99bdac9
--- /dev/null
+++ b/libc/stdio/fgets.c
@@ -0,0 +1,97 @@
+/*	$OpenBSD: fgets.c,v 1.10 2005/08/08 08:05:36 espie Exp $ */
+/*-
+ * Copyright (c) 1990, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include "local.h"
+
+/*
+ * Read at most n-1 characters from the given file.
+ * Stop when a newline has been read, or the count runs out.
+ * Return first argument, or NULL if no characters were read.
+ * Do not return NULL if n == 1.
+ */
+char *
+fgets(char *buf, int n, FILE *fp)
+{
+	size_t len;
+	char *s;
+	unsigned char *p, *t;
+
+	if (n <= 0)		/* sanity check */
+		return (NULL);
+
+	_SET_ORIENTATION(fp, -1);
+	s = buf;
+	n--;			/* leave space for NUL */
+	while (n != 0) {
+		/*
+		 * If the buffer is empty, refill it.
+		 */
+		if (fp->_r <= 0) {
+			if (__srefill(fp)) {
+				/* EOF/error: stop with partial or no line */
+				if (s == buf)
+					return (NULL);
+      break;
+  }
+		}
+		len = fp->_r;
+		p = fp->_p;
+  
+		/*
+		 * Scan through at most n bytes of the current buffer,
+		 * looking for '\n'.  If found, copy up to and including
+		 * newline, and stop.  Otherwise, copy entire chunk
+		 * and loop.
+		 */
+		if ((int)len > n)
+			len = n;
+		t = memchr((void *)p, '\n', len);
+		if (t != NULL) {
+			len = ++t - p;
+			fp->_r -= len;
+			fp->_p = t;
+			(void)memcpy((void *)s, (void *)p, len);
+			s[len] = '\0';
+			return (buf);
+		}
+		fp->_r -= len;
+		fp->_p += len;
+		(void)memcpy((void *)s, (void *)p, len);
+		s += len;
+		n -= len;
+	}
+	*s = '\0';
+	return (buf);
+}
diff --git a/libc/stdio/fileext.h b/libc/stdio/fileext.h
new file mode 100644
index 0000000..2d07043
--- /dev/null
+++ b/libc/stdio/fileext.h
@@ -0,0 +1,54 @@
+/*	$OpenBSD: fileext.h,v 1.2 2005/06/17 20:40:32 espie Exp $	*/
+/* $NetBSD: fileext.h,v 1.5 2003/07/18 21:46:41 nathanw Exp $ */
+
+/*-
+ * Copyright (c)2001 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $Citrus$
+ */
+
+/*
+ * file extension
+ */
+struct __sfileext {
+	struct	__sbuf _ub; /* ungetc buffer */
+	struct wchar_io_data _wcio;	/* wide char io status */
+};
+
+#define _EXT(fp) ((struct __sfileext *)((fp)->_ext._base))
+#define _UB(fp) _EXT(fp)->_ub
+
+#define _FILEEXT_INIT(fp) \
+do { \
+	_UB(fp)._base = NULL; \
+	_UB(fp)._size = 0; \
+	WCIO_INIT(fp); \
+} while (0)
+
+#define _FILEEXT_SETUP(f, fext) \
+do { \
+	(f)->_ext._base = (unsigned char *)(fext); \
+	_FILEEXT_INIT(f); \
+} while (0)
diff --git a/libc/stdio/fileno.c b/libc/stdio/fileno.c
new file mode 100644
index 0000000..0fd985b
--- /dev/null
+++ b/libc/stdio/fileno.c
@@ -0,0 +1,45 @@
+/*	$OpenBSD: fileno.c,v 1.5 2005/08/08 08:05:36 espie Exp $ */
+/*-
+ * Copyright (c) 1990, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <stdio.h>
+
+/*
+ * A subroutine version of the macro fileno.
+ */
+#undef fileno
+
+int
+fileno(FILE *fp)
+{
+	return (__sfileno(fp));
+}
diff --git a/libc/stdio/findfp.c b/libc/stdio/findfp.c
new file mode 100644
index 0000000..a55a65d
--- /dev/null
+++ b/libc/stdio/findfp.c
@@ -0,0 +1,181 @@
+/*	$OpenBSD: findfp.c,v 1.9 2005/08/08 08:05:36 espie Exp $ */
+/*-
+ * Copyright (c) 1990, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/param.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include "local.h"
+#include "glue.h"
+
+int	__sdidinit;
+
+#define	NDYNAMIC 10		/* add ten more whenever necessary */
+
+#define	std(flags, file) \
+	{0,0,0,flags,file,{0,0},0,__sF+file,__sclose,__sread,__sseek,__swrite, \
+	 {(unsigned char *)(__sFext+file), 0},NULL,0,{0,0,0},{0},{0,0},0,0}
+/*	 p r w flags file _bf z  cookie      close    read    seek    write
+	 ext */
+
+				/* the usual - (stdin + stdout + stderr) */
+static FILE usual[FOPEN_MAX - 3];
+static struct __sfileext usualext[FOPEN_MAX - 3];
+static struct glue uglue = { 0, FOPEN_MAX - 3, usual };
+
+struct __sfileext __sFext[3];
+FILE __sF[3] = {
+	std(__SRD, STDIN_FILENO),		/* stdin */
+	std(__SWR, STDOUT_FILENO),		/* stdout */
+	std(__SWR|__SNBF, STDERR_FILENO)	/* stderr */
+};
+struct glue __sglue = { &uglue, 3, __sF };
+
+static struct glue *
+moreglue(int n)
+{
+	struct glue *g;
+	FILE *p;
+	struct __sfileext *pext;
+	static FILE empty;
+	char *data;
+
+	data = malloc(sizeof(*g) + ALIGNBYTES + n * sizeof(FILE)
+	    + n * sizeof(struct __sfileext));
+	if (data == NULL)
+		return (NULL);
+	g = (struct glue *)data;
+	p = (FILE *)ALIGN(data + sizeof(*g));
+	pext = (struct __sfileext *)
+	    (ALIGN(data + sizeof(*g)) + n * sizeof(FILE));
+	g->next = NULL;
+	g->niobs = n;
+	g->iobs = p;
+	while (--n >= 0) {
+		*p = empty;
+		_FILEEXT_SETUP(p, pext);
+		p++;
+		pext++;
+	}
+	return (g);
+}
+
+/*
+ * Find a free FILE for fopen et al.
+ */
+FILE *
+__sfp(void)
+{
+	FILE *fp;
+	int n;
+	struct glue *g;
+
+	if (!__sdidinit)
+		__sinit();
+	for (g = &__sglue;; g = g->next) {
+		for (fp = g->iobs, n = g->niobs; --n >= 0; fp++)
+			if (fp->_flags == 0)
+				goto found;
+		if (g->next == NULL && (g->next = moreglue(NDYNAMIC)) == NULL)
+			break;
+	}
+	return (NULL);
+found:
+	fp->_flags = 1;		/* reserve this slot; caller sets real flags */
+	fp->_p = NULL;		/* no current pointer */
+	fp->_w = 0;		/* nothing to read or write */
+	fp->_r = 0;
+	fp->_bf._base = NULL;	/* no buffer */
+	fp->_bf._size = 0;
+	fp->_lbfsize = 0;	/* not line buffered */
+	fp->_file = -1;		/* no file */
+/*	fp->_cookie = <any>; */	/* caller sets cookie, _read/_write etc */
+	fp->_lb._base = NULL;	/* no line buffer */
+	fp->_lb._size = 0;
+	_FILEEXT_INIT(fp);
+	return (fp);
+}
+
+#if 0
+#define getdtablesize()	sysconf(_SC_OPEN_MAX)
+
+/*
+ * XXX.  Force immediate allocation of internal memory.  Not used by stdio,
+ * but documented historically for certain applications.  Bad applications.
+ */
+void
+f_prealloc(void)
+{
+	struct glue *g;
+	int n;
+
+	n = getdtablesize() - FOPEN_MAX + 20;		/* 20 for slop. */
+	for (g = &__sglue; (n -= g->niobs) > 0 && g->next; g = g->next)
+		/* void */;
+	if (n > 0)
+		g->next = moreglue(n);
+}
+#endif
+
+/*
+ * exit() and abort() call _cleanup() through the callback registered
+ * with __atexit_register_cleanup(), set whenever we open or buffer a
+ * file. This chicanery is done so that programs that do not use stdio
+ * need not link it all in.
+ *
+ * The name `_cleanup' is, alas, fairly well known outside stdio.
+ */
+void
+_cleanup(void)
+{
+	/* (void) _fwalk(fclose); */
+	(void) _fwalk(__sflush);		/* `cheating' */
+}
+
+/*
+ * __sinit() is called whenever stdio's internal variables must be set up.
+ */
+void
+__sinit(void)
+{
+	int i;
+
+	for (i = 0; i < FOPEN_MAX - 3; i++) {
+		_FILEEXT_SETUP(usual+i, usualext+i);
+	}
+	/* make sure we clean up on exit */
+	__atexit_register_cleanup(_cleanup); /* conservative */
+	__sdidinit = 1;
+}
diff --git a/libc/stdio/flags.c b/libc/stdio/flags.c
new file mode 100644
index 0000000..dde0447
--- /dev/null
+++ b/libc/stdio/flags.c
@@ -0,0 +1,82 @@
+/*	$OpenBSD: flags.c,v 1.6 2005/08/08 08:05:36 espie Exp $ */
+/*-
+ * Copyright (c) 1990, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/types.h>
+#include <sys/file.h>
+#include <stdio.h>
+#include <errno.h>
+#include <fcntl.h>
+
+/*
+ * Return the (stdio) flags for a given mode.  Store the flags
+ * to be passed to an open() syscall through *optr.
+ * Return 0 on error.
+ */
+int
+__sflags(const char *mode, int *optr)
+{
+	int ret, m, o;
+
+	switch (*mode++) {
+
+	case 'r':	/* open for reading */
+		ret = __SRD;
+		m = O_RDONLY;
+		o = 0;
+		break;
+
+	case 'w':	/* open for writing */
+		ret = __SWR;
+		m = O_WRONLY;
+		o = O_CREAT | O_TRUNC;
+		break;
+
+	case 'a':	/* open for appending */
+		ret = __SWR;
+		m = O_WRONLY;
+		o = O_CREAT | O_APPEND;
+		break;
+
+	default:	/* illegal mode */
+		errno = EINVAL;
+		return (0);
+	}
+
+	/* [rwa]\+ or [rwa]b\+ means read and write */
+	if (*mode == '+' || (*mode == 'b' && mode[1] == '+')) {
+		ret = __SRW;
+		m = O_RDWR;
+	}
+	*optr = m | o;
+	return (ret);
+}
diff --git a/libc/stdio/floatio.h b/libc/stdio/floatio.h
new file mode 100644
index 0000000..20f9801
--- /dev/null
+++ b/libc/stdio/floatio.h
@@ -0,0 +1,42 @@
+/*	$OpenBSD: floatio.h,v 1.3 2003/06/02 20:18:37 millert Exp $	*/
+
+/*-
+ * Copyright (c) 1990, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * Floating point scanf/printf (input/output) definitions.
+ */
+
+/* 11-bit exponent (VAX G floating point) is 308 decimal digits */
+#define	MAXEXP		308
+/* 128 bit fraction takes up 39 decimal digits; max reasonable precision */
+#define	MAXFRACT	39
diff --git a/libc/stdio/fopen.c b/libc/stdio/fopen.c
new file mode 100644
index 0000000..de15dc3
--- /dev/null
+++ b/libc/stdio/fopen.c
@@ -0,0 +1,76 @@
+/*	$OpenBSD: fopen.c,v 1.5 2005/08/08 08:05:36 espie Exp $ */
+/*-
+ * Copyright (c) 1990, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <errno.h>
+#include "local.h"
+#include <linux/stat.h>
+
+FILE *
+fopen(const char *file, const char *mode)
+{
+	FILE *fp;
+	int f;
+	int flags, oflags;
+
+	if ((flags = __sflags(mode, &oflags)) == 0)
+		return (NULL);
+	if ((fp = __sfp()) == NULL)
+		return (NULL);
+	if ((f = open(file, oflags, DEFFILEMODE)) < 0) {
+		fp->_flags = 0;			/* release */
+		return (NULL);
+  }
+	fp->_file = f;
+	fp->_flags = flags;
+	fp->_cookie = fp;
+	fp->_read = __sread;
+	fp->_write = __swrite;
+	fp->_seek = __sseek;
+	fp->_close = __sclose;
+
+	/*
+	 * When opening in append mode, even though we use O_APPEND,
+	 * we need to seek to the end so that ftell() gets the right
+	 * answer.  If the user then alters the seek pointer, or
+	 * the file extends, this will fail, but there is not much
+	 * we can do about this.  (We could set __SAPP and check in
+	 * fseek and ftell.)
+	 */
+	if (oflags & O_APPEND)
+		(void) __sseek((void *)fp, (fpos_t)0, SEEK_END);
+	return (fp);
+}
diff --git a/libc/stdio/fprintf.c b/libc/stdio/fprintf.c
new file mode 100644
index 0000000..809d8db
--- /dev/null
+++ b/libc/stdio/fprintf.c
@@ -0,0 +1,47 @@
+/*	$OpenBSD: fprintf.c,v 1.6 2005/08/08 08:05:36 espie Exp $ */
+/*-
+ * Copyright (c) 1990, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <stdio.h>
+#include <stdarg.h>
+
+int
+fprintf(FILE *fp, const char *fmt, ...)
+{
+	int ret;
+  va_list ap;
+
+	va_start(ap, fmt);
+	ret = vfprintf(fp, fmt, ap);
+  va_end(ap);
+	return (ret);
+}
diff --git a/libc/stdio/fpurge.c b/libc/stdio/fpurge.c
new file mode 100644
index 0000000..fa0213a
--- /dev/null
+++ b/libc/stdio/fpurge.c
@@ -0,0 +1,58 @@
+/*	$OpenBSD: fpurge.c,v 1.6 2005/08/08 08:05:36 espie Exp $ */
+/*-
+ * Copyright (c) 1990, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include "local.h"
+
+/*
+ * fpurge: like fflush, but without writing anything: leave the
+ * given FILE's buffer empty.
+ */
+int
+fpurge(FILE *fp)
+{
+	if (!fp->_flags) {
+		errno = EBADF;
+		return(EOF);
+	}
+
+	if (HASUB(fp))
+		FREEUB(fp);
+	WCIO_FREE(fp);
+	fp->_p = fp->_bf._base;
+	fp->_r = 0;
+	fp->_w = fp->_flags & (__SLBF|__SNBF) ? 0 : fp->_bf._size;
+	return (0);
+}
diff --git a/libc/stdio/fputc.c b/libc/stdio/fputc.c
new file mode 100644
index 0000000..2a6e7b7
--- /dev/null
+++ b/libc/stdio/fputc.c
@@ -0,0 +1,46 @@
+/*	$OpenBSD: fputc.c,v 1.7 2005/08/08 08:05:36 espie Exp $ */
+/*-
+ * Copyright (c) 1990, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <stdio.h>
+#include <errno.h>
+#include "local.h"
+
+int
+fputc(int c, FILE *fp)
+{
+	if (cantwrite(fp)) {
+		errno = EBADF;
+		return (EOF);
+	}
+	return (putc(c, fp));
+}
diff --git a/libc/stdio/fputs.c b/libc/stdio/fputs.c
new file mode 100644
index 0000000..7434ca8
--- /dev/null
+++ b/libc/stdio/fputs.c
@@ -0,0 +1,54 @@
+/*	$OpenBSD: fputs.c,v 1.7 2005/08/08 08:05:36 espie Exp $ */
+/*-
+ * Copyright (c) 1990, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include "local.h"
+#include "fvwrite.h"
+
+/*
+ * Write the given string to the given file.
+ */
+int
+fputs(const char *s, FILE *fp)
+{
+	struct __suio uio;
+	struct __siov iov;
+
+	iov.iov_base = (void *)s;
+	iov.iov_len = uio.uio_resid = strlen(s);
+	uio.uio_iov = &iov;
+	uio.uio_iovcnt = 1;
+	_SET_ORIENTATION(fp, -1);
+	return (__sfvwrite(fp, &uio));
+}
diff --git a/libc/stdio/fread.c b/libc/stdio/fread.c
new file mode 100644
index 0000000..9f9977f
--- /dev/null
+++ b/libc/stdio/fread.c
@@ -0,0 +1,158 @@
+/*	$OpenBSD: fread.c,v 1.6 2005/08/08 08:05:36 espie Exp $ */
+/*-
+ * Copyright (c) 1990, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include "local.h"
+
+static int
+lflush(FILE *fp)
+{
+
+    if ((fp->_flags & (__SLBF|__SWR)) == (__SLBF|__SWR))
+        return (__sflush(fp));
+    return (0);
+}
+
+size_t
+fread(void *buf, size_t size, size_t count, FILE *fp)
+{
+	size_t resid;
+	char *p;
+	int r;
+	size_t total;
+
+	/*
+	 * The ANSI standard requires a return value of 0 for a count
+	 * or a size of 0.  Peculiarily, it imposes no such requirements
+	 * on fwrite; it only requires fread to be broken.
+	 */
+	if ((resid = count * size) == 0)
+		return (0);
+	if (fp->_r < 0)
+		fp->_r = 0;
+	total = resid;
+	p = buf;
+
+#if 1  /* BIONIC: optimize unbuffered reads */
+    if (fp->_flags & __SNBF && fp->_ur == 0)
+    {
+       /* the following comes mainly from __srefill(), with slight
+        * modifications
+        */
+
+        /* make sure stdio is set up */
+        if (!__sdidinit)
+            __sinit();
+
+        fp->_r = 0;     /* largely a convenience for callers */
+
+        /* SysV does not make this test; take it out for compatibility */
+        if (fp->_flags & __SEOF)
+            return (EOF);
+
+        /* if not already reading, have to be reading and writing */
+        if ((fp->_flags & __SRD) == 0) {
+            if ((fp->_flags & __SRW) == 0) {
+                errno = EBADF;
+                fp->_flags |= __SERR;
+                return (EOF);
+            }
+            /* switch to reading */
+            if (fp->_flags & __SWR) {
+                if (__sflush(fp))
+                    return (EOF);
+                fp->_flags &= ~__SWR;
+                fp->_w = 0;
+                fp->_lbfsize = 0;
+            }
+            fp->_flags |= __SRD;
+        } else {
+           /*
+            * We were reading.  If there is an ungetc buffer,
+            * we must have been reading from that.  Drop it,
+            * restoring the previous buffer (if any).  If there
+            * is anything in that buffer, return.
+            */
+            if (HASUB(fp)) {
+                FREEUB(fp);
+            }
+        }
+
+       /*
+        * Before reading from a line buffered or unbuffered file,
+        * flush all line buffered output files, per the ANSI C
+        * standard.
+        */
+
+        if (fp->_flags & (__SLBF|__SNBF))
+            (void) _fwalk(lflush);
+
+        while (resid > 0) {
+            int   len = (*fp->_read)(fp->_cookie, p, resid );
+            fp->_flags &= ~__SMOD;
+            if (len <= 0) {
+                if (len == 0)
+                    fp->_flags |= __SEOF;
+                else {
+                    fp->_flags |= __SERR;
+                }
+                return ((total - resid) / size);
+            }
+            p     += len;
+            resid -= len;
+        }
+        return (count);
+    }
+    else
+#endif
+    {
+        while (resid > (size_t)(r = fp->_r)) {
+            (void)memcpy((void *)p, (void *)fp->_p, (size_t)r);
+            fp->_p += r;
+            /* fp->_r = 0 ... done in __srefill */
+            p += r;
+            resid -= r;
+            if (__srefill(fp)) {
+                /* no more input: return partial result */
+                return ((total - resid) / size);
+            }
+        }
+    }
+
+	(void)memcpy((void *)p, (void *)fp->_p, resid);
+	fp->_r -= resid;
+	fp->_p += resid;
+	return (count);
+}
diff --git a/libc/stdio/freopen.c b/libc/stdio/freopen.c
new file mode 100644
index 0000000..414d810
--- /dev/null
+++ b/libc/stdio/freopen.c
@@ -0,0 +1,158 @@
+/*	$OpenBSD: freopen.c,v 1.9 2005/08/08 08:05:36 espie Exp $ */
+/*-
+ * Copyright (c) 1990, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include "local.h"
+
+/* 
+ * Re-direct an existing, open (probably) file to some other file. 
+ * ANSI is written such that the original file gets closed if at
+ * all possible, no matter what.
+ */
+FILE *
+freopen(const char *file, const char *mode, FILE *fp)
+{
+	int f;
+	int flags, isopen, oflags, sverrno, wantfd;
+
+	if ((flags = __sflags(mode, &oflags)) == 0) {
+		(void) fclose(fp);
+		return (NULL);
+	}
+
+	if (!__sdidinit)
+		__sinit();
+
+	/*
+	 * There are actually programs that depend on being able to "freopen"
+	 * descriptors that weren't originally open.  Keep this from breaking.
+	 * Remember whether the stream was open to begin with, and which file
+	 * descriptor (if any) was associated with it.  If it was attached to
+	 * a descriptor, defer closing it; freopen("/dev/stdin", "r", stdin)
+	 * should work.  This is unnecessary if it was not a Unix file.
+	 */
+	if (fp->_flags == 0) {
+		fp->_flags = __SEOF;	/* hold on to it */
+		isopen = 0;
+		wantfd = -1;
+	} else {
+		/* flush the stream; ANSI doesn't require this. */
+		if (fp->_flags & __SWR)
+			(void) __sflush(fp);
+		/* if close is NULL, closing is a no-op, hence pointless */
+		isopen = fp->_close != NULL;
+		if ((wantfd = fp->_file) < 0 && isopen) {
+			(void) (*fp->_close)(fp->_cookie);
+			isopen = 0;
+		}
+	}
+
+	/* Get a new descriptor to refer to the new file. */
+	f = open(file, oflags, DEFFILEMODE);
+	if (f < 0 && isopen) {
+		/* If out of fd's close the old one and try again. */
+		if (errno == ENFILE || errno == EMFILE) {
+			(void) (*fp->_close)(fp->_cookie);
+			isopen = 0;
+			f = open(file, oflags, DEFFILEMODE);
+		}
+	}
+	sverrno = errno;
+
+	/*
+	 * Finish closing fp.  Even if the open succeeded above, we cannot
+	 * keep fp->_base: it may be the wrong size.  This loses the effect
+	 * of any setbuffer calls, but stdio has always done this before.
+	 */
+	if (isopen && f != wantfd)
+		(void) (*fp->_close)(fp->_cookie);
+	if (fp->_flags & __SMBF)
+		free((char *)fp->_bf._base);
+	fp->_w = 0;
+	fp->_r = 0;
+	fp->_p = NULL;
+	fp->_bf._base = NULL;
+	fp->_bf._size = 0;
+	fp->_lbfsize = 0;
+	if (HASUB(fp))
+		FREEUB(fp);
+	_UB(fp)._size = 0;
+	WCIO_FREE(fp);
+	if (HASLB(fp))
+		FREELB(fp);
+	fp->_lb._size = 0;
+
+	if (f < 0) {			/* did not get it after all */
+		fp->_flags = 0;		/* set it free */
+		errno = sverrno;	/* restore in case _close clobbered */
+		return (NULL);
+	}
+
+	/*
+	 * If reopening something that was open before on a real file, try
+	 * to maintain the descriptor.  Various C library routines (perror)
+	 * assume stderr is always fd STDERR_FILENO, even if being freopen'd.
+	 */
+	if (wantfd >= 0 && f != wantfd) {
+		if (dup2(f, wantfd) >= 0) {
+			(void) close(f);
+			f = wantfd;
+		}
+	}
+
+	fp->_flags = flags;
+	fp->_file = f;
+	fp->_cookie = fp;
+	fp->_read = __sread;
+	fp->_write = __swrite;
+	fp->_seek = __sseek;
+	fp->_close = __sclose;
+
+	/*
+	 * When opening in append mode, even though we use O_APPEND,
+	 * we need to seek to the end so that ftell() gets the right
+	 * answer.  If the user then alters the seek pointer, or
+	 * the file extends, this will fail, but there is not much
+	 * we can do about this.  (We could set __SAPP and check in
+	 * fseek and ftell.)
+	 */
+	if (oflags & O_APPEND)
+		(void) __sseek((void *)fp, (fpos_t)0, SEEK_END);
+	return (fp);
+}
diff --git a/libc/stdio/fscanf.c b/libc/stdio/fscanf.c
new file mode 100644
index 0000000..2f3fceb
--- /dev/null
+++ b/libc/stdio/fscanf.c
@@ -0,0 +1,47 @@
+/*	$OpenBSD: fscanf.c,v 1.9 2005/10/10 17:37:44 espie Exp $ */
+/*-
+ * Copyright (c) 1990, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <stdio.h>
+#include <stdarg.h>
+
+int
+fscanf(FILE *fp, const char *fmt, ...)
+{
+	int ret;
+	va_list ap;
+
+	va_start(ap, fmt);
+	ret = vfscanf(fp, fmt, ap);
+	va_end(ap);
+	return (ret);
+}
diff --git a/libc/stdio/fseek.c b/libc/stdio/fseek.c
new file mode 100644
index 0000000..0ac25e2
--- /dev/null
+++ b/libc/stdio/fseek.c
@@ -0,0 +1,252 @@
+/*	$OpenBSD: fseek.c,v 1.7 2005/08/08 08:05:36 espie Exp $ */
+/*-
+ * Copyright (c) 1990, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include "local.h"
+
+#define	POS_ERR	(-(fpos_t)1)
+
+/*
+ * Seek the given file to the given offset.
+ * `Whence' must be one of the three SEEK_* macros.
+ */
+int
+fseeko(FILE *fp, off_t offset, int whence)
+{
+	fpos_t (*seekfn)(void *, fpos_t, int);
+	fpos_t target, curoff;
+	size_t n;
+	struct stat st;
+	int havepos;
+
+	/* make sure stdio is set up */
+	if (!__sdidinit)
+		__sinit();
+
+	/*
+	 * Have to be able to seek.
+	 */
+	if ((seekfn = fp->_seek) == NULL) {
+		errno = ESPIPE;			/* historic practice */
+		return (EOF);
+	}
+
+	/*
+	 * Change any SEEK_CUR to SEEK_SET, and check `whence' argument.
+	 * After this, whence is either SEEK_SET or SEEK_END.
+	 */
+	switch (whence) {
+
+	case SEEK_CUR:
+		/*
+		 * In order to seek relative to the current stream offset,
+		 * we have to first find the current stream offset a la
+		 * ftell (see ftell for details).
+		 */
+		__sflush(fp);	/* may adjust seek offset on append stream */
+		if (fp->_flags & __SOFF)
+			curoff = fp->_offset;
+		else {
+			curoff = (*seekfn)(fp->_cookie, (fpos_t)0, SEEK_CUR);
+			if (curoff == (fpos_t)-1)
+				return (EOF);
+		}
+		if (fp->_flags & __SRD) {
+			curoff -= fp->_r;
+			if (HASUB(fp))
+				curoff -= fp->_ur;
+		} else if (fp->_flags & __SWR && fp->_p != NULL)
+			curoff += fp->_p - fp->_bf._base;
+
+		offset += curoff;
+		whence = SEEK_SET;
+		havepos = 1;
+		break;
+
+	case SEEK_SET:
+	case SEEK_END:
+		curoff = 0;		/* XXX just to keep gcc quiet */
+		havepos = 0;
+		break;
+
+	default:
+		errno = EINVAL;
+		return (EOF);
+	}
+
+	/*
+	 * Can only optimise if:
+	 *	reading (and not reading-and-writing);
+	 *	not unbuffered; and
+	 *	this is a `regular' Unix file (and hence seekfn==__sseek).
+	 * We must check __NBF first, because it is possible to have __NBF
+	 * and __SOPT both set.
+	 */
+	if (fp->_bf._base == NULL)
+		__smakebuf(fp);
+	if (fp->_flags & (__SWR | __SRW | __SNBF | __SNPT))
+		goto dumb;
+	if ((fp->_flags & __SOPT) == 0) {
+		if (seekfn != __sseek ||
+		    fp->_file < 0 || fstat(fp->_file, &st) ||
+		    (st.st_mode & S_IFMT) != S_IFREG) {
+			fp->_flags |= __SNPT;
+			goto dumb;
+		}
+		fp->_blksize = st.st_blksize;
+		fp->_flags |= __SOPT;
+	}
+
+	/*
+	 * We are reading; we can try to optimise.
+	 * Figure out where we are going and where we are now.
+	 */
+	if (whence == SEEK_SET)
+		target = offset;
+	else {
+		if (fstat(fp->_file, &st))
+			goto dumb;
+		target = st.st_size + offset;
+	}
+
+	if (!havepos) {
+		if (fp->_flags & __SOFF)
+			curoff = fp->_offset;
+		else {
+			curoff = (*seekfn)(fp->_cookie, (fpos_t)0, SEEK_CUR);
+			if (curoff == POS_ERR)
+				goto dumb;
+		}
+		curoff -= fp->_r;
+		if (HASUB(fp))
+			curoff -= fp->_ur;
+	}
+
+	/*
+	 * Compute the number of bytes in the input buffer (pretending
+	 * that any ungetc() input has been discarded).  Adjust current
+	 * offset backwards by this count so that it represents the
+	 * file offset for the first byte in the current input buffer.
+	 */
+	if (HASUB(fp)) {
+		curoff += fp->_r;	/* kill off ungetc */
+		n = fp->_up - fp->_bf._base;
+		curoff -= n;
+		n += fp->_ur;
+	} else {
+		n = fp->_p - fp->_bf._base;
+		curoff -= n;
+		n += fp->_r;
+	}
+
+	/*
+	 * If the target offset is within the current buffer,
+	 * simply adjust the pointers, clear EOF, undo ungetc(),
+	 * and return.  (If the buffer was modified, we have to
+	 * skip this; see fgetln.c.)
+	 */
+	if ((fp->_flags & __SMOD) == 0 &&
+	    target >= curoff && target < (fpos_t)(curoff + n)) {
+		int o = target - curoff;
+
+		fp->_p = fp->_bf._base + o;
+		fp->_r = n - o;
+		if (HASUB(fp))
+			FREEUB(fp);
+		fp->_flags &= ~__SEOF;
+		return (0);
+	}
+
+	/*
+	 * The place we want to get to is not within the current buffer,
+	 * but we can still be kind to the kernel copyout mechanism.
+	 * By aligning the file offset to a block boundary, we can let
+	 * the kernel use the VM hardware to map pages instead of
+	 * copying bytes laboriously.  Using a block boundary also
+	 * ensures that we only read one block, rather than two.
+	 */
+	curoff = target & ~(fp->_blksize - 1);
+	if ((*seekfn)(fp->_cookie, curoff, SEEK_SET) == POS_ERR)
+		goto dumb;
+	fp->_r = 0;
+ 	fp->_p = fp->_bf._base;
+	if (HASUB(fp))
+		FREEUB(fp);
+	fp->_flags &= ~__SEOF;
+	n = target - curoff;
+	if (n) {
+		if (__srefill(fp) || (size_t)fp->_r < n)
+			goto dumb;
+		fp->_p += n;
+		fp->_r -= n;
+	}
+	return (0);
+
+	/*
+	 * We get here if we cannot optimise the seek ... just
+	 * do it.  Allow the seek function to change fp->_bf._base.
+	 */
+dumb:
+	if (__sflush(fp) ||
+	    (*seekfn)(fp->_cookie, (fpos_t)offset, whence) == POS_ERR) {
+		return (EOF);
+	}
+	/* success: clear EOF indicator and discard ungetc() data */
+	if (HASUB(fp))
+		FREEUB(fp);
+	fp->_p = fp->_bf._base;
+	fp->_r = 0;
+	/* fp->_w = 0; */	/* unnecessary (I think...) */
+	fp->_flags &= ~__SEOF;
+	return (0);
+}
+
+/*
+ * fseek()'s offset is a long and sizeof(off_t) != sizeof(long) on all arches
+ */
+#if defined(__alpha__) && defined(__indr_reference)
+__indr_reference(fseeko, fseek);
+#else
+int
+fseek(FILE *fp, long offset, int whence)
+{
+	off_t off = offset;
+
+	return(fseeko(fp, off, whence));
+}
+#endif
diff --git a/libc/stdio/fsetpos.c b/libc/stdio/fsetpos.c
new file mode 100644
index 0000000..9624fe5
--- /dev/null
+++ b/libc/stdio/fsetpos.c
@@ -0,0 +1,43 @@
+/*	$OpenBSD: fsetpos.c,v 1.6 2005/08/08 08:05:36 espie Exp $ */
+/*-
+ * Copyright (c) 1990, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <stdio.h>
+
+/*
+ * fsetpos: like fseeko.
+ */
+int
+fsetpos(FILE *iop, const fpos_t *pos)
+{
+	return (fseeko(iop, (off_t)*pos, SEEK_SET));
+}
diff --git a/libc/stdio/ftell.c b/libc/stdio/ftell.c
new file mode 100644
index 0000000..b7d449e
--- /dev/null
+++ b/libc/stdio/ftell.c
@@ -0,0 +1,97 @@
+/*	$OpenBSD: ftell.c,v 1.6 2005/08/08 08:05:36 espie Exp $ */
+/*-
+ * Copyright (c) 1990, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <stdio.h>
+#include <errno.h>
+#include "local.h"
+
+/*
+ * ftello: return current offset.
+ */
+off_t
+ftello(FILE *fp)
+{
+	fpos_t pos;
+
+	if (fp->_seek == NULL) {
+		errno = ESPIPE;			/* historic practice */
+		return ((off_t)-1);
+	}
+
+	/*
+	 * Find offset of underlying I/O object, then
+	 * adjust for buffered bytes.
+	 */
+	__sflush(fp);		/* may adjust seek offset on append stream */
+	if (fp->_flags & __SOFF)
+		pos = fp->_offset;
+	else {
+		pos = (*fp->_seek)(fp->_cookie, (fpos_t)0, SEEK_CUR);
+		if (pos == -1L)
+			return (pos);
+	}
+	if (fp->_flags & __SRD) {
+		/*
+		 * Reading.  Any unread characters (including
+		 * those from ungetc) cause the position to be
+		 * smaller than that in the underlying object.
+		 */
+		pos -= fp->_r;
+		if (HASUB(fp))
+			pos -= fp->_ur;
+	} else if (fp->_flags & __SWR && fp->_p != NULL) {
+		/*
+		 * Writing.  Any buffered characters cause the
+		 * position to be greater than that in the
+		 * underlying object.
+		 */
+		pos += fp->_p - fp->_bf._base;
+	}
+	return (pos);
+}
+
+/*
+ * ftell() returns a long and sizeof(off_t) != sizeof(long) on all arches
+ */
+#if defined(__alpha__) && defined(__indr_reference)
+__indr_reference(ftello, ftell);
+#else
+long
+ftell(FILE *fp)
+{
+	long pos;
+
+	pos = (long)ftello(fp);
+	return(pos);
+}
+#endif
diff --git a/libc/stdio/funopen.c b/libc/stdio/funopen.c
new file mode 100644
index 0000000..b85ee96
--- /dev/null
+++ b/libc/stdio/funopen.c
@@ -0,0 +1,68 @@
+/*	$OpenBSD: funopen.c,v 1.8 2005/08/08 08:05:36 espie Exp $ */
+/*-
+ * Copyright (c) 1990, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <stdio.h>
+#include <errno.h>
+#include "local.h"
+
+FILE *
+funopen(const void *cookie, int (*readfn)(void *, char *, int),
+	int (*writefn)(void *, const char *, int),
+	fpos_t (*seekfn)(void *, fpos_t, int), int (*closefn)(void *))
+{
+	FILE *fp;
+	int flags;
+
+	if (readfn == NULL) {
+		if (writefn == NULL) {		/* illegal */
+			errno = EINVAL;
+			return (NULL);
+		} else
+			flags = __SWR;		/* write only */
+	} else {
+		if (writefn == NULL)
+			flags = __SRD;		/* read only */
+		else
+			flags = __SRW;		/* read-write */
+	}
+	if ((fp = __sfp()) == NULL)
+		return (NULL);
+	fp->_flags = flags;
+	fp->_file = -1;
+	fp->_cookie = (void *)cookie;		/* SAFE: cookie not modified */
+	fp->_read = readfn;
+	fp->_write = writefn;
+	fp->_seek = seekfn;
+	fp->_close = closefn;
+	return (fp);
+}
diff --git a/libc/stdio/fvwrite.c b/libc/stdio/fvwrite.c
new file mode 100644
index 0000000..bbea672
--- /dev/null
+++ b/libc/stdio/fvwrite.c
@@ -0,0 +1,208 @@
+/*	$OpenBSD: fvwrite.c,v 1.14 2005/08/08 08:05:36 espie Exp $ */
+/*-
+ * Copyright (c) 1990, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include "local.h"
+#include "fvwrite.h"
+
+/*
+ * Write some memory regions.  Return zero on success, EOF on error.
+ *
+ * This routine is large and unsightly, but most of the ugliness due
+ * to the three different kinds of output buffering is handled here.
+ */
+int
+__sfvwrite(FILE *fp, struct __suio *uio)
+{
+	size_t len;
+	char *p;
+	struct __siov *iov;
+	int w, s;
+	char *nl;
+	int nlknown, nldist;
+
+	if ((len = uio->uio_resid) == 0)
+		return (0);
+	/* make sure we can write */
+	if (cantwrite(fp)) {
+		errno = EBADF;
+		return (EOF);
+	}
+
+#define	MIN(a, b) ((a) < (b) ? (a) : (b))
+#define	COPY(n)	  (void)memcpy((void *)fp->_p, (void *)p, (size_t)(n))
+
+	iov = uio->uio_iov;
+	p = iov->iov_base;
+	len = iov->iov_len;
+	iov++;
+#define GETIOV(extra_work) \
+	while (len == 0) { \
+		extra_work; \
+		p = iov->iov_base; \
+		len = iov->iov_len; \
+		iov++; \
+	}
+	if (fp->_flags & __SNBF) {
+		/*
+		 * Unbuffered: write up to BUFSIZ bytes at a time.
+		 */
+		do {
+			GETIOV(;);
+#if 1  /* BIONIC: don't limit to 1KB writes */
+            w = (*fp->_write)(fp->_cookie, p, len);
+#else
+			w = (*fp->_write)(fp->_cookie, p, MIN(len, BUFSIZ2));
+#endif
+			if (w <= 0)
+				goto err;
+			p += w;
+			len -= w;
+		} while ((uio->uio_resid -= w) != 0);
+	} else if ((fp->_flags & __SLBF) == 0) {
+		/*
+		 * Fully buffered: fill partially full buffer, if any,
+		 * and then flush.  If there is no partial buffer, write
+		 * one _bf._size byte chunk directly (without copying).
+		 *
+		 * String output is a special case: write as many bytes
+		 * as fit, but pretend we wrote everything.  This makes
+		 * snprintf() return the number of bytes needed, rather
+		 * than the number used, and avoids its write function
+		 * (so that the write function can be invalid).
+		 */
+		do {
+			GETIOV(;);
+			if ((fp->_flags & (__SALC | __SSTR)) ==
+			    (__SALC | __SSTR) && fp->_w < (int)len) {
+				size_t blen = fp->_p - fp->_bf._base;
+				unsigned char *_base;
+				int _size;
+
+				/* Allocate space exponentially. */
+				_size = fp->_bf._size;
+				do {
+					_size = (_size << 1) + 1;
+				} while (_size < (int)(blen + len));
+				_base = realloc(fp->_bf._base, _size + 1);
+				if (_base == NULL)
+					goto err;
+				fp->_w += _size - fp->_bf._size;
+				fp->_bf._base = _base;
+				fp->_bf._size = _size;
+				fp->_p = _base + blen;
+			}
+			w = fp->_w;
+			if (fp->_flags & __SSTR) {
+				if ((int)len < w)
+					w = len;
+				COPY(w);	/* copy MIN(fp->_w,len), */
+				fp->_w -= w;
+				fp->_p += w;
+				w = len;	/* but pretend copied all */
+			} else if (fp->_p > fp->_bf._base && (int)len > w) {
+				/* fill and flush */
+				COPY(w);
+				/* fp->_w -= w; */ /* unneeded */
+				fp->_p += w;
+				if (fflush(fp))
+					goto err;
+			} else if ((int)len >= (w = fp->_bf._size)) {
+				/* write directly */
+				w = (*fp->_write)(fp->_cookie, p, w);
+				if (w <= 0)
+					goto err;
+			} else {
+				/* fill and done */
+				w = len;
+				COPY(w);
+				fp->_w -= w;
+				fp->_p += w;
+			}
+			p += w;
+			len -= w;
+		} while ((uio->uio_resid -= w) != 0);
+	} else {
+		/*
+		 * Line buffered: like fully buffered, but we
+		 * must check for newlines.  Compute the distance
+		 * to the first newline (including the newline),
+		 * or `infinity' if there is none, then pretend
+		 * that the amount to write is MIN(len,nldist).
+		 */
+		nlknown = 0;
+		nldist = 0;	/* XXX just to keep gcc happy */
+		do {
+			GETIOV(nlknown = 0);
+			if (!nlknown) {
+				nl = memchr((void *)p, '\n', len);
+				nldist = nl ? nl + 1 - p : (int)len + 1;
+				nlknown = 1;
+			}
+			s = MIN((int)len, nldist);
+			w = fp->_w + fp->_bf._size;
+			if (fp->_p > fp->_bf._base && s > w) {
+				COPY(w);
+				/* fp->_w -= w; */
+				fp->_p += w;
+				if (fflush(fp))
+					goto err;
+			} else if (s >= (w = fp->_bf._size)) {
+				w = (*fp->_write)(fp->_cookie, p, w);
+				if (w <= 0)
+				 	goto err;
+			} else {
+				w = s;
+				COPY(w);
+				fp->_w -= w;
+				fp->_p += w;
+			}
+			if ((nldist -= w) == 0) {
+				/* copied the newline: flush and forget */
+				if (fflush(fp))
+					goto err;
+				nlknown = 0;
+			}
+			p += w;
+			len -= w;
+		} while ((uio->uio_resid -= w) != 0);
+	}
+	return (0);
+
+err:
+	fp->_flags |= __SERR;
+	return (EOF);
+}
diff --git a/libc/stdio/fvwrite.h b/libc/stdio/fvwrite.h
new file mode 100644
index 0000000..2344e42
--- /dev/null
+++ b/libc/stdio/fvwrite.h
@@ -0,0 +1,48 @@
+/*	$OpenBSD: fvwrite.h,v 1.5 2003/06/02 20:18:37 millert Exp $	*/
+
+/*-
+ * Copyright (c) 1990, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * I/O descriptors for __sfvwrite().
+ */
+struct __siov {
+	void	*iov_base;
+	size_t	iov_len;
+};
+struct __suio {
+	struct	__siov *uio_iov;
+	int	uio_iovcnt;
+	int	uio_resid;
+};
+
+extern int __sfvwrite(FILE *, struct __suio *);
diff --git a/libc/stdio/fwalk.c b/libc/stdio/fwalk.c
new file mode 100644
index 0000000..5606cf1
--- /dev/null
+++ b/libc/stdio/fwalk.c
@@ -0,0 +1,52 @@
+/*	$OpenBSD: fwalk.c,v 1.7 2005/08/08 08:05:36 espie Exp $ */
+/*-
+ * Copyright (c) 1990, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <errno.h>
+#include <stdio.h>
+#include "local.h"
+#include "glue.h"
+
+int
+_fwalk(int (*function)(FILE *))
+{
+	FILE *fp;
+	int n, ret;
+	struct glue *g;
+
+	ret = 0;
+	for (g = &__sglue; g != NULL; g = g->next)
+		for (fp = g->iobs, n = g->niobs; --n >= 0; fp++)
+			if (fp->_flags != 0)
+				ret |= (*function)(fp);
+	return (ret);
+}
diff --git a/libc/stdio/fwrite.c b/libc/stdio/fwrite.c
new file mode 100644
index 0000000..8a508dc
--- /dev/null
+++ b/libc/stdio/fwrite.c
@@ -0,0 +1,62 @@
+/*	$OpenBSD: fwrite.c,v 1.5 2005/08/08 08:05:36 espie Exp $ */
+/*-
+ * Copyright (c) 1990, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <stdio.h>
+#include "local.h"
+#include "fvwrite.h"
+
+/*
+ * Write `count' objects (each size `size') from memory to the given file.
+ * Return the number of whole objects written.
+ */
+size_t
+fwrite(const void *buf, size_t size, size_t count, FILE *fp)
+{
+	size_t n;
+	struct __suio uio;
+	struct __siov iov;
+
+	iov.iov_base = (void *)buf;
+	uio.uio_resid = iov.iov_len = n = count * size;
+	uio.uio_iov = &iov;
+	uio.uio_iovcnt = 1;
+
+	/*
+	 * The usual case is success (__sfvwrite returns 0);
+	 * skip the divide if this happens, since divides are
+	 * generally slow and since this occurs whenever size==0.
+	 */
+	if (__sfvwrite(fp, &uio) == 0)
+		return (count);
+	return ((n - uio.uio_resid) / size);
+}
diff --git a/libc/stdio/getc.c b/libc/stdio/getc.c
new file mode 100644
index 0000000..cdd5722
--- /dev/null
+++ b/libc/stdio/getc.c
@@ -0,0 +1,61 @@
+/*	$OpenBSD: getc.c,v 1.6 2005/08/08 08:05:36 espie Exp $ */
+/*-
+ * Copyright (c) 1990, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <stdio.h>
+
+/*
+ * A subroutine version of the macro getc_unlocked.
+ */
+#undef getc_unlocked
+
+int
+getc_unlocked(FILE *fp)
+{
+	return (__sgetc(fp));
+}
+
+/*
+ * A subroutine version of the macro getc.
+ */
+#undef getc
+
+int
+getc(FILE *fp)
+{
+	int c;
+
+	flockfile(fp);
+	c = __sgetc(fp);
+	funlockfile(fp);
+	return (c);
+}
diff --git a/libc/stdio/getchar.c b/libc/stdio/getchar.c
new file mode 100644
index 0000000..550817d
--- /dev/null
+++ b/libc/stdio/getchar.c
@@ -0,0 +1,58 @@
+/*	$OpenBSD: getchar.c,v 1.7 2005/08/08 08:05:36 espie Exp $ */
+/*-
+ * Copyright (c) 1990, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <stdio.h>
+
+/*
+ * A subroutine version of the macro getchar_unlocked.
+ */
+#undef getchar_unlocked
+
+int
+getchar_unlocked(void)
+{
+	return (getc_unlocked(stdin));
+}
+
+
+/*
+ * A subroutine version of the macro getchar.
+ */
+
+#undef getchar
+
+int
+getchar(void)
+{
+	return (getc(stdin));
+}
diff --git a/libc/stdio/gets.c b/libc/stdio/gets.c
new file mode 100644
index 0000000..004eb99
--- /dev/null
+++ b/libc/stdio/gets.c
@@ -0,0 +1,55 @@
+/*	$OpenBSD: gets.c,v 1.9 2005/08/08 08:05:36 espie Exp $ */
+/*-
+ * Copyright (c) 1990, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <stdio.h>
+
+__warn_references(gets,
+    "warning: gets() is very unsafe; consider using fgets()");
+
+char *
+gets(char *buf)
+{
+	int c;
+	char *s;
+
+	for (s = buf; (c = getchar()) != '\n';)
+		if (c == EOF)
+			if (s == buf)
+				return (NULL);
+			else
+				break;
+		else
+			*s++ = c;
+	*s = '\0';
+	return (buf);
+}
diff --git a/libc/stdio/glue.h b/libc/stdio/glue.h
new file mode 100644
index 0000000..73cef63
--- /dev/null
+++ b/libc/stdio/glue.h
@@ -0,0 +1,45 @@
+/*	$OpenBSD: glue.h,v 1.4 2004/01/11 21:39:51 millert Exp $	*/
+
+/*-
+ * Copyright (c) 1990, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * The first few FILEs are statically allocated; others are dynamically
+ * allocated and linked in via this glue structure.
+ */
+struct glue {
+	struct	glue *next;
+	int	niobs;
+	FILE	*iobs;
+};
+
+extern struct glue __sglue;
diff --git a/libc/stdio/local.h b/libc/stdio/local.h
new file mode 100644
index 0000000..3db1fc5
--- /dev/null
+++ b/libc/stdio/local.h
@@ -0,0 +1,91 @@
+/*	$OpenBSD: local.h,v 1.12 2005/10/10 17:37:44 espie Exp $	*/
+
+/*-
+ * Copyright (c) 1990, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "wcio.h"
+#include "fileext.h"
+
+#ifndef DEFFILEMODE
+#define DEFFILEMODE  (S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH)
+#endif
+
+
+/*
+ * Information local to this implementation of stdio,
+ * in particular, macros and private variables.
+ */
+
+int	__sflush(FILE *);
+FILE	*__sfp(void);
+int	__srefill(FILE *);
+int	__sread(void *, char *, int);
+int	__swrite(void *, const char *, int);
+fpos_t	__sseek(void *, fpos_t, int);
+int	__sclose(void *);
+void	__sinit(void);
+void	_cleanup(void);
+void	__smakebuf(FILE *);
+int	__swhatbuf(FILE *, size_t *, int *);
+int	_fwalk(int (*)(FILE *));
+int	__swsetup(FILE *);
+int	__sflags(const char *, int *);
+
+extern void __atexit_register_cleanup(void (*)(void));
+extern int __sdidinit;
+
+/*
+ * Return true if the given FILE cannot be written now.
+ */
+#define	cantwrite(fp) \
+	((((fp)->_flags & __SWR) == 0 || (fp)->_bf._base == NULL) && \
+	 __swsetup(fp))
+
+/*
+ * Test whether the given stdio file has an active ungetc buffer;
+ * release such a buffer, without restoring ordinary unread data.
+ */
+#define	HASUB(fp) (_UB(fp)._base != NULL)
+#define	FREEUB(fp) { \
+	if (_UB(fp)._base != (fp)->_ubuf) \
+		free(_UB(fp)._base); \
+	_UB(fp)._base = NULL; \
+}
+
+/*
+ * test for an fgetln() buffer.
+ */
+#define	HASLB(fp) ((fp)->_lb._base != NULL)
+#define	FREELB(fp) { \
+	free((char *)(fp)->_lb._base); \
+	(fp)->_lb._base = NULL; \
+}
diff --git a/libc/stdio/makebuf.c b/libc/stdio/makebuf.c
new file mode 100644
index 0000000..d47e27c
--- /dev/null
+++ b/libc/stdio/makebuf.c
@@ -0,0 +1,107 @@
+/*	$OpenBSD: makebuf.c,v 1.8 2005/12/28 18:50:22 millert Exp $ */
+/*-
+ * Copyright (c) 1990, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include "local.h"
+
+/*
+ * Allocate a file buffer, or switch to unbuffered I/O.
+ * Per the ANSI C standard, ALL tty devices default to line buffered.
+ *
+ * As a side effect, we set __SOPT or __SNPT (en/dis-able fseek
+ * optimisation) right after the fstat() that finds the buffer size.
+ */
+void
+__smakebuf(FILE *fp)
+{
+	void *p;
+	int flags;
+	size_t size;
+	int couldbetty;
+
+	if (fp->_flags & __SNBF) {
+		fp->_bf._base = fp->_p = fp->_nbuf;
+		fp->_bf._size = 1;
+		return;
+	}
+	flags = __swhatbuf(fp, &size, &couldbetty);
+	if ((p = malloc(size)) == NULL) {
+		fp->_flags |= __SNBF;
+		fp->_bf._base = fp->_p = fp->_nbuf;
+		fp->_bf._size = 1;
+		return;
+	}
+	__atexit_register_cleanup(_cleanup);
+	flags |= __SMBF;
+	fp->_bf._base = fp->_p = p;
+	fp->_bf._size = size;
+	if (couldbetty && isatty(fp->_file))
+		flags |= __SLBF;
+	fp->_flags |= flags;
+}
+
+/*
+ * Internal routine to determine `proper' buffering for a file.
+ */
+int
+__swhatbuf(FILE *fp, size_t *bufsize, int *couldbetty)
+{
+	struct stat st;
+
+	if (fp->_file < 0 || fstat(fp->_file, &st) < 0) {
+		*couldbetty = 0;
+		*bufsize = BUFSIZ;
+		return (__SNPT);
+	}
+
+	/* could be a tty iff it is a character device */
+	*couldbetty = S_ISCHR(st.st_mode);
+	if (st.st_blksize == 0) {
+		*bufsize = BUFSIZ;
+		return (__SNPT);
+	}
+
+	/*
+	 * Optimise fseek() only if it is a regular file.  (The test for
+	 * __sseek is mainly paranoia.)  It is safe to set _blksize
+	 * unconditionally; it will only be used if __SOPT is also set.
+	 */
+	*bufsize = st.st_blksize;
+	fp->_blksize = st.st_blksize;
+	return ((st.st_mode & S_IFMT) == S_IFREG && fp->_seek == __sseek ?
+	    __SOPT : __SNPT);
+}
diff --git a/libc/stdio/mktemp.c b/libc/stdio/mktemp.c
new file mode 100644
index 0000000..951f803
--- /dev/null
+++ b/libc/stdio/mktemp.c
@@ -0,0 +1,184 @@
+/*	$OpenBSD: mktemp.c,v 1.19 2005/08/08 08:05:36 espie Exp $ */
+/*
+ * Copyright (c) 1987, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <unistd.h>
+
+static int _gettemp(char *, int *, int, int);
+
+extern uint32_t  arc4random();
+
+int
+mkstemps(char *path, int slen)
+{
+	int fd;
+
+	return (_gettemp(path, &fd, 0, slen) ? fd : -1);
+}
+
+int
+mkstemp(char *path)
+{
+	int fd;
+
+	return (_gettemp(path, &fd, 0, 0) ? fd : -1);
+}
+
+char *
+mkdtemp(char *path)
+{
+	return(_gettemp(path, (int *)NULL, 1, 0) ? path : (char *)NULL);
+}
+
+char *_mktemp(char *);
+
+char *
+_mktemp(char *path)
+{
+	return(_gettemp(path, (int *)NULL, 0, 0) ? path : (char *)NULL);
+}
+
+__warn_references(mktemp,
+    "warning: mktemp() possibly used unsafely; consider using mkstemp()");
+
+char *
+mktemp(char *path)
+{
+	return(_mktemp(path));
+}
+
+
+static int
+_gettemp(char *path, int *doopen, int domkdir, int slen)
+{
+	char *start, *trv, *suffp;
+	struct stat sbuf;
+	int rval;
+	pid_t pid;
+
+	if (doopen && domkdir) {
+		errno = EINVAL;
+		return(0);
+	}
+
+	for (trv = path; *trv; ++trv)
+		;
+	trv -= slen;
+	suffp = trv;
+	--trv;
+	if (trv < path) {
+		errno = EINVAL;
+		return (0);
+	}
+	pid = getpid();
+	while (trv >= path && *trv == 'X' && pid != 0) {
+		*trv-- = (pid % 10) + '0';
+		pid /= 10;
+	}
+	while (trv >= path && *trv == 'X') {
+		char c;
+
+		pid = (arc4random() & 0xffff) % (26+26);
+		if (pid < 26)
+			c = pid + 'A';
+		else
+			c = (pid - 26) + 'a';
+		*trv-- = c;
+	}
+	start = trv + 1;
+
+	/*
+	 * check the target directory; if you have six X's and it
+	 * doesn't exist this runs for a *very* long time.
+	 */
+	if (doopen || domkdir) {
+		for (;; --trv) {
+			if (trv <= path)
+				break;
+			if (*trv == '/') {
+				*trv = '\0';
+				rval = stat(path, &sbuf);
+				*trv = '/';
+				if (rval != 0)
+					return(0);
+				if (!S_ISDIR(sbuf.st_mode)) {
+					errno = ENOTDIR;
+					return(0);
+				}
+				break;
+			}
+		}
+	}
+
+	for (;;) {
+		if (doopen) {
+			if ((*doopen =
+			    open(path, O_CREAT|O_EXCL|O_RDWR, 0600)) >= 0)
+				return(1);
+			if (errno != EEXIST)
+				return(0);
+		} else if (domkdir) {
+			if (mkdir(path, 0700) == 0)
+				return(1);
+			if (errno != EEXIST)
+				return(0);
+		} else if (lstat(path, &sbuf))
+			return(errno == ENOENT ? 1 : 0);
+
+		/* tricky little algorithm for backward compatibility */
+		for (trv = start;;) {
+			if (!*trv)
+				return (0);
+			if (*trv == 'Z') {
+				if (trv == suffp)
+					return (0);
+				*trv++ = 'a';
+			} else {
+				if (isdigit(*trv))
+					*trv = 'a';
+				else if (*trv == 'z')	/* inc from z to A */
+					*trv = 'A';
+				else {
+					if (trv == suffp)
+						return (0);
+					++*trv;
+				}
+				break;
+			}
+		}
+	}
+	/*NOTREACHED*/
+}
diff --git a/libc/stdio/printf.c b/libc/stdio/printf.c
new file mode 100644
index 0000000..4acc19b
--- /dev/null
+++ b/libc/stdio/printf.c
@@ -0,0 +1,47 @@
+/*	$OpenBSD: printf.c,v 1.7 2005/08/08 08:05:36 espie Exp $ */
+/*-
+ * Copyright (c) 1990, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <stdio.h>
+#include <stdarg.h>
+
+int
+printf(const char *fmt, ...)
+{
+	int ret;
+  va_list ap;
+
+	va_start(ap, fmt);
+	ret = vfprintf(stdout, fmt, ap);
+  va_end(ap);
+	return (ret);
+}
diff --git a/libc/stdio/putc.c b/libc/stdio/putc.c
new file mode 100644
index 0000000..9250215
--- /dev/null
+++ b/libc/stdio/putc.c
@@ -0,0 +1,67 @@
+/*	$OpenBSD: putc.c,v 1.7 2005/08/08 08:05:36 espie Exp $ */
+/*-
+ * Copyright (c) 1990, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <stdio.h>
+#include <errno.h>
+#include "local.h"
+
+/*
+ * A subroutine version of the macro putc_unlocked.
+ */
+#undef putc_unlocked
+
+int
+putc_unlocked(int c, FILE *fp)
+{
+	if (cantwrite(fp)) {
+		errno = EBADF;
+		return (EOF);
+	}
+	return (__sputc(c, fp));
+}
+
+/*
+ * A subroutine version of the macro putc.
+ */
+#undef putc
+
+int
+putc(int c, FILE *fp)
+{
+	int ret;
+
+	flockfile(fp);
+	ret = putc_unlocked(c, fp);
+	funlockfile(fp);
+	return (ret);
+}
diff --git a/libc/stdio/putchar.c b/libc/stdio/putchar.c
new file mode 100644
index 0000000..233cdfd
--- /dev/null
+++ b/libc/stdio/putchar.c
@@ -0,0 +1,59 @@
+/*	$OpenBSD: putchar.c,v 1.7 2005/08/08 08:05:36 espie Exp $ */
+/*-
+ * Copyright (c) 1990, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <stdio.h>
+
+#undef putchar_unlocked
+/*
+ * A subrouting version of the macro putchar_unlocked
+ */
+int
+putchar_unlocked(int c)
+{
+	FILE *so = stdout;
+
+	return (putc_unlocked(c,so));
+}
+
+#undef putchar
+
+/*
+ * A subroutine version of the macro putchar
+ */
+int
+putchar(int c)
+{
+	FILE *so = stdout;
+
+	return (putc(c, so));
+}
diff --git a/libc/stdio/puts.c b/libc/stdio/puts.c
new file mode 100644
index 0000000..c6ecc24
--- /dev/null
+++ b/libc/stdio/puts.c
@@ -0,0 +1,56 @@
+/*	$OpenBSD: puts.c,v 1.7 2005/08/08 08:05:36 espie Exp $ */
+/*-
+ * Copyright (c) 1990, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include "fvwrite.h"
+
+/*
+ * Write the given string to stdout, appending a newline.
+ */
+int
+puts(const char *s)
+{
+	size_t c = strlen(s);
+	struct __suio uio;
+	struct __siov iov[2];
+
+	iov[0].iov_base = (void *)s;
+	iov[0].iov_len = c;
+	iov[1].iov_base = "\n";
+	iov[1].iov_len = 1;
+	uio.uio_resid = c + 1;
+	uio.uio_iov = &iov[0];
+	uio.uio_iovcnt = 2;
+	return (__sfvwrite(stdout, &uio) ? EOF : '\n');
+}
diff --git a/libc/stdio/putw.c b/libc/stdio/putw.c
new file mode 100644
index 0000000..12955fe
--- /dev/null
+++ b/libc/stdio/putw.c
@@ -0,0 +1,48 @@
+/*	$OpenBSD: putw.c,v 1.6 2005/08/08 08:05:36 espie Exp $ */
+/*-
+ * Copyright (c) 1990, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <stdio.h>
+#include "fvwrite.h"
+
+int
+putw(int w, FILE *fp)
+{
+	struct __suio uio;
+	struct __siov iov;
+
+	iov.iov_base = &w;
+	iov.iov_len = uio.uio_resid = sizeof(w);
+	uio.uio_iov = &iov;
+	uio.uio_iovcnt = 1;
+	return (__sfvwrite(fp, &uio));
+}
diff --git a/libc/stdio/refill.c b/libc/stdio/refill.c
new file mode 100644
index 0000000..74b378e
--- /dev/null
+++ b/libc/stdio/refill.c
@@ -0,0 +1,121 @@
+/*	$OpenBSD: refill.c,v 1.8 2005/08/08 08:05:36 espie Exp $ */
+/*-
+ * Copyright (c) 1990, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include "local.h"
+
+static int
+lflush(FILE *fp)
+{
+
+	if ((fp->_flags & (__SLBF|__SWR)) == (__SLBF|__SWR))
+		return (__sflush(fp));
+	return (0);
+}
+
+/*
+ * Refill a stdio buffer.
+ * Return EOF on eof or error, 0 otherwise.
+ */
+int
+__srefill(FILE *fp)
+{
+
+	/* make sure stdio is set up */
+	if (!__sdidinit)
+		__sinit();
+
+	fp->_r = 0;		/* largely a convenience for callers */
+
+	/* SysV does not make this test; take it out for compatibility */
+	if (fp->_flags & __SEOF)
+		return (EOF);
+
+	/* if not already reading, have to be reading and writing */
+	if ((fp->_flags & __SRD) == 0) {
+		if ((fp->_flags & __SRW) == 0) {
+			errno = EBADF;
+			fp->_flags |= __SERR;
+			return (EOF);
+		}
+		/* switch to reading */
+		if (fp->_flags & __SWR) {
+			if (__sflush(fp))
+				return (EOF);
+			fp->_flags &= ~__SWR;
+			fp->_w = 0;
+			fp->_lbfsize = 0;
+		}
+		fp->_flags |= __SRD;
+	} else {
+		/*
+		 * We were reading.  If there is an ungetc buffer,
+		 * we must have been reading from that.  Drop it,
+		 * restoring the previous buffer (if any).  If there
+		 * is anything in that buffer, return.
+		 */
+		if (HASUB(fp)) {
+			FREEUB(fp);
+			if ((fp->_r = fp->_ur) != 0) {
+				fp->_p = fp->_up;
+				return (0);
+			}
+		}
+	}
+
+	if (fp->_bf._base == NULL)
+		__smakebuf(fp);
+
+	/*
+	 * Before reading from a line buffered or unbuffered file,
+	 * flush all line buffered output files, per the ANSI C
+	 * standard.
+	 */
+	if (fp->_flags & (__SLBF|__SNBF))
+		(void) _fwalk(lflush);
+	fp->_p = fp->_bf._base;
+	fp->_r = (*fp->_read)(fp->_cookie, (char *)fp->_p, fp->_bf._size);
+	fp->_flags &= ~__SMOD;	/* buffer contents are again pristine */
+	if (fp->_r <= 0) {
+		if (fp->_r == 0)
+			fp->_flags |= __SEOF;
+		else {
+			fp->_r = 0;
+			fp->_flags |= __SERR;
+		}
+		return (EOF);
+	}
+	return (0);
+}
diff --git a/libc/stdio/remove.c b/libc/stdio/remove.c
new file mode 100644
index 0000000..d09d76f
--- /dev/null
+++ b/libc/stdio/remove.c
@@ -0,0 +1,49 @@
+/*	$OpenBSD: remove.c,v 1.7 2005/08/08 08:05:36 espie Exp $	*/
+
+/*-
+ * Copyright (c) 1990, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <stdio.h>
+#include <unistd.h>
+#include <sys/stat.h>
+
+int
+remove(const char *file)
+{
+	struct stat st;
+
+	if (lstat(file, &st) < 0)
+		return (-1);
+	if (S_ISDIR(st.st_mode))
+		return (rmdir(file));
+	return (unlink(file));
+}
diff --git a/libc/stdio/rewind.c b/libc/stdio/rewind.c
new file mode 100644
index 0000000..28119b6
--- /dev/null
+++ b/libc/stdio/rewind.c
@@ -0,0 +1,43 @@
+/*	$OpenBSD: rewind.c,v 1.5 2005/08/08 08:05:36 espie Exp $ */
+/*-
+ * Copyright (c) 1990, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <errno.h>
+#include <stdio.h>
+
+void
+rewind(FILE *fp)
+{
+	(void) fseek(fp, 0L, SEEK_SET);
+	clearerr(fp);
+	errno = 0;      /* not required, but seems reasonable */
+}
diff --git a/libc/stdio/rget.c b/libc/stdio/rget.c
new file mode 100644
index 0000000..4cd97cb
--- /dev/null
+++ b/libc/stdio/rget.c
@@ -0,0 +1,51 @@
+/*	$OpenBSD: rget.c,v 1.7 2005/08/08 08:05:36 espie Exp $ */
+/*-
+ * Copyright (c) 1990, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <stdio.h>
+#include "local.h"
+
+/*
+ * Handle getc() when the buffer ran out:
+ * Refill, then return the first character
+ * in the newly-filled buffer.
+ */
+int
+__srget(FILE *fp)
+{
+	_SET_ORIENTATION(fp, -1);
+	if (__srefill(fp) == 0) {
+		fp->_r--;
+		return (*fp->_p++);
+	}
+	return (EOF);
+}
diff --git a/libc/stdio/scanf.c b/libc/stdio/scanf.c
new file mode 100644
index 0000000..71194d0
--- /dev/null
+++ b/libc/stdio/scanf.c
@@ -0,0 +1,47 @@
+/*	$OpenBSD: scanf.c,v 1.9 2005/08/08 08:05:36 espie Exp $ */
+/*-
+ * Copyright (c) 1990, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <stdio.h>
+#include <stdarg.h>
+
+int
+scanf(const char *fmt, ...)
+{
+	int ret;
+	va_list ap;
+
+	va_start(ap, fmt);
+	ret = vfscanf(stdin, fmt, ap);
+	va_end(ap);
+	return (ret);
+}
diff --git a/libc/stdio/setbuf.c b/libc/stdio/setbuf.c
new file mode 100644
index 0000000..883b895
--- /dev/null
+++ b/libc/stdio/setbuf.c
@@ -0,0 +1,41 @@
+/*	$OpenBSD: setbuf.c,v 1.5 2005/08/08 08:05:36 espie Exp $ */
+/*-
+ * Copyright (c) 1990, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <stdio.h>
+#include "local.h"
+
+void
+setbuf(FILE *fp, char *buf)
+{
+	(void) setvbuf(fp, buf, buf ? _IOFBF : _IONBF, BUFSIZ);
+}
diff --git a/libc/stdio/setbuffer.c b/libc/stdio/setbuffer.c
new file mode 100644
index 0000000..8725ff7
--- /dev/null
+++ b/libc/stdio/setbuffer.c
@@ -0,0 +1,51 @@
+/*	$OpenBSD: setbuffer.c,v 1.5 2005/08/08 08:05:36 espie Exp $ */
+/*-
+ * Copyright (c) 1990, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <stdio.h>
+
+void
+setbuffer(FILE *fp, char *buf, int size)
+{
+
+	(void)setvbuf(fp, buf, buf ? _IOFBF : _IONBF, size);
+}
+
+/*
+ * set line buffering
+ */
+int
+setlinebuf(FILE *fp)
+{
+
+	return (setvbuf(fp, (char *)NULL, _IOLBF, (size_t)0));
+}
diff --git a/libc/stdio/setvbuf.c b/libc/stdio/setvbuf.c
new file mode 100644
index 0000000..9b92bf0
--- /dev/null
+++ b/libc/stdio/setvbuf.c
@@ -0,0 +1,151 @@
+/*	$OpenBSD: setvbuf.c,v 1.8 2005/08/08 08:05:36 espie Exp $ */
+/*-
+ * Copyright (c) 1990, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include "local.h"
+
+/*
+ * Set one of the three kinds of buffering, optionally including
+ * a buffer.
+ */
+int
+setvbuf(FILE *fp, char *buf, int mode, size_t size)
+{
+	int ret, flags;
+	size_t iosize;
+	int ttyflag;
+
+	/*
+	 * Verify arguments.  The `int' limit on `size' is due to this
+	 * particular implementation.  Note, buf and size are ignored
+	 * when setting _IONBF.
+	 */
+	if (mode != _IONBF)
+		if ((mode != _IOFBF && mode != _IOLBF) || (int)size < 0)
+			return (EOF);
+
+	/*
+	 * Write current buffer, if any.  Discard unread input (including
+	 * ungetc data), cancel line buffering, and free old buffer if
+	 * malloc()ed.  We also clear any eof condition, as if this were
+	 * a seek.
+	 */
+	ret = 0;
+	(void)__sflush(fp);
+	if (HASUB(fp))
+		FREEUB(fp);
+	WCIO_FREE(fp);
+	fp->_r = fp->_lbfsize = 0;
+	flags = fp->_flags;
+	if (flags & __SMBF)
+		free((void *)fp->_bf._base);
+	flags &= ~(__SLBF | __SNBF | __SMBF | __SOPT | __SNPT | __SEOF);
+
+	/* If setting unbuffered mode, skip all the hard work. */
+	if (mode == _IONBF)
+		goto nbf;
+
+	/*
+	 * Find optimal I/O size for seek optimization.  This also returns
+	 * a `tty flag' to suggest that we check isatty(fd), but we do not
+	 * care since our caller told us how to buffer.
+	 */
+	flags |= __swhatbuf(fp, &iosize, &ttyflag);
+	if (size == 0) {
+		buf = NULL;	/* force local allocation */
+		size = iosize;
+	}
+
+	/* Allocate buffer if needed. */
+	if (buf == NULL) {
+		if ((buf = malloc(size)) == NULL) {
+			/*
+			 * Unable to honor user's request.  We will return
+			 * failure, but try again with file system size.
+			 */
+			ret = EOF;
+			if (size != iosize) {
+				size = iosize;
+				buf = malloc(size);
+			}
+		}
+		if (buf == NULL) {
+			/* No luck; switch to unbuffered I/O. */
+nbf:
+			fp->_flags = flags | __SNBF;
+			fp->_w = 0;
+			fp->_bf._base = fp->_p = fp->_nbuf;
+			fp->_bf._size = 1;
+			return (ret);
+		}
+		flags |= __SMBF;
+	}
+
+	/*
+	 * Kill any seek optimization if the buffer is not the
+	 * right size.
+	 *
+	 * SHOULD WE ALLOW MULTIPLES HERE (i.e., ok iff (size % iosize) == 0)?
+	 */
+	if (size != iosize)
+		flags |= __SNPT;
+
+	/*
+	 * Fix up the FILE fields, and set __cleanup for output flush on
+	 * exit (since we are buffered in some way).
+	 */
+	if (mode == _IOLBF)
+		flags |= __SLBF;
+	fp->_flags = flags;
+	fp->_bf._base = fp->_p = (unsigned char *)buf;
+	fp->_bf._size = size;
+	/* fp->_lbfsize is still 0 */
+	if (flags & __SWR) {
+		/*
+		 * Begin or continue writing: see __swsetup().  Note
+		 * that __SNBF is impossible (it was handled earlier).
+		 */
+		if (flags & __SLBF) {
+			fp->_w = 0;
+			fp->_lbfsize = -fp->_bf._size;
+		} else
+			fp->_w = size;
+	} else {
+		/* begin/continue reading, or stay in intermediate state */
+		fp->_w = 0;
+	}
+	__atexit_register_cleanup(_cleanup);
+
+	return (ret);
+}
diff --git a/libc/stdio/snprintf.c b/libc/stdio/snprintf.c
new file mode 100644
index 0000000..e830c0f
--- /dev/null
+++ b/libc/stdio/snprintf.c
@@ -0,0 +1,67 @@
+/*	$OpenBSD: snprintf.c,v 1.14 2005/10/10 12:00:52 espie Exp $ */
+/*-
+ * Copyright (c) 1990, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <limits.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdarg.h>
+#include "local.h"
+
+int
+snprintf(char *str, size_t n, const char *fmt, ...)
+{
+  va_list ap;
+	int ret;
+	char dummy;
+	FILE f;
+	struct __sfileext fext;
+
+	/* While snprintf(3) specifies size_t stdio uses an int internally */
+	if (n > INT_MAX)
+		n = INT_MAX;
+	/* Stdio internals do not deal correctly with zero length buffer */
+	if (n == 0) {
+		str = &dummy;
+		n = 1;
+	}
+	_FILEEXT_SETUP(&f, &fext);
+	f._file = -1;
+	f._flags = __SWR | __SSTR;
+	f._bf._base = f._p = (unsigned char *)str;
+	f._bf._size = f._w = n - 1;
+	va_start(ap, fmt);
+	ret = vfprintf(&f, fmt, ap);
+  va_end(ap);
+	*f._p = '\0';
+	return (ret);
+}
diff --git a/libc/stdio/sprintf.c b/libc/stdio/sprintf.c
new file mode 100644
index 0000000..739cde7
--- /dev/null
+++ b/libc/stdio/sprintf.c
@@ -0,0 +1,63 @@
+/*	$OpenBSD: sprintf.c,v 1.13 2005/10/10 12:00:52 espie Exp $ */
+/*-
+ * Copyright (c) 1990, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdarg.h>
+#include <limits.h>
+#include "local.h"
+
+#if defined(APIWARN)
+__warn_references(sprintf,
+    "warning: sprintf() is often misused, please use snprintf()");
+#endif
+
+int
+sprintf(char *str, const char *fmt, ...)
+{
+	int ret;
+  va_list ap;
+	FILE f;
+	struct __sfileext fext;
+
+	_FILEEXT_SETUP(&f, &fext);
+	f._file = -1;
+	f._flags = __SWR | __SSTR;
+	f._bf._base = f._p = (unsigned char *)str;
+	f._bf._size = f._w = INT_MAX;
+	va_start(ap, fmt);
+	ret = vfprintf(&f, fmt, ap);
+  va_end(ap);
+	*f._p = '\0';
+	return (ret);
+}
diff --git a/libc/stdio/sscanf.c b/libc/stdio/sscanf.c
new file mode 100644
index 0000000..e141eec
--- /dev/null
+++ b/libc/stdio/sscanf.c
@@ -0,0 +1,65 @@
+/*	$OpenBSD: sscanf.c,v 1.12 2005/08/08 08:05:36 espie Exp $ */
+/*-
+ * Copyright (c) 1990, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdarg.h>
+#include "local.h"
+
+/* ARGSUSED */
+static int
+eofread(void *cookie, char *buf, int len)
+{
+
+	return (0);
+}
+
+int
+sscanf(const char *str, const char *fmt, ...)
+{
+	int ret;
+  va_list ap;
+	FILE f;
+	struct __sfileext fext;
+
+	_FILEEXT_SETUP(&f, &fext);
+	f._flags = __SRD;
+	f._bf._base = f._p = (unsigned char *)str;
+	f._bf._size = f._r = strlen(str);
+	f._read = eofread;
+	f._lb._base = NULL;
+	va_start(ap, fmt);
+	ret = vfscanf(&f, fmt, ap);
+  va_end(ap);
+	return (ret);
+}
diff --git a/libc/stdio/stdio.c b/libc/stdio/stdio.c
new file mode 100644
index 0000000..a4a27b5
--- /dev/null
+++ b/libc/stdio/stdio.c
@@ -0,0 +1,89 @@
+/*	$OpenBSD: stdio.c,v 1.9 2005/08/08 08:05:36 espie Exp $ */
+/*-
+ * Copyright (c) 1990, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdio.h>
+#include "local.h"
+
+/*
+ * Small standard I/O/seek/close functions.
+ * These maintain the `known seek offset' for seek optimisation.
+ */
+int
+__sread(void *cookie, char *buf, int n)
+{
+	FILE *fp = cookie;
+	int ret;
+	
+	ret = read(fp->_file, buf, n);
+	/* if the read succeeded, update the current offset */
+	if (ret >= 0)
+		fp->_offset += ret;
+	else
+		fp->_flags &= ~__SOFF;	/* paranoia */
+	return (ret);
+}
+
+int
+__swrite(void *cookie, const char *buf, int n)
+{
+	FILE *fp = cookie;
+
+	if (fp->_flags & __SAPP)
+		(void) lseek(fp->_file, (off_t)0, SEEK_END);
+	fp->_flags &= ~__SOFF;	/* in case FAPPEND mode is set */
+	return (write(fp->_file, buf, n));
+}
+
+fpos_t
+__sseek(void *cookie, fpos_t offset, int whence)
+{
+	FILE *fp = cookie;
+	off_t ret;
+	
+	ret = lseek(fp->_file, (off_t)offset, whence);
+	if (ret == (off_t)-1)
+		fp->_flags &= ~__SOFF;
+	else {
+		fp->_flags |= __SOFF;
+		fp->_offset = ret;
+	}
+	return (ret);
+}
+
+int
+__sclose(void *cookie)
+{
+	return (close(((FILE *)cookie)->_file));
+}
diff --git a/libc/stdio/tempnam.c b/libc/stdio/tempnam.c
new file mode 100644
index 0000000..3b7ec75
--- /dev/null
+++ b/libc/stdio/tempnam.c
@@ -0,0 +1,84 @@
+/*	$OpenBSD: tempnam.c,v 1.14 2005/08/08 08:05:36 espie Exp $ */
+/*
+ * Copyright (c) 1988, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/param.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <paths.h>
+
+__warn_references(tempnam,
+    "warning: tempnam() possibly used unsafely; consider using mkstemp()");
+
+extern char *_mktemp(char *);
+
+char *
+tempnam(const char *dir, const char *pfx)
+{
+	int sverrno;
+	char *f, *name;
+
+	if (!(name = malloc(MAXPATHLEN)))
+		return(NULL);
+
+	if (!pfx)
+		pfx = "tmp.";
+
+	if (issetugid() == 0 && (f = getenv("TMPDIR"))) {
+		(void)snprintf(name, MAXPATHLEN, "%s%s%sXXXXXXXXXX", f,
+		    *(f + strlen(f) - 1) == '/'? "": "/", pfx);
+		if ((f = _mktemp(name)))
+			return(f);
+	}
+
+	if ((f = (char *)dir)) {
+		(void)snprintf(name, MAXPATHLEN, "%s%s%sXXXXXXXXXX", f,
+		    *(f + strlen(f) - 1) == '/'? "": "/", pfx);
+		if ((f = _mktemp(name)))
+			return(f);
+	}
+
+	f = P_tmpdir;
+	(void)snprintf(name, MAXPATHLEN, "%s%sXXXXXXXXX", f, pfx);
+	if ((f = _mktemp(name)))
+		return(f);
+
+	f = _PATH_TMP;
+	(void)snprintf(name, MAXPATHLEN, "%s%sXXXXXXXXX", f, pfx);
+	if ((f = _mktemp(name)))
+		return(f);
+
+	sverrno = errno;
+	free(name);
+	errno = sverrno;
+	return(NULL);
+}
diff --git a/libc/stdio/tmpfile.c b/libc/stdio/tmpfile.c
new file mode 100644
index 0000000..39f7e92
--- /dev/null
+++ b/libc/stdio/tmpfile.c
@@ -0,0 +1,81 @@
+/*	$OpenBSD: tmpfile.c,v 1.10 2005/10/10 12:00:52 espie Exp $ */
+/*-
+ * Copyright (c) 1990, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <signal.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <paths.h>
+
+FILE *
+tmpfile(void)
+{
+	sigset_t set, oset;
+	FILE *fp;
+	int fd, sverrno;
+#define	TRAILER	"tmp.XXXXXXXXXX"
+	char buf[sizeof(_PATH_TMP) + sizeof(TRAILER)];
+
+	(void)memcpy(buf, _PATH_TMP, sizeof(_PATH_TMP) - 1);
+	(void)memcpy(buf + sizeof(_PATH_TMP) - 1, TRAILER, sizeof(TRAILER));
+
+	sigfillset(&set);
+	(void)sigprocmask(SIG_BLOCK, &set, &oset);
+
+	fd = mkstemp(buf);
+	if (fd != -1) {
+		mode_t u;
+
+		(void)unlink(buf);
+		u = umask(0);
+		(void)umask(u);
+		(void)fchmod(fd, 0666 & ~u);
+	}
+
+	(void)sigprocmask(SIG_SETMASK, &oset, NULL);
+
+	if (fd == -1)
+		return (NULL);
+
+	if ((fp = fdopen(fd, "w+")) == NULL) {
+		sverrno = errno;
+		(void)close(fd);
+		errno = sverrno;
+		return (NULL);
+	}
+	return (fp);
+}
diff --git a/libc/stdio/tmpnam.c b/libc/stdio/tmpnam.c
new file mode 100644
index 0000000..32e0a22
--- /dev/null
+++ b/libc/stdio/tmpnam.c
@@ -0,0 +1,55 @@
+/*	$OpenBSD: tmpnam.c,v 1.10 2005/08/08 08:05:36 espie Exp $ */
+/*-
+ * Copyright (c) 1990, 1993, 1994
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/types.h>
+
+#include <stdio.h>
+#include <unistd.h>
+
+__warn_references(tmpnam,
+    "warning: tmpnam() possibly used unsafely; consider using mkstemp()");
+
+extern char *_mktemp(char *);
+
+char *
+tmpnam(char *s)
+{
+	static u_long tmpcount;
+	static char buf[L_tmpnam];
+
+	if (s == NULL)
+		s = buf;
+	(void)snprintf(s, L_tmpnam, "%stmp.%lu.XXXXXXXXX", P_tmpdir, tmpcount);
+	++tmpcount;
+	return (_mktemp(s));
+}
diff --git a/libc/stdio/ungetc.c b/libc/stdio/ungetc.c
new file mode 100644
index 0000000..fe05258
--- /dev/null
+++ b/libc/stdio/ungetc.c
@@ -0,0 +1,141 @@
+/*	$OpenBSD: ungetc.c,v 1.9 2005/08/08 08:05:36 espie Exp $ */
+/*-
+ * Copyright (c) 1990, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "local.h"
+
+static int __submore(FILE *);
+/*
+ * Expand the ungetc buffer `in place'.  That is, adjust fp->_p when
+ * the buffer moves, so that it points the same distance from the end,
+ * and move the bytes in the buffer around as necessary so that they
+ * are all at the end (stack-style).
+ */
+static int
+__submore(FILE *fp)
+{
+	int i;
+	unsigned char *p;
+
+	if (_UB(fp)._base == fp->_ubuf) {
+		/*
+		 * Get a new buffer (rather than expanding the old one).
+		 */
+		if ((p = malloc((size_t)BUFSIZ)) == NULL)
+			return (EOF);
+		_UB(fp)._base = p;
+		_UB(fp)._size = BUFSIZ;
+		p += BUFSIZ - sizeof(fp->_ubuf);
+		for (i = sizeof(fp->_ubuf); --i >= 0;)
+			p[i] = fp->_ubuf[i];
+		fp->_p = p;
+		return (0);
+	}
+	i = _UB(fp)._size;
+	p = realloc(_UB(fp)._base, i << 1);
+	if (p == NULL)
+		return (EOF);
+	/* no overlap (hence can use memcpy) because we doubled the size */
+	(void)memcpy((void *)(p + i), (void *)p, (size_t)i);
+	fp->_p = p + i;
+	_UB(fp)._base = p;
+	_UB(fp)._size = i << 1;
+	return (0);
+}
+
+int
+ungetc(int c, FILE *fp)
+{
+	if (c == EOF)
+		return (EOF);
+	if (!__sdidinit)
+		__sinit();
+	_SET_ORIENTATION(fp, -1);
+	if ((fp->_flags & __SRD) == 0) {
+		/*
+		 * Not already reading: no good unless reading-and-writing.
+		 * Otherwise, flush any current write stuff.
+		 */
+		if ((fp->_flags & __SRW) == 0)
+			return (EOF);
+		if (fp->_flags & __SWR) {
+			if (__sflush(fp))
+				return (EOF);
+			fp->_flags &= ~__SWR;
+			fp->_w = 0;
+			fp->_lbfsize = 0;
+		}
+		fp->_flags |= __SRD;
+	}
+	c = (unsigned char)c;
+
+	/*
+	 * If we are in the middle of ungetc'ing, just continue.
+	 * This may require expanding the current ungetc buffer.
+	 */
+	if (HASUB(fp)) {
+		if (fp->_r >= _UB(fp)._size && __submore(fp))
+			return (EOF);
+		*--fp->_p = c;
+		fp->_r++;
+		return (c);
+	}
+	fp->_flags &= ~__SEOF;
+
+	/*
+	 * If we can handle this by simply backing up, do so,
+	 * but never replace the original character.
+	 * (This makes sscanf() work when scanning `const' data.)
+	 */
+	if (fp->_bf._base != NULL && fp->_p > fp->_bf._base &&
+	    fp->_p[-1] == c) {
+		fp->_p--;
+		fp->_r++;
+		return (c);
+	}
+
+	/*
+	 * Create an ungetc buffer.
+	 * Initially, we will use the `reserve' buffer.
+	 */
+	fp->_ur = fp->_r;
+	fp->_up = fp->_p;
+	_UB(fp)._base = fp->_ubuf;
+	_UB(fp)._size = sizeof(fp->_ubuf);
+	fp->_ubuf[sizeof(fp->_ubuf) - 1] = c;
+	fp->_p = &fp->_ubuf[sizeof(fp->_ubuf) - 1];
+	fp->_r = 1;
+	return (c);
+}
diff --git a/libc/stdio/vasprintf.c b/libc/stdio/vasprintf.c
new file mode 100644
index 0000000..c3280c9
--- /dev/null
+++ b/libc/stdio/vasprintf.c
@@ -0,0 +1,58 @@
+/*	$OpenBSD: vasprintf.c,v 1.13 2006/01/06 18:53:04 millert Exp $	*/
+
+/*
+ * Copyright (c) 1997 Todd C. Miller <Todd.Miller@courtesan.com>
+ *
+ * Permission to use, copy, modify, and 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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include "local.h"
+
+int
+vasprintf(char **str, const char *fmt, __va_list ap)
+{
+	int ret;
+	FILE f;
+	struct __sfileext fext;
+	unsigned char *_base;
+
+	_FILEEXT_SETUP(&f, &fext);
+	f._file = -1;
+	f._flags = __SWR | __SSTR | __SALC;
+	f._bf._base = f._p = (unsigned char *)malloc(128);
+	if (f._bf._base == NULL)
+		goto err;
+	f._bf._size = f._w = 127;		/* Leave room for the NUL */
+	ret = vfprintf(&f, fmt, ap);
+	if (ret == -1)
+		goto err;
+	*f._p = '\0';
+	_base = realloc(f._bf._base, ret + 1);
+	if (_base == NULL)
+		goto err;
+	*str = (char *)_base;
+	return (ret);
+
+err:
+	if (f._bf._base) {
+		free(f._bf._base);
+		f._bf._base = NULL;
+	}
+	*str = NULL;
+	errno = ENOMEM;
+	return (-1);
+}
diff --git a/libc/stdio/vfprintf.c b/libc/stdio/vfprintf.c
new file mode 100644
index 0000000..2ce0361
--- /dev/null
+++ b/libc/stdio/vfprintf.c
@@ -0,0 +1,1313 @@
+/*	$OpenBSD: vfprintf.c,v 1.37 2006/01/13 17:56:18 millert Exp $	*/
+/*-
+ * Copyright (c) 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * Actual printf innards.
+ *
+ * This code is large and complicated...
+ */
+
+#include <sys/types.h>
+#include <sys/mman.h>
+
+#include <errno.h>
+#include <stdarg.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "local.h"
+#include "fvwrite.h"
+
+static void __find_arguments(const char *fmt0, va_list ap, va_list **argtable,
+    size_t *argtablesiz);
+static int __grow_type_table(unsigned char **typetable, int *tablesize);
+
+/*
+ * Flush out all the vectors defined by the given uio,
+ * then reset it so that it can be reused.
+ */
+static int
+__sprint(FILE *fp, struct __suio *uio)
+{
+	int err;
+
+	if (uio->uio_resid == 0) {
+		uio->uio_iovcnt = 0;
+		return (0);
+	}
+	err = __sfvwrite(fp, uio);
+	uio->uio_resid = 0;
+	uio->uio_iovcnt = 0;
+	return (err);
+}
+
+/*
+ * Helper function for `fprintf to unbuffered unix file': creates a
+ * temporary buffer.  We only work on write-only files; this avoids
+ * worries about ungetc buffers and so forth.
+ */
+static int
+__sbprintf(FILE *fp, const char *fmt, va_list ap)
+{
+	int ret;
+	FILE fake;
+	struct __sfileext fakeext;
+	unsigned char buf[BUFSIZ];
+
+	_FILEEXT_SETUP(&fake, &fakeext);
+	/* copy the important variables */
+	fake._flags = fp->_flags & ~__SNBF;
+	fake._file = fp->_file;
+	fake._cookie = fp->_cookie;
+	fake._write = fp->_write;
+
+	/* set up the buffer */
+	fake._bf._base = fake._p = buf;
+	fake._bf._size = fake._w = sizeof(buf);
+	fake._lbfsize = 0;	/* not actually used, but Just In Case */
+
+	/* do the work, then copy any error status */
+	ret = vfprintf(&fake, fmt, ap);
+	if (ret >= 0 && fflush(&fake))
+		ret = EOF;
+	if (fake._flags & __SERR)
+		fp->_flags |= __SERR;
+	return (ret);
+}
+
+
+#ifdef FLOATING_POINT
+#include <locale.h>
+#include <math.h>
+#include "floatio.h"
+
+#define	BUF		(MAXEXP+MAXFRACT+1)	/* + decimal point */
+#define	DEFPREC		6
+
+static char *cvt(double, int, int, char *, int *, int, int *);
+static int exponent(char *, int, int);
+#else /* no FLOATING_POINT */
+#define	BUF		40
+#endif /* FLOATING_POINT */
+
+#define STATIC_ARG_TBL_SIZE 8	/* Size of static argument table. */
+
+/* BIONIC: do not link libm for only two rather simple functions */
+#ifdef FLOATING_POINT
+static  int  _my_isinf(double);
+static  int  _my_isnan(double);
+#endif
+
+/*
+ * Macros for converting digits to letters and vice versa
+ */
+#define	to_digit(c)	((c) - '0')
+#define is_digit(c)	((unsigned)to_digit(c) <= 9)
+#define	to_char(n)	((n) + '0')
+
+/*
+ * Flags used during conversion.
+ */
+#define	ALT		0x0001		/* alternate form */
+#define	HEXPREFIX	0x0002		/* add 0x or 0X prefix */
+#define	LADJUST		0x0004		/* left adjustment */
+#define	LONGDBL		0x0008		/* long double; unimplemented */
+#define	LONGINT		0x0010		/* long integer */
+#define	LLONGINT	0x0020		/* long long integer */
+#define	SHORTINT	0x0040		/* short integer */
+#define	ZEROPAD		0x0080		/* zero (as opposed to blank) pad */
+#define FPT		0x0100		/* Floating point number */
+#define PTRINT		0x0200		/* (unsigned) ptrdiff_t */
+#define SIZEINT		0x0400		/* (signed) size_t */
+#define CHARINT		0x0800		/* 8 bit integer */
+#define MAXINT		0x1000		/* largest integer size (intmax_t) */
+
+int
+vfprintf(FILE *fp, const char *fmt0, __va_list ap)
+{
+	char *fmt;	/* format string */
+	int ch;	/* character from fmt */
+	int n, m, n2;	/* handy integers (short term usage) */
+	char *cp;	/* handy char pointer (short term usage) */
+	char *cp_free = NULL;  /* BIONIC: copy of cp to be freed after usage */
+	struct __siov *iovp;/* for PRINT macro */
+	int flags;	/* flags as above */
+	int ret;		/* return value accumulator */
+	int width;		/* width from format (%8d), or 0 */
+	int prec;		/* precision from format (%.3d), or -1 */
+	char sign;		/* sign prefix (' ', '+', '-', or \0) */
+	wchar_t wc;
+	void* ps;
+#ifdef FLOATING_POINT
+	char *decimal_point = ".";
+	char softsign;		/* temporary negative sign for floats */
+	double _double = 0.;	/* double precision arguments %[eEfgG] */
+	int expt;		/* integer value of exponent */
+	int expsize = 0;	/* character count for expstr */
+	int ndig;		/* actual number of digits returned by cvt */
+	char expstr[7];		/* buffer for exponent string */
+#endif
+
+	uintmax_t _umax;	/* integer arguments %[diouxX] */
+	enum { OCT, DEC, HEX } base;/* base for [diouxX] conversion */
+	int dprec;		/* a copy of prec if [diouxX], 0 otherwise */
+	int realsz;		/* field size expanded by dprec */
+	int size;		/* size of converted field or string */
+	char* xdigs = NULL;		/* digits for [xX] conversion */
+#define NIOV 8
+	struct __suio uio;	/* output information: summary */
+	struct __siov iov[NIOV];/* ... and individual io vectors */
+	char buf[BUF];		/* space for %c, %[diouxX], %[eEfgG] */
+	char ox[2];		/* space for 0x hex-prefix */
+	va_list *argtable;	/* args, built due to positional arg */
+	va_list statargtable[STATIC_ARG_TBL_SIZE];
+	size_t argtablesiz;
+	int nextarg;		/* 1-based argument index */
+	va_list orgap;		/* original argument pointer */
+	/*
+	 * Choose PADSIZE to trade efficiency vs. size.  If larger printf
+	 * fields occur frequently, increase PADSIZE and make the initialisers
+	 * below longer.
+	 */
+#define	PADSIZE	16		/* pad chunk size */
+	static char blanks[PADSIZE] =
+	 {' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' '};
+	static char zeroes[PADSIZE] =
+	 {'0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0'};
+
+	/*
+	 * BEWARE, these `goto error' on error, and PAD uses `n'.
+	 */
+#define	PRINT(ptr, len) do { \
+	iovp->iov_base = (ptr); \
+	iovp->iov_len = (len); \
+	uio.uio_resid += (len); \
+	iovp++; \
+	if (++uio.uio_iovcnt >= NIOV) { \
+		if (__sprint(fp, &uio)) \
+			goto error; \
+		iovp = iov; \
+	} \
+} while (0)
+#define	PAD(howmany, with) do { \
+	if ((n = (howmany)) > 0) { \
+		while (n > PADSIZE) { \
+			PRINT(with, PADSIZE); \
+			n -= PADSIZE; \
+		} \
+		PRINT(with, n); \
+	} \
+} while (0)
+#define	FLUSH() do { \
+	if (uio.uio_resid && __sprint(fp, &uio)) \
+		goto error; \
+	uio.uio_iovcnt = 0; \
+	iovp = iov; \
+} while (0)
+
+	/*
+	 * To extend shorts properly, we need both signed and unsigned
+	 * argument extraction methods.
+	 */
+#define	SARG() \
+	((intmax_t)(flags&MAXINT ? GETARG(intmax_t) : \
+	    flags&LLONGINT ? GETARG(long long) : \
+	    flags&LONGINT ? GETARG(long) : \
+	    flags&PTRINT ? GETARG(ptrdiff_t) : \
+	    flags&SIZEINT ? GETARG(ssize_t) : \
+	    flags&SHORTINT ? (short)GETARG(int) : \
+	    flags&CHARINT ? (__signed char)GETARG(int) : \
+	    GETARG(int)))
+#define	UARG() \
+	((uintmax_t)(flags&MAXINT ? GETARG(uintmax_t) : \
+	    flags&LLONGINT ? GETARG(unsigned long long) : \
+	    flags&LONGINT ? GETARG(unsigned long) : \
+	    flags&PTRINT ? (uintptr_t)GETARG(ptrdiff_t) : /* XXX */ \
+	    flags&SIZEINT ? GETARG(size_t) : \
+	    flags&SHORTINT ? (unsigned short)GETARG(int) : \
+	    flags&CHARINT ? (unsigned char)GETARG(int) : \
+	    GETARG(unsigned int)))
+
+	 /*
+	  * Get * arguments, including the form *nn$.  Preserve the nextarg
+	  * that the argument can be gotten once the type is determined.
+	  */
+#define GETASTER(val) \
+	n2 = 0; \
+	cp = fmt; \
+	while (is_digit(*cp)) { \
+		n2 = 10 * n2 + to_digit(*cp); \
+		cp++; \
+	} \
+	if (*cp == '$') { \
+		int hold = nextarg; \
+		if (argtable == NULL) { \
+			argtable = statargtable; \
+			__find_arguments(fmt0, orgap, &argtable, &argtablesiz); \
+		} \
+		nextarg = n2; \
+		val = GETARG(int); \
+		nextarg = hold; \
+		fmt = ++cp; \
+	} else { \
+		val = GETARG(int); \
+	}
+
+/*
+* Get the argument indexed by nextarg.   If the argument table is
+* built, use it to get the argument.  If its not, get the next
+* argument (and arguments must be gotten sequentially).
+*/
+#define GETARG(type) \
+	(((argtable != NULL) ? (void)(ap = argtable[nextarg]) : (void)0), \
+	 nextarg++, va_arg(ap, type))
+
+	_SET_ORIENTATION(fp, -1);
+	/* sorry, fprintf(read_only_file, "") returns EOF, not 0 */
+	if (cantwrite(fp)) {
+		errno = EBADF;
+		return (EOF);
+	}
+
+	/* optimise fprintf(stderr) (and other unbuffered Unix files) */
+	if ((fp->_flags & (__SNBF|__SWR|__SRW)) == (__SNBF|__SWR) &&
+	    fp->_file >= 0)
+		return (__sbprintf(fp, fmt0, ap));
+
+	fmt = (char *)fmt0;
+	argtable = NULL;
+	nextarg = 1;
+	va_copy(orgap, ap);
+	uio.uio_iov = iovp = iov;
+	uio.uio_resid = 0;
+	uio.uio_iovcnt = 0;
+	ret = 0;
+
+	memset(&ps, 0, sizeof(ps));
+	/*
+	 * Scan the format for conversions (`%' character).
+	 */
+	for (;;) {
+		cp = fmt;
+#if 1  /* BIONIC */
+                n = -1;
+                while ( (wc = *fmt) != 0 ) {
+                    if (wc == '%') {
+                        n = 1;
+                        break;
+                    }
+                    fmt++;
+                }
+#else
+		while ((n = mbrtowc(&wc, fmt, MB_CUR_MAX, &ps)) > 0) {
+			fmt += n;
+			if (wc == '%') {
+				fmt--;
+				break;
+			}
+		}
+#endif
+		if ((m = fmt - cp) != 0) {
+			PRINT(cp, m);
+			ret += m;
+		}
+		if (n <= 0)
+			goto done;
+		fmt++;		/* skip over '%' */
+
+		flags = 0;
+		dprec = 0;
+		width = 0;
+		prec = -1;
+		sign = '\0';
+
+rflag:		ch = *fmt++;
+reswitch:	switch (ch) {
+		case ' ':
+			/*
+			 * ``If the space and + flags both appear, the space
+			 * flag will be ignored.''
+			 *	-- ANSI X3J11
+			 */
+			if (!sign)
+				sign = ' ';
+			goto rflag;
+		case '#':
+			flags |= ALT;
+			goto rflag;
+		case '*':
+			/*
+			 * ``A negative field width argument is taken as a
+			 * - flag followed by a positive field width.''
+			 *	-- ANSI X3J11
+			 * They don't exclude field widths read from args.
+			 */
+			GETASTER(width);
+			if (width >= 0)
+				goto rflag;
+			width = -width;
+			/* FALLTHROUGH */
+		case '-':
+			flags |= LADJUST;
+			goto rflag;
+		case '+':
+			sign = '+';
+			goto rflag;
+		case '.':
+			if ((ch = *fmt++) == '*') {
+				GETASTER(n);
+				prec = n < 0 ? -1 : n;
+				goto rflag;
+			}
+			n = 0;
+			while (is_digit(ch)) {
+				n = 10 * n + to_digit(ch);
+				ch = *fmt++;
+			}
+			if (ch == '$') {
+				nextarg = n;
+				if (argtable == NULL) {
+					argtable = statargtable;
+					__find_arguments(fmt0, orgap,
+					    &argtable, &argtablesiz);
+				}
+				goto rflag;
+			}
+			prec = n < 0 ? -1 : n;
+			goto reswitch;
+		case '0':
+			/*
+			 * ``Note that 0 is taken as a flag, not as the
+			 * beginning of a field width.''
+			 *	-- ANSI X3J11
+			 */
+			flags |= ZEROPAD;
+			goto rflag;
+		case '1': case '2': case '3': case '4':
+		case '5': case '6': case '7': case '8': case '9':
+			n = 0;
+			do {
+				n = 10 * n + to_digit(ch);
+				ch = *fmt++;
+			} while (is_digit(ch));
+			if (ch == '$') {
+				nextarg = n;
+				if (argtable == NULL) {
+					argtable = statargtable;
+					__find_arguments(fmt0, orgap,
+					    &argtable, &argtablesiz);
+				}
+				goto rflag;
+			}
+			width = n;
+			goto reswitch;
+#ifdef FLOATING_POINT
+		case 'L':
+			flags |= LONGDBL;
+			goto rflag;
+#endif
+		case 'h':
+			flags |= SHORTINT;
+			goto rflag;
+		case 'j':
+			flags |= MAXINT;
+			goto rflag;
+		case 'l':
+			if (*fmt == 'l') {
+				fmt++;
+				flags |= LLONGINT;
+			} else {
+				flags |= LONGINT;
+			}
+			goto rflag;
+		case 'q':
+			flags |= LLONGINT;
+			goto rflag;
+		case 't':
+			flags |= PTRINT;
+			goto rflag;
+		case 'z':
+			flags |= SIZEINT;
+			goto rflag;
+		case 'c':
+			*(cp = buf) = GETARG(int);
+			size = 1;
+			sign = '\0';
+			break;
+		case 'D':
+			flags |= LONGINT;
+			/*FALLTHROUGH*/
+		case 'd':
+		case 'i':
+			_umax = SARG();
+			if ((intmax_t)_umax < 0) {
+				_umax = -_umax;
+				sign = '-';
+			}
+			base = DEC;
+			goto number;
+#ifdef FLOATING_POINT
+		case 'e':
+		case 'E':
+		case 'f':
+		case 'g':
+		case 'G':
+			if (prec == -1) {
+				prec = DEFPREC;
+			} else if ((ch == 'g' || ch == 'G') && prec == 0) {
+				prec = 1;
+			}
+
+			if (flags & LONGDBL) {
+				_double = (double) GETARG(long double);
+			} else {
+				_double = GETARG(double);
+			}
+
+			/* do this before tricky precision changes */
+			if (_my_isinf(_double)) {
+				if (_double < 0)
+					sign = '-';
+				cp = "Inf";
+				size = 3;
+				break;
+			}
+			if (_my_isnan(_double)) {
+				cp = "NaN";
+				size = 3;
+				break;
+			}
+
+			flags |= FPT;
+			cp = cvt(_double, prec, flags, &softsign,
+				&expt, ch, &ndig);
+		    cp_free = cp;
+			if (ch == 'g' || ch == 'G') {
+				if (expt <= -4 || expt > prec)
+					ch = (ch == 'g') ? 'e' : 'E';
+				else
+					ch = 'g';
+			}
+			if (ch <= 'e') {	/* 'e' or 'E' fmt */
+				--expt;
+				expsize = exponent(expstr, expt, ch);
+				size = expsize + ndig;
+				if (ndig > 1 || flags & ALT)
+					++size;
+			} else if (ch == 'f') {		/* f fmt */
+				if (expt > 0) {
+					size = expt;
+					if (prec || flags & ALT)
+						size += prec + 1;
+				} else	/* "0.X" */
+					size = prec + 2;
+			} else if (expt >= ndig) {	/* fixed g fmt */
+				size = expt;
+				if (flags & ALT)
+					++size;
+			} else
+				size = ndig + (expt > 0 ?
+					1 : 2 - expt);
+
+			if (softsign)
+				sign = '-';
+			break;
+#endif /* FLOATING_POINT */
+/* the Android security team suggests removing support for %n
+ * since it has no real practical value, and could lead to
+ * running malicious code (for really bugy programs that
+ * send to printf() user-generated formatting strings).
+ */
+#if 0
+		case 'n':
+			if (flags & LLONGINT)
+				*GETARG(long long *) = ret;
+			else if (flags & LONGINT)
+				*GETARG(long *) = ret;
+			else if (flags & SHORTINT)
+				*GETARG(short *) = ret;
+			else if (flags & CHARINT)
+				*GETARG(__signed char *) = ret;
+			else if (flags & PTRINT)
+				*GETARG(ptrdiff_t *) = ret;
+			else if (flags & SIZEINT)
+				*GETARG(ssize_t *) = ret;
+			else if (flags & MAXINT)
+				*GETARG(intmax_t *) = ret;
+			else
+				*GETARG(int *) = ret;
+			continue;	/* no output */
+#endif
+		case 'O':
+			flags |= LONGINT;
+			/*FALLTHROUGH*/
+		case 'o':
+			_umax = UARG();
+			base = OCT;
+			goto nosign;
+		case 'p':
+			/*
+			 * ``The argument shall be a pointer to void.  The
+			 * value of the pointer is converted to a sequence
+			 * of printable characters, in an implementation-
+			 * defined manner.''
+			 *	-- ANSI X3J11
+			 */
+			/* NOSTRICT */
+			_umax = (u_long)GETARG(void *);
+			base = HEX;
+			xdigs = "0123456789abcdef";
+			flags |= HEXPREFIX;
+			ch = 'x';
+			goto nosign;
+		case 's':
+			if ((cp = GETARG(char *)) == NULL)
+				cp = "(null)";
+			if (prec >= 0) {
+				/*
+				 * can't use strlen; can only look for the
+				 * NUL in the first `prec' characters, and
+				 * strlen() will go further.
+				 */
+				char *p = memchr(cp, 0, prec);
+
+				if (p != NULL) {
+					size = p - cp;
+					if (size > prec)
+						size = prec;
+				} else
+					size = prec;
+			} else
+				size = strlen(cp);
+			sign = '\0';
+			break;
+		case 'U':
+			flags |= LONGINT;
+			/*FALLTHROUGH*/
+		case 'u':
+			_umax = UARG();
+			base = DEC;
+			goto nosign;
+		case 'X':
+			xdigs = "0123456789ABCDEF";
+			goto hex;
+		case 'x':
+			xdigs = "0123456789abcdef";
+hex:			_umax = UARG();
+			base = HEX;
+			/* leading 0x/X only if non-zero */
+			if (flags & ALT && _umax != 0)
+				flags |= HEXPREFIX;
+
+			/* unsigned conversions */
+nosign:			sign = '\0';
+			/*
+			 * ``... diouXx conversions ... if a precision is
+			 * specified, the 0 flag will be ignored.''
+			 *	-- ANSI X3J11
+			 */
+number:			if ((dprec = prec) >= 0)
+				flags &= ~ZEROPAD;
+
+			/*
+			 * ``The result of converting a zero value with an
+			 * explicit precision of zero is no characters.''
+			 *	-- ANSI X3J11
+			 */
+			cp = buf + BUF;
+			if (_umax != 0 || prec != 0) {
+				/*
+				 * Unsigned mod is hard, and unsigned mod
+				 * by a constant is easier than that by
+				 * a variable; hence this switch.
+				 */
+				switch (base) {
+				case OCT:
+					do {
+						*--cp = to_char(_umax & 7);
+						_umax >>= 3;
+					} while (_umax);
+					/* handle octal leading 0 */
+					if (flags & ALT && *cp != '0')
+						*--cp = '0';
+					break;
+
+				case DEC:
+					/* many numbers are 1 digit */
+					while (_umax >= 10) {
+						*--cp = to_char(_umax % 10);
+						_umax /= 10;
+					}
+					*--cp = to_char(_umax);
+					break;
+
+				case HEX:
+					do {
+						*--cp = xdigs[_umax & 15];
+						_umax >>= 4;
+					} while (_umax);
+					break;
+
+				default:
+					cp = "bug in vfprintf: bad base";
+					size = strlen(cp);
+					goto skipsize;
+				}
+			}
+			size = buf + BUF - cp;
+		skipsize:
+			break;
+		default:	/* "%?" prints ?, unless ? is NUL */
+			if (ch == '\0')
+				goto done;
+			/* pretend it was %c with argument ch */
+			cp = buf;
+			*cp = ch;
+			size = 1;
+			sign = '\0';
+			break;
+		}
+
+		/*
+		 * All reasonable formats wind up here.  At this point, `cp'
+		 * points to a string which (if not flags&LADJUST) should be
+		 * padded out to `width' places.  If flags&ZEROPAD, it should
+		 * first be prefixed by any sign or other prefix; otherwise,
+		 * it should be blank padded before the prefix is emitted.
+		 * After any left-hand padding and prefixing, emit zeroes
+		 * required by a decimal [diouxX] precision, then print the
+		 * string proper, then emit zeroes required by any leftover
+		 * floating precision; finally, if LADJUST, pad with blanks.
+		 *
+		 * Compute actual size, so we know how much to pad.
+		 * size excludes decimal prec; realsz includes it.
+		 */
+		realsz = dprec > size ? dprec : size;
+		if (sign)
+			realsz++;
+		else if (flags & HEXPREFIX)
+			realsz+= 2;
+
+		/* right-adjusting blank padding */
+		if ((flags & (LADJUST|ZEROPAD)) == 0)
+			PAD(width - realsz, blanks);
+
+		/* prefix */
+		if (sign) {
+			PRINT(&sign, 1);
+		} else if (flags & HEXPREFIX) {
+			ox[0] = '0';
+			ox[1] = ch;
+			PRINT(ox, 2);
+		}
+
+		/* right-adjusting zero padding */
+		if ((flags & (LADJUST|ZEROPAD)) == ZEROPAD)
+			PAD(width - realsz, zeroes);
+
+		/* leading zeroes from decimal precision */
+		PAD(dprec - size, zeroes);
+
+		/* the string or number proper */
+#ifdef FLOATING_POINT
+		if ((flags & FPT) == 0) {
+			PRINT(cp, size);
+		} else {	/* glue together f_p fragments */
+			if (ch >= 'f') {	/* 'f' or 'g' */
+				if (_double == 0) {
+					/* kludge for __dtoa irregularity */
+					PRINT("0", 1);
+					if (expt < ndig || (flags & ALT) != 0) {
+						PRINT(decimal_point, 1);
+						PAD(ndig - 1, zeroes);
+					}
+				} else if (expt <= 0) {
+					PRINT("0", 1);
+					PRINT(decimal_point, 1);
+					PAD(-expt, zeroes);
+					PRINT(cp, ndig);
+				} else if (expt >= ndig) {
+					PRINT(cp, ndig);
+					PAD(expt - ndig, zeroes);
+					if (flags & ALT)
+						PRINT(".", 1);
+				} else {
+					PRINT(cp, expt);
+					cp += expt;
+					PRINT(".", 1);
+					PRINT(cp, ndig-expt);
+				}
+			} else {	/* 'e' or 'E' */
+				if (ndig > 1 || flags & ALT) {
+					ox[0] = *cp++;
+					ox[1] = '.';
+					PRINT(ox, 2);
+					if (_double) {
+						PRINT(cp, ndig-1);
+					} else	/* 0.[0..] */
+						/* __dtoa irregularity */
+						PAD(ndig - 1, zeroes);
+				} else	/* XeYYY */
+					PRINT(cp, 1);
+				PRINT(expstr, expsize);
+			}
+		}
+#else
+		PRINT(cp, size);
+#endif
+		/* left-adjusting padding (always blank) */
+		if (flags & LADJUST)
+			PAD(width - realsz, blanks);
+
+		/* finally, adjust ret */
+		ret += width > realsz ? width : realsz;
+
+		FLUSH();	/* copy out the I/O vectors */
+#if 1   /* BIONIC: remove memory leak when printing doubles */
+		if (cp_free) {
+		  free(cp_free);
+		  cp_free = NULL;
+		}
+#endif
+	}
+done:
+	FLUSH();
+error:
+#if 1   /* BIONIC: remove memory leak when printing doubles */
+    if (cp_free) {
+        free(cp_free);
+        cp_free = NULL;
+    }
+#endif
+	if (argtable != NULL && argtable != statargtable) {
+		munmap(argtable, argtablesiz);
+		argtable = NULL;
+	}
+	return (__sferror(fp) ? EOF : ret);
+	/* NOTREACHED */
+}
+
+/*
+ * Type ids for argument type table.
+ */
+#define T_UNUSED	0
+#define T_SHORT		1
+#define T_U_SHORT	2
+#define TP_SHORT	3
+#define T_INT		4
+#define T_U_INT		5
+#define TP_INT		6
+#define T_LONG		7
+#define T_U_LONG	8
+#define TP_LONG		9
+#define T_LLONG		10
+#define T_U_LLONG	11
+#define TP_LLONG	12
+#define T_DOUBLE	13
+#define T_LONG_DOUBLE	14
+#define TP_CHAR		15
+#define TP_VOID		16
+#define T_PTRINT	17
+#define TP_PTRINT	18
+#define T_SIZEINT	19
+#define T_SSIZEINT	20
+#define TP_SSIZEINT	21
+#define T_MAXINT	22
+#define T_MAXUINT	23
+#define TP_MAXINT	24
+
+/*
+ * Find all arguments when a positional parameter is encountered.  Returns a
+ * table, indexed by argument number, of pointers to each arguments.  The
+ * initial argument table should be an array of STATIC_ARG_TBL_SIZE entries.
+ * It will be replaced with a mmap-ed one if it overflows (malloc cannot be
+ * used since we are attempting to make snprintf thread safe, and alloca is
+ * problematic since we have nested functions..)
+ */
+static void
+__find_arguments(const char *fmt0, va_list ap, va_list **argtable,
+    size_t *argtablesiz)
+{
+	char *fmt;	/* format string */
+	int ch;	/* character from fmt */
+	int n, n2;	/* handy integer (short term usage) */
+	char *cp;	/* handy char pointer (short term usage) */
+	int flags;	/* flags as above */
+	unsigned char *typetable; /* table of types */
+	unsigned char stattypetable[STATIC_ARG_TBL_SIZE];
+	int tablesize;		/* current size of type table */
+	int tablemax;		/* largest used index in table */
+	int nextarg;		/* 1-based argument index */
+	wchar_t wc;
+	void* ps;
+
+	/*
+	 * Add an argument type to the table, expanding if necessary.
+	 */
+#define ADDTYPE(type) \
+	((nextarg >= tablesize) ? \
+		__grow_type_table(&typetable, &tablesize) : 0, \
+	(nextarg > tablemax) ? tablemax = nextarg : 0, \
+	typetable[nextarg++] = type)
+
+#define	ADDSARG() \
+        ((flags&MAXINT) ? ADDTYPE(T_MAXINT) : \
+	    ((flags&PTRINT) ? ADDTYPE(T_PTRINT) : \
+	    ((flags&SIZEINT) ? ADDTYPE(T_SSIZEINT) : \
+	    ((flags&LLONGINT) ? ADDTYPE(T_LLONG) : \
+	    ((flags&LONGINT) ? ADDTYPE(T_LONG) : \
+	    ((flags&SHORTINT) ? ADDTYPE(T_SHORT) : ADDTYPE(T_INT)))))))
+
+#define	ADDUARG() \
+        ((flags&MAXINT) ? ADDTYPE(T_MAXUINT) : \
+	    ((flags&PTRINT) ? ADDTYPE(T_PTRINT) : \
+	    ((flags&SIZEINT) ? ADDTYPE(T_SIZEINT) : \
+	    ((flags&LLONGINT) ? ADDTYPE(T_U_LLONG) : \
+	    ((flags&LONGINT) ? ADDTYPE(T_U_LONG) : \
+	    ((flags&SHORTINT) ? ADDTYPE(T_U_SHORT) : ADDTYPE(T_U_INT)))))))
+
+	/*
+	 * Add * arguments to the type array.
+	 */
+#define ADDASTER() \
+	n2 = 0; \
+	cp = fmt; \
+	while (is_digit(*cp)) { \
+		n2 = 10 * n2 + to_digit(*cp); \
+		cp++; \
+	} \
+	if (*cp == '$') { \
+		int hold = nextarg; \
+		nextarg = n2; \
+		ADDTYPE(T_INT); \
+		nextarg = hold; \
+		fmt = ++cp; \
+	} else { \
+		ADDTYPE(T_INT); \
+	}
+	fmt = (char *)fmt0;
+	typetable = stattypetable;
+	tablesize = STATIC_ARG_TBL_SIZE;
+	tablemax = 0;
+	nextarg = 1;
+	memset(typetable, T_UNUSED, STATIC_ARG_TBL_SIZE);
+	memset(&ps, 0, sizeof(ps));
+
+	/*
+	 * Scan the format for conversions (`%' character).
+	 */
+	for (;;) {
+		cp = fmt;
+#if 1  /* BIONIC */
+                n = -1;
+                while ((wc = *fmt) != 0) {
+                    if (wc == '%') {
+                        n = 1;
+                        break;
+                    }
+                    fmt++;
+                }
+#else
+		while ((n = mbrtowc(&wc, fmt, MB_CUR_MAX, &ps)) > 0) {
+			fmt += n;
+			if (wc == '%') {
+				fmt--;
+				break;
+			}
+		}
+#endif
+		if (n <= 0)
+			goto done;
+		fmt++;		/* skip over '%' */
+
+		flags = 0;
+
+rflag:		ch = *fmt++;
+reswitch:	switch (ch) {
+		case ' ':
+		case '#':
+			goto rflag;
+		case '*':
+			ADDASTER();
+			goto rflag;
+		case '-':
+		case '+':
+			goto rflag;
+		case '.':
+			if ((ch = *fmt++) == '*') {
+				ADDASTER();
+				goto rflag;
+			}
+			while (is_digit(ch)) {
+				ch = *fmt++;
+			}
+			goto reswitch;
+		case '0':
+			goto rflag;
+		case '1': case '2': case '3': case '4':
+		case '5': case '6': case '7': case '8': case '9':
+			n = 0;
+			do {
+				n = 10 * n + to_digit(ch);
+				ch = *fmt++;
+			} while (is_digit(ch));
+			if (ch == '$') {
+				nextarg = n;
+				goto rflag;
+			}
+			goto reswitch;
+#ifdef FLOATING_POINT
+		case 'L':
+			flags |= LONGDBL;
+			goto rflag;
+#endif
+		case 'h':
+			if (*fmt == 'h') {
+				fmt++;
+				flags |= CHARINT;
+			} else {
+				flags |= SHORTINT;
+			}
+			goto rflag;
+		case 'l':
+			if (*fmt == 'l') {
+				fmt++;
+				flags |= LLONGINT;
+			} else {
+				flags |= LONGINT;
+			}
+			goto rflag;
+		case 'q':
+			flags |= LLONGINT;
+			goto rflag;
+		case 't':
+			flags |= PTRINT;
+			goto rflag;
+		case 'z':
+			flags |= SIZEINT;
+			goto rflag;
+		case 'c':
+			ADDTYPE(T_INT);
+			break;
+		case 'D':
+			flags |= LONGINT;
+			/*FALLTHROUGH*/
+		case 'd':
+		case 'i':
+			ADDSARG();
+			break;
+#ifdef FLOATING_POINT
+		case 'e':
+		case 'E':
+		case 'f':
+		case 'g':
+		case 'G':
+			if (flags & LONGDBL)
+				ADDTYPE(T_LONG_DOUBLE);
+			else
+				ADDTYPE(T_DOUBLE);
+			break;
+#endif /* FLOATING_POINT */
+		case 'n':
+			if (flags & LLONGINT)
+				ADDTYPE(TP_LLONG);
+			else if (flags & LONGINT)
+				ADDTYPE(TP_LONG);
+			else if (flags & SHORTINT)
+				ADDTYPE(TP_SHORT);
+			else if (flags & PTRINT)
+				ADDTYPE(TP_PTRINT);
+			else if (flags & SIZEINT)
+				ADDTYPE(TP_SSIZEINT);
+			else if (flags & MAXINT)
+				ADDTYPE(TP_MAXINT);
+			else
+				ADDTYPE(TP_INT);
+			continue;	/* no output */
+		case 'O':
+			flags |= LONGINT;
+			/*FALLTHROUGH*/
+		case 'o':
+			ADDUARG();
+			break;
+		case 'p':
+			ADDTYPE(TP_VOID);
+			break;
+		case 's':
+			ADDTYPE(TP_CHAR);
+			break;
+		case 'U':
+			flags |= LONGINT;
+			/*FALLTHROUGH*/
+		case 'u':
+		case 'X':
+		case 'x':
+			ADDUARG();
+			break;
+		default:	/* "%?" prints ?, unless ? is NUL */
+			if (ch == '\0')
+				goto done;
+			break;
+		}
+	}
+done:
+	/*
+	 * Build the argument table.
+	 */
+	if (tablemax >= STATIC_ARG_TBL_SIZE) {
+		*argtablesiz = sizeof (va_list) * (tablemax + 1);
+		*argtable = (va_list *)mmap(NULL, *argtablesiz,
+		    PROT_WRITE|PROT_READ, MAP_ANON|MAP_PRIVATE, -1, 0);
+	}
+
+#if 0
+	/* XXX is this required? */
+	(*argtable) [0] = NULL;
+#endif
+	for (n = 1; n <= tablemax; n++) {
+		va_copy((*argtable)[n], ap);
+		switch (typetable[n]) {
+		case T_UNUSED:
+			(void) va_arg(ap, int);
+			break;
+		case T_SHORT:
+			(void) va_arg(ap, int);
+			break;
+		case T_U_SHORT:
+			(void) va_arg(ap, int);
+			break;
+		case TP_SHORT:
+			(void) va_arg(ap, short *);
+			break;
+		case T_INT:
+			(void) va_arg(ap, int);
+			break;
+		case T_U_INT:
+			(void) va_arg(ap, unsigned int);
+			break;
+		case TP_INT:
+			(void) va_arg(ap, int *);
+			break;
+		case T_LONG:
+			(void) va_arg(ap, long);
+			break;
+		case T_U_LONG:
+			(void) va_arg(ap, unsigned long);
+			break;
+		case TP_LONG:
+			(void) va_arg(ap, long *);
+			break;
+		case T_LLONG:
+			(void) va_arg(ap, long long);
+			break;
+		case T_U_LLONG:
+			(void) va_arg(ap, unsigned long long);
+			break;
+		case TP_LLONG:
+			(void) va_arg(ap, long long *);
+			break;
+		case T_DOUBLE:
+			(void) va_arg(ap, double);
+			break;
+		case T_LONG_DOUBLE:
+			(void) va_arg(ap, long double);
+			break;
+		case TP_CHAR:
+			(void) va_arg(ap, char *);
+			break;
+		case TP_VOID:
+			(void) va_arg(ap, void *);
+			break;
+		case T_PTRINT:
+			(void) va_arg(ap, ptrdiff_t);
+			break;
+		case TP_PTRINT:
+			(void) va_arg(ap, ptrdiff_t *);
+			break;
+		case T_SIZEINT:
+			(void) va_arg(ap, size_t);
+			break;
+		case T_SSIZEINT:
+			(void) va_arg(ap, ssize_t);
+			break;
+		case TP_SSIZEINT:
+			(void) va_arg(ap, ssize_t *);
+			break;
+		case TP_MAXINT:
+			(void) va_arg(ap, intmax_t *);
+			break;
+		}
+	}
+
+	if (typetable != NULL && typetable != stattypetable) {
+		munmap(typetable, *argtablesiz);
+		typetable = NULL;
+	}
+}
+
+/*
+ * Increase the size of the type table.
+ */
+static int
+__grow_type_table(unsigned char **typetable, int *tablesize)
+{
+	unsigned char *oldtable = *typetable;
+	int newsize = *tablesize * 2;
+
+	if (*tablesize == STATIC_ARG_TBL_SIZE) {
+		*typetable = (unsigned char *)mmap(NULL,
+		    sizeof (unsigned char) * newsize, PROT_WRITE|PROT_READ,
+		    MAP_ANON|MAP_PRIVATE, -1, 0);
+		/* XXX unchecked */
+		memcpy( *typetable, oldtable, *tablesize);
+	} else {
+		unsigned char *new = (unsigned char *)mmap(NULL,
+		    sizeof (unsigned char) * newsize, PROT_WRITE|PROT_READ,
+		    MAP_ANON|MAP_PRIVATE, -1, 0);
+		memmove(new, *typetable, *tablesize);
+		munmap(*typetable, *tablesize);
+		*typetable = new;
+		/* XXX unchecked */
+	}
+	memset(*typetable + *tablesize, T_UNUSED, (newsize - *tablesize));
+
+	*tablesize = newsize;
+	return(0);
+}
+
+
+#ifdef FLOATING_POINT
+
+extern char *__dtoa(double, int, int, int *, int *, char **);
+
+static char *
+cvt(double value, int ndigits, int flags, char *sign, int *decpt, int ch,
+    int *length)
+{
+	int mode, dsgn;
+	char *digits, *bp, *rve;
+	static  char  temp[64];
+
+	if (ch == 'f') {
+		mode = 3;		/* ndigits after the decimal point */
+	} else {
+		/* To obtain ndigits after the decimal point for the 'e'
+		 * and 'E' formats, round to ndigits + 1 significant
+		 * figures.
+		 */
+		if (ch == 'e' || ch == 'E') {
+			ndigits++;
+		}
+		mode = 2;		/* ndigits significant digits */
+	}
+
+	if (value < 0) {
+		value = -value;
+		*sign = '-';
+	} else
+		*sign = '\000';
+	digits = __dtoa(value, mode, ndigits, decpt, &dsgn, &rve);
+	if ((ch != 'g' && ch != 'G') || flags & ALT) {	/* Print trailing zeros */
+		bp = digits + ndigits;
+		if (ch == 'f') {
+			if (*digits == '0' && value)
+				*decpt = -ndigits + 1;
+			bp += *decpt;
+		}
+		if (value == 0)	/* kludge for __dtoa irregularity */
+			rve = bp;
+		while (rve < bp)
+			*rve++ = '0';
+	}
+	*length = rve - digits;
+	return (digits);
+}
+
+static int
+exponent(char *p0, int exp, int fmtch)
+{
+	char *p, *t;
+	char expbuf[MAXEXP];
+
+	p = p0;
+	*p++ = fmtch;
+	if (exp < 0) {
+		exp = -exp;
+		*p++ = '-';
+	}
+	else
+		*p++ = '+';
+	t = expbuf + MAXEXP;
+	if (exp > 9) {
+		do {
+			*--t = to_char(exp % 10);
+		} while ((exp /= 10) > 9);
+		*--t = to_char(exp);
+		for (; t < expbuf + MAXEXP; *p++ = *t++);
+	}
+	else {
+		*p++ = '0';
+		*p++ = to_char(exp);
+	}
+	return (p - p0);
+}
+
+
+/* BIONIC */
+#include <machine/ieee.h>
+typedef union {
+    double              d;
+    struct ieee_double  i;
+} ieee_u;
+
+static int
+_my_isinf (double  value)
+{
+    ieee_u   u;
+
+    u.d = value;
+    return (u.i.dbl_exp == 2047 && u.i.dbl_frach == 0 && u.i.dbl_fracl == 0);
+}
+
+static int
+_my_isnan (double  value)
+{
+    ieee_u   u;
+
+    u.d = value;
+    return (u.i.dbl_exp == 2047 && (u.i.dbl_frach != 0 || u.i.dbl_fracl != 0));
+}
+#endif /* FLOATING_POINT */
diff --git a/libc/stdio/vfscanf.c b/libc/stdio/vfscanf.c
new file mode 100644
index 0000000..dbd0a8b
--- /dev/null
+++ b/libc/stdio/vfscanf.c
@@ -0,0 +1,791 @@
+/*	$OpenBSD: vfscanf.c,v 1.21 2006/01/13 21:33:28 millert Exp $ */
+/*-
+ * Copyright (c) 1990, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <ctype.h>
+#include <inttypes.h>
+#include <stdarg.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include "local.h"
+
+#ifdef FLOATING_POINT
+#include "floatio.h"
+#endif
+
+#define	BUF		513	/* Maximum length of numeric string. */
+
+/*
+ * Flags used during conversion.
+ */
+#define	LONG		0x00001	/* l: long or double */
+#define	LONGDBL		0x00002	/* L: long double; unimplemented */
+#define	SHORT		0x00004	/* h: short */
+#define	SHORTSHORT	0x00008	/* hh: 8 bit integer */
+#define LLONG		0x00010	/* ll: long long (+ deprecated q: quad) */
+#define	POINTER		0x00020	/* p: void * (as hex) */
+#define	SIZEINT		0x00040	/* z: (signed) size_t */
+#define	MAXINT		0x00080	/* j: intmax_t */
+#define	PTRINT		0x00100	/* t: ptrdiff_t */
+#define	NOSKIP		0x00200	/* [ or c: do not skip blanks */
+#define	SUPPRESS	0x00400	/* *: suppress assignment */
+#define	UNSIGNED	0x00800	/* %[oupxX] conversions */
+
+/*
+ * The following are used in numeric conversions only:
+ * SIGNOK, HAVESIGN, NDIGITS, DPTOK, and EXPOK are for floating point;
+ * SIGNOK, HAVESIGN, NDIGITS, PFXOK, and NZDIGITS are for integral.
+ */
+#define	SIGNOK		0x01000	/* +/- is (still) legal */
+#define	HAVESIGN	0x02000	/* sign detected */
+#define	NDIGITS		0x04000	/* no digits detected */
+
+#define	DPTOK		0x08000	/* (float) decimal point is still legal */
+#define	EXPOK		0x10000	/* (float) exponent (e+3, etc) still legal */
+
+#define	PFXOK		0x08000	/* 0x prefix is (still) legal */
+#define	NZDIGITS	0x10000	/* no zero digits detected */
+
+/*
+ * Conversion types.
+ */
+#define	CT_CHAR		0	/* %c conversion */
+#define	CT_CCL		1	/* %[...] conversion */
+#define	CT_STRING	2	/* %s conversion */
+#define	CT_INT		3	/* integer, i.e., strtoimax or strtoumax */
+#define	CT_FLOAT	4	/* floating, i.e., strtod */
+
+#define u_char unsigned char
+#define u_long unsigned long
+
+static u_char *__sccl(char *, u_char *);
+
+#if !defined(VFSCANF)
+#define VFSCANF	vfscanf
+#endif
+
+/*
+ * vfscanf
+ */
+int
+VFSCANF(FILE *fp, const char *fmt0, __va_list ap)
+{
+	u_char *fmt = (u_char *)fmt0;
+	int c;		/* character from format, or conversion */
+	size_t width;	/* field width, or 0 */
+	char *p;	/* points into all kinds of strings */
+	int n;		/* handy integer */
+	int flags;	/* flags as defined above */
+	char *p0;	/* saves original value of p when necessary */
+	int nassigned;		/* number of fields assigned */
+	int nread;		/* number of characters consumed from fp */
+	int base;		/* base argument to strtoimax/strtouimax */
+	char ccltab[256];	/* character class table for %[...] */
+	char buf[BUF];		/* buffer for numeric conversions */
+
+	/* `basefix' is used to avoid `if' tests in the integer scanner */
+	static short basefix[17] =
+		{ 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 };
+
+	_SET_ORIENTATION(fp, -1);
+
+	nassigned = 0;
+	nread = 0;
+	base = 0;		/* XXX just to keep gcc happy */
+	for (;;) {
+		c = *fmt++;
+		if (c == 0)
+			return (nassigned);
+		if (isspace(c)) {
+			while ((fp->_r > 0 || __srefill(fp) == 0) &&
+			    isspace(*fp->_p))
+				nread++, fp->_r--, fp->_p++;
+			continue;
+		}
+		if (c != '%')
+			goto literal;
+		width = 0;
+		flags = 0;
+		/*
+		 * switch on the format.  continue if done;
+		 * break once format type is derived.
+		 */
+again:		c = *fmt++;
+		switch (c) {
+		case '%':
+literal:
+			if (fp->_r <= 0 && __srefill(fp))
+				goto input_failure;
+			if (*fp->_p != c)
+				goto match_failure;
+			fp->_r--, fp->_p++;
+			nread++;
+			continue;
+
+		case '*':
+			flags |= SUPPRESS;
+			goto again;
+		case 'j':
+			flags |= MAXINT;
+			goto again;
+		case 'L':
+			flags |= LONGDBL;
+			goto again;
+		case 'h':
+			if (*fmt == 'h') {
+				fmt++;
+				flags |= SHORTSHORT;
+			} else {
+				flags |= SHORT;
+			}
+			goto again;
+		case 'l':
+			if (*fmt == 'l') {
+				fmt++;
+				flags |= LLONG;
+			} else {
+				flags |= LONG;
+			}
+			goto again;
+		case 'q':
+			flags |= LLONG;		/* deprecated */
+			goto again;
+		case 't':
+			flags |= PTRINT;
+			goto again;
+		case 'z':
+			flags |= SIZEINT;
+			goto again;
+
+		case '0': case '1': case '2': case '3': case '4':
+		case '5': case '6': case '7': case '8': case '9':
+			width = width * 10 + c - '0';
+			goto again;
+
+		/*
+		 * Conversions.
+		 * Those marked `compat' are for 4.[123]BSD compatibility.
+		 *
+		 * (According to ANSI, E and X formats are supposed
+		 * to the same as e and x.  Sorry about that.)
+		 */
+		case 'D':	/* compat */
+			flags |= LONG;
+			/* FALLTHROUGH */
+		case 'd':
+			c = CT_INT;
+			base = 10;
+			break;
+
+		case 'i':
+			c = CT_INT;
+			base = 0;
+			break;
+
+		case 'O':	/* compat */
+			flags |= LONG;
+			/* FALLTHROUGH */
+		case 'o':
+			c = CT_INT;
+			flags |= UNSIGNED;
+			base = 8;
+			break;
+
+		case 'u':
+			c = CT_INT;
+			flags |= UNSIGNED;
+			base = 10;
+			break;
+
+		case 'X':
+		case 'x':
+			flags |= PFXOK;	/* enable 0x prefixing */
+			c = CT_INT;
+			flags |= UNSIGNED;
+			base = 16;
+			break;
+
+#ifdef FLOATING_POINT
+		case 'E':
+		case 'G':
+		case 'e': 
+		case 'f': 
+		case 'g':
+			c = CT_FLOAT;
+			break;
+#endif
+
+		case 's':
+			c = CT_STRING;
+			break;
+
+		case '[':
+			fmt = __sccl(ccltab, fmt);
+			flags |= NOSKIP;
+			c = CT_CCL;
+			break;
+
+		case 'c':
+			flags |= NOSKIP;
+			c = CT_CHAR;
+			break;
+
+		case 'p':	/* pointer format is like hex */
+			flags |= POINTER | PFXOK;
+			c = CT_INT;
+			flags |= UNSIGNED;
+			base = 16;
+			break;
+
+		case 'n':
+			if (flags & SUPPRESS)
+				continue;
+			if (flags & SHORTSHORT)
+				*va_arg(ap, __signed char *) = nread;
+			else if (flags & SHORT)
+				*va_arg(ap, short *) = nread;
+			else if (flags & LONG)
+				*va_arg(ap, long *) = nread;
+			else if (flags & SIZEINT)
+				*va_arg(ap, ssize_t *) = nread;
+			else if (flags & PTRINT)
+				*va_arg(ap, ptrdiff_t *) = nread;
+			else if (flags & LLONG)
+				*va_arg(ap, long long *) = nread;
+			else if (flags & MAXINT)
+				*va_arg(ap, intmax_t *) = nread;
+			else
+				*va_arg(ap, int *) = nread;
+			continue;
+
+		/*
+		 * Disgusting backwards compatibility hacks.	XXX
+		 */
+		case '\0':	/* compat */
+			return (EOF);
+
+		default:	/* compat */
+			if (isupper(c))
+				flags |= LONG;
+			c = CT_INT;
+			base = 10;
+			break;
+		}
+
+		/*
+		 * We have a conversion that requires input.
+		 */
+		if (fp->_r <= 0 && __srefill(fp))
+			goto input_failure;
+
+		/*
+		 * Consume leading white space, except for formats
+		 * that suppress this.
+		 */
+		if ((flags & NOSKIP) == 0) {
+			while (isspace(*fp->_p)) {
+				nread++;
+				if (--fp->_r > 0)
+					fp->_p++;
+				else if (__srefill(fp))
+					goto input_failure;
+			}
+			/*
+			 * Note that there is at least one character in
+			 * the buffer, so conversions that do not set NOSKIP
+			 * ca no longer result in an input failure.
+			 */
+		}
+
+		/*
+		 * Do the conversion.
+		 */
+		switch (c) {
+
+		case CT_CHAR:
+			/* scan arbitrary characters (sets NOSKIP) */
+			if (width == 0)
+				width = 1;
+			if (flags & SUPPRESS) {
+				size_t sum = 0;
+				for (;;) {
+					if ((n = fp->_r) < (int)width) {
+						sum += n;
+						width -= n;
+						fp->_p += n;
+						if (__srefill(fp)) {
+							if (sum == 0)
+							    goto input_failure;
+							break;
+						}
+					} else {
+						sum += width;
+						fp->_r -= width;
+						fp->_p += width;
+						break;
+					}
+				}
+				nread += sum;
+			} else {
+				size_t r = fread((void *)va_arg(ap, char *), 1,
+				    width, fp);
+
+				if (r == 0)
+					goto input_failure;
+				nread += r;
+				nassigned++;
+			}
+			break;
+
+		case CT_CCL:
+			/* scan a (nonempty) character class (sets NOSKIP) */
+			if (width == 0)
+				width = (size_t)~0;	/* `infinity' */
+			/* take only those things in the class */
+			if (flags & SUPPRESS) {
+				n = 0;
+				while (ccltab[*fp->_p]) {
+					n++, fp->_r--, fp->_p++;
+					if (--width == 0)
+						break;
+					if (fp->_r <= 0 && __srefill(fp)) {
+						if (n == 0)
+							goto input_failure;
+						break;
+					}
+				}
+				if (n == 0)
+					goto match_failure;
+			} else {
+				p0 = p = va_arg(ap, char *);
+				while (ccltab[*fp->_p]) {
+					fp->_r--;
+					*p++ = *fp->_p++;
+					if (--width == 0)
+						break;
+					if (fp->_r <= 0 && __srefill(fp)) {
+						if (p == p0)
+							goto input_failure;
+						break;
+					}
+				}
+				n = p - p0;
+				if (n == 0)
+					goto match_failure;
+				*p = '\0';
+				nassigned++;
+			}
+			nread += n;
+			break;
+
+		case CT_STRING:
+			/* like CCL, but zero-length string OK, & no NOSKIP */
+			if (width == 0)
+				width = (size_t)~0;
+			if (flags & SUPPRESS) {
+				n = 0;
+				while (!isspace(*fp->_p)) {
+					n++, fp->_r--, fp->_p++;
+					if (--width == 0)
+						break;
+					if (fp->_r <= 0 && __srefill(fp))
+						break;
+				}
+				nread += n;
+			} else {
+				p0 = p = va_arg(ap, char *);
+				while (!isspace(*fp->_p)) {
+					fp->_r--;
+					*p++ = *fp->_p++;
+					if (--width == 0)
+						break;
+					if (fp->_r <= 0 && __srefill(fp))
+						break;
+				}
+				*p = '\0';
+				nread += p - p0;
+				nassigned++;
+			}
+			continue;
+
+		case CT_INT:
+			/* scan an integer as if by strtoimax/strtoumax */
+#ifdef hardway
+			if (width == 0 || width > sizeof(buf) - 1)
+				width = sizeof(buf) - 1;
+#else
+			/* size_t is unsigned, hence this optimisation */
+			if (--width > sizeof(buf) - 2)
+				width = sizeof(buf) - 2;
+			width++;
+#endif
+			flags |= SIGNOK | NDIGITS | NZDIGITS;
+			for (p = buf; width; width--) {
+				c = *fp->_p;
+				/*
+				 * Switch on the character; `goto ok'
+				 * if we accept it as a part of number.
+				 */
+				switch (c) {
+
+				/*
+				 * The digit 0 is always legal, but is
+				 * special.  For %i conversions, if no
+				 * digits (zero or nonzero) have been
+				 * scanned (only signs), we will have
+				 * base==0.  In that case, we should set
+				 * it to 8 and enable 0x prefixing.
+				 * Also, if we have not scanned zero digits
+				 * before this, do not turn off prefixing
+				 * (someone else will turn it off if we
+				 * have scanned any nonzero digits).
+				 */
+				case '0':
+					if (base == 0) {
+						base = 8;
+						flags |= PFXOK;
+					}
+					if (flags & NZDIGITS)
+					    flags &= ~(SIGNOK|NZDIGITS|NDIGITS);
+					else
+					    flags &= ~(SIGNOK|PFXOK|NDIGITS);
+					goto ok;
+
+				/* 1 through 7 always legal */
+				case '1': case '2': case '3':
+				case '4': case '5': case '6': case '7':
+					base = basefix[base];
+					flags &= ~(SIGNOK | PFXOK | NDIGITS);
+					goto ok;
+
+				/* digits 8 and 9 ok iff decimal or hex */
+				case '8': case '9':
+					base = basefix[base];
+					if (base <= 8)
+						break;	/* not legal here */
+					flags &= ~(SIGNOK | PFXOK | NDIGITS);
+					goto ok;
+
+				/* letters ok iff hex */
+				case 'A': case 'B': case 'C':
+				case 'D': case 'E': case 'F':
+				case 'a': case 'b': case 'c':
+				case 'd': case 'e': case 'f':
+					/* no need to fix base here */
+					if (base <= 10)
+						break;	/* not legal here */
+					flags &= ~(SIGNOK | PFXOK | NDIGITS);
+					goto ok;
+
+				/* sign ok only as first character */
+				case '+': case '-':
+					if (flags & SIGNOK) {
+						flags &= ~SIGNOK;
+						flags |= HAVESIGN;
+						goto ok;
+					}
+					break;
+
+				/*
+				 * x ok iff flag still set and 2nd char (or
+				 * 3rd char if we have a sign).
+				 */
+				case 'x': case 'X':
+					if ((flags & PFXOK) && p ==
+					    buf + 1 + !!(flags & HAVESIGN)) {
+						base = 16;	/* if %i */
+						flags &= ~PFXOK;
+						goto ok;
+					}
+					break;
+				}
+
+				/*
+				 * If we got here, c is not a legal character
+				 * for a number.  Stop accumulating digits.
+				 */
+				break;
+		ok:
+				/*
+				 * c is legal: store it and look at the next.
+				 */
+				*p++ = c;
+				if (--fp->_r > 0)
+					fp->_p++;
+				else if (__srefill(fp))
+					break;		/* EOF */
+			}
+			/*
+			 * If we had only a sign, it is no good; push
+			 * back the sign.  If the number ends in `x',
+			 * it was [sign] '0' 'x', so push back the x
+			 * and treat it as [sign] '0'.
+			 */
+			if (flags & NDIGITS) {
+				if (p > buf)
+					(void) ungetc(*(u_char *)--p, fp);
+				goto match_failure;
+			}
+			c = ((u_char *)p)[-1];
+			if (c == 'x' || c == 'X') {
+				--p;
+				(void) ungetc(c, fp);
+			}
+			if ((flags & SUPPRESS) == 0) {
+				uintmax_t res;
+
+				*p = '\0';
+				if (flags & UNSIGNED)
+					res = strtoumax(buf, NULL, base);
+				else
+					res = strtoimax(buf, NULL, base);
+				if (flags & POINTER)
+					*va_arg(ap, void **) =
+					    (void *)(uintptr_t)res;
+				else if (flags & MAXINT)
+					*va_arg(ap, intmax_t *) = res;
+				else if (flags & LLONG)
+					*va_arg(ap, long long *) = res;
+				else if (flags & SIZEINT)
+					*va_arg(ap, ssize_t *) = res;
+				else if (flags & PTRINT)
+					*va_arg(ap, ptrdiff_t *) = res;
+				else if (flags & LONG)
+					*va_arg(ap, long *) = res;
+				else if (flags & SHORT)
+					*va_arg(ap, short *) = res;
+				else if (flags & SHORTSHORT)
+					*va_arg(ap, __signed char *) = res;
+				else
+					*va_arg(ap, int *) = res;
+				nassigned++;
+			}
+			nread += p - buf;
+			break;
+
+#ifdef FLOATING_POINT
+		case CT_FLOAT:
+			/* scan a floating point number as if by strtod */
+#ifdef hardway
+			if (width == 0 || width > sizeof(buf) - 1)
+				width = sizeof(buf) - 1;
+#else
+			/* size_t is unsigned, hence this optimisation */
+			if (--width > sizeof(buf) - 2)
+				width = sizeof(buf) - 2;
+			width++;
+#endif
+			flags |= SIGNOK | NDIGITS | DPTOK | EXPOK;
+			for (p = buf; width; width--) {
+				c = *fp->_p;
+				/*
+				 * This code mimicks the integer conversion
+				 * code, but is much simpler.
+				 */
+				switch (c) {
+
+				case '0': case '1': case '2': case '3':
+				case '4': case '5': case '6': case '7':
+				case '8': case '9':
+					flags &= ~(SIGNOK | NDIGITS);
+					goto fok;
+
+				case '+': case '-':
+					if (flags & SIGNOK) {
+						flags &= ~SIGNOK;
+						goto fok;
+					}
+					break;
+				case '.':
+					if (flags & DPTOK) {
+						flags &= ~(SIGNOK | DPTOK);
+						goto fok;
+					}
+					break;
+				case 'e': case 'E':
+					/* no exponent without some digits */
+					if ((flags&(NDIGITS|EXPOK)) == EXPOK) {
+						flags =
+						    (flags & ~(EXPOK|DPTOK)) |
+						    SIGNOK | NDIGITS;
+						goto fok;
+					}
+					break;
+				}
+				break;
+		fok:
+				*p++ = c;
+				if (--fp->_r > 0)
+					fp->_p++;
+				else if (__srefill(fp))
+					break;	/* EOF */
+			}
+			/*
+			 * If no digits, might be missing exponent digits
+			 * (just give back the exponent) or might be missing
+			 * regular digits, but had sign and/or decimal point.
+			 */
+			if (flags & NDIGITS) {
+				if (flags & EXPOK) {
+					/* no digits at all */
+					while (p > buf)
+						ungetc(*(u_char *)--p, fp);
+					goto match_failure;
+				}
+				/* just a bad exponent (e and maybe sign) */
+				c = *(u_char *)--p;
+				if (c != 'e' && c != 'E') {
+					(void) ungetc(c, fp);/* sign */
+					c = *(u_char *)--p;
+				}
+				(void) ungetc(c, fp);
+			}
+			if ((flags & SUPPRESS) == 0) {
+				double res;
+
+				*p = '\0';
+				res = strtod(buf, (char **) NULL);
+				if (flags & LONGDBL)
+					*va_arg(ap, long double *) = res;
+				else if (flags & LONG)
+					*va_arg(ap, double *) = res;
+				else
+					*va_arg(ap, float *) = res;
+				nassigned++;
+			}
+			nread += p - buf;
+			break;
+#endif /* FLOATING_POINT */
+		}
+	}
+input_failure:
+	return (nassigned ? nassigned : -1);
+match_failure:
+	return (nassigned);
+}
+
+/*
+ * Fill in the given table from the scanset at the given format
+ * (just after `[').  Return a pointer to the character past the
+ * closing `]'.  The table has a 1 wherever characters should be
+ * considered part of the scanset.
+ */
+static u_char *
+__sccl(char *tab, u_char *fmt)
+{
+	int c, n, v;
+
+	/* first `clear' the whole table */
+	c = *fmt++;		/* first char hat => negated scanset */
+	if (c == '^') {
+		v = 1;		/* default => accept */
+		c = *fmt++;	/* get new first char */
+	} else
+		v = 0;		/* default => reject */
+	/* should probably use memset here */
+	for (n = 0; n < 256; n++)
+		tab[n] = v;
+	if (c == 0)
+		return (fmt - 1);/* format ended before closing ] */
+
+	/*
+	 * Now set the entries corresponding to the actual scanset
+	 * to the opposite of the above.
+	 *
+	 * The first character may be ']' (or '-') without being special;
+	 * the last character may be '-'.
+	 */
+	v = 1 - v;
+	for (;;) {
+		tab[c] = v;		/* take character c */
+doswitch:
+		n = *fmt++;		/* and examine the next */
+		switch (n) {
+
+		case 0:			/* format ended too soon */
+			return (fmt - 1);
+
+		case '-':
+			/*
+			 * A scanset of the form
+			 *	[01+-]
+			 * is defined as `the digit 0, the digit 1,
+			 * the character +, the character -', but
+			 * the effect of a scanset such as
+			 *	[a-zA-Z0-9]
+			 * is implementation defined.  The V7 Unix
+			 * scanf treats `a-z' as `the letters a through
+			 * z', but treats `a-a' as `the letter a, the
+			 * character -, and the letter a'.
+			 *
+			 * For compatibility, the `-' is not considerd
+			 * to define a range if the character following
+			 * it is either a close bracket (required by ANSI)
+			 * or is not numerically greater than the character
+			 * we just stored in the table (c).
+			 */
+			n = *fmt;
+			if (n == ']' || n < c) {
+				c = '-';
+				break;	/* resume the for(;;) */
+			}
+			fmt++;
+			do {		/* fill in the range */
+				tab[++c] = v;
+			} while (c < n);
+#if 1	/* XXX another disgusting compatibility hack */
+			/*
+			 * Alas, the V7 Unix scanf also treats formats
+			 * such as [a-c-e] as `the letters a through e'.
+			 * This too is permitted by the standard....
+			 */
+			goto doswitch;
+#else
+			c = *fmt++;
+			if (c == 0)
+				return (fmt - 1);
+			if (c == ']')
+				return (fmt);
+#endif
+			break;
+
+		case ']':		/* end of scanset */
+			return (fmt);
+
+		default:		/* just another character */
+			c = n;
+			break;
+		}
+	}
+	/* NOTREACHED */
+}
diff --git a/libc/stdio/vprintf.c b/libc/stdio/vprintf.c
new file mode 100644
index 0000000..fcc622c
--- /dev/null
+++ b/libc/stdio/vprintf.c
@@ -0,0 +1,40 @@
+/*	$OpenBSD: vprintf.c,v 1.8 2006/01/06 18:53:04 millert Exp $ */
+/*-
+ * Copyright (c) 1990, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <stdio.h>
+
+int
+vprintf(const char *fmt, __va_list ap)
+{
+	return (vfprintf(stdout, fmt, ap));
+}
diff --git a/libc/stdio/vscanf.c b/libc/stdio/vscanf.c
new file mode 100644
index 0000000..228498e
--- /dev/null
+++ b/libc/stdio/vscanf.c
@@ -0,0 +1,41 @@
+/*	$OpenBSD: vscanf.c,v 1.8 2006/01/06 18:53:04 millert Exp $ */
+/*-
+ * Copyright (c) 1990, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Donn Seeley at UUNET Technologies, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <stdio.h>
+
+int
+vscanf(const char *fmt, __va_list ap)
+{
+
+	return (vfscanf(stdin, fmt, ap));
+}
diff --git a/libc/stdio/vsnprintf.c b/libc/stdio/vsnprintf.c
new file mode 100644
index 0000000..e6dd009
--- /dev/null
+++ b/libc/stdio/vsnprintf.c
@@ -0,0 +1,64 @@
+/*	$OpenBSD: vsnprintf.c,v 1.12 2006/01/06 18:53:04 millert Exp $ */
+/*-
+ * Copyright (c) 1990, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <limits.h>
+#include <stdio.h>
+#include <string.h>
+#include "local.h"
+
+int
+vsnprintf(char *str, size_t n, const char *fmt, __va_list ap)
+{
+	int ret;
+	char dummy;
+	FILE f;
+	struct __sfileext fext;
+
+	_FILEEXT_SETUP(&f, &fext);
+
+	/* While snprintf(3) specifies size_t stdio uses an int internally */
+	if (n > INT_MAX)
+		n = INT_MAX;
+	/* Stdio internals do not deal correctly with zero length buffer */
+	if (n == 0) {
+		str = &dummy;
+		n = 1;
+	}
+	f._file = -1;
+	f._flags = __SWR | __SSTR;
+	f._bf._base = f._p = (unsigned char *)str;
+	f._bf._size = f._w = n - 1;
+	ret = vfprintf(&f, fmt, ap);
+	*f._p = '\0';
+	return (ret);
+}
diff --git a/libc/stdio/vsprintf.c b/libc/stdio/vsprintf.c
new file mode 100644
index 0000000..67a53a1
--- /dev/null
+++ b/libc/stdio/vsprintf.c
@@ -0,0 +1,59 @@
+/*	$OpenBSD: vsprintf.c,v 1.13 2006/01/06 18:53:04 millert Exp $ */
+/*-
+ * Copyright (c) 1990, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <limits.h>
+#include "local.h"
+
+#if defined(APIWARN)
+__warn_references(vsprintf,
+    "warning: vsprintf() is often misused, please use vsnprintf()");
+#endif
+
+int
+vsprintf(char *str, const char *fmt, __va_list ap)
+{
+	int ret;
+	FILE f;
+	struct __sfileext fext;
+
+	_FILEEXT_SETUP(&f, &fext);
+	f._file = -1;
+	f._flags = __SWR | __SSTR;
+	f._bf._base = f._p = (unsigned char *)str;
+	f._bf._size = f._w = INT_MAX;
+	ret = vfprintf(&f, fmt, ap);
+	*f._p = '\0';
+	return (ret);
+}
diff --git a/libc/stdio/vsscanf.c b/libc/stdio/vsscanf.c
new file mode 100644
index 0000000..47c1ae6
--- /dev/null
+++ b/libc/stdio/vsscanf.c
@@ -0,0 +1,59 @@
+/*	$OpenBSD: vsscanf.c,v 1.11 2006/01/06 18:53:04 millert Exp $ */
+/*-
+ * Copyright (c) 1990, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Donn Seeley at UUNET Technologies, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include "local.h"
+
+/* ARGSUSED */
+static int
+eofread(void *cookie, char *buf, int len)
+{
+
+	return (0);
+}
+
+int
+vsscanf(const char *str, const char *fmt, __va_list ap)
+{
+	FILE f;
+	struct __sfileext fext;
+
+	_FILEEXT_SETUP(&f, &fext);
+	f._flags = __SRD;
+	f._bf._base = f._p = (unsigned char *)str;
+	f._bf._size = f._r = strlen(str);
+	f._read = eofread;
+	f._lb._base = NULL;
+	return (vfscanf(&f, fmt, ap));
+}
diff --git a/libc/stdio/wbuf.c b/libc/stdio/wbuf.c
new file mode 100644
index 0000000..c757799
--- /dev/null
+++ b/libc/stdio/wbuf.c
@@ -0,0 +1,84 @@
+/*	$OpenBSD: wbuf.c,v 1.9 2005/08/08 08:05:36 espie Exp $ */
+/*-
+ * Copyright (c) 1990, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <stdio.h>
+#include <errno.h>
+#include "local.h"
+
+/*
+ * Write the given character into the (probably full) buffer for
+ * the given file.  Flush the buffer out if it is or becomes full,
+ * or if c=='\n' and the file is line buffered.
+ */
+int
+__swbuf(int c, FILE *fp)
+{
+	int n;
+
+	_SET_ORIENTATION(fp, -1);
+	/*
+	 * In case we cannot write, or longjmp takes us out early,
+	 * make sure _w is 0 (if fully- or un-buffered) or -_bf._size
+	 * (if line buffered) so that we will get called again.
+	 * If we did not do this, a sufficient number of putc()
+	 * calls might wrap _w from negative to positive.
+	 */
+	fp->_w = fp->_lbfsize;
+	if (cantwrite(fp)) {
+		errno = EBADF;
+		return (EOF);
+	}
+	c = (unsigned char)c;
+
+	/*
+	 * If it is completely full, flush it out.  Then, in any case,
+	 * stuff c into the buffer.  If this causes the buffer to fill
+	 * completely, or if c is '\n' and the file is line buffered,
+	 * flush it (perhaps a second time).  The second flush will always
+	 * happen on unbuffered streams, where _bf._size==1; fflush()
+	 * guarantees that putc() will always call wbuf() by setting _w
+	 * to 0, so we need not do anything else.
+	 */
+	n = fp->_p - fp->_bf._base;
+	if (n >= fp->_bf._size) {
+		if (fflush(fp))
+			return (EOF);
+		n = 0;
+	}
+	fp->_w--;
+	*fp->_p++ = c;
+	if (++n == fp->_bf._size || (fp->_flags & __SLBF && c == '\n'))
+		if (fflush(fp))
+			return (EOF);
+	return (c);
+}
diff --git a/libc/stdio/wcio.h b/libc/stdio/wcio.h
new file mode 100644
index 0000000..f8ac1b2
--- /dev/null
+++ b/libc/stdio/wcio.h
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/* this file is only used to quiet the BSD stdio implementation
+ * since we don't implement wchar support at all
+ */
+#ifndef _WCIO_H_
+#define _WCIO_H_
+
+/* minimal requirement of SUSv2 */
+#define WCIO_UNGETWC_BUFSIZE 1
+
+struct wchar_io_data {
+        int dummy;
+};
+
+/* BIONIC: disable wchar support */
+#define WCIO_GET(fp) \
+	((struct whcar_io_data*) 0)
+
+#define _SET_ORIENTATION(fp, mode) ((void)0)
+
+/*
+ * WCIO_FREE should be called by fclose
+ */
+#define WCIO_FREE(fp) ((void)(0))
+
+#define WCIO_FREEUB(fp) ((void)0)
+
+#define WCIO_INIT(fp)  ((void)0)
+
+#endif /*_WCIO_H_*/
diff --git a/libc/stdio/wsetup.c b/libc/stdio/wsetup.c
new file mode 100644
index 0000000..0834223
--- /dev/null
+++ b/libc/stdio/wsetup.c
@@ -0,0 +1,86 @@
+/*	$OpenBSD: wsetup.c,v 1.7 2005/08/08 08:05:36 espie Exp $ */
+/*-
+ * Copyright (c) 1990, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include "local.h"
+
+/*
+ * Various output routines call wsetup to be sure it is safe to write,
+ * because either _flags does not include __SWR, or _buf is NULL.
+ * _wsetup returns 0 if OK to write, nonzero otherwise.
+ */
+int
+__swsetup(FILE *fp)
+{
+	/* make sure stdio is set up */
+	if (!__sdidinit)
+		__sinit();
+
+	/*
+	 * If we are not writing, we had better be reading and writing.
+	 */
+	if ((fp->_flags & __SWR) == 0) {
+		if ((fp->_flags & __SRW) == 0)
+			return (EOF);
+		if (fp->_flags & __SRD) {
+			/* clobber any ungetc data */
+			if (HASUB(fp))
+				FREEUB(fp);
+			fp->_flags &= ~(__SRD|__SEOF);
+			fp->_r = 0;
+			fp->_p = fp->_bf._base;
+		}
+		fp->_flags |= __SWR;
+	}
+
+	/*
+	 * Make a buffer if necessary, then set _w.
+	 */
+	if (fp->_bf._base == NULL) {
+		if ((fp->_flags & (__SSTR | __SALC)) == __SSTR)
+			return (EOF);
+		__smakebuf(fp);
+	}
+	if (fp->_flags & __SLBF) {
+		/*
+		 * It is line buffered, so make _lbfsize be -_bufsize
+		 * for the putc() macro.  We will change _lbfsize back
+		 * to 0 whenever we turn off __SWR.
+		 */
+		fp->_w = 0;
+		fp->_lbfsize = -fp->_bf._size;
+	} else
+		fp->_w = fp->_flags & __SNBF ? 0 : fp->_bf._size;
+	return (0);
+}