In message
<[EMAIL PROTECTED]>, Richard
Hall writes:
Runtime.getRuntime().exec("/usr/games/monop"); works just fine,
but Process.getInputStream() doesn't seem to work.
Richard,
It's not exactly "C interaction" that you mean here. There's 1.1 JNI (Java
Native Interfaces) for that.
Has anyone succeeded at getting a Java program to interact with a C
program via stdin/stdout? If so, how? If not, can you explain the
behavior of the following code? (JDK 1.1.6 and Debian 2.0 libc5, i386)
I didn't see any obvious problems with your code, but I didn't read
it carefully. The monop(1) program may be asking for something other
than what you're passing to it or visa versa. That's often the case
in these situations.
Here's (a mostly untested) class I was working on to talk to Kermit. I
don't know if it'll help you. It'll work for arbitrary shell commands,
though. It actually worked to connect another class to my HP48 via
RS232! At one point, and I passed data both ways (as far as I
remember). It has a thread to do reading/writing, and a thread to
perform a timeout (in case your chat gets stuck and the time slips
by). At any rate, this proves that Runtime.getRuntime().exec(command,
environment); works, at least for what I was trying to do.
Steve
import java.io.*;
/**
* Class for executing a command at a shell.
*
* <p>
*
* @see java.lang.Process
* @see SPException
* @version $Id: ShellProcess.java,v 1.4 1998/05/19 10:00:29 stevemw Exp stevemw $
* @author Stephen Wynne <[EMAIL PROTECTED]>
*
*/
public class ShellProcess extends Thread {
private Writer outPut;
private String command[] = { "/bin/true" };
String environment[] = { "PATH=/bin:/usr/bin:/usr/X11R6/bin:." };
private int MAXWAIT_MILLIS = 60 * 1000;
private Process child;
private boolean done = false;
/**
* Default constructor.
*/
ShellProcess() {
}
/**
* Combined constructor initialization class.
*
* @param cmd Command tokens to execute.
*/
ShellProcess(String cmd[]) {
command = cmd;
init(cmd, null, new OutputStreamWriter(System.out));
}
/**
* Combined constructor initialization class.
*
* @param cmd Command tokens to execute.
* @param env Environment.
*/
ShellProcess(String cmd[], String env[]) {
init(cmd, env, new OutputStreamWriter(System.out));
}
/**
* Combined constructor initialization class.
*
* @param cmd Command tokens to execute.
* @param env Environment.
* @param out Stream used to send results.
*/
ShellProcess(String cmd[], String env[], Writer out) {
init(cmd, env, out);
}
/**
* Initialization code for all non-default constructors.
* Also used to setup default-constructed object and get it running.
*
* @param cmd Command tokens to execute.
* @param env Environment.
* @param out Stream used to send results.
*/
public void init(String cmd[], String env[], Writer out) {
command = cmd != null ? cmd : command;
environment = env != null ? env : environment;
outPut = out != null ? out : new OutputStreamWriter(System.out);
start(); // Start doing some I/O
try {
join(MAXWAIT_MILLIS);
} catch(InterruptedException e) {
// XXX IGNORE INTERRUPTIONS
}
if (! done) {
setPriority(Thread.MIN_PRIORITY);
child.destroy(); // Kill our Process (from exec).
interrupt(); // Wake blocked threads.
}
}
/**
* Executes a command at the shell.
* @exception SPException.
*/
private void execute() throws SPException {
try {
child = Runtime.getRuntime().exec(command, environment);
BufferedReader in = new
BufferedReader(new InputStreamReader(child.getInputStream()));
String line;
while((line = in.readLine()) != null) {
outPut.write(line + "\n");
outPut.flush();
}
if (child.waitFor() != 0) {
// Command failed.
throw new SPException(child.exitValue());
}
} catch (Exception e) {
throw new SPException(e.toString());
}
return;
}
/**
* Do the work.
*/
public void run() {
// Try to prevent the watch thread from starving. XXX necessary?
setPriority(currentThread().getPriority() - 1);
try {
execute();
} catch(SPException e) {
System.err.println("Caught exception " + e.toString() +
". Terminated.");
}
synchronized (this) {
done = true;
}
return;
}
/**
* Access the current timeout value in seconds.
*/
public int getTimeoutSeconds() {
return MAXWAIT_MILLIS * 1000;
}
/**
* Change the timeout value in seconds.
*/
public void setTimeoutSeconds(int seconds) {
MAXWAIT_MILLIS = seconds * 1000;
}
/**
* Test-harness.
*
* @param args command-line to execute.
*/
public static final void main(String args[]) {
if (args.length == 0) {
System.err.println("Usage: java ShellProcess cmd ...");
System.exit(1);
} else {
System.err.println("---------------Start!-(no default)-");
ShellProcess p = new ShellProcess();
p.init(args, null, new OutputStreamWriter(System.out));
System.err.println("---------------Done!--(no default)-");
System.err.println("---------------Start!--------------");
new ShellProcess(args, null, new OutputStreamWriter(System.out));
System.err.println("---------------Done!---------------");
}
}
}
/**
* Simple class for ShellProcess exceptions.
*/
class SPException extends Exception {
/**
* @param exitValue return value from <I>shell command</I> executed.
*/
SPException(int exitValue) {
super("Shell process failed with exit status \n" + exitValue);
}
/**
* @param reason a short explanation of the execution error encountered.
*/
SPException(String reason) {
super("Shell process failed: \n" + reason);
}
/**
* @param exitValue return value from <I>shell command</I> executed.
* @param reason a short explanation of the execution error encountered.
*/
SPException(int exitValue, String reason) {
super("Process failed with exit " + exitValue +
".\nReason: " + reason );
}
}