/* 
 * Copyright 1995-2006 Sun Microsystems, Inc.  All Rights Reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Sun designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Sun in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
 * CA 95054 USA or visit www.sun.com if you need additional information or
 * have any questions.
 */

package java.lang;

import java.io.*;

/* java.lang.Process subclass in the UNIX environment.
 *
 * @author Mario Wolczko and Ross Knippel.
 */

final class UNIXProcess extends Process {
    private FileDescriptor stdin_fd;
    private FileDescriptor stdout_fd;
    private FileDescriptor stderr_fd;
    private int pid;
    private int exitcode;
    private boolean hasExited;

    private OutputStream stdin_stream;
    private BufferedInputStream stdout_stream;
    private DeferredCloseInputStream stdout_inner_stream;
    private DeferredCloseInputStream stderr_stream;

    /* this is for the reaping thread */
    private native int waitForProcessExit(int pid);

    private native int forkAndExec(byte[] prog,
				   byte[] argBlock, int argc,
				   byte[] envBlock, int envc,
				   byte[] dir,
				   boolean redirectErrorStream,
				   FileDescriptor stdin_fd,
				   FileDescriptor stdout_fd,
				   FileDescriptor stderr_fd)
	throws IOException;

    UNIXProcess(final byte[] prog,
		final byte[] argBlock, int argc,
		final byte[] envBlock, int envc,
		final byte[] dir,
		final boolean redirectErrorStream)
    throws IOException {
	stdin_fd  = new FileDescriptor();
	stdout_fd = new FileDescriptor();
	stderr_fd = new FileDescriptor();

	pid = forkAndExec(prog,
			  argBlock, argc,
			  envBlock, envc,
			  dir,
			  redirectErrorStream,
			  stdin_fd, stdout_fd, stderr_fd);

	java.security.AccessController.doPrivileged(
				    new java.security.PrivilegedAction() {
	    public Object run() {
	        stdin_stream
		    = new BufferedOutputStream(new FileOutputStream(stdin_fd));
		stdout_inner_stream = new DeferredCloseInputStream(stdout_fd);
	        stdout_stream = new BufferedInputStream(stdout_inner_stream);
	        stderr_stream = new DeferredCloseInputStream(stderr_fd);
		return null;
	    }
	});

	/*
	 * For each subprocess forked a corresponding reaper thread
	 * is started.  That thread is the only thread which waits
	 * for the subprocess to terminate and it doesn't hold any
	 * locks while doing so.  This design allows waitFor() and
	 * exitStatus() to be safely executed in parallel (and they
	 * need no native code).
	 */

	java.security.AccessController.doPrivileged(
			    new java.security.PrivilegedAction() {
	    public Object run() {
		Thread t = new Thread("process reaper") {
		    public void run() {
			int res = waitForProcessExit(pid);
			synchronized (UNIXProcess.this) {
			    hasExited = true;
			    exitcode = res;
			    UNIXProcess.this.notifyAll();
			}
		    }
		};
		t.setDaemon(true);
		t.start();
		return null;
	    }
	});
    }

    public OutputStream getOutputStream() {
	return stdin_stream;
    }

    public InputStream getInputStream() {
	return stdout_stream;
    }

    public InputStream getErrorStream() {
	return stderr_stream;
    }

    public synchronized int waitFor() throws InterruptedException {
        while (!hasExited) {
	    wait();
	}
	return exitcode;
    }

    public synchronized int exitValue() {
	if (!hasExited) {
	    throw new IllegalThreadStateException("process hasn't exited");
	}
	return exitcode;
    }

    private static native void destroyProcess(int pid);
    public synchronized void destroy() {
	// There is a risk that pid will be recycled, causing us to
	// kill the wrong process!  So we only terminate processes
	// that appear to still be running.  Even with this check,
	// there is an unavoidable race condition here, but the window
	// is very small, and OSes try hard to not recycle pids too
	// soon, so this is quite safe.
	if (!hasExited)
	    destroyProcess(pid);
	try {
            stdin_stream.close();
	    stdout_inner_stream.closeDeferred(stdout_stream);
	    stderr_stream.closeDeferred(stderr_stream);
        } catch (IOException e) {
            // ignore
        }
    }

    // A FileInputStream that supports the deferment of the actual close
    // operation until the last pending I/O operation on the stream has
    // finished.  This is required on Solaris because we must close the stdin
    // and stdout streams in the destroy method in order to reclaim the
    // underlying file descriptors.  Doing so, however, causes any thread
    // currently blocked in a read on one of those streams to receive an
    // IOException("Bad file number"), which is incompatible with historical
    // behavior.  By deferring the close we allow any pending reads to see -1
    // (EOF) as they did before.
    //
    private static class DeferredCloseInputStream
	extends FileInputStream
    {

	private DeferredCloseInputStream(FileDescriptor fd) {
	    super(fd);
	}

	private Object lock = new Object();	// For the following fields
	private boolean closePending = false;
	private int useCount = 0;
	private InputStream streamToClose;

	private void raise() {
	    synchronized (lock) {
		useCount++;
	    }
	}

	private void lower() throws IOException {
	    synchronized (lock) {
		useCount--;
		if (useCount == 0 && closePending) {
		    streamToClose.close();
		}
	    }
	}

	// stc is the actual stream to be closed; it might be this object, or
	// it might be an upstream object for which this object is downstream.
	//
	private void closeDeferred(InputStream stc) throws IOException {
	    synchronized (lock) {
		if (useCount == 0) {
		    stc.close();
		} else {
		    closePending = true;
		    streamToClose = stc;
		}
	    }
	}

	public void close() throws IOException {
	    synchronized (lock) {
		useCount = 0;
		closePending = false;
	    }
	    super.close();
	}

	public int read() throws IOException {
	    raise();
	    try {
		return super.read();
	    } finally {
		lower();
	    }
	}

	public int read(byte[] b) throws IOException {
	    raise();
	    try {
		return super.read(b);
	    } finally {
		lower();
	    }
	}

	public int read(byte[] b, int off, int len) throws IOException {
	    raise();
	    try {
		return super.read(b, off, len);
	    } finally {
		lower();
	    }
	}

	public long skip(long n) throws IOException {
	    raise();
	    try {
		return super.skip(n);
	    } finally {
		lower();
	    }
	}

	public int available() throws IOException {
	    raise();
	    try {
		return super.available();
	    } finally {
		lower();
	    }
	}

    }

    /* This routine initializes JNI field offsets for the class */
    private static native void initIDs();

    static {
	initIDs();
    }
}
