146074Sbostic /*- 246074Sbostic * Copyright (c) 1990 The Regents of the University of California. 346074Sbostic * 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*46611Sbostic static char sccsid[] = "@(#)findfp.c 5.10 (Berkeley) 02/24/91"; 1346074Sbostic #endif /* LIBC_SCCS and not lint */ 1421402Sdist 15*46611Sbostic #include <unistd.h> 1617951Sserge #include <stdio.h> 17*46611Sbostic #include <errno.h> 1846074Sbostic #include <stdlib.h> 19*46611Sbostic #include <string.h> 2046074Sbostic #include "local.h" 2146074Sbostic #include "glue.h" 2217874Sserge 2346074Sbostic int __sdidinit; 2424936Slepreau 2526097Skarels #define NSTATIC 20 /* stdin + stdout + stderr + the usual */ 2646074Sbostic #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 3246074Sbostic static FILE usual[NSTATIC - 3]; /* the usual */ 3346074Sbostic static struct glue uglue = { 0, NSTATIC - 3, usual }; 3446074Sbostic 3546074Sbostic FILE __sF[3] = { 3646074Sbostic std(__SRD, STDIN_FILENO), /* stdin */ 3746074Sbostic std(__SWR, STDOUT_FILENO), /* stdout */ 3846074Sbostic std(__SWR|__SNBF, STDERR_FILENO) /* stderr */ 3917874Sserge }; 4046074Sbostic struct glue __sglue = { &uglue, 3, __sF }; 4117874Sserge 4246074Sbostic static struct glue * 4346074Sbostic moreglue(n) 4446074Sbostic register int n; 4546074Sbostic { 4646074Sbostic register struct glue *g; 4746074Sbostic register FILE *p; 4846074Sbostic static FILE empty; 4918248Sserge 5046074Sbostic g = (struct glue *)malloc(sizeof(*g) + n * sizeof(FILE)); 5146074Sbostic if (g == NULL) 5246074Sbostic return (NULL); 5346074Sbostic p = (FILE *)(g + 1); 5446074Sbostic g->next = NULL; 5546074Sbostic g->niobs = n; 5646074Sbostic g->iobs = p; 5746074Sbostic while (--n >= 0) 5846074Sbostic *p++ = empty; 5946074Sbostic return (g); 6046074Sbostic } 6118248Sserge 6226119Skarels /* 6326119Skarels * Find a free FILE for fopen et al. 6426119Skarels */ 6517874Sserge FILE * 6646074Sbostic __sfp() 6717874Sserge { 6817874Sserge register FILE *fp; 6946074Sbostic register int n; 7046074Sbostic register struct glue *g; 7117874Sserge 7246074Sbostic if (!__sdidinit) 7346074Sbostic __sinit(); 7446074Sbostic for (g = &__sglue;; g = g->next) { 7546074Sbostic for (fp = g->iobs, n = g->niobs; --n >= 0; fp++) 7646074Sbostic if (fp->_flags == 0) 7746074Sbostic goto found; 7846074Sbostic if (g->next == NULL && (g->next = moreglue(NDYNAMIC)) == NULL) 7946074Sbostic break; 8017874Sserge } 8146074Sbostic return (NULL); 8246074Sbostic found: 8346074Sbostic fp->_flags = 1; /* reserve this slot; caller sets real flags */ 8446074Sbostic fp->_p = NULL; /* no current pointer */ 8546074Sbostic fp->_w = 0; /* nothing to read or write */ 8646074Sbostic fp->_r = 0; 8746074Sbostic fp->_bf._base = NULL; /* no buffer */ 8846074Sbostic fp->_bf._size = 0; 8946074Sbostic fp->_lbfsize = 0; /* not line buffered */ 9046074Sbostic fp->_file = -1; /* no file */ 9146074Sbostic /* fp->_cookie = <any>; */ /* caller sets cookie, _read/_write etc */ 9246074Sbostic fp->_ub._base = NULL; /* no ungetc buffer */ 9346074Sbostic fp->_ub._size = 0; 9446074Sbostic fp->_lb._base = NULL; /* no line buffer */ 9546074Sbostic fp->_lb._size = 0; 9646074Sbostic return (fp); 9717874Sserge } 9817874Sserge 9946074Sbostic /* 10046074Sbostic * XXX. Force immediate allocation of internal memory. Not used by stdio, 10146074Sbostic * but documented historically for certain applications. Bad applications. 10246074Sbostic */ 10346074Sbostic f_prealloc() 10426097Skarels { 10546074Sbostic int n = getdtablesize() - NSTATIC + 20; /* 20 for slop */ 10646074Sbostic register struct glue *g; 10726097Skarels 10846074Sbostic for (g = &__sglue; (n -= g->niobs) > 0 && g->next; g = g->next) 10946074Sbostic /* void */; 11046074Sbostic if (n > 0) 11146074Sbostic g->next = moreglue(n); 11226097Skarels } 11326097Skarels 11446074Sbostic /* 11546074Sbostic * exit() calls _cleanup() through *__cleanup, set whenever we 11646074Sbostic * open or buffer a file. This chicanery is done so that programs 11746074Sbostic * that do not use stdio need not link it all in. 11846074Sbostic * 11946074Sbostic * The name `_cleanup' is, alas, fairly well known outside stdio. 12046074Sbostic */ 12146074Sbostic void 12246074Sbostic _cleanup() 12326097Skarels { 12446074Sbostic /* (void) _fwalk(fclose); */ 12546074Sbostic (void) _fwalk(__sflush); /* `cheating' */ 12626097Skarels } 12726097Skarels 12846074Sbostic /* 12946074Sbostic * __sinit() is called whenever stdio's internal variables must be set up. 13046074Sbostic */ 13146074Sbostic void 13246074Sbostic __sinit() 13317874Sserge { 13446074Sbostic /* make sure we clean up on exit */ 13546074Sbostic __cleanup = _cleanup; /* conservative */ 13646074Sbostic __sdidinit = 1; 13717874Sserge } 138