It is the kernel. Keep in mind the keyboard is hardware and everything that happens there passes through the kernel; in the case of VT switching, it handles the event completely itself and does not pass anything on to userspace (however, I believe there is an ioctl related means by which userspace programs can be notified of a switch occurring involving them and perhaps affect it, which X no doubt does).
The kernel has a keymap build into it; this can be modified while running with loadkeys
, and viewed with dumpkeys
:
[...]
keycode 59 = F1 F13 Console_13 F25
alt keycode 59 = Console_1
control alt keycode 59 = Console_1
keycode 60 = F2 F14 Console_14 F26
alt keycode 60 = Console_2
control alt keycode 60 = Console_2
keycode 61 = F3 F15 Console_15 F27
alt keycode 61 = Console_3
control alt keycode 61 = Console_3
[...]
The kernel source contains a default keymap file which looks exactly like this; for 3.12.2 it's src/drivers/tty/vt/defkeymap.map
. You'll also notice there is a corresponding defkeymap.c file (this can be generated with loadkeys --mktable
). The handling is in keyboard.c
(all these files are in the same directory) which calls set_console()
from vt.c
:
» grep set_console *.c
keyboard.c: set_console(last_console);
keyboard.c: set_console(i);
keyboard.c: set_console(i);
keyboard.c: set_console(value);
vt.c:int set_console(int nr)
vt_ioctl.c: set_console(arg);
I edited some hits out of that list; you can see the function signature on the second last line.
So these are the things involved in the switching. If you look at the sequence of calls, eventually you come back to kbd_event()
in keyboard.c
. This is registered as an event handler for the module:
(3.12.2 drivers/tty/vt/keyboard.c
line 1473)
MODULE_DEVICE_TABLE(input, kbd_ids);
static struct input_handler kbd_handler = {
.event = kbd_event, <--- function pointer HERE
.match = kbd_match,
.connect = kbd_connect,
.disconnect = kbd_disconnect,
.start = kbd_start,
.name = "kbd",
.id_table = kbd_ids,
};
int __init kbd_init(void)
{
[...]
error = input_register_handler(&kbd_handler);
Hence, kbd_event()
should be called when something bubbles up from the actual hardware driver (probably something from drivers/hid/
or drivers/input/
). However, you won't see it referred to as kbd_event
outside of that file, since it is registered via a function pointer.
Some resources for scrutinizing the kernel
- The Linux Cross Reference Identifier Search is a great tool.
- The Interactive Linux Kernel Map is an interesting graphical front end to the cross reference tool.
- There are a few historical archives of the massive Linux Kernel Mailing List (LKML), which goes back to at least 1995; some of them are not maintained and have broken search features, but the gmane one seems to work very well. People have asked a lot of questions on the mail list and it is a primary means of communication amongst the developers as well.
- You can inject your own
printk
lines into the source as a simple means of tracing (not all of the standard C lib can be used in kernel code, including printf from stdio). printk stuff ends up in syslog.
Wolfgang Mauerer wrote a great big book on the 2.6 kernel, Professional Linux Kernel Architecture, which goes through a lot of the source. Greg Kroah-Hartman, one of the principle devs for the last decade, also has a lot of things kicking around.
Terminal line control can be queried and/or set by stty
. To see the current settings, use stty -a
. The manpages provide details.
For example, from stty -a
you might find this kill-line control:
kill = ^U
The caret means hold the control key (Ctrl) and then type the character shown (U
). To change the line-kill sequence, you could do:
$ stty kill \@
NOTE: The backslash is an escape to signify that the character following is to be interpreted literally by the shell.
Having changed your line-kill to this, (a literal @), you can now obliterate a line that looks like:
$ ddtae@
NOTE: In the above, scenario, when you type ddtae, when you type the character @, the entire line will be erased.
One way to restore the default settings (and this is very useful when you have inadvertently altered settings) is to simply do:
$ stty sane
Yet another use of stty
is to control character echo-back. For instance, a simple way to hide a user's password as (s)he types it is to do:
#!/bin/sh
echo "Enter password"
stty -echo
read PWORD
stty echo
echo "You entered '${PWORD}'"
Best Answer
Depending on how the terminal is configured, typing Alt+Key is like typing the Esc and Key keys in sequence, so it sends the ESC character (aka
\e
or^[
or\033
) followed by the character or sequence of characters sent upon pressing that Key.Upon pressing Up, most terminal emulators send either the three characters
\033[A
or\033OA
depending on whether they're in application keypad mode or not.The first one does correspond to the escape sequence which when output to the terminal, move the cursor up. If you do:
You'll see
bar
written afterfoo
one row up. If you do:You'll see that the arrow keys do move the cursor around.
When an application like
zsh
orvi
reads that sequence of characters from the terminal, it interprets it as the "Up" action, because it knows from the terminfo database (kcuu1
capability) that it is the escape sequence sent upon pressing Up.Now, for Alt-Up, some terminals like
rxvt
and its derivatives likeeterm
send\033
followed by the escape sequence for Up (that is\033\033[A
or\033\033OA
), while some others likexterm
orgnome-terminal
have separate escape sequences for those types of keys when used with the combination keys like Alt, Shift, Ctrl.Those will typically send
\033[1;3A
upon Alt-Up.When sent to the terminal, that sequence will also move the cursor up (the second parameter (3) is ignored). There's no corresponding keypad key, so it's the same sequence sent upon Alt-Up in or out of application keypad mode.
Now whether it's
\033\033[A
or\033[1;3A
, many applications don't know what those sequences are for. The terminfo database won't help them, because there's no such capability that defines what characters those key combinations send.They will try their best to interpret that sequence.
bash
for instance will interpret\033[1;3
as an escape sequence, doesn't know anything about it, so does nothing, followed byA
.zsh
, will stop reading as soon as it finds out there's no known matching character sequence. There's no escape sequence that it knows that starts with\033[1
so it will skip that, and read the rest:;3A
and insert that in the line editor.Many applications like
vi
,zsh
orreadline
based ones likegdb
orbash
(though bewarebash
uses a modified version ofreadline
) allow you to add bindings for any sequence of characters.For instance, in
zsh
, you may want to bind Alt-Up, Alt-Down like:Those are to search the history backward and forward for command lines that start like the current one up to the current position of the cursor which is quite handy to recall previous commands.