1 /* 2 * Copyright (c) 1983, 1985 Regents of the University of California. 3 * All rights reserved. The Berkeley software License Agreement 4 * specifies the terms and conditions for redistribution. 5 */ 6 7 #if defined(LIBC_SCCS) && !defined(lint) 8 static char sccsid[] = "@(#)findfp.c 5.7 (Berkeley) 09/22/88"; 9 #endif LIBC_SCCS and not lint 10 11 #include <stdio.h> 12 #include <errno.h> 13 14 extern int errno; 15 16 #define active(iop) ((iop)->_flag & (_IOREAD|_IOWRT|_IORW)) 17 18 #define NSTATIC 20 /* stdin + stdout + stderr + the usual */ 19 20 FILE _iob[NSTATIC] = { 21 { 0, NULL, NULL, 0, _IOREAD, 0 }, /* stdin */ 22 { 0, NULL, NULL, 0, _IOWRT, 1 }, /* stdout */ 23 { 0, NULL, NULL, 0, _IOWRT|_IONBF, 2 }, /* stderr */ 24 }; 25 26 extern char *calloc(); 27 28 static char sbuf[NSTATIC]; 29 char *_smallbuf = sbuf; 30 static FILE **iobglue; 31 static FILE **endglue; 32 33 /* 34 * Find a free FILE for fopen et al. 35 * We have a fixed static array of entries, and in addition 36 * may allocate additional entries dynamically, up to the kernel 37 * limit on the number of open files. 38 * At first just check for a free slot in the fixed static array. 39 * If none are available, then we allocate a structure to glue together 40 * the old and new FILE entries, which are then no longer contiguous. 41 */ 42 FILE * 43 _findiop() 44 { 45 register FILE **iov, *iop; 46 register FILE *fp; 47 48 if (iobglue == 0) { 49 for (iop = _iob; iop < _iob + NSTATIC; iop++) 50 if (!active(iop)) 51 return (iop); 52 53 if (_f_morefiles() == 0) { 54 errno = ENOMEM; 55 return (NULL); 56 } 57 } 58 59 iov = iobglue; 60 while (*iov != NULL && active(*iov)) 61 if (++iov >= endglue) { 62 errno = EMFILE; 63 return (NULL); 64 } 65 66 if (*iov == NULL) 67 *iov = (FILE *)calloc(1, sizeof **iov); 68 69 return (*iov); 70 } 71 72 _f_morefiles() 73 { 74 register FILE **iov; 75 register FILE *fp; 76 register char *cp; 77 int nfiles; 78 79 nfiles = getdtablesize(); 80 81 iobglue = (FILE **)calloc(nfiles, sizeof *iobglue); 82 if (iobglue == NULL) 83 return (0); 84 85 endglue = iobglue + nfiles; 86 87 for (fp = _iob, iov = iobglue; fp < &_iob[NSTATIC]; /* void */) 88 *iov++ = fp++; 89 90 _smallbuf = calloc(nfiles, sizeof(*_smallbuf)); 91 return (1); 92 } 93 94 f_prealloc() 95 { 96 register FILE **iov; 97 register FILE *fp; 98 99 if (iobglue == NULL && _f_morefiles() == 0) 100 return; 101 102 for (iov = iobglue; iov < endglue; iov++) 103 if (*iov == NULL) 104 *iov = (FILE *)calloc(1, sizeof **iov); 105 } 106 107 _fwalk(function) 108 register int (*function)(); 109 { 110 register FILE **iov; 111 register FILE *fp; 112 113 if (iobglue == NULL) { 114 for (fp = _iob; fp < &_iob[NSTATIC]; fp++) 115 if (active(fp)) 116 (*function)(fp); 117 } else { 118 for (iov = iobglue; iov < endglue; iov++) 119 if (*iov && active(*iov)) 120 (*function)(*iov); 121 } 122 } 123