How to send control chars using ExpectJ in interactive mode?

247 views Asked by At

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);
    }
}
0

There are 0 answers