1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
|
package keyboard;
use diagnostics;
use strict;
use vars qw($KMAP_MAGIC %defaultKeyboards %loadKeymap);
use common qw(:system :file);
use log;
$KMAP_MAGIC = 0x8B39C07F;
%defaultKeyboards = (
"de" => "de-latin1",
"fi" => "fi-latin1",
"se" => "se-latin1",
"no" => "no-latin1",
"cs" => "cz-lat2",
"tr" => "trq",
);
1;
sub load($) {
my ($keymap_raw) = @_;
my ($magic, @keymaps) = unpack "i i" . c::MAX_NR_KEYMAPS() . "a*", $keymap_raw;
$keymap_raw = pop @keymaps;
$magic != $KMAP_MAGIC and die "failed to read kmap magic: $!";
local *F;
sysopen F, "/dev/console", 2 or die "failed to open /dev/console: $!";
my $count = 0;
foreach (0 .. c::MAX_NR_KEYMAPS() - 1) {
$keymaps[$_] or next;
my @keymap = unpack "s" . c::NR_KEYS() . "a*", $keymap_raw;
$keymap_raw = pop @keymap;
my $key = 0;
foreach my $value (@keymap) {
c::KTYP($value) != c::KT_SPEC() or next;
ioctl(F, c::KDSKBENT(), pack("CCS", $_, $key++, $value)) or log::l("keymap ioctl failed: $!");
$key++;
}
$count++;
}
log::l("loaded $count keymap tables");
1;
}
sub setup($) {
my ($defkbd) = @_;
my $t;
#$::testing and return 1;
$defkbd ||= $defaultKeyboards{$ENV{LANG}} || "us";
local *F;
open F, "/etc/keymaps" or die "cannot open /etc/keymaps: $!";
my $format = "i2";
read F, $t, psizeof($format) or die "failed to read keymaps header: $!";
my ($magic, $numEntries) = unpack $format, $t;
log::l("%d keymaps are available", $numEntries);
my @infoTable;
my $format2 = "i Z40";
foreach (1..$numEntries) {
read F, $t, psizeof($format2) or die "failed to read keymap information: $!";
push @infoTable, [ unpack $format2, $t ];
}
foreach (@infoTable) {
read F, $t, $_->[0] or log::l("error reading $_->[0] bytes from file: $!"), return;
if ($defkbd eq $_->[1]) {
log::l("using keymap $_->[1]");
load($t) or return;
&write("/tmp", $_->[1]) or log::l("write keyboard config failed");
return $_->[1];
}
}
undef;
}
sub write($$) {
my ($prefix, $keymap) = @_;
$keymap or return 1;
$::testing and return 1;
local *F;
open F, ">$prefix/etc/sysconfig/keyboard" or die "failed to create keyboard configuration: $!";
print F "KEYTABLE=$keymap\n" or die "failed to write keyboard configuration: $!";
# write default keymap
if (fork) {
wait;
$? == 0 or log::l('dumpkeys failed');
} else {
chroot $prefix;
CORE::system("/usr/bin/dumpkeys > /etc/sysconfig/console/default.kmap 2>/dev/null");
exit($?);
}
}
sub read($) {
my ($file) = @_;
local *F;
open F, "$file" or # fail silently -- old bootdisks won't create this
log::l("failed to read keyboard configuration (probably ok)"), return;
foreach (<F>) {
($_) = /^KEYTABLE=(.*)/ or die "unrecognized entry in keyboard configuration file";
s/\"//g;
s/\.[^.]*//; # remove extension
return basename($_);
}
log::l("empty keyboard configuration file");
undef;
}
|