Merge branch 'master' of dice:git/vm

This commit is contained in:
Joel Dice 2007-12-03 16:36:57 -07:00
commit fc78e122c0
3 changed files with 187 additions and 16 deletions

View File

@ -8,6 +8,9 @@
#include "stdint.h"
#include "jni.h"
#include "jni-util.h"
#include "errno.h"
#include "fcntl.h"
#include "unistd.h"
#ifdef WIN32
# include "windows.h"
@ -17,6 +20,7 @@
# define SO_PREFIX ""
#else
# define SO_PREFIX "lib"
#include "sys/wait.h"
#endif
#ifdef __APPLE__
@ -69,6 +73,35 @@ namespace {
}
return fd;
}
#else
void makePipe(JNIEnv* e, int p[2])
{
if(pipe(p) != 0) {
throwNew(e, "java/io/IOException", strerror(errno));
}
}
void safeClose(int &fd)
{
if(fd != -1) close(fd);
fd = -1;
}
void close(int p[2])
{
::close(p[0]);
::close(p[1]);
}
void clean(JNIEnv* e, jobjectArray command, char** p)
{
int i = 0;
for(char** x = p; *x; ++x, ++i){
jstring element = (jstring) e->GetObjectArrayElement(command, i);
e->ReleaseStringUTFChars(element, *x);
}
free(p);
}
#endif
}
@ -165,6 +198,129 @@ Java_java_lang_Runtime_waitFor(JNIEnv* e, jclass, jlong pid)
}
return exitCode;
}
#else
extern "C" JNIEXPORT void JNICALL
Java_java_lang_Runtime_exec(JNIEnv* e, jclass,
jobjectArray command, jlongArray process)
{
char** argv = static_cast<char**>(malloc((e->GetArrayLength(command) + 1) * sizeof(char*)));
int i;
for(i = 0; i < e->GetArrayLength(command); i++){
jstring element = (jstring) e->GetObjectArrayElement(command, i);
char* s = const_cast<char*>(e->GetStringUTFChars(element, 0));
argv[i] = s;
}
argv[i] = 0;
int in[] = { -1, -1 };
int out[] = { -1, -1 };
int err[] = { -1, -1 };
int msg[] = { -1, -1 };
makePipe(e, in);
if(e->ExceptionOccurred()) return;
jlong inDescriptor = static_cast<jlong>(in[0]);
e->SetLongArrayRegion(process, 1, 1, &inDescriptor);
makePipe(e, out);
if(e->ExceptionOccurred()) return;
jlong outDescriptor = static_cast<jlong>(out[1]);
e->SetLongArrayRegion(process, 1, 1, &outDescriptor);
makePipe(e, err);
if(e->ExceptionOccurred()) return;
jlong errDescriptor = static_cast<jlong>(err[0]);
e->SetLongArrayRegion(process, 1, 1, &errDescriptor);
makePipe(e, msg);
if(e->ExceptionOccurred()) return;
if(fcntl(msg[1], F_SETFD, FD_CLOEXEC) != 0) {
throwNew(e, "java/io/IOException", strerror(errno));
return;
}
pid_t pid = fork();
switch(pid){
case -1: // error
throwNew(e, "java/io/IOException", strerror(errno));
return;
case 0: { // child
// Setup stdin, stdout and stderr
dup2(in[1], 1);
close(in);
dup2(out[0], 0);
close(out);
dup2(err[1], 2);
close(err);
close(msg[0]);
execvp(argv[0], argv);
// Error if here
char c = errno;
write(msg[1], &c, 1);
exit(127);
} break;
default: { //parent
jlong JNIPid = static_cast<jlong>(pid);
e->SetLongArrayRegion(process, 0, 1, &JNIPid);
safeClose(in[1]);
safeClose(out[0]);
safeClose(err[1]);
safeClose(msg[1]);
char c;
int r = read(msg[0], &c, 1);
if(r == -1) {
throwNew(e, "java/io/IOException", strerror(errno));
return;
} else if(r) {
throwNew(e, "java/io/IOException", strerror(c));
return;
}
} break;
}
safeClose(msg[0]);
clean(e, command, argv);
fcntl(in[0], F_SETFD, FD_CLOEXEC);
fcntl(out[1], F_SETFD, FD_CLOEXEC);
fcntl(err[0], F_SETFD, FD_CLOEXEC);
}
extern "C" JNIEXPORT jint JNICALL
Java_java_lang_Runtime_exitValue(JNIEnv* e, jclass, jlong pid)
{
int status;
pid_t returned = waitpid(pid, &status, WNOHANG);
if(returned == 0){
throwNew(e, "java/lang/IllegalThreadStateException", strerror(errno));
} else if(returned == -1){
throwNew(e, "java/lang/Exception", strerror(errno));
}
return WEXITSTATUS(status);
}
extern "C" JNIEXPORT jint JNICALL
Java_java_lang_Runtime_waitFor(JNIEnv*, jclass, jlong pid)
{
bool finished = false;
int status;
int exitCode;
while(!finished){
waitpid(pid, &status, 0);
if(WIFEXITED(status)){
finished = true;
exitCode = WEXITSTATUS(status);
} else if(WIFSIGNALED(status)){
finished = true;
exitCode = -1;
}
}
return exitCode;
}
#endif
extern "C" JNIEXPORT jstring JNICALL

