1

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);
    }
}
Leo
  • 6,480
  • 4
  • 37
  • 52

0 Answers0