
/*
  Recovered from a part of a `More' output captured in some file on DH3:.
  The date on this file was 910814 in a `ls' command before it.  The part
  of the file that this was taken from starts at key 169882.  I don't know
  the name or date for the file was capture file.  There were files as new
  as 910915 in the listing. */

/*
 * Libraries and headers for PDC release 3.3 (C) 1989 Lionel Hummel.
 * PDC Software Distribution (C) 1989 Lionel Hummel and Paul Petersen.
 * PDC I/O Library (C) 1987 by J.A. Lydiatt.
 *
 * This code is freely redistributable upon the conditions that this
 * notice remains intact and that modified versions of this file not
 * be included as part of the PDC Software Distribution without the
 * express consent of the copyright holders.  No warrantee of any
 * kind is provided with this code.  For further information, contact:
 *
 *  PDC Software Distribution    Internet:                     BIX:
 *  P.O. Box 4006             or hummel@cs.uiuc.edu            lhummel
 *  Urbana, IL  61801-8801       petersen@uicsrd.csrd.uiuc.edu
 */

/*  fopen.c - assigns buffered I/O streams to files
 *
 *  fopen	- opens the given file name for buffered I/O
 *  freopen	- changes the mode on a buffered I/O stream
 *  fclose 	- close a stdio stream
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <errno.h>

int open ();
int close ();
int _doflush ();
FILE *addStream (void);

FILE *
freopen (const char *name, const char *mode, FILE *fp)
{
  int fd;
  int direction, flags;

  fclose (fp);

  /*
   * Decide DIRECTION and FLAGS from the MODE string.
   * Ignore a `b' in the MODE string.
   */
  switch (mode[0])
    {
    case 'r':
      direction = O_RDONLY;
      flags = 0;
      break;
    case 'w':
      direction = O_WRONLY;
      flags = O_CREAT | O_TRUNC;
      break;
    case 'a':
      direction = O_WRONLY;
      flags = O_CREAT | O_APPEND;
      break;
    case 'x':
      direction = O_WRONLY;
      flags = O_CREAT | O_EXCL;
      break;
    default:
      errno = EINVAL;
      return NULL;
    }
  if (mode[1] && (mode[1] == '+' || (mode[2] && mode[2] == '+')))
    direction = O_RDWR;

  /* Open it again with the correct attributes. */
  fd = open (name, direction | flags);
  if (fd == -1)
    return NULL;

  fp->_fileunit = fd;
  fp->_fileflag = _FILEACTIVE;

  return fp;
}

FILE *
fopen (const char *name, const char *mode)
{
  FILE *fp;

  fp = addStream ();
  if (!fp)
    return NULL;

  return freopen (name, mode, fp);
}

int 
fclose (FILE *fp)
{
  int result;

  result = 0;
  if (!fp)
    return -1;

  if (fp->_fileflag)
    {
      if (fp->_fileflag & _FILEISDIRTY)
	result = _doflush (fp, -1);
      result |= close ((int) fp->_fileunit);
      if (fp->_fileflag & _FILEISDYNA)
	free (fp->_filebufp);
    }

  if (fp->_tempname != NULL)
    remove (fp->_tempname);

  fp->_filebufp = NULL;
  fp->_filecpos = NULL;
  fp->_fileend = NULL;
  fp->_fileflag = 0;
  fp->_tempname = NULL;

  return result;
}
