summaryrefslogtreecommitdiffstats
path: root/perl-install/keyboard.pm
blob: 267b0be954106c556a9e34d15631fb70b24770a4 (plain)
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
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 die "keymap ioctl failed: $!";
	    $key++;
	 }
	$count++;
    }
    log::l("loaded $count keymap tables");
}

sub setup($) {
    my ($defkbd) = @_;
    my $t; 

    $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 die "error reading keymap data: $!";

	if ($defkbd eq $_->[1]) {
	    log::l("using keymap $_->[1]");
	    load($t);
	    &write("/tmp", $_->[1]);
	    return;
	}
    }
    die "keyboard $defkbd not found in /etc/keymaps";
}

sub write($$) {
    my ($prefix, $keymap) = @_;

    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 die "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 die "failed to read keyboard configuration";

    foreach (<F>) {
	($_) = /^KEYTABLE=(.*)/ or log::l("unrecognized entry in keyboard configuration file ($_)"), next;
	s/\"//g; 
	s/\.[^.]*//; # remove extension
	return basename($_);
    }
    die "empty keyboard configuration file";
}