4 #include <netinet/in.h>
6 #define KDGKBTYPE 0x4B33
7 #define ARRAYSIZE(a) sizeof(a)/sizeof(a[0])
8 static int console_fd(int mode
) {
9 const char devs
[][16] = { "/dev/tty", "/dev/vc/0", "/dev/console" };
12 while(i
< ARRAYSIZE(devs
) && fd
== -1) {
13 fd
= open(devs
[i
++], mode
);
14 if(fd
!= -1 && ioctl(fd
, KDGKBTYPE
, &(char){0})) {
23 unsigned char kb_table
;
24 unsigned char kb_index
;
25 unsigned short kb_value
;
28 #define KDSKBENT 0x4B47
30 #define MAX_NR_KEYMAPS 256
35 #include <ulz/stdio-repl.h>
38 #define noret __attribute__((noreturn))
40 noret
static void die_perror(const char* msg
) {
45 noret
static void usage(const char *arg0
) {
46 dprintf(2, "usage: %s < my.kmap\n"
47 "loads kmap from stdin.\n", arg0
);
51 static void fetch(int fd
, void* buf
, size_t cnt
) {
52 if(read(fd
, buf
, cnt
) != (ssize_t
) cnt
) die_perror("read");
57 int main(int argc
, char** argv
) {
59 if(argv
[1] || isatty(0)) usage(argv
[0]);
60 char flags
[MAX_NR_KEYMAPS
];
62 if(memcmp(flags
, "hcukmap", 7)) { errno
= EINVAL
; die_perror("invalid magic"); }
63 fetch(0, flags
, MAX_NR_KEYMAPS
);
64 int cfd
= console_fd(O_WRONLY
);
65 if(cfd
== -1) die_perror("could not get console fd");
67 for(;i
< MAX_NR_KEYMAPS
; i
++) if(flags
[i
]) {
69 fetch(0, kmap
, sizeof kmap
);
70 for(j
=0; j
< NR_KEYS
; j
++) {
71 struct kbentry ke
= { .kb_index
= j
, .kb_table
= i
};
72 ke
.kb_value
= ntohs(kmap
[j
]);
73 if(ioctl(cfd
, KDSKBENT
, &ke
))
75 // some keymaps contain the value 638 in the first entry, which means K_ALLOCATED.
76 // not sure how to deal with this best; it seems it can be ignored.
77 /* dprintf(2, "warning: failed to set key slot %zu,%zu to %d, reason: %s\n",
78 i, j, ke.kb_value, strerror(errno)); */