Commit | Line | Data |
---|---|---|
b8671c88 KB |
1 | /*- |
2 | * Copyright (c) 1990 The Regents of the University of California. | |
3 | * All rights reserved. | |
4 | * | |
5 | * This code is derived from software contributed to Berkeley by | |
6 | * Chris Torek. | |
7 | * | |
8 | * %sccs.include.redist.c% | |
586c39b1 DF |
9 | */ |
10 | ||
2ce81398 | 11 | #if defined(LIBC_SCCS) && !defined(lint) |
cb631443 | 12 | static char sccsid[] = "@(#)findfp.c 5.10 (Berkeley) %G%"; |
b8671c88 | 13 | #endif /* LIBC_SCCS and not lint */ |
586c39b1 | 14 | |
b8671c88 | 15 | #include <unistd.h> |
cb631443 | 16 | #include <stdio.h> |
dc08ce09 | 17 | #include <errno.h> |
cb631443 KB |
18 | #include <stdlib.h> |
19 | #include <string.h> | |
b8671c88 KB |
20 | #include "local.h" |
21 | #include "glue.h" | |
dc08ce09 | 22 | |
b8671c88 | 23 | int __sdidinit; |
f9f3c5fb | 24 | |
78d51389 | 25 | #define NSTATIC 20 /* stdin + stdout + stderr + the usual */ |
b8671c88 | 26 | #define NDYNAMIC 10 /* add ten more whenever necessary */ |
f9f3c5fb | 27 | |
b8671c88 | 28 | #define std(flags, file) \ |
1e298368 KB |
29 | {0,0,0,flags,file,{0},0,__sF+file,__sclose,__sread,__sseek,__swrite} |
30 | /* p r w flags file _bf z cookie close read seek write */ | |
b8671c88 KB |
31 | |
32 | static FILE usual[NSTATIC - 3]; /* the usual */ | |
33 | static struct glue uglue = { 0, NSTATIC - 3, usual }; | |
f9f3c5fb | 34 | |
b8671c88 KB |
35 | FILE __sF[3] = { |
36 | std(__SRD, STDIN_FILENO), /* stdin */ | |
37 | std(__SWR, STDOUT_FILENO), /* stdout */ | |
38 | std(__SWR|__SNBF, STDERR_FILENO) /* stderr */ | |
39 | }; | |
40 | struct glue __sglue = { &uglue, 3, __sF }; | |
2801a079 | 41 | |
b8671c88 KB |
42 | static struct glue * |
43 | moreglue(n) | |
44 | register int n; | |
45 | { | |
46 | register struct glue *g; | |
47 | register FILE *p; | |
48 | static FILE empty; | |
49 | ||
50 | g = (struct glue *)malloc(sizeof(*g) + n * sizeof(FILE)); | |
51 | if (g == NULL) | |
52 | return (NULL); | |
53 | p = (FILE *)(g + 1); | |
54 | g->next = NULL; | |
55 | g->niobs = n; | |
56 | g->iobs = p; | |
57 | while (--n >= 0) | |
58 | *p++ = empty; | |
59 | return (g); | |
60 | } | |
41e01b3e | 61 | |
d0962cc0 MK |
62 | /* |
63 | * Find a free FILE for fopen et al. | |
d0962cc0 | 64 | */ |
f9f3c5fb | 65 | FILE * |
b8671c88 | 66 | __sfp() |
f9f3c5fb | 67 | { |
f9f3c5fb | 68 | register FILE *fp; |
b8671c88 KB |
69 | register int n; |
70 | register struct glue *g; | |
71 | ||
72 | if (!__sdidinit) | |
73 | __sinit(); | |
74 | for (g = &__sglue;; g = g->next) { | |
75 | for (fp = g->iobs, n = g->niobs; --n >= 0; fp++) | |
76 | if (fp->_flags == 0) | |
77 | goto found; | |
78 | if (g->next == NULL && (g->next = moreglue(NDYNAMIC)) == NULL) | |
79 | break; | |
f9f3c5fb | 80 | } |
b8671c88 KB |
81 | return (NULL); |
82 | found: | |
83 | fp->_flags = 1; /* reserve this slot; caller sets real flags */ | |
84 | fp->_p = NULL; /* no current pointer */ | |
85 | fp->_w = 0; /* nothing to read or write */ | |
86 | fp->_r = 0; | |
87 | fp->_bf._base = NULL; /* no buffer */ | |
88 | fp->_bf._size = 0; | |
89 | fp->_lbfsize = 0; /* not line buffered */ | |
90 | fp->_file = -1; /* no file */ | |
91 | /* fp->_cookie = <any>; */ /* caller sets cookie, _read/_write etc */ | |
92 | fp->_ub._base = NULL; /* no ungetc buffer */ | |
93 | fp->_ub._size = 0; | |
94 | fp->_lb._base = NULL; /* no line buffer */ | |
95 | fp->_lb._size = 0; | |
96 | return (fp); | |
f9f3c5fb S |
97 | } |
98 | ||
b8671c88 KB |
99 | /* |
100 | * XXX. Force immediate allocation of internal memory. Not used by stdio, | |
101 | * but documented historically for certain applications. Bad applications. | |
102 | */ | |
103 | f_prealloc() | |
f9f3c5fb | 104 | { |
b8671c88 KB |
105 | int n = getdtablesize() - NSTATIC + 20; /* 20 for slop */ |
106 | register struct glue *g; | |
2801a079 | 107 | |
b8671c88 KB |
108 | for (g = &__sglue; (n -= g->niobs) > 0 && g->next; g = g->next) |
109 | /* void */; | |
110 | if (n > 0) | |
111 | g->next = moreglue(n); | |
78d51389 MK |
112 | } |
113 | ||
b8671c88 KB |
114 | /* |
115 | * exit() calls _cleanup() through *__cleanup, set whenever we | |
116 | * open or buffer a file. This chicanery is done so that programs | |
117 | * that do not use stdio need not link it all in. | |
118 | * | |
119 | * The name `_cleanup' is, alas, fairly well known outside stdio. | |
120 | */ | |
121 | void | |
122 | _cleanup() | |
78d51389 | 123 | { |
b8671c88 KB |
124 | /* (void) _fwalk(fclose); */ |
125 | (void) _fwalk(__sflush); /* `cheating' */ | |
78d51389 MK |
126 | } |
127 | ||
b8671c88 KB |
128 | /* |
129 | * __sinit() is called whenever stdio's internal variables must be set up. | |
130 | */ | |
131 | void | |
132 | __sinit() | |
78d51389 | 133 | { |
b8671c88 KB |
134 | /* make sure we clean up on exit */ |
135 | __cleanup = _cleanup; /* conservative */ | |
136 | __sdidinit = 1; | |
f9f3c5fb | 137 | } |