Interface TerminalService
These are perhaps better described as XTerm clones. It seems the term "VT100" is applied to any
text display that interprets some number of ANSI escape codes. While the XTerm documentation does
a decent job of listing which VT version (or Tektronix, or whatever terminal) that introduced or
specified each code/sequence in the last 6 or so decades, applications don't really seem to care
about the details. You set TERM=xterm
, and they just use whatever codes the feel like.
Some make more conservative assumptions than others. For example, there is an escape sequence to
insert a blank character, shifting the remaining characters in the line to the right. Despite
using this, Bash (or perhaps Readline) will still re-send the remaining characters, just in case.
It seems over the years, in an effort to be compatible with as many applications as possible,
terminal emulators have implemented more and more escape codes, many of which were invented by
XTerm, and some of which result from mis-reading documentation and/or replicating erroneous
implementations.
Perhaps our interpretation of the history is jaded, and as we learn more, our implementation can
become more disciplined, but as it stands, our TerminalPlugin
takes the ad hoc
approach: We've implemented the sequences we need to make it compatible with the applications we
intend to run, hoping that the resulting feature set will work with many others. It will likely
need patching to add missing features over its lifetime. We make extensive use of the
XTerm control sequence
documentation, as well as the
Wikipedia article on ANSI escape
codes. Where the documentation lacks specificity or otherwise seems incorrect, we experiment
with a reference implementation to discern and replicate its behavior. The clearest way we know
to do this is to run the tty
command from the reference terminal to get its
pseudo-terminal (pty) file name. Then, we use Python from a separate terminal to write test
sequences to it and/or read sequences from it. We use the sleep
command to prevent Bash
from reading its own terminal. This same process is applied to test our implementation.
The applications we've tested with include, without regard to version:
bash
less
vim
gdb -tui
termmines
(from our Debugger training exercises)
Some known issues:
- It seems Java does not provide all the key modifier information, esp., the meta key. Either that or Ghidra's intercepting them. Thus, we can't encode those modifiers.
- Many control sequences are not implemented. They're intentionally left to be implemented on an as-needed basis.
- We inherit many of the erroneous key encodings, e.g., for F1-F4, present in the reference implementation.
- Character sets are incomplete. The box/line drawing set is most important to us as it's used
by
gdb -tui
. Historically, these charsets are used to encode international characters. Modern systems (and terminal emulators) support Unicode (though perhaps only UTF-8), but it's not obvious how that interacts with the legacy charset switching. It's also likely many applications, despite UTF-8 being available, will still use the legacy charset switching, esp., for box drawing. Furthermore, because it's tedious work to figure the mapping for every character in a charset, we've only cared to implement a portion of the box-drawing charset, and it's sorely incomplete.
-
Method Summary
Modifier and TypeMethodDescriptionvoid
Remove all terminals whose sessions have terminated from the toolcreateNullTerminal
(Plugin helpPlugin, Charset charset, ghidra.app.plugin.core.terminal.vt.VtOutput outputCb) Create a terminal not connected to any particular application.createNullTerminal
(Charset charset, ghidra.app.plugin.core.terminal.vt.VtOutput outputCb) createWithStreams
(Plugin helpPlugin, Charset charset, InputStream in, OutputStream out) Create a terminal connected to the application (or pty session) via the given streams.createWithStreams
(Charset charset, InputStream in, OutputStream out)
-
Method Details
-
createNullTerminal
Terminal createNullTerminal(Plugin helpPlugin, Charset charset, ghidra.app.plugin.core.terminal.vt.VtOutput outputCb) Create a terminal not connected to any particular application.To display application output, use
Terminal.injectDisplayOutput(java.nio.ByteBuffer)
. Application input is delivered to the given terminal output callback. If the application is connected via streams, esp., those from a pty, consider usingcreateWithStreams(Plugin, Charset, InputStream, OutputStream)
, instead.- Parameters:
helpPlugin
- the invoking plugin, which ought to provide a help topic for this terminal.charset
- the character set for the terminal. See note increateWithStreams(Plugin, Charset, InputStream, OutputStream)
.outputCb
- callback for output from the terminal, i.e., the application's input.- Returns:
- the terminal
-
createNullTerminal
- Parameters:
charset
- the character set for the terminal. See note increateWithStreams(Plugin, Charset, InputStream, OutputStream)
.outputCb
- callback for output from the terminal, i.e., the application's input.- Returns:
- the terminal
- See Also:
-
createWithStreams
Create a terminal connected to the application (or pty session) via the given streams.- Parameters:
helpPlugin
- the invoking plugin, which ought to provide a help topic for this terminal.charset
- the character set for the terminal. NOTE: Only US-ASCII and UTF-8 have been tested. So long as the bytes 0x00-0x7f map one-to-one with characters with the same code point, it'll probably work. Charsets that require more than one byte to decode those characters will almost certainly break things.in
- the application's output, i.e., input for the terminal to display.out
- the application's input, i.e., output from the terminal's keyboard and mouse.- Returns:
- the terminal
-
createWithStreams
- Parameters:
charset
- the character set for the terminal. NOTE: Only US-ASCII and UTF-8 have been tested. So long as the bytes 0x00-0x7f map one-to-one with characters with the same code point, it'll probably work. Charsets that require more than one byte to decode those characters will almost certainly break things.in
- the application's output, i.e., input for the terminal to display.out
- the application's input, i.e., output from the terminal's keyboard and mouse.- Returns:
- the terminal
- See Also:
-
cleanTerminated
void cleanTerminated()Remove all terminals whose sessions have terminated from the toolThis is done automatically when creating any new terminal.
-