146074Sbostic /*-
261180Sbostic * Copyright (c) 1990, 1993
361180Sbostic * The Regents of the University of California. All rights reserved.
446074Sbostic *
546074Sbostic * This code is derived from software contributed to Berkeley by
646074Sbostic * Chris Torek.
746074Sbostic *
846074Sbostic * %sccs.include.redist.c%
921402Sdist */
1021402Sdist
1126645Sdonn #if defined(LIBC_SCCS) && !defined(lint)
12*65403Sbostic static char sccsid[] = "@(#)findfp.c 8.2 (Berkeley) 01/04/94";
1346074Sbostic #endif /* LIBC_SCCS and not lint */
1421402Sdist
1561109Storek #include <sys/param.h>
1646611Sbostic #include <unistd.h>
1717951Sserge #include <stdio.h>
1846611Sbostic #include <errno.h>
1946074Sbostic #include <stdlib.h>
2046611Sbostic #include <string.h>
2146074Sbostic #include "local.h"
2246074Sbostic #include "glue.h"
2317874Sserge
2446074Sbostic int __sdidinit;
2524936Slepreau
26*65403Sbostic #define NDYNAMIC 10 /* add ten more whenever necessary */
2717874Sserge
2846074Sbostic #define std(flags, file) \
2946211Sbostic {0,0,0,flags,file,{0},0,__sF+file,__sclose,__sread,__sseek,__swrite}
3046211Sbostic /* p r w flags file _bf z cookie close read seek write */
3146074Sbostic
32*65403Sbostic /* the usual - (stdin + stdout + stderr) */
33*65403Sbostic static FILE usual[FOPEN_MAX - 3];
34*65403Sbostic static struct glue uglue = { 0, FOPEN_MAX - 3, usual };
3546074Sbostic
3646074Sbostic FILE __sF[3] = {
3746074Sbostic std(__SRD, STDIN_FILENO), /* stdin */
3846074Sbostic std(__SWR, STDOUT_FILENO), /* stdout */
3946074Sbostic std(__SWR|__SNBF, STDERR_FILENO) /* stderr */
4017874Sserge };
4146074Sbostic struct glue __sglue = { &uglue, 3, __sF };
4217874Sserge
4346074Sbostic static struct glue *
moreglue(n)4446074Sbostic moreglue(n)
4546074Sbostic register int n;
4646074Sbostic {
4746074Sbostic register struct glue *g;
4846074Sbostic register FILE *p;
4946074Sbostic static FILE empty;
5018248Sserge
5161109Storek g = (struct glue *)malloc(sizeof(*g) + ALIGNBYTES + n * sizeof(FILE));
5246074Sbostic if (g == NULL)
5346074Sbostic return (NULL);
5461109Storek p = (FILE *)ALIGN(g + 1);
5546074Sbostic g->next = NULL;
5646074Sbostic g->niobs = n;
5746074Sbostic g->iobs = p;
5846074Sbostic while (--n >= 0)
5946074Sbostic *p++ = empty;
6046074Sbostic return (g);
6146074Sbostic }
6218248Sserge
6326119Skarels /*
6426119Skarels * Find a free FILE for fopen et al.
6526119Skarels */
6617874Sserge FILE *
__sfp()6746074Sbostic __sfp()
6817874Sserge {
6917874Sserge register FILE *fp;
7046074Sbostic register int n;
7146074Sbostic register struct glue *g;
7217874Sserge
7346074Sbostic if (!__sdidinit)
7446074Sbostic __sinit();
7546074Sbostic for (g = &__sglue;; g = g->next) {
7646074Sbostic for (fp = g->iobs, n = g->niobs; --n >= 0; fp++)
7746074Sbostic if (fp->_flags == 0)
7846074Sbostic goto found;
7946074Sbostic if (g->next == NULL && (g->next = moreglue(NDYNAMIC)) == NULL)
8046074Sbostic break;
8117874Sserge }
8246074Sbostic return (NULL);
8346074Sbostic found:
8446074Sbostic fp->_flags = 1; /* reserve this slot; caller sets real flags */
8546074Sbostic fp->_p = NULL; /* no current pointer */
8646074Sbostic fp->_w = 0; /* nothing to read or write */
8746074Sbostic fp->_r = 0;
8846074Sbostic fp->_bf._base = NULL; /* no buffer */
8946074Sbostic fp->_bf._size = 0;
9046074Sbostic fp->_lbfsize = 0; /* not line buffered */
9146074Sbostic fp->_file = -1; /* no file */
9246074Sbostic /* fp->_cookie = <any>; */ /* caller sets cookie, _read/_write etc */
9346074Sbostic fp->_ub._base = NULL; /* no ungetc buffer */
9446074Sbostic fp->_ub._size = 0;
9546074Sbostic fp->_lb._base = NULL; /* no line buffer */
9646074Sbostic fp->_lb._size = 0;
9746074Sbostic return (fp);
9817874Sserge }
9917874Sserge
10046074Sbostic /*
10146074Sbostic * XXX. Force immediate allocation of internal memory. Not used by stdio,
10246074Sbostic * but documented historically for certain applications. Bad applications.
10346074Sbostic */
f_prealloc()10446074Sbostic f_prealloc()
10526097Skarels {
10646074Sbostic register struct glue *g;
107*65403Sbostic int n;
10826097Skarels
109*65403Sbostic n = getdtablesize() - FOPEN_MAX + 20; /* 20 for slop. */
11046074Sbostic for (g = &__sglue; (n -= g->niobs) > 0 && g->next; g = g->next)
11146074Sbostic /* void */;
11246074Sbostic if (n > 0)
11346074Sbostic g->next = moreglue(n);
11426097Skarels }
11526097Skarels
11646074Sbostic /*
11746074Sbostic * exit() calls _cleanup() through *__cleanup, set whenever we
11846074Sbostic * open or buffer a file. This chicanery is done so that programs
11946074Sbostic * that do not use stdio need not link it all in.
12046074Sbostic *
12146074Sbostic * The name `_cleanup' is, alas, fairly well known outside stdio.
12246074Sbostic */
12346074Sbostic void
_cleanup()12446074Sbostic _cleanup()
12526097Skarels {
12646074Sbostic /* (void) _fwalk(fclose); */
12746074Sbostic (void) _fwalk(__sflush); /* `cheating' */
12826097Skarels }
12926097Skarels
13046074Sbostic /*
13146074Sbostic * __sinit() is called whenever stdio's internal variables must be set up.
13246074Sbostic */
13346074Sbostic void
__sinit()13446074Sbostic __sinit()
13517874Sserge {
13646074Sbostic /* make sure we clean up on exit */
13746074Sbostic __cleanup = _cleanup; /* conservative */
13846074Sbostic __sdidinit = 1;
13917874Sserge }
140