|
|
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.