xref: /csrg-svn/lib/libc/stdio/findfp.c (revision 46074)
1*46074Sbostic /*-
2*46074Sbostic  * Copyright (c) 1990 The Regents of the University of California.
3*46074Sbostic  * All rights reserved.
4*46074Sbostic  *
5*46074Sbostic  * This code is derived from software contributed to Berkeley by
6*46074Sbostic  * Chris Torek.
7*46074Sbostic  *
8*46074Sbostic  * %sccs.include.redist.c%
921402Sdist  */
1021402Sdist 
1126645Sdonn #if defined(LIBC_SCCS) && !defined(lint)
12*46074Sbostic static char sccsid[] = "@(#)findfp.c	5.8 (Berkeley) 01/20/91";
13*46074Sbostic #endif /* LIBC_SCCS and not lint */
1421402Sdist 
1517951Sserge #include <stdio.h>
16*46074Sbostic #include <stdlib.h>
17*46074Sbostic #include <unistd.h>
1824936Slepreau #include <errno.h>
19*46074Sbostic #include "local.h"
20*46074Sbostic #include "glue.h"
2117874Sserge 
22*46074Sbostic int	__sdidinit;
2324936Slepreau 
2426097Skarels #define NSTATIC	20	/* stdin + stdout + stderr + the usual */
25*46074Sbostic #define	NDYNAMIC 10	/* add ten more whenever necessary */
2617874Sserge 
27*46074Sbostic #define	std(flags, file) \
28*46074Sbostic 	{0,0,0,flags,file,{0},0,__sF+file,__sread,__swrite,__sseek,__sclose}
29*46074Sbostic /*	 p r w flags file _bf z  cookie    read    write    seek    close */
30*46074Sbostic 
31*46074Sbostic static FILE usual[NSTATIC - 3];	/* the usual */
32*46074Sbostic static struct glue uglue = { 0, NSTATIC - 3, usual };
33*46074Sbostic 
34*46074Sbostic FILE __sF[3] = {
35*46074Sbostic 	std(__SRD, STDIN_FILENO),		/* stdin */
36*46074Sbostic 	std(__SWR, STDOUT_FILENO),		/* stdout */
37*46074Sbostic 	std(__SWR|__SNBF, STDERR_FILENO)	/* stderr */
3817874Sserge };
39*46074Sbostic struct glue __sglue = { &uglue, 3, __sF };
4017874Sserge 
41*46074Sbostic static struct glue *
42*46074Sbostic moreglue(n)
43*46074Sbostic 	register int n;
44*46074Sbostic {
45*46074Sbostic 	register struct glue *g;
46*46074Sbostic 	register FILE *p;
47*46074Sbostic 	static FILE empty;
4818248Sserge 
49*46074Sbostic 	g = (struct glue *)malloc(sizeof(*g) + n * sizeof(FILE));
50*46074Sbostic 	if (g == NULL)
51*46074Sbostic 		return (NULL);
52*46074Sbostic 	p = (FILE *)(g + 1);
53*46074Sbostic 	g->next = NULL;
54*46074Sbostic 	g->niobs = n;
55*46074Sbostic 	g->iobs = p;
56*46074Sbostic 	while (--n >= 0)
57*46074Sbostic 		*p++ = empty;
58*46074Sbostic 	return (g);
59*46074Sbostic }
6018248Sserge 
6126119Skarels /*
6226119Skarels  * Find a free FILE for fopen et al.
6326119Skarels  */
6417874Sserge FILE *
65*46074Sbostic __sfp()
6617874Sserge {
6717874Sserge 	register FILE *fp;
68*46074Sbostic 	register int n;
69*46074Sbostic 	register struct glue *g;
7017874Sserge 
71*46074Sbostic 	if (!__sdidinit)
72*46074Sbostic 		__sinit();
73*46074Sbostic 	for (g = &__sglue;; g = g->next) {
74*46074Sbostic 		for (fp = g->iobs, n = g->niobs; --n >= 0; fp++)
75*46074Sbostic 			if (fp->_flags == 0)
76*46074Sbostic 				goto found;
77*46074Sbostic 		if (g->next == NULL && (g->next = moreglue(NDYNAMIC)) == NULL)
78*46074Sbostic 			break;
7917874Sserge 	}
80*46074Sbostic 	return (NULL);
81*46074Sbostic found:
82*46074Sbostic 	fp->_flags = 1;		/* reserve this slot; caller sets real flags */
83*46074Sbostic 	fp->_p = NULL;		/* no current pointer */
84*46074Sbostic 	fp->_w = 0;		/* nothing to read or write */
85*46074Sbostic 	fp->_r = 0;
86*46074Sbostic 	fp->_bf._base = NULL;	/* no buffer */
87*46074Sbostic 	fp->_bf._size = 0;
88*46074Sbostic 	fp->_lbfsize = 0;	/* not line buffered */
89*46074Sbostic 	fp->_file = -1;		/* no file */
90*46074Sbostic /*	fp->_cookie = <any>; */	/* caller sets cookie, _read/_write etc */
91*46074Sbostic 	fp->_ub._base = NULL;	/* no ungetc buffer */
92*46074Sbostic 	fp->_ub._size = 0;
93*46074Sbostic 	fp->_lb._base = NULL;	/* no line buffer */
94*46074Sbostic 	fp->_lb._size = 0;
95*46074Sbostic 	return (fp);
9617874Sserge }
9717874Sserge 
98*46074Sbostic /*
99*46074Sbostic  * XXX.  Force immediate allocation of internal memory.  Not used by stdio,
100*46074Sbostic  * but documented historically for certain applications.  Bad applications.
101*46074Sbostic  */
102*46074Sbostic f_prealloc()
10326097Skarels {
104*46074Sbostic 	int n = getdtablesize() - NSTATIC + 20;		/* 20 for slop */
105*46074Sbostic 	register struct glue *g;
10626097Skarels 
107*46074Sbostic 	for (g = &__sglue; (n -= g->niobs) > 0 && g->next; g = g->next)
108*46074Sbostic 		/* void */;
109*46074Sbostic 	if (n > 0)
110*46074Sbostic 		g->next = moreglue(n);
11126097Skarels }
11226097Skarels 
113*46074Sbostic /*
114*46074Sbostic  * exit() calls _cleanup() through *__cleanup, set whenever we
115*46074Sbostic  * open or buffer a file.  This chicanery is done so that programs
116*46074Sbostic  * that do not use stdio need not link it all in.
117*46074Sbostic  *
118*46074Sbostic  * The name `_cleanup' is, alas, fairly well known outside stdio.
119*46074Sbostic  */
120*46074Sbostic void
121*46074Sbostic _cleanup()
12226097Skarels {
123*46074Sbostic 	/* (void) _fwalk(fclose); */
124*46074Sbostic 	(void) _fwalk(__sflush);		/* `cheating' */
12526097Skarels }
12626097Skarels 
127*46074Sbostic /*
128*46074Sbostic  * __sinit() is called whenever stdio's internal variables must be set up.
129*46074Sbostic  */
130*46074Sbostic void
131*46074Sbostic __sinit()
13217874Sserge {
133*46074Sbostic 	/* make sure we clean up on exit */
134*46074Sbostic 	__cleanup = _cleanup;		/* conservative */
135*46074Sbostic 	__sdidinit = 1;
13617874Sserge }
137