Terminal and Keyboard Issues in the UNIX World |
When moving from a mainframe environment with 3270-style terminals to a UNIX-based workstation or network, one of the first issues that confronts the user is an unfamiliar terminal. For users of mainframe-style tools under UNIX, this issue is further complicated by their quite reasonable expectations that a similar key should perform a predictable function, regardless of the terminal type. In other words, a user of uni-XEDIT would expect a key marked "F7" on any keyboard to behave exactly like the key marked "PF7" on a 3270-style terminal.
For the developers of such mainframe style tools, meeting these expectations presents a challenge. In the mainframe environment, all 3270-style terminals, whether manufactured by IBM or from a vendor of plug-compatible products, conform to a single specification. With UNIX workstations, any terminal from any manufacturer may be connected to any workstation. And in some cases, the "terminal" may be, not a physical device, but a program running on a PC or workstation that provides software emulation of certain terminal characteristics. This is, in fact, one element of the concept of open systems -- that components from any vendor can be combined into a system that meets the needs of your particular organization.
This document attempts to address these connectivity issues and to offer some insight into The Workstation Group's approach to solving them in uni-XEDIT and uni-SPF. Perhaps with this insight, the problems of using different terminals and appropriate keyboard mappings will be minimal.
There are numerous manufacturers of ASCII terminals in the hardware marketplace. The VT100 from Digital Equipment Corporation is considered by some to be the de facto standard for a basic ASCII terminal. Its cousin, the VT220, also enjoys considerable popularity. Other hardware manufacturers who sell ASCII terminals include Wyse, Tektronix, Hewlett-Packard, NEC, Televideo, and many, many others.
One of the most popular pieces of software that runs on personal computers is a terminal emulation program that allows the PC, connected through a cable or modem to another CPU, to appear to that host as an ordinary terminal. Terminal emulation programs are available from a variety of software vendors; and there are many in the public domain as well. Most terminal emulation programs provide emulation of the popular VT100 as well as other types of hardware devices.
Still more modern technology, such as Motif, X-Windows, OpenLook and the various vendor implementations of these standards, initiate windows on your physical screen that exhibit the behavior of their own well-defined "terminal" types. A command tool on a Sun, an aixterm window on an RS/6000, or an hpterm window on an HP/9000 workstation are all examples of this technology. Programs such as X11/AT and DesqViewX extend the UNIX GUI technology to the PC world so that your personal computer may actually run these native UNIX tools.
But whether your terminal is physically a monitor from DEC that is labelled VT100, a PC running a program that emulates a VT100, or an aixterm window on the console of an RS/6000 workstation, the host computer sees it as a terminal of a specific type that is "connected" in some manner (physical or logical). The UNIX environment variable TERM reflects what the host computer currently believes that terminal type to be.
The TERM environment variable is set automatically by the login process, and this is normally appropriate for Workstation Group products. Specific instances in which you might want to override the automatic determination of your terminal type are discussed in subsequent sections of this document.
[In UNIX, an environment variable is a configuration parameter that describes an individual user's environment to the operating system. Some environment variables are set automatically when you login to the system; their values may be provided by system-wide defaults or by values set in a shell initialization script such as .profile (Korn shell), .login (Bourne shell), or .cshrc (C shell). These initialization scripts may be likened to an AUTOEXEC.BAT file on a PC or a mainframe user profile. You may, however, change the setting of any environment variable at any time by typing an appropriate command at your keyboard.]
Terminal emulation programs present a special set of challenges both to the user and to the developer of products which must interact with them. These fall into two categories:
The ANSI standard definition for an ASCII terminal and the VT100 standard are both well-established and widely used. Regardless of this fact, a terminal emulation program is just that -- software written by humans to simulate the performance of a specific piece of hardware. It is therefore possible that the degree of emulation may vary from one program to another.
A more troublesome problem for some users is the requirement of a terminal emulation program to reserve certain keystrokes for its own program control functions. A terminal emulator program works by receiving a keystroke, determining if it is intended for a program control function, and if not, converting it to the appropriate sequence and transmitting it to the host computer. Most terminal emulators use keystroke combinations (such as Alt in combination with some other key) for program control, thereby attempting to minimize possible collisions between program control functions and key sequences used by the application on the host computer. Some emulators, however, use one or more of the PC's function keys for such purposes. When you press such a key or key combination, it is intercepted and processed by the emulator and never transmitted to the host computer. Thus an application running on the host computer never receives this keystroke and cannot perform the expected action. A terminal emulator program may have installation options that allow you to define a custom configuration or execution options that allow you to override program control defaults.
Regardless of what kind of terminal you use, the process by which your terminal communicates with the host computer is fairly straightforward. When you press a key, the terminal sends a signal to the host. The host processes that signal and sends a signal in response. This response is often the display on the terminal screen of a character or the output of a process. In the mainframe environment, transmission of data to the host occurs only when you press Enter or a Program Function key. UNIX workstations are more like PCs in that the computer responds to each keystroke immediately.
The signal sent by the keyboard is called a keycode or key sequence. For consistency with the documentation of Workstation Group products, this document uses the term key sequence. A key sequence may be a single character (such as the letter "a"), or it may be a more complex sequence of hexadecimal values that can be represented by a group of human-readable characters. Special components of key sequences (such as escape or control) have standard character representations. Escape is always represented as "\e" or "\E"; control is always represented as "^"; octal values that have no character equivalent are always preceded by the "\" character; and so forth. Examples of key sequences are
Key pressed Key sequence transmitted a a Delete on a Sun Type 4 keyboard \177 (Octal 177) F3 on a Sun Type 4 keyboard \e[226z
It is possible that a key does not transmit a key sequence to the host. This is most likely if you are running a terminal emulator program and the program does not contain a software translation of the key you pressed to its functional equivalent for the terminal you are emulating. For example, you may be running a terminal emulator program on your PC and emulating a "blotz123" terminal. Your PC has an F3 key and you want to use it as PF3 in the host application. However, your terminal emulator program sets the translation of the PC's F3 keystroke to null in its translate table for the "blotz123" terminal. Thus, when you press F3 on your PC keyboard, the emulator sends null -- or nothing -- to the host. The host application therefore does not know that you tried to send it a "PF3" instruction.
It is also possible that two keys (or key combinations) will send an identical sequence. As an example, the aixterm on the RS/6000 sends the sequence "\t" for both Tab (the tab key) and Backtab (the Shift-Tab combination). The host application therefore cannot distinguish between these two keystrokes and performs the Tab function, regardless of whether you press Tab or Shift-Tab.
Terminal I/O does not present a particular problem to the developer of a host application in the area of such keys as alphanumerics, Return, Tab, and Backspace because these keys have standard, simple key sequences regardless of the terminal type. The challenge arises in the area of special keys such as cursor arrow keys, function keys, and specially marked keys such as Insert, Delete, End, Page Up, or Page Down. Consider the following variations among just three terminal types:
Key Terminal Type Key Sequence Up arrow VT100
VT220
Wyse 50\EOA
\E[A
^KDown arrow VT100
VT220
Wyse 50\EOB
\E[B
\nLeft arrow VT100
VT220
Wyse 50\EOD
\E[D
\bRight arrow VT100
VT220
Wyse 50\EOC
\E[C
\fF7 VT100
VT220
Wyse 50\EOv
\E[18~
^AG\rF12 VT100
VT220
Wyse 50key does not exist on physical device
\E[24~
^AK\r
What's a mother to do?! The application developer could write device drivers for every terminal type to be supported. This option requires extensive effort on the part of the developer to be fully compliant with open systems concepts. Fortunately, there is a native solution in the UNIX operating system itself.
The authors of UNIX System V came to grips with the terminal support problem by building into the operating system the necessary I/O programs and the information about terminal characteristics required to support the wide variety of ASCII terminals available . There are two components of this support:
[As a historical note, this idea was first implemented by the authors of BSD UNIX (the Berkeley version) using curses I/O functions and a terminal capabilities database named termcap. System V adopted the idea and extended it. A terminfo database entry contains more detailed information about terminal characteristics than does a termcap entry; and System V curses functions are programmed to take advantage of the additional information.]
Since the goal of this document is to help the user of an application understand how his or her terminal communicates with the application, the discussion of curses and terminfo here is at a fairly basic level. System administrators or others who wish to study curses, termcap, and terminfo in more detail may be interested in other resources such as the Nutshell Handbook termcap & terminfo published by O'Reilly & Associates, Inc.
The curses library includes such functions as screen
initialization and
character fetch and interpretation that allow an application program to
communicate effectively with any terminal type. An application program calls
the appropriate curses function to determine how to process terminal input or
how to output data to the screen. For the end user, how an application
interprets and processes input is of the most immediate concern.
Curses functions use the terminal characteristics stored in the terminfo database. The terminfo database is a directory usually found in the path /usr/lib/terminfo. For SunOS and other BSD-based UNIX implementations, terminfo is located in /usr/5lib/terminfo. Within this directory is a collection of subdirectories with single- character names. The output of
ls /usr/5lib/terminfoon a Sun workstation illustrates:
1 3 5 7 9 B M V a c e g i k m o q s u w y 2 4 6 8 A I P X b d f h j l n p r t v x z
Within each of these subdirectories are definitions for each
terminal type that begins with the letter or number of the directory name.
The output of
ls /usr/5lib/terminfo/von a Sun workstation illustrates:
v50 venix viewpoint vt100-bot-s vt100am v5410 vi200 viewpoint-90 vt100-nam vt100nam v90 vi200-f viewpoint60 vt100-nam-w vt100s vanilla vi200-ic viewpt60 vt100-nav vt100w vc103 vi200-rv virtual vt100-nav-w vt125 vc203 vi200-rv-ic visual vt100-np vt125-am vc303 vi300 visual50 vt100-s vt132 vc303-a vi300-aw vitty vt100-s-bot vt220 vc303a vi300-rv vk100 vt100-s-top vt50 vc404 vi300-ss vs100 vt100-top-s vt50h vc404-na vi50 vs100s vt100-w vt52 vc404-s vi550 vt-61 vt100-w-am vt61 vc404-s-na vic vt100 vt100-w-nam vt61.5 vc415 vic20 vt100-am vt100-w-nav vw
The entries are stored in a
compiled format known to the curses functions that use them. You may
uncompile an
entry using either infocmp (Sun, SCO UNIX, and others) or untic (HP-UX and others). These commands are normally located in /usr/bin
(which is usually in each user's PATH) and are therefore executable by typing one of the
following commands:
infocmp terminal-typeterminal-type is any terminal type in the database.untic terminal-type
On SunOS, infocmp is found in /usr/5bin. If this directory is not in your PATH, you must type
/usr/5bin/infocmp terminal-typeThe output of infocmp or untic goes to STDOUT normally the terminal screen. You may redirect the output to a file for future reference using syntax such as
infocmp vt100 > vt100.terminfo.dataThis uncompiles the terminfo entry for vt100 and places the result in a file named vt100.terminfo.data in your current working directory.
The exception to this is the RS/6000 where the directory /usr/lib/terminfo contains both the compiled entries and the clear-text data. The following is output from
ls /usr/lib/terminfounder AIX 3.2:
9 datamedia.ti hp.ti s.ti u.ti README dec.ti i special.ti v a diablo.ti ibm.ti sun.ti virtual.ti adds.ti general.ti j t visual.ti annarbor.ti hardcopy.ti lsi.ti tektronix.ti w beehive.ti h microterm.ti teleray.ti wyse.ti c hazeltine.ti misc.ti teletype.ti x cdc.ti header pc.ti televideo.ti concept.ti heath.ti perkinelm.ti ti.ti d homebrew.ti print.ti trailerThe names with extension ".ti" are the clear-text files that contain data for all terminals built by the manufacturer indicated in the file name. The single letter filenames are directories similar to those shown previously for the Sun where the compiled database entries are stored.
In general, a terminfo entry consists of a series of characteristic names followed by an equal sign and the expected key sequence in a form such as
kf7=\EOv,
Typical is the vt100 terminfo entry provided with SunOS 4.1.3 shown below:
vt100|vt100-am|dec vt100 (w/advanced video), am, mir, msgr, xenl, xon, cols#80, it#8, lines#24, vt#3, acsc=``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~, bel=^G, blink=\E[5m$, bold=\E[1m$, clear=\E[H\E[J\$2, cr=\r, csr=\E[%i%p1%d;%p2%dr, cub=\E[%p1%dD, cub1=\b, cud=\E[%p1%dB, cud1=\n, cuf=\E[%p1%dC, cuf1=\E[C$, cup=\E[%i%p1%d;%p2%dH~~, cuu=\E[%p1%dA, cuu1=\E[A$, ed=\E[J$2, el=\E[K$, el1=\E[1K$, enacs=\E(B\E)0, home=\E[H, ht=\t, hts=\EH, ind=\n, ka1=\EOq, ka3=\EOs, kb2=\EOr, kbs=\b, kc1=\EOp, kc3=\EOn, kcub1=\EOD, kcud1=\EOB, kcuf1=\EOC, kcuu1=\EOA, kent=\EOM, kf0=\EOy, kf1=\EOP, kf10=\EOx, kf2=\EOQ, kf3=\EOR, kf4=\EOS, kf5=\EOt, kf6=\EOu, kf7=\EOv, kf8=\EOl, kf9=\EOw, rc=\E8, rev=\E[7m$, ri=\EM$, rmacs=^O, rmkx=\E[?1l\E, rmso=\E[m$, rmul=\E[m$, rs2=\E\E[?3l\E[?4l\E[?5l\E[?7h\E[?8h, sc=\E7, sgr=\E[0%?%p1%p6%|%t;1%;%?%p2%t;4%;%?%p1%p3%|%t;7%;... sgr0=\E[m^O$, smacs=^N, smkx=\E[?1h\E=, smso=\E[1;7m$, smul=\E[4m$, tbc=\E[3g,Special keys begin with the letter "k". Other items in a terminfo entry for a given terminal include such characteristics as which key sequence sounds the terminal bell (bel=), how to cause terminal output to blink (blink=), how to enable (smul=) or disable (rmul=) underscoring all terminal output, and other input and output characteristics for this terminal type.
When you start a curses application on your computer, the
initialization process looks at the current
setting of your
TERM environment variable to determine your terminal type. All other input
and output operations will be processed according to this terminal type.
Curses functions will use the information stored in the terminfo database entry
for that terminal type to decide how to process incoming keystrokes and how to
display output.
Both uni-XEDIT and uni-SPF use curses facilities for terminal input and output -- they are curses applications. Curses applications for UNIX-based operating systems abound, the most common being the vi editor that is delivered as a component of the operating system. Thus, if a user is experiencing terminal related problems with a Workstation Group Product and is unsure if the problem lies in the application or in his stars, trying something similar in vi is an excellent way to isolate the problem. If keystrokes in vi produce the same results that they do in uni-XEDIT -- for example, if the arrow keys do not move the cursor as expected -- then you can be certain that the problem is not specific to the application. Most likely, the terminfo entry on your system for your current terminal type does not have as a definition for the arrow keys the same key sequence that your terminal is sending. How this could be and what you can do about it become clearer as you read further in this document.
Expressed simply, terminal input in a curses application is processed as follows:
Two important points should be noted from this description:
Programmatically, the
process is as follows:
[curses.h is located in the directory /usr/include for System V based UNIX implementations; for SunOS and other BSD-based implementations, it is located in /usr/5include, usr/sys5.3/include, or wherever System V header files are stores.]
So what could possibly go wrong? . . . go wrong?
. . . go wrong?
Actually, only two things:
Well, maybe three. The RS/6000,
HP/9000, and a few other platforms are special cases discussed in some detail
after the general discussion that follows.
Understanding Terminal Input Problems. The uni-KEY utility from The Workstation Group allows you to determine which problem you have. Keyboard mapping features in uni-XEDIT and uni-SPF allow you to personalize your keyboard configuration. For uni-XEDIT, uni-KEY is a separate program included on the distribution media. Instructions for using it are in Appendix C of the uni-XEDIT Reference Manual. For uni-SPF, uni-KEY is embedded as Option 0.K.2. Instructions for using it are in the section entitled "Keybind Maintenance Utility (Option 0.K.2)" in Chapter 3 of the uni-SPF Reference Manual. uni-KEY is a curses application as well, so terminal input is processed by uni-KEY exactly as it would be processed by uni-XEDIT, uni-SPF, or any other curses application.
To determine if the key you press actually transmits a key sequence, run uni-KEY in test mode (select "t" from the main menu). Press the desired key. If nothing appears on the screen, the key is not transmitting a sequence. There is little that you can do about this problem other than trying a different terminal type. If you are using a physical terminal, there may be hardware settings that can control what sequence is transmitted by a key. If you are using a terminal emulator program, there may be configuration or execution options available; or you may choose to emulate a different terminal type altogether. Emulating a different terminal type may or may not change the results you see. This is dependent on the specific emulator program that you are using. Keep in mind, also, that the key you are trying to use may be reserved by the emulator program for its own program control functions.
If the key you press does transmit a key sequence, you will see one of two possible results on the uni-KEY screen:
F(7), curses KEY_F(7)=417, terminfo kf7=
\e[211z
When uni-KEY indicates that a curses return code is being set and a curses keyname identified, you can expect this key to automatically perform the indicated function in uni-XEDIT or uni-SPF. When uni-KEY displays the key sequence transmitted by the key, you must provide a custom mapping if you want to use this key in uni-XEDIT or uni-SPF. Keybinding is the facility through which custom mappings are supported in Workstation Group products.
Creating Custom Keyboard
Mappings. In uni-XEDIT, keybinding is achieved through the SET KEYBIND
command. This is documented in Chapter 6 of the
uni-XEDIT Reference Manual
(Chapter 7 if the document number shown on the Preface page is XEV1-3). You
may type SET KEYBIND commands at the command line, or you may store them in a
profile macro. You may create your profile macro by hand, or you may use the
keybind maintenance function of uni-KEY (option "u" from the main menu) to
automatically generate keybindings in the filename you
specify. This use of uni-KEY is also documented in Appendix
C of the uni-XEDIT Reference Manual.
In uni-SPF, keybinding is achieved through the SET KEYBIND dialog management service. It is automatically available through Option 0.K. Option 0.K.1 allows you to view current keybind settings and to add new ones manually. Option 0.K.2 allows you to use uni-KEY to automatically generate keybinds. Option 0.K.3 allows you to import a set of keybinds from the keybind library or to export a set for a specific terminal type for storage in the library where others may access them. Sections beginning with the one entitled "Keyboard Mapping (Option 0.K)" in Chapter 3 of the uni-SPF Reference Manual discuss the details of setting keybinds in uni-SPF.
When you read the documentation or use uni-KEY to generate key bindings, you will note that the "keyname" used in a keybind is yet a different keyname from the curses and terminfo names. There is method to this madness. uni-XEDIT and uni-SPF allow you to define keybinds that override the automatic setting by curses. If the application used only the curses keyname, there would not be a simple way to remap these keys within the SET KEYBIND syntax. Using the example of the F7 key on a Sun Type 4 keyboard, with no keybinds in effect, pressing F7 automatically processes the function associated with PF7 (normally the BACKWARD command). You may override this automatic processing by using SET KEYBIND to redirect the F7 key to another purpose as follows:
SET KEYBIND KEY_F(7) BACKTABThis command tells uni-XEDIT that whenever it receives the curses keyname KEY_F(7), it is to remap this to the function normally performed by the Backtab key.
The third potential
area for keyboard input problems is specific to certain workstations. If you
access your host computer over a network using rlogin, rsh, or telnet, your
keystrokes must traverse the network before they arrive at the host. On
RS/6000, HP/9000 (and possibly others), the operating system expects all
components of a keystroke to arrive within a limited time and does not offer a
programming option to override this requirement. Thus, if your network is very
busy and you press a key that sends "\E[225z", the parts of this key sequence
may arrive at the host in disjoint pieces "\E[" gets there first and is
followed some microseconds later by "22" and still later by "5z". If these
pieces do not all arrive within the default timeout internal, they are treated
as separate transmissions (or separate "keystrokes"). The most common symptom
of this problem is that special keys work sometimes and do not work at other
times. As a user of uni-XEDIT, you may find that all your F-keys work fine
between 7:00 and 9:00 A.M.; but after about 9:30, when more and more people
are getting on the system, they seem to work less frequently,
and you are getting unwanted garbage in your data
or on the command line when you press an F-key.
The cure for this problem on the RS/6000 is to set a special environment variable that is available only under AIX. ESCDELAY specifies the default timeout interval for receiving keystrokes. It is expressed in units of 200 microseconds. The default value is 500, or 0.1 second. You may need to increase this to 2000 (0.4 second) or 2500 (0.5 second) if your network is very busy. Appendix B of the uni-XEDIT Reference Manual describes ESCDELAY for the RS/6000 and gives specific instructions for setting it under the Korn, Bourne, or C shell.
At the present time, The Workstation Group does not know of a similar solution for the HP/9000 platform. You may wish to contact your Hewlett-Packard support personnel for suggestions. If you choose to do this, you may wish to mention that the problem arises specifically from the lack of a notimeout() function in the curses library.
When you start a curses application, the initialization function creates a memory image of the screen size at that time. All output is then displayed according to that screen configuration. No further testing or query of the screen configuration occurs until you exit the application. Thus, if you change your screen configuration while you are running the application, the output results may be unpredictable. In most UNIX implementations, the curses screen initialization uses the current dimensions of the window or screen in which you start the application.
Some System V-based UNIX implementations use the rows and columns values in the terminfo entry for a given terminal type, regardless of the screen's current configuration. The symptoms of this include unexpected wrapping of data lines or application prompts and unexpected truncation of data lines even though there is sufficient screen real estate available to display them. Solutions include
eval `/usr/bin/x11/resize`before starting the curses application; this resets the internal image of the screen before the curses initialization process occurs; note that the characters surrounding /usr/bin/x11/resize are backquotes (often located on the same key with the tilde [~] character) rather than ordinary single quote characters; other UNIX implementations may have similar commands
The other most common problem with terminal output results from scrolling up and down through the data and is manifested by "bleedthrough" of characters from previous screen display(s) into areas that should be blank in the current display. This is usually attribut-able to the specific choice of terminal type and to alternative terminfo entries that implement various output capabilities for an individual terminal name. A common example is the VT100, for which most terminfo databases contain numerous flavors designated as
and many more.
vt100 basic configuration vt100-am vt100 with adjustable margin configurations vt100-nam vt100, no adjustable margins
It may be necessary to set your TERM environment variable to one of these alternatives of the basic terminal type to produce the correct output display. Specifically, IBM states in their definition for the basic vt100 that special changes were made to correctly support vi and that other curses applications may find that vt100-am is the better choice for vt100 support. Selection of the right alternative terminal type is often a matter of trial and error, though your hardware vendor or system documentation may offer some guidance.
The correct command for setting the TERM environment variable depends on which shell you are using. Choose the right command sequence from the table below:
Shell Command(s) C setenv TERM vt100-am OR
set term=vt100-amBourne TERM=vt100-am
export TERMKorn TERM=vt100-am
export TERM
The Workstation Group has attempted to provide, in its products and utilities, sufficient facilities to eliminate the need for modifying terminfo entries. However, some sites may find it desirable or unavoidable to do this. Terminfo modifications may be either of two types:
System-wide modification involves three steps:
infocmp terminal-type > filename
tic terminal-typeThe tic command is available across all UNIX implementations. Its location may vary; but it is normally found in the same directory as the infocmp or untic command.
Local modification requires that you define a local directory to be searched for terminfo data. It therefore requires two additional steps in the modification process and requires that an environment variable be set before running a curses application that uses this local modification. The steps for modification are:
infocmp terminal-type > filename
Set TERMINFO to the location of your localterm directory -- for example
/home/user1/localterm
tic terminal-typeThe tic command is available across all UNIX implementations. Its location may vary; but it is normally found in the same directory as the infocmp or untic command. When the TERMINFO environment variable is set, tic places its output in that location rather than in the master database.
If local terminfo modifications have been made, you must ensure that the environment variable TERMINFO is set before you start a curses application that uses such modifications.
© Copyright 2013, The Workstation Group Ltd.
Phone: 847 540 3390 Last modified: 18 Jan 2013
Comments: webmaster
|