// natPosixProcess.cc - Native side of POSIX process code.

/* Copyright (C) 1998, 1999, 2000  Free Software Foundation

   This file is part of libgcj.

This software is copyrighted work licensed under the terms of the
Libgcj License.  Please consult the file "LIBGCJ_LICENSE" for
details.  */

#include <config.h>

#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#include <errno.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <signal.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>

#include <gcj/cni.h>
#include <jvm.h>

#include <java/lang/ConcreteProcess.h>
#include <java/lang/IllegalThreadStateException.h>
#include <java/lang/InterruptedException.h>
#include <java/lang/NullPointerException.h>
#include <java/lang/Thread.h>
#include <java/io/FileDescriptor.h>
#include <java/io/FileInputStream.h>
#include <java/io/FileOutputStream.h>
#include <java/io/IOException.h>
#include <java/lang/OutOfMemoryError.h>

extern char **environ;

void
java::lang::ConcreteProcess::destroy (void)
{
  if (! hasExited)
    {
      // Really kill it.
      kill ((pid_t) pid, SIGKILL);
    }
}

jint
java::lang::ConcreteProcess::waitFor (void)
{
  if (! hasExited)
    {
      int wstat;
      int r = waitpid ((pid_t) pid, &wstat, 0);

      if (r == -1)
        {
	  if (java::lang::Thread::interrupted())
	    throw new InterruptedException (JvNewStringLatin1 (strerror
	      (errno)));
	}
      else
	{
	  hasExited = true;

	  if (WIFEXITED (wstat))
	    status = WEXITSTATUS (wstat);
	  else
	    status = -1;
	}
    }

  return status;
}

static char *
new_string (jstring string)
{
  jsize s = _Jv_GetStringUTFLength (string);
  char *buf = (char *) _Jv_Malloc (s + 1);
  _Jv_GetStringUTFRegion (string, 0, s, buf);
  buf[s] = '\0';
  return buf;
}

static void
cleanup (char **args, char **env)
{
  if (args != NULL)
    {
      for (int i = 0; args[i] != NULL; ++i)
	_Jv_Free (args[i]);
      _Jv_Free (args);
    }
  if (env != NULL)
    {
      for (int i = 0; env[i] != NULL; ++i)
	_Jv_Free (env[i]);
      _Jv_Free (env);
    }
}

static void
fail (int error_value, char **args, char **env,
      int *one = NULL, int *two = NULL,
      int *three = NULL, int *four = NULL,
      java::lang::Throwable *t = NULL)
{
  cleanup (args, env);
  if (one != NULL)
    {
      close (one[0]);
      close (one[1]);
    }
  if (two != NULL)
    {
      close (two[0]);
      close (two[1]);
    }
  if (three != NULL)
    {
      close (three[0]);
      close (three[1]);
    }
  if (four != NULL)
    {
      close (four[0]);
      close (four[1]);
    }
  if (t == NULL)
    t = new java::io::IOException (JvNewStringLatin1 (strerror (error_value)));
  throw t;
}

void
java::lang::ConcreteProcess::startProcess (jstringArray progarray,
					   jstringArray envp)
{
  using namespace java::io;

  hasExited = false;

  if (! progarray)
    throw new NullPointerException;

  // Transform arrays to native form.
  char **args = (char **) _Jv_Malloc ((progarray->length + 1)
				      * sizeof (char *));
  char **env = NULL;

  // Initialize so we can gracefully recover.
  jstring *elts = elements (progarray);
  for (int i = 0; i <= progarray->length; ++i)
    args[i] = NULL;

  try
    {
      for (int i = 0; i < progarray->length; ++i)
	args[i] = new_string (elts[i]);
      args[progarray->length] = NULL;

      if (envp)
	{
	  env = (char **) _Jv_Malloc ((envp->length + 1) * sizeof (char *));
	  elts = elements (envp);

	  // Initialize so we can gracefully recover.
	  for (int i = 0; i <= envp->length; ++i)
	    env[i] = NULL;

	  for (int i = 0; i < envp->length; ++i)
	    env[i] = new_string (elts[i]);
	  env[envp->length] = NULL;
	}
    }
  catch (java::lang::OutOfMemoryError *oome)
    {
      fail (0, args, env, NULL, NULL, NULL, NULL, oome);
      throw oome;
    }

  // Create pipes for I/O.  MSGP is for communicating exec() status.
  int inp[2], outp[2], errp[2], msgp[2];

  if (pipe (inp))
    fail (errno, args, env);
  if (pipe (outp))
    fail (errno, args, env, inp);
  if (pipe (errp))
    fail (errno, args, env, inp, outp);
  if (pipe (msgp))
    fail (errno, args, env, inp, outp, errp);
  if (fcntl (msgp[1], F_SETFD, FD_CLOEXEC))
    fail (errno, args, env, inp, outp, errp, msgp);

  // We create the streams before forking.  Otherwise if we had an
  // error while creating the streams we would have run the child with
  // no way to communicate with it.
  try
    {
      errorStream = new FileInputStream (new FileDescriptor (errp[0]));
      inputStream = new FileInputStream (new FileDescriptor (inp[0]));
      outputStream = new FileOutputStream (new FileDescriptor (outp[1]));
    }
  catch (java::lang::Throwable *t)
    {
      fail (0, args, env, inp, outp, errp, msgp, t);
    }

  // We don't use vfork() because that would cause the local
  // environment to be set by the child.
  if ((pid = (jlong) fork ()) == -1)
    fail (errno, args, env, inp, outp, errp, msgp);

  if (pid == 0)
    {
      // Child process, so remap descriptors and exec.

      if (envp)
        {
	  // preserve PATH unless specified explicitly
	  char *path_val = getenv ("PATH");
	  environ = env;
	  if (getenv ("PATH") == NULL)
	    {
	      char *path_env = (char *) _Jv_Malloc (strlen (path_val) + 5 + 1);
	      strcpy (path_env, "PATH=");
	      strcat (path_env, path_val);
	      putenv (path_env);
	    }
	}
	
      // We ignore errors from dup2 because they should never occur.
      dup2 (outp[0], 0);
      dup2 (inp[1], 1);
      dup2 (errp[1], 2);

      close (inp[0]);
      close (inp[1]);
      close (errp[0]);
      close (errp[1]);
      close (outp[0]);
      close (outp[1]);
      close (msgp[0]);

      execvp (args[0], args);

      // Send the parent notification that the exec failed.
      char c = errno;
      write (msgp[1], &c, 1);
      _exit (127);
    }

  // Parent.  Close extra file descriptors and mark ours as
  // close-on-exec.
  close (outp[0]);
  close (inp[1]);
  close (errp[1]);
  close (msgp[1]);

  char c;
  int r = read (msgp[0], &c, 1);
  if (r == -1)
    fail (errno, args, env, inp, outp, errp, msgp);
  else if (r != 0)
    fail (c, args, env, inp, outp, errp, msgp);

  close (msgp[0]);
  cleanup (args, env);

  fcntl (outp[1], F_SETFD, 1);
  fcntl (inp[0], F_SETFD, 1);
  fcntl (errp[0], F_SETFD, 1);
}
