import socket.TelnetIO; import java.io.IOException; /** * HostIO.java wraps TelnetIO to allow line by line reading * * This is a quick & dirty prototype, but it helps to "get the idea". * * It uses the Java Telnet implementation from the Java Telnet Applet * available at "http://www.first.gmd.de/persons/leo/java/Telnet". */ class HostIO { // compile-time switch to trace host I/O on stdout static final boolean DEBUG = true; // compile-time switch to test GUI without host access static final boolean LOCAL = false; // a few ASCII constants (control characters) static final char LF = 10; static final char CR = 13; static final char DC1 = 17; /** * The telnet connection to the host system. */ private TelnetIO tio; /** * Internal buffer for collecting data for line-by-line access. */ private StringBuffer buf; /** * The most recently parsed line and how it was terminated. */ private String line; private String term; // uses symbolic strings (CR, CRLF, LF, DC1) /** * Next readln() should return the same line again (pushBack) */ private boolean back; /* * Constructor. */ HostIO() { tio = new TelnetIO(); buf = new StringBuffer(); line = null; term = null; back = false; } /** * Opens telnet connection to give hostname. */ void open(String hostname) throws IOException { if (! LOCAL) tio.connect(hostname); } /** * Closes open telnet connection. */ void close() throws IOException { if (! LOCAL) tio.disconnect(); } /** * Read data from telnet connection and parse for line delimiters. * Accepts CR, LF and CRLF as well as DC1, the latter being typically * used as read trigger when host waits for user input. The parsed * line terminator is recorded for getTerm() availability. */ String readln() { // the implementation of this routine could surely benefit from // a closer analysis regarding source code clarity as well as low // resource overhead, but as said before, this is "quick & dirty" // especially the handling of IOException needs more work... if (back) { if (DEBUG) System.out.println("[again] " + line); back = false; return line; } line = null; int len = buf.length(); int pos = 0; while (line == null) { if (pos < len) { String tmp; switch (buf.charAt(pos)) { case CR: tmp = new String(buf); line = tmp.substring(0,pos); if (pos+1 < len && buf.charAt(pos+1) == LF) { term = "CRLF"; ++pos; } else { term = "CR"; } if (pos+1 < len) { buf = new StringBuffer(tmp.substring(pos+1)); } else { buf = new StringBuffer(); } break; case LF: tmp = new String(buf); line = tmp.substring(0,pos); term = "LF"; if (pos+1 < len) { buf = new StringBuffer(tmp.substring(pos+1)); } else { buf = new StringBuffer(); } break; case DC1: tmp = new String(buf); line = tmp.substring(0,pos); term = "DC1"; if (pos+1 < len) { buf = new StringBuffer(tmp.substring(pos+1)); } else { buf = new StringBuffer(); } break; default: ++pos; } } else { try { if (! LOCAL) buf.append(new String(tio.receive())); else { byte[] aux = new byte[72]; int got = System.in.read(aux, 0, 72); buf.append(new String(aux, 0, got)); } len = buf.length(); } catch (IOException e) { System.out.println("HostIO.readln: " + e); line = "???"; term = "???"; } } } if (DEBUG) System.out.println(line); back = false; return line; } /** * Set pushBack flag so that next readln() returns same line again. */ void pushBack() { back = true; } /** * The most recently parsed line returned by readln(). */ String getLine() { return line; } /** * The terminator(s) found when collecting the most recent line. */ String getTerm() { return term; } /** * Send a line to the host (with CR+LF) to emulate user input. */ void writeln(String x) { // the handling of IOException needs more work here as well... try { if (DEBUG) System.out.println(x); String tmp = x + CR + LF; if (! LOCAL) tio.send(tmp.getBytes()); } catch (IOException e) { System.out.println("HostIO.writeln: " + e); } } /** * Convenience method to skip and ignore host output. */ void skipLines (int count) { for (int k=0; k < count; k++) readln(); } /** * Convenience method to skip scanning for specific line of host output. */ void skipUntilEquals (String x) { while (! readln().equals(x)) { /* eat */ } } /** * Convenience method to skip scanning for specific line of host output. */ void skipUntilStartsWith (String x) { while (! readln().startsWith(x)) { /* eat */ } } /** * Convenience method to skip scanning for specific line of host output. */ void skipUntilEndsWith (String x) { while (! readln().endsWith(x)) { /* eat */ } } /** * Convenience method to skip to a given prompt and emulate user input. */ void answerTo(String prompt, String answer) { skipUntilEquals(prompt); writeln(answer); } }