samer@0: package samer.silk; samer@0: import java.net.*; samer@0: import java.io.*; samer@0: import jsint.*; samer@0: samer@0: /** Terminal to acces a remote JVM. samer@0: Connects to a given port on the remote host, samer@0: then relays System.in and out to the socket. samer@0: */ samer@0: samer@0: public class Terminal { samer@0: samer@0: public static void connect(Socket sock) throws Exception { connect(sock,null); } samer@0: public static void connect(Socket sock, Procedure readline) throws Exception { samer@0: InputStream in=sock.getInputStream(); samer@0: OutputStream out=sock.getOutputStream(); samer@0: Thread reader=new Thread(new Transfer(in,System.out)); samer@0: samer@0: reader.start(); // everything coming from socket gets squirted to stdout samer@0: samer@0: // this end should be responsible for writing prompt samer@0: if (readline!=null) { samer@0: PrintWriter prn=new PrintWriter(out,true); samer@0: try { samer@0: for (;;) { samer@0: prn.println((String)SI.call(readline,"remote> ")); samer@0: Thread.sleep(100); // wait for reply samer@0: } samer@0: } catch (Exception ex) {} samer@0: } else (new Transfer(System.in,out)).run(); samer@0: System.out.println(); samer@0: samer@0: sock.shutdownOutput(); // other end should notice this samer@0: reader.join(5000); // wait for reader to die, 5 seconds max samer@0: sock.close(); samer@0: } samer@0: samer@0: samer@0: static class Transfer implements Runnable { samer@0: InputStream in; samer@0: OutputStream out; samer@0: byte [] buffer; samer@0: samer@0: public Transfer(InputStream in, OutputStream out) { samer@0: this.in=in; samer@0: this.out=out; samer@0: buffer=new byte[2048]; samer@0: } samer@0: samer@0: public void run() { samer@0: int n; samer@0: try { samer@0: do { samer@0: n=in.read(buffer,0,2048); samer@0: if (n>0) { out.write(buffer,0,n); out.flush(); } samer@0: } while (n>=0); samer@0: } catch (Exception ex) { ex.printStackTrace(); } samer@0: System.err.println("reader thread terminating."); samer@0: } samer@0: } samer@0: samer@0: public static void REPL(Socket call) throws Exception samer@0: { samer@0: Evaluator evaluator=Scheme.currentEvaluator(); samer@0: samer@0: PrintWriter oldout=evaluator.getOutput(); samer@0: PrintWriter olderr=evaluator.getError(); samer@0: PrintWriter newout=new PrintWriter(call.getOutputStream(),true); samer@0: InputPort newin=new InputPort(new BufferedReader( samer@0: new InputStreamReader(call.getInputStream()))); samer@0: samer@0: samer@0: oldout.println("... starting new remote REPL."); samer@0: newout.println("Welcome to remote JVM - Type Ctrl-D to terminate session."); samer@0: samer@0: // would like to replace System.err and System.out samer@0: // with multicast streams samer@0: evaluator.setOutput(newout); samer@0: evaluator.setError(newout); samer@0: samer@0: try { samer@0: evaluator.readEvalWriteLoop("remote> "); samer@0: /* Old version, can't work with jscheme 7.2 samer@0: Object x; samer@0: while (!Scheme.EXIT) { samer@0: try { samer@0: newout.print("remote> "); newout.flush(); samer@0: if ((x = newin.read()) == InputPort.EOF) break; samer@0: U.write(evaluator.eval(x), newout, true); samer@0: newout.println(); newout.flush(); samer@0: } catch (Throwable e) { e.printStackTrace(newout); newout.flush(); } samer@0: } samer@0: */ samer@0: // try to let the other end know that the show's over samer@0: call.shutdownInput(); samer@0: } samer@0: finally { samer@0: newout.println("Remote session terminated."); samer@0: oldout.println("... remote REPL terminated."); samer@0: evaluator.setOutput(oldout); samer@0: evaluator.setError(olderr); samer@0: evaluator.setExit(false); // remote session not allowed to terminate JVM! samer@0: call.close(); // ?? or shutdownOutput(); samer@0: } samer@0: } samer@0: }