A headless terminal emulator (ANSI / VT100) in C89
Switch branches/tags
Nothing to show
Clone or download

README.md

vt100 emulator

vt100-emulator is a headless vt100 emulator, a bit like any terminal you may use daily (like urxvt, xterm, ...) but those you're using are NOT headless, they have a graphical interface to interact with you, human). Here, vt100-emulator is only the underlying a C and Python API to an actual emulator, so you can do everything you want with it, like interfacing over TCP, HTTP, automatically testing your implementation malloc against top while running top in the headless terminal, whatever pleases you.

For copyright information, please see the file COPYRIGHT in this directory or in the files of the source tree.

INSTALL

Python module

You'll need swig, so apt-get install swig or whatever works for you.

Run:

$ make python_module && su -c 'python setup.py install'

Usage using the python wrapper (same methods in C)

>>> import hl_vt100
>>> import threading
>>> class Top:
...     def __init__(self):
...         self.vt100 = hl_vt100.vt100_headless()
...         self.vt100.fork('top', ['top'])
...
...     def __call__(self):
...         self.vt100.main_loop()
...
...     def __str__(self):
...         return "\n".join(self.vt100.getlines())
...
>>> top = Top()
>>> thread = threading.Thread(target=top)
>>> thread.start()
>>> print(top)
top - 09:42:43 up 332 days, 23:42, 14 users,  load average: 3.08, 3.41, 3.52
KiB Mem:  16443168 total, 15865172 used,   577996 free,  1141216 buffers
KiB Swap:   999420 total,   669960 used,   329460 free.  6097952 cached Mem

  PID USER      PR  NI    VIRT    RES    SHR S  %CPU %MEM     TIME+ COMMAND
24237 nobody    20   0 1041352 348040  39116 R  78.8  2.1 142:18.54 redacted
24078 nobody    20   0 1152024 382592  38948 R  25.8  2.3 355:44.85 for
24892 nobody    20   0 1182408 434560  40276 S  21.1  2.6 394:06.48 privacy
24472 nobody    20   0 1153196 380712  39000 S  20.3  2.3 410:51.64 ayah
23617 nobody    20   0  170048 100072   6376 S  19.5  0.6   8:36.66 python
23646 nobody    20   0 1095252 367128  39916 R  17.9  2.2 353:48.65 you
23505 nobody    20   0 1159452 377948  38920 S  17.2  2.3 364:29.40 wont
24757 nobody    20   0  943848 216084  40028 R  15.6  1.3 231:10.38 know
23894 nobody    20   0  885740 166600  38724 S  13.3  1.0 195:48.99 what
24689 nobody    20   0  901152 183240  39780 S  13.3  1.1 192:50.13 eats
24820 nobody    20   0  937712 232392  39496 S  13.3  1.4 215:25.32 my_cpu
 3117 nobody    20   0  402568 351740   5912 S   3.1  2.1   0:03.72 python
 3122 mandark   20   0   27052   3040   1184 R   3.1  0.0   0:00.34 top
23796 nobody    20   0 1069940 347252  39156 S   3.1  2.1 190:37.78 probably
23503 nobody    20   0  903592 268248  38360 S   1.6  1.6  75:54.32 somethign
 5169 root      20   0       0      0      0 S   0.8  0.0  45:05.66 kworker/0:1
15324 root      20   0   63848   9768   1628 S   0.8  0.1 437:02.99 supervisord
16382 root      20   0       0      0      0 S   0.8  0.0  11:29.88 kworker/2:0
18278 root      20   0       0      0      0 S   0.8  0.0 184:02.23 kworker/1:0

Code overview

lw_terminal_parser, lw_terminal_vt100, and hl_vt100 are three modules used to emulate a vt100 terminal:

                                  -------------
                                  |           |
                                  | Your Code |
                                  |           |
                                  -------------
                                    |      ^
 vt100 = vt100_headless_init()      |      |
 vt100->changed = changed;          |      | hl_vt100 raises 'changed'
 vt100_headless_fork(vt100, ...     |      | when the screen has changed.
                                    |      | You get the content of the screen
                                    |      | calling vt100_headless_getlines.
                                    V      |
                                  -------------              -------------
 Read from PTY master and write | |           |     PTY      |           |
 to lw_terminal_vt100_read_str  | |  hl_vt100 |<------------>|  Program  |
                                V |           |Master   Slave|           |
                                  -------------              -------------
                                   |        |^ hl_vt100 gets lw_terminal_vt100's
                                   |        || lines by calling
                                   |        || lw_terminal_vt100_getlines
                                   |        ||
                                   |        ||
                                   V        V|
                              ----------------------
 Got data from              | |                    | Recieve data from callbacks
 lw_terminal_vt100_read_str | | lw_terminal_vt100  | And store an in-memory
 give it to                 | |                    | state of the vt100 terminal
 lw_terminal_read_str       V ----------------------
                                 |              ^
                                 |              |
                                 |              |
                                 |              |
                                 |              |
                                 |              | Callbacks
                                 |              |
                                 |              |
                                 |              |
                                 |              |
                                 |              |
                                 V              |
                              ----------------------
 Got data from                |                    |
 lw_terminal_pasrser_read_str | lw_terminal_parser |
 parses, and call callbacks   |                    |
                              ----------------------

lw_terminal_parser

lw_terminal_parser parses terminal escape sequences, calling callbacks when a sequence is sucessfully parsed, read example/parse.c.

Provides :

  • struct lw_terminal *lw_terminal_parser_init(void);
  • void lw_terminal_parser_destroy(struct lw_terminal* this);
  • void lw_terminal_parser_default_unimplemented(struct lw_terminal* this, char *seq, char chr);
  • void lw_terminal_parser_read(struct lw_terminal *this, char c);
  • void lw_terminal_parser_read_str(struct lw_terminal *this, char *c);

lw_terminal_vt100

Hooks into a lw_terminal_parser and keep an in-memory state of the screen of a vt100.

Provides :

  • struct lw_terminal_vt100 *lw_terminal_vt100_init(void *user_data, void (*unimplemented)(struct lw_terminal* term_emul, char *seq, char chr));
  • char lw_terminal_vt100_get(struct lw_terminal_vt100 *vt100, unsigned int x, unsigned int y);
  • const char **lw_terminal_vt100_getlines(struct lw_terminal_vt100 *vt100);
  • void lw_terminal_vt100_destroy(struct lw_terminal_vt100 *this);
  • void lw_terminal_vt100_read_str(struct lw_terminal_vt100 *this, char *buffer);

hl_vt100

Forks a program, plug its io to a pseudo terminal and emulate a vt100 using lw_terminal_vt100.

Provides :

  • void vt100_headless_fork(struct vt100_headless *this, const char *progname, char *const argv[]);
  • struct vt100_headless *vt100_headless_init(void);
  • const char **vt100_headless_getlines(struct vt100_headless *this);