xref: /csrg-svn/lib/libc/stdio/findfp.c (revision 26645)
121402Sdist /*
226097Skarels  * Copyright (c) 1983, 1985 Regents of the University of California.
321402Sdist  * All rights reserved.  The Berkeley software License Agreement
421402Sdist  * specifies the terms and conditions for redistribution.
521402Sdist  */
621402Sdist 
7*26645Sdonn #if defined(LIBC_SCCS) && !defined(lint)
8*26645Sdonn static char sccsid[] = "@(#)findfp.c	5.6 (Berkeley) 03/09/86";
9*26645Sdonn #endif LIBC_SCCS and not lint
1021402Sdist 
1117951Sserge #include <stdio.h>
1224936Slepreau #include <errno.h>
1317874Sserge 
1424936Slepreau extern int errno;
1524936Slepreau 
1618248Sserge #define active(iop)	((iop)->_flag & (_IOREAD|_IOWRT|_IORW))
1717874Sserge 
1826097Skarels #define NSTATIC	20	/* stdin + stdout + stderr + the usual */
1917874Sserge 
2017874Sserge FILE _iob[NSTATIC] = {
2118248Sserge 	{ 0, NULL, NULL, 0, _IOREAD,		0 },	/* stdin  */
2218248Sserge 	{ 0, NULL, NULL, 0, _IOWRT,		1 },	/* stdout */
2318248Sserge 	{ 0, NULL, NULL, 0, _IOWRT|_IONBF,	2 },	/* stderr */
2417874Sserge };
2517874Sserge 
2626129Skarels extern	char	*calloc();
2718248Sserge 
2826119Skarels static	char sbuf[NSTATIC];
2926119Skarels char	*_smallbuf = sbuf;
3018248Sserge static	FILE	**iobglue;
3118248Sserge static	FILE	**endglue;
3218248Sserge 
3326119Skarels /*
3426119Skarels  * Find a free FILE for fopen et al.
3526119Skarels  * We have a fixed static array of entries, and in addition
3626119Skarels  * may allocate additional entries dynamically, up to the kernel
3726119Skarels  * limit on the number of open files.
3826119Skarels  * At first just check for a free slot in the fixed static array.
3926119Skarels  * If none are available, then we allocate a structure to glue together
4026119Skarels  * the old and new FILE entries, which are then no longer contiguous.
4126119Skarels  */
4217874Sserge FILE *
4317874Sserge _findiop()
4417874Sserge {
4526119Skarels 	register FILE **iov, *iop;
4617874Sserge 	register FILE *fp;
4717874Sserge 
4826119Skarels 	if (iobglue == 0) {
4926119Skarels 		for (iop = _iob; iop < _iob + NSTATIC; iop++)
5026119Skarels 			if (!active(iop))
5126119Skarels 				return (iop);
5226119Skarels 
5326119Skarels 		if (_f_morefiles() == 0) {
5426119Skarels 			errno = ENOMEM;
5526119Skarels 			return (NULL);
5626119Skarels 		}
5717874Sserge 	}
5817874Sserge 
5918248Sserge 	iov = iobglue;
6018248Sserge 	while (*iov != NULL && active(*iov))
6124936Slepreau 		if (++iov >= endglue) {
6224936Slepreau 			errno = EMFILE;
6317874Sserge 			return (NULL);
6424936Slepreau 		}
6517874Sserge 
6618248Sserge 	if (*iov == NULL)
6726129Skarels 		*iov = (FILE *)calloc(1, sizeof **iov);
6818248Sserge 
6918248Sserge 	return (*iov);
7017874Sserge }
7117874Sserge 
7226119Skarels _f_morefiles()
7326097Skarels {
7426097Skarels 	register FILE **iov;
7526097Skarels 	register FILE *fp;
7626119Skarels 	register char *cp;
7726119Skarels 	int nfiles;
7826097Skarels 
7926097Skarels 	nfiles = getdtablesize();
8026097Skarels 
8126129Skarels 	iobglue = (FILE **)calloc(nfiles, sizeof *iobglue);
8226097Skarels 	if (iobglue == NULL)
8326097Skarels 		return (0);
8426097Skarels 
8526097Skarels 	endglue = iobglue + nfiles;
8626097Skarels 
8726097Skarels 	for (fp = _iob, iov = iobglue; fp < &_iob[NSTATIC]; /* void */)
8826097Skarels 		*iov++ = fp++;
8926119Skarels 
9026129Skarels 	_smallbuf = calloc(nfiles, sizeof(*_smallbuf));
9126097Skarels 	return (1);
9226097Skarels }
9326097Skarels 
9426097Skarels f_prealloc()
9526097Skarels {
9626097Skarels 	register FILE **iov;
9726097Skarels 	register FILE *fp;
9826097Skarels 
9926119Skarels 	if (iobglue == NULL && _f_morefiles() == 0)
10026097Skarels 		return;
10126097Skarels 
10226097Skarels 	for (iov = iobglue; iov < endglue; iov++)
10326129Skarels 		if (*iov == NULL)
10426129Skarels 			*iov = (FILE *)calloc(1, sizeof **iov);
10526097Skarels }
10626097Skarels 
10718248Sserge _fwalk(function)
10818248Sserge 	register int (*function)();
10917874Sserge {
11018248Sserge 	register FILE **iov;
11118248Sserge 	register FILE *fp;
11217874Sserge 
11318248Sserge 	if (iobglue == NULL) {
11426097Skarels 		for (fp = _iob; fp < &_iob[NSTATIC]; fp++)
11518248Sserge 			if (active(fp))
11618248Sserge 				(*function)(fp);
11718248Sserge 	} else {
11818248Sserge 		for (iov = iobglue; iov < endglue; iov++)
11926097Skarels 			if (*iov && active(*iov))
12018248Sserge 				(*function)(*iov);
12118248Sserge 	}
12217874Sserge }
12317951Sserge 
12418248Sserge _cleanup()
12517951Sserge {
12618248Sserge 	extern int fclose();
12718248Sserge 
12818248Sserge 	_fwalk(fclose);
12917951Sserge }
130