/* ioctl.c (emx+gcc) -- Copyright (c) 1990-1996 by Eberhard Mattes */

#include <stdlib.h>
#include <stdarg.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/termio.h>
#include <sys/ioctl.h>
#include <emx/io.h>
#include <emx/syscalls.h>

/* Including the socket header files would be overkill. */

#define FIONBIO         0x667e

int _ioctl (int handle, int request, ...)
{
  va_list va;
  int rc, saved_errno, arg, *int_ptr, *pflags, *pla;
  const struct termio *tp;

  if ((pflags = _fd_flags (handle)) == NULL)
    {
      errno = EBADF;
      return -1;
    }
  saved_errno = errno; errno = 0;
  va_start (va, request);
  arg = va_arg (va, int);
  va_end (va);
  rc = __ioctl2 (handle, request, arg);
  if (rc >= 0 && errno == 0)
    switch (request)
      {
      case TCSETAF:
      case TCSETAW:
      case TCSETA:
        va_start (va, request);
        tp = va_arg (va, const struct termio *);
        va_end (va);
        if (tp->c_lflag & IDEFAULT)
          *pflags &= ~F_TERMIO;
        else
          *pflags |= F_TERMIO;
        break;

      case _TCSANOW:
      case _TCSADRAIN:
      case _TCSAFLUSH:
        *pflags |= F_TERMIO;
        break;

      case FIONREAD:
        if ((pla = _fd_lookahead (handle)) != NULL && *pla >= 0)
          {
            va_start (va, request);
            int_ptr = va_arg (va, int *);
            va_end (va);
            ++(*int_ptr);
          }
        break;

      case FIONBIO:
        va_start (va, request);
        int_ptr = va_arg (va, int *);
        va_end (va);
        if (*int_ptr)
          *pflags |= O_NDELAY;
        else
          *pflags &= ~O_NDELAY;
        break;
      }
  if (errno == 0)
    errno = saved_errno;
  return rc;
}
