1 /* $NetBSD: findfp.c,v 1.28 2012/03/27 15:05:42 christos Exp $ */
4 * Copyright (c) 1990, 1993
5 * The Regents of the University of California. All rights reserved.
7 * This code is derived from software contributed to Berkeley by
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 * 3. Neither the name of the University nor the names of its contributors
19 * may be used to endorse or promote products derived from this software
20 * without specific prior written permission.
22 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35 #include <sys/cdefs.h>
36 #if defined(LIBC_SCCS) && !defined(lint)
38 static char sccsid
[] = "@(#)findfp.c 8.2 (Berkeley) 1/4/94";
40 __RCSID("$NetBSD: findfp.c,v 1.28 2012/03/27 15:05:42 christos Exp $");
42 #endif /* LIBC_SCCS and not lint */
44 #include "namespace.h"
45 #include <sys/param.h>
51 #include "reentrant.h"
57 #define NDYNAMIC 10 /* add ten more whenever necessary */
59 #if !defined(_LIBMINC) && !defined(__kernel__)
61 #define std(flags, file) { \
67 ._bf = { ._base = NULL, ._size = 0 }, \
69 ._cookie = __sF + (file), \
74 ._ext = { ._base = (void *)(__sFext + (file)), ._size = 0 }, \
77 ._ubuf = { [0] = '\0', [1] = '\0', [2] = '\0' }, \
78 ._nbuf = { [0] = '\0' }, \
80 ._lb_unused = { '\0' }, \
82 ._offset = (off_t)0, \
87 #define std(flags, file) { \
93 ._bf = { ._base = NULL, ._size = 0 }, \
95 ._cookie = __sF + (file), \
100 ._ext = { ._base = (void *)(__sFext + (file)), ._size = 0 }, \
103 ._ubuf = { [0] = '\0', [1] = '\0', [2] = '\0' }, \
104 ._nbuf = { [0] = '\0' }, \
106 ._lb_unused = { '\0' }, \
108 ._offset = (off_t)0, \
111 #endif /* !defined(_LIBMINC) && !defined(__kernel__) */
113 #if !defined(__kernel__)
114 /* the usual - (stdin + stdout + stderr) */
115 static FILE usual
[FOPEN_MAX
- 3];
116 static struct __sfileext usualext
[FOPEN_MAX
- 3];
117 static struct glue uglue
= { 0, FOPEN_MAX
- 3, usual
};
118 #endif /* !defined(__kernel__) */
120 #if defined(_REENTRANT) && !defined(__lint__) /* XXX lint is busted */
121 #define STDEXT { ._lock = MUTEX_INITIALIZER, ._lockcond = COND_INITIALIZER }
122 struct __sfileext __sFext
[3] = { STDEXT
,
126 struct __sfileext __sFext
[3];
130 std(__SRD
, STDIN_FILENO
), /* stdin */
131 std(__SWR
, STDOUT_FILENO
), /* stdout */
132 std(__SWR
|__SNBF
, STDERR_FILENO
) /* stderr */
135 #if !defined(__kernel__)
136 struct glue __sglue
= { &uglue
, 3, __sF
};
138 void f_prealloc(void);
141 rwlock_t __sfp_lock
= RWLOCK_INITIALIZER
;
149 struct __sfileext
*pext
;
152 g
= malloc(sizeof(*g
) + ALIGNBYTES
+ n
* sizeof(FILE)
153 + n
* sizeof(struct __sfileext
));
156 p
= (FILE *)ALIGN((u_long
)(g
+ 1));
160 pext
= (void *)(p
+ n
);
163 _FILEEXT_SETUP(p
, pext
);
173 fp
->_flags
= 1; /* reserve this slot; caller sets real flags */
174 fp
->_p
= NULL
; /* no current pointer */
175 fp
->_w
= 0; /* nothing to read or write */
177 fp
->_bf
._base
= NULL
; /* no buffer */
179 fp
->_lbfsize
= 0; /* not line buffered */
180 fp
->_file
= -1; /* no file */
181 /* fp->_cookie = <any>; */ /* caller sets cookie, _read/_write etc */
182 fp
->_flush
= NULL
; /* default flush */
183 _UB(fp
)._base
= NULL
; /* no ungetc buffer */
185 memset(WCIO_GET(fp
), 0, sizeof(struct wchar_io_data
));
189 * Find a free FILE for fopen et al.
201 rwlock_wrlock(&__sfp_lock
);
202 for (g
= &__sglue
;; g
= g
->next
) {
203 for (fp
= g
->iobs
, n
= g
->niobs
; --n
>= 0; fp
++)
206 if (g
->next
== NULL
&& (g
->next
= moreglue(NDYNAMIC
)) == NULL
)
209 rwlock_unlock(&__sfp_lock
);
213 rwlock_unlock(&__sfp_lock
);
218 * XXX. Force immediate allocation of internal memory. Not used by stdio,
219 * but documented historically for certain applications. Bad applications.
224 #if !defined(_LIBMINC)
228 n
= (int)sysconf(_SC_OPEN_MAX
) - FOPEN_MAX
+ 20; /* 20 for slop. */
229 for (g
= &__sglue
; (n
-= g
->niobs
) > 0 && g
->next
; g
= g
->next
)
232 g
->next
= moreglue(n
);
233 #endif /* !defined(_LIBMINC) */
237 * exit() calls _cleanup() through *__cleanup, set whenever we
238 * open or buffer a file. This chicanery is done so that programs
239 * that do not use stdio need not link it all in.
241 * The name `_cleanup' is, alas, fairly well known outside stdio.
246 #if !defined(_LIBMINC)
247 /* (void) _fwalk(fclose); */
248 (void) fflush(NULL
); /* `cheating' */
249 #endif /* !defined(_LIBMINC) */
253 * __sinit() is called whenever stdio's internal variables must be set up.
260 for (i
= 0; i
< FOPEN_MAX
- 3; i
++)
261 _FILEEXT_SETUP(&usual
[i
], &usualext
[i
]);
263 /* make sure we clean up on exit */
264 __cleanup
= _cleanup
; /* conservative */
267 #endif /* !defined(__kernel__) */