/*
 * Java core library component.
 *
 * Copyright (c) 1997, 1998
 *      Transvirtual Technologies, Inc.  All rights reserved.
 *
 * See the file "license.terms" for information on usage and redistribution
 * of this file.
 */

package kaffe.lang;

import java.lang.String;
import java.io.FileDescriptor;
import java.io.FileOutputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

public class UNIXProcess
  extends Process
  implements Runnable
{
	boolean isalive;
	int exit_code;
	FileDescriptor stdin_fd;
	FileDescriptor stdout_fd;
	FileDescriptor stderr_fd;
	FileDescriptor sync_fd;
	int pid;
	OutputStream stdin_stream;
	InputStream raw_stdout;
	InputStream raw_stderr;
	int numReaders;			// what's that for?
	private static Thread tidy;	// what's that for?
	Throwable throwable;		// saved to rethrow in correct thread


public UNIXProcess() {
}

public UNIXProcess(String argv[], String arge[])
    throws Throwable
{
	stdin_fd = new FileDescriptor();
	stdout_fd = new FileDescriptor();
	stderr_fd = new FileDescriptor();
	sync_fd = new FileDescriptor();

	/* We first create a thread to start the new process in.  This
	 * is because on some system we can only wait for the child from
	 * it's parent (UNIX for example).  So, we have to create a thread
	 * to do the waiting.
	 */
	final String _argv[] = argv;
	final String _arge[] = arge;
	Thread sitter = new Thread() {
		public void run() {
			int fae = 0;
			try {
				fae = forkAndExec(_argv, _arge);
			}
			catch (Throwable t) {
				// save it to rethrow in correct thread
				throwable = t;
				synchronized(this) {
					this.notify();
				}
				return;
			}
			if (fae == 0) {
				synchronized(this) {
					isalive = true;
					this.notify();
				}
				exit_code = execWait();
			}
			synchronized(this) {
				isalive = false;
				this.notifyAll();
			}
			synchronized(UNIXProcess.this) {
				UNIXProcess.this.notifyAll();
			}
		}
	};

	/* Start the sitter then wait until it says it's child has started.
	 * We then retrieve the childs connection information.
	 */
	synchronized(sitter) {
		sitter.start();
		try {
			sitter.wait();
		}
		catch (InterruptedException _) {
		}
		if (throwable != null) {
			// rethrow in current thread
			throw throwable.fillInStackTrace();
		}

		// Create streams from the file descriptors
		stdin_stream = new FileOutputStream(stdin_fd);
		raw_stdout = new FileInputStream(stdout_fd);
		raw_stderr = new FileInputStream(stderr_fd);

		// now signal child to proceed
		FileOutputStream sync = new FileOutputStream(sync_fd);
		byte[] sbuf = new byte[1];
		try {
			sync.write(sbuf);
		}
		catch (IOException _) {
		}
	}
}

native public void destroy();

public int exitValue() {
	if (isalive) {
		throw new IllegalThreadStateException();
	}
	return exit_code;
}

native private int forkAndExec(Object cmd[], Object env[]);
native private int execWait();

public void run() {
}

public InputStream getErrorStream() {
	return raw_stderr;
}

public InputStream getInputStream() {
	return raw_stdout;
}

public OutputStream getOutputStream() {
	return stdin_stream;
}

public int waitFor() throws InterruptedException {
	synchronized(this) {
		while (isalive == true) {
			wait();
		}
	}
	return (exit_code);
}

/**
 * Native callback.
 */
private void processDied(int status) {
	synchronized(this) {
		isalive = false;
		exit_code = status;
		notifyAll();
	}
}

}

@@ -1,8 +1,9 @@
+%0A
 /*%0A * Ja
@@ -260,200 +260,12 @@
 ava.
-lang.String;%0Aimport java.io.FileDescriptor;%0Aimport java.io.FileOutputStream;%0Aimport java.io.FileInputStream;%0Aimport java.io.IOException;%0Aimport java.io.InputStream;%0Aimport java.io.OutputStream
+io.*
 ;%0A%0Ap
@@ -287,18 +287,16 @@
 XProcess
-%0A 
  extends
@@ -307,31 +307,9 @@
 cess
-%0A  implements Runnable%0A
+ 
 %7B%0A%09b
@@ -537,96 +537,8 @@
 rr;%0A
-%09int numReaders;%09%09%09// what's that for?%0A%09private static Thread tidy;%09// what's that for?%0A
 %09Thr
@@ -595,17 +595,16 @@
 thread%0A%0A
-%0A
 public U
@@ -618,34 +618,14 @@
 ess(
-) %7B%0A%7D%0A%0Apublic UNIXProcess(
+final 
 Stri
@@ -634,16 +634,22 @@
  argv%5B%5D,
+ final
  String 
@@ -659,12 +659,8 @@
 e%5B%5D)
-%0A   
  thr
@@ -672,17 +672,17 @@
 hrowable
-%0A
+ 
 %7B%0A%09stdin
@@ -1043,68 +1043,8 @@
  */%0A
-%09final String _argv%5B%5D = argv;%0A%09final String _arge%5B%5D = arge;%0A
 %09Thr
@@ -1144,16 +1144,14 @@
 xec(
-_
 argv, 
-_
 arge
@@ -2320,39 +2320,8 @@
 %0A%7D%0A%0A
-native public void destroy();%0A%0A
 publ
@@ -2429,123 +2429,8 @@
 %0A%7D%0A%0A
-native private int forkAndExec(Object cmd%5B%5D, Object env%5B%5D);%0Anative private int execWait();%0A%0Apublic void run() %7B%0A%7D%0A%0A
 publ
@@ -2759,157 +2759,378 @@
 %0A%7D%0A%0A
-/**%0A * Native callback.%0A */%0Aprivate void processDied(int status) %7B%0A%09synchronized(this) %7B%0A%09%09isalive = false;%0A%09%09exit_code = status;%0A%09%09notifyAll(
+public void sendSignal(int signum) throws IOException %7B%0A%09sendSignal0(pid, signum);%0A%7D%0A%0Apublic static void sendSignal(int pid, int signum) throws IOException %7B%0A%09sendSignal0(pid, signum);%0A%7D%0A%0Apublic native void destroy();%0Aprivate native int forkAndExec(Object cmd%5B%5D, Object env%5B%5D);%0Aprivate native int execWait();%0Aprivate native static void sendSignal0(int pid, int signum
 );%0A
-%09%7D
 %0A%7D%0A%0A
-%7D%0A

Add a new method sendSignal() to UNIXProcess.java for sending signals. Remove some unnecessary cruft.