If you always work at the same terminal or use the same terminal emulator, there's no problem with setting the terminal type explicitly in your shell setup file (Section 3.3) -- like .login or .profile. Just set the TERM environment variable (Section 35.3):
setenv TERM vt100 ...csh, tcsh TERM=vt100; export TERM ...sh, ksh, zsh export TERM=vt100 ...pdksh, bash, zsh
In fact, on a hardwired terminal, your terminal type may already have been set in a system file like /etc/ttys or /etc/ttytype (Section 3.15). But if, like many Unix users, you might log in from time to time at different terminals, from home, or on different systems over a network, you may need some more intelligent method for setting the terminal type. To find out, try logging in at each place and starting a screen-oriented program like vi. Do various operations: scrolling up, inserting text that wraps onto another line, deleting lines. If the screen scrambles or the cursor gets "out of sync," your terminal type may need to be set.
It's possible to set up various tests (Section 3.10) in your shell setup files to do this. But you can also do a surprising amount of terminal type testing with tset, even though it was nominally designed for initializing the terminal:
If no arguments (Section 1.4) are specified and TERM is already set, tset uses the value of TERM to determine the terminal type.
If no arguments are specified and TERM is not set, then tset uses the value specified in the system file /etc/ttytype or /etc/ttys (BSD 4.3 and later and its derivatives only). On Linux systems, the terminal type is determined by getty, based on a similar process but using the /etc/inittab file or other configuration files used by getty during initialization. On SVR4 systems, a similar process is managed by ttymon and listen.[16]
[16]getty is spawned by the init at multiuser system startup, and it sets up all ttys, handles the initial login prompt, and then hands successful logins over to login to complete.
If a terminal type is specified as an argument, that argument is used as the terminal type, regardless of the value of TERM.
The -m (map) option allows a fine degree of control in cases where the terminal type may be ambiguous. For example, if you sometimes log in on a dialup line, sometimes over a local area network, and sometimes on a hardwired line, the -m option can be specified to determine which login is currently being used, and the terminal type can be set accordingly.
In Bourne-type shells, tset can be used to set the value of TERM as follows:
export TERM=`tset - -Q options` ...newer shells TERM=`tset - -Q options`; export TERM ...all shells
(Given the - option, tset prints the value determined for the terminal type to standard output (Section 43.1). Otherwise, it initializes the terminal (Section 5.3), but keeps the terminal type to itself. The -Q (quiet) option causes tset to suppress printing a message it normally prints regarding the values set for the erase and kill characters -- a job it does in its alternate role as terminal initializer. The backquotes (Section 28.14) surrounding the tset command interpolate its output into the command line.)
In the C shell, you should use the eval (Section 27.8) command to capture the output of tset; this will also allow you to set the TERMCAP variable (Section 35.5). (You must also issue the command set noglob.) To simplify the rest of this article, we'll show examples for the C shell; if you don't use a C-type shell, please translate to Bourne-shell syntax (as shown earlier).
To see what tset can do, consider a case where the terminal's serial line is connected to a dialup modem, through which several different users might be connected, each using a different type of terminal. Accordingly, the default terminal type in /etc/ttytype or /etc/ttys should be set to dialup. The tset command could then be used in the .login file as follows, with the appropriate terminal type set for each user:
set noglob eval `tset -s -Q -m 'dialup:vt100'`
This means that if ttytype says dialup, use vt100 as the terminal type. A colon separates the ttytype value and the value to which it is to be mapped. If a user wants to be prompted to be sure, place a question mark after the colon and before the mapped terminal type:
set noglob eval `tset -s -Q -m 'dialup:?vt100'`
The prompt will look like this:
TERM = (vt100)
If the user presses RETURN, the preferred terminal type will be used. Alternately, another terminal type could be entered at that time.
You can cause tset to prompt for a terminal type even without testing a generic entry like dialup. Just specify the desired terminal type, preceded by a question mark, after the -m option. For example:
set noglob eval `tset -s -Q -m '?vt100'`
It is also possible to specify different terminal types for different line speeds. For example, say that you normally used a Wyse-50 with a 9600-bps modem when dialing in from home, but used a portable PC with a VT100 terminal emulator and 2400-bps modem on the road.[17] You might then use a tset command like this:
[17]Sure, you don't have to worry about whether there is a local TYMNET dialup nowadays, but back in the day . . .
set noglob eval `tset -s -Q -m 'dialup@2400:vt100' wy50`
Assuming that the type is set in /etc/ttys or /etc/ttytype as dialup, tset will use the type vt100 if at 2400 bps and, if not, will use the type wy50. See the tset(1) manual page for more choices. Watch out for the line-speed switches. They don't work on a lot of networked systems -- usually, the line speed at the computer's port is higher than the speed at the terminal. The same problem occurs with dialup modems that use data compression. The stty command will tell you what data rate the system believes you're using.
Multiple -m options can be specified; the first map to be satisfied will be used. If no match is found, a final value specified on the line without a -m option (as in the previous example) will be used. If no value is specified, the type in /etc/ttytype or /etc/ttys will be used.
--TOR and SJC
Copyright © 2003 O'Reilly & Associates. All rights reserved.