Terminal I/O


Terminal handler for x/84

class x84.terminal.Terminal(kind, stream, rows, columns)[source]

Bases: blessed.terminal.Terminal

A thin wrapper over blessed.Terminal.

Class initializer.


Dummy method yields nothing for blessed compatibility.


Read, decode, and return the next byte from the keyboard stream.

Return type:unicode
Returns:a single unicode character, or u'' if a multi-byte sequence has not yet been fully received.

This method name and behavior mimics curses getch(void), and it supports inkey(), reading only one byte from the keyboard string at a time. This method should always return without blocking if called after kbhit() has returned True.

Implementors of alternate input stream methods should override this method.

inkey(timeout=None, esc_delay=0.35, *_)[source]

Read and return the next keyboard event within given timeout.

Generally, this should be used inside the raw() context manager.

  • timeout (float) – Number of seconds to wait for a keystroke before returning. When None (default), this method may block indefinitely.
  • esc_delay (float) – To distinguish between the keystroke of KEY_ESCAPE, and sequences beginning with escape, the parameter esc_delay specifies the amount of time after receiving escape (chr(27)) to seek for the completion of an application key before returning a Keystroke instance for KEY_ESCAPE.
Return type:



Keystroke, which may be empty (u'') if timeout is specified and keystroke is not received.


When used without the context manager cbreak(), or raw(), sys.__stdin__ remains line-buffered, and this function will block until the return key is pressed!


Dummy property always returns True.

kbhit(timeout=0, *_)[source]

Return whether a keypress has been detected on the keyboard.

This method is used by inkey() to determine if a byte may be read using getch() without blocking. The standard implementation simply uses the select.select() call on stdin.

Parameters:timeout (float) – When timeout is 0, this call is non-blocking, otherwise blocking indefinitely until keypress is detected when None (default). When timeout is a positive number, returns after timeout seconds have elapsed (float).
Return type:bool
Returns:True if a keypress is awaiting to be read on the keyboard attached to this terminal. When input is not a terminal, False is always returned.

Dummy method yields nothing for blessed compatibility.


Session associated with this terminal.


Set or change incremental decoder for keyboard input.

class x84.terminal.TerminalProcess(client, sid, master_pipes)[source]

Bases: object

Class record for tracking “terminals”.

Probably of most interest, is that a TerminalProcess is an abstract association with a multiprocessing.Process sub-process, and its i/o queues (master_pipes).

This is not a really tty, or even a pseudo-tty (pty)! No termios, fnctl, or any terminal driver i/o is performed, it is all virtual.

An instance of this class is stored using register_tty() and removed by unregister_tty(), and discovered using get_terminals().

Class constructor.


Determine and return preferred encoding given session env.


Given a client, return a matching tty, or None if not registered.


Flush all data awaiting on the ipc queue.

Seeks any remaining events in queue, used before closing to prevent zombie processes with IPC waiting to be picked up.


Returns a list of all terminals as tuples (session-id, ttys).

x84.terminal.init_term(writer, env)[source]

Determine the final TERM and encoding and return a Terminal.

curses is initialized using the value of ‘TERM’ of dictionary env, as well as a starting window size of ‘LINES’ and ‘COLUMNS’. If the terminal-type is of ‘ansi’ or ‘ansi-bbs’, then the cp437 encoding is assumed; otherwise ‘utf8’.

A blessed-abstracted curses terminal is returned.

x84.terminal.kill_session(client, reason='killed')[source]

Given a client, shutdown its socket and signal subprocess exit.


Callback for telnet NAWS negotiation.

On a Telnet NAWS sub-negotiation, check if client is yet registered in registry, and if so, send a ‘refresh’ event down the event queue.

This is ultimately handled by x84.bbs.session.Session.buffer_event().


Register a TerminalProcess instance.

x84.terminal.spawn_client_session(client, matrix_kwargs=None)[source]

Spawn sub-process for connecting client.


x84.terminal.start_process(sid, env, CFG, child_pipes, kind, addrport, matrix_args=None, matrix_kwargs=None)[source]

A multiprocessing.Process target.

  • sid (str) – string describing session source (IP address & port).
  • env (dict) – dictionary of client environment variables (must contain at least 'TERM').
  • CFG (ConfigParser.ConfigParser) – bbs configuration
  • child_pipes (tuple) – tuple of (writer, reader) for engine IPC.
  • kind (str) – what kind of connection as string, 'telnet', 'ssh', etc.
  • addrport (tuple) – (client-ip, client-port) as string and integer.
  • matrix_args (tuple) – optional positional arguments to pass to matrix script.
  • matrix_kwargs (dict) – optional keyward arguments to pass to matrix script.

Return preferred terminal type given the session-negotiation ttype.

This provides a kind of coercion; we know some terminals, such as SyncTerm report a terminal type of ‘ansi’ – however, the author publishes a termcap database for ‘ansi-bbs’ which he instructs should be used! So an [system] configuration item of termcap-ansi may be set to 'ansi-bbs' to coerce such terminals for Syncterm-centric telnet servers – though I would not recommend it.

Furthermore, if the ttype is (literally) ‘unknown’, then a system-wide default terminal type may be returned, also by [system] configuration option termcap-unknown.


Unregister a TerminalProcess instance.