/*******************************************************************************
 * Copyright (c) 2000, 2011 QNX Software Systems and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     QNX Software Systems - Initial API and implementation
 *     Wind River Systems   - bug 248071, bug 286162
 *******************************************************************************/
package org.eclipse.cdt.utils.spawner;


import java.io.*;
import java.util.StringTokenizer;

import org.eclipse.cdt.core.CCorePlugin;
import org.eclipse.cdt.utils.pty.PTY;
import org.eclipse.core.runtime.Platform;
import org.eclipse.osgi.util.NLS;

public class Spawner extends Process {
  static final String LIBRARY_NAME = "gspawner"; //$NON-NLS-1$

  public int NOOP = 0;
	public int HUP = 1;
	public int KILL = 9;
	public int TERM = 15;

	/**
	 * On Windows, what this does is far from easy to explain.
	 * Some of the logic is in the JNI code, some in the spawner.exe code.
	 *
	 * <ul>
	 * <li>If the process this is being raised against was launched by us (the Spawner)
	 *    <ul>
	 *    <li>If the process is a cygwin program (has the cygwin1.dll loaded), then issue a 'kill -SIGINT'. If
	 *    the 'kill' utility isn't available, send the process a CTRL-C
	 *    <li>If the process is <i>not</i> a cygwin program, send the process a CTRL-C
	 *    </ul>
	 * <li>If the process this is being raised against was <i>not</i> launched by us, use
	 * DebugBreakProcess to interrupt it (sending a CTRL-C is easy only if we share a console
	 * with the target process)
	 * </ul>
	 *
	 * On non-Windows, raising this just raises a POSIX SIGINT
	 *
	 */
	public int INT = 2;

	/**
	 * A fabricated signal number for use on Windows only. Tells the starter program to send a CTRL-C
	 * regardless of whether the process is a Cygwin one or not.
	 *
	 * @since 5.2
	 */
	public int CTRLC = 1000;  // arbitrary high number to avoid collision

	int pid = 0;
	int status;
	final int[] fChannels = new int[3];
	boolean isDone;
	OutputStream out;
	InputStream in;
	InputStream err;
	private PTY fPty;

	public Spawner(String command, boolean bNoRedirect) throws IOException {
		StringTokenizer tokenizer = new StringTokenizer(command);
		String[] cmdarray = new String[tokenizer.countTokens()];
		for (int n = 0; tokenizer.hasMoreTokens(); n++) {
      cmdarray[n] = tokenizer.nextToken();
    }
		if (bNoRedirect) {
      exec_detached(cmdarray, new String[0], "."); //$NON-NLS-1$
    }
    else {
      exec(cmdarray, new String[0], "."); //$NON-NLS-1$
    }
	}
	/**
	 * Executes the specified command and arguments in a separate process with the
	 * specified environment and working directory.
	 **/
	protected Spawner(String[] cmdarray, String[] envp, File dir) throws IOException {
		String dirpath = "."; //$NON-NLS-1$
		if (dir != null) {
      dirpath = dir.getAbsolutePath();
    }
		exec(cmdarray, envp, dirpath);
	}

	protected Spawner(String[] cmdarray, String[] envp, File dir, PTY pty) throws IOException {
		String dirpath = "."; //$NON-NLS-1$
		if (dir != null) {
      dirpath = dir.getAbsolutePath();
    }
		fPty = pty;
		exec_pty(cmdarray, envp, dirpath, pty);
	}
	/**
	 * Executes the specified string command in a separate process.
	 **/
	protected Spawner(String command) throws IOException {
		this(command, null);
	}

	/**
	 * Executes the specified command and arguments in a separate process.
	 **/
	protected Spawner(String[] cmdarray) throws IOException {
		this(cmdarray, null);
	}

	/**
	 * Executes the specified command and arguments in a separate process with the
	 * specified environment.
	 **/
	protected Spawner(String[] cmdarray, String[] envp) throws IOException {
		this(cmdarray, envp, null);
	}

	/**
	 * Executes the specified string command in a separate process with the specified
	 * environment.
	 **/
	protected Spawner(String cmd, String[] envp) throws IOException {
		this(cmd, envp, null);
	}

	/**
	 * Executes the specified string command in a separate process with the specified
	 * environment and working directory.
	 **/
	protected Spawner(String command, String[] envp, File dir) throws IOException {
		StringTokenizer tokenizer = new StringTokenizer(command);
		String[] cmdarray = new String[tokenizer.countTokens()];
		for (int n = 0; tokenizer.hasMoreTokens(); n++) {
      cmdarray[n] = tokenizer.nextToken();
    }
		String dirpath = "."; //$NON-NLS-1$
		if (dir != null) {
      dirpath = dir.getAbsolutePath();
    }
		exec(cmdarray, envp, dirpath);
	}

	@Override
	protected void finalize() throws Throwable {
		closeUnusedStreams();
	}

	/**
	 * See java.lang.Process#getInputStream ();
	 * The client is responsible for closing the stream explicitly.
	 **/
	@Override
	public synchronized InputStream getInputStream() {
		if(null == in) {
			if (fPty != null) {
				in = fPty.getInputStream();
			} else {
				in = new SpawnerInputStream(fChannels[1]);
			}
		}
		return in;
	}

	/**
	 * See java.lang.Process#getOutputStream ();
	 * The client is responsible for closing the stream explicitly.
	 **/
	@Override
	public synchronized OutputStream getOutputStream() {
		if(null == out) {
			if (fPty != null) {
				out = fPty.getOutputStream();
			} else {
				out = new SpawnerOutputStream(fChannels[0]);
			}
		}
		return out;
	}

	/**
	 * See java.lang.Process#getErrorStream ();
	 * The client is responsible for closing the stream explicitly.
	 **/
	@Override
	public synchronized InputStream getErrorStream() {
		if(null == err) {
			if (fPty != null && !fPty.isConsole()) {
				// If PTY is used and it's not in "Console" mode, then stderr is
				// redirected to the PTY's output stream.  Therefore, return a
				// dummy stream for error stream.
				err = new InputStream() {
					@Override
					public int read() throws IOException {
						return -1;
					}
				};
			} else {
				err = new SpawnerInputStream(fChannels[2]);
			}
		}
		return err;
	}

	/**
	 * See java.lang.Process#waitFor ();
	 **/
	@Override
	public synchronized int waitFor() throws InterruptedException {
		while (!isDone) {
			wait();
		}

		// For situations where the user does not call destroy(),
		// we try to kill the streams that were not used here.
		// We check for streams that were not created, we create
		// them to attach to the pipes, and then we close them
		// to release the pipes.
		// Streams that were created by the client need to be
		// closed by the client itself.
		//
		// But 345164
		closeUnusedStreams();
		return status;
	}

	/**
	 * See java.lang.Process#exitValue ();
	 **/
	@Override
	public synchronized int exitValue() {
		if (!isDone) {
			throw new IllegalThreadStateException("Process not Terminated"); //$NON-NLS-1$
		}
		return status;
	}

	/**
	 * See java.lang.Process#destroy ();
	 *
	 * Clients are responsible for explicitly closing any streams
	 * that they have requested through
	 *   getErrorStream(), getInputStream() or getOutputStream()
	 **/
	@Override
	public synchronized void destroy() {
		// Sends the TERM
		terminate();

		// Close the streams on this side.
		//
		// We only close the streams that were
		// never used by any client.
		// So, if the stream was not created yet,
		// we create it ourselves and close it
		// right away, so as to release the pipe.
		// Note that even if the stream was never
		// created, the pipe has been allocated in
		// native code, so we need to create the
		// stream and explicitly close it.
		//
		// We don't close streams the clients have
		// created because we don't know when the
		// client will be finished using them.
		// It is up to the client to close those
		// streams.
		//
		// But 345164
		closeUnusedStreams();

		// Grace before using the heavy gone.
		if (!isDone) {
			try {
				wait(1000);
			} catch (InterruptedException e) {
			}
		}
		if (!isDone) {
			kill();
		}
	}

	/**
	 * On Windows, interrupt the spawned program by using Cygwin's utility 'kill -SIGINT' if it's a Cgywin
	 * program, otherwise send it a CTRL-C. If Cygwin's 'kill' command is not available, send a CTRL-C. On
	 * linux, interrupt it by raising a SIGINT.
	 */
	public int interrupt() {
		return raise(pid, INT);
	}

	/**
	 * On Windows, interrupt the spawned program by send it a CTRL-C (even if it's a Cygwin program). On
	 * linux, interrupt it by raising a SIGINT.
	 *
	 * @since 5.2
	 */
	public int interruptCTRLC() {
        if (Platform.getOS().equals(Platform.OS_WIN32)) {
        	return raise(pid, CTRLC);
        }
        else {
        	return interrupt();
        }
	}

	public int hangup() {
		return raise(pid, HUP);
	}

	public int kill() {
		return raise(pid, KILL);
	}

	public int terminate() {
		return raise(pid, TERM);
	}

	public boolean isRunning() {
		return (raise(pid, NOOP) == 0);
	}

	private void exec(String[] cmdarray, String[] envp, String dirpath) throws IOException {
		String command = cmdarray[0];
		SecurityManager s = System.getSecurityManager();
		if (s != null) {
      s.checkExec(command);
    }
		if (envp == null) {
      envp = new String[0];
    }

		Reaper reaper = new Reaper(cmdarray, envp, dirpath);
		reaper.setDaemon(true);
		reaper.start();

		// Wait until the subprocess is started or error.
		synchronized (this) {
			while (pid == 0) {
				try {
					wait();
				} catch (InterruptedException e) {
				}
			}
		}

		// Check for errors.
		if (pid == -1) {
			throw new IOException(reaper.getErrorMessage());
		}
	}

	private void exec_pty(String[] cmdarray, String[] envp, String dirpath, PTY pty) throws IOException {
		String command = cmdarray[0];
		SecurityManager s = System.getSecurityManager();
		if (s != null) {
      s.checkExec(command);
    }
		if (envp == null) {
      envp = new String[0];
    }

		final String slaveName = pty.getSlaveName();
		final int masterFD = pty.getMasterFD().getFD();
		final boolean console = pty.isConsole();
		//int fdm = pty.get
		Reaper reaper = new Reaper(cmdarray, envp, dirpath) {
			/* (non-Javadoc)
			 * @see org.eclipse.cdt.utils.spawner.Spawner.Reaper#execute(java.lang.String[], java.lang.String[], java.lang.String, int[])
			 */
			@Override
			int execute(String[] cmd, String[] env, String dir, int[] channels) throws IOException {
				return exec2(cmd, env, dir, channels, slaveName, masterFD, console);
			}
		};
		reaper.setDaemon(true);
		reaper.start();

		// Wait until the subprocess is started or error.
		synchronized (this) {
			while (pid == 0) {
				try {
					wait();
				} catch (InterruptedException e) {
				}
			}
		}

		// Check for errors.
		if (pid == -1) {
			throw new IOException("Exec_tty error:" + reaper.getErrorMessage()); //$NON-NLS-1$
		}
	}

	public void exec_detached(String[] cmdarray, String[] envp, String dirpath) throws IOException {
		String command = cmdarray[0];
		SecurityManager s = System.getSecurityManager();
		if (s != null) {
      s.checkExec(command);
    }

		if (envp == null) {
      envp = new String[0];
    }
		pid = exec1(cmdarray, envp, dirpath);
		if (pid == -1) {
			throw new IOException("Exec error"); //$NON-NLS-1$
		}
		fChannels[0] = -1;
		fChannels[1] = -1;
		fChannels[2] = -1;
	}

	/**
	 * Close any streams not used by clients.
	 */
	private synchronized void closeUnusedStreams() {
		try {
			if(null == err) {
        getErrorStream().close();
      }
		} catch (IOException e) {}
		try {
			if(null == in) {
        getInputStream().close();
      }
		} catch (IOException e) {}
		try {
			if(null == out) {
        getOutputStream().close();
      }
		} catch (IOException e) {}
	}

	/**
	 * Native method use in normal exec() calls.
	 */
	native int exec0( String[] cmdarray, String[] envp, String dir, int[] chan) throws IOException;

	/**
	 * Native method use in no redirect meaning to streams will created.
	 */
	native int exec1( String[] cmdarray, String[] envp, String dir) throws IOException;

	/**
	 * Native method when executing with a terminal emulation.
	 */
	native int exec2( String[] cmdarray, String[] envp, String dir, int[] chan, String slaveName, int masterFD, boolean console) throws IOException;

	/**
	 * Native method to drop a signal on the process with pid.
	 */
	public native int raise(int processID, int sig);

	/*
	 * Native method to wait(3) for process to terminate.
	 */
	native int waitFor(int processID);

	static {
		try {
			System.loadLibrary(LIBRARY_NAME);
		} catch (SecurityException e) {
			CCorePlugin.log(e);
		} catch (UnsatisfiedLinkError e) {
			CCorePlugin.log(e);
		}
	}

	// Spawn a thread to handle the forking and waiting
	// We do it this way because on linux the SIGCHLD is
	// send to the one thread.  So do the forking and
	// the wait in the same thread.
	class Reaper extends Thread {
		String[] fCmdarray;
		String[] fEnvp;
		String fDirpath;
		volatile Throwable fException;

		public Reaper(String[] array, String[] env, String dir) {
			super("Spawner Reaper"); //$NON-NLS-1$
			fCmdarray = array;
			fEnvp = env;
			fDirpath = dir;
			fException = null;
		}

		int execute(String[] cmdarray, String[] envp, String dir, int[] channels) throws IOException {
			return exec0(cmdarray, envp, dir, channels);
		}

		@Override
		public void run() {
			try {
				pid = execute(fCmdarray, fEnvp, fDirpath, fChannels);
			} catch (Exception e) {
				pid = -1;
				fException= e;
			}

			// Tell spawner that the process started.
			synchronized (Spawner.this) {
				Spawner.this.notifyAll();
			}

			if (pid != -1) {
				// Sync with spawner and notify when done.
				status = waitFor(pid);
				synchronized (Spawner.this) {
					isDone = true;
					Spawner.this.notifyAll();
				}
			}
		}

		public String getErrorMessage() {
			final String reason= fException != null ? fException.getMessage() : "Unknown reason"; //$NON-NLS-1$
			return NLS.bind(CCorePlugin.getResourceString("Util.error.cannotRun"), fCmdarray[0], reason); //$NON-NLS-1$
		}
	}
}
