#include <unistd.h>
#include <stdio.h>
#include <fcntl.h>
#include "file2.h"
#include "internal.h"
#include <errno.h>

#include <trace.h>
/***************************************************************************
 *
 * Function:   _openfile
 *
 * Description:
 *     parse the input string for the file mode.
 *
 * Input:
 *      filename    - Name of the file to be opened
 *      mode        - file open mode
 *      stream      - Pointer to the file stream to be used for the file
 *
 * Output:
 *      A pointer to the file table if successful or NULL if an error occured.
 */

FILE *_openfile (const char *filename, const char *mode, FILE *stream)
    {
    int   filedes;
    int   modeflag    = -1;
    char  streamflag  = 0;
    FILE2 *stream2    = NULL;
    FILE  *strmResult = NULL;
    FUNC_ENTRY ("_openfile");
/*
 *  Parse the user's specification and set the mode flags as needed
 *  The first character may be r, w, or a to indicate the access type desired.
 */
    switch (*mode)
        {
    case 'r':
        modeflag   = O_RDONLY;
        streamflag = _IOREAD;
        break;

    case 'w':
        modeflag   = O_WRONLY | O_CREAT | O_TRUNC;
        streamflag = _IOWRT;
        break;

    case 'a':
        modeflag   = O_WRONLY | O_CREAT | O_APPEND;
        streamflag = _IOWRT;
        break;

    default:
        break;
        }
/*
 *  Ignore the trailing "t" character. ANSI says that this may indicate
 *  that the file is a "text" file. UNIX has no special flag for this
 *  purpose.  Do sake thing with 'b'.
 */
    ++mode;
    while (modeflag != -1)
        {
	if (*mode == 't')
	    {
	    ++mode;
	    continue;
	    }
	/* Same for 'b' */
	if (*mode == 'b')
	    {
	    ++mode;
	    continue;
	    }
/*
 *  Look for the '+' character to indicate that the file is read/write
 */
	if (*mode == '+')
	    {
	    if (streamflag == _IORW)
	        {
		mode = 0;
		break;
		}

	    modeflag  |= O_RDWR;
	    modeflag  &= ~(O_RDONLY | O_WRONLY);
	    streamflag = _IORW;
	    ++mode;
	    continue;
	    }
/*
 *  The only legal condition at this point is the end of the string.
 */
	if (*mode == '\0')
	    {
	    break;
	    }
	modeflag = -1;
        }
/*
 *  At this point, it is acceptable to ensure that the mode flag has been
 *  fully processed.
 */
    if (modeflag != -1)
        {
/*
 *  Attempt to open the file. If successful, then filedes will be >= 0.
 *  Ensure that the file number for the open is within legal range since
 *  it is used to index the FILE2 table.
 */
	filedes = open (filename, modeflag, 0666);
	if (filedes >= _NFILE)
	    {
	    close (filedes);
	    errno   = EMFILE;
	    filedes = -1;
	    }
/*
 *  Construct the file tables based upon the open request.
 */
	if (filedes >= 0)
	    {
	    stream->_flag     = streamflag;
	    stream->_cnt      = 0;
	    stream->_base     =
            stream->_ptr      = NULL;
	    stream->_file     = filedes;
	    strmResult        = stream;
/*
 *   Once the file number has been determined then file2p should work.
 */
	    stream2           = file2p (stream);
	    stream2->_flag2   = 0;
	    stream2->_ttyflag = 0;
	    _cflush++;
	    }
        }
/*
 *  Return the output stream pointer or NULL if an error occured
 */
    FUNC_ENTRY ("_openfile");
    return (strmResult);
    }
