(The following article was submitted to the Linux Journal for publication and is being presented here with the permission of the publisher of the Linux Journal -- John M. Fisk)
"It's a GUI, GUI, GUI, GUI world!" -- or so the major OS manufacturers would have you belief. 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 that 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 Allesandro Rubini entitled "The Best Without X" that appeared in the November, 1995 (Issue 19) edition of the Linux Journal. Among a wealth of helpful ideas, Allesandro 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 can be done. We'll also look at:
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 for this are standard inclusions in most recent Linux distributions and include:
A listing of Linux FTP archives where these may be found is included at the end of this article.
The numeric keypad is an ideal candidate for remapping into a virtual terminal (VT) switching scratch pad as most of us have never learned to "touch type" using the keypad. In addition, on a 101-key keyboard, its non-numeric functions 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.
To do this you'll need to have the kbd package installed on your system. The two programs we'll be using for this are the 'showkey' and 'loadkey' programs. To check whether they are installed on your system you can type in:
% 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 /usr/bin/showkey /usr/bin/loadkeys
If you don't have these programs installed you'll need to get the sources for the kbd package and install it yourself. (This comes as source only but installation is as simple as unachiving it into a temporary directory and typing in 'make && make install').
Converting the keypad into VT switcher involves defining a keyboard mapping and then using loadkeys to actually load this information into the kernel keyboard translation tables. It's a whole lot 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 VT's, not just the one you're working on.
The kbd package 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 defkeymap.map file. This is the default keyboard mapping and is a useful place to start. You can call the new file anything you'd like - e.g.,
cp defkeymap.map custom.map
Use your favorite editor and load up this file. At this point it's probably helpful to stop for a moment and have a look around. It's 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 remap the keyboard except to say that the basic format that we'll 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 these events are 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. Being able 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+keynumber 3 is pressed, the output is the Meta_at (whatever one of those looks like).
Getting back to the task at hand, what we want to do is change to a specified VT when we press one of the keypad keys: pressing keypad 1 should switch to VT number 1, pressing keypad 2 should switch to VT number 2, and so forth. 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:
# NUMERIC KEYPAD MAPPING # # The section remaps the keypad keys so that they act as a # VT-switcher: keypad 1 switches to VT 1, keypad 2 to VT 2, # and so forth. Note that pressing Shift+key switches to a VT # which is 10+ the number of the key (Shift+3 = VT 13) and that # pressing Alt+key (when Num Lock is on) causes numeric output. # # Keypad number 7 # keycode 71 = Console_7 shift keycode 71 = Console_17 alt keycode 71 = KP_7 alt control keycode 71 = Console_7 # # Keypad number 8 # keycode 72 = Console_8 shift keycode 72 = Console_18 alt keycode 72 = KP_8 alt control keycode 72 = Console_8 # # Keypad number 9 # keycode 73 = Console_9 shift keycode 73 = Console_19 alt keycode 73 = KP_9 alt control keycode 73 = Console_9 keycode 74 = KP_Subtract # # Keypad number 4 # keycode 75 = Console_4 shift keycode 75 = Console_14 alt keycode 75 = KP_4 alt control keycode 75 = Console_4 # # Keypad number 5 # keycode 76 = Console_5 shift keycode 76 = Console_15 alt keycode 76 = KP_5 alt control keycode 76 = Console_5 # # Keypad number 6 # keycode 77 = Console_6 shift keycode 77 = Console_16 alt keycode 77 = KP_6 alt control keycode 77 = Console_6 keycode 78 = KP_Add # # Keypad number 1 # keycode 79 = Console_1 shift keycode 79 = Console_11 alt keycode 79 = KP_1 alt control keycode 79 = Console_1 # # Keypad number 2 # keycode 80 = Console_2 shift keycode 80 = Console_12 alt keycode 80 = KP_2 alt control keycode 80 = Console_2 # # Keypad number 3 # keycode 81 = Console_3 shift keycode 81 = Console_13 alt keycode 81 = KP_3 alt control keycode 81 = Console_3 # # Keypad number 0 # keycode 82 = Last_Console shift keycode 82 = Console_10 alt keycode 82 = KP_0 # # Keypad '.' key # keycode 83 = KP_Period altgr control keycode 83 = Boot control alt keycode 83 = Boot keycode 84 = Last_Console
Before going on let's make a couple observations. First, it's not a bad idea to comment the file as you go. What's seems so clear and obvious now quickly fades into obscurity as the weeks pass. Adding comments will help prevent your having to pour back over manual pages, program documentation, and magazine articles looking for the correct syntax or usage.
Second, notice that with each entry there are "sub-stanzas" if you will, that begin with the words "alt keycode" "shift keycode" etc. These are the stanzas that 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 "Ctrl-C" combination that is used to terminate a program in execution.
Finally, you may be asking yourself how you're supposed to know which keynumber is associated with a key. Anyone know off hand what keynumber goes with the " key? The way you find this out is using the 'showkey' program. After you invoke the program, showkey prints the keynumber for any key that you hit (and quits after 10 seconds of no input). So, now that we've already edited the pertinent section in the 'custom.map' file, let's see how we'd arrive at this "from scratch."
The basic steps we'd need to take would be to:
To do this, let's begin by using the 'showkey' program which can be invoked using:
Now, any key that you press causes showkey to print the keynumber. On my machine, invoking showkey and pressing keypad keys 1 through 9 results in the following output:
~$ showkey kb mode was XLATE press any key (program terminates after 10s of last key press)... keycode 79 press keycode 79 release keycode 80 press keycode 80 release keycode 81 press keycode 81 release keycode 75 press keycode 75 release keycode 76 press keycode 76 release keycode 77 press keycode 77 release keycode 71 press keycode 71 release keycode 72 press keycode 72 release keycode 73 press keycode 73 release
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 following format:
Actual Key: Keynumber: 7 8 9 71 72 73 4 5 6 75 76 77 1 2 3 79 80 81
So that keypad number 1 has keynumber 79, keypad number 2 has keynumber 80, and so forth. Knowing this, we can now 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. So, a simple entry to map keypad number 1 to switching to VT 1 would look like:
keycode 79 = Console_1
If you look at the example given above, you'll notice that this is what we've done. Suppose, however, that we wanted to switch to a VT greater than 9, how are we to do that? The solution to this 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, hit the Num Lock key so that it toggles to 'on' and then hold down the Alt key while you enter numbers at the keypad.
Note, too, that in this example, Alt+Ctrl+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 occurs when the the Alt+Fn (Alt + Function key) or Alt+Ctrl+Fn (Alt + Ctrl + Function key) combination is used. The intuitive will immediately have noticed that this 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+Ctrl+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+Ctrl+Fn key combination while the two key Alt+Fn key combination is used at the console. Obviously, while you can change this default behavior it's best to leave this as is.
So, 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. This is done using 'loadkeys' and can be done without having to log in as root. To load the customized keymap enter:
% loadkeys /usr/lib/kbd/keytables/custom.map
This will print a message indicating that the 'custom.map' 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/defkeymap.map
and the default mappings will be loaded once again. You can use this edit -> load customized map -> test -> load default map cycle to get the mapping that you want. 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/custom.map ]; then loadkeys /usr/lib/kbd/keytables/custom.map fi
This ensures that the file is present and readable and then invokes loadkeys to load the file. Again, keep in mind that loading a key mapping changes the keytable information for ALL VT's, not just the one you are working on.
The Incr_Console and Decr_Console keysym do as their names might imply: they switch to (VT + 1) or (VT - 1) respectively. So, if you were currently working at VT 3, the Incr_Console keysym would switch you to VT 4 while the Decr_Console keysym would switch you to VT 2. The Last_Console keysym also does as its name might imply: it switches to the last VT that you were previously at. If you were working at VT 3 and switched to VT 6, the Last_Console keysym would switch you back to VT 3.
You can map a key or modifier+key combination to invoke any of these keysyms. I've mapped these to:
Ctrl+left arrow = Decr_Console Ctrl+right arrow = Incr_Console keypad 0 = Last_Console
Obviously, you can map these in any manner you wish, but the relevant entries to map the above actions would be:
#keycode 82 = KP_0 keycode 82 = Last_Console shift keycode 82 = Console_10 alt keycode 82 = KP_0 [...] keycode 105 = Left alt keycode 105 = Decr_Console keycode 106 = Right alt keycode 106 = Incr_Console
These entries map the keypad 0 key to the Last_Console keysym and the Alt+ left or right arrows to Decr_Console or Incr_Console keysyms. The good news is that these last two are already the default so that you only have to edit the stanza for the keypad 0 key. Now, you can quickly cycle through all the VT's by holding down the Alt key and repeatedly pressing the left or right arrow. To alternate between two VT's you have only to repeatedly hit the keypad 0 key. I've found these mappings to be quite useful but, as has been mentioned before, they can be customized to anything that you find helpful.
The last bit of VT cruising magic is the 'chvt' program which is included with the kbd package. It's use is quite simple:
% chvt 3
would change to VT 3. Substituting another number for '3' allows you to change to that VT. A foreshortened version of this can be set up using a shell alias:
% alias vt='chvt'
so that entering:
% vt 3
would switch you to VT 3.
So, now that we've defined several methods of getting from VT to VT it is important to note that works only at the console and not under the X Window system. Under X, the X server takes control of the keyboard, mouse, and display: setting up customized keyboard mappings is performed using the ~/.Xmodmap file or the program 'xkeycaps' and is a subject for some later article :-)
Without going into all the details of this (again, a subject for a later article) suffice it to say that this is set up in the /etc/inittab file. A sample entry for this might look like:
# The getties in multi user mode on consoles an serial lines. # # NOTE NOTE NOTE adjust this to your getty or you will not be # able to login !! # # Note: for 'agetty' you use linespeed, line. # for 'getty_ps' you use line, linespeed and also use 'gettydefs' c1:1235:respawn:/sbin/agetty 38400 tty1 linux c2:1235:respawn:/sbin/agetty 38400 tty2 linux c3:5:respawn:/sbin/agetty 38400 tty3 linux c4:5:respawn:/sbin/agetty 38400 tty4 linux c5:5:respawn:/sbin/agetty 38400 tty5 linux c6:45:respawn:/sbin/agetty 38400 tty6 linux
The important thing to note here is that the 'agetty' program is run on each of the tty devices from tty1 to tty6. Thus, at system startup there are a total of six getty's running allowing you to log in to VT 1 through 6. So what about VT 7 and beyond? Are they still usable in any way?
If you've remapped you keyboard, try pressing keypad 7 -- alternatively, hit Alt-F7 -- and see what happens. In general, the screen is blank with the cursor positioned at the upper left corner. You can type in at the keyboard and the output is displayed on the screen. Despite this, there is no way to execute programs at this terminal. Now you see the purpose of the 'getty' program: without being able to log in at a terminal it really isn't much use. There are, however, two important exceptions to this.
You get the idea.
The other thing to note is that while you can't run programs on a VT without logging in, you can still send output there. As a simple experiment try the following:
% echo "This is a test" > /dev/tty7
Switching to VT 7, you'll see the words, "This is a test" displayed. This becomes useful with system logging. Without going into an exhaustive discussion of system logging and configuration, it is worth noting that the output of all logging facilities can be "dumped" to an unused VT which allows quick perusal for events such as login's, kernel messages, mail logging, and so forth.
To do this simply add the following line to the /etc/syslog.conf file (after logging in as root):
# this one will log ALL messages to the /dev/tty9 terminal # since this is an unused terminal at the moment. This way, we # don't need to hang a getty on it or take up a lot of system resources. *.* /dev/tty9
Once you've added this stanza to /etc/syslog.conf, you'll need to either kill and restart the syslog daemon or else send it the HUP (hang up) signal. Since this latter method is fairly easy let's do it:
% ps -x | grep syslog 28 ? S 0:01 /usr/sbin/syslogd
will output the PID (process ID number) of the syslog daemon which in this case is 28. Now, just type in:
% kill -HUP 28
in which '28' is the PID number. The syslog daemon will then re-read its initialization files. From here on, all logging that occurs, regardless of its source, will be output to tty9 (or whichever tty device you specify).
Switching to VT 9 you might see something like the following:
Jul 1 10:11:37 FiskHaus kernel: Max size:342694 Log zone size:2048 Jul 1 10:11:38 FiskHaus kernel: First datazone:68 Root inode number 139264 Jul 1 10:11:38 FiskHaus kernel: ISO9660 Extensions: RRIP_1991A Jul 1 12:21:50 FiskHaus login: ROOT LOGIN ON tty2 Jul 1 17:26:56 FiskHaus login: 1 LOGIN FAILURE ON tty5, fiskjm
The first three lines represent kernel messages that occur when a CD was mounted. Root logins are noted by the 'login' program as well as login failures -- in this last case I purposely entered an incorrect password.
The value of all of this logging may not be immediately evident, but if you've ever noticed that your machine begins thrashing about and swapping like crazy or that, while online, your hard drive lights begin to light up when you're not doing anything -- a quick switch to VT 9 can often give you an idea about what's going on.
Well, all of this should get you going! The manual pages for 'loadkeys', 'showkey', and 'keytables' have much more complete technical descriptions of key mapping. Also, the kbd package comes with a good deal of helpful documentation in its /doc subdirectory. And finally, don't forget the Keyboard-HOWTO which can be found amongst the growing number of Linux HOWTO's.
Note that the FTP site is GA Tech -- a Sunsite mirror. Please check the MIRRORS file in the /pub/Linux subdirectory for a site nearest you.