154 lines
		
	
	
	
		
			2.8 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			154 lines
		
	
	
	
		
			2.8 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /*
 | |
|  * flushbuf.c - flush a buffer
 | |
|  */
 | |
| /* $Id$ */
 | |
| 
 | |
| #include <stdlib.h>
 | |
| #include <stdio.h>
 | |
| #include <unistd.h>
 | |
| #include "loc_incl.h"
 | |
| 
 | |
| #if ACKCONF_WANT_STDIO
 | |
| 
 | |
| 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)
 | |
| {
 | |
| 	__register_stdio_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;
 | |
| }
 | |
| 
 | |
| #endif
 |