Keyboards, Consoles, and VT Cruising

There are times when the command line interface is still a very good choice for getting things done.

“It's a GUI, GUI, GUI, GUI world!”—or so the major OS manufacturers would have you believe. The truth is that while this is increasingly the case, there are times when the command line interface (CLI) is still a very good choice for getting things done. It's fast, generally efficient, and is a good choice on memory or CPU constrained machines. And don't forget, there are still a lot of very nifty things that can be done at the console.

In this spirit, I'd like to start by following up on a delightful and informative article written by Alessandro Rubini entitled “The Best Without X” in the November 1995 issue (#19) of Linux Journal. Among a wealth of helpful ideas, Alessandro suggested converting the numeric keypad into a console-switch scratch pad to allow single key switching from one virtual terminal (VT) to another. We'll begin by looking at how this conversion can be done. We'll also look at:

  • Getting from Here to There: handy methods for VT cruising

  • The Useful Unused VT: where to put all that logging information, and where X-Windows really ends up

By the time that you get through tinkering around with these things I think you'll agree that the CLI isn't such a bad place after all. Also, the good news is that the programs you'll need to do this conversion are standard inclusions in most recent Linux distributions and include:

  • kbd 0.91 (keyboard font and utility programs)

  • utils 2.5 (Rick Faith's huge collection of utilities)

  • GNU shell-utils 1.12 (shell utilities including the stty program)

A listing of Linux FTP archives where these utilities can be found is included in the sidebar.

The Keypad VT-Switcher

The numeric keypad is an ideal candidate for re-mapping into a virtual terminal-switching scratch pad since most of us have never learned “ten-key by touch”. In addition, the non-numeric functions on a 101-key keyboard are already duplicated by the home, end, page up, page down, insert, delete and arrow keys. Since there may be occasions in which we still want to use the keypad for numeric input, let's see how to set it up as a VT switcher while retaining numeric input ability. You'll need to have the kbd package installed on your system. The two programs we'll be using are showkey and loadkey. To check whether they are installed on your system type:

$ type loadkeys showkey

if you're using the BASH shell, or:

$ which loadkeys showkey

The which program or the BASH shell built-in function type will both print the path to the executable if they exist in the PATH search path. On my machine this produces:

$ type showkey loadkeys
showkey is /usr/bin/showkey
loadkeys is /usr/bin/loadkeys
$ which showkey loadkeys

If you don't have these programs installed, you'll need to get the the kbd package source, and install it yourself. This package is available only as source code, but installation is as simple as un-archiving it into a temporary directory, then typing:

$make && make install

Converting the keypad into a VT switcher involves defining a keyboard mapping and using loadkeys to actually load this information into the kernel keyboard translation tables. It's easier than it sounds—although you must keep in mind that indiscriminate tinkering can render your keyboard useless (requiring one of those dreaded cold reboots), and that changing the keyboard translation tables affects ALL VTs, not just the one you're working on. The kbd package's default installation location is under /usr/lib/kbd, with the key mapping files in the keytables subdirectory. Change to this directory and make a copy of the file, which contains the default keyboard mapping and is a useful place to begin. You can name the new file anything you'd like—e.g.,


Use your favorite editor and load up the copied file. At this point it's probably helpful to have a look around at the current contents. The experience is rather like visiting one of those fine old curio shops—look, but don't touch! The first few lines may look something like this:

keycode   1 = Escape  Escape
    alt keycode   1 = Meta_Escape
keycode   2 = one  exclam
    alt keycode   2 = Meta_one
    shift   alt keycode   2 = Meta_exclam
keycode   3 = two   at   at
    control keycode   3 = nul
    shift   control keycode   3 = nul
    alt keycode   3 = Meta_two
    shift   alt keycode   3 = Meta_at

I won't go into all the gory details of how to re-map the keyboard except to say that the basic format to use is:

keycode keynumber = keysym
    modifier keycode keynumber = keysym

in which keynumber is the internal identification number of the key and keysym represents the action to take. Now, before you bail out on me, let's put this into simple terms. Each key on the keyboard is identified by a unique number which is represented by keynumber. When a key is pressed or released, the press or release event is passed to the operating system, which responds by performing the appropriate action—represented here by keysym. The modifier is a key which is held down at the same time that the key is pressed. These modifier keys include the well-known control, alt and shift keys. The ability to define multi-key combinations extends the mapping available for each key.

So, using the example above, pressing the key associated with keynumber 3 actually causes the number 2 to be printed to the screen. If the shift key is held down at the same time as the key is pressed, the @ sign is printed to the screen, and if the three key combination shift-alt-3 is pressed, the output is the Meta_at (whatever that looks like).

Getting back to the task at hand, we want to change to a specified VT when we press one of the keypad keys: i.e., pressing keypad 1 should switch to VT number 1, pressing keypad 2 should switch to VT number 2, etc. In your customized key map file find the section that defines the keypad keys—it should look similar to this:

keycode  71 = KP_7
    alt keycode  71 = Ascii_7
keycode  72 = KP_8
    alt keycode  72 = Ascii_8
keycode  73 = KP_9
    alt keycode  73 = Ascii_9

Now, edit this section so that it reads something like Listing 1.

Before continuing, let's make a couple of observations. First, it's not a bad idea to comment the file as you go. What seems clear and obvious now fades into obscurity as the weeks pass. Adding comments now will prevent your having to pore over manual pages, program documentation and magazine articles later, looking for the correct syntax or usage. Second, notice that with each entry there are sub-stanzas, beginning with the words alt keycode, shift keycode, etc. These stanzas define multi-key combinations in which a modifier key is pressed at the same time as the key being defined. A common example of this is the crtl-c combination used to terminate a program during execution.

Finally, you may be asking yourself how you're supposed to know which keynumber is associated with a key. Does anyone know off-hand what keynumber goes with the ; key? You can find this out by using the showkey program. After you invoke the program, showkey will print the keynumber for any key you press and will quit after 10 seconds of no input. So, now that we've edited the pertinent section in the file, let's see how we'd arrive at this from scratch. The basic steps would be:

  • Find the keynumber for the keypad keys.

  • Edit the customized mapping for the keys so that pressing them would change to the appropriate VT.

  • Edit the customized mapping for the keys so that the keypad could still be used for numeric input (using a modifier key combination in this case).

  • Load the customized mapping and see whether it works.

  • Optionally, have the default key mapping loaded at system boot.

To do this, let's begin by invoking the showkey program:

$ showkey

Now, any key you press causes showkey to print the keynumber. On my machine, invoking showkey and pressing keypad keys 1 through 9 results in the output shown in Listing 2. You can see that both key press and key release events are detected. Also note that the numbering of the keypad keys is not sequential. The numeric keys have the format shown in Table 1:

Table 1

Actual Key:                 Keynumber:
7    8    9                 71   72   73
4    5    6                 75   76   77
1    2    3                 79   80   81

Table 1 shows that keypad number 1 has keynumber 79, keypad number 2 has keynumber 80, etc, Knowing this, we can set up the appropriate key map entry for each of these keys. The keysym event that we're interested in is Console_x, in which x is the number of the VT to which the view is switched. A simple entry to map keypad number 1 to switching to VT 1 would look like:

keycode 79 = Console_1

If you look at Listing 1, you'll notice that this is what we've done. Suppose, however, we wanted to switch to a VT greater than 9—how are we to do that? The solution is to use a modifier key combination. Looking again at the example above, using the shift key with the keypad allows us to use Console_10 through Console_19. We also wanted to be able to use the numeric keypad as just that—a means of entering numeric data. In the example above, notice that the modifier alt was used to do this:

keycode  71 = Console_7
    shift       keycode  71 = Console_17
    alt         keycode  71 = KP_7
    alt control keycode  71 = Console_7

In this stanza for the keypad_7 key, the first entry maps the keypad_7 key to switch to VT 7. The second line maps shift-keypad_7 to switch to VT 17 and the third line maps the alt-keypad_7 combination to KP_7 which is the keysym for numeric output when num lock is on. Thus, to use the keypad as a numeric keypad, press the num lock key so that it toggles to on, then hold down the alt key while you enter numbers at the keypad. Note, too, that alt-crtl-keypad was defined to switch to the same console as simply pressing the keypad key itself. In this case, it acts in exactly the same fashion as the alt-fn (alt-Function_key) or alt-crtl-fn (alt-crtl-Function key) combination. You may have noticed that using the function keys is how one is typically instructed to switch from one VT to another. Looking at the stanzas for the function keys you'll notice entries such as the following:

keycode  59 = F1    F13    Console_13
    control keycode  59 = F25
    shift   control keycode  59 = F37
    alt keycode  59 = Console_1
    control alt keycode  59 = Console_1

Note that both alt-f1 and alt-crtl-f1 are used to switch to VT 1. Those of you using X will probably already have found that switching to a VT from X requires the three key alt-crtl-fn key combination while the two key alt-fn key combination is used at the console. Although you can change this default behavior, it's best not to. At this point, we've defined mappings for the keypad keys such that each key acts as a switch to the VT of the same number. Using shift-keypad_key switches to VT (10 + keypad number) and using alt-keypad key with the num lock on outputs the numeric value of the key. The final step is to actually load the new mapping and give it a try. The loading is done using loadkeys and can be done without logging on as root. To load the customized keymap, enter:

$ loadkeys /usr/lib/kbd/keytables/

This will print a message indicating that the file is being loaded. After this, you're all set! Give it a try. To revert back to the default mapping simply enter:

$ loadkeys /usr/lib/kbd/keytables/

and the default mappings will be loaded once again. You can use this edit -> load customized map -> test -> load default map cycle to obtain the desired mapping. Once you've created a custom map file and wish to have it loaded at boot, you can add an entry to one of the rc.* files, such as rc.local, to have loadkeys automatically load your customized mapping:

if [ -r /usr/lib/kbd/keytables/ ]; then
     loadkeys /usr/lib/kbd/keytables/

This entry ensures that the file is present and readable and invokes loadkeys to load the file. Again, keep in mind that loading a key mapping changes the keytable information for all VTs, not just your current one.