/* dupexec.c (emx+gcc) */

/* Test remapping file handles for running a DOS program. */

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
#include <process.h>


static FILE *output;
static int use_spawn;
static int use_fcntl;
static int inherit;

static void redir_input (int fd_target, const char *fname)
{
  int fd_file, mode;

  mode = O_RDONLY;
  if (!inherit && !use_fcntl)
    mode |= O_NOINHERIT;
  fd_file = open (fname, mode);
  if (fd_file < 0)
    {
      fprintf (output, "%s: %s\n", fname, strerror (errno));
      exit (2);
    }
  if (dup2 (fd_file, fd_target) < 0)
    {
      fprintf (output, "dup2(): %s\n", strerror (errno));
      exit (2);
    }
  if (!inherit && use_fcntl && fcntl (fd_file, F_SETFD, FD_CLOEXEC) < 0)
    {
      fprintf (output, "fcntl(): %s\n", strerror (errno));
      exit (2);
    }
}


static void one_line (int fd)
{
  int nread;
  char buf[512], *p;

  if (isatty (fd))
    fprintf (output, "%d: is a TTY\n", fd);
  else
    {
      lseek (fd, 0L, SEEK_SET);
      nread = read (fd, buf, sizeof (buf));
      if (nread > 0)
        {
          p = memchr (buf, '\n', nread);
          if (p != NULL)
            nread = p - buf;
          fprintf (output, "%d: %.*s\n", fd, nread, buf);
        }
    }
}


static void child (void)
{
  int fd, max_fd;

  max_fd = sysconf (_SC_OPEN_MAX);
  fprintf (output, "Child:\n");
  for (fd = 0; fd < max_fd; ++fd)
    one_line (fd);
}


static void show (void)
{
  fprintf (output, "Parent:\n");
  one_line (0);
  one_line (1);
  one_line (2);
}


static void parent (void)
{
  redir_input (0, "dupexec.t1");
  /* redir_input (1, "dupexec.t2"); */
  redir_input (2, "dupexec.t3");
  show ();
  fflush (stdout);
  if (use_spawn)
    {
      if (spawnl (P_WAIT, "dupexec.exe",
                  "dupexec.exe", "-child", (char *)0) < 0)
        fprintf (output, "spawnl(): %s\n", strerror (errno));
    }
  else
    {
      if (system ("dupexec -child") < 0)
        fprintf (output, "system(): %s\n", strerror (errno));
   }
  show ();
}


static void usage (void)
{
  puts ("Usage: dupexec [-s] [-i] [-f]");
  exit (1);
}


int main (int argc, char *argv[])
{
  int i;

  output = fopen ("con", "w");
  if (output == NULL)
    exit (2);
  setvbuf (output, NULL, _IONBF, 0);
  if (argc == 2 && strcmp (argv[1], "-child") == 0)
    child ();
  else
    {
      for (i = 1; i < argc; ++i)
        if (strcmp (argv[i], "-s") == 0)
          use_spawn = 1;
        else if (strcmp (argv[i], "-i") == 0)
          inherit = 1;
        else if (strcmp (argv[i], "-f") == 0)
          use_fcntl = 1;
        else
          usage ();
      parent ();
    }
  return 0;
}
