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 #ifndef lint 8 static char sccsid[] = "@(#)findfp.c 5.4 (Berkeley) 02/09/86"; 9 #endif 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 *malloc(); 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 *)malloc(sizeof **iov); 68 if (*iov) 69 bzero((char *)*iov, sizeof(**iov)); 70 71 return (*iov); 72 } 73 74 _f_morefiles() 75 { 76 register FILE **iov; 77 register FILE *fp; 78 register char *cp; 79 int nfiles; 80 81 nfiles = getdtablesize(); 82 83 iobglue = (FILE **)malloc(nfiles * sizeof *iobglue); 84 if (iobglue == NULL) 85 return (0); 86 87 bzero((char *)iobglue, nfiles * sizeof(*iobglue)); 88 endglue = iobglue + nfiles; 89 90 for (fp = _iob, iov = iobglue; fp < &_iob[NSTATIC]; /* void */) 91 *iov++ = fp++; 92 93 _smallbuf = malloc(nfiles * sizeof(*_smallbuf)); 94 return (1); 95 } 96 97 f_prealloc() 98 { 99 register FILE **iov; 100 register FILE *fp; 101 102 if (iobglue == NULL && _f_morefiles() == 0) 103 return; 104 105 for (iov = iobglue; iov < endglue; iov++) 106 if (*iov == NULL) { 107 *iov = (FILE *)malloc(1, sizeof **iov); 108 if (*iov) 109 bzero((char *)*iov, sizeof(**iov)); 110 } 111 } 112 113 _fwalk(function) 114 register int (*function)(); 115 { 116 register FILE **iov; 117 register FILE *fp; 118 119 if (iobglue == NULL) { 120 for (fp = _iob; fp < &_iob[NSTATIC]; fp++) 121 if (active(fp)) 122 (*function)(fp); 123 } else { 124 for (iov = iobglue; iov < endglue; iov++) 125 if (*iov && active(*iov)) 126 (*function)(*iov); 127 } 128 } 129 130 _cleanup() 131 { 132 extern int fclose(); 133 134 _fwalk(fclose); 135 } 136