--- /dev/null
+/* $NetBSD: findfp.c,v 1.23 2006/10/07 21:40:46 thorpej Exp $ */\r
+\r
+/*-\r
+ * Copyright (c) 1990, 1993\r
+ * The Regents of the University of California. All rights reserved.\r
+ *\r
+ * This code is derived from software contributed to Berkeley by\r
+ * Chris Torek.\r
+ *\r
+ * Redistribution and use in source and binary forms, with or without\r
+ * modification, are permitted provided that the following conditions\r
+ * are met:\r
+ * 1. Redistributions of source code must retain the above copyright\r
+ * notice, this list of conditions and the following disclaimer.\r
+ * 2. Redistributions in binary form must reproduce the above copyright\r
+ * notice, this list of conditions and the following disclaimer in the\r
+ * documentation and/or other materials provided with the distribution.\r
+ * 3. Neither the name of the University nor the names of its contributors\r
+ * may be used to endorse or promote products derived from this software\r
+ * without specific prior written permission.\r
+ *\r
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND\r
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\r
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\r
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE\r
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\r
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS\r
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\r
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT\r
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY\r
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF\r
+ * SUCH DAMAGE.\r
+ */\r
+#include <LibConfig.h>\r
+#include <sys/EfiCdefs.h>\r
+#if defined(LIBC_SCCS) && !defined(lint)\r
+#if 0\r
+static char sccsid[] = "@(#)findfp.c 8.2 (Berkeley) 1/4/94";\r
+#else\r
+__RCSID("$NetBSD: findfp.c,v 1.23 2006/10/07 21:40:46 thorpej Exp $");\r
+#endif\r
+#endif /* LIBC_SCCS and not lint */\r
+\r
+#include "namespace.h"\r
+#include <sys/param.h>\r
+#include <sys/EfiSysCall.h>\r
+#include <stdio.h>\r
+#include <errno.h>\r
+#include <stdlib.h>\r
+#include <string.h>\r
+#include "reentrant.h"\r
+#include "local.h"\r
+#include "glue.h"\r
+#include <MainData.h>\r
+\r
+int __sdidinit;\r
+\r
+#define NDYNAMIC 10 /* add ten more whenever necessary */\r
+\r
+#define std(flags, file) \\r
+/* p r w flags file bf lfbsize cookie close */ \\r
+ { NULL, 0, 0, flags, file, { NULL, 0 }, 0, __sF + file, __sclose, \\r
+/* read seek write ext up */ \\r
+ __sread, __sseek, __swrite, { (void *)(__sFext + file), 0 }, NULL, \\r
+/* ur ubuf, nbuf lb blksize offset */ \\r
+ 0, { '\0', '\0', '\0' }, { '\0' }, { NULL, 0 }, 0, (fpos_t)0 }\r
+\r
+ /* the usual - (stdin + stdout + stderr) */\r
+static FILE usual[FOPEN_MAX - 3];\r
+static struct __sfileext usualext[FOPEN_MAX - 3];\r
+static struct glue uglue = { 0, FOPEN_MAX - 3, usual };\r
+\r
+#if defined(_REENTRANT) && !defined(__lint__) /* XXX lint is busted */\r
+#define STDEXT { ._lock = MUTEX_INITIALIZER, ._lockcond = COND_INITIALIZER }\r
+struct __sfileext __sFext[3] = { STDEXT,\r
+ STDEXT,\r
+ STDEXT};\r
+#else\r
+struct __sfileext __sFext[3];\r
+#endif\r
+\r
+FILE __sF[3] = {\r
+ std(__SRD, STDIN_FILENO), /* stdin */\r
+ std(__SWR, STDOUT_FILENO), /* stdout */\r
+ std(__SWR|__SNBF, STDERR_FILENO) /* stderr */\r
+};\r
+struct glue __sglue = { &uglue, 3, __sF };\r
+\r
+static struct glue *moreglue(int);\r
+void f_prealloc(void);\r
+\r
+#ifdef _REENTRANT\r
+rwlock_t __sfp_lock = RWLOCK_INITIALIZER;\r
+#endif\r
+\r
+static struct glue *\r
+moreglue(int n)\r
+{\r
+ struct glue *g;\r
+ FILE *p;\r
+ struct __sfileext *pext;\r
+ static FILE empty;\r
+\r
+ g = (struct glue *)malloc(sizeof(*g) + ALIGNBYTES + n * sizeof(FILE)\r
+ + n * sizeof(struct __sfileext));\r
+ if (g == NULL)\r
+ return (NULL);\r
+ p = (FILE *)ALIGN((g + 1));\r
+ g->next = NULL;\r
+ g->niobs = n;\r
+ g->iobs = p;\r
+ pext = (void *)(p + n);\r
+ while (--n >= 0) {\r
+ *p = empty;\r
+ _FILEEXT_SETUP(p, pext);\r
+ p++;\r
+ pext++;\r
+ }\r
+ return (g);\r
+}\r
+\r
+/*\r
+ * Find a free FILE for fopen et al.\r
+ */\r
+FILE *\r
+__sfp()\r
+{\r
+ FILE *fp;\r
+ int n;\r
+ struct glue *g;\r
+\r
+ if (!__sdidinit)\r
+ __sinit();\r
+\r
+ rwlock_wrlock(&__sfp_lock);\r
+ for (g = &__sglue;; g = g->next) {\r
+ for (fp = g->iobs, n = g->niobs; --n >= 0; fp++)\r
+ if (fp->_flags == 0)\r
+ goto found;\r
+ if (g->next == NULL && (g->next = moreglue(NDYNAMIC)) == NULL)\r
+ break;\r
+ }\r
+ rwlock_unlock(&__sfp_lock);\r
+ return (NULL);\r
+found:\r
+ fp->_flags = 1; /* reserve this slot; caller sets real flags */\r
+ fp->_p = NULL; /* no current pointer */\r
+ fp->_w = 0; /* nothing to read or write */\r
+ fp->_r = 0;\r
+ fp->_bf._base = NULL; /* no buffer */\r
+ fp->_bf._size = 0;\r
+ fp->_lbfsize = 0; /* not line buffered */\r
+ fp->_file = -1; /* no file */\r
+/* fp->_cookie = <any>; */ /* caller sets cookie, _read/_write etc */\r
+ _UB(fp)._base = NULL; /* no ungetc buffer */\r
+ _UB(fp)._size = 0;\r
+ fp->_lb._base = NULL; /* no line buffer */\r
+ fp->_lb._size = 0;\r
+ memset(WCIO_GET(fp), 0, sizeof(struct wchar_io_data));\r
+ rwlock_unlock(&__sfp_lock);\r
+ return (fp);\r
+}\r
+\r
+#if 0\r
+/*\r
+ * XXX. Force immediate allocation of internal memory. Not used by stdio,\r
+ * but documented historically for certain applications. Bad applications.\r
+ */\r
+void\r
+f_prealloc()\r
+{\r
+ struct glue *g;\r
+ int n;\r
+\r
+ n = (int)sysconf(_SC_OPEN_MAX) - FOPEN_MAX + 20; /* 20 for slop. */\r
+ for (g = &__sglue; (n -= g->niobs) > 0 && g->next; g = g->next)\r
+ /* void */;\r
+ if (n > 0)\r
+ g->next = moreglue(n);\r
+}\r
+#endif\r
+\r
+/*\r
+ * exit() calls _cleanup() through *gMD->cleanup, set whenever we\r
+ * open or buffer a file. This chicanery is done so that programs\r
+ * that do not use stdio need not link it all in.\r
+ *\r
+ * The name `_cleanup' is, alas, fairly well known outside stdio.\r
+ */\r
+void\r
+_cleanup( void )\r
+{\r
+ /* (void) _fwalk(fclose); */\r
+ (void) fflush(NULL); /* `cheating' */\r
+}\r
+\r
+/*\r
+ * __sinit() is called whenever stdio's internal variables must be set up.\r
+ */\r
+void\r
+__sinit( void )\r
+{\r
+ int i;\r
+\r
+ for (i = 0; i < FOPEN_MAX - 3; i++)\r
+ _FILEEXT_SETUP(&usual[i], &usualext[i]);\r
+\r
+ /* make sure we clean up on exit */\r
+ gMD->cleanup = _cleanup; /* conservative */\r
+ __sdidinit = 1;\r
+}\r