add netbsd nl(1)
[rofl0r-hardcore-utils.git] / loadkmap.c
blob5362c873aa2526260ffa6d9177cff3e47eeee03c
1 #include <unistd.h>
2 #include <fcntl.h>
3 #include <sys/ioctl.h>
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" };
10 size_t i = 0;
11 int fd = -1;
12 while(i < ARRAYSIZE(devs) && fd == -1) {
13 fd = open(devs[i++], mode);
14 if(fd != -1 && ioctl(fd, KDGKBTYPE, &(char){0})) {
15 close(fd);
16 fd = -1;
19 return fd;
22 struct kbentry {
23 unsigned char kb_table;
24 unsigned char kb_index;
25 unsigned short kb_value;
28 #define KDSKBENT 0x4B47
29 #define NR_KEYS 128
30 #define MAX_NR_KEYMAPS 256
32 #include <stdio.h>
33 #include <stdlib.h>
34 #ifdef USE_LIBULZ
35 #include <ulz/stdio-repl.h>
36 #endif
38 #define noret __attribute__((noreturn))
40 noret static void die_perror(const char* msg) {
41 perror(msg);
42 exit(1);
45 noret static void usage(const char *arg0) {
46 dprintf(2, "usage: %s < my.kmap\n"
47 "loads kmap from stdin.\n", arg0);
48 exit(1);
51 static void fetch(int fd, void* buf, size_t cnt) {
52 if(read(fd, buf, cnt) != (ssize_t) cnt) die_perror("read");
55 #include <errno.h>
56 #include <string.h>
57 int main(int argc, char** argv) {
58 (void) argc;
59 if(argv[1] || isatty(0)) usage(argv[0]);
60 char flags[MAX_NR_KEYMAPS];
61 fetch(0, flags, 7);
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");
66 size_t i = 0, j;
67 for(;i < MAX_NR_KEYMAPS; i++) if(flags[i]) {
68 short kmap[NR_KEYS];
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)); */
81 return 0;