#ifdef __MSDOS__

#include <errno.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/exceptn.h>
#include <process.h>
#include <limits.h>
#include <fcntl.h>

#include "shell.h"
#include "dosutil.h"

int bash_spawnve(char *path, char **args, char **envp)
{
  int status;
  int fd;
  static char oldcwd[PATH_MAX];
  int maybe_shell_script;
  int cmd_sample_len;
  static char cmd_sample[2];
  int errno_save;
  int sample_file = 1;
  int path_len;
  int *selectors;
  int old_enable, old_ctrl_c;
  
  path_len = strlen(path);
  if (path_len >= 4 && path[path_len - 4] == '.'
      && stricmp (path + path_len - 3, "bat") == 0)
    sample_file = 0;

  /* If we have a plain text file, just punt and let Bash handle it.  */
  if (sample_file)
    {
      fd = open (path, O_RDONLY);
      if (fd >= 0)
        {
          cmd_sample_len = read (fd, cmd_sample, sizeof cmd_sample);
          close (fd);
          if (cmd_sample_len < 0)
            return -1;

          if (cmd_sample_len < sizeof cmd_sample)
            return 0;

          if (!check_binary_file (cmd_sample, cmd_sample_len)
              && !(*cmd_sample == '#' && cmd_sample[1] == '!'))
            {
              errno = ENOEXEC;
              return -1;
            }
        }
    }

  /* keep cwd on exec */
  getcwd (oldcwd, sizeof oldcwd);

  /* Expand 'path'.  */
  if (dosutil_is_encoded_drivename (path))
    path = dosutil_decode_drivename (path);

  /* disable interrupt */
  old_enable = __dpmi_get_and_disable_virtual_interrupt_state ();
  old_ctrl_c = __djgpp_set_ctrl_c (0);

  /* check empty dpmi selectors */
  selectors = dosutil_check_dpmi_selectors ();

  __djgpp_exception_toggle();

  errno = 0;

  /* Run child process. If the filename doesn't have a period, add one
     to prevent __dos_find_on_path from finding a different file than
     intended.  */
  status = spawnve (P_WAIT, path, args, envp);

  /* make response file if E2BIG */
  if (errno == E2BIG && args != NULL && args[1] != NULL && args[1][0] != '@')
    {
      char *tname;

      tname = dosutil_make_response_file (args);
      if (tname != NULL)
	  {
	    char *xargs[3];

	    xargs[0] = args[0];
	    xargs[1] = xmalloc (1 + strlen (tname) + 1);
	    xargs[1][0] = '@';
	    strcpy (&xargs[1][1], tname);
	    xargs[2] = NULL;

	    errno = 0;

	    /* try again */
            status = spawnve (P_WAIT, path, xargs, envp);

	    /* cleanup */
	    free (xargs[1]);
	    remove (tname);
	    free (tname);
	  }
    }

  /* disable interrupt */
  __dpmi_get_and_disable_virtual_interrupt_state ();

  __djgpp_exception_toggle();

  /* free discarded dpmi selectors */
  dosutil_free_dpmi_selectors (selectors);

  /* Reset standard input */
  dosutil_reset_console();

  /* enable interrupt */
  __djgpp_set_ctrl_c (old_ctrl_c);
  __dpmi_get_and_enable_virtual_interrupt_state ();

  errno_save = errno;
  if (status >= 0)
    chdir (oldcwd);
  errno = errno_save;

  return status;
}

#endif

