1*46074Sbostic /*- 2*46074Sbostic * Copyright (c) 1990 The Regents of the University of California. 3*46074Sbostic * All rights reserved. 4*46074Sbostic * 5*46074Sbostic * This code is derived from software contributed to Berkeley by 6*46074Sbostic * Chris Torek. 7*46074Sbostic * 8*46074Sbostic * %sccs.include.redist.c% 921402Sdist */ 1021402Sdist 1126645Sdonn #if defined(LIBC_SCCS) && !defined(lint) 12*46074Sbostic static char sccsid[] = "@(#)findfp.c 5.8 (Berkeley) 01/20/91"; 13*46074Sbostic #endif /* LIBC_SCCS and not lint */ 1421402Sdist 1517951Sserge #include <stdio.h> 16*46074Sbostic #include <stdlib.h> 17*46074Sbostic #include <unistd.h> 1824936Slepreau #include <errno.h> 19*46074Sbostic #include "local.h" 20*46074Sbostic #include "glue.h" 2117874Sserge 22*46074Sbostic int __sdidinit; 2324936Slepreau 2426097Skarels #define NSTATIC 20 /* stdin + stdout + stderr + the usual */ 25*46074Sbostic #define NDYNAMIC 10 /* add ten more whenever necessary */ 2617874Sserge 27*46074Sbostic #define std(flags, file) \ 28*46074Sbostic {0,0,0,flags,file,{0},0,__sF+file,__sread,__swrite,__sseek,__sclose} 29*46074Sbostic /* p r w flags file _bf z cookie read write seek close */ 30*46074Sbostic 31*46074Sbostic static FILE usual[NSTATIC - 3]; /* the usual */ 32*46074Sbostic static struct glue uglue = { 0, NSTATIC - 3, usual }; 33*46074Sbostic 34*46074Sbostic FILE __sF[3] = { 35*46074Sbostic std(__SRD, STDIN_FILENO), /* stdin */ 36*46074Sbostic std(__SWR, STDOUT_FILENO), /* stdout */ 37*46074Sbostic std(__SWR|__SNBF, STDERR_FILENO) /* stderr */ 3817874Sserge }; 39*46074Sbostic struct glue __sglue = { &uglue, 3, __sF }; 4017874Sserge 41*46074Sbostic static struct glue * 42*46074Sbostic moreglue(n) 43*46074Sbostic register int n; 44*46074Sbostic { 45*46074Sbostic register struct glue *g; 46*46074Sbostic register FILE *p; 47*46074Sbostic static FILE empty; 4818248Sserge 49*46074Sbostic g = (struct glue *)malloc(sizeof(*g) + n * sizeof(FILE)); 50*46074Sbostic if (g == NULL) 51*46074Sbostic return (NULL); 52*46074Sbostic p = (FILE *)(g + 1); 53*46074Sbostic g->next = NULL; 54*46074Sbostic g->niobs = n; 55*46074Sbostic g->iobs = p; 56*46074Sbostic while (--n >= 0) 57*46074Sbostic *p++ = empty; 58*46074Sbostic return (g); 59*46074Sbostic } 6018248Sserge 6126119Skarels /* 6226119Skarels * Find a free FILE for fopen et al. 6326119Skarels */ 6417874Sserge FILE * 65*46074Sbostic __sfp() 6617874Sserge { 6717874Sserge register FILE *fp; 68*46074Sbostic register int n; 69*46074Sbostic register struct glue *g; 7017874Sserge 71*46074Sbostic if (!__sdidinit) 72*46074Sbostic __sinit(); 73*46074Sbostic for (g = &__sglue;; g = g->next) { 74*46074Sbostic for (fp = g->iobs, n = g->niobs; --n >= 0; fp++) 75*46074Sbostic if (fp->_flags == 0) 76*46074Sbostic goto found; 77*46074Sbostic if (g->next == NULL && (g->next = moreglue(NDYNAMIC)) == NULL) 78*46074Sbostic break; 7917874Sserge } 80*46074Sbostic return (NULL); 81*46074Sbostic found: 82*46074Sbostic fp->_flags = 1; /* reserve this slot; caller sets real flags */ 83*46074Sbostic fp->_p = NULL; /* no current pointer */ 84*46074Sbostic fp->_w = 0; /* nothing to read or write */ 85*46074Sbostic fp->_r = 0; 86*46074Sbostic fp->_bf._base = NULL; /* no buffer */ 87*46074Sbostic fp->_bf._size = 0; 88*46074Sbostic fp->_lbfsize = 0; /* not line buffered */ 89*46074Sbostic fp->_file = -1; /* no file */ 90*46074Sbostic /* fp->_cookie = <any>; */ /* caller sets cookie, _read/_write etc */ 91*46074Sbostic fp->_ub._base = NULL; /* no ungetc buffer */ 92*46074Sbostic fp->_ub._size = 0; 93*46074Sbostic fp->_lb._base = NULL; /* no line buffer */ 94*46074Sbostic fp->_lb._size = 0; 95*46074Sbostic return (fp); 9617874Sserge } 9717874Sserge 98*46074Sbostic /* 99*46074Sbostic * XXX. Force immediate allocation of internal memory. Not used by stdio, 100*46074Sbostic * but documented historically for certain applications. Bad applications. 101*46074Sbostic */ 102*46074Sbostic f_prealloc() 10326097Skarels { 104*46074Sbostic int n = getdtablesize() - NSTATIC + 20; /* 20 for slop */ 105*46074Sbostic register struct glue *g; 10626097Skarels 107*46074Sbostic for (g = &__sglue; (n -= g->niobs) > 0 && g->next; g = g->next) 108*46074Sbostic /* void */; 109*46074Sbostic if (n > 0) 110*46074Sbostic g->next = moreglue(n); 11126097Skarels } 11226097Skarels 113*46074Sbostic /* 114*46074Sbostic * exit() calls _cleanup() through *__cleanup, set whenever we 115*46074Sbostic * open or buffer a file. This chicanery is done so that programs 116*46074Sbostic * that do not use stdio need not link it all in. 117*46074Sbostic * 118*46074Sbostic * The name `_cleanup' is, alas, fairly well known outside stdio. 119*46074Sbostic */ 120*46074Sbostic void 121*46074Sbostic _cleanup() 12226097Skarels { 123*46074Sbostic /* (void) _fwalk(fclose); */ 124*46074Sbostic (void) _fwalk(__sflush); /* `cheating' */ 12526097Skarels } 12626097Skarels 127*46074Sbostic /* 128*46074Sbostic * __sinit() is called whenever stdio's internal variables must be set up. 129*46074Sbostic */ 130*46074Sbostic void 131*46074Sbostic __sinit() 13217874Sserge { 133*46074Sbostic /* make sure we clean up on exit */ 134*46074Sbostic __cleanup = _cleanup; /* conservative */ 135*46074Sbostic __sdidinit = 1; 13617874Sserge } 137