/*
* @(#)Win32Process.java 1.30 06/10/10
*
* Copyright 1990-2008 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER
*
* This program 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.
*
* This program 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 at /legal/license.txt).
*
* 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 or visit www.sun.com if you need additional
* information or have any questions.
*/
package java.lang;
import java.io.*;
class Win32Process extends Process {
private long handle = 0;
private FileDescriptor stdin_fd;
private FileDescriptor stdout_fd;
private FileDescriptor stderr_fd;
private OutputStream stdin_stream;
private InputStream stdout_stream;
private InputStream stderr_stream;
private int exitcode;
private boolean hasExited;
Win32Process(String cmd[], String env[]) throws Exception {
this(cmd, env, null);
}
Win32Process(String cmd[], String env[], String path) throws Exception {
StringBuffer cmdbuf = new StringBuffer(80);
for (int i = 0; i < cmd.length; i++) {
if (i > 0) {
cmdbuf.append(' ');
}
String s = cmd[i];
if (s.indexOf(' ') >= 0 || s.indexOf('\t') >= 0) {
if (s.charAt(0) != '"') {
cmdbuf.append('"');
cmdbuf.append(s);
if (s.endsWith("\\")) {
cmdbuf.append("\\");
}
cmdbuf.append('"');
} else if (s.endsWith("\"")) {
/* The argument has already been quoted. */
cmdbuf.append(s);
} else {
/* Unmatched quote for the argument. */
throw new IllegalArgumentException();
}
} else {
cmdbuf.append(s);
}
}
String cmdstr = cmdbuf.toString();
String envstr = null;
if (env != null) {
StringBuffer envbuf = new StringBuffer(256);
for (int i = 0; i < env.length; i++) {
envbuf.append(env[i]).append('\0');
}
envstr = envbuf.toString();
}
stdin_fd = new FileDescriptor();
stdout_fd = new FileDescriptor();
stderr_fd = new FileDescriptor();
handle = create(cmdstr, envstr, path, 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_stream =
new BufferedInputStream(new FileInputStream(stdout_fd));
stderr_stream =
new FileInputStream(stderr_fd);
/*
* 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).
*/
Thread t = new Thread("process reaper") {
public void run() {
int res = waitFor0();
synchronized (Win32Process.this) {
hasExited = true;
exitcode = res;
Win32Process.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 void finalize() {
close();
}
private native int waitFor0();
public native void destroy();
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 native long create(String cmdstr, String envstr, String path,
FileDescriptor in_fd,
FileDescriptor out_fd,
FileDescriptor err_fd);
private native void close();
}