home *** CD-ROM | disk | FTP | other *** search
- #include <alloca.h>
- #include <errno.h>
- #include <fcntl.h>
- #include <sys/ioctl.h>
- #include <linux/keyboard.h>
- #include <linux/kd.h>
- #include <stdio.h>
- #include <string.h>
- #include <unistd.h>
- #include <zlib.h>
-
- #include "install.h"
- #include "kbd.h"
- #include "log.h"
- #include "newt.h"
- #include "windows.h"
-
- /* the file pointer must be at the beginning of the section already! */
- static int loadKeymap(gzFile stream) {
- int console;
- int kmap, key;
- struct kbentry entry;
- int keymaps[MAX_NR_KEYMAPS];
- int count = 0;
- int magic;
- short keymap[NR_KEYS];
-
- if (gzread(stream, &magic, sizeof(magic)) != sizeof(magic)) {
- logMessage("failed to read kmap magic: %s", strerror(errno));
- return INST_ERROR;
- }
-
- if (magic != KMAP_MAGIC) {
- logMessage("bad magic for keymap!");
- return INST_ERROR;
- }
-
- if (gzread(stream, keymaps, sizeof(keymaps)) != sizeof(keymaps)) {
- logMessage("failed to read keymap header: %s", strerror(errno));
- return INST_ERROR;
- }
-
-
- console = open("/dev/console", O_RDWR);
- if (console < 0) {
- logMessage("failed to open /dev/console: %s", strerror(errno));
- return INST_ERROR;
- }
-
- for (kmap = 0; kmap < MAX_NR_KEYMAPS; kmap++) {
- if (!keymaps[kmap]) continue;
-
- if (gzread(stream, keymap, sizeof(keymap)) != sizeof(keymap)) {
- logMessage("failed to read keymap data: %s", strerror(errno));
- close(console);
- return INST_ERROR;
- }
-
- count++;
- for (key = 0; key < NR_KEYS; key++) {
- entry.kb_index = key;
- entry.kb_table = kmap;
- entry.kb_value = keymap[key];
- if (KTYP(entry.kb_value) != KT_SPEC) {
- if (ioctl(console, KDSKBENT, &entry)) {
- close(console);
- logMessage("keymap ioctl failed: %s", strerror(errno));
- }
- }
- }
- }
-
- logMessage("loaded %d keymap tables", count);
-
- close(console);
-
- return 0;
- }
-
- int setupKeyboard(void) {
- newtComponent form, okay, listbox, answer;
- int num;
- int rc;
- gzFile f;
- struct kmapHeader hdr;
- struct kmapInfo * infoTable;
- char buf[16384]; /* I hope this is big enough */
- int i;
-
- f = gzopen("/etc/keymaps.gz", "r");
- if (!f) {
- errorWindow("cannot open /etc/keymaps.gz: %s");
- return INST_ERROR;
- }
-
- if (gzread(f, &hdr, sizeof(hdr)) != sizeof(hdr)) {
- errorWindow("failed to read keymaps header: %s");
- gzclose(f);
- return INST_ERROR;
- }
-
- logMessage("%d keymaps are available", hdr.numEntries);
-
- i = hdr.numEntries * sizeof(*infoTable);
- infoTable = alloca(i);
- if (gzread(f, infoTable, i) != i) {
- errorWindow("failed to read keymap information: %s");
- gzclose(f);
- return INST_ERROR;
- }
-
- newtOpenWindow(20, 3, 40, 16, "Keyboard Type");
-
- form = newtForm(NULL, NULL, 0);
-
- newtFormAddComponent(form,
- newtLabel(3, 1, "What type of keyboard do you have?"));
-
- listbox = newtListbox(8, 3, 8, NEWT_LISTBOX_RETURNEXIT);
-
- for (i = 0; i < hdr.numEntries; i++) {
- newtListboxAddEntry(listbox, infoTable[i].name, (void *) i);
-
- if (!strcmp(infoTable[i].name, "us"))
- newtListboxSetCurrent(listbox, i);
- }
-
- okay = newtButton(18, 12, "Ok");
-
- newtFormAddComponents(form, listbox, okay, NULL);
-
- answer = newtRunForm(form);
-
- num = (int) newtListboxGetCurrent(listbox);
- rc = 0;
-
- logMessage("using keymap %s", infoTable[num].name);
-
- for (i = 0; i < num; i++) {
- if (gzread(f, buf, infoTable[i].size) != infoTable[i].size) {
- logMessage("error reading %d bytes from file: %s",
- infoTable[i].size, strerror(errno));
- gzclose(f);
- rc = INST_ERROR;
- }
- }
-
- if (!rc) rc = loadKeymap(f);
-
- gzclose(f);
-
- writeKbdConfig("/tmp", infoTable[num].name);
-
- newtFormDestroy(form);
- newtPopWindow();
-
- return rc;
- }
-
- int writeKbdConfig(char * prefix, char * keymap) {
- FILE * f;
- char * filename;
-
- if (testing || !keymap) return 0;
-
- filename = alloca(strlen(prefix) + 20);
- sprintf(filename, "%s/keyboard", prefix);
-
- f = fopen(filename, "w");
- if (!f) {
- errorWindow("failed to create keyboard configuration: %s");
- return INST_ERROR;
- }
-
- if (fprintf(f, "KEYTABLE=\"/usr/lib/kbd/keytables/%s.map\"\n",
- keymap) < 0) {
- errorWindow("failed to write keyboard configuration: %s");
- return INST_ERROR;
- }
-
- fclose(f);
-
- return 0;
- }
-
- int readKbdConfig(char * prefix, char ** keymap) {
- FILE * f;
- char * filename;
- char buf[255];
- char * chptr;
-
- *keymap = NULL;
-
- if (testing) return 0;
-
- filename = alloca(strlen(prefix) + 20);
- sprintf(filename, "%s/keyboard", prefix);
-
- f = fopen(filename, "r");
- if (!f) {
- /* fail silently -- old bootdisks won't create this */
- logMessage("failed to read keyboard configuration (proably ok)");
- return 0;
- }
-
- /* this is a bit braindead -- we can steal better parsing from
- kbdconfig if we ever need it */
- if (!fgets(buf, sizeof(buf) - 1, f)) {
- errorWindow("empty keyboard configuration file");
- fclose(f);
- return INST_ERROR;
- }
-
- fclose(f);
-
- if (strncmp("KEYTABLE=", buf, 9)) {
- errorWindow("unrecognized entry in keyboard configuration file");
- return INST_ERROR;
- }
-
- chptr = buf + strlen(buf) - 1;
- /* ignore the '\n' on the end */
- *chptr-- = '\0';
- if (*chptr == '"')
- *chptr-- = '\0';
-
- while (chptr > buf && *chptr != '.') chptr--;
- if (*chptr == '.') *chptr-- = '\0';
-
- while (chptr > buf && *chptr != '/') chptr--;
- if (*chptr == '/') chptr++;
-
- *keymap = strdup(chptr);
-
- return 0;
- }
-