Unix programs are generally written to beterminal-independent: they don't know about or rely on the specific characteristics of any particular kind ofterminal, but rather, they call a standard screen manipulation library that is responsible for interfacing to actual terminals. Such libraries serve to map general terminal characteristics and functions (e.g., clearing the screen) to the specific character sequences required to perform them on any specific terminal.
Terminal definitions are stored in databases on the system, and users indicate what kind of terminal they are using by setting the TERM environment variable (usually at login time). These databases are handled differently under BSD and System V and are the subject of the next section.
12.2.1 termcap and terminfo
Programs use the name specified in the TERM environment variable as a key into the system terminal definitions database. Under the BSD scheme, terminal definitions are stored in the file /etc/termcap ; under System V, they are stored in the subdirectories of the terminfo top-level subdirectory. Some systems provide both facilities:
This section provides a brief overview of termcap and terminfo entries. See the Nutshell Handbook termcap & terminfo, by John Strang, Linda Mui, and Tim O'Reilly (O'Reilly & Associates), for detailed information about the Unix terminal definition databases and modifying or writing entries.
188.8.131.52 termcap entries
The BSD termcap database is a text file consisting of a series of entries that describe how different terminals function. Here is a sample entry for a VT100 terminal:
d0|vt100|vt100am|dec vt100:\ :co#80:li#24:am:ho=\E[H:\ :ku=\EOA:kd=\EOB:
This sample entry is much shorter than an actual entry, but it will serve to illustrate the features of termcap entries. The first line is a series of aliases for the terminal type. Any entry without a space can be used as the value of the TERM environment variable. The remainder of the entry is a colon-separated series of capability codes and values. There are several kinds of capabilities. They can specify:
On FreeBSD systems, you must run the following command after modifying the termcap file:
# cap_mkdb /usr/share/misc/termcap
184.108.40.206 terminfo entries
The System V terminfo database is a series of binary files describing terminal capabilities. Each entry is a separate file in the subdirectory of the main terminfo location that is named for the first letter of its name: e.g., the terminfo entry for a VT100 is stored in the file terminfo/v/vt100. terminfo entries are compiled from source code vaguely similar to termcap. Here is the equivalent terminfo source code for the sample termcap entry for the VT100:
vt100|vt100am|dec vt100, am, cols#80, lines#24, home=\E[H, kcud1=\EOB, kcuu1=\EOA,
The following commands are available for manipulating terminfo entries:
220.127.116.11 Modifying entries
If you need to change a termcap entry, you just have to edit /etc/termcap; to change a terminfo entry, list its source with infocmp, edit the source, and then recompile it with tic. In either case, it's wise to test the new entry by installing it under a slightly different name (vt100t for example) rather than merely replacing the old one. The easiest way to create a new entry is usually to find an existing one for a similar device and then rename and modify it for the new terminal type.
The terminfo commands listed previously are useful not only for modifying terminfo entries or creating new ones but also whenever you need to convert an entry from one format to the other. For example, I wanted to use an old terminal I had on an AIX system, but the system had no terminfo entry for it. However, I was able to find a termcap entry for it on a BSD system, so all I had to do was extract the entry into a separate file, ship it to the AIX system, run captoinfo on it, and then compile the result with tic.
Users can specify an alternate termcap or terminfo database with the TERMCAP and TERMINFO environment variables. If their value is a filename, that file (TERMCAP) or directory (TERMINFO) will be used instead of the usual location. In the latter case, the named directory must contain subdirectories named for the first letter of the entries they hold, just as the standard location does. Thus, if TERMINFO is set to /home/chavez/terminfo and TERM is set to etchasketch, the file /home/chavez/terminfo/e/etchasketch must be a compiled terminfo entry for that device type.
The TERMCAP environment variable can also be used to pre-retrieve a termcap entry; this feature is discussed in the next subsection.
12.2.2 The tset Command
Once a user has set the terminal type with theTERM environment variable, the tset command can be used to initialize the terminal. Without arguments, tset sets basic terminal properties to common default values, including setting the erase, kill, and interrupt characters, and sending any appropriate initialization sequences for that terminal type. tset is traditionally included in default user initialization files when the user's default login location is a terminal.
Although it's most often used without options, tset is actually a very versatile utility. For example, it can prompt for the terminal type if desired by using its -m option. For example, the following command prompts the user for the terminal type, supplying vt100 as a default, and then initializes the terminal:
$ tset -m ":?vt100" TERM = (vt100)
If the user enters a carriage return, tset will use vt100 as the terminal type; otherwise, it will use whatever type the user enters. In either case, tset will then initialize the terminal accordingly. Instead of vt100, you can enter any terminal type that your system supports.
You can use tset to prompt for and set the TERM variable by including its hyphen option, which directs tset to echo the terminal type to standard output:
$ TERM=`tset - -Q -m ":?vt100"` Bourne and Korn shells $ export TERM % setenv TERM `tset - -Q -m ":?vt100"` C shell
The -Q option suppresses the normal messages tset prints out.
On BSD-based systems, tset can also be used to set the TERMCAP environment variable. When used this way, the entire termcap entry corresponding to the type named in the TERM variable becomes the value of the TERMCAP variable. Setting TERMCAP allows programs to start up more quickly, since they don't need to search the termcap database file.
tset's -s option generates the shell commands necessary to set the TERM and TERMCAP environment variables (commands are generated for the shell specified in the SHELL environment variable). There are many ways of executing them; one common way is to use the eval command:
$ eval `tset -sQ -m ":?vt100"`
The tset command in back quotes is executed first. It prompts for the terminal type, initializes the terminal, and then emits the commands necessary to set TERM and TERMCAP, which are executed by eval. These are the commands tset produces for the Bourne shell:
export TERMCAP TERM; TERM=vt100; TERMCAP=`d0|vt100:co#80:li#24:am:ho=\E[H: . . .';
Another way to execute the emitted commands is to capture them in a file, which is then source'd (in the C shell):
tset -sQ -m ":?vt100" >! ~/.tmpfile source ~/.tmpfile rm ~/.tmpfile
These are the commands as they might appear in a user initialization file. They can also be kept in a separate file, to be source'd whenever it is necessary to change the terminal type. The first command prompts for the terminal type and initializes the terminal. The remaining commands generate and execute setenv commands for TERM and TERMCAP, and then finally delete the temporary file.
What's in the temporary file? Assuming that the user selects the terminal type vt100 (i.e., assuming that she selects the default that tset suggests), ~/.tmpfile will look like this:
set noglob; setenv TERM vt100; setenv TERMCAP 'd0|vt100:co#80:li#24:am:ho=\E[H: ... '; unset noglob;
The set noglob command turns off shell interpretation for the special characters (asterisks and so on) that are commonly used in termcap entries. Note that if something goes wrong with this sequence of commands, unsetnoglob will never be executed, and the user will get a shell in which shell wildcards don't work. This is rare, but it's certainly confusing.
12.2.3 The stty Command
While tset performs type-specific terminal initialization, the stty command can be used to specify generic terminal and terminal line characteristics (such as parity). Its general syntax is:
$ stty option [value ]
Not all options require values. stty's options are not preceded by hyphens, although some options have a hyphen as the first character of their name. Options often come in pairs like echo and -echo where the second form means the negative of the first (in this case "no echo").
stty has a large number of options; the most useful are listed in Table 12-2.
For example, the werase option tells stty which character, when typed, should erase the previous word. By default, it's Ctrl-W. (Try it; many Unix users aren't even aware that this feature exists.) Likewise, the reprint option tells stty which character, when typed, will make the system reprint the line you're currently typing. The sane option just might help you to restore normal functioning if you accidentally do something that confuses your terminal.
Among the most useful stty options is erase, which defines the control sequence that erases the previous character (performed by the Delete or Backspace key). If the key is echoed as ^H or ^? instead of removing the previous character:
A command like the following will fix it:
$ stty erase ^h
This command sets the erase character to Ctrl-H, the sequence emitted by the Backspace key. You can type the desired keystroke in as erase's argument or use the symbolic form: the caret character followed by the appropriate letter for that control sequence. Case does not matter, and this symbolic form may be used for any stty option requiring a character as its value. The code for the Delete key is ^?.
When a terminal has become hopelessly messed up and won't respond to anything, the following command sequence may help:
This has the effect of clearing out any junk remaining around in the terminal's buffer and then resetting the terminal to a set of safe settings.
The stty -a command may be used to display the current terminal settings:
$ stty -a speed 38400 baud; rows 40; columns 80; line = 0; intr = ^C; quit = ^\; erase = ^?; kill = ^U; eof = ^D; eol = <undef>; eol2 = <undef>; start = ^Q; stop = ^S; susp = ^Z; rprnt = ^R; werase = ^W; lnext = ^V; flush = ^O; min = 1; time = 0; -parenb -parodd cs8 -hupcl -cstopb cread -clocal -crtscts -ignbrk brkint -ignpar -parmrk -inpck -istrip -inlcr -igncr icrnl ixon -ixoff -iuclc -ixany imaxbel opost -olcuc -ocrnl onlcr -onocr -onlret -ofill -ofdel nl0 cr0 tab0 bs0 vt0 ff0 isig icanon iexten echo echoe echok -echonl -noflsh -xcase -tostop -echoprt echoctl echoke
stty and the terminal characteristics databases provide complementary information. termcap and terminfo provide generic information about all terminals of a given type, while stty -a provides information about the current setting of options that are, for the most part, supported by many terminals. For example, the vt100 entries provide fairly complete information about the features specific to VT100 terminals. However, by themselves, termcap, terminfo, and tset do not support users who like or require particular terminal options for example, users who like "#" as an erase character (a feature of very, very old Unix systems) or whose modem only runs at 9600 baud. stty controls the TTY device driver, and thus it allows a user to specify options like these. It can be particularly useful when a user logs in to another system remotely; in this situation, the properties of the remote connection often don't correspond exactly to the default settings and must be explicitly changed.