xref: /csrg-svn/lib/libc/stdio/findfp.c (revision 26119)
1 /*
2  * Copyright (c) 1983, 1985 Regents of the University of California.
3  * All rights reserved.  The Berkeley software License Agreement
4  * specifies the terms and conditions for redistribution.
5  */
6 
7 #ifndef lint
8 static char sccsid[] = "@(#)findfp.c	5.4 (Berkeley) 02/09/86";
9 #endif not lint
10 
11 #include <stdio.h>
12 #include <errno.h>
13 
14 extern int errno;
15 
16 #define active(iop)	((iop)->_flag & (_IOREAD|_IOWRT|_IORW))
17 
18 #define NSTATIC	20	/* stdin + stdout + stderr + the usual */
19 
20 FILE _iob[NSTATIC] = {
21 	{ 0, NULL, NULL, 0, _IOREAD,		0 },	/* stdin  */
22 	{ 0, NULL, NULL, 0, _IOWRT,		1 },	/* stdout */
23 	{ 0, NULL, NULL, 0, _IOWRT|_IONBF,	2 },	/* stderr */
24 };
25 
26 extern	char	*malloc();
27 
28 static	char sbuf[NSTATIC];
29 char	*_smallbuf = sbuf;
30 static	FILE	**iobglue;
31 static	FILE	**endglue;
32 
33 /*
34  * Find a free FILE for fopen et al.
35  * We have a fixed static array of entries, and in addition
36  * may allocate additional entries dynamically, up to the kernel
37  * limit on the number of open files.
38  * At first just check for a free slot in the fixed static array.
39  * If none are available, then we allocate a structure to glue together
40  * the old and new FILE entries, which are then no longer contiguous.
41  */
42 FILE *
43 _findiop()
44 {
45 	register FILE **iov, *iop;
46 	register FILE *fp;
47 
48 	if (iobglue == 0) {
49 		for (iop = _iob; iop < _iob + NSTATIC; iop++)
50 			if (!active(iop))
51 				return (iop);
52 
53 		if (_f_morefiles() == 0) {
54 			errno = ENOMEM;
55 			return (NULL);
56 		}
57 	}
58 
59 	iov = iobglue;
60 	while (*iov != NULL && active(*iov))
61 		if (++iov >= endglue) {
62 			errno = EMFILE;
63 			return (NULL);
64 		}
65 
66 	if (*iov == NULL)
67 		*iov = (FILE *)malloc(sizeof **iov);
68 	if (*iov)
69 		bzero((char *)*iov, sizeof(**iov));
70 
71 	return (*iov);
72 }
73 
74 _f_morefiles()
75 {
76 	register FILE **iov;
77 	register FILE *fp;
78 	register char *cp;
79 	int nfiles;
80 
81 	nfiles = getdtablesize();
82 
83 	iobglue = (FILE **)malloc(nfiles * sizeof *iobglue);
84 	if (iobglue == NULL)
85 		return (0);
86 
87 	bzero((char *)iobglue, nfiles * sizeof(*iobglue));
88 	endglue = iobglue + nfiles;
89 
90 	for (fp = _iob, iov = iobglue; fp < &_iob[NSTATIC]; /* void */)
91 		*iov++ = fp++;
92 
93 	_smallbuf = malloc(nfiles * sizeof(*_smallbuf));
94 	return (1);
95 }
96 
97 f_prealloc()
98 {
99 	register FILE **iov;
100 	register FILE *fp;
101 
102 	if (iobglue == NULL && _f_morefiles() == 0)
103 		return;
104 
105 	for (iov = iobglue; iov < endglue; iov++)
106 		if (*iov == NULL) {
107 			*iov = (FILE *)malloc(1, sizeof **iov);
108 			if (*iov)
109 				bzero((char *)*iov, sizeof(**iov));
110 		}
111 }
112 
113 _fwalk(function)
114 	register int (*function)();
115 {
116 	register FILE **iov;
117 	register FILE *fp;
118 
119 	if (iobglue == NULL) {
120 		for (fp = _iob; fp < &_iob[NSTATIC]; fp++)
121 			if (active(fp))
122 				(*function)(fp);
123 	} else {
124 		for (iov = iobglue; iov < endglue; iov++)
125 			if (*iov && active(*iov))
126 				(*function)(*iov);
127 	}
128 }
129 
130 _cleanup()
131 {
132 	extern int fclose();
133 
134 	_fwalk(fclose);
135 }
136