146074Sbostic /*- 2*61180Sbostic * Copyright (c) 1990, 1993 3*61180Sbostic * 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*61180Sbostic static char sccsid[] = "@(#)findfp.c 8.1 (Berkeley) 06/04/93"; 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 2626097Skarels #define NSTATIC 20 /* stdin + stdout + stderr + the usual */ 2746074Sbostic #define NDYNAMIC 10 /* add ten more whenever necessary */ 2817874Sserge 2946074Sbostic #define std(flags, file) \ 3046211Sbostic {0,0,0,flags,file,{0},0,__sF+file,__sclose,__sread,__sseek,__swrite} 3146211Sbostic /* p r w flags file _bf z cookie close read seek write */ 3246074Sbostic 3346074Sbostic static FILE usual[NSTATIC - 3]; /* the usual */ 3446074Sbostic static struct glue uglue = { 0, NSTATIC - 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 * 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 * 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 */ 10446074Sbostic f_prealloc() 10526097Skarels { 10646074Sbostic int n = getdtablesize() - NSTATIC + 20; /* 20 for slop */ 10746074Sbostic register struct glue *g; 10826097Skarels 10946074Sbostic for (g = &__sglue; (n -= g->niobs) > 0 && g->next; g = g->next) 11046074Sbostic /* void */; 11146074Sbostic if (n > 0) 11246074Sbostic g->next = moreglue(n); 11326097Skarels } 11426097Skarels 11546074Sbostic /* 11646074Sbostic * exit() calls _cleanup() through *__cleanup, set whenever we 11746074Sbostic * open or buffer a file. This chicanery is done so that programs 11846074Sbostic * that do not use stdio need not link it all in. 11946074Sbostic * 12046074Sbostic * The name `_cleanup' is, alas, fairly well known outside stdio. 12146074Sbostic */ 12246074Sbostic void 12346074Sbostic _cleanup() 12426097Skarels { 12546074Sbostic /* (void) _fwalk(fclose); */ 12646074Sbostic (void) _fwalk(__sflush); /* `cheating' */ 12726097Skarels } 12826097Skarels 12946074Sbostic /* 13046074Sbostic * __sinit() is called whenever stdio's internal variables must be set up. 13146074Sbostic */ 13246074Sbostic void 13346074Sbostic __sinit() 13417874Sserge { 13546074Sbostic /* make sure we clean up on exit */ 13646074Sbostic __cleanup = _cleanup; /* conservative */ 13746074Sbostic __sdidinit = 1; 13817874Sserge } 139