/* * flushbuf.c - flush a buffer */ /* $Id$ */ #include #include #include #include "loc_incl.h" extern void (*_clean)(void); static int do_write(int d, char* buf, int nbytes) { int c; /* POSIX actually allows write() to return a positive value less than nbytes, so loop ... */ while ((c = write(d, buf, nbytes)) > 0 && c < nbytes) { nbytes -= c; buf += c; } return c > 0; } int __flushbuf(int c, FILE* stream) { _clean = __cleanup; if (fileno(stream) < 0) return EOF; if (!io_testflag(stream, _IOWRITE)) return EOF; if (io_testflag(stream, _IOREADING) && !feof(stream)) return EOF; stream->_flags &= ~_IOREADING; stream->_flags |= _IOWRITING; if (!io_testflag(stream, _IONBF)) { if (!stream->_buf) { if (stream == stdout && isatty(fileno(stdout))) { if (!(stream->_buf = (unsigned char*)malloc(BUFSIZ))) { stream->_flags |= _IONBF; } else { stream->_flags |= _IOLBF | _IOMYBUF; stream->_bufsiz = BUFSIZ; stream->_count = -1; } } else { if (!(stream->_buf = (unsigned char*)malloc(BUFSIZ))) { stream->_flags |= _IONBF; } else { stream->_flags |= _IOMYBUF; stream->_bufsiz = BUFSIZ; if (!io_testflag(stream, _IOLBF)) stream->_count = BUFSIZ - 1; else stream->_count = -1; } } stream->_ptr = stream->_buf; } } if (io_testflag(stream, _IONBF)) { char c1 = c; stream->_count = 0; if (io_testflag(stream, _IOAPPEND)) { if (lseek(fileno(stream), 0L, SEEK_END) == -1) { stream->_flags |= _IOERR; return EOF; } } if (write(fileno(stream), &c1, 1) != 1) { stream->_flags |= _IOERR; return EOF; } return (unsigned char)c; } else if (io_testflag(stream, _IOLBF)) { *stream->_ptr++ = c; /* stream->_count has been updated in putc macro. */ if (c == '\n' || stream->_count == -stream->_bufsiz) { int count = -stream->_count; stream->_ptr = stream->_buf; stream->_count = 0; if (io_testflag(stream, _IOAPPEND)) { if (lseek(fileno(stream), 0L, SEEK_END) == -1) { stream->_flags |= _IOERR; return EOF; } } if (!do_write(fileno(stream), (char*)stream->_buf, count)) { stream->_flags |= _IOERR; return EOF; } } } else { int count = stream->_ptr - stream->_buf; stream->_count = stream->_bufsiz - 1; stream->_ptr = stream->_buf + 1; if (count > 0) { if (io_testflag(stream, _IOAPPEND)) { if (lseek(fileno(stream), 0L, SEEK_END) == -1) { stream->_flags |= _IOERR; return EOF; } } if (!do_write(fileno(stream), (char*)stream->_buf, count)) { *(stream->_buf) = c; stream->_flags |= _IOERR; return EOF; } } *(stream->_buf) = c; } return (unsigned char)c; }