The Linux console normally imitates a serial terminal. By writing special character sequences to the console device, you control all aspects of the screen presentation. You will usually use S-Lang, curses, or some other screen-drawing library to draw to the screen; they use these escape sequences. The console can also be read and modified through an alternative full-screen interface, which is particularly useful for some specialized programs.
DOS programmers introduced for the first time to Linux programming often are dismayed to find that writing characters to the screen is not a simple matter of initializing a pointer to the address of the screen in memory and writing blindly through it. Some complain loudly about this “backwards” system that forces them to pretend that they are writing to a serial terminal, writing escape sequences in between the characters that are written to the screen to control cursor movement, color, screen clearing, and so on.
There are several good reasons to treat the console as a fancy serial terminal. Not the least is that when the program is being run on a serial terminal, it still works. More important—in these Internet-conscious times—the program runs correctly across networks and—in these GUI-conscious times—the program runs correctly in a terminal emulator window under X or any other GUI. Furthermore, programs that are run remotely, either via a network or a serial connection, display properly on your console.
Furthermore, you will find that the escape codes are a reasonable low-level interface to the screen, and they are a good base on which to build higher-level primitives, such as curses, documented in Programming with curses [Strang, 1991A]. This is no accident; serial terminals are a venerable technology, fine-tuned over the years in response to programmers’ real needs. The Linux console is based on the most popular family of serial terminals, the descendants of the DEC VT100.
Most escape sequences use the ANSI escape character, which has no convenient printed representation. We follow the termcap and terminfo libraries in using ^[
to denote the ANSI escape character; be aware when reading them that they sometimes refer to the same character as E
. As elsewhere in this book, as well as in termcap and terminfo, ^
C
indicates the Control-C character.
The actions controlled by these escape sequences are often called capabilities. Some escape sequences are shared among many terminals, and many of those sequences are specified in the ANSI X3.64-1979 standard. Nearly all color-capable terminals use the same sequences to choose colors to display. However, many terminals have wildly different escape sequences. For instance, on a Wyse 30 terminal, pressing F1 sends the sequence ^A@
, whereas pressing F1 on your Linux console sends the sequence ^[[[A
. Similarly, to move the cursor up on a Wyse 30, you send it a ^K
character; to move the cursor up on the Linux console, send the ^[[A
sequence. To write a program that can work on either terminal, you clearly need a way to abstract these differences, which would allow you to program with the capabilities rather than the raw character sequences.
The most common programming library that provides this abstraction is called curses,[1] documented in Programming with curses [Strang, 1991A]. It has two important conceptual levels. The first level provides functions that (generally speaking) send one escape sequence to accomplish one action, such as move the cursor up, move it down, scroll the screen, and so on. The second level provides a concept of “windows": independent screen areas that can be manipulated separately, with curses quietly figuring out the shortest character sequences to send to effect the changes you request.
The curses library determines which sequences to send to the terminal by consulting a database that, for each terminal, maps capability names to the strings that need to be sent.
Linux, like all modern Unix systems, provides two databases that describe terminals in terms of the capabilities they possess and which escape sequences map to which capabilities. The older database is called termcap (short for terminal capabilities) and is kept in one large ASCII flat file called /etc/termcap. This file has become unwieldy; it has grown to approximately half a megabyte. The newer database is called terminfo (short for terminal information) and is kept in many binary files, one per terminal, normally in subdirectories of the /usr/lib/terminfo directory.
Within each database, the capability information for each terminal is indexed by one or more unique names. Both databases use the same name for the same terminal. For instance, the Linux console is called linux
in both termcap and terminfo. You tell programs which terminal entry to use by setting the TERM
environment variable. When writing programs that use termcap and terminfo, you rarely need to look at the TERM
environment variable; usually, the low-level libraries for accessing the termcap or terminfo databases automatically take care of that.
However, if you wish to do Linux-specific optimizations, especially if you want to use some of Linux’s unusual capabilities that are not described in the capability databases, you can check the TERM
environment variable with code like this:
if (!strcmp("linux", getenv("TERM"))) { /* should be a Linux console */ } else { /* handle as a normal serial terminal */ }
Also, if you wish to write programs in programming languages without easy access to curses or some other terminal abstraction library, you may find it convenient to use this documentation.
Of course, that your terminal type is linux
does not guarantee that your program is running on a local terminal. If the terminal type is linux
, you know you have access to the escape sequences documented in this chapter, but you do not know if you have access to the vcs devices (documented later in this chapter) or ioctl()
s. POSIX specifies a ttyname()
function that you can use to find the name of the device file for the controlling terminal. On a Linux system, the virtual consoles are named /dev/ttyn for n between 1 and 63 (/dev/tty0 is always the current console).
Complete documentation for the termcap and terminfo systems is available in termcap & terminfo [Strang, 1991B]. Eric Raymond currently maintains the termcap and terminfo databases, which he makes available via the Web at http://www.ccil.org/~esr/terminfo/ The source code to ncurses (new curses, the implementation of curses used on Linux) includes an introduction to curses programming in the misc/ncurses-intro.html file.
When you write a character to any terminal, several steps of translation may happen. The value written to the terminal is the character number, or character code. That character code is not enough to determine what to display on the screen, however. The shape depends on what font is being used. The character code 97 may be printed as an a
in a font designed for rendering Latin-based languages, but might be rendered as an in a font designed for rendering Greek or mathematics. The shape that is displayed is called a glyph. The translation from character codes to glyphs is called a map.
The Linux console,[2] like most terminals, is modal: Its response to data depends on what mode it is in. By default, it prints on the screen the characters you send to it unless it receives an escape or control character. A control character simply causes some control action to be taken, but the next character is read normally; there is no change in processing mode. An escape character signals the beginning of an escape sequence and changes the processing mode to escape mode.
For example, consider the following C string:
"this is a line a 33[1mbold 33[0m word "
The console processes the string in the following sequence:
Starting from the current cursor position, the console prints the words “this is a line
“.
It encounters the linefeed (
) control character, so (because Linux and Unix traditionally operate in a mode in which a linefeed signals a carriage return, as well) it moves the cursor to the beginning of the next line, scrolling the whole display up one line if the cursor was already on the bottom line.
It displays the string “a
” at the beginning of that line.
It encounters the escape character, “