xref: /original-bsd/lib/libc/stdio/findfp.c (revision 5fd6b0d9)
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 #if defined(LIBC_SCCS) && !defined(lint)
8 static char sccsid[] = "@(#)findfp.c	5.7 (Berkeley) 09/22/88";
9 #endif LIBC_SCCS and 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	*calloc();
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 *)calloc(1, sizeof **iov);
68 
69 	return (*iov);
70 }
71 
72 _f_morefiles()
73 {
74 	register FILE **iov;
75 	register FILE *fp;
76 	register char *cp;
77 	int nfiles;
78 
79 	nfiles = getdtablesize();
80 
81 	iobglue = (FILE **)calloc(nfiles, sizeof *iobglue);
82 	if (iobglue == NULL)
83 		return (0);
84 
85 	endglue = iobglue + nfiles;
86 
87 	for (fp = _iob, iov = iobglue; fp < &_iob[NSTATIC]; /* void */)
88 		*iov++ = fp++;
89 
90 	_smallbuf = calloc(nfiles, sizeof(*_smallbuf));
91 	return (1);
92 }
93 
94 f_prealloc()
95 {
96 	register FILE **iov;
97 	register FILE *fp;
98 
99 	if (iobglue == NULL && _f_morefiles() == 0)
100 		return;
101 
102 	for (iov = iobglue; iov < endglue; iov++)
103 		if (*iov == NULL)
104 			*iov = (FILE *)calloc(1, sizeof **iov);
105 }
106 
107 _fwalk(function)
108 	register int (*function)();
109 {
110 	register FILE **iov;
111 	register FILE *fp;
112 
113 	if (iobglue == NULL) {
114 		for (fp = _iob; fp < &_iob[NSTATIC]; fp++)
115 			if (active(fp))
116 				(*function)(fp);
117 	} else {
118 		for (iov = iobglue; iov < endglue; iov++)
119 			if (*iov && active(*iov))
120 				(*function)(*iov);
121 	}
122 }
123