I've been using expectJ to automate some administrative tasks over ssh (jsch) for some time. It has been working well.
Now I am facing an interface that accepts commands triggered by control characters. Such as CTRL+B for example.
For non-interactive automation tasks, it works well if I just send the unicode character, like
if (request.contains("<CTRL-B>")){
request = request.replaceAll("<CTRL-B>", "\u0002");
}
The problem is expectJ "interactive mode", which wires stdin and stdout into two thread loops (inside a undocumented class called expectj.StreamPiper
, which does exactly that, pipes from one stream into another).
Running from command line, I just don't know how to send a CTRL-B from Java command line (stdin).
So my question is: how do I send control chars from System.in
to expectJ in interactive mode?
Ps. one workaroud, it seems, is to "remap" these control characters somehow. For example, one command is triggered by a CTRL-Z, but issuing CTRL-Z in a unix environment will immediately send the current process to background. In this case, how could I do that?
update -- I've been using this. I hope there's a better way (I am not talking about refactoring this code, of course). Snippet from expectj.StreamPiper
/**
* Thread method that reads from the stream and writes to the other.
*/
public void run() {
byte[] buffer = new byte[1024];
int bytes_read;
try {
while(getContinueProcessing()) {
bytes_read = inputStream.read(buffer);
if (bytes_read == -1) {
LOG.debug("Stream ended, closing");
inputStream.close();
outputStream.close();
return;
}
String stringRead = new String(buffer, 0, bytes_read);
if (stringRead.startsWith("CTRL+B")) {
outputStream.write("\u0002".getBytes());
sCurrentOut.append("\u0002");
if (copyStream != null && !getPipingPaused()) {
copyStream.write("\u0002".getBytes());
copyStream.flush();
}
}else if (stringRead.startsWith("CTRL+Z")) {
outputStream.write("\u001A".getBytes());
sCurrentOut.append("\u001A");
if (copyStream != null && !getPipingPaused()) {
copyStream.write("\u001A".getBytes());
copyStream.flush();
}
}else if (stringRead.startsWith("CTRL+R")) {
outputStream.write("\u0012".getBytes());
sCurrentOut.append("\u0012");
if (copyStream != null && !getPipingPaused()) {
copyStream.write("\u0012".getBytes());
copyStream.flush();
}
}else if (stringRead.startsWith("CTRL+A")) {
outputStream.write("\u0001".getBytes());
sCurrentOut.append("\u0001");
if (copyStream != null && !getPipingPaused()) {
copyStream.write("\u0001".getBytes());
copyStream.flush();
}
}else {
outputStream.write(buffer, 0, bytes_read);
sCurrentOut.append(new String(buffer, 0, bytes_read));
if (copyStream != null && !getPipingPaused()) {
copyStream.write(buffer, 0, bytes_read);
copyStream.flush();
}
}
outputStream.flush();
}
} catch (IOException e) {
if (getContinueProcessing()) {
LOG.error("Trouble while pushing data between streams", e);
}
} catch(IllegalBlockingModeException ignored){
//LOG.warn("Expected exception, don't worry", ignored);
}
}