1f14fb602SLionel Sambuc /* $NetBSD: findfp.c,v 1.28 2012/03/27 15:05:42 christos Exp $ */
22fe8fb19SBen Gras
32fe8fb19SBen Gras /*-
42fe8fb19SBen Gras * Copyright (c) 1990, 1993
52fe8fb19SBen Gras * The Regents of the University of California. All rights reserved.
62fe8fb19SBen Gras *
72fe8fb19SBen Gras * This code is derived from software contributed to Berkeley by
82fe8fb19SBen Gras * Chris Torek.
92fe8fb19SBen Gras *
102fe8fb19SBen Gras * Redistribution and use in source and binary forms, with or without
112fe8fb19SBen Gras * modification, are permitted provided that the following conditions
122fe8fb19SBen Gras * are met:
132fe8fb19SBen Gras * 1. Redistributions of source code must retain the above copyright
142fe8fb19SBen Gras * notice, this list of conditions and the following disclaimer.
152fe8fb19SBen Gras * 2. Redistributions in binary form must reproduce the above copyright
162fe8fb19SBen Gras * notice, this list of conditions and the following disclaimer in the
172fe8fb19SBen Gras * documentation and/or other materials provided with the distribution.
182fe8fb19SBen Gras * 3. Neither the name of the University nor the names of its contributors
192fe8fb19SBen Gras * may be used to endorse or promote products derived from this software
202fe8fb19SBen Gras * without specific prior written permission.
212fe8fb19SBen Gras *
222fe8fb19SBen Gras * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
232fe8fb19SBen Gras * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
242fe8fb19SBen Gras * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
252fe8fb19SBen Gras * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
262fe8fb19SBen Gras * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
272fe8fb19SBen Gras * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
282fe8fb19SBen Gras * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
292fe8fb19SBen Gras * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
302fe8fb19SBen Gras * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
312fe8fb19SBen Gras * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
322fe8fb19SBen Gras * SUCH DAMAGE.
332fe8fb19SBen Gras */
342fe8fb19SBen Gras
352fe8fb19SBen Gras #include <sys/cdefs.h>
362fe8fb19SBen Gras #if defined(LIBC_SCCS) && !defined(lint)
372fe8fb19SBen Gras #if 0
382fe8fb19SBen Gras static char sccsid[] = "@(#)findfp.c 8.2 (Berkeley) 1/4/94";
392fe8fb19SBen Gras #else
40f14fb602SLionel Sambuc __RCSID("$NetBSD: findfp.c,v 1.28 2012/03/27 15:05:42 christos Exp $");
412fe8fb19SBen Gras #endif
422fe8fb19SBen Gras #endif /* LIBC_SCCS and not lint */
432fe8fb19SBen Gras
442fe8fb19SBen Gras #include "namespace.h"
452fe8fb19SBen Gras #include <sys/param.h>
462fe8fb19SBen Gras #include <unistd.h>
472fe8fb19SBen Gras #include <stdio.h>
482fe8fb19SBen Gras #include <errno.h>
492fe8fb19SBen Gras #include <stdlib.h>
502fe8fb19SBen Gras #include <string.h>
512fe8fb19SBen Gras #include "reentrant.h"
522fe8fb19SBen Gras #include "local.h"
532fe8fb19SBen Gras #include "glue.h"
542fe8fb19SBen Gras
552fe8fb19SBen Gras int __sdidinit;
562fe8fb19SBen Gras
572fe8fb19SBen Gras #define NDYNAMIC 10 /* add ten more whenever necessary */
582fe8fb19SBen Gras
5984d9c625SLionel Sambuc #if !defined(_LIBMINC) && !defined(__kernel__) && defined(__minix)
602fe8fb19SBen Gras
61f14fb602SLionel Sambuc #define std(flags, file) { \
62f14fb602SLionel Sambuc ._p = NULL, \
63f14fb602SLionel Sambuc ._r = 0, \
64f14fb602SLionel Sambuc ._w = 0, \
65f14fb602SLionel Sambuc ._flags = (flags), \
66f14fb602SLionel Sambuc ._file = (file), \
67f14fb602SLionel Sambuc ._bf = { ._base = NULL, ._size = 0 }, \
68f14fb602SLionel Sambuc ._lbfsize = 0, \
69f14fb602SLionel Sambuc ._cookie = __sF + (file), \
70f14fb602SLionel Sambuc ._close = __sclose, \
71f14fb602SLionel Sambuc ._read = __sread, \
72f14fb602SLionel Sambuc ._seek = __sseek, \
73f14fb602SLionel Sambuc ._write = __swrite, \
74f14fb602SLionel Sambuc ._ext = { ._base = (void *)(__sFext + (file)), ._size = 0 }, \
75f14fb602SLionel Sambuc ._up = NULL, \
76f14fb602SLionel Sambuc ._ur = 0, \
77f14fb602SLionel Sambuc ._ubuf = { [0] = '\0', [1] = '\0', [2] = '\0' }, \
78f14fb602SLionel Sambuc ._nbuf = { [0] = '\0' }, \
79f14fb602SLionel Sambuc ._flush = NULL, \
80f14fb602SLionel Sambuc ._lb_unused = { '\0' }, \
81f14fb602SLionel Sambuc ._blksize = 0, \
82f14fb602SLionel Sambuc ._offset = (off_t)0, \
83f14fb602SLionel Sambuc }
84f14fb602SLionel Sambuc
85f14fb602SLionel Sambuc #else
86f14fb602SLionel Sambuc
87f14fb602SLionel Sambuc #define std(flags, file) { \
88f14fb602SLionel Sambuc ._p = NULL, \
89f14fb602SLionel Sambuc ._r = 0, \
90f14fb602SLionel Sambuc ._w = 0, \
91f14fb602SLionel Sambuc ._flags = (flags), \
92f14fb602SLionel Sambuc ._file = (file), \
93f14fb602SLionel Sambuc ._bf = { ._base = NULL, ._size = 0 }, \
94f14fb602SLionel Sambuc ._lbfsize = 0, \
95f14fb602SLionel Sambuc ._cookie = __sF + (file), \
96f14fb602SLionel Sambuc ._close = NULL, \
97f14fb602SLionel Sambuc ._read = NULL, \
98f14fb602SLionel Sambuc ._seek = NULL, \
99f14fb602SLionel Sambuc ._write = NULL, \
100f14fb602SLionel Sambuc ._ext = { ._base = (void *)(__sFext + (file)), ._size = 0 }, \
101f14fb602SLionel Sambuc ._up = NULL, \
102f14fb602SLionel Sambuc ._ur = 0, \
103f14fb602SLionel Sambuc ._ubuf = { [0] = '\0', [1] = '\0', [2] = '\0' }, \
104f14fb602SLionel Sambuc ._nbuf = { [0] = '\0' }, \
105f14fb602SLionel Sambuc ._flush = NULL, \
106f14fb602SLionel Sambuc ._lb_unused = { '\0' }, \
107f14fb602SLionel Sambuc ._blksize = 0, \
108f14fb602SLionel Sambuc ._offset = (off_t)0, \
109f14fb602SLionel Sambuc }
110f14fb602SLionel Sambuc
111f14fb602SLionel Sambuc #endif /* !defined(_LIBMINC) && !defined(__kernel__) */
112f14fb602SLionel Sambuc
113*0a6a1f1dSLionel Sambuc #if !defined(__kernel__) && defined(__minix)
1142fe8fb19SBen Gras /* the usual - (stdin + stdout + stderr) */
1152fe8fb19SBen Gras static FILE usual[FOPEN_MAX - 3];
1162fe8fb19SBen Gras static struct __sfileext usualext[FOPEN_MAX - 3];
1172fe8fb19SBen Gras static struct glue uglue = { 0, FOPEN_MAX - 3, usual };
118*0a6a1f1dSLionel Sambuc #endif /* !defined(__kernel__) && defined(__minix) */
1192fe8fb19SBen Gras
1202fe8fb19SBen Gras #if defined(_REENTRANT) && !defined(__lint__) /* XXX lint is busted */
1212fe8fb19SBen Gras #define STDEXT { ._lock = MUTEX_INITIALIZER, ._lockcond = COND_INITIALIZER }
1222fe8fb19SBen Gras struct __sfileext __sFext[3] = { STDEXT,
1232fe8fb19SBen Gras STDEXT,
1242fe8fb19SBen Gras STDEXT};
1252fe8fb19SBen Gras #else
1262fe8fb19SBen Gras struct __sfileext __sFext[3];
1272fe8fb19SBen Gras #endif
1282fe8fb19SBen Gras
1292fe8fb19SBen Gras FILE __sF[3] = {
1302fe8fb19SBen Gras std(__SRD, STDIN_FILENO), /* stdin */
1312fe8fb19SBen Gras std(__SWR, STDOUT_FILENO), /* stdout */
1322fe8fb19SBen Gras std(__SWR|__SNBF, STDERR_FILENO) /* stderr */
1332fe8fb19SBen Gras };
134f14fb602SLionel Sambuc
13584d9c625SLionel Sambuc #if !defined(__kernel__) && defined(__minix)
1362fe8fb19SBen Gras struct glue __sglue = { &uglue, 3, __sF };
1372fe8fb19SBen Gras
138f14fb602SLionel Sambuc void f_prealloc(void);
1392fe8fb19SBen Gras
1402fe8fb19SBen Gras #ifdef _REENTRANT
1412fe8fb19SBen Gras rwlock_t __sfp_lock = RWLOCK_INITIALIZER;
1422fe8fb19SBen Gras #endif
1432fe8fb19SBen Gras
1442fe8fb19SBen Gras static struct glue *
moreglue(int n)145f14fb602SLionel Sambuc moreglue(int n)
1462fe8fb19SBen Gras {
1472fe8fb19SBen Gras struct glue *g;
1482fe8fb19SBen Gras FILE *p;
1492fe8fb19SBen Gras struct __sfileext *pext;
1502fe8fb19SBen Gras static FILE empty;
1512fe8fb19SBen Gras
152f14fb602SLionel Sambuc g = malloc(sizeof(*g) + ALIGNBYTES + n * sizeof(FILE)
1532fe8fb19SBen Gras + n * sizeof(struct __sfileext));
1542fe8fb19SBen Gras if (g == NULL)
155f14fb602SLionel Sambuc return NULL;
1562fe8fb19SBen Gras p = (FILE *)ALIGN((u_long)(g + 1));
1572fe8fb19SBen Gras g->next = NULL;
1582fe8fb19SBen Gras g->niobs = n;
1592fe8fb19SBen Gras g->iobs = p;
1602fe8fb19SBen Gras pext = (void *)(p + n);
1612fe8fb19SBen Gras while (--n >= 0) {
1622fe8fb19SBen Gras *p = empty;
1632fe8fb19SBen Gras _FILEEXT_SETUP(p, pext);
1642fe8fb19SBen Gras p++;
1652fe8fb19SBen Gras pext++;
1662fe8fb19SBen Gras }
167f14fb602SLionel Sambuc return g;
1682fe8fb19SBen Gras }
1692fe8fb19SBen Gras
1702fe8fb19SBen Gras void
__sfpinit(FILE * fp)1712fe8fb19SBen Gras __sfpinit(FILE *fp)
1722fe8fb19SBen Gras {
1732fe8fb19SBen Gras fp->_flags = 1; /* reserve this slot; caller sets real flags */
1742fe8fb19SBen Gras fp->_p = NULL; /* no current pointer */
1752fe8fb19SBen Gras fp->_w = 0; /* nothing to read or write */
1762fe8fb19SBen Gras fp->_r = 0;
1772fe8fb19SBen Gras fp->_bf._base = NULL; /* no buffer */
1782fe8fb19SBen Gras fp->_bf._size = 0;
1792fe8fb19SBen Gras fp->_lbfsize = 0; /* not line buffered */
1802fe8fb19SBen Gras fp->_file = -1; /* no file */
1812fe8fb19SBen Gras /* fp->_cookie = <any>; */ /* caller sets cookie, _read/_write etc */
182f14fb602SLionel Sambuc fp->_flush = NULL; /* default flush */
1832fe8fb19SBen Gras _UB(fp)._base = NULL; /* no ungetc buffer */
1842fe8fb19SBen Gras _UB(fp)._size = 0;
1852fe8fb19SBen Gras memset(WCIO_GET(fp), 0, sizeof(struct wchar_io_data));
1862fe8fb19SBen Gras }
1872fe8fb19SBen Gras
1882fe8fb19SBen Gras /*
1892fe8fb19SBen Gras * Find a free FILE for fopen et al.
1902fe8fb19SBen Gras */
1912fe8fb19SBen Gras FILE *
__sfp(void)192f14fb602SLionel Sambuc __sfp(void)
1932fe8fb19SBen Gras {
1942fe8fb19SBen Gras FILE *fp;
1952fe8fb19SBen Gras int n;
1962fe8fb19SBen Gras struct glue *g;
1972fe8fb19SBen Gras
1982fe8fb19SBen Gras if (!__sdidinit)
1992fe8fb19SBen Gras __sinit();
2002fe8fb19SBen Gras
2012fe8fb19SBen Gras rwlock_wrlock(&__sfp_lock);
2022fe8fb19SBen Gras for (g = &__sglue;; g = g->next) {
2032fe8fb19SBen Gras for (fp = g->iobs, n = g->niobs; --n >= 0; fp++)
2042fe8fb19SBen Gras if (fp->_flags == 0)
2052fe8fb19SBen Gras goto found;
2062fe8fb19SBen Gras if (g->next == NULL && (g->next = moreglue(NDYNAMIC)) == NULL)
2072fe8fb19SBen Gras break;
2082fe8fb19SBen Gras }
2092fe8fb19SBen Gras rwlock_unlock(&__sfp_lock);
210f14fb602SLionel Sambuc return NULL;
2112fe8fb19SBen Gras found:
2122fe8fb19SBen Gras __sfpinit(fp);
2132fe8fb19SBen Gras rwlock_unlock(&__sfp_lock);
214f14fb602SLionel Sambuc return fp;
2152fe8fb19SBen Gras }
2162fe8fb19SBen Gras
2172fe8fb19SBen Gras /*
2182fe8fb19SBen Gras * XXX. Force immediate allocation of internal memory. Not used by stdio,
2192fe8fb19SBen Gras * but documented historically for certain applications. Bad applications.
2202fe8fb19SBen Gras */
2212fe8fb19SBen Gras void
f_prealloc(void)222f14fb602SLionel Sambuc f_prealloc(void)
2232fe8fb19SBen Gras {
22484d9c625SLionel Sambuc #if !defined(_LIBMINC) && defined(__minix)
2252fe8fb19SBen Gras struct glue *g;
2262fe8fb19SBen Gras int n;
2272fe8fb19SBen Gras
2282fe8fb19SBen Gras n = (int)sysconf(_SC_OPEN_MAX) - FOPEN_MAX + 20; /* 20 for slop. */
2292fe8fb19SBen Gras for (g = &__sglue; (n -= g->niobs) > 0 && g->next; g = g->next)
230f14fb602SLionel Sambuc continue;
2312fe8fb19SBen Gras if (n > 0)
2322fe8fb19SBen Gras g->next = moreglue(n);
233*0a6a1f1dSLionel Sambuc #endif /* !defined(_LIBMINC) && defined(__minix) */
2342fe8fb19SBen Gras }
2352fe8fb19SBen Gras
2362fe8fb19SBen Gras /*
2372fe8fb19SBen Gras * exit() calls _cleanup() through *__cleanup, set whenever we
2382fe8fb19SBen Gras * open or buffer a file. This chicanery is done so that programs
2392fe8fb19SBen Gras * that do not use stdio need not link it all in.
2402fe8fb19SBen Gras *
2412fe8fb19SBen Gras * The name `_cleanup' is, alas, fairly well known outside stdio.
2422fe8fb19SBen Gras */
2432fe8fb19SBen Gras void
_cleanup(void)244f14fb602SLionel Sambuc _cleanup(void)
2452fe8fb19SBen Gras {
24684d9c625SLionel Sambuc #if !defined(_LIBMINC) && defined(__minix)
2472fe8fb19SBen Gras /* (void) _fwalk(fclose); */
2482fe8fb19SBen Gras (void) fflush(NULL); /* `cheating' */
249*0a6a1f1dSLionel Sambuc #endif /* !defined(_LIBMINC) && defined(__minix) */
2502fe8fb19SBen Gras }
2512fe8fb19SBen Gras
2522fe8fb19SBen Gras /*
2532fe8fb19SBen Gras * __sinit() is called whenever stdio's internal variables must be set up.
2542fe8fb19SBen Gras */
2552fe8fb19SBen Gras void
__sinit(void)256f14fb602SLionel Sambuc __sinit(void)
2572fe8fb19SBen Gras {
2582fe8fb19SBen Gras int i;
2592fe8fb19SBen Gras
2602fe8fb19SBen Gras for (i = 0; i < FOPEN_MAX - 3; i++)
2612fe8fb19SBen Gras _FILEEXT_SETUP(&usual[i], &usualext[i]);
2622fe8fb19SBen Gras
2632fe8fb19SBen Gras /* make sure we clean up on exit */
2642fe8fb19SBen Gras __cleanup = _cleanup; /* conservative */
2652fe8fb19SBen Gras __sdidinit = 1;
2662fe8fb19SBen Gras }
267*0a6a1f1dSLionel Sambuc #endif /* !defined(__kernel__) && defined(__minix) */
268