|
|
1.1 ! root 1: /* @(#)flsbuf.c 2.8 */ ! 2: /*LINTLIBRARY*/ ! 3: #include <stdio.h> ! 4: #include "stdiom.h" ! 5: #include <errno.h> ! 6: ! 7: extern void free(); ! 8: extern int errno, write(), close(), isatty(); ! 9: extern char *malloc(); ! 10: extern FILE *_lastbuf; ! 11: #if !u370 ! 12: extern unsigned char *_stdbuf[]; ! 13: #endif ! 14: extern unsigned char _smbuf[][_SBFSIZ]; ! 15: ! 16: /* ! 17: * Flush buffers on exit ! 18: */ ! 19: ! 20: void ! 21: _cleanup() ! 22: { ! 23: register FILE *iop; ! 24: ! 25: for(iop = _iob; iop < _lastbuf; iop++) ! 26: (void) fclose(iop); ! 27: } ! 28: /* ! 29: fclose() will flush (output) buffers for a buffered open ! 30: FILE and then issue a system close on the _fileno. The ! 31: _base field will be reset to NULL for any but stdin and ! 32: stdout, the _ptr field will be set the same as the _base ! 33: field. The _flags and the _cnt field will be zeroed. ! 34: If buffers had been obtained via malloc(), the space will ! 35: be free()'d. In case the FILE was not open, or fflush() ! 36: or close() failed, an EOF will be returned, otherwise the ! 37: return value is 0. ! 38: */ ! 39: ! 40: int ! 41: fclose(iop) ! 42: register FILE *iop; ! 43: { ! 44: register int rtn=EOF; ! 45: ! 46: if(iop == NULL) ! 47: return(rtn); ! 48: if(iop->_flag & (_IOREAD | _IOWRT | _IORW)) { ! 49: rtn = (iop->_flag & _IONBF)? 0: fflush(iop); ! 50: if(close(fileno(iop)) < 0) { ! 51: rtn = EOF; ! 52: errno = ENOENT; ! 53: } ! 54: } ! 55: if(iop->_flag & _IOMYBUF) { ! 56: free((char*)iop->_base); ! 57: iop->_base = NULL; ! 58: } ! 59: iop->_flag = 0; ! 60: iop->_cnt = 0; ! 61: iop->_ptr = iop->_base; ! 62: return(rtn); ! 63: } ! 64: ! 65: /* ! 66: The fflush() routine must take care because of the ! 67: possibility for recursion. The calling program might ! 68: do IO in an interupt catching routine that is likely ! 69: to interupt the write() call within fflush() ! 70: */ ! 71: ! 72: int ! 73: fflush(iop) ! 74: register FILE *iop; ! 75: { ! 76: if (!(iop->_flag & _IOWRT)) { ! 77: iop->_cnt = 0; ! 78: return(0); ! 79: } ! 80: while(!(iop->_flag & _IONBF) && (iop->_flag & _IOWRT) && ! 81: (iop->_base != NULL) && (iop->_ptr > iop->_base) ) ! 82: (void) _xflsbuf(iop); ! 83: return(ferror(iop) ? EOF : 0); ! 84: } ! 85: ! 86: /* The routine _flsbuf may or may not actually flush the output buffer. If ! 87: * the file is line-buffered, the fact that iop->_cnt has run below zero ! 88: * is meaningless: it is always kept below zero so that invocations of putc ! 89: * will consistently give control to _flsbuf, even if the buffer is far from ! 90: * full. _flsbuf, on seeing the "line-buffered" flag, determines whether the ! 91: * buffer is actually full by comparing iop->_ptr to the end-of-buffer pointer ! 92: * _bufend(iop). If it is full, or if an output line is completed (with a ! 93: * newline), the buffer is flushed. (Note: the character argument to _flsbuf ! 94: * is not flushed with the current buffer if the buffer is actually full-- ! 95: * it goes into the buffer after flushing.) ! 96: */ ! 97: ! 98: int ! 99: _flsbuf(c, iop) ! 100: unsigned char c; ! 101: register FILE *iop; ! 102: { ! 103: unsigned char c1; ! 104: ! 105: do { ! 106: /* check for linebuffered with write perm, but no EOF */ ! 107: if ( (iop->_flag & (_IOLBF | _IOWRT | _IOEOF)) == (_IOLBF | _IOWRT) ) { ! 108: if ( iop->_ptr >= _bufend(iop) ) /* if buffer full, */ ! 109: break; /* exit do-while, and flush buf. */ ! 110: if ( (*iop->_ptr++ = c) != '\n' ) ! 111: return(c); ! 112: return(_xflsbuf(iop) == EOF ? EOF : c); ! 113: } ! 114: /* write out an unbuffered file, if have write perm, but no EOF */ ! 115: if ( (iop->_flag & (_IONBF | _IOWRT | _IOEOF)) == (_IONBF | _IOWRT) ) { ! 116: c1 = c; ! 117: iop->_cnt = 0; ! 118: if (write(fileno(iop), (char *) &c1, 1) == 1) ! 119: return(c); ! 120: iop->_flag |= _IOERR; ! 121: return(EOF); ! 122: } ! 123: /* The _wrtchk call is here rather than at the top of _flsbuf to re- */ ! 124: /* duce overhead for line-buffered I/O under normal circumstances. */ ! 125: ! 126: if (_WRTCHK(iop)) /* is writing legitimate? */ ! 127: return(EOF); ! 128: } while ( (iop->_flag & (_IONBF | _IOLBF)) ); ! 129: ! 130: ! 131: (void) _xflsbuf(iop); /* full buffer: flush buffer */ ! 132: (void) putc((char) c, iop); /* then put "c" in newly emptied buf */ ! 133: /* (which, because of signals, may NOT be empty) */ ! 134: return( ferror(iop) ? EOF : c); ! 135: } ! 136: ! 137: /* The function _xflsbuf writes out the current contents of the output ! 138: * buffer delimited by iop->_base and iop->_ptr. ! 139: * iop->_cnt is reset appropriately, but its value on entry to _xflsbuf ! 140: * is ignored. ! 141: * ! 142: * The following code is not strictly correct. If a signal is raised, ! 143: * invoking a signal-handler which generates output into the same buffer ! 144: * being flushed, a peculiar output sequence may result (for example, ! 145: * the output generated by the signal-handler may appear twice). At ! 146: * present no means has been found to guarantee correct behavior without ! 147: * resorting to the disabling of signals, a means considered too expensive. ! 148: * For now the code has been written with the intent of reducing the ! 149: * probability of strange effects and, when they do occur, of confining ! 150: * the damage. Except under extremely pathological circumstances, this ! 151: * code should be expected to respect buffer boundaries even in the face ! 152: * of interrupts and other signals. ! 153: */ ! 154: ! 155: int ! 156: _xflsbuf(iop) ! 157: register FILE *iop; ! 158: { ! 159: register unsigned char *base; ! 160: register int n; ! 161: ! 162: n = iop->_ptr - (base = iop->_base); ! 163: iop->_ptr = base; ! 164: iop->_cnt = (iop->_flag &(_IONBF | _IOLBF)) ? 0 : _bufsiz(iop); ! 165: _BUFSYNC(iop); ! 166: if (n > 0 && n != write(fileno(iop),(char*)base,(unsigned)n) ) { ! 167: iop->_flag |= _IOERR; ! 168: return(EOF); ! 169: } ! 170: return(0); ! 171: } ! 172: ! 173: /* The function _wrtchk checks to see whether it is legitimate to write ! 174: * to the specified device. If it is, _wrtchk sets flags in iop->_flag for ! 175: * writing, assures presence of a buffer, and returns 0. If writing is not ! 176: * legitimate, EOF is returned. ! 177: */ ! 178: ! 179: int ! 180: _wrtchk(iop) ! 181: register FILE *iop; ! 182: { ! 183: if ( (iop->_flag & (_IOWRT | _IOEOF)) != _IOWRT ) { ! 184: if (!(iop->_flag & (_IOWRT | _IORW))) ! 185: return(EOF); /* bogus call--read-only file */ ! 186: iop->_flag = iop->_flag & ~_IOEOF | _IOWRT; /* fix flags */ ! 187: } ! 188: if (iop->_base == NULL) /* this is first I/O to file--get buffer */ ! 189: _findbuf(iop); ! 190: if (iop->_ptr == iop->_base && !(iop->_flag & (_IONBF | _IOLBF)) ) { ! 191: iop->_cnt = _bufsiz(iop); /* first write since seek--set cnt */ ! 192: _BUFSYNC(iop); ! 193: } ! 194: return(0); ! 195: } ! 196: ! 197: /* ! 198: * _findbuf, called only when iop->_base == NULL, locates a predefined buffer ! 199: * or allocates a buffer using malloc. If a buffer is obtained from malloc, ! 200: * the _IOMYBUF flag is set in iop->_flag. ! 201: */ ! 202: ! 203: _findbuf(iop) ! 204: register FILE *iop; ! 205: { extern int errno; ! 206: int sverr; ! 207: register int fno = fileno(iop); /* file number */ ! 208: ! 209: /* allocate a small block for unbuffered, large for buffered */ ! 210: if (iop->_flag & _IONBF) { ! 211: _bufend(iop) = (iop->_base = _smbuf[fno]) + _SBFSIZ; ! 212: } else { ! 213: #if !u370 ! 214: if (fno < 2) /* use existing bufs for stdin, stdout */ ! 215: _bufend(iop) = (iop->_base = _stdbuf[fno]) + BUFSIZ; ! 216: else ! 217: #endif ! 218: if ((iop->_base = (unsigned char *) malloc(BUFSIZ+8)) != NULL) { ! 219: /* if we got a buffer */ ! 220: iop->_flag |= _IOMYBUF; ! 221: _bufend(iop) = iop->_base + BUFSIZ; ! 222: } else ! 223: /* if no room for buffer, use small buffer */ ! 224: _bufend(iop) = (iop->_base = _smbuf[fno]) + _SBFSIZ; ! 225: } ! 226: iop->_ptr = iop->_base; ! 227: sverr = errno; ! 228: if ( isatty(fno) && !(iop->_flag & _IONBF) ) ! 229: iop->_flag |= _IOLBF; ! 230: errno = sverr; /* isatty may set errno to ENOTTY */ ! 231: } ! 232: ! 233: /* The function _bufsync is called because interrupts and other signals ! 234: * which occur in between the decrementing of iop->_cnt and the incrementing ! 235: * of iop->_ptr, or in other contexts as well, may upset the synchronization ! 236: * of iop->_cnt and iop->ptr. If this happens, calling _bufsync should ! 237: * resynchronize the two quantities (this is not always possible). Resyn- ! 238: * chronization guarantees that putc invocations will not write beyond ! 239: * the end of the buffer. Note that signals during _bufsync can cause ! 240: * _bufsync to do the wrong thing, but usually with benign effects. ! 241: */ ! 242: ! 243: _bufsync(iop) ! 244: register FILE *iop; ! 245: { ! 246: register int spaceleft; ! 247: ! 248: if ((spaceleft = _bufend(iop) - iop->_ptr) < 0) ! 249: iop->_ptr = _bufend(iop); ! 250: else if (spaceleft < iop->_cnt) ! 251: iop->_cnt = spaceleft; ! 252: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.