]> git.saurik.com Git - apple/libc.git/blob - stdio/findfp.c
Libc-262.2.12.tar.gz
[apple/libc.git] / stdio / findfp.c
1 /*
2 * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
7 *
8 * This file contains Original Code and/or Modifications of Original Code
9 * as defined in and that are subject to the Apple Public Source License
10 * Version 2.0 (the 'License'). You may not use this file except in
11 * compliance with the License. Please obtain a copy of the License at
12 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * file.
14 *
15 * The Original Code and all software distributed under the License are
16 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
17 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
18 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
20 * Please see the License for the specific language governing rights and
21 * limitations under the License.
22 *
23 * @APPLE_LICENSE_HEADER_END@
24 */
25 /*
26 * Copyright (c) 1990, 1993
27 * The Regents of the University of California. All rights reserved.
28 *
29 * This code is derived from software contributed to Berkeley by
30 * Chris Torek.
31 *
32 * Redistribution and use in source and binary forms, with or without
33 * modification, are permitted provided that the following conditions
34 * are met:
35 * 1. Redistributions of source code must retain the above copyright
36 * notice, this list of conditions and the following disclaimer.
37 * 2. Redistributions in binary form must reproduce the above copyright
38 * notice, this list of conditions and the following disclaimer in the
39 * documentation and/or other materials provided with the distribution.
40 * 3. All advertising materials mentioning features or use of this software
41 * must display the following acknowledgement:
42 * This product includes software developed by the University of
43 * California, Berkeley and its contributors.
44 * 4. Neither the name of the University nor the names of its contributors
45 * may be used to endorse or promote products derived from this software
46 * without specific prior written permission.
47 *
48 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
49 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
50 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
51 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
52 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
53 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
54 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
55 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
56 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
57 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
58 * SUCH DAMAGE.
59 */
60
61
62 #include <sys/param.h>
63 #include <unistd.h>
64 #include <stdio.h>
65 #include <errno.h>
66 #include <stdlib.h>
67 #include <string.h>
68 #include "local.h"
69 #include "glue.h"
70
71 int __sdidinit = 0;
72
73 #define NDYNAMIC 10 /* add ten more whenever necessary */
74
75 #define std(flags, file) \
76 {0,0,0,flags,file,{0},0,__sF+file,__sclose,__sread,__sseek,__swrite}
77 /* p r w flags file _bf z cookie close read seek write */
78
79 /* the usual - (stdin + stdout + stderr) */
80 static FILE usual[FOPEN_MAX - 3];
81 static struct glue uglue = { 0, FOPEN_MAX - 3, usual };
82
83 FILE __sF[3] = {
84 std(__SRD, STDIN_FILENO), /* stdin */
85 std(__SWR, STDOUT_FILENO), /* stdout */
86 std(__SWR|__SNBF, STDERR_FILENO) /* stderr */
87 };
88 struct glue __sglue = { &uglue, 3, __sF };
89
90 static struct glue *
91 moreglue(n)
92 register int n;
93 {
94 register struct glue *g;
95 register FILE *p;
96 static FILE empty;
97
98 g = (struct glue *)malloc(sizeof(*g) + ALIGNBYTES + n * sizeof(FILE));
99 if (g == NULL)
100 return (NULL);
101 p = (FILE *)ALIGN(g + 1);
102 g->next = NULL;
103 g->niobs = n;
104 g->iobs = p;
105 while (--n >= 0)
106 *p++ = empty;
107 return (g);
108 }
109
110 /*
111 * Find a free FILE for fopen et al.
112 */
113 FILE *
114 __sfp()
115 {
116 register FILE *fp;
117 register int n;
118 register struct glue *g;
119
120 if (!__sdidinit)
121 __sinit();
122 for (g = &__sglue;; g = g->next) {
123 for (fp = g->iobs, n = g->niobs; --n >= 0; fp++)
124 if (fp->_flags == 0)
125 goto found;
126 if (g->next == NULL && (g->next = moreglue(NDYNAMIC)) == NULL)
127 break;
128 }
129 return (NULL);
130 found:
131 fp->_flags = 1; /* reserve this slot; caller sets real flags */
132 fp->_p = NULL; /* no current pointer */
133 fp->_w = 0; /* nothing to read or write */
134 fp->_r = 0;
135 fp->_bf._base = NULL; /* no buffer */
136 fp->_bf._size = 0;
137 fp->_lbfsize = 0; /* not line buffered */
138 fp->_file = -1; /* no file */
139 /* fp->_cookie = <any>; */ /* caller sets cookie, _read/_write etc */
140 fp->_ub._base = NULL; /* no ungetc buffer */
141 fp->_ub._size = 0;
142 fp->_lb._base = NULL; /* no line buffer */
143 fp->_lb._size = 0;
144 return (fp);
145 }
146
147 /*
148 * XXX. Force immediate allocation of internal memory. Not used by stdio,
149 * but documented historically for certain applications. Bad applications.
150 */
151 void
152 f_prealloc()
153 {
154 register struct glue *g;
155 int n;
156
157 n = getdtablesize() - FOPEN_MAX + 20; /* 20 for slop. */
158 for (g = &__sglue; (n -= g->niobs) > 0 && g->next; g = g->next)
159 /* void */;
160 if (n > 0)
161 g->next = moreglue(n);
162 }
163
164 /*
165 * exit() calls _cleanup() through *__cleanup, set whenever we
166 * open or buffer a file. This chicanery is done so that programs
167 * that do not use stdio need not link it all in.
168 *
169 * The name `_cleanup' is, alas, fairly well known outside stdio.
170 */
171 void
172 _cleanup()
173 {
174 /* (void) _fwalk(fclose); */
175 (void) _fwalk(__sflush); /* `cheating' */
176 }
177
178 /*
179 * __sinit() is called whenever stdio's internal variables must be set up.
180 */
181 void
182 __sinit()
183 {
184 /* make sure we clean up on exit */
185 __cleanup = _cleanup; /* conservative */
186 __sdidinit = 1;
187 }