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*46211Sbostic static char sccsid[] = "@(#)findfp.c 5.9 (Berkeley) 02/01/91"; 1346074Sbostic #endif /* LIBC_SCCS and not lint */ 1421402Sdist 1517951Sserge #include <stdio.h> 1646074Sbostic #include <stdlib.h> 1746074Sbostic #include <unistd.h> 1824936Slepreau #include <errno.h> 1946074Sbostic #include "local.h" 2046074Sbostic #include "glue.h" 2117874Sserge 2246074Sbostic int __sdidinit; 2324936Slepreau 2426097Skarels #define NSTATIC 20 /* stdin + stdout + stderr + the usual */ 2546074Sbostic #define NDYNAMIC 10 /* add ten more whenever necessary */ 2617874Sserge 2746074Sbostic #define std(flags, file) \ 28*46211Sbostic {0,0,0,flags,file,{0},0,__sF+file,__sclose,__sread,__sseek,__swrite} 29*46211Sbostic /* p r w flags file _bf z cookie close read seek write */ 3046074Sbostic 3146074Sbostic static FILE usual[NSTATIC - 3]; /* the usual */ 3246074Sbostic static struct glue uglue = { 0, NSTATIC - 3, usual }; 3346074Sbostic 3446074Sbostic FILE __sF[3] = { 3546074Sbostic std(__SRD, STDIN_FILENO), /* stdin */ 3646074Sbostic std(__SWR, STDOUT_FILENO), /* stdout */ 3746074Sbostic std(__SWR|__SNBF, STDERR_FILENO) /* stderr */ 3817874Sserge }; 3946074Sbostic struct glue __sglue = { &uglue, 3, __sF }; 4017874Sserge 4146074Sbostic static struct glue * 4246074Sbostic moreglue(n) 4346074Sbostic register int n; 4446074Sbostic { 4546074Sbostic register struct glue *g; 4646074Sbostic register FILE *p; 4746074Sbostic static FILE empty; 4818248Sserge 4946074Sbostic g = (struct glue *)malloc(sizeof(*g) + n * sizeof(FILE)); 5046074Sbostic if (g == NULL) 5146074Sbostic return (NULL); 5246074Sbostic p = (FILE *)(g + 1); 5346074Sbostic g->next = NULL; 5446074Sbostic g->niobs = n; 5546074Sbostic g->iobs = p; 5646074Sbostic while (--n >= 0) 5746074Sbostic *p++ = empty; 5846074Sbostic return (g); 5946074Sbostic } 6018248Sserge 6126119Skarels /* 6226119Skarels * Find a free FILE for fopen et al. 6326119Skarels */ 6417874Sserge FILE * 6546074Sbostic __sfp() 6617874Sserge { 6717874Sserge register FILE *fp; 6846074Sbostic register int n; 6946074Sbostic register struct glue *g; 7017874Sserge 7146074Sbostic if (!__sdidinit) 7246074Sbostic __sinit(); 7346074Sbostic for (g = &__sglue;; g = g->next) { 7446074Sbostic for (fp = g->iobs, n = g->niobs; --n >= 0; fp++) 7546074Sbostic if (fp->_flags == 0) 7646074Sbostic goto found; 7746074Sbostic if (g->next == NULL && (g->next = moreglue(NDYNAMIC)) == NULL) 7846074Sbostic break; 7917874Sserge } 8046074Sbostic return (NULL); 8146074Sbostic found: 8246074Sbostic fp->_flags = 1; /* reserve this slot; caller sets real flags */ 8346074Sbostic fp->_p = NULL; /* no current pointer */ 8446074Sbostic fp->_w = 0; /* nothing to read or write */ 8546074Sbostic fp->_r = 0; 8646074Sbostic fp->_bf._base = NULL; /* no buffer */ 8746074Sbostic fp->_bf._size = 0; 8846074Sbostic fp->_lbfsize = 0; /* not line buffered */ 8946074Sbostic fp->_file = -1; /* no file */ 9046074Sbostic /* fp->_cookie = <any>; */ /* caller sets cookie, _read/_write etc */ 9146074Sbostic fp->_ub._base = NULL; /* no ungetc buffer */ 9246074Sbostic fp->_ub._size = 0; 9346074Sbostic fp->_lb._base = NULL; /* no line buffer */ 9446074Sbostic fp->_lb._size = 0; 9546074Sbostic return (fp); 9617874Sserge } 9717874Sserge 9846074Sbostic /* 9946074Sbostic * XXX. Force immediate allocation of internal memory. Not used by stdio, 10046074Sbostic * but documented historically for certain applications. Bad applications. 10146074Sbostic */ 10246074Sbostic f_prealloc() 10326097Skarels { 10446074Sbostic int n = getdtablesize() - NSTATIC + 20; /* 20 for slop */ 10546074Sbostic register struct glue *g; 10626097Skarels 10746074Sbostic for (g = &__sglue; (n -= g->niobs) > 0 && g->next; g = g->next) 10846074Sbostic /* void */; 10946074Sbostic if (n > 0) 11046074Sbostic g->next = moreglue(n); 11126097Skarels } 11226097Skarels 11346074Sbostic /* 11446074Sbostic * exit() calls _cleanup() through *__cleanup, set whenever we 11546074Sbostic * open or buffer a file. This chicanery is done so that programs 11646074Sbostic * that do not use stdio need not link it all in. 11746074Sbostic * 11846074Sbostic * The name `_cleanup' is, alas, fairly well known outside stdio. 11946074Sbostic */ 12046074Sbostic void 12146074Sbostic _cleanup() 12226097Skarels { 12346074Sbostic /* (void) _fwalk(fclose); */ 12446074Sbostic (void) _fwalk(__sflush); /* `cheating' */ 12526097Skarels } 12626097Skarels 12746074Sbostic /* 12846074Sbostic * __sinit() is called whenever stdio's internal variables must be set up. 12946074Sbostic */ 13046074Sbostic void 13146074Sbostic __sinit() 13217874Sserge { 13346074Sbostic /* make sure we clean up on exit */ 13446074Sbostic __cleanup = _cleanup; /* conservative */ 13546074Sbostic __sdidinit = 1; 13617874Sserge } 137