#include <unistd.h>
#include <stdio.h>
#include <malloc.h>
#include "file2.h"
#include "internal.h"

#include <trace.h>
/****************************************************************************
 *
 * Function:       _xflsbuf
 *
 * Description:    Flush the output character and the pending buffer
 *
 * Input:          ch      - Output character at the time of overflow
 *                 stream  - Pointer to the file table to be flushed.
 *
 * Output:         The results of the flush operation
 *                 0 : success
 *                 EOF : error
 */

int _xflsbuf (int ch, FILE *stream)
    {
    int   charcount;
    int   written;
    FILE2 *stream2 = file2p (stream);
    int   fh       = fileno (stream);
    int   nAnswer  = -1;
    FUNC_ENTRY ("_xflsbuf");
/*
 *  Validate the file status
 */
    if (inuse(stream))
        {
	if ((stream->_flag & _IOSTRG) != 0)
	    {
	    stream->_flag |= _IOERR;
	    }
/*
 *  If the file was last read then it is not legal to write to the buffer
 */
	else
	    {
	    if (stream->_flag & _IOREAD)
	        {
		stream->_flag |= _IOERR;
	        }
/*
 *  Indicate the file is in write mode and clear the EOF condition.
 */
	    else
	        {
		stream->_flag |= _IOWRT;
		stream->_flag &= ~_IOEOF;
		written = charcount = stream->_cnt = 0;
/*
 *  Get a buffer for the output stream if necessary. Do special processing
 *  for the stdout and stderr files. Attempt to use the local buffers if
 *  possible.
 */
		if (!anybuf(stream))
		    {
		    _libc__cleanup = _cleanup;

		    if (stream == stdout || stream == stderr)
		        {
			if (!isatty (fh))
			    {
/*
 *  Set the appropriate pointer to the file buffer
 */
			    if (stream == stdout)
			        {
			        stream->_base = _bufout;
			        }
                            else
			        {
                                stream->_base = _buferr;
			        }
/*
 *  Fill the remainder of the information for the file table.
 */
                            stream->_ptr     = stream->_base;
			    stream2->_bufsiz = BUFSIZ;
			    stream2->_flag2  = _IOYOURBUF;
			    }
		        }
/*
 *   This is not stdout / stderr. Attempt to allocate a buffer for this
 *   stream.
 */
                    else
		        {
		        _getbuf(stream);
			}
		    }
/*
 *  If the file is fully buffered then update the information for the read
 */
		if (bigbuf(stream))
		    {
		    charcount    = stream->_ptr - stream->_base;
		    stream->_ptr = stream->_base + 1;
		    stream->_cnt = stream2->_bufsiz - 1;
/*
 *  Attempt to write the data to the output file. If there is nothing to
 *  write then seek to the end of the current file.
 */		    
		    if (charcount > 0)
		        {
			written = write(fh, stream->_base, charcount);
		        }
		    else
		        {
			lseek (fh, 0L, SEEK_END);
		        }
		    *stream->_base = ch;
		    }
/*
 *  The file is not fully buffered. Perform a single character output
 *  or nor buffering.
 */
		else
		    {
		    charcount = 1;
		    written   = write (fh, &ch, charcount);
		    }
/*
 *  Set the write error if indicated or the output is the last character
 *  written to indicate success.
 */
		if (written != charcount)
		    {
		    stream->_flag |= _IOERR;
		    }
		else
		    {
		    nAnswer = ch & 0xff;
		    }
	        }
	    }
        }
/*
 *  Return the status to the caller.
 */
    FUNC_EXIT ("_xflsbuf");
    return (nAnswer);
    }

#ifdef ELF_LIBRARY
__asm__(".globl _xflsbuf; _xflsbuf = __flsbuf");
__asm__(".weak _flsbuf; _flsbuf = __flsbuf");
#endif
