4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License"). You may not use this file except in compliance
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
23 * Copyright 1989 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
27 #pragma ident "%Z%%M% %I% %E% SMI"
32 #include "../common/stdiom.h"
33 #include <sys/types.h>
38 extern unsigned char (*_smbuf
)[_SBFSIZ
];
40 void _findbuf(FILE *);
41 void _bufsync(FILE *);
46 * Flush buffers on exit
56 * fclose() will flush (output) buffers for a buffered open
57 * FILE and then issue a system close on the _fileno. The
58 * _base field will be reset to NULL for any but stdin and
59 * stdout, the _ptr field will be set the same as the _base
60 * field. The _flags and the _cnt field will be zeroed.
61 * If buffers had been obtained via malloc(), the space will
62 * be free()'d. In case the FILE was not open, or fflush()
63 * or close() failed, an EOF will be returned, otherwise the
73 if(iop
->_flag
& (_IOREAD
| _IOWRT
| _IORW
)
74 && (iop
->_flag
& _IOSTRG
) == 0) {
75 rtn
= (iop
->_flag
& _IONBF
)? 0: fflush(iop
);
76 if(close(fileno(iop
)) < 0)
79 if(iop
->_flag
& _IOMYBUF
) {
80 free((char*)iop
->_base
);
85 iop
->_ptr
= iop
->_base
;
91 * The fflush() routine must take care because of the
92 * possibility for recursion. The calling program might
93 * do IO in an interupt catching routine that is likely
94 * to interupt the write() call within fflush()
100 if (!(iop
->_flag
& _IOWRT
)) {
101 if ((iop
->_base
!= NULL
) && iop
->_cnt
) {
102 lseek(iop
->_file
, -(iop
->_cnt
), SEEK_CUR
);
107 while(!(iop
->_flag
& _IONBF
) && (iop
->_flag
& _IOWRT
) &&
108 (iop
->_base
!= NULL
) && (iop
->_ptr
> iop
->_base
) )
109 (void) _xflsbuf(iop
);
110 return(ferror(iop
) ? EOF
: 0);
114 * The routine _flsbuf may or may not actually flush the output buffer. If
115 * the file is line-buffered, the fact that iop->_cnt has run below zero
116 * is meaningless: it is always kept below zero so that invocations of putc
117 * will consistently give control to _flsbuf, even if the buffer is far from
118 * full. _flsbuf, on seeing the "line-buffered" flag, determines whether the
119 * buffer is actually full by comparing iop->_ptr to the end of the buffer
120 * iop->_base + iop->_bufsiz. If it is full, or if an output line is
121 * completed (with a newline), the buffer is flushed. (Note: the character
122 * argument to _flsbuf is not flushed with the current buffer if the buffer
123 * is actually full -- it goes into the buffer after flushing.)
127 _flsbuf(unsigned char c
, FILE *iop
)
132 /* check for linebuffered with write perm, but no EOF */
133 if ( (iop
->_flag
& (_IOLBF
| _IOWRT
| _IOEOF
)) == (_IOLBF
| _IOWRT
) ) {
134 if ( iop
->_ptr
>= iop
->_base
+ iop
->_bufsiz
) /* if buffer full, */
135 break; /* exit do-while, and flush buf. */
136 if ( (*iop
->_ptr
++ = c
) != '\n' )
138 return(_xflsbuf(iop
) == EOF
? EOF
: c
);
140 /* write out an unbuffered file, if have write perm, but no EOF */
141 if ( (iop
->_flag
& (_IONBF
| _IOWRT
| _IOEOF
)) == (_IONBF
| _IOWRT
) ) {
144 if (write(fileno(iop
), (char *) &c1
, 1) == 1)
146 iop
->_flag
|= _IOERR
;
149 /* The _wrtchk call is here rather than at the top of _flsbuf to re- */
150 /* duce overhead for line-buffered I/O under normal circumstances. */
152 if (_WRTCHK(iop
)) /* is writing legitimate? */
154 } while ( (iop
->_flag
& (_IONBF
| _IOLBF
)) );
157 (void) _xflsbuf(iop
); /* full buffer: flush buffer */
158 (void) putc((char) c
, iop
); /* then put "c" in newly emptied buf */
159 /* (which, because of signals, may NOT be empty) */
160 return( ferror(iop
) ? EOF
: c
);
164 * The function _xflsbuf writes out the current contents of the output
165 * buffer delimited by iop->_base and iop->_ptr.
166 * iop->_cnt is reset appropriately, but its value on entry to _xflsbuf
169 * The following code is not strictly correct. If a signal is raised,
170 * invoking a signal-handler which generates output into the same buffer
171 * being flushed, a peculiar output sequence may result (for example,
172 * the output generated by the signal-handler may appear twice). At
173 * present no means has been found to guarantee correct behavior without
174 * resorting to the disabling of signals, a means considered too expensive.
175 * For now the code has been written with the intent of reducing the
176 * probability of strange effects and, when they do occur, of confining
177 * the damage. Except under extremely pathological circumstances, this
178 * code should be expected to respect buffer boundaries even in the face
179 * of interrupts and other signals.
188 n
= iop
->_ptr
- (base
= iop
->_base
);
190 iop
->_cnt
= (iop
->_flag
&(_IONBF
| _IOLBF
)) ? 0 : iop
->_bufsiz
;
192 if (n
> 0 && n
!= write(fileno(iop
),(char*)base
,(unsigned)n
) ) {
193 iop
->_flag
|= _IOERR
;
200 * The function _wrtchk checks to see whether it is legitimate to write
201 * to the specified device. If it is, _wrtchk sets flags in iop->_flag for
202 * writing, assures presence of a buffer, and returns 0. If writing is not
203 * legitimate, EOF is returned.
209 if ( (iop
->_flag
& (_IOWRT
| _IOEOF
)) != _IOWRT
) {
210 if (!(iop
->_flag
& (_IOWRT
| _IORW
)))
211 return(EOF
); /* bogus call--read-only file */
212 iop
->_flag
= iop
->_flag
& ~_IOEOF
| _IOWRT
; /* fix flags */
214 if (iop
->_flag
& _IOSTRG
)
215 return(0); /* not our business to monkey with buffers or counts */
216 if (iop
->_base
== NULL
) /* this is first I/O to file--get buffer */
218 if (iop
->_ptr
== iop
->_base
&& !(iop
->_flag
& (_IONBF
| _IOLBF
)) ) {
219 iop
->_cnt
= iop
->_bufsiz
; /* first write since seek--set cnt */
226 * _findbuf, called only when iop->_base == NULL, locates a predefined buffer
227 * or allocates a buffer using malloc. If a buffer is obtained from malloc,
228 * the _IOMYBUF flag is set in iop->_flag.
234 int fno
= fileno(iop
); /* file number */
238 /* allocate a small block for unbuffered, large for buffered */
239 if (iop
->_flag
& _IONBF
) {
240 iop
->_base
= _smbuf
[fno
];
241 iop
->_bufsiz
= _SBFSIZ
;
245 iop
->_flag
|= _IOLBF
;
248 if (fstat(fno
, &statb
) < 0)
251 if ((size
= statb
.st_blksize
) <= 0)
255 if ((iop
->_base
= (unsigned char *) malloc(size
+8)) != NULL
) {
256 /* if we got a buffer */
257 iop
->_flag
|= _IOMYBUF
;
260 /* if no room for buffer, use small buffer */
261 iop
->_base
= _smbuf
[fno
];
262 iop
->_bufsiz
= _SBFSIZ
;
263 iop
->_flag
&= ~_IOLBF
;
264 iop
->_flag
|= _IONBF
;
267 iop
->_ptr
= iop
->_base
;
271 * The function _bufsync is called because interrupts and other signals
272 * which occur in between the decrementing of iop->_cnt and the incrementing
273 * of iop->_ptr, or in other contexts as well, may upset the synchronization
274 * of iop->_cnt and iop->ptr. If this happens, calling _bufsync should
275 * resynchronize the two quantities (this is not always possible). Resyn-
276 * chronization guarantees that putc invocations will not write beyond
277 * the end of the buffer. Note that signals during _bufsync can cause
278 * _bufsync to do the wrong thing, but usually with benign effects.
285 unsigned char *bufend
= iop
->_base
+ iop
->_bufsiz
;
287 if ((spaceleft
= bufend
- iop
->_ptr
) < 0)
289 else if (spaceleft
< iop
->_cnt
)
290 iop
->_cnt
= spaceleft
;