View File

@ -49,8 +49,6 @@ public class Runtime {
return new MyProcess(process[0], (int) process[1], (int) process[2], (int) process[3]);
}
//private static native void exec(String command, int[] process);
private static native void exec(String[] command, long[] process);
private static native int exitValue(long pid);

View File

@ -4,15 +4,28 @@ import java.lang.Process;
public class RuntimeExec {
public static void main(String[] args) throws java.io.IOException, java.lang.InterruptedException {
Runtime runtime = Runtime.getRuntime();
System.out.println("Executing internet explorer");
String ieStr = "\"c:\\program files\\internet explorer\\iexplore.exe\" http://www.google.com";
Process ie = runtime.exec(ieStr);
System.out.println("Executing firefox");
String ieStr = null;
String charmapStr = null;
String[] firefox = new String[2];
firefox[0] = "c:\\program files\\mozilla firefox\\firefox.exe";
firefox[1] = "http://www.google.com";
if(System.getProperty("os.name").equals("windows")){
System.out.println("Executing internet explorer");
ieStr = "\"c:\\program files\\internet explorer\\iexplore.exe\" http://www.google.com";
} else {
System.out.println("Executing Firefox using string");
ieStr = "firefox http://www.google.com";
}
Process ie = runtime.exec(ieStr);
if(System.getProperty("os.name").equals("windows")){
System.out.println("Executing firefox");
firefox[0] = "c:\\program files\\mozilla firefox\\firefox.exe";
firefox[1] = "http://www.google.com";
} else {
System.out.println("Executing Firefox using array");
firefox[0] = "firefox";
firefox[1] = "http://www.google.com";
}
Process ff = runtime.exec(firefox);
boolean ffSuccess = false;
@ -20,21 +33,25 @@ public class RuntimeExec {
while(!(ieSuccess && ffSuccess)){
if(!ffSuccess){
try{
System.out.println("Firefox exit value: " + ff.exitValue());
System.out.println("Exit value from string exec: " + ff.exitValue());
ffSuccess = true;
} catch(IllegalThreadStateException e) {}
}
if(!ieSuccess){
try{
System.out.println("Internet Explorer exit value: " + ie.exitValue());
System.out.println("Exit value from array exec: " + ie.exitValue());
ieSuccess = true;
} catch(IllegalThreadStateException e) {}
}
}
System.out.println("Executing and waiting for charmap");
String charmapStr = "c:\\windows\\system32\\charmap.exe";
if(System.getProperty("os.name").equals("windows")){
System.out.println("Executing and waiting for charmap");
charmapStr = "c:\\windows\\system32\\charmap.exe";
} else {
System.out.println("Executing and waiting for firefox");
charmapStr = "firefox http://www.google.com";
}
Process cm = runtime.exec(charmapStr);
System.out.println("Charmap exit value: " + cm.waitFor());
System.out.println("Exit value: " + cm.waitFor());
}
}