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

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

/* See app/iodata.c. */

extern int _nfiles;
extern int _files[];
extern int _lookahead[];

#ifdef ORIGIN_EMX
extern int __crtinit1__;
extern void __ctordtorInit1 (int *ptr);
#else
typedef void (*FUNC)(void);
extern FUNC _CRT_INIT_START[];
extern FUNC _CRT_INIT_END[];
#endif

/* The version of this libc. */
static const char _libc_version[] =
  " libc for emx 0.9c";

/* Display this warning if emx.dll or emx.exe is out of date. */
static const char _version_warning[] =
  "WARNING: emx 0.9c or later required\r\n";


static void init_files (void);


/* Initialize the C run-time library.  This function is called from
   crt0.s. */

void _startup (void)
{
  static int startup_flag;

  /* Protect against multiple calls (for instance, by _CRT_init() in a
     _DLL_InitTerm() and by the application program's startup code). */

  if (startup_flag)
    return;
  startup_flag = 1;

  /* Print a warning message on handle 2 (stderr) if emx.dll or
     emx.exe is out of date. */

  if (_emx_vcmp < 0x302e3963)   /* 0.9c */
    __write (2, _version_warning, sizeof (_version_warning) - 1);

  /* Initialize the file handles. */

  init_files ();

  /* Initialize streams etc. if required. */

#ifdef ORIGIN_EMX
  __ctordtorInit1 (&__crtinit1__);
#else
  {
    int i;

    for (i = 0; i < _CRT_INIT_END - _CRT_INIT_START; i++)
      _CRT_INIT_START[i]();
  }
#endif

  /* ANSI X3.159-1989, 4.1.3: "The value of errno is zero at program
     startup..."

     The above code usually sets errno to EBADF, therefore we reset
     errno to zero before calling main(). */

  errno = 0;
}


/* Initialize the file handles. */

static void init_files (void)
{
  int i, ht, fl;

  for (i = 0; i < _nfiles; ++i)
    {
      _files[i] = 0;
      _lookahead[i] = -1;

      /* Get the handle type.  If this fails, the handle is not open. */

      if (i < _io_ninherit && __ioctl2 (i, FGETHTYPE, (int)&ht) == 0)
        {
          /* init_streams() depends on _files[] being non-zero for
             open file handles.  When omitting O_TEXT, don't forget to
             set another bit. */

          _files[i] |= O_TEXT;
          if (HT_ISDEV (ht))
            _files[i] |= F_DEV;
          if (ht == HT_UPIPE || ht == HT_NPIPE)
            {
              _files[i] |= F_PIPE;
              fl = __fcntl (i, F_GETFL, 0);
              if (fl >= 0)
                _files[i] |= fl & O_NDELAY;
            }
          switch (i)
            {
            case 0:
              _files[0] |= O_RDONLY;
              break;

            case 1:
            case 2:
              _files[i] |= O_WRONLY;
              break;

            default:
              /* All other handles can be read and written. */
              _files[i] |= O_RDWR;
              break;
            }
        }
    }
}
