/*- * Copyright (c) 1990 The Regents of the University of California. * All rights reserved. * * This code is derived from software contributed to Berkeley by * Chris Torek. * * %sccs.include.redist.c% */ #if defined(LIBC_SCCS) && !defined(lint) static char sccsid[] = "@(#)findfp.c 5.8 (Berkeley) 01/20/91"; #endif /* LIBC_SCCS and not lint */ #include #include #include #include #include "local.h" #include "glue.h" int __sdidinit; #define NSTATIC 20 /* stdin + stdout + stderr + the usual */ #define NDYNAMIC 10 /* add ten more whenever necessary */ #define std(flags, file) \ {0,0,0,flags,file,{0},0,__sF+file,__sread,__swrite,__sseek,__sclose} /* p r w flags file _bf z cookie read write seek close */ static FILE usual[NSTATIC - 3]; /* the usual */ static struct glue uglue = { 0, NSTATIC - 3, usual }; FILE __sF[3] = { std(__SRD, STDIN_FILENO), /* stdin */ std(__SWR, STDOUT_FILENO), /* stdout */ std(__SWR|__SNBF, STDERR_FILENO) /* stderr */ }; struct glue __sglue = { &uglue, 3, __sF }; static struct glue * moreglue(n) register int n; { register struct glue *g; register FILE *p; static FILE empty; g = (struct glue *)malloc(sizeof(*g) + n * sizeof(FILE)); if (g == NULL) return (NULL); p = (FILE *)(g + 1); g->next = NULL; g->niobs = n; g->iobs = p; while (--n >= 0) *p++ = empty; return (g); } /* * Find a free FILE for fopen et al. */ FILE * __sfp() { register FILE *fp; register int n; register struct glue *g; if (!__sdidinit) __sinit(); for (g = &__sglue;; g = g->next) { for (fp = g->iobs, n = g->niobs; --n >= 0; fp++) if (fp->_flags == 0) goto found; if (g->next == NULL && (g->next = moreglue(NDYNAMIC)) == NULL) break; } return (NULL); found: fp->_flags = 1; /* reserve this slot; caller sets real flags */ fp->_p = NULL; /* no current pointer */ fp->_w = 0; /* nothing to read or write */ fp->_r = 0; fp->_bf._base = NULL; /* no buffer */ fp->_bf._size = 0; fp->_lbfsize = 0; /* not line buffered */ fp->_file = -1; /* no file */ /* fp->_cookie = ; */ /* caller sets cookie, _read/_write etc */ fp->_ub._base = NULL; /* no ungetc buffer */ fp->_ub._size = 0; fp->_lb._base = NULL; /* no line buffer */ fp->_lb._size = 0; return (fp); } /* * XXX. Force immediate allocation of internal memory. Not used by stdio, * but documented historically for certain applications. Bad applications. */ f_prealloc() { int n = getdtablesize() - NSTATIC + 20; /* 20 for slop */ register struct glue *g; for (g = &__sglue; (n -= g->niobs) > 0 && g->next; g = g->next) /* void */; if (n > 0) g->next = moreglue(n); } /* * exit() calls _cleanup() through *__cleanup, set whenever we * open or buffer a file. This chicanery is done so that programs * that do not use stdio need not link it all in. * * The name `_cleanup' is, alas, fairly well known outside stdio. */ void _cleanup() { /* (void) _fwalk(fclose); */ (void) _fwalk(__sflush); /* `cheating' */ } /* * __sinit() is called whenever stdio's internal variables must be set up. */ void __sinit() { /* make sure we clean up on exit */ __cleanup = _cleanup; /* conservative */ __sdidinit = 1; }