8322 nl: misleading-indentation
[unleashed/tickless.git] / usr / src / lib / libbc / libc / stdio / sys5 / flsbuf.c
blob4dcc1f3f18f5ec72bd2f03babd0444093c5bffed
1 /*
2 * CDDL HEADER START
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
7 * with the License.
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]
20 * CDDL HEADER END
23 * Copyright 1989 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
27 #pragma ident "%Z%%M% %I% %E% SMI"
29 /*LINTLIBRARY*/
30 #include <stdio.h>
31 #include <errno.h>
32 #include "../common/stdiom.h"
33 #include <sys/types.h>
34 #include <sys/stat.h>
35 #include <unistd.h>
36 #include <malloc.h>
38 extern unsigned char (*_smbuf)[_SBFSIZ];
40 void _findbuf(FILE *);
41 void _bufsync(FILE *);
43 extern int fclose();
46 * Flush buffers on exit
48 void
49 _cleanup(void)
52 _fwalk(fclose);
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
64 * return value is 0.
66 int
67 fclose(FILE *iop)
69 int rtn=EOF;
71 if(iop == NULL)
72 return(rtn);
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)
77 rtn = EOF;
79 if(iop->_flag & _IOMYBUF) {
80 free((char*)iop->_base);
81 iop->_base = NULL;
83 iop->_flag = 0;
84 iop->_cnt = 0;
85 iop->_ptr = iop->_base;
86 iop->_bufsiz = 0;
87 return(rtn);
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()
97 int
98 fflush(FILE *iop)
100 if (!(iop->_flag & _IOWRT)) {
101 if ((iop->_base != NULL) && iop->_cnt) {
102 lseek(iop->_file, -(iop->_cnt), SEEK_CUR);
103 iop->_cnt = 0;
105 return(0);
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)
129 unsigned char c1;
131 do {
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' )
137 return(c);
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) ) {
142 c1 = c;
143 iop->_cnt = 0;
144 if (write(fileno(iop), (char *) &c1, 1) == 1)
145 return(c);
146 iop->_flag |= _IOERR;
147 return(EOF);
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? */
153 return(EOF);
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
167 * is ignored.
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.
183 _xflsbuf(FILE *iop)
185 unsigned char *base;
186 int n;
188 n = iop->_ptr - (base = iop->_base);
189 iop->_ptr = base;
190 iop->_cnt = (iop->_flag &(_IONBF | _IOLBF)) ? 0 : iop->_bufsiz;
191 _BUFSYNC(iop);
192 if (n > 0 && n != write(fileno(iop),(char*)base,(unsigned)n) ) {
193 iop->_flag |= _IOERR;
194 return(EOF);
196 return(0);
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.
207 _wrtchk(FILE *iop)
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 */
217 _findbuf(iop);
218 if (iop->_ptr == iop->_base && !(iop->_flag & (_IONBF | _IOLBF)) ) {
219 iop->_cnt = iop->_bufsiz; /* first write since seek--set cnt */
220 _BUFSYNC(iop);
222 return(0);
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.
231 void
232 _findbuf(FILE *iop)
234 int fno = fileno(iop); /* file number */
235 struct stat statb;
236 int size;
238 /* allocate a small block for unbuffered, large for buffered */
239 if (iop->_flag & _IONBF) {
240 iop->_base = _smbuf[fno];
241 iop->_bufsiz = _SBFSIZ;
242 } else {
244 if ( isatty(fno) ) {
245 iop->_flag |= _IOLBF;
246 size = 128;
247 } else {
248 if (fstat(fno, &statb) < 0)
249 size = BUFSIZ;
250 else {
251 if ((size = statb.st_blksize) <= 0)
252 size = BUFSIZ;
255 if ((iop->_base = (unsigned char *) malloc(size+8)) != NULL) {
256 /* if we got a buffer */
257 iop->_flag |= _IOMYBUF;
258 iop->_bufsiz = size;
259 } else {
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.
281 void
282 _bufsync(FILE *iop)
284 int spaceleft;
285 unsigned char *bufend = iop->_base + iop->_bufsiz;
287 if ((spaceleft = bufend - iop->_ptr) < 0)
288 iop->_ptr = bufend;
289 else if (spaceleft < iop->_cnt)
290 iop->_cnt = spaceleft